Commit | Line | Data |
---|---|---|
c758ecf6 GOC |
1 | #ifndef __ASM_X86_PROCESSOR_H |
2 | #define __ASM_X86_PROCESSOR_H | |
3 | ||
053de044 GOC |
4 | #include <asm/processor-flags.h> |
5 | ||
c72dcf83 GOC |
6 | #include <asm/page.h> |
7 | #include <asm/system.h> | |
8 | ||
c758ecf6 GOC |
9 | static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, |
10 | unsigned int *ecx, unsigned int *edx) | |
11 | { | |
12 | /* ecx is often an input as well as an output. */ | |
13 | __asm__("cpuid" | |
14 | : "=a" (*eax), | |
15 | "=b" (*ebx), | |
16 | "=c" (*ecx), | |
17 | "=d" (*edx) | |
18 | : "0" (*eax), "2" (*ecx)); | |
19 | } | |
20 | ||
c72dcf83 GOC |
21 | static inline void load_cr3(pgd_t *pgdir) |
22 | { | |
23 | write_cr3(__pa(pgdir)); | |
24 | } | |
c758ecf6 | 25 | |
96a388de TG |
26 | #ifdef CONFIG_X86_32 |
27 | # include "processor_32.h" | |
28 | #else | |
29 | # include "processor_64.h" | |
30 | #endif | |
c758ecf6 | 31 | |
1b46cbe0 GOC |
32 | static inline unsigned long native_get_debugreg(int regno) |
33 | { | |
34 | unsigned long val = 0; /* Damn you, gcc! */ | |
35 | ||
36 | switch (regno) { | |
37 | case 0: | |
38 | asm("mov %%db0, %0" :"=r" (val)); break; | |
39 | case 1: | |
40 | asm("mov %%db1, %0" :"=r" (val)); break; | |
41 | case 2: | |
42 | asm("mov %%db2, %0" :"=r" (val)); break; | |
43 | case 3: | |
44 | asm("mov %%db3, %0" :"=r" (val)); break; | |
45 | case 6: | |
46 | asm("mov %%db6, %0" :"=r" (val)); break; | |
47 | case 7: | |
48 | asm("mov %%db7, %0" :"=r" (val)); break; | |
49 | default: | |
50 | BUG(); | |
51 | } | |
52 | return val; | |
53 | } | |
54 | ||
55 | static inline void native_set_debugreg(int regno, unsigned long value) | |
56 | { | |
57 | switch (regno) { | |
58 | case 0: | |
59 | asm("mov %0,%%db0" : /* no output */ :"r" (value)); | |
60 | break; | |
61 | case 1: | |
62 | asm("mov %0,%%db1" : /* no output */ :"r" (value)); | |
63 | break; | |
64 | case 2: | |
65 | asm("mov %0,%%db2" : /* no output */ :"r" (value)); | |
66 | break; | |
67 | case 3: | |
68 | asm("mov %0,%%db3" : /* no output */ :"r" (value)); | |
69 | break; | |
70 | case 6: | |
71 | asm("mov %0,%%db6" : /* no output */ :"r" (value)); | |
72 | break; | |
73 | case 7: | |
74 | asm("mov %0,%%db7" : /* no output */ :"r" (value)); | |
75 | break; | |
76 | default: | |
77 | BUG(); | |
78 | } | |
79 | } | |
80 | ||
62d7d7ed GOC |
81 | /* |
82 | * Set IOPL bits in EFLAGS from given mask | |
83 | */ | |
84 | static inline void native_set_iopl_mask(unsigned mask) | |
85 | { | |
86 | #ifdef CONFIG_X86_32 | |
87 | unsigned int reg; | |
88 | __asm__ __volatile__ ("pushfl;" | |
89 | "popl %0;" | |
90 | "andl %1, %0;" | |
91 | "orl %2, %0;" | |
92 | "pushl %0;" | |
93 | "popfl" | |
94 | : "=&r" (reg) | |
95 | : "i" (~X86_EFLAGS_IOPL), "r" (mask)); | |
96 | #endif | |
97 | } | |
98 | ||
1b46cbe0 | 99 | |
c758ecf6 GOC |
100 | #ifndef CONFIG_PARAVIRT |
101 | #define __cpuid native_cpuid | |
1b46cbe0 GOC |
102 | #define paravirt_enabled() 0 |
103 | ||
104 | /* | |
105 | * These special macros can be used to get or set a debugging register | |
106 | */ | |
107 | #define get_debugreg(var, register) \ | |
108 | (var) = native_get_debugreg(register) | |
109 | #define set_debugreg(value, register) \ | |
110 | native_set_debugreg(register, value) | |
111 | ||
62d7d7ed | 112 | #define set_iopl_mask native_set_iopl_mask |
1b46cbe0 GOC |
113 | #endif /* CONFIG_PARAVIRT */ |
114 | ||
115 | /* | |
116 | * Save the cr4 feature set we're using (ie | |
117 | * Pentium 4MB enable and PPro Global page | |
118 | * enable), so that any CPU's that boot up | |
119 | * after us can get the correct flags. | |
120 | */ | |
121 | extern unsigned long mmu_cr4_features; | |
122 | ||
123 | static inline void set_in_cr4(unsigned long mask) | |
124 | { | |
125 | unsigned cr4; | |
126 | mmu_cr4_features |= mask; | |
127 | cr4 = read_cr4(); | |
128 | cr4 |= mask; | |
129 | write_cr4(cr4); | |
130 | } | |
131 | ||
132 | static inline void clear_in_cr4(unsigned long mask) | |
133 | { | |
134 | unsigned cr4; | |
135 | mmu_cr4_features &= ~mask; | |
136 | cr4 = read_cr4(); | |
137 | cr4 &= ~mask; | |
138 | write_cr4(cr4); | |
139 | } | |
140 | ||
141 | ||
c758ecf6 GOC |
142 | |
143 | /* | |
144 | * Generic CPUID function | |
145 | * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx | |
146 | * resulting in stale register contents being returned. | |
147 | */ | |
148 | static inline void cpuid(unsigned int op, | |
149 | unsigned int *eax, unsigned int *ebx, | |
150 | unsigned int *ecx, unsigned int *edx) | |
151 | { | |
152 | *eax = op; | |
153 | *ecx = 0; | |
154 | __cpuid(eax, ebx, ecx, edx); | |
155 | } | |
156 | ||
157 | /* Some CPUID calls want 'count' to be placed in ecx */ | |
158 | static inline void cpuid_count(unsigned int op, int count, | |
159 | unsigned int *eax, unsigned int *ebx, | |
160 | unsigned int *ecx, unsigned int *edx) | |
161 | { | |
162 | *eax = op; | |
163 | *ecx = count; | |
164 | __cpuid(eax, ebx, ecx, edx); | |
165 | } | |
166 | ||
167 | /* | |
168 | * CPUID functions returning a single datum | |
169 | */ | |
170 | static inline unsigned int cpuid_eax(unsigned int op) | |
171 | { | |
172 | unsigned int eax, ebx, ecx, edx; | |
173 | ||
174 | cpuid(op, &eax, &ebx, &ecx, &edx); | |
175 | return eax; | |
176 | } | |
177 | static inline unsigned int cpuid_ebx(unsigned int op) | |
178 | { | |
179 | unsigned int eax, ebx, ecx, edx; | |
180 | ||
181 | cpuid(op, &eax, &ebx, &ecx, &edx); | |
182 | return ebx; | |
183 | } | |
184 | static inline unsigned int cpuid_ecx(unsigned int op) | |
185 | { | |
186 | unsigned int eax, ebx, ecx, edx; | |
187 | ||
188 | cpuid(op, &eax, &ebx, &ecx, &edx); | |
189 | return ecx; | |
190 | } | |
191 | static inline unsigned int cpuid_edx(unsigned int op) | |
192 | { | |
193 | unsigned int eax, ebx, ecx, edx; | |
194 | ||
195 | cpuid(op, &eax, &ebx, &ecx, &edx); | |
196 | return edx; | |
197 | } | |
198 | ||
199 | #endif |