debuggers.hg

view xen/arch/x86/traps.c @ 3770:d21fbb46b9d8

bitkeeper revision 1.1159.253.1 (4208f8a54Zaz-XgC11YTHeLxPHPoZg)

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 Tue Feb 08 17:36:37 2005 +0000 (2005-02-08)
parents f5f2757b3aa2 cb87fd290eb0
children 12104922e743
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 asmlinkage int hypercall(void);
72 /* Master table, and the one used by CPU0. */
73 idt_entry_t idt_table[IDT_ENTRIES] = { {0, 0}, };
74 /* All other CPUs have their own copy. */
75 idt_entry_t *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 /*
98 * This is called for faults at very unexpected times (e.g., when interrupts
99 * are disabled). In such situations we can't do much that is safe. We try to
100 * print out some tracing and then we just spin.
101 */
102 asmlinkage void fatal_trap(int trapnr, struct xen_regs *regs)
103 {
104 int cpu = smp_processor_id();
105 unsigned long cr2;
106 static char *trapstr[] = {
107 "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
108 "invalid operation", "device not available", "double fault",
109 "coprocessor segment", "invalid tss", "segment not found",
110 "stack error", "general protection fault", "page fault",
111 "spurious interrupt", "coprocessor error", "alignment check",
112 "machine check", "simd error"
113 };
115 show_registers(regs);
117 if ( trapnr == TRAP_page_fault )
118 {
119 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (cr2) : );
120 printk("Faulting linear address might be %0lx %lx\n", cr2, cr2);
121 }
123 printk("************************************\n");
124 printk("CPU%d FATAL TRAP %d (%s), ERROR_CODE %04x%s.\n",
125 cpu, trapnr, trapstr[trapnr], regs->error_code,
126 (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");
127 printk("System shutting down -- need manual reset.\n");
128 printk("************************************\n");
130 /* Lock up the console to prevent spurious output from other CPUs. */
131 console_force_lock();
133 /* Wait for manual reset. */
134 for ( ; ; )
135 __asm__ __volatile__ ( "hlt" );
136 }
138 static inline int do_trap(int trapnr, char *str,
139 struct xen_regs *regs,
140 int use_error_code)
141 {
142 struct exec_domain *ed = current;
143 struct trap_bounce *tb = &ed->arch.trap_bounce;
144 trap_info_t *ti;
145 unsigned long fixup;
147 DEBUGGER_trap_entry(trapnr, regs);
149 if ( !GUEST_FAULT(regs) )
150 goto xen_fault;
152 #ifndef NDEBUG
153 if ( (ed->arch.traps[trapnr].address == 0) && (ed->domain->id == 0) )
154 goto xen_fault;
155 #endif
157 ti = current->arch.traps + trapnr;
158 tb->flags = TBF_EXCEPTION;
159 tb->cs = ti->cs;
160 tb->eip = ti->address;
161 if ( use_error_code )
162 {
163 tb->flags |= TBF_EXCEPTION_ERRCODE;
164 tb->error_code = regs->error_code;
165 }
166 if ( TI_GET_IF(ti) )
167 ed->vcpu_info->evtchn_upcall_mask = 1;
168 return 0;
170 xen_fault:
172 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
173 {
174 DPRINTK("Trap %d: %p -> %p\n", trapnr, regs->eip, fixup);
175 regs->eip = fixup;
176 return 0;
177 }
179 DEBUGGER_trap_fatal(trapnr, regs);
181 show_registers(regs);
182 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
183 "[error_code=%04x]\n",
184 smp_processor_id(), trapnr, str, regs->error_code);
185 return 0;
186 }
188 #define DO_ERROR_NOCODE(trapnr, str, name) \
189 asmlinkage int do_##name(struct xen_regs *regs) \
190 { \
191 return do_trap(trapnr, str, regs, 0); \
192 }
194 #define DO_ERROR(trapnr, str, name) \
195 asmlinkage int do_##name(struct xen_regs *regs) \
196 { \
197 return do_trap(trapnr, str, regs, 1); \
198 }
200 DO_ERROR_NOCODE( 0, "divide error", divide_error)
201 DO_ERROR_NOCODE( 4, "overflow", overflow)
202 DO_ERROR_NOCODE( 5, "bounds", bounds)
203 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
204 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
205 DO_ERROR(10, "invalid TSS", invalid_TSS)
206 DO_ERROR(11, "segment not present", segment_not_present)
207 DO_ERROR(12, "stack segment", stack_segment)
208 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
209 DO_ERROR(17, "alignment check", alignment_check)
210 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
212 asmlinkage int do_int3(struct xen_regs *regs)
213 {
214 struct exec_domain *ed = current;
215 struct trap_bounce *tb = &ed->arch.trap_bounce;
216 trap_info_t *ti;
218 DEBUGGER_trap_entry(TRAP_int3, regs);
220 if ( !GUEST_FAULT(regs) )
221 {
222 DEBUGGER_trap_fatal(TRAP_int3, regs);
223 show_registers(regs);
224 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
225 }
227 ti = current->arch.traps + 3;
228 tb->flags = TBF_EXCEPTION;
229 tb->cs = ti->cs;
230 tb->eip = ti->address;
231 if ( TI_GET_IF(ti) )
232 ed->vcpu_info->evtchn_upcall_mask = 1;
234 return 0;
235 }
237 asmlinkage void do_machine_check(struct xen_regs *regs)
238 {
239 fatal_trap(TRAP_machine_check, regs);
240 }
242 void propagate_page_fault(unsigned long addr, u16 error_code)
243 {
244 trap_info_t *ti;
245 struct exec_domain *ed = current;
246 struct trap_bounce *tb = &ed->arch.trap_bounce;
248 ti = ed->arch.traps + 14;
249 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
250 tb->cr2 = addr;
251 tb->error_code = error_code;
252 tb->cs = ti->cs;
253 tb->eip = ti->address;
254 if ( TI_GET_IF(ti) )
255 ed->vcpu_info->evtchn_upcall_mask = 1;
257 ed->arch.guest_cr2 = addr;
258 }
260 asmlinkage int do_page_fault(struct xen_regs *regs)
261 {
262 unsigned long off, addr, fixup;
263 struct exec_domain *ed = current;
264 struct domain *d = ed->domain;
265 extern int map_ldt_shadow_page(unsigned int);
266 int cpu = ed->processor;
267 int ret;
269 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
271 DEBUGGER_trap_entry(TRAP_page_fault, regs);
273 perfc_incrc(page_faults);
275 if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
276 {
277 LOCK_BIGLOCK(d);
278 if ( unlikely(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) &&
279 unlikely((addr >> L2_PAGETABLE_SHIFT) ==
280 ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
281 {
282 ptwr_flush(PTWR_PT_ACTIVE);
283 UNLOCK_BIGLOCK(d);
284 return EXCRET_fault_fixed;
285 }
287 if ( (addr < PAGE_OFFSET) &&
288 ((regs->error_code & 3) == 3) && /* write-protection fault */
289 ptwr_do_page_fault(addr) )
290 {
291 if ( unlikely(d->arch.shadow_mode) )
292 (void)shadow_fault(addr, regs->error_code);
293 UNLOCK_BIGLOCK(d);
294 return EXCRET_fault_fixed;
295 }
296 UNLOCK_BIGLOCK(d);
297 }
299 if ( unlikely(d->arch.shadow_mode) &&
300 (addr < PAGE_OFFSET) && shadow_fault(addr, regs->error_code) )
301 return EXCRET_fault_fixed;
303 if ( unlikely(addr >= LDT_VIRT_START(ed)) &&
304 (addr < (LDT_VIRT_START(ed) + (ed->arch.ldt_ents*LDT_ENTRY_SIZE))) )
305 {
306 /*
307 * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
308 * send the fault up to the guest OS to be handled.
309 */
310 LOCK_BIGLOCK(d);
311 off = addr - LDT_VIRT_START(ed);
312 addr = ed->arch.ldt_base + off;
313 ret = map_ldt_shadow_page(off >> PAGE_SHIFT);
314 UNLOCK_BIGLOCK(d);
315 if ( likely(ret) )
316 return EXCRET_fault_fixed; /* successfully copied the mapping */
317 }
319 if ( !GUEST_FAULT(regs) )
320 goto xen_fault;
322 #ifndef NDEBUG
323 if ( (ed->arch.traps[TRAP_page_fault].address == 0) && (d->id == 0) )
324 goto xen_fault;
325 #endif
327 propagate_page_fault(addr, regs->error_code);
328 return 0;
330 xen_fault:
332 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
333 {
334 perfc_incrc(copy_user_faults);
335 if ( !d->arch.shadow_mode )
336 DPRINTK("Page fault: %p -> %p\n", regs->eip, fixup);
337 regs->eip = fixup;
338 return 0;
339 }
341 DEBUGGER_trap_fatal(TRAP_page_fault, regs);
343 show_registers(regs);
344 show_page_walk(addr);
345 panic("CPU%d FATAL PAGE FAULT\n"
346 "[error_code=%04x]\n"
347 "Faulting linear address might be %p\n",
348 smp_processor_id(), regs->error_code, addr);
349 return 0;
350 }
352 static int emulate_privileged_op(struct xen_regs *regs)
353 {
354 extern long do_fpu_taskswitch(void);
355 extern void *decode_reg(struct xen_regs *regs, u8 b);
357 struct exec_domain *ed = current;
358 unsigned long *reg, eip = regs->eip;
359 u8 opcode;
361 if ( get_user(opcode, (u8 *)eip) )
362 goto page_fault;
363 eip += 1;
364 if ( (opcode & 0xff) != 0x0f )
365 goto fail;
367 if ( get_user(opcode, (u8 *)eip) )
368 goto page_fault;
369 eip += 1;
371 switch ( opcode )
372 {
373 case 0x06: /* CLTS */
374 (void)do_fpu_taskswitch();
375 break;
377 case 0x09: /* WBINVD */
378 if ( !IS_CAPABLE_PHYSDEV(ed->domain) )
379 {
380 DPRINTK("Non-physdev domain attempted WBINVD.\n");
381 goto fail;
382 }
383 wbinvd();
384 break;
386 case 0x20: /* MOV CR?,<reg> */
387 if ( get_user(opcode, (u8 *)eip) )
388 goto page_fault;
389 eip += 1;
390 if ( (opcode & 0xc0) != 0xc0 )
391 goto fail;
392 reg = decode_reg(regs, opcode & 7);
393 switch ( (opcode >> 3) & 7 )
394 {
395 case 0: /* Read CR0 */
396 *reg =
397 (read_cr0() & ~X86_CR0_TS) |
398 (test_bit(EDF_GUEST_STTS, &ed->ed_flags) ? X86_CR0_TS : 0);
399 break;
401 case 2: /* Read CR2 */
402 *reg = ed->arch.guest_cr2;
403 break;
405 case 3: /* Read CR3 */
406 *reg = pagetable_val(ed->arch.pagetable);
407 break;
409 default:
410 goto fail;
411 }
412 break;
414 case 0x22: /* MOV <reg>,CR? */
415 if ( get_user(opcode, (u8 *)eip) )
416 goto page_fault;
417 eip += 1;
418 if ( (opcode & 0xc0) != 0xc0 )
419 goto fail;
420 reg = decode_reg(regs, opcode & 7);
421 switch ( (opcode >> 3) & 7 )
422 {
423 case 0: /* Write CR0 */
424 if ( *reg & X86_CR0_TS ) /* XXX ignore all but TS bit */
425 (void)do_fpu_taskswitch;
426 break;
428 case 2: /* Write CR2 */
429 ed->arch.guest_cr2 = *reg;
430 break;
432 case 3: /* Write CR3 */
433 LOCK_BIGLOCK(ed->domain);
434 (void)new_guest_cr3(*reg);
435 UNLOCK_BIGLOCK(ed->domain);
436 break;
438 default:
439 goto fail;
440 }
441 break;
443 case 0x30: /* WRMSR */
444 if ( !IS_PRIV(ed->domain) )
445 {
446 DPRINTK("Non-priv domain attempted WRMSR.\n");
447 goto fail;
448 }
449 wrmsr(regs->ecx, regs->eax, regs->edx);
450 break;
452 case 0x32: /* RDMSR */
453 if ( !IS_PRIV(ed->domain) )
454 {
455 DPRINTK("Non-priv domain attempted RDMSR.\n");
456 goto fail;
457 }
458 rdmsr(regs->ecx, regs->eax, regs->edx);
459 break;
461 default:
462 goto fail;
463 }
465 regs->eip = eip;
466 return EXCRET_fault_fixed;
468 fail:
469 return 0;
471 page_fault:
472 propagate_page_fault(eip, 0);
473 return EXCRET_fault_fixed;
474 }
476 asmlinkage int do_general_protection(struct xen_regs *regs)
477 {
478 struct exec_domain *ed = current;
479 struct trap_bounce *tb = &ed->arch.trap_bounce;
480 trap_info_t *ti;
481 unsigned long fixup;
483 DEBUGGER_trap_entry(TRAP_gp_fault, regs);
485 if ( regs->error_code & 1 )
486 goto hardware_gp;
488 if ( !GUEST_FAULT(regs) )
489 goto gp_in_kernel;
491 /*
492 * Cunning trick to allow arbitrary "INT n" handling.
493 *
494 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
495 * instruction from trapping to the appropriate vector, when that might not
496 * be expected by Xen or the guest OS. For example, that entry might be for
497 * a fault handler (unlike traps, faults don't increment EIP), or might
498 * expect an error code on the stack (which a software trap never
499 * provides), or might be a hardware interrupt handler that doesn't like
500 * being called spuriously.
501 *
502 * Instead, a GPF occurs with the faulting IDT vector in the error code.
503 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
504 * clear to indicate that it's a software fault, not hardware.
505 *
506 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
507 * okay because they can only be triggered by an explicit DPL-checked
508 * instruction. The DPL specified by the guest OS for these vectors is NOT
509 * CHECKED!!
510 */
511 if ( (regs->error_code & 3) == 2 )
512 {
513 /* This fault must be due to <INT n> instruction. */
514 ti = current->arch.traps + (regs->error_code>>3);
515 if ( TI_GET_DPL(ti) >= (VM86_MODE(regs) ? 3 : (regs->cs & 3)) )
516 {
517 tb->flags = TBF_EXCEPTION;
518 regs->eip += 2;
519 goto finish_propagation;
520 }
521 }
523 /* Emulate some simple privileged instructions when exec'ed in ring 1. */
524 if ( (regs->error_code == 0) &&
525 GUESTOS_FAULT(regs) &&
526 emulate_privileged_op(regs) )
527 return 0;
529 #if defined(__i386__)
530 if ( VM_ASSIST(ed->domain, VMASST_TYPE_4gb_segments) &&
531 (regs->error_code == 0) &&
532 gpf_emulate_4gb(regs) )
533 return 0;
534 #endif
536 #ifndef NDEBUG
537 if ( (ed->arch.traps[TRAP_gp_fault].address == 0) &&
538 (ed->domain->id == 0) )
539 goto gp_in_kernel;
540 #endif
542 /* Pass on GPF as is. */
543 ti = current->arch.traps + 13;
544 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
545 tb->error_code = regs->error_code;
546 finish_propagation:
547 tb->cs = ti->cs;
548 tb->eip = ti->address;
549 if ( TI_GET_IF(ti) )
550 ed->vcpu_info->evtchn_upcall_mask = 1;
551 return 0;
553 gp_in_kernel:
555 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
556 {
557 DPRINTK("GPF (%04x): %p -> %p\n",
558 regs->error_code, regs->eip, fixup);
559 regs->eip = fixup;
560 return 0;
561 }
563 DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
565 hardware_gp:
566 show_registers(regs);
567 panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
568 smp_processor_id(), regs->error_code);
569 return 0;
570 }
572 unsigned long nmi_softirq_reason;
573 static void nmi_softirq(void)
574 {
575 if ( dom0 == NULL )
576 return;
578 if ( test_and_clear_bit(0, &nmi_softirq_reason) )
579 send_guest_virq(dom0->exec_domain[0], VIRQ_PARITY_ERR);
581 if ( test_and_clear_bit(1, &nmi_softirq_reason) )
582 send_guest_virq(dom0->exec_domain[0], VIRQ_IO_ERR);
583 }
585 asmlinkage void mem_parity_error(struct xen_regs *regs)
586 {
587 /* Clear and disable the parity-error line. */
588 outb((inb(0x61)&15)|4,0x61);
590 switch ( opt_nmi[0] )
591 {
592 case 'd': /* 'dom0' */
593 set_bit(0, &nmi_softirq_reason);
594 raise_softirq(NMI_SOFTIRQ);
595 case 'i': /* 'ignore' */
596 break;
597 default: /* 'fatal' */
598 console_force_unlock();
599 printk("\n\nNMI - MEMORY ERROR\n");
600 fatal_trap(TRAP_nmi, regs);
601 }
602 }
604 asmlinkage void io_check_error(struct xen_regs *regs)
605 {
606 /* Clear and disable the I/O-error line. */
607 outb((inb(0x61)&15)|8,0x61);
609 switch ( opt_nmi[0] )
610 {
611 case 'd': /* 'dom0' */
612 set_bit(0, &nmi_softirq_reason);
613 raise_softirq(NMI_SOFTIRQ);
614 case 'i': /* 'ignore' */
615 break;
616 default: /* 'fatal' */
617 console_force_unlock();
618 printk("\n\nNMI - I/O ERROR\n");
619 fatal_trap(TRAP_nmi, regs);
620 }
621 }
623 static void unknown_nmi_error(unsigned char reason)
624 {
625 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
626 printk("Dazed and confused, but trying to continue\n");
627 printk("Do you have a strange power saving mode enabled?\n");
628 }
630 asmlinkage void do_nmi(struct xen_regs *regs, unsigned long reason)
631 {
632 ++nmi_count(smp_processor_id());
634 if ( nmi_watchdog )
635 nmi_watchdog_tick(regs);
637 if ( reason & 0x80 )
638 mem_parity_error(regs);
639 else if ( reason & 0x40 )
640 io_check_error(regs);
641 else if ( !nmi_watchdog )
642 unknown_nmi_error((unsigned char)(reason&0xff));
643 }
645 asmlinkage int math_state_restore(struct xen_regs *regs)
646 {
647 /* Prevent recursion. */
648 clts();
650 if ( !test_bit(EDF_USEDFPU, &current->ed_flags) )
651 {
652 if ( test_bit(EDF_DONEFPUINIT, &current->ed_flags) )
653 restore_fpu(current);
654 else
655 init_fpu();
656 set_bit(EDF_USEDFPU, &current->ed_flags); /* so we fnsave on switch_to() */
657 }
659 if ( test_and_clear_bit(EDF_GUEST_STTS, &current->ed_flags) )
660 {
661 struct trap_bounce *tb = &current->arch.trap_bounce;
662 tb->flags = TBF_EXCEPTION;
663 tb->cs = current->arch.traps[7].cs;
664 tb->eip = current->arch.traps[7].address;
665 }
667 return EXCRET_fault_fixed;
668 }
670 asmlinkage int do_debug(struct xen_regs *regs)
671 {
672 unsigned long condition;
673 struct exec_domain *d = current;
674 struct trap_bounce *tb = &d->arch.trap_bounce;
676 DEBUGGER_trap_entry(TRAP_debug, regs);
678 __asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
680 /* Mask out spurious debug traps due to lazy DR7 setting */
681 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
682 (d->arch.debugreg[7] == 0) )
683 {
684 __asm__("mov %0,%%db7" : : "r" (0UL));
685 goto out;
686 }
688 if ( !GUEST_FAULT(regs) )
689 {
690 /* Clear TF just for absolute sanity. */
691 regs->eflags &= ~EF_TF;
692 /*
693 * We ignore watchpoints when they trigger within Xen. This may happen
694 * when a buffer is passed to us which previously had a watchpoint set
695 * on it. No need to bump EIP; the only faulting trap is an instruction
696 * breakpoint, which can't happen to us.
697 */
698 goto out;
699 }
701 /* Save debug status register where guest OS can peek at it */
702 d->arch.debugreg[6] = condition;
704 tb->flags = TBF_EXCEPTION;
705 tb->cs = d->arch.traps[1].cs;
706 tb->eip = d->arch.traps[1].address;
708 out:
709 return EXCRET_not_a_fault;
710 }
712 asmlinkage int do_spurious_interrupt_bug(struct xen_regs *regs)
713 {
714 return EXCRET_not_a_fault;
715 }
717 BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi)
718 asmlinkage void smp_deferred_nmi(struct xen_regs regs)
719 {
720 ack_APIC_irq();
721 do_nmi(&regs, 0);
722 }
724 void set_intr_gate(unsigned int n, void *addr)
725 {
726 _set_gate(idt_table+n,14,0,addr);
727 }
729 void set_system_gate(unsigned int n, void *addr)
730 {
731 _set_gate(idt_table+n,14,3,addr);
732 }
734 void set_task_gate(unsigned int n, unsigned int sel)
735 {
736 idt_table[n].a = sel << 16;
737 idt_table[n].b = 0x8500;
738 }
740 void set_tss_desc(unsigned int n, void *addr)
741 {
742 _set_tssldt_desc(
743 gdt_table + __TSS(n),
744 (unsigned long)addr,
745 offsetof(struct tss_struct, __cacheline_filler) - 1,
746 9);
747 }
749 void __init trap_init(void)
750 {
751 extern void percpu_traps_init(void);
752 extern void cpu_init(void);
754 /*
755 * Note that interrupt gates are always used, rather than trap gates. We
756 * must have interrupts disabled until DS/ES/FS/GS are saved because the
757 * first activation must have the "bad" value(s) for these registers and
758 * we may lose them if another activation is installed before they are
759 * saved. The page-fault handler also needs interrupts disabled until %cr2
760 * has been read and saved on the stack.
761 */
762 set_intr_gate(TRAP_divide_error,&divide_error);
763 set_intr_gate(TRAP_debug,&debug);
764 set_intr_gate(TRAP_nmi,&nmi);
765 set_system_gate(TRAP_int3,&int3); /* usable from all privileges */
766 set_system_gate(TRAP_overflow,&overflow); /* usable from all privileges */
767 set_intr_gate(TRAP_bounds,&bounds);
768 set_intr_gate(TRAP_invalid_op,&invalid_op);
769 set_intr_gate(TRAP_no_device,&device_not_available);
770 set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
771 set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
772 set_intr_gate(TRAP_no_segment,&segment_not_present);
773 set_intr_gate(TRAP_stack_error,&stack_segment);
774 set_intr_gate(TRAP_gp_fault,&general_protection);
775 set_intr_gate(TRAP_page_fault,&page_fault);
776 set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
777 set_intr_gate(TRAP_copro_error,&coprocessor_error);
778 set_intr_gate(TRAP_alignment_check,&alignment_check);
779 set_intr_gate(TRAP_machine_check,&machine_check);
780 set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
781 set_intr_gate(TRAP_deferred_nmi,&deferred_nmi);
783 #if defined(__i386__)
784 _set_gate(idt_table+HYPERCALL_VECTOR, 14, 1, &hypercall);
785 #endif
787 /* CPU0 uses the master IDT. */
788 idt_tables[0] = idt_table;
790 percpu_traps_init();
792 cpu_init();
794 open_softirq(NMI_SOFTIRQ, nmi_softirq);
795 }
798 long do_set_trap_table(trap_info_t *traps)
799 {
800 trap_info_t cur;
801 trap_info_t *dst = current->arch.traps;
803 LOCK_BIGLOCK(current->domain);
805 for ( ; ; )
806 {
807 if ( hypercall_preempt_check() )
808 {
809 UNLOCK_BIGLOCK(current->domain);
810 return hypercall1_create_continuation(
811 __HYPERVISOR_set_trap_table, traps);
812 }
814 if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
816 if ( cur.address == 0 ) break;
818 if ( !VALID_CODESEL(cur.cs) ) return -EPERM;
820 memcpy(dst+cur.vector, &cur, sizeof(cur));
821 traps++;
822 }
824 UNLOCK_BIGLOCK(current->domain);
826 return 0;
827 }
830 long do_set_callbacks(unsigned long event_selector,
831 unsigned long event_address,
832 unsigned long failsafe_selector,
833 unsigned long failsafe_address)
834 {
835 struct exec_domain *d = current;
837 if ( !VALID_CODESEL(event_selector) || !VALID_CODESEL(failsafe_selector) )
838 return -EPERM;
840 d->arch.event_selector = event_selector;
841 d->arch.event_address = event_address;
842 d->arch.failsafe_selector = failsafe_selector;
843 d->arch.failsafe_address = failsafe_address;
845 return 0;
846 }
849 long do_fpu_taskswitch(void)
850 {
851 set_bit(EDF_GUEST_STTS, &current->ed_flags);
852 stts();
853 return 0;
854 }
857 #if defined(__i386__)
858 #define DB_VALID_ADDR(_a) \
859 ((_a) <= (PAGE_OFFSET - 4))
860 #elif defined(__x86_64__)
861 #define DB_VALID_ADDR(_a) \
862 ((_a) >= HYPERVISOR_VIRT_END) || ((_a) <= (HYPERVISOR_VIRT_START-8))
863 #endif
864 long set_debugreg(struct exec_domain *p, int reg, unsigned long value)
865 {
866 int i;
868 switch ( reg )
869 {
870 case 0:
871 if ( !DB_VALID_ADDR(value) ) return -EPERM;
872 if ( p == current )
873 __asm__ ( "mov %0, %%db0" : : "r" (value) );
874 break;
875 case 1:
876 if ( !DB_VALID_ADDR(value) ) return -EPERM;
877 if ( p == current )
878 __asm__ ( "mov %0, %%db1" : : "r" (value) );
879 break;
880 case 2:
881 if ( !DB_VALID_ADDR(value) ) return -EPERM;
882 if ( p == current )
883 __asm__ ( "mov %0, %%db2" : : "r" (value) );
884 break;
885 case 3:
886 if ( !DB_VALID_ADDR(value) ) return -EPERM;
887 if ( p == current )
888 __asm__ ( "mov %0, %%db3" : : "r" (value) );
889 break;
890 case 6:
891 /*
892 * DR6: Bits 4-11,16-31 reserved (set to 1).
893 * Bit 12 reserved (set to 0).
894 */
895 value &= 0xffffefff; /* reserved bits => 0 */
896 value |= 0xffff0ff0; /* reserved bits => 1 */
897 if ( p == current )
898 __asm__ ( "mov %0, %%db6" : : "r" (value) );
899 break;
900 case 7:
901 /*
902 * DR7: Bit 10 reserved (set to 1).
903 * Bits 11-12,14-15 reserved (set to 0).
904 * Privileged bits:
905 * GD (bit 13): must be 0.
906 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
907 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
908 */
909 /* DR7 == 0 => debugging disabled for this domain. */
910 if ( value != 0 )
911 {
912 value &= 0xffff27ff; /* reserved bits => 0 */
913 value |= 0x00000400; /* reserved bits => 1 */
914 if ( (value & (1<<13)) != 0 ) return -EPERM;
915 for ( i = 0; i < 16; i += 2 )
916 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
917 }
918 if ( p == current )
919 __asm__ ( "mov %0, %%db7" : : "r" (value) );
920 break;
921 default:
922 return -EINVAL;
923 }
925 p->arch.debugreg[reg] = value;
926 return 0;
927 }
929 long do_set_debugreg(int reg, unsigned long value)
930 {
931 return set_debugreg(current, reg, value);
932 }
934 unsigned long do_get_debugreg(int reg)
935 {
936 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
937 return current->arch.debugreg[reg];
938 }