diff options
Diffstat (limited to 'arch/i386/kernel/paravirt.c')
-rw-r--r-- | arch/i386/kernel/paravirt.c | 293 |
1 files changed, 5 insertions, 288 deletions
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c index 2ec331e03fa9..47698756aec5 100644 --- a/arch/i386/kernel/paravirt.c +++ b/arch/i386/kernel/paravirt.c | |||
@@ -93,294 +93,11 @@ static unsigned native_patch(u8 type, u16 clobbers, void *insns, unsigned len) | |||
93 | return insn_len; | 93 | return insn_len; |
94 | } | 94 | } |
95 | 95 | ||
96 | static unsigned long native_get_debugreg(int regno) | ||
97 | { | ||
98 | unsigned long val = 0; /* Damn you, gcc! */ | ||
99 | |||
100 | switch (regno) { | ||
101 | case 0: | ||
102 | asm("movl %%db0, %0" :"=r" (val)); break; | ||
103 | case 1: | ||
104 | asm("movl %%db1, %0" :"=r" (val)); break; | ||
105 | case 2: | ||
106 | asm("movl %%db2, %0" :"=r" (val)); break; | ||
107 | case 3: | ||
108 | asm("movl %%db3, %0" :"=r" (val)); break; | ||
109 | case 6: | ||
110 | asm("movl %%db6, %0" :"=r" (val)); break; | ||
111 | case 7: | ||
112 | asm("movl %%db7, %0" :"=r" (val)); break; | ||
113 | default: | ||
114 | BUG(); | ||
115 | } | ||
116 | return val; | ||
117 | } | ||
118 | |||
119 | static void native_set_debugreg(int regno, unsigned long value) | ||
120 | { | ||
121 | switch (regno) { | ||
122 | case 0: | ||
123 | asm("movl %0,%%db0" : /* no output */ :"r" (value)); | ||
124 | break; | ||
125 | case 1: | ||
126 | asm("movl %0,%%db1" : /* no output */ :"r" (value)); | ||
127 | break; | ||
128 | case 2: | ||
129 | asm("movl %0,%%db2" : /* no output */ :"r" (value)); | ||
130 | break; | ||
131 | case 3: | ||
132 | asm("movl %0,%%db3" : /* no output */ :"r" (value)); | ||
133 | break; | ||
134 | case 6: | ||
135 | asm("movl %0,%%db6" : /* no output */ :"r" (value)); | ||
136 | break; | ||
137 | case 7: | ||
138 | asm("movl %0,%%db7" : /* no output */ :"r" (value)); | ||
139 | break; | ||
140 | default: | ||
141 | BUG(); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | void init_IRQ(void) | 96 | void init_IRQ(void) |
146 | { | 97 | { |
147 | paravirt_ops.init_IRQ(); | 98 | paravirt_ops.init_IRQ(); |
148 | } | 99 | } |
149 | 100 | ||
150 | static void native_clts(void) | ||
151 | { | ||
152 | asm volatile ("clts"); | ||
153 | } | ||
154 | |||
155 | static unsigned long native_read_cr0(void) | ||
156 | { | ||
157 | unsigned long val; | ||
158 | asm volatile("movl %%cr0,%0\n\t" :"=r" (val)); | ||
159 | return val; | ||
160 | } | ||
161 | |||
162 | static void native_write_cr0(unsigned long val) | ||
163 | { | ||
164 | asm volatile("movl %0,%%cr0": :"r" (val)); | ||
165 | } | ||
166 | |||
167 | static unsigned long native_read_cr2(void) | ||
168 | { | ||
169 | unsigned long val; | ||
170 | asm volatile("movl %%cr2,%0\n\t" :"=r" (val)); | ||
171 | return val; | ||
172 | } | ||
173 | |||
174 | static void native_write_cr2(unsigned long val) | ||
175 | { | ||
176 | asm volatile("movl %0,%%cr2": :"r" (val)); | ||
177 | } | ||
178 | |||
179 | static unsigned long native_read_cr3(void) | ||
180 | { | ||
181 | unsigned long val; | ||
182 | asm volatile("movl %%cr3,%0\n\t" :"=r" (val)); | ||
183 | return val; | ||
184 | } | ||
185 | |||
186 | static void native_write_cr3(unsigned long val) | ||
187 | { | ||
188 | asm volatile("movl %0,%%cr3": :"r" (val)); | ||
189 | } | ||
190 | |||
191 | static unsigned long native_read_cr4(void) | ||
192 | { | ||
193 | unsigned long val; | ||
194 | asm volatile("movl %%cr4,%0\n\t" :"=r" (val)); | ||
195 | return val; | ||
196 | } | ||
197 | |||
198 | static unsigned long native_read_cr4_safe(void) | ||
199 | { | ||
200 | unsigned long val; | ||
201 | /* This could fault if %cr4 does not exist */ | ||
202 | asm("1: movl %%cr4, %0 \n" | ||
203 | "2: \n" | ||
204 | ".section __ex_table,\"a\" \n" | ||
205 | ".long 1b,2b \n" | ||
206 | ".previous \n" | ||
207 | : "=r" (val): "0" (0)); | ||
208 | return val; | ||
209 | } | ||
210 | |||
211 | static void native_write_cr4(unsigned long val) | ||
212 | { | ||
213 | asm volatile("movl %0,%%cr4": :"r" (val)); | ||
214 | } | ||
215 | |||
216 | static unsigned long native_save_fl(void) | ||
217 | { | ||
218 | unsigned long f; | ||
219 | asm volatile("pushfl ; popl %0":"=g" (f): /* no input */); | ||
220 | return f; | ||
221 | } | ||
222 | |||
223 | static void native_restore_fl(unsigned long f) | ||
224 | { | ||
225 | asm volatile("pushl %0 ; popfl": /* no output */ | ||
226 | :"g" (f) | ||
227 | :"memory", "cc"); | ||
228 | } | ||
229 | |||
230 | static void native_irq_disable(void) | ||
231 | { | ||
232 | asm volatile("cli": : :"memory"); | ||
233 | } | ||
234 | |||
235 | static void native_irq_enable(void) | ||
236 | { | ||
237 | asm volatile("sti": : :"memory"); | ||
238 | } | ||
239 | |||
240 | static void native_safe_halt(void) | ||
241 | { | ||
242 | asm volatile("sti; hlt": : :"memory"); | ||
243 | } | ||
244 | |||
245 | static void native_halt(void) | ||
246 | { | ||
247 | asm volatile("hlt": : :"memory"); | ||
248 | } | ||
249 | |||
250 | static void native_wbinvd(void) | ||
251 | { | ||
252 | asm volatile("wbinvd": : :"memory"); | ||
253 | } | ||
254 | |||
255 | static unsigned long long native_read_msr(unsigned int msr, int *err) | ||
256 | { | ||
257 | unsigned long long val; | ||
258 | |||
259 | asm volatile("2: rdmsr ; xorl %0,%0\n" | ||
260 | "1:\n\t" | ||
261 | ".section .fixup,\"ax\"\n\t" | ||
262 | "3: movl %3,%0 ; jmp 1b\n\t" | ||
263 | ".previous\n\t" | ||
264 | ".section __ex_table,\"a\"\n" | ||
265 | " .align 4\n\t" | ||
266 | " .long 2b,3b\n\t" | ||
267 | ".previous" | ||
268 | : "=r" (*err), "=A" (val) | ||
269 | : "c" (msr), "i" (-EFAULT)); | ||
270 | |||
271 | return val; | ||
272 | } | ||
273 | |||
274 | static int native_write_msr(unsigned int msr, unsigned long long val) | ||
275 | { | ||
276 | int err; | ||
277 | asm volatile("2: wrmsr ; xorl %0,%0\n" | ||
278 | "1:\n\t" | ||
279 | ".section .fixup,\"ax\"\n\t" | ||
280 | "3: movl %4,%0 ; jmp 1b\n\t" | ||
281 | ".previous\n\t" | ||
282 | ".section __ex_table,\"a\"\n" | ||
283 | " .align 4\n\t" | ||
284 | " .long 2b,3b\n\t" | ||
285 | ".previous" | ||
286 | : "=a" (err) | ||
287 | : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)), | ||
288 | "i" (-EFAULT)); | ||
289 | return err; | ||
290 | } | ||
291 | |||
292 | static unsigned long long native_read_tsc(void) | ||
293 | { | ||
294 | unsigned long long val; | ||
295 | asm volatile("rdtsc" : "=A" (val)); | ||
296 | return val; | ||
297 | } | ||
298 | |||
299 | static unsigned long long native_read_pmc(void) | ||
300 | { | ||
301 | unsigned long long val; | ||
302 | asm volatile("rdpmc" : "=A" (val)); | ||
303 | return val; | ||
304 | } | ||
305 | |||
306 | static void native_load_tr_desc(void) | ||
307 | { | ||
308 | asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); | ||
309 | } | ||
310 | |||
311 | static void native_load_gdt(const struct Xgt_desc_struct *dtr) | ||
312 | { | ||
313 | asm volatile("lgdt %0"::"m" (*dtr)); | ||
314 | } | ||
315 | |||
316 | static void native_load_idt(const struct Xgt_desc_struct *dtr) | ||
317 | { | ||
318 | asm volatile("lidt %0"::"m" (*dtr)); | ||
319 | } | ||
320 | |||
321 | static void native_store_gdt(struct Xgt_desc_struct *dtr) | ||
322 | { | ||
323 | asm ("sgdt %0":"=m" (*dtr)); | ||
324 | } | ||
325 | |||
326 | static void native_store_idt(struct Xgt_desc_struct *dtr) | ||
327 | { | ||
328 | asm ("sidt %0":"=m" (*dtr)); | ||
329 | } | ||
330 | |||
331 | static unsigned long native_store_tr(void) | ||
332 | { | ||
333 | unsigned long tr; | ||
334 | asm ("str %0":"=r" (tr)); | ||
335 | return tr; | ||
336 | } | ||
337 | |||
338 | static void native_load_tls(struct thread_struct *t, unsigned int cpu) | ||
339 | { | ||
340 | #define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] | ||
341 | C(0); C(1); C(2); | ||
342 | #undef C | ||
343 | } | ||
344 | |||
345 | static inline void native_write_dt_entry(void *dt, int entry, u32 entry_low, u32 entry_high) | ||
346 | { | ||
347 | u32 *lp = (u32 *)((char *)dt + entry*8); | ||
348 | lp[0] = entry_low; | ||
349 | lp[1] = entry_high; | ||
350 | } | ||
351 | |||
352 | static void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high) | ||
353 | { | ||
354 | native_write_dt_entry(dt, entrynum, low, high); | ||
355 | } | ||
356 | |||
357 | static void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high) | ||
358 | { | ||
359 | native_write_dt_entry(dt, entrynum, low, high); | ||
360 | } | ||
361 | |||
362 | static void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high) | ||
363 | { | ||
364 | native_write_dt_entry(dt, entrynum, low, high); | ||
365 | } | ||
366 | |||
367 | static void native_load_esp0(struct tss_struct *tss, | ||
368 | struct thread_struct *thread) | ||
369 | { | ||
370 | tss->esp0 = thread->esp0; | ||
371 | |||
372 | /* This can only happen when SEP is enabled, no need to test "SEP"arately */ | ||
373 | if (unlikely(tss->ss1 != thread->sysenter_cs)) { | ||
374 | tss->ss1 = thread->sysenter_cs; | ||
375 | wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); | ||
376 | } | ||
377 | } | ||
378 | |||
379 | static void native_io_delay(void) | ||
380 | { | ||
381 | asm volatile("outb %al,$0x80"); | ||
382 | } | ||
383 | |||
384 | static void native_flush_tlb(void) | 101 | static void native_flush_tlb(void) |
385 | { | 102 | { |
386 | __native_flush_tlb(); | 103 | __native_flush_tlb(); |
@@ -517,8 +234,8 @@ struct paravirt_ops paravirt_ops = { | |||
517 | .safe_halt = native_safe_halt, | 234 | .safe_halt = native_safe_halt, |
518 | .halt = native_halt, | 235 | .halt = native_halt, |
519 | .wbinvd = native_wbinvd, | 236 | .wbinvd = native_wbinvd, |
520 | .read_msr = native_read_msr, | 237 | .read_msr = native_read_msr_safe, |
521 | .write_msr = native_write_msr, | 238 | .write_msr = native_write_msr_safe, |
522 | .read_tsc = native_read_tsc, | 239 | .read_tsc = native_read_tsc, |
523 | .read_pmc = native_read_pmc, | 240 | .read_pmc = native_read_pmc, |
524 | .get_scheduled_cycles = native_read_tsc, | 241 | .get_scheduled_cycles = native_read_tsc, |
@@ -531,9 +248,9 @@ struct paravirt_ops paravirt_ops = { | |||
531 | .store_idt = native_store_idt, | 248 | .store_idt = native_store_idt, |
532 | .store_tr = native_store_tr, | 249 | .store_tr = native_store_tr, |
533 | .load_tls = native_load_tls, | 250 | .load_tls = native_load_tls, |
534 | .write_ldt_entry = native_write_ldt_entry, | 251 | .write_ldt_entry = write_dt_entry, |
535 | .write_gdt_entry = native_write_gdt_entry, | 252 | .write_gdt_entry = write_dt_entry, |
536 | .write_idt_entry = native_write_idt_entry, | 253 | .write_idt_entry = write_dt_entry, |
537 | .load_esp0 = native_load_esp0, | 254 | .load_esp0 = native_load_esp0, |
538 | 255 | ||
539 | .set_iopl_mask = native_set_iopl_mask, | 256 | .set_iopl_mask = native_set_iopl_mask, |