ia64/xen-unstable

view xen/arch/x86/traps.c @ 3781:1d13ed9582e0

bitkeeper revision 1.1172.1.1 (420ba344y-TLJ8cFOVA_8bN7wd3dMw)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xen-unstable.bk
author kaf24@scramble.cl.cam.ac.uk
date Thu Feb 10 18:09:08 2005 +0000 (2005-02-10)
parents 09ef8bf5a916 f368e743fc2e
children 0cd8803a1553
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
2 /******************************************************************************
3 * arch/x86/traps.c
4 *
5 * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
22 /*
23 * Copyright (C) 1991, 1992 Linus Torvalds
24 *
25 * Pentium III FXSR, SSE support
26 * Gareth Hughes <gareth@valinux.com>, May 2000
27 */
29 #include <xen/config.h>
30 #include <xen/init.h>
31 #include <xen/sched.h>
32 #include <xen/lib.h>
33 #include <xen/errno.h>
34 #include <xen/mm.h>
35 #include <xen/console.h>
36 #include <asm/regs.h>
37 #include <xen/delay.h>
38 #include <xen/event.h>
39 #include <xen/spinlock.h>
40 #include <xen/irq.h>
41 #include <xen/perfc.h>
42 #include <xen/softirq.h>
43 #include <asm/shadow.h>
44 #include <asm/domain_page.h>
45 #include <asm/system.h>
46 #include <asm/io.h>
47 #include <asm/atomic.h>
48 #include <asm/desc.h>
49 #include <asm/debugreg.h>
50 #include <asm/smp.h>
51 #include <asm/flushtlb.h>
52 #include <asm/uaccess.h>
53 #include <asm/i387.h>
54 #include <asm/debugger.h>
55 #include <asm/msr.h>
57 /*
58 * opt_nmi: one of 'ignore', 'dom0', or 'fatal'.
59 * fatal: Xen prints diagnostic message and then hangs.
60 * dom0: The NMI is virtualised to DOM0.
61 * ignore: The NMI error is cleared and ignored.
62 */
63 #ifdef NDEBUG
64 char opt_nmi[10] = "dom0";
65 #else
66 char opt_nmi[10] = "fatal";
67 #endif
68 string_param("nmi", opt_nmi);
70 /* Master table, used by all CPUs on x86/64, and by CPU0 on x86/32.*/
71 idt_entry_t idt_table[IDT_ENTRIES] = { {0, 0}, };
73 asmlinkage void divide_error(void);
74 asmlinkage void debug(void);
75 asmlinkage void nmi(void);
76 asmlinkage void int3(void);
77 asmlinkage void overflow(void);
78 asmlinkage void bounds(void);
79 asmlinkage void invalid_op(void);
80 asmlinkage void device_not_available(void);
81 asmlinkage void coprocessor_segment_overrun(void);
82 asmlinkage void invalid_TSS(void);
83 asmlinkage void segment_not_present(void);
84 asmlinkage void stack_segment(void);
85 asmlinkage void general_protection(void);
86 asmlinkage void page_fault(void);
87 asmlinkage void coprocessor_error(void);
88 asmlinkage void simd_coprocessor_error(void);
89 asmlinkage void alignment_check(void);
90 asmlinkage void spurious_interrupt_bug(void);
91 asmlinkage void machine_check(void);
93 /*
94 * This is called for faults at very unexpected times (e.g., when interrupts
95 * are disabled). In such situations we can't do much that is safe. We try to
96 * print out some tracing and then we just spin.
97 */
98 asmlinkage void fatal_trap(int trapnr, struct xen_regs *regs)
99 {
100 int cpu = smp_processor_id();
101 unsigned long cr2;
102 static char *trapstr[] = {
103 "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
104 "invalid operation", "device not available", "double fault",
105 "coprocessor segment", "invalid tss", "segment not found",
106 "stack error", "general protection fault", "page fault",
107 "spurious interrupt", "coprocessor error", "alignment check",
108 "machine check", "simd error"
109 };
111 show_registers(regs);
113 if ( trapnr == TRAP_page_fault )
114 {
115 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (cr2) : );
116 printk("Faulting linear address might be %0lx %lx\n", cr2, cr2);
117 }
119 printk("************************************\n");
120 printk("CPU%d FATAL TRAP %d (%s), ERROR_CODE %04x%s.\n",
121 cpu, trapnr, trapstr[trapnr], regs->error_code,
122 (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");
123 printk("System shutting down -- need manual reset.\n");
124 printk("************************************\n");
126 debugger_trap_immediate();
128 /* Lock up the console to prevent spurious output from other CPUs. */
129 console_force_lock();
131 /* Wait for manual reset. */
132 for ( ; ; )
133 __asm__ __volatile__ ( "hlt" );
134 }
136 static inline int do_trap(int trapnr, char *str,
137 struct xen_regs *regs,
138 int use_error_code)
139 {
140 struct exec_domain *ed = current;
141 struct trap_bounce *tb = &ed->arch.trap_bounce;
142 trap_info_t *ti;
143 unsigned long fixup;
145 DEBUGGER_trap_entry(trapnr, regs);
147 if ( !GUEST_MODE(regs) )
148 goto xen_fault;
150 #ifndef NDEBUG
151 if ( (ed->arch.traps[trapnr].address == 0) && (ed->domain->id == 0) )
152 goto xen_fault;
153 #endif
155 ti = current->arch.traps + trapnr;
156 tb->flags = TBF_EXCEPTION;
157 tb->cs = ti->cs;
158 tb->eip = ti->address;
159 if ( use_error_code )
160 {
161 tb->flags |= TBF_EXCEPTION_ERRCODE;
162 tb->error_code = regs->error_code;
163 }
164 if ( TI_GET_IF(ti) )
165 ed->vcpu_info->evtchn_upcall_mask = 1;
166 return 0;
168 xen_fault:
170 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
171 {
172 DPRINTK("Trap %d: %p -> %p\n", trapnr, regs->eip, fixup);
173 regs->eip = fixup;
174 return 0;
175 }
177 DEBUGGER_trap_fatal(trapnr, regs);
179 show_registers(regs);
180 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
181 "[error_code=%04x]\n",
182 smp_processor_id(), trapnr, str, regs->error_code);
183 return 0;
184 }
186 #define DO_ERROR_NOCODE(trapnr, str, name) \
187 asmlinkage int do_##name(struct xen_regs *regs) \
188 { \
189 return do_trap(trapnr, str, regs, 0); \
190 }
192 #define DO_ERROR(trapnr, str, name) \
193 asmlinkage int do_##name(struct xen_regs *regs) \
194 { \
195 return do_trap(trapnr, str, regs, 1); \
196 }
198 DO_ERROR_NOCODE( 0, "divide error", divide_error)
199 DO_ERROR_NOCODE( 4, "overflow", overflow)
200 DO_ERROR_NOCODE( 5, "bounds", bounds)
201 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
202 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
203 DO_ERROR(10, "invalid TSS", invalid_TSS)
204 DO_ERROR(11, "segment not present", segment_not_present)
205 DO_ERROR(12, "stack segment", stack_segment)
206 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
207 DO_ERROR(17, "alignment check", alignment_check)
208 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
210 asmlinkage int do_int3(struct xen_regs *regs)
211 {
212 struct exec_domain *ed = current;
213 struct trap_bounce *tb = &ed->arch.trap_bounce;
214 trap_info_t *ti;
216 DEBUGGER_trap_entry(TRAP_int3, regs);
218 if ( !GUEST_MODE(regs) )
219 {
220 DEBUGGER_trap_fatal(TRAP_int3, regs);
221 show_registers(regs);
222 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
223 }
225 ti = current->arch.traps + 3;
226 tb->flags = TBF_EXCEPTION;
227 tb->cs = ti->cs;
228 tb->eip = ti->address;
229 if ( TI_GET_IF(ti) )
230 ed->vcpu_info->evtchn_upcall_mask = 1;
232 return 0;
233 }
235 asmlinkage void do_machine_check(struct xen_regs *regs)
236 {
237 fatal_trap(TRAP_machine_check, regs);
238 }
240 void propagate_page_fault(unsigned long addr, u16 error_code)
241 {
242 trap_info_t *ti;
243 struct exec_domain *ed = current;
244 struct trap_bounce *tb = &ed->arch.trap_bounce;
246 ti = ed->arch.traps + 14;
247 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
248 tb->cr2 = addr;
249 tb->error_code = error_code;
250 tb->cs = ti->cs;
251 tb->eip = ti->address;
252 if ( TI_GET_IF(ti) )
253 ed->vcpu_info->evtchn_upcall_mask = 1;
255 ed->arch.guest_cr2 = addr;
256 }
258 asmlinkage int do_page_fault(struct xen_regs *regs)
259 {
260 unsigned long off, addr, fixup;
261 struct exec_domain *ed = current;
262 struct domain *d = ed->domain;
263 extern int map_ldt_shadow_page(unsigned int);
264 int cpu = ed->processor;
265 int ret;
267 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
269 DEBUGGER_trap_entry(TRAP_page_fault, regs);
271 perfc_incrc(page_faults);
273 if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
274 {
275 LOCK_BIGLOCK(d);
276 if ( unlikely(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) &&
277 unlikely((addr >> L2_PAGETABLE_SHIFT) ==
278 ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
279 {
280 ptwr_flush(PTWR_PT_ACTIVE);
281 UNLOCK_BIGLOCK(d);
282 return EXCRET_fault_fixed;
283 }
285 if ( (addr < PAGE_OFFSET) &&
286 ((regs->error_code & 3) == 3) && /* write-protection fault */
287 ptwr_do_page_fault(addr) )
288 {
289 if ( unlikely(d->arch.shadow_mode) )
290 (void)shadow_fault(addr, regs->error_code);
291 UNLOCK_BIGLOCK(d);
292 return EXCRET_fault_fixed;
293 }
294 UNLOCK_BIGLOCK(d);
295 }
297 if ( unlikely(d->arch.shadow_mode) &&
298 (addr < PAGE_OFFSET) && shadow_fault(addr, regs->error_code) )
299 return EXCRET_fault_fixed;
301 if ( unlikely(addr >= LDT_VIRT_START(ed)) &&
302 (addr < (LDT_VIRT_START(ed) + (ed->arch.ldt_ents*LDT_ENTRY_SIZE))) )
303 {
304 /*
305 * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
306 * send the fault up to the guest OS to be handled.
307 */
308 LOCK_BIGLOCK(d);
309 off = addr - LDT_VIRT_START(ed);
310 addr = ed->arch.ldt_base + off;
311 ret = map_ldt_shadow_page(off >> PAGE_SHIFT);
312 UNLOCK_BIGLOCK(d);
313 if ( likely(ret) )
314 return EXCRET_fault_fixed; /* successfully copied the mapping */
315 }
317 if ( !GUEST_MODE(regs) )
318 goto xen_fault;
320 #ifndef NDEBUG
321 if ( (ed->arch.traps[TRAP_page_fault].address == 0) && (d->id == 0) )
322 goto xen_fault;
323 #endif
325 propagate_page_fault(addr, regs->error_code);
326 return 0;
328 xen_fault:
330 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
331 {
332 perfc_incrc(copy_user_faults);
333 if ( !d->arch.shadow_mode )
334 DPRINTK("Page fault: %p -> %p\n", regs->eip, fixup);
335 regs->eip = fixup;
336 return 0;
337 }
339 DEBUGGER_trap_fatal(TRAP_page_fault, regs);
341 show_registers(regs);
342 show_page_walk(addr);
343 panic("CPU%d FATAL PAGE FAULT\n"
344 "[error_code=%04x]\n"
345 "Faulting linear address might be %p\n",
346 smp_processor_id(), regs->error_code, addr);
347 return 0;
348 }
350 static int emulate_privileged_op(struct xen_regs *regs)
351 {
352 extern long do_fpu_taskswitch(void);
353 extern void *decode_reg(struct xen_regs *regs, u8 b);
355 struct exec_domain *ed = current;
356 unsigned long *reg, eip = regs->eip;
357 u8 opcode;
359 if ( get_user(opcode, (u8 *)eip) )
360 goto page_fault;
361 eip += 1;
362 if ( (opcode & 0xff) != 0x0f )
363 goto fail;
365 if ( get_user(opcode, (u8 *)eip) )
366 goto page_fault;
367 eip += 1;
369 switch ( opcode )
370 {
371 case 0x06: /* CLTS */
372 (void)do_fpu_taskswitch();
373 break;
375 case 0x09: /* WBINVD */
376 if ( !IS_CAPABLE_PHYSDEV(ed->domain) )
377 {
378 DPRINTK("Non-physdev domain attempted WBINVD.\n");
379 goto fail;
380 }
381 wbinvd();
382 break;
384 case 0x20: /* MOV CR?,<reg> */
385 if ( get_user(opcode, (u8 *)eip) )
386 goto page_fault;
387 eip += 1;
388 if ( (opcode & 0xc0) != 0xc0 )
389 goto fail;
390 reg = decode_reg(regs, opcode & 7);
391 switch ( (opcode >> 3) & 7 )
392 {
393 case 0: /* Read CR0 */
394 *reg =
395 (read_cr0() & ~X86_CR0_TS) |
396 (test_bit(EDF_GUEST_STTS, &ed->ed_flags) ? X86_CR0_TS : 0);
397 break;
399 case 2: /* Read CR2 */
400 *reg = ed->arch.guest_cr2;
401 break;
403 case 3: /* Read CR3 */
404 *reg = pagetable_val(ed->arch.pagetable);
405 break;
407 default:
408 goto fail;
409 }
410 break;
412 case 0x22: /* MOV <reg>,CR? */
413 if ( get_user(opcode, (u8 *)eip) )
414 goto page_fault;
415 eip += 1;
416 if ( (opcode & 0xc0) != 0xc0 )
417 goto fail;
418 reg = decode_reg(regs, opcode & 7);
419 switch ( (opcode >> 3) & 7 )
420 {
421 case 0: /* Write CR0 */
422 if ( *reg & X86_CR0_TS ) /* XXX ignore all but TS bit */
423 (void)do_fpu_taskswitch;
424 break;
426 case 2: /* Write CR2 */
427 ed->arch.guest_cr2 = *reg;
428 break;
430 case 3: /* Write CR3 */
431 LOCK_BIGLOCK(ed->domain);
432 (void)new_guest_cr3(*reg);
433 UNLOCK_BIGLOCK(ed->domain);
434 break;
436 default:
437 goto fail;
438 }
439 break;
441 case 0x30: /* WRMSR */
442 if ( !IS_PRIV(ed->domain) )
443 {
444 DPRINTK("Non-priv domain attempted WRMSR.\n");
445 goto fail;
446 }
447 wrmsr(regs->ecx, regs->eax, regs->edx);
448 break;
450 case 0x32: /* RDMSR */
451 if ( !IS_PRIV(ed->domain) )
452 {
453 DPRINTK("Non-priv domain attempted RDMSR.\n");
454 goto fail;
455 }
456 rdmsr(regs->ecx, regs->eax, regs->edx);
457 break;
459 default:
460 goto fail;
461 }
463 regs->eip = eip;
464 return EXCRET_fault_fixed;
466 fail:
467 return 0;
469 page_fault:
470 propagate_page_fault(eip, 0);
471 return EXCRET_fault_fixed;
472 }
474 asmlinkage int do_general_protection(struct xen_regs *regs)
475 {
476 struct exec_domain *ed = current;
477 struct trap_bounce *tb = &ed->arch.trap_bounce;
478 trap_info_t *ti;
479 unsigned long fixup;
481 DEBUGGER_trap_entry(TRAP_gp_fault, regs);
483 if ( regs->error_code & 1 )
484 goto hardware_gp;
486 if ( !GUEST_MODE(regs) )
487 goto gp_in_kernel;
489 /*
490 * Cunning trick to allow arbitrary "INT n" handling.
491 *
492 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
493 * instruction from trapping to the appropriate vector, when that might not
494 * be expected by Xen or the guest OS. For example, that entry might be for
495 * a fault handler (unlike traps, faults don't increment EIP), or might
496 * expect an error code on the stack (which a software trap never
497 * provides), or might be a hardware interrupt handler that doesn't like
498 * being called spuriously.
499 *
500 * Instead, a GPF occurs with the faulting IDT vector in the error code.
501 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
502 * clear to indicate that it's a software fault, not hardware.
503 *
504 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
505 * okay because they can only be triggered by an explicit DPL-checked
506 * instruction. The DPL specified by the guest OS for these vectors is NOT
507 * CHECKED!!
508 */
509 if ( (regs->error_code & 3) == 2 )
510 {
511 /* This fault must be due to <INT n> instruction. */
512 ti = current->arch.traps + (regs->error_code>>3);
513 if ( TI_GET_DPL(ti) >= (VM86_MODE(regs) ? 3 : (regs->cs & 3)) )
514 {
515 tb->flags = TBF_EXCEPTION;
516 regs->eip += 2;
517 goto finish_propagation;
518 }
519 }
521 /* Emulate some simple privileged instructions when exec'ed in ring 1. */
522 if ( (regs->error_code == 0) &&
523 KERNEL_MODE(ed, regs) &&
524 emulate_privileged_op(regs) )
525 return 0;
527 #if defined(__i386__)
528 if ( VM_ASSIST(ed->domain, VMASST_TYPE_4gb_segments) &&
529 (regs->error_code == 0) &&
530 gpf_emulate_4gb(regs) )
531 return 0;
532 #endif
534 #ifndef NDEBUG
535 if ( (ed->arch.traps[TRAP_gp_fault].address == 0) &&
536 (ed->domain->id == 0) )
537 goto gp_in_kernel;
538 #endif
540 /* Pass on GPF as is. */
541 ti = current->arch.traps + 13;
542 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
543 tb->error_code = regs->error_code;
544 finish_propagation:
545 tb->cs = ti->cs;
546 tb->eip = ti->address;
547 if ( TI_GET_IF(ti) )
548 ed->vcpu_info->evtchn_upcall_mask = 1;
549 return 0;
551 gp_in_kernel:
553 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
554 {
555 DPRINTK("GPF (%04x): %p -> %p\n",
556 regs->error_code, regs->eip, fixup);
557 regs->eip = fixup;
558 return 0;
559 }
561 DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
563 hardware_gp:
564 show_registers(regs);
565 panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
566 smp_processor_id(), regs->error_code);
567 return 0;
568 }
570 unsigned long nmi_softirq_reason;
571 static void nmi_softirq(void)
572 {
573 if ( dom0 == NULL )
574 return;
576 if ( test_and_clear_bit(0, &nmi_softirq_reason) )
577 send_guest_virq(dom0->exec_domain[0], VIRQ_PARITY_ERR);
579 if ( test_and_clear_bit(1, &nmi_softirq_reason) )
580 send_guest_virq(dom0->exec_domain[0], VIRQ_IO_ERR);
581 }
583 asmlinkage void mem_parity_error(struct xen_regs *regs)
584 {
585 /* Clear and disable the parity-error line. */
586 outb((inb(0x61)&15)|4,0x61);
588 switch ( opt_nmi[0] )
589 {
590 case 'd': /* 'dom0' */
591 set_bit(0, &nmi_softirq_reason);
592 raise_softirq(NMI_SOFTIRQ);
593 case 'i': /* 'ignore' */
594 break;
595 default: /* 'fatal' */
596 console_force_unlock();
597 printk("\n\nNMI - MEMORY ERROR\n");
598 fatal_trap(TRAP_nmi, regs);
599 }
600 }
602 asmlinkage void io_check_error(struct xen_regs *regs)
603 {
604 /* Clear and disable the I/O-error line. */
605 outb((inb(0x61)&15)|8,0x61);
607 switch ( opt_nmi[0] )
608 {
609 case 'd': /* 'dom0' */
610 set_bit(0, &nmi_softirq_reason);
611 raise_softirq(NMI_SOFTIRQ);
612 case 'i': /* 'ignore' */
613 break;
614 default: /* 'fatal' */
615 console_force_unlock();
616 printk("\n\nNMI - I/O ERROR\n");
617 fatal_trap(TRAP_nmi, regs);
618 }
619 }
621 static void unknown_nmi_error(unsigned char reason)
622 {
623 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
624 printk("Dazed and confused, but trying to continue\n");
625 printk("Do you have a strange power saving mode enabled?\n");
626 }
628 asmlinkage void do_nmi(struct xen_regs *regs, unsigned long reason)
629 {
630 ++nmi_count(smp_processor_id());
632 if ( nmi_watchdog )
633 nmi_watchdog_tick(regs);
635 if ( reason & 0x80 )
636 mem_parity_error(regs);
637 else if ( reason & 0x40 )
638 io_check_error(regs);
639 else if ( !nmi_watchdog )
640 unknown_nmi_error((unsigned char)(reason&0xff));
641 }
643 asmlinkage int math_state_restore(struct xen_regs *regs)
644 {
645 /* Prevent recursion. */
646 clts();
648 if ( !test_bit(EDF_USEDFPU, &current->ed_flags) )
649 {
650 if ( test_bit(EDF_DONEFPUINIT, &current->ed_flags) )
651 restore_fpu(current);
652 else
653 init_fpu();
654 set_bit(EDF_USEDFPU, &current->ed_flags); /* so we fnsave on switch_to() */
655 }
657 if ( test_and_clear_bit(EDF_GUEST_STTS, &current->ed_flags) )
658 {
659 struct trap_bounce *tb = &current->arch.trap_bounce;
660 tb->flags = TBF_EXCEPTION;
661 tb->cs = current->arch.traps[7].cs;
662 tb->eip = current->arch.traps[7].address;
663 }
665 return EXCRET_fault_fixed;
666 }
668 asmlinkage int do_debug(struct xen_regs *regs)
669 {
670 unsigned long condition;
671 struct exec_domain *d = current;
672 struct trap_bounce *tb = &d->arch.trap_bounce;
674 DEBUGGER_trap_entry(TRAP_debug, regs);
676 __asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
678 /* Mask out spurious debug traps due to lazy DR7 setting */
679 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
680 (d->arch.debugreg[7] == 0) )
681 {
682 __asm__("mov %0,%%db7" : : "r" (0UL));
683 goto out;
684 }
686 if ( !GUEST_MODE(regs) )
687 {
688 /* Clear TF just for absolute sanity. */
689 regs->eflags &= ~EF_TF;
690 /*
691 * We ignore watchpoints when they trigger within Xen. This may happen
692 * when a buffer is passed to us which previously had a watchpoint set
693 * on it. No need to bump EIP; the only faulting trap is an instruction
694 * breakpoint, which can't happen to us.
695 */
696 goto out;
697 }
699 /* Save debug status register where guest OS can peek at it */
700 d->arch.debugreg[6] = condition;
702 tb->flags = TBF_EXCEPTION;
703 tb->cs = d->arch.traps[1].cs;
704 tb->eip = d->arch.traps[1].address;
706 out:
707 return EXCRET_not_a_fault;
708 }
710 asmlinkage int do_spurious_interrupt_bug(struct xen_regs *regs)
711 {
712 return EXCRET_not_a_fault;
713 }
715 void set_intr_gate(unsigned int n, void *addr)
716 {
717 _set_gate(idt_table+n,14,0,addr);
718 }
720 void set_system_gate(unsigned int n, void *addr)
721 {
722 _set_gate(idt_table+n,14,3,addr);
723 }
725 void set_task_gate(unsigned int n, unsigned int sel)
726 {
727 idt_table[n].a = sel << 16;
728 idt_table[n].b = 0x8500;
729 }
731 void set_tss_desc(unsigned int n, void *addr)
732 {
733 _set_tssldt_desc(
734 gdt_table + __TSS(n),
735 (unsigned long)addr,
736 offsetof(struct tss_struct, __cacheline_filler) - 1,
737 9);
738 }
740 void __init trap_init(void)
741 {
742 extern void percpu_traps_init(void);
743 extern void cpu_init(void);
745 /*
746 * Note that interrupt gates are always used, rather than trap gates. We
747 * must have interrupts disabled until DS/ES/FS/GS are saved because the
748 * first activation must have the "bad" value(s) for these registers and
749 * we may lose them if another activation is installed before they are
750 * saved. The page-fault handler also needs interrupts disabled until %cr2
751 * has been read and saved on the stack.
752 */
753 set_intr_gate(TRAP_divide_error,&divide_error);
754 set_intr_gate(TRAP_debug,&debug);
755 set_intr_gate(TRAP_nmi,&nmi);
756 set_system_gate(TRAP_int3,&int3); /* usable from all privileges */
757 set_system_gate(TRAP_overflow,&overflow); /* usable from all privileges */
758 set_intr_gate(TRAP_bounds,&bounds);
759 set_intr_gate(TRAP_invalid_op,&invalid_op);
760 set_intr_gate(TRAP_no_device,&device_not_available);
761 set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
762 set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
763 set_intr_gate(TRAP_no_segment,&segment_not_present);
764 set_intr_gate(TRAP_stack_error,&stack_segment);
765 set_intr_gate(TRAP_gp_fault,&general_protection);
766 set_intr_gate(TRAP_page_fault,&page_fault);
767 set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
768 set_intr_gate(TRAP_copro_error,&coprocessor_error);
769 set_intr_gate(TRAP_alignment_check,&alignment_check);
770 set_intr_gate(TRAP_machine_check,&machine_check);
771 set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
773 percpu_traps_init();
775 cpu_init();
777 open_softirq(NMI_SOFTIRQ, nmi_softirq);
778 }
781 long do_set_trap_table(trap_info_t *traps)
782 {
783 trap_info_t cur;
784 trap_info_t *dst = current->arch.traps;
786 LOCK_BIGLOCK(current->domain);
788 for ( ; ; )
789 {
790 if ( hypercall_preempt_check() )
791 {
792 UNLOCK_BIGLOCK(current->domain);
793 return hypercall1_create_continuation(
794 __HYPERVISOR_set_trap_table, traps);
795 }
797 if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
799 if ( cur.address == 0 ) break;
801 if ( !VALID_CODESEL(cur.cs) ) return -EPERM;
803 memcpy(dst+cur.vector, &cur, sizeof(cur));
804 traps++;
805 }
807 UNLOCK_BIGLOCK(current->domain);
809 return 0;
810 }
813 long do_fpu_taskswitch(void)
814 {
815 set_bit(EDF_GUEST_STTS, &current->ed_flags);
816 stts();
817 return 0;
818 }
821 #if defined(__i386__)
822 #define DB_VALID_ADDR(_a) \
823 ((_a) <= (PAGE_OFFSET - 4))
824 #elif defined(__x86_64__)
825 #define DB_VALID_ADDR(_a) \
826 ((_a) >= HYPERVISOR_VIRT_END) || ((_a) <= (HYPERVISOR_VIRT_START-8))
827 #endif
828 long set_debugreg(struct exec_domain *p, int reg, unsigned long value)
829 {
830 int i;
832 switch ( reg )
833 {
834 case 0:
835 if ( !DB_VALID_ADDR(value) ) return -EPERM;
836 if ( p == current )
837 __asm__ ( "mov %0, %%db0" : : "r" (value) );
838 break;
839 case 1:
840 if ( !DB_VALID_ADDR(value) ) return -EPERM;
841 if ( p == current )
842 __asm__ ( "mov %0, %%db1" : : "r" (value) );
843 break;
844 case 2:
845 if ( !DB_VALID_ADDR(value) ) return -EPERM;
846 if ( p == current )
847 __asm__ ( "mov %0, %%db2" : : "r" (value) );
848 break;
849 case 3:
850 if ( !DB_VALID_ADDR(value) ) return -EPERM;
851 if ( p == current )
852 __asm__ ( "mov %0, %%db3" : : "r" (value) );
853 break;
854 case 6:
855 /*
856 * DR6: Bits 4-11,16-31 reserved (set to 1).
857 * Bit 12 reserved (set to 0).
858 */
859 value &= 0xffffefff; /* reserved bits => 0 */
860 value |= 0xffff0ff0; /* reserved bits => 1 */
861 if ( p == current )
862 __asm__ ( "mov %0, %%db6" : : "r" (value) );
863 break;
864 case 7:
865 /*
866 * DR7: Bit 10 reserved (set to 1).
867 * Bits 11-12,14-15 reserved (set to 0).
868 * Privileged bits:
869 * GD (bit 13): must be 0.
870 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
871 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
872 */
873 /* DR7 == 0 => debugging disabled for this domain. */
874 if ( value != 0 )
875 {
876 value &= 0xffff27ff; /* reserved bits => 0 */
877 value |= 0x00000400; /* reserved bits => 1 */
878 if ( (value & (1<<13)) != 0 ) return -EPERM;
879 for ( i = 0; i < 16; i += 2 )
880 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
881 }
882 if ( p == current )
883 __asm__ ( "mov %0, %%db7" : : "r" (value) );
884 break;
885 default:
886 return -EINVAL;
887 }
889 p->arch.debugreg[reg] = value;
890 return 0;
891 }
893 long do_set_debugreg(int reg, unsigned long value)
894 {
895 return set_debugreg(current, reg, value);
896 }
898 unsigned long do_get_debugreg(int reg)
899 {
900 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
901 return current->arch.debugreg[reg];
902 }