ia64/xen-unstable

view xen/arch/i386/traps.c @ 800:b33875f82bbb

bitkeeper revision 1.489 (3f831c7avBom96QV85aqKhJrQbXHUQ)

traps.c:
Faster handling of LDT shadow mapping.
author kaf24@scramble.cl.cam.ac.uk
date Tue Oct 07 20:05:14 2003 +0000 (2003-10-07)
parents 3d5ab61162dc
children c980231846cc
line source
1 /******************************************************************************
2 * arch/i386/traps.c
3 *
4 * Modifications to Linux original are copyright (c) 2002-2003, K A Fraser
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
21 /*
22 * xen/arch/i386/traps.c
23 *
24 * Copyright (C) 1991, 1992 Linus Torvalds
25 *
26 * Pentium III FXSR, SSE support
27 * Gareth Hughes <gareth@valinux.com>, May 2000
28 */
30 #include <xeno/config.h>
31 #include <xeno/init.h>
32 #include <xeno/interrupt.h>
33 #include <xeno/sched.h>
34 #include <xeno/lib.h>
35 #include <xeno/errno.h>
36 #include <xeno/mm.h>
37 #include <asm/ptrace.h>
38 #include <xeno/delay.h>
39 #include <xeno/spinlock.h>
40 #include <xeno/irq.h>
41 #include <xeno/perfc.h>
42 #include <asm/domain_page.h>
43 #include <asm/system.h>
44 #include <asm/io.h>
45 #include <asm/atomic.h>
46 #include <asm/desc.h>
47 #include <asm/debugreg.h>
48 #include <asm/smp.h>
49 #include <asm/pgalloc.h>
50 #include <asm/uaccess.h>
51 #include <asm/i387.h>
53 #define GTBF_TRAP 1
54 #define GTBF_TRAP_NOCODE 2
55 #define GTBF_TRAP_CR2 4
56 struct guest_trap_bounce {
57 unsigned long error_code; /* 0 */
58 unsigned long cr2; /* 4 */
59 unsigned short flags; /* 8 */
60 unsigned short cs; /* 10 */
61 unsigned long eip; /* 12 */
62 } guest_trap_bounce[NR_CPUS] = { { 0 } };
64 #define DOUBLEFAULT_STACK_SIZE 1024
65 static struct tss_struct doublefault_tss;
66 static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
68 asmlinkage int hypervisor_call(void);
69 asmlinkage void lcall7(void);
70 asmlinkage void lcall27(void);
72 /* Master table, and the one used by CPU0. */
73 struct desc_struct idt_table[256] = { {0, 0}, };
74 /* All other CPUs have their own copy. */
75 struct desc_struct *idt_tables[NR_CPUS] = { 0 };
77 asmlinkage void divide_error(void);
78 asmlinkage void debug(void);
79 asmlinkage void nmi(void);
80 asmlinkage void int3(void);
81 asmlinkage void overflow(void);
82 asmlinkage void bounds(void);
83 asmlinkage void invalid_op(void);
84 asmlinkage void device_not_available(void);
85 asmlinkage void coprocessor_segment_overrun(void);
86 asmlinkage void invalid_TSS(void);
87 asmlinkage void segment_not_present(void);
88 asmlinkage void stack_segment(void);
89 asmlinkage void general_protection(void);
90 asmlinkage void page_fault(void);
91 asmlinkage void coprocessor_error(void);
92 asmlinkage void simd_coprocessor_error(void);
93 asmlinkage void alignment_check(void);
94 asmlinkage void spurious_interrupt_bug(void);
95 asmlinkage void machine_check(void);
97 int kstack_depth_to_print = 8*20;
99 static inline int kernel_text_address(unsigned long addr)
100 {
101 if (addr >= (unsigned long) &_stext &&
102 addr <= (unsigned long) &_etext)
103 return 1;
104 return 0;
106 }
108 void show_trace(unsigned long * stack)
109 {
110 int i;
111 unsigned long addr;
113 printk("Call Trace: ");
114 i = 1;
115 while (((long) stack & (STACK_SIZE-1)) != 0) {
116 addr = *stack++;
117 if (kernel_text_address(addr)) {
118 if (i && ((i % 6) == 0))
119 printk("\n ");
120 printk("[<%08lx>] ", addr);
121 i++;
122 }
123 }
124 printk("\n");
125 }
127 void show_stack(unsigned long *esp)
128 {
129 unsigned long *stack;
130 int i;
132 printk("Stack trace from ESP=%p:\n", esp);
134 stack = esp;
135 for ( i = 0; i < kstack_depth_to_print; i++ )
136 {
137 if ( ((long)stack & (STACK_SIZE-1)) == 0 )
138 break;
139 if ( i && ((i % 8) == 0) )
140 printk("\n ");
141 if ( kernel_text_address(*stack) )
142 printk("[%08lx] ", *stack++);
143 else
144 printk("%08lx ", *stack++);
145 }
146 printk("\n");
147 }
149 void show_registers(struct pt_regs *regs)
150 {
151 unsigned long esp;
152 unsigned short ss;
154 esp = (unsigned long) (&regs->esp);
155 ss = __HYPERVISOR_DS;
156 if ( regs->xcs & 3 )
157 {
158 esp = regs->esp;
159 ss = regs->xss & 0xffff;
160 }
162 printk("CPU: %d\nEIP: %04x:[<%08lx>] \nEFLAGS: %08lx\n",
163 smp_processor_id(), 0xffff & regs->xcs, regs->eip, regs->eflags);
164 printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
165 regs->eax, regs->ebx, regs->ecx, regs->edx);
166 printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
167 regs->esi, regs->edi, regs->ebp, esp);
168 printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
169 regs->xds & 0xffff, regs->xes & 0xffff,
170 regs->xfs & 0xffff, regs->xgs & 0xffff, ss);
172 show_stack(&regs->esp);
173 }
176 spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
178 void die(const char * str, struct pt_regs * regs, long err)
179 {
180 unsigned long flags;
181 spin_lock_irqsave(&die_lock, flags);
182 printk("%s: %04lx,%04lx\n", str, err >> 16, err & 0xffff);
183 show_registers(regs);
184 spin_unlock_irqrestore(&die_lock, flags);
185 panic("HYPERVISOR DEATH!!\n");
186 }
188 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
189 {
190 if (!(3 & regs->xcs)) die(str, regs, err);
191 }
193 static void inline do_trap(int trapnr, char *str,
194 struct pt_regs * regs,
195 long error_code, int use_error_code)
196 {
197 struct task_struct *p = current;
198 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
199 trap_info_t *ti;
200 unsigned long fixup;
202 if (!(regs->xcs & 3))
203 goto fault_in_hypervisor;
205 ti = current->thread.traps + trapnr;
206 gtb->flags = use_error_code ? GTBF_TRAP : GTBF_TRAP_NOCODE;
207 gtb->error_code = error_code;
208 gtb->cs = ti->cs;
209 gtb->eip = ti->address;
210 if ( TI_GET_IF(ti) )
211 clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
212 return;
214 fault_in_hypervisor:
216 if ( (fixup = search_exception_table(regs->eip)) != 0 )
217 {
218 regs->eip = fixup;
219 regs->xfs = regs->xgs = 0;
220 return;
221 }
223 show_registers(regs);
224 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
225 "[error_code=%08x]\n",
226 smp_processor_id(), trapnr, str, error_code);
227 }
229 #define DO_ERROR_NOCODE(trapnr, str, name) \
230 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
231 { \
232 do_trap(trapnr, str, regs, error_code, 0); \
233 }
235 #define DO_ERROR(trapnr, str, name) \
236 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
237 { \
238 do_trap(trapnr, str, regs, error_code, 1); \
239 }
241 DO_ERROR_NOCODE( 0, "divide error", divide_error)
242 DO_ERROR_NOCODE( 3, "int3", int3)
243 DO_ERROR_NOCODE( 4, "overflow", overflow)
244 DO_ERROR_NOCODE( 5, "bounds", bounds)
245 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
246 DO_ERROR_NOCODE( 7, "device not available", device_not_available)
247 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
248 DO_ERROR(10, "invalid TSS", invalid_TSS)
249 DO_ERROR(11, "segment not present", segment_not_present)
250 DO_ERROR(12, "stack segment", stack_segment)
251 /* Vector 15 reserved by Intel */
252 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
253 DO_ERROR(17, "alignment check", alignment_check)
254 DO_ERROR_NOCODE(18, "machine check", machine_check)
255 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
257 asmlinkage void do_double_fault(void)
258 {
259 extern spinlock_t console_lock;
260 struct tss_struct *tss = &doublefault_tss;
261 unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1;
263 /* Disable the NMI watchdog. It's useless now. */
264 watchdog_on = 0;
266 /* Find information saved during fault and dump it to the console. */
267 tss = &init_tss[cpu];
268 printk("CPU: %d\nEIP: %04x:[<%08lx>] \nEFLAGS: %08lx\n",
269 cpu, tss->cs, tss->eip, tss->eflags);
270 printk("CR3: %08lx\n", tss->__cr3);
271 printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
272 tss->eax, tss->ebx, tss->ecx, tss->edx);
273 printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
274 tss->esi, tss->edi, tss->ebp, tss->esp);
275 printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
276 tss->ds, tss->es, tss->fs, tss->gs, tss->ss);
277 printk("************************************\n");
278 printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu);
279 printk("System needs manual reset.\n");
280 printk("************************************\n");
282 /* Lock up the console to prevent spurious output from other CPUs. */
283 spin_lock(&console_lock);
285 /* Wait for manual reset. */
286 for ( ; ; ) ;
287 }
289 asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
290 {
291 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
292 trap_info_t *ti;
293 unsigned long addr, off, fixup, l1e, *ldt_page;
294 struct task_struct *p = current;
295 struct pfn_info *page;
296 int i;
298 __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
300 if ( unlikely(addr > PAGE_OFFSET) )
301 goto fault_in_xen_space;
303 bounce_fault:
305 if ( unlikely(!(regs->xcs & 3)) )
306 goto fault_in_hypervisor;
308 ti = p->thread.traps + 14;
309 gtb->flags = GTBF_TRAP_CR2; /* page fault pushes %cr2 */
310 gtb->cr2 = addr;
311 gtb->error_code = error_code;
312 gtb->cs = ti->cs;
313 gtb->eip = ti->address;
314 if ( TI_GET_IF(ti) )
315 clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
316 return;
318 /*
319 * FAULT IN XEN ADDRESS SPACE:
320 * We only deal with one kind -- a fault in the shadow LDT mapping.
321 * If this occurs we pull a mapping from the guest's LDT, if it is
322 * valid. Otherwise we send the fault up to the guest OS to be handled.
323 */
324 fault_in_xen_space:
326 if ( (addr < LDT_VIRT_START) ||
327 (addr >= (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) )
328 goto bounce_fault;
330 off = addr - LDT_VIRT_START;
331 addr = p->mm.ldt_base + off;
333 spin_lock(&p->page_lock);
335 __get_user(l1e, (unsigned long *)(linear_pg_table+(addr>>PAGE_SHIFT)));
336 if ( !(l1e & _PAGE_PRESENT) )
337 goto unlock_and_bounce_fault;
339 page = frame_table + (l1e >> PAGE_SHIFT);
340 if ( (page->flags & PG_type_mask) != PGT_ldt_page )
341 {
342 if ( page->type_count != 0 )
343 goto unlock_and_bounce_fault;
345 /* Check all potential LDT entries in the page. */
346 ldt_page = (unsigned long *)(addr & PAGE_MASK);
347 for ( i = 0; i < 512; i++ )
348 if ( !check_descriptor(ldt_page[i*2], ldt_page[i*2+1]) )
349 goto unlock_and_bounce_fault;
351 if ( page->flags & PG_need_flush )
352 {
353 perfc_incrc(need_flush_tlb_flush);
354 local_flush_tlb();
355 page->flags &= ~PG_need_flush;
356 }
358 page->flags &= ~PG_type_mask;
359 page->flags |= PGT_ldt_page;
360 }
362 /* Success! */
363 get_page_type(page);
364 get_page_tot(page);
365 p->mm.perdomain_pt[l1_table_offset(off)+16] = mk_l1_pgentry(l1e|_PAGE_RW);
366 p->mm.shadow_ldt_mapcnt++;
368 spin_unlock(&p->page_lock);
369 return;
372 unlock_and_bounce_fault:
374 spin_unlock(&p->page_lock);
375 goto bounce_fault;
378 fault_in_hypervisor:
380 if ( (fixup = search_exception_table(regs->eip)) != 0 )
381 {
382 regs->eip = fixup;
383 regs->xfs = regs->xgs = 0;
384 return;
385 }
387 if ( addr >= PAGE_OFFSET )
388 {
389 unsigned long page;
390 page = l2_pgentry_val(idle_pg_table[addr >> L2_PAGETABLE_SHIFT]);
391 printk("*pde = %08lx\n", page);
392 if ( page & _PAGE_PRESENT )
393 {
394 page &= PAGE_MASK;
395 page = ((unsigned long *) __va(page))[(addr&0x3ff000)>>PAGE_SHIFT];
396 printk(" *pte = %08lx\n", page);
397 }
398 }
400 show_registers(regs);
401 panic("CPU%d FATAL PAGE FAULT\n"
402 "[error_code=%08x]\n"
403 "Faulting linear address might be %08lx\n",
404 smp_processor_id(), error_code, addr);
405 }
407 asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
408 {
409 struct task_struct *p = current;
410 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
411 trap_info_t *ti;
412 unsigned long fixup;
414 /* Bad shit if error in ring 0, or result of an interrupt. */
415 if (!(regs->xcs & 3) || (error_code & 1))
416 goto gp_in_kernel;
418 /*
419 * Cunning trick to allow arbitrary "INT n" handling.
420 *
421 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
422 * instruction from trapping to the appropriate vector, when that might not
423 * be expected by Xen or the guest OS. For example, that entry might be for
424 * a fault handler (unlike traps, faults don't increment EIP), or might
425 * expect an error code on the stack (which a software trap never
426 * provides), or might be a hardware interrupt handler that doesn't like
427 * being called spuriously.
428 *
429 * Instead, a GPF occurs with the faulting IDT vector in the error code.
430 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
431 * clear to indicate that it's a software fault, not hardware.
432 *
433 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
434 * okay because they can only be triggered by an explicit DPL-checked
435 * instruction. The DPL specified by the guest OS for these vectors is NOT
436 * CHECKED!!
437 */
438 if ( (error_code & 3) == 2 )
439 {
440 /* This fault must be due to <INT n> instruction. */
441 ti = current->thread.traps + (error_code>>3);
442 if ( TI_GET_DPL(ti) >= (regs->xcs & 3) )
443 {
444 gtb->flags = GTBF_TRAP_NOCODE;
445 regs->eip += 2;
446 goto finish_propagation;
447 }
448 }
450 /* Pass on GPF as is. */
451 ti = current->thread.traps + 13;
452 gtb->flags = GTBF_TRAP;
453 gtb->error_code = error_code;
454 finish_propagation:
455 gtb->cs = ti->cs;
456 gtb->eip = ti->address;
457 if ( TI_GET_IF(ti) )
458 clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
459 return;
461 gp_in_kernel:
463 if ( (fixup = search_exception_table(regs->eip)) != 0 )
464 {
465 regs->eip = fixup;
466 regs->xfs = regs->xgs = 0;
467 return;
468 }
470 die("general protection fault", regs, error_code);
471 }
473 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
474 {
475 printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
476 printk("You probably have a hardware problem with your RAM chips\n");
478 /* Clear and disable the memory parity error line. */
479 reason = (reason & 0xf) | 4;
480 outb(reason, 0x61);
481 }
483 static void io_check_error(unsigned char reason, struct pt_regs * regs)
484 {
485 unsigned long i;
487 printk("NMI: IOCK error (debug interrupt?)\n");
488 show_registers(regs);
490 /* Re-enable the IOCK line, wait for a few seconds */
491 reason = (reason & 0xf) | 8;
492 outb(reason, 0x61);
493 i = 2000;
494 while (--i) udelay(1000);
495 reason &= ~8;
496 outb(reason, 0x61);
497 }
499 static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
500 {
501 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
502 printk("Dazed and confused, but trying to continue\n");
503 printk("Do you have a strange power saving mode enabled?\n");
504 }
506 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
507 {
508 unsigned char reason = inb(0x61);
510 ++nmi_count(smp_processor_id());
512 if (!(reason & 0xc0)) {
513 #if CONFIG_X86_LOCAL_APIC
514 if (nmi_watchdog) {
515 nmi_watchdog_tick(regs);
516 return;
517 }
518 #endif
519 unknown_nmi_error(reason, regs);
520 return;
521 }
522 if (reason & 0x80)
523 mem_parity_error(reason, regs);
524 if (reason & 0x40)
525 io_check_error(reason, regs);
526 /*
527 * Reassert NMI in case it became active meanwhile
528 * as it's edge-triggered.
529 */
530 outb(0x8f, 0x70);
531 inb(0x71); /* dummy */
532 outb(0x0f, 0x70);
533 inb(0x71); /* dummy */
534 }
536 asmlinkage void math_state_restore(struct pt_regs *regs, long error_code)
537 {
538 /* Prevent recursion. */
539 clts();
541 if ( !(current->flags & PF_USEDFPU) )
542 {
543 if ( current->flags & PF_DONEFPUINIT )
544 restore_fpu(current);
545 else
546 init_fpu();
547 current->flags |= PF_USEDFPU; /* So we fnsave on switch_to() */
548 }
550 if ( current->flags & PF_GUEST_STTS )
551 {
552 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
553 gtb->flags = GTBF_TRAP_NOCODE;
554 gtb->cs = current->thread.traps[7].cs;
555 gtb->eip = current->thread.traps[7].address;
556 current->flags &= ~PF_GUEST_STTS;
557 }
558 }
561 asmlinkage void do_debug(struct pt_regs * regs, long error_code)
562 {
563 unsigned int condition;
564 struct task_struct *tsk = current;
565 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
567 __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
569 /* Mask out spurious debug traps due to lazy DR7 setting */
570 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
571 (tsk->thread.debugreg[7] == 0) )
572 {
573 __asm__("movl %0,%%db7" : : "r" (0));
574 return;
575 }
577 if ( (regs->xcs & 3) == 0 )
578 {
579 /* Clear TF just for absolute sanity. */
580 regs->eflags &= ~EF_TF;
581 /*
582 * Basically, we ignore watchpoints when they trigger in
583 * the hypervisor. This may happen when a buffer is passed
584 * to us which previously had a watchpoint set on it.
585 * No need to bump EIP; the only faulting trap is an
586 * instruction breakpoint, which can't happen to us.
587 */
588 return;
589 }
591 /* Save debug status register where guest OS can peek at it */
592 tsk->thread.debugreg[6] = condition;
594 gtb->flags = GTBF_TRAP_NOCODE;
595 gtb->cs = tsk->thread.traps[1].cs;
596 gtb->eip = tsk->thread.traps[1].address;
597 }
600 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
601 long error_code)
602 { /* nothing */ }
605 #define _set_gate(gate_addr,type,dpl,addr) \
606 do { \
607 int __d0, __d1; \
608 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
609 "movw %4,%%dx\n\t" \
610 "movl %%eax,%0\n\t" \
611 "movl %%edx,%1" \
612 :"=m" (*((long *) (gate_addr))), \
613 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
614 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
615 "3" ((char *) (addr)),"2" (__HYPERVISOR_CS << 16)); \
616 } while (0)
618 void set_intr_gate(unsigned int n, void *addr)
619 {
620 _set_gate(idt_table+n,14,0,addr);
621 }
623 static void __init set_system_gate(unsigned int n, void *addr)
624 {
625 _set_gate(idt_table+n,14,3,addr);
626 }
628 static void set_task_gate(unsigned int n, unsigned int sel)
629 {
630 idt_table[n].a = sel << 16;
631 idt_table[n].b = 0x8500;
632 }
634 #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
635 *((gate_addr)+1) = ((base) & 0xff000000) | \
636 (((base) & 0x00ff0000)>>16) | \
637 ((limit) & 0xf0000) | \
638 ((dpl)<<13) | \
639 (0x00408000) | \
640 ((type)<<8); \
641 *(gate_addr) = (((base) & 0x0000ffff)<<16) | \
642 ((limit) & 0x0ffff); }
644 #define _set_tssldt_desc(n,addr,limit,type) \
645 __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
646 "movw %%ax,2(%2)\n\t" \
647 "rorl $16,%%eax\n\t" \
648 "movb %%al,4(%2)\n\t" \
649 "movb %4,5(%2)\n\t" \
650 "movb $0,6(%2)\n\t" \
651 "movb %%ah,7(%2)\n\t" \
652 "rorl $16,%%eax" \
653 : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
655 void set_tss_desc(unsigned int n, void *addr)
656 {
657 _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89);
658 }
660 void __init trap_init(void)
661 {
662 /*
663 * Make a separate task for double faults. This will get us debug output if
664 * we blow the kernel stack.
665 */
666 struct tss_struct *tss = &doublefault_tss;
667 memset(tss, 0, sizeof(*tss));
668 tss->ds = __HYPERVISOR_DS;
669 tss->es = __HYPERVISOR_DS;
670 tss->ss = __HYPERVISOR_DS;
671 tss->esp = (unsigned long)
672 &doublefault_stack[DOUBLEFAULT_STACK_SIZE];
673 tss->__cr3 = __pa(idle_pg_table);
674 tss->cs = __HYPERVISOR_CS;
675 tss->eip = (unsigned long)do_double_fault;
676 tss->eflags = 2;
677 tss->bitmap = INVALID_IO_BITMAP_OFFSET;
678 _set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY,
679 (int)tss, 235, 0x89);
681 /*
682 * Note that interrupt gates are always used, rather than trap gates. We
683 * must have interrupts disabled until DS/ES/FS/GS are saved because the
684 * first activation must have the "bad" value(s) for these registers and
685 * we may lose them if another activation is installed before they are
686 * saved. The page-fault handler also needs interrupts disabled until %cr2
687 * has been read and saved on the stack.
688 */
689 set_intr_gate(0,&divide_error);
690 set_intr_gate(1,&debug);
691 set_intr_gate(2,&nmi);
692 set_system_gate(3,&int3); /* usable from all privilege levels */
693 set_system_gate(4,&overflow); /* usable from all privilege levels */
694 set_intr_gate(5,&bounds);
695 set_intr_gate(6,&invalid_op);
696 set_intr_gate(7,&device_not_available);
697 set_task_gate(8,__DOUBLEFAULT_TSS_ENTRY<<3);
698 set_intr_gate(9,&coprocessor_segment_overrun);
699 set_intr_gate(10,&invalid_TSS);
700 set_intr_gate(11,&segment_not_present);
701 set_intr_gate(12,&stack_segment);
702 set_intr_gate(13,&general_protection);
703 set_intr_gate(14,&page_fault);
704 set_intr_gate(15,&spurious_interrupt_bug);
705 set_intr_gate(16,&coprocessor_error);
706 set_intr_gate(17,&alignment_check);
707 set_intr_gate(18,&machine_check);
708 set_intr_gate(19,&simd_coprocessor_error);
710 /* Only ring 1 can access monitor services. */
711 _set_gate(idt_table+HYPERVISOR_CALL_VECTOR,14,1,&hypervisor_call);
713 /* CPU0 uses the master IDT. */
714 idt_tables[0] = idt_table;
716 /*
717 * Should be a barrier for any external CPU state.
718 */
719 {
720 extern void cpu_init(void);
721 cpu_init();
722 }
723 }
726 long do_set_trap_table(trap_info_t *traps)
727 {
728 trap_info_t cur;
729 trap_info_t *dst = current->thread.traps;
731 for ( ; ; )
732 {
733 if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
735 if ( cur.address == 0 ) break;
737 if ( !VALID_CODESEL(cur.cs) ) return -EPERM;
739 memcpy(dst+cur.vector, &cur, sizeof(cur));
740 traps++;
741 }
743 return 0;
744 }
747 long do_set_callbacks(unsigned long event_selector,
748 unsigned long event_address,
749 unsigned long failsafe_selector,
750 unsigned long failsafe_address)
751 {
752 struct task_struct *p = current;
754 if ( !VALID_CODESEL(event_selector) || !VALID_CODESEL(failsafe_selector) )
755 return -EPERM;
757 p->event_selector = event_selector;
758 p->event_address = event_address;
759 p->failsafe_selector = failsafe_selector;
760 p->failsafe_address = failsafe_address;
762 return 0;
763 }
766 long do_set_fast_trap(int idx)
767 {
768 trap_info_t *ti;
770 /* Index 0 is special: it disables fast traps. */
771 if ( idx == 0 )
772 {
773 CLEAR_FAST_TRAP(&current->thread);
774 SET_DEFAULT_FAST_TRAP(&current->thread);
775 return 0;
776 }
778 /*
779 * We only fast-trap vectors 0x20-0x2f, and vector 0x80.
780 * The former range is used by Windows and MS-DOS.
781 * Vector 0x80 is used by Linux and the BSD variants.
782 */
783 if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) )
784 return -1;
786 ti = current->thread.traps + idx;
788 /*
789 * We can't virtualise interrupt gates, as there's no way to get
790 * the CPU to automatically clear the events_mask variable.
791 */
792 if ( TI_GET_IF(ti) )
793 return -1;
795 CLEAR_FAST_TRAP(&current->thread);
797 current->thread.fast_trap_idx = idx;
798 current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
799 current->thread.fast_trap_desc.b =
800 (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13;
802 SET_FAST_TRAP(&current->thread);
804 return 0;
805 }
808 long do_fpu_taskswitch(void)
809 {
810 current->flags |= PF_GUEST_STTS;
811 stts();
812 return 0;
813 }
816 long do_set_debugreg(int reg, unsigned long value)
817 {
818 int i;
820 switch ( reg )
821 {
822 case 0:
823 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
824 __asm__ ( "movl %0, %%db0" : : "r" (value) );
825 break;
826 case 1:
827 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
828 __asm__ ( "movl %0, %%db1" : : "r" (value) );
829 break;
830 case 2:
831 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
832 __asm__ ( "movl %0, %%db2" : : "r" (value) );
833 break;
834 case 3:
835 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
836 __asm__ ( "movl %0, %%db3" : : "r" (value) );
837 break;
838 case 6:
839 /*
840 * DR6: Bits 4-11,16-31 reserved (set to 1).
841 * Bit 12 reserved (set to 0).
842 */
843 value &= 0xffffefff; /* reserved bits => 0 */
844 value |= 0xffff0ff0; /* reserved bits => 1 */
845 __asm__ ( "movl %0, %%db6" : : "r" (value) );
846 break;
847 case 7:
848 /*
849 * DR7: Bit 10 reserved (set to 1).
850 * Bits 11-12,14-15 reserved (set to 0).
851 * Privileged bits:
852 * GD (bit 13): must be 0.
853 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
854 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
855 */
856 /* DR7 == 0 => debugging disabled for this domain. */
857 if ( value != 0 )
858 {
859 value &= 0xffff27ff; /* reserved bits => 0 */
860 value |= 0x00000400; /* reserved bits => 1 */
861 if ( (value & (1<<13)) != 0 ) return -EPERM;
862 for ( i = 0; i < 16; i += 2 )
863 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
864 }
865 __asm__ ( "movl %0, %%db7" : : "r" (value) );
866 break;
867 default:
868 return -EINVAL;
869 }
871 current->thread.debugreg[reg] = value;
872 return 0;
873 }
875 unsigned long do_get_debugreg(int reg)
876 {
877 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
878 return current->thread.debugreg[reg];
879 }