1
2
3
4
5
6
7#ifndef __ASM_I386_PROCESSOR_H
8#define __ASM_I386_PROCESSOR_H
9
10#include <asm/vm86.h>
11#include <asm/math_emu.h>
12#include <asm/segment.h>
13#include <asm/page.h>
14#include <asm/types.h>
15#include <asm/sigcontext.h>
16#include <asm/cpufeature.h>
17#include <asm/msr.h>
18#include <asm/system.h>
19#include <linux/cache.h>
20#include <linux/threads.h>
21#include <asm/percpu.h>
22#include <linux/cpumask.h>
23#include <linux/init.h>
24#include <asm/processor-flags.h>
25
26
27extern int tsc_disable;
28
29struct desc_struct {
30 unsigned long a,b;
31};
32
33#define desc_empty(desc) \
34 (!((desc)->a | (desc)->b))
35
36#define desc_equal(desc1, desc2) \
37 (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
38
39
40
41
42#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
43
44
45
46
47
48
49
50struct cpuinfo_x86 {
51 __u8 x86;
52 __u8 x86_vendor;
53 __u8 x86_model;
54 __u8 x86_mask;
55 char wp_works_ok;
56 char hlt_works_ok;
57 char hard_math;
58 char rfu;
59 int cpuid_level;
60 unsigned long x86_capability[NCAPINTS];
61 char x86_vendor_id[16];
62 char x86_model_id[64];
63 int x86_cache_size;
64
65 int x86_cache_alignment;
66 char fdiv_bug;
67 char f00f_bug;
68 char coma_bug;
69 char pad0;
70 int x86_power;
71 unsigned long loops_per_jiffy;
72#ifdef CONFIG_SMP
73 cpumask_t llc_shared_map;
74#endif
75 unsigned char x86_max_cores;
76 unsigned char apicid;
77 unsigned short x86_clflush_size;
78#ifdef CONFIG_SMP
79 unsigned char booted_cores;
80 __u8 phys_proc_id;
81 __u8 cpu_core_id;
82#endif
83} __attribute__((__aligned__(SMP_CACHE_BYTES)));
84
85#define X86_VENDOR_INTEL 0
86#define X86_VENDOR_CYRIX 1
87#define X86_VENDOR_AMD 2
88#define X86_VENDOR_UMC 3
89#define X86_VENDOR_NEXGEN 4
90#define X86_VENDOR_CENTAUR 5
91#define X86_VENDOR_RISE 6
92#define X86_VENDOR_TRANSMETA 7
93#define X86_VENDOR_NSC 8
94#define X86_VENDOR_NUM 9
95#define X86_VENDOR_UNKNOWN 0xff
96
97
98
99
100
101extern struct cpuinfo_x86 boot_cpu_data;
102extern struct cpuinfo_x86 new_cpu_data;
103extern struct tss_struct doublefault_tss;
104DECLARE_PER_CPU(struct tss_struct, init_tss);
105
106#ifdef CONFIG_SMP
107extern struct cpuinfo_x86 cpu_data[];
108#define current_cpu_data cpu_data[smp_processor_id()]
109#else
110#define cpu_data (&boot_cpu_data)
111#define current_cpu_data boot_cpu_data
112#endif
113
114extern int cpu_llc_id[NR_CPUS];
115extern char ignore_fpu_irq;
116
117void __init cpu_detect(struct cpuinfo_x86 *c);
118
119extern void identify_boot_cpu(void);
120extern void identify_secondary_cpu(struct cpuinfo_x86 *);
121extern void print_cpu_info(struct cpuinfo_x86 *);
122extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
123extern unsigned short num_cache_leaves;
124
125#ifdef CONFIG_X86_HT
126extern void detect_ht(struct cpuinfo_x86 *c);
127#else
128static inline void detect_ht(struct cpuinfo_x86 *c) {}
129#endif
130
131static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
132 unsigned int *ecx, unsigned int *edx)
133{
134
135 __asm__("cpuid"
136 : "=a" (*eax),
137 "=b" (*ebx),
138 "=c" (*ecx),
139 "=d" (*edx)
140 : "0" (*eax), "2" (*ecx));
141}
142
143#define load_cr3(pgdir) write_cr3(__pa(pgdir))
144
145
146
147
148
149
150
151extern unsigned long mmu_cr4_features;
152
153static inline void set_in_cr4 (unsigned long mask)
154{
155 unsigned cr4;
156 mmu_cr4_features |= mask;
157 cr4 = read_cr4();
158 cr4 |= mask;
159 write_cr4(cr4);
160}
161
162static inline void clear_in_cr4 (unsigned long mask)
163{
164 unsigned cr4;
165 mmu_cr4_features &= ~mask;
166 cr4 = read_cr4();
167 cr4 &= ~mask;
168 write_cr4(cr4);
169}
170
171
172
173
174
175#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
176
177#define setCx86(reg, data) do { \
178 outb((reg), 0x22); \
179 outb((data), 0x23); \
180} while (0)
181
182
183static inline void sync_core(void)
184{
185 int tmp;
186 asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
187}
188
189static inline void __monitor(const void *eax, unsigned long ecx,
190 unsigned long edx)
191{
192
193 asm volatile(
194 ".byte 0x0f,0x01,0xc8;"
195 : :"a" (eax), "c" (ecx), "d"(edx));
196}
197
198static inline void __mwait(unsigned long eax, unsigned long ecx)
199{
200
201 asm volatile(
202 ".byte 0x0f,0x01,0xc9;"
203 : :"a" (eax), "c" (ecx));
204}
205
206extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
207
208
209
210extern unsigned int machine_id;
211extern unsigned int machine_submodel_id;
212extern unsigned int BIOS_revision;
213extern unsigned int mca_pentium_flag;
214
215
216extern int bootloader_type;
217
218
219
220
221#define TASK_SIZE (PAGE_OFFSET)
222
223
224
225
226#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
227
228#define HAVE_ARCH_PICK_MMAP_LAYOUT
229
230
231
232
233#define IO_BITMAP_BITS 65536
234#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
235#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
236#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
237#define INVALID_IO_BITMAP_OFFSET 0x8000
238#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
239
240struct i387_fsave_struct {
241 long cwd;
242 long swd;
243 long twd;
244 long fip;
245 long fcs;
246 long foo;
247 long fos;
248 long st_space[20];
249 long status;
250};
251
252struct i387_fxsave_struct {
253 unsigned short cwd;
254 unsigned short swd;
255 unsigned short twd;
256 unsigned short fop;
257 long fip;
258 long fcs;
259 long foo;
260 long fos;
261 long mxcsr;
262 long mxcsr_mask;
263 long st_space[32];
264 long xmm_space[32];
265 long padding[56];
266} __attribute__ ((aligned (16)));
267
268struct i387_soft_struct {
269 long cwd;
270 long swd;
271 long twd;
272 long fip;
273 long fcs;
274 long foo;
275 long fos;
276 long st_space[20];
277 unsigned char ftop, changed, lookahead, no_update, rm, alimit;
278 struct info *info;
279 unsigned long entry_eip;
280};
281
282union i387_union {
283 struct i387_fsave_struct fsave;
284 struct i387_fxsave_struct fxsave;
285 struct i387_soft_struct soft;
286};
287
288typedef struct {
289 unsigned long seg;
290} mm_segment_t;
291
292struct thread_struct;
293
294
295struct i386_hw_tss {
296 unsigned short back_link,__blh;
297 unsigned long esp0;
298 unsigned short ss0,__ss0h;
299 unsigned long esp1;
300 unsigned short ss1,__ss1h;
301 unsigned long esp2;
302 unsigned short ss2,__ss2h;
303 unsigned long __cr3;
304 unsigned long eip;
305 unsigned long eflags;
306 unsigned long eax,ecx,edx,ebx;
307 unsigned long esp;
308 unsigned long ebp;
309 unsigned long esi;
310 unsigned long edi;
311 unsigned short es, __esh;
312 unsigned short cs, __csh;
313 unsigned short ss, __ssh;
314 unsigned short ds, __dsh;
315 unsigned short fs, __fsh;
316 unsigned short gs, __gsh;
317 unsigned short ldt, __ldth;
318 unsigned short trace, io_bitmap_base;
319} __attribute__((packed));
320
321struct tss_struct {
322 struct i386_hw_tss x86_tss;
323
324
325
326
327
328
329
330 unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
331
332
333
334 unsigned long io_bitmap_max;
335 struct thread_struct *io_bitmap_owner;
336
337
338
339 unsigned long __cacheline_filler[35];
340
341
342
343 unsigned long stack[64];
344} __attribute__((packed));
345
346#define ARCH_MIN_TASKALIGN 16
347
348struct thread_struct {
349
350 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
351 unsigned long esp0;
352 unsigned long sysenter_cs;
353 unsigned long eip;
354 unsigned long esp;
355 unsigned long fs;
356 unsigned long gs;
357
358 unsigned long debugreg[8];
359
360 unsigned long cr2, trap_no, error_code;
361
362 union i387_union i387;
363
364 struct vm86_struct __user * vm86_info;
365 unsigned long screen_bitmap;
366 unsigned long v86flags, v86mask, saved_esp0;
367 unsigned int saved_fs, saved_gs;
368
369 unsigned long *io_bitmap_ptr;
370 unsigned long iopl;
371
372 unsigned long io_bitmap_max;
373};
374
375#define INIT_THREAD { \
376 .esp0 = sizeof(init_stack) + (long)&init_stack, \
377 .vm86_info = NULL, \
378 .sysenter_cs = __KERNEL_CS, \
379 .io_bitmap_ptr = NULL, \
380 .fs = __KERNEL_PERCPU, \
381}
382
383
384
385
386
387
388
389#define INIT_TSS { \
390 .x86_tss = { \
391 .esp0 = sizeof(init_stack) + (long)&init_stack, \
392 .ss0 = __KERNEL_DS, \
393 .ss1 = __KERNEL_CS, \
394 .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
395 }, \
396 .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \
397}
398
399#define start_thread(regs, new_eip, new_esp) do { \
400 __asm__("movl %0,%%gs": :"r" (0)); \
401 regs->xfs = 0; \
402 set_fs(USER_DS); \
403 regs->xds = __USER_DS; \
404 regs->xes = __USER_DS; \
405 regs->xss = __USER_DS; \
406 regs->xcs = __USER_CS; \
407 regs->eip = new_eip; \
408 regs->esp = new_esp; \
409} while (0)
410
411
412struct task_struct;
413struct mm_struct;
414
415
416extern void release_thread(struct task_struct *);
417
418
419extern void prepare_to_copy(struct task_struct *tsk);
420
421
422
423
424extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
425
426extern unsigned long thread_saved_pc(struct task_struct *tsk);
427void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack);
428
429unsigned long get_wchan(struct task_struct *p);
430
431#define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
432#define KSTK_TOP(info) \
433({ \
434 unsigned long *__ptr = (unsigned long *)(info); \
435 (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
436})
437
438
439
440
441
442
443
444
445
446
447
448#define task_pt_regs(task) \
449({ \
450 struct pt_regs *__regs__; \
451 __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
452 __regs__ - 1; \
453})
454
455#define KSTK_EIP(task) (task_pt_regs(task)->eip)
456#define KSTK_ESP(task) (task_pt_regs(task)->esp)
457
458
459struct microcode_header {
460 unsigned int hdrver;
461 unsigned int rev;
462 unsigned int date;
463 unsigned int sig;
464 unsigned int cksum;
465 unsigned int ldrver;
466 unsigned int pf;
467 unsigned int datasize;
468 unsigned int totalsize;
469 unsigned int reserved[3];
470};
471
472struct microcode {
473 struct microcode_header hdr;
474 unsigned int bits[0];
475};
476
477typedef struct microcode microcode_t;
478typedef struct microcode_header microcode_header_t;
479
480
481struct extended_signature {
482 unsigned int sig;
483 unsigned int pf;
484 unsigned int cksum;
485};
486
487struct extended_sigtable {
488 unsigned int count;
489 unsigned int cksum;
490 unsigned int reserved[3];
491 struct extended_signature sigs[0];
492};
493
494
495static inline void rep_nop(void)
496{
497 __asm__ __volatile__("rep;nop": : :"memory");
498}
499
500#define cpu_relax() rep_nop()
501
502static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread)
503{
504 tss->x86_tss.esp0 = thread->esp0;
505
506 if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
507 tss->x86_tss.ss1 = thread->sysenter_cs;
508 wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
509 }
510}
511
512
513static inline unsigned long native_get_debugreg(int regno)
514{
515 unsigned long val = 0;
516
517 switch (regno) {
518 case 0:
519 asm("movl %%db0, %0" :"=r" (val)); break;
520 case 1:
521 asm("movl %%db1, %0" :"=r" (val)); break;
522 case 2:
523 asm("movl %%db2, %0" :"=r" (val)); break;
524 case 3:
525 asm("movl %%db3, %0" :"=r" (val)); break;
526 case 6:
527 asm("movl %%db6, %0" :"=r" (val)); break;
528 case 7:
529 asm("movl %%db7, %0" :"=r" (val)); break;
530 default:
531 BUG();
532 }
533 return val;
534}
535
536static inline void native_set_debugreg(int regno, unsigned long value)
537{
538 switch (regno) {
539 case 0:
540 asm("movl %0,%%db0" : :"r" (value));
541 break;
542 case 1:
543 asm("movl %0,%%db1" : :"r" (value));
544 break;
545 case 2:
546 asm("movl %0,%%db2" : :"r" (value));
547 break;
548 case 3:
549 asm("movl %0,%%db3" : :"r" (value));
550 break;
551 case 6:
552 asm("movl %0,%%db6" : :"r" (value));
553 break;
554 case 7:
555 asm("movl %0,%%db7" : :"r" (value));
556 break;
557 default:
558 BUG();
559 }
560}
561
562
563
564
565static inline void native_set_iopl_mask(unsigned mask)
566{
567 unsigned int reg;
568 __asm__ __volatile__ ("pushfl;"
569 "popl %0;"
570 "andl %1, %0;"
571 "orl %2, %0;"
572 "pushl %0;"
573 "popfl"
574 : "=&r" (reg)
575 : "i" (~X86_EFLAGS_IOPL), "r" (mask));
576}
577
578#ifdef CONFIG_PARAVIRT
579#include <asm/paravirt.h>
580#else
581#define paravirt_enabled() 0
582#define __cpuid native_cpuid
583
584static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread)
585{
586 native_load_esp0(tss, thread);
587}
588
589
590
591
592#define get_debugreg(var, register) \
593 (var) = native_get_debugreg(register)
594#define set_debugreg(value, register) \
595 native_set_debugreg(register, value)
596
597#define set_iopl_mask native_set_iopl_mask
598#endif
599
600
601
602
603
604
605static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
606{
607 *eax = op;
608 *ecx = 0;
609 __cpuid(eax, ebx, ecx, edx);
610}
611
612
613static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
614 int *edx)
615{
616 *eax = op;
617 *ecx = count;
618 __cpuid(eax, ebx, ecx, edx);
619}
620
621
622
623
624static inline unsigned int cpuid_eax(unsigned int op)
625{
626 unsigned int eax, ebx, ecx, edx;
627
628 cpuid(op, &eax, &ebx, &ecx, &edx);
629 return eax;
630}
631static inline unsigned int cpuid_ebx(unsigned int op)
632{
633 unsigned int eax, ebx, ecx, edx;
634
635 cpuid(op, &eax, &ebx, &ecx, &edx);
636 return ebx;
637}
638static inline unsigned int cpuid_ecx(unsigned int op)
639{
640 unsigned int eax, ebx, ecx, edx;
641
642 cpuid(op, &eax, &ebx, &ecx, &edx);
643 return ecx;
644}
645static inline unsigned int cpuid_edx(unsigned int op)
646{
647 unsigned int eax, ebx, ecx, edx;
648
649 cpuid(op, &eax, &ebx, &ecx, &edx);
650 return edx;
651}
652
653
654#define GENERIC_NOP1 ".byte 0x90\n"
655#define GENERIC_NOP2 ".byte 0x89,0xf6\n"
656#define GENERIC_NOP3 ".byte 0x8d,0x76,0x00\n"
657#define GENERIC_NOP4 ".byte 0x8d,0x74,0x26,0x00\n"
658#define GENERIC_NOP5 GENERIC_NOP1 GENERIC_NOP4
659#define GENERIC_NOP6 ".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n"
660#define GENERIC_NOP7 ".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n"
661#define GENERIC_NOP8 GENERIC_NOP1 GENERIC_NOP7
662
663
664#define K8_NOP1 GENERIC_NOP1
665#define K8_NOP2 ".byte 0x66,0x90\n"
666#define K8_NOP3 ".byte 0x66,0x66,0x90\n"
667#define K8_NOP4 ".byte 0x66,0x66,0x66,0x90\n"
668#define K8_NOP5 K8_NOP3 K8_NOP2
669#define K8_NOP6 K8_NOP3 K8_NOP3
670#define K8_NOP7 K8_NOP4 K8_NOP3
671#define K8_NOP8 K8_NOP4 K8_NOP4
672
673
674
675#define K7_NOP1 GENERIC_NOP1
676#define K7_NOP2 ".byte 0x8b,0xc0\n"
677#define K7_NOP3 ".byte 0x8d,0x04,0x20\n"
678#define K7_NOP4 ".byte 0x8d,0x44,0x20,0x00\n"
679#define K7_NOP5 K7_NOP4 ASM_NOP1
680#define K7_NOP6 ".byte 0x8d,0x80,0,0,0,0\n"
681#define K7_NOP7 ".byte 0x8D,0x04,0x05,0,0,0,0\n"
682#define K7_NOP8 K7_NOP7 ASM_NOP1
683
684#ifdef CONFIG_MK8
685#define ASM_NOP1 K8_NOP1
686#define ASM_NOP2 K8_NOP2
687#define ASM_NOP3 K8_NOP3
688#define ASM_NOP4 K8_NOP4
689#define ASM_NOP5 K8_NOP5
690#define ASM_NOP6 K8_NOP6
691#define ASM_NOP7 K8_NOP7
692#define ASM_NOP8 K8_NOP8
693#elif defined(CONFIG_MK7)
694#define ASM_NOP1 K7_NOP1
695#define ASM_NOP2 K7_NOP2
696#define ASM_NOP3 K7_NOP3
697#define ASM_NOP4 K7_NOP4
698#define ASM_NOP5 K7_NOP5
699#define ASM_NOP6 K7_NOP6
700#define ASM_NOP7 K7_NOP7
701#define ASM_NOP8 K7_NOP8
702#else
703#define ASM_NOP1 GENERIC_NOP1
704#define ASM_NOP2 GENERIC_NOP2
705#define ASM_NOP3 GENERIC_NOP3
706#define ASM_NOP4 GENERIC_NOP4
707#define ASM_NOP5 GENERIC_NOP5
708#define ASM_NOP6 GENERIC_NOP6
709#define ASM_NOP7 GENERIC_NOP7
710#define ASM_NOP8 GENERIC_NOP8
711#endif
712
713#define ASM_NOP_MAX 8
714
715
716
717
718
719
720#define ARCH_HAS_PREFETCH
721static inline void prefetch(const void *x)
722{
723 alternative_input(ASM_NOP4,
724 "prefetchnta (%1)",
725 X86_FEATURE_XMM,
726 "r" (x));
727}
728
729#define ARCH_HAS_PREFETCH
730#define ARCH_HAS_PREFETCHW
731#define ARCH_HAS_SPINLOCK_PREFETCH
732
733
734
735static inline void prefetchw(const void *x)
736{
737 alternative_input(ASM_NOP4,
738 "prefetchw (%1)",
739 X86_FEATURE_3DNOW,
740 "r" (x));
741}
742#define spin_lock_prefetch(x) prefetchw(x)
743
744extern void select_idle_routine(const struct cpuinfo_x86 *c);
745
746#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
747
748extern unsigned long boot_option_idle_override;
749extern void enable_sep_cpu(void);
750extern int sysenter_setup(void);
751
752
753extern struct Xgt_desc_struct early_gdt_descr;
754
755extern void cpu_set_gdt(int);
756extern void switch_to_new_gdt(void);
757extern void cpu_init(void);
758extern void init_gdt(int cpu);
759
760extern int force_mwait;
761
762#endif
763