diff options
Diffstat (limited to 'include/asm-i386/processor.h')
-rw-r--r-- | include/asm-i386/processor.h | 204 |
1 files changed, 111 insertions, 93 deletions
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index e0ddca94d50c..a52d65440429 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/threads.h> | 20 | #include <linux/threads.h> |
21 | #include <asm/percpu.h> | 21 | #include <asm/percpu.h> |
22 | #include <linux/cpumask.h> | 22 | #include <linux/cpumask.h> |
23 | #include <linux/init.h> | ||
23 | 24 | ||
24 | /* flag for disabling the tsc */ | 25 | /* flag for disabling the tsc */ |
25 | extern int tsc_disable; | 26 | extern int tsc_disable; |
@@ -72,6 +73,7 @@ struct cpuinfo_x86 { | |||
72 | #endif | 73 | #endif |
73 | unsigned char x86_max_cores; /* cpuid returned max cores value */ | 74 | unsigned char x86_max_cores; /* cpuid returned max cores value */ |
74 | unsigned char apicid; | 75 | unsigned char apicid; |
76 | unsigned short x86_clflush_size; | ||
75 | #ifdef CONFIG_SMP | 77 | #ifdef CONFIG_SMP |
76 | unsigned char booted_cores; /* number of cores as seen by OS */ | 78 | unsigned char booted_cores; /* number of cores as seen by OS */ |
77 | __u8 phys_proc_id; /* Physical processor id. */ | 79 | __u8 phys_proc_id; /* Physical processor id. */ |
@@ -111,6 +113,8 @@ extern struct cpuinfo_x86 cpu_data[]; | |||
111 | extern int cpu_llc_id[NR_CPUS]; | 113 | extern int cpu_llc_id[NR_CPUS]; |
112 | extern char ignore_fpu_irq; | 114 | extern char ignore_fpu_irq; |
113 | 115 | ||
116 | void __init cpu_detect(struct cpuinfo_x86 *c); | ||
117 | |||
114 | extern void identify_cpu(struct cpuinfo_x86 *); | 118 | extern void identify_cpu(struct cpuinfo_x86 *); |
115 | extern void print_cpu_info(struct cpuinfo_x86 *); | 119 | extern void print_cpu_info(struct cpuinfo_x86 *); |
116 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); | 120 | extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); |
@@ -143,8 +147,8 @@ static inline void detect_ht(struct cpuinfo_x86 *c) {} | |||
143 | #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ | 147 | #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ |
144 | #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ | 148 | #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ |
145 | 149 | ||
146 | static inline void __cpuid(unsigned int *eax, unsigned int *ebx, | 150 | static inline fastcall void native_cpuid(unsigned int *eax, unsigned int *ebx, |
147 | unsigned int *ecx, unsigned int *edx) | 151 | unsigned int *ecx, unsigned int *edx) |
148 | { | 152 | { |
149 | /* ecx is often an input as well as an output. */ | 153 | /* ecx is often an input as well as an output. */ |
150 | __asm__("cpuid" | 154 | __asm__("cpuid" |
@@ -155,59 +159,6 @@ static inline void __cpuid(unsigned int *eax, unsigned int *ebx, | |||
155 | : "0" (*eax), "2" (*ecx)); | 159 | : "0" (*eax), "2" (*ecx)); |
156 | } | 160 | } |
157 | 161 | ||
158 | /* | ||
159 | * Generic CPUID function | ||
160 | * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx | ||
161 | * resulting in stale register contents being returned. | ||
162 | */ | ||
163 | static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) | ||
164 | { | ||
165 | *eax = op; | ||
166 | *ecx = 0; | ||
167 | __cpuid(eax, ebx, ecx, edx); | ||
168 | } | ||
169 | |||
170 | /* Some CPUID calls want 'count' to be placed in ecx */ | ||
171 | static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, | ||
172 | int *edx) | ||
173 | { | ||
174 | *eax = op; | ||
175 | *ecx = count; | ||
176 | __cpuid(eax, ebx, ecx, edx); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * CPUID functions returning a single datum | ||
181 | */ | ||
182 | static inline unsigned int cpuid_eax(unsigned int op) | ||
183 | { | ||
184 | unsigned int eax, ebx, ecx, edx; | ||
185 | |||
186 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
187 | return eax; | ||
188 | } | ||
189 | static inline unsigned int cpuid_ebx(unsigned int op) | ||
190 | { | ||
191 | unsigned int eax, ebx, ecx, edx; | ||
192 | |||
193 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
194 | return ebx; | ||
195 | } | ||
196 | static inline unsigned int cpuid_ecx(unsigned int op) | ||
197 | { | ||
198 | unsigned int eax, ebx, ecx, edx; | ||
199 | |||
200 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
201 | return ecx; | ||
202 | } | ||
203 | static inline unsigned int cpuid_edx(unsigned int op) | ||
204 | { | ||
205 | unsigned int eax, ebx, ecx, edx; | ||
206 | |||
207 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
208 | return edx; | ||
209 | } | ||
210 | |||
211 | #define load_cr3(pgdir) write_cr3(__pa(pgdir)) | 162 | #define load_cr3(pgdir) write_cr3(__pa(pgdir)) |
212 | 163 | ||
213 | /* | 164 | /* |
@@ -473,6 +424,7 @@ struct thread_struct { | |||
473 | .vm86_info = NULL, \ | 424 | .vm86_info = NULL, \ |
474 | .sysenter_cs = __KERNEL_CS, \ | 425 | .sysenter_cs = __KERNEL_CS, \ |
475 | .io_bitmap_ptr = NULL, \ | 426 | .io_bitmap_ptr = NULL, \ |
427 | .gs = __KERNEL_PDA, \ | ||
476 | } | 428 | } |
477 | 429 | ||
478 | /* | 430 | /* |
@@ -489,18 +441,9 @@ struct thread_struct { | |||
489 | .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \ | 441 | .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \ |
490 | } | 442 | } |
491 | 443 | ||
492 | static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread) | ||
493 | { | ||
494 | tss->esp0 = thread->esp0; | ||
495 | /* This can only happen when SEP is enabled, no need to test "SEP"arately */ | ||
496 | if (unlikely(tss->ss1 != thread->sysenter_cs)) { | ||
497 | tss->ss1 = thread->sysenter_cs; | ||
498 | wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | #define start_thread(regs, new_eip, new_esp) do { \ | 444 | #define start_thread(regs, new_eip, new_esp) do { \ |
503 | __asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0)); \ | 445 | __asm__("movl %0,%%fs": :"r" (0)); \ |
446 | regs->xgs = 0; \ | ||
504 | set_fs(USER_DS); \ | 447 | set_fs(USER_DS); \ |
505 | regs->xds = __USER_DS; \ | 448 | regs->xds = __USER_DS; \ |
506 | regs->xes = __USER_DS; \ | 449 | regs->xes = __USER_DS; \ |
@@ -510,33 +453,6 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa | |||
510 | regs->esp = new_esp; \ | 453 | regs->esp = new_esp; \ |
511 | } while (0) | 454 | } while (0) |
512 | 455 | ||
513 | /* | ||
514 | * These special macros can be used to get or set a debugging register | ||
515 | */ | ||
516 | #define get_debugreg(var, register) \ | ||
517 | __asm__("movl %%db" #register ", %0" \ | ||
518 | :"=r" (var)) | ||
519 | #define set_debugreg(value, register) \ | ||
520 | __asm__("movl %0,%%db" #register \ | ||
521 | : /* no output */ \ | ||
522 | :"r" (value)) | ||
523 | |||
524 | /* | ||
525 | * Set IOPL bits in EFLAGS from given mask | ||
526 | */ | ||
527 | static inline void set_iopl_mask(unsigned mask) | ||
528 | { | ||
529 | unsigned int reg; | ||
530 | __asm__ __volatile__ ("pushfl;" | ||
531 | "popl %0;" | ||
532 | "andl %1, %0;" | ||
533 | "orl %2, %0;" | ||
534 | "pushl %0;" | ||
535 | "popfl" | ||
536 | : "=&r" (reg) | ||
537 | : "i" (~X86_EFLAGS_IOPL), "r" (mask)); | ||
538 | } | ||
539 | |||
540 | /* Forward declaration, a strange C thing */ | 456 | /* Forward declaration, a strange C thing */ |
541 | struct task_struct; | 457 | struct task_struct; |
542 | struct mm_struct; | 458 | struct mm_struct; |
@@ -628,6 +544,105 @@ static inline void rep_nop(void) | |||
628 | 544 | ||
629 | #define cpu_relax() rep_nop() | 545 | #define cpu_relax() rep_nop() |
630 | 546 | ||
547 | #ifdef CONFIG_PARAVIRT | ||
548 | #include <asm/paravirt.h> | ||
549 | #else | ||
550 | #define paravirt_enabled() 0 | ||
551 | #define __cpuid native_cpuid | ||
552 | |||
553 | static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread) | ||
554 | { | ||
555 | tss->esp0 = thread->esp0; | ||
556 | /* This can only happen when SEP is enabled, no need to test "SEP"arately */ | ||
557 | if (unlikely(tss->ss1 != thread->sysenter_cs)) { | ||
558 | tss->ss1 = thread->sysenter_cs; | ||
559 | wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /* | ||
564 | * These special macros can be used to get or set a debugging register | ||
565 | */ | ||
566 | #define get_debugreg(var, register) \ | ||
567 | __asm__("movl %%db" #register ", %0" \ | ||
568 | :"=r" (var)) | ||
569 | #define set_debugreg(value, register) \ | ||
570 | __asm__("movl %0,%%db" #register \ | ||
571 | : /* no output */ \ | ||
572 | :"r" (value)) | ||
573 | |||
574 | #define set_iopl_mask native_set_iopl_mask | ||
575 | #endif /* CONFIG_PARAVIRT */ | ||
576 | |||
577 | /* | ||
578 | * Set IOPL bits in EFLAGS from given mask | ||
579 | */ | ||
580 | static fastcall inline void native_set_iopl_mask(unsigned mask) | ||
581 | { | ||
582 | unsigned int reg; | ||
583 | __asm__ __volatile__ ("pushfl;" | ||
584 | "popl %0;" | ||
585 | "andl %1, %0;" | ||
586 | "orl %2, %0;" | ||
587 | "pushl %0;" | ||
588 | "popfl" | ||
589 | : "=&r" (reg) | ||
590 | : "i" (~X86_EFLAGS_IOPL), "r" (mask)); | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * Generic CPUID function | ||
595 | * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx | ||
596 | * resulting in stale register contents being returned. | ||
597 | */ | ||
598 | static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) | ||
599 | { | ||
600 | *eax = op; | ||
601 | *ecx = 0; | ||
602 | __cpuid(eax, ebx, ecx, edx); | ||
603 | } | ||
604 | |||
605 | /* Some CPUID calls want 'count' to be placed in ecx */ | ||
606 | static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, | ||
607 | int *edx) | ||
608 | { | ||
609 | *eax = op; | ||
610 | *ecx = count; | ||
611 | __cpuid(eax, ebx, ecx, edx); | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * CPUID functions returning a single datum | ||
616 | */ | ||
617 | static inline unsigned int cpuid_eax(unsigned int op) | ||
618 | { | ||
619 | unsigned int eax, ebx, ecx, edx; | ||
620 | |||
621 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
622 | return eax; | ||
623 | } | ||
624 | static inline unsigned int cpuid_ebx(unsigned int op) | ||
625 | { | ||
626 | unsigned int eax, ebx, ecx, edx; | ||
627 | |||
628 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
629 | return ebx; | ||
630 | } | ||
631 | static inline unsigned int cpuid_ecx(unsigned int op) | ||
632 | { | ||
633 | unsigned int eax, ebx, ecx, edx; | ||
634 | |||
635 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
636 | return ecx; | ||
637 | } | ||
638 | static inline unsigned int cpuid_edx(unsigned int op) | ||
639 | { | ||
640 | unsigned int eax, ebx, ecx, edx; | ||
641 | |||
642 | cpuid(op, &eax, &ebx, &ecx, &edx); | ||
643 | return edx; | ||
644 | } | ||
645 | |||
631 | /* generic versions from gas */ | 646 | /* generic versions from gas */ |
632 | #define GENERIC_NOP1 ".byte 0x90\n" | 647 | #define GENERIC_NOP1 ".byte 0x90\n" |
633 | #define GENERIC_NOP2 ".byte 0x89,0xf6\n" | 648 | #define GENERIC_NOP2 ".byte 0x89,0xf6\n" |
@@ -727,4 +742,7 @@ extern unsigned long boot_option_idle_override; | |||
727 | extern void enable_sep_cpu(void); | 742 | extern void enable_sep_cpu(void); |
728 | extern int sysenter_setup(void); | 743 | extern int sysenter_setup(void); |
729 | 744 | ||
745 | extern int init_gdt(int cpu, struct task_struct *idle); | ||
746 | extern void secondary_cpu_init(void); | ||
747 | |||
730 | #endif /* __ASM_I386_PROCESSOR_H */ | 748 | #endif /* __ASM_I386_PROCESSOR_H */ |