aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/paravirt.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-05-02 13:27:10 -0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 13:27:10 -0400
commit90a0a06aa81692028864c21f981905fda46b1208 (patch)
tree516528b328d5288ee057d1eff5491e2ba1b49af1 /arch/i386/kernel/paravirt.c
parent52de74dd3994e165ef1b35c33d54655a6400e30c (diff)
[PATCH] i386: rationalize paravirt wrappers
paravirt.c used to implement native versions of all low-level functions. Far cleaner is to have the native versions exposed in the headers and as inline native_XXX, and if !CONFIG_PARAVIRT, then simply #define XXX native_XXX. There are several nice side effects: 1) write_dt_entry() now takes the correct "struct Xgt_desc_struct *" not "void *". 2) load_TLS is reintroduced to the for loop, not manually unrolled with a #error in case the bounds ever change. 3) Macros become inlines, with type checking. 4) Access to the native versions is trivial for KVM, lguest, Xen and others who might want it. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andi Kleen <ak@suse.de> Cc: Andi Kleen <ak@muc.de> Cc: Avi Kivity <avi@qumranet.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'arch/i386/kernel/paravirt.c')
-rw-r--r--arch/i386/kernel/paravirt.c293
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
96static 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
119static 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
145void init_IRQ(void) 96void init_IRQ(void)
146{ 97{
147 paravirt_ops.init_IRQ(); 98 paravirt_ops.init_IRQ();
148} 99}
149 100
150static void native_clts(void)
151{
152 asm volatile ("clts");
153}
154
155static 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
162static void native_write_cr0(unsigned long val)
163{
164 asm volatile("movl %0,%%cr0": :"r" (val));
165}
166
167static 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
174static void native_write_cr2(unsigned long val)
175{
176 asm volatile("movl %0,%%cr2": :"r" (val));
177}
178
179static 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
186static void native_write_cr3(unsigned long val)
187{
188 asm volatile("movl %0,%%cr3": :"r" (val));
189}
190
191static 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
198static 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
211static void native_write_cr4(unsigned long val)
212{
213 asm volatile("movl %0,%%cr4": :"r" (val));
214}
215
216static 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
223static void native_restore_fl(unsigned long f)
224{
225 asm volatile("pushl %0 ; popfl": /* no output */
226 :"g" (f)
227 :"memory", "cc");
228}
229
230static void native_irq_disable(void)
231{
232 asm volatile("cli": : :"memory");
233}
234
235static void native_irq_enable(void)
236{
237 asm volatile("sti": : :"memory");
238}
239
240static void native_safe_halt(void)
241{
242 asm volatile("sti; hlt": : :"memory");
243}
244
245static void native_halt(void)
246{
247 asm volatile("hlt": : :"memory");
248}
249
250static void native_wbinvd(void)
251{
252 asm volatile("wbinvd": : :"memory");
253}
254
255static 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
274static 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
292static unsigned long long native_read_tsc(void)
293{
294 unsigned long long val;
295 asm volatile("rdtsc" : "=A" (val));
296 return val;
297}
298
299static unsigned long long native_read_pmc(void)
300{
301 unsigned long long val;
302 asm volatile("rdpmc" : "=A" (val));
303 return val;
304}
305
306static void native_load_tr_desc(void)
307{
308 asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
309}
310
311static void native_load_gdt(const struct Xgt_desc_struct *dtr)
312{
313 asm volatile("lgdt %0"::"m" (*dtr));
314}
315
316static void native_load_idt(const struct Xgt_desc_struct *dtr)
317{
318 asm volatile("lidt %0"::"m" (*dtr));
319}
320
321static void native_store_gdt(struct Xgt_desc_struct *dtr)
322{
323 asm ("sgdt %0":"=m" (*dtr));
324}
325
326static void native_store_idt(struct Xgt_desc_struct *dtr)
327{
328 asm ("sidt %0":"=m" (*dtr));
329}
330
331static unsigned long native_store_tr(void)
332{
333 unsigned long tr;
334 asm ("str %0":"=r" (tr));
335 return tr;
336}
337
338static 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
345static 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
352static 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
357static 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
362static 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
367static 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
379static void native_io_delay(void)
380{
381 asm volatile("outb %al,$0x80");
382}
383
384static void native_flush_tlb(void) 101static 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,