ia64/xen-unstable

view xen/arch/x86/traps.c @ 3780:f368e743fc2e

bitkeeper revision 1.1159.1.568 (420ba33bo4Ly13qI5cHgZttHha5_-g)

Change do_set_callbacks hypercall for x86/64 to not take any selector
values, but to take a syscall_entry point.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Thu Feb 10 18:08:59 2005 +0000 (2005-02-10)
parents d8506fb506ed
children 1d13ed9582e0
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 /* Lock up the console to prevent spurious output from other CPUs. */
127 console_force_lock();
129 /* Wait for manual reset. */
130 for ( ; ; )
131 __asm__ __volatile__ ( "hlt" );
132 }
134 static inline int do_trap(int trapnr, char *str,
135 struct xen_regs *regs,
136 int use_error_code)
137 {
138 struct exec_domain *ed = current;
139 struct trap_bounce *tb = &ed->arch.trap_bounce;
140 trap_info_t *ti;
141 unsigned long fixup;
143 DEBUGGER_trap_entry(trapnr, regs);
145 if ( !GUEST_MODE(regs) )
146 goto xen_fault;
148 #ifndef NDEBUG
149 if ( (ed->arch.traps[trapnr].address == 0) && (ed->domain->id == 0) )
150 goto xen_fault;
151 #endif
153 ti = current->arch.traps + trapnr;
154 tb->flags = TBF_EXCEPTION;
155 tb->cs = ti->cs;
156 tb->eip = ti->address;
157 if ( use_error_code )
158 {
159 tb->flags |= TBF_EXCEPTION_ERRCODE;
160 tb->error_code = regs->error_code;
161 }
162 if ( TI_GET_IF(ti) )
163 ed->vcpu_info->evtchn_upcall_mask = 1;
164 return 0;
166 xen_fault:
168 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
169 {
170 DPRINTK("Trap %d: %p -> %p\n", trapnr, regs->eip, fixup);
171 regs->eip = fixup;
172 return 0;
173 }
175 DEBUGGER_trap_fatal(trapnr, regs);
177 show_registers(regs);
178 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
179 "[error_code=%04x]\n",
180 smp_processor_id(), trapnr, str, regs->error_code);
181 return 0;
182 }
184 #define DO_ERROR_NOCODE(trapnr, str, name) \
185 asmlinkage int do_##name(struct xen_regs *regs) \
186 { \
187 return do_trap(trapnr, str, regs, 0); \
188 }
190 #define DO_ERROR(trapnr, str, name) \
191 asmlinkage int do_##name(struct xen_regs *regs) \
192 { \
193 return do_trap(trapnr, str, regs, 1); \
194 }
196 DO_ERROR_NOCODE( 0, "divide error", divide_error)
197 DO_ERROR_NOCODE( 4, "overflow", overflow)
198 DO_ERROR_NOCODE( 5, "bounds", bounds)
199 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
200 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
201 DO_ERROR(10, "invalid TSS", invalid_TSS)
202 DO_ERROR(11, "segment not present", segment_not_present)
203 DO_ERROR(12, "stack segment", stack_segment)
204 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
205 DO_ERROR(17, "alignment check", alignment_check)
206 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
208 asmlinkage int do_int3(struct xen_regs *regs)
209 {
210 struct exec_domain *ed = current;
211 struct trap_bounce *tb = &ed->arch.trap_bounce;
212 trap_info_t *ti;
214 DEBUGGER_trap_entry(TRAP_int3, regs);
216 if ( !GUEST_MODE(regs) )
217 {
218 DEBUGGER_trap_fatal(TRAP_int3, regs);
219 show_registers(regs);
220 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
221 }
223 ti = current->arch.traps + 3;
224 tb->flags = TBF_EXCEPTION;
225 tb->cs = ti->cs;
226 tb->eip = ti->address;
227 if ( TI_GET_IF(ti) )
228 ed->vcpu_info->evtchn_upcall_mask = 1;
230 return 0;
231 }
233 asmlinkage void do_machine_check(struct xen_regs *regs)
234 {
235 fatal_trap(TRAP_machine_check, regs);
236 }
238 void propagate_page_fault(unsigned long addr, u16 error_code)
239 {
240 trap_info_t *ti;
241 struct exec_domain *ed = current;
242 struct trap_bounce *tb = &ed->arch.trap_bounce;
244 ti = ed->arch.traps + 14;
245 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
246 tb->cr2 = addr;
247 tb->error_code = error_code;
248 tb->cs = ti->cs;
249 tb->eip = ti->address;
250 if ( TI_GET_IF(ti) )
251 ed->vcpu_info->evtchn_upcall_mask = 1;
253 ed->arch.guest_cr2 = addr;
254 }
256 asmlinkage int do_page_fault(struct xen_regs *regs)
257 {
258 unsigned long off, addr, fixup;
259 struct exec_domain *ed = current;
260 struct domain *d = ed->domain;
261 extern int map_ldt_shadow_page(unsigned int);
262 int cpu = ed->processor;
263 int ret;
265 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
267 DEBUGGER_trap_entry(TRAP_page_fault, regs);
269 perfc_incrc(page_faults);
271 if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
272 {
273 LOCK_BIGLOCK(d);
274 if ( unlikely(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) &&
275 unlikely((addr >> L2_PAGETABLE_SHIFT) ==
276 ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
277 {
278 ptwr_flush(PTWR_PT_ACTIVE);
279 UNLOCK_BIGLOCK(d);
280 return EXCRET_fault_fixed;
281 }
283 if ( (addr < PAGE_OFFSET) &&
284 ((regs->error_code & 3) == 3) && /* write-protection fault */
285 ptwr_do_page_fault(addr) )
286 {
287 if ( unlikely(d->arch.shadow_mode) )
288 (void)shadow_fault(addr, regs->error_code);
289 UNLOCK_BIGLOCK(d);
290 return EXCRET_fault_fixed;
291 }
292 UNLOCK_BIGLOCK(d);
293 }
295 if ( unlikely(d->arch.shadow_mode) &&
296 (addr < PAGE_OFFSET) && shadow_fault(addr, regs->error_code) )
297 return EXCRET_fault_fixed;
299 if ( unlikely(addr >= LDT_VIRT_START(ed)) &&
300 (addr < (LDT_VIRT_START(ed) + (ed->arch.ldt_ents*LDT_ENTRY_SIZE))) )
301 {
302 /*
303 * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
304 * send the fault up to the guest OS to be handled.
305 */
306 LOCK_BIGLOCK(d);
307 off = addr - LDT_VIRT_START(ed);
308 addr = ed->arch.ldt_base + off;
309 ret = map_ldt_shadow_page(off >> PAGE_SHIFT);
310 UNLOCK_BIGLOCK(d);
311 if ( likely(ret) )
312 return EXCRET_fault_fixed; /* successfully copied the mapping */
313 }
315 if ( !GUEST_MODE(regs) )
316 goto xen_fault;
318 #ifndef NDEBUG
319 if ( (ed->arch.traps[TRAP_page_fault].address == 0) && (d->id == 0) )
320 goto xen_fault;
321 #endif
323 propagate_page_fault(addr, regs->error_code);
324 return 0;
326 xen_fault:
328 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
329 {
330 perfc_incrc(copy_user_faults);
331 if ( !d->arch.shadow_mode )
332 DPRINTK("Page fault: %p -> %p\n", regs->eip, fixup);
333 regs->eip = fixup;
334 return 0;
335 }
337 DEBUGGER_trap_fatal(TRAP_page_fault, regs);
339 show_registers(regs);
340 show_page_walk(addr);
341 panic("CPU%d FATAL PAGE FAULT\n"
342 "[error_code=%04x]\n"
343 "Faulting linear address might be %p\n",
344 smp_processor_id(), regs->error_code, addr);
345 return 0;
346 }
348 static int emulate_privileged_op(struct xen_regs *regs)
349 {
350 extern long do_fpu_taskswitch(void);
351 extern void *decode_reg(struct xen_regs *regs, u8 b);
353 struct exec_domain *ed = current;
354 unsigned long *reg, eip = regs->eip;
355 u8 opcode;
357 if ( get_user(opcode, (u8 *)eip) )
358 goto page_fault;
359 eip += 1;
360 if ( (opcode & 0xff) != 0x0f )
361 goto fail;
363 if ( get_user(opcode, (u8 *)eip) )
364 goto page_fault;
365 eip += 1;
367 switch ( opcode )
368 {
369 case 0x06: /* CLTS */
370 (void)do_fpu_taskswitch();
371 break;
373 case 0x09: /* WBINVD */
374 if ( !IS_CAPABLE_PHYSDEV(ed->domain) )
375 {
376 DPRINTK("Non-physdev domain attempted WBINVD.\n");
377 goto fail;
378 }
379 wbinvd();
380 break;
382 case 0x20: /* MOV CR?,<reg> */
383 if ( get_user(opcode, (u8 *)eip) )
384 goto page_fault;
385 eip += 1;
386 if ( (opcode & 0xc0) != 0xc0 )
387 goto fail;
388 reg = decode_reg(regs, opcode & 7);
389 switch ( (opcode >> 3) & 7 )
390 {
391 case 0: /* Read CR0 */
392 *reg =
393 (read_cr0() & ~X86_CR0_TS) |
394 (test_bit(EDF_GUEST_STTS, &ed->ed_flags) ? X86_CR0_TS : 0);
395 break;
397 case 2: /* Read CR2 */
398 *reg = ed->arch.guest_cr2;
399 break;
401 case 3: /* Read CR3 */
402 *reg = pagetable_val(ed->arch.pagetable);
403 break;
405 default:
406 goto fail;
407 }
408 break;
410 case 0x22: /* MOV <reg>,CR? */
411 if ( get_user(opcode, (u8 *)eip) )
412 goto page_fault;
413 eip += 1;
414 if ( (opcode & 0xc0) != 0xc0 )
415 goto fail;
416 reg = decode_reg(regs, opcode & 7);
417 switch ( (opcode >> 3) & 7 )
418 {
419 case 0: /* Write CR0 */
420 if ( *reg & X86_CR0_TS ) /* XXX ignore all but TS bit */
421 (void)do_fpu_taskswitch;
422 break;
424 case 2: /* Write CR2 */
425 ed->arch.guest_cr2 = *reg;
426 break;
428 case 3: /* Write CR3 */
429 LOCK_BIGLOCK(ed->domain);
430 (void)new_guest_cr3(*reg);
431 UNLOCK_BIGLOCK(ed->domain);
432 break;
434 default:
435 goto fail;
436 }
437 break;
439 case 0x30: /* WRMSR */
440 if ( !IS_PRIV(ed->domain) )
441 {
442 DPRINTK("Non-priv domain attempted WRMSR.\n");
443 goto fail;
444 }
445 wrmsr(regs->ecx, regs->eax, regs->edx);
446 break;
448 case 0x32: /* RDMSR */
449 if ( !IS_PRIV(ed->domain) )
450 {
451 DPRINTK("Non-priv domain attempted RDMSR.\n");
452 goto fail;
453 }
454 rdmsr(regs->ecx, regs->eax, regs->edx);
455 break;
457 default:
458 goto fail;
459 }
461 regs->eip = eip;
462 return EXCRET_fault_fixed;
464 fail:
465 return 0;
467 page_fault:
468 propagate_page_fault(eip, 0);
469 return EXCRET_fault_fixed;
470 }
472 asmlinkage int do_general_protection(struct xen_regs *regs)
473 {
474 struct exec_domain *ed = current;
475 struct trap_bounce *tb = &ed->arch.trap_bounce;
476 trap_info_t *ti;
477 unsigned long fixup;
479 DEBUGGER_trap_entry(TRAP_gp_fault, regs);
481 if ( regs->error_code & 1 )
482 goto hardware_gp;
484 if ( !GUEST_MODE(regs) )
485 goto gp_in_kernel;
487 /*
488 * Cunning trick to allow arbitrary "INT n" handling.
489 *
490 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
491 * instruction from trapping to the appropriate vector, when that might not
492 * be expected by Xen or the guest OS. For example, that entry might be for
493 * a fault handler (unlike traps, faults don't increment EIP), or might
494 * expect an error code on the stack (which a software trap never
495 * provides), or might be a hardware interrupt handler that doesn't like
496 * being called spuriously.
497 *
498 * Instead, a GPF occurs with the faulting IDT vector in the error code.
499 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
500 * clear to indicate that it's a software fault, not hardware.
501 *
502 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
503 * okay because they can only be triggered by an explicit DPL-checked
504 * instruction. The DPL specified by the guest OS for these vectors is NOT
505 * CHECKED!!
506 */
507 if ( (regs->error_code & 3) == 2 )
508 {
509 /* This fault must be due to <INT n> instruction. */
510 ti = current->arch.traps + (regs->error_code>>3);
511 if ( TI_GET_DPL(ti) >= (VM86_MODE(regs) ? 3 : (regs->cs & 3)) )
512 {
513 tb->flags = TBF_EXCEPTION;
514 regs->eip += 2;
515 goto finish_propagation;
516 }
517 }
519 /* Emulate some simple privileged instructions when exec'ed in ring 1. */
520 if ( (regs->error_code == 0) &&
521 KERNEL_MODE(ed, regs) &&
522 emulate_privileged_op(regs) )
523 return 0;
525 #if defined(__i386__)
526 if ( VM_ASSIST(ed->domain, VMASST_TYPE_4gb_segments) &&
527 (regs->error_code == 0) &&
528 gpf_emulate_4gb(regs) )
529 return 0;
530 #endif
532 #ifndef NDEBUG
533 if ( (ed->arch.traps[TRAP_gp_fault].address == 0) &&
534 (ed->domain->id == 0) )
535 goto gp_in_kernel;
536 #endif
538 /* Pass on GPF as is. */
539 ti = current->arch.traps + 13;
540 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
541 tb->error_code = regs->error_code;
542 finish_propagation:
543 tb->cs = ti->cs;
544 tb->eip = ti->address;
545 if ( TI_GET_IF(ti) )
546 ed->vcpu_info->evtchn_upcall_mask = 1;
547 return 0;
549 gp_in_kernel:
551 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
552 {
553 DPRINTK("GPF (%04x): %p -> %p\n",
554 regs->error_code, regs->eip, fixup);
555 regs->eip = fixup;
556 return 0;
557 }
559 DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
561 hardware_gp:
562 show_registers(regs);
563 panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
564 smp_processor_id(), regs->error_code);
565 return 0;
566 }
568 unsigned long nmi_softirq_reason;
569 static void nmi_softirq(void)
570 {
571 if ( dom0 == NULL )
572 return;
574 if ( test_and_clear_bit(0, &nmi_softirq_reason) )
575 send_guest_virq(dom0->exec_domain[0], VIRQ_PARITY_ERR);
577 if ( test_and_clear_bit(1, &nmi_softirq_reason) )
578 send_guest_virq(dom0->exec_domain[0], VIRQ_IO_ERR);
579 }
581 asmlinkage void mem_parity_error(struct xen_regs *regs)
582 {
583 /* Clear and disable the parity-error line. */
584 outb((inb(0x61)&15)|4,0x61);
586 switch ( opt_nmi[0] )
587 {
588 case 'd': /* 'dom0' */
589 set_bit(0, &nmi_softirq_reason);
590 raise_softirq(NMI_SOFTIRQ);
591 case 'i': /* 'ignore' */
592 break;
593 default: /* 'fatal' */
594 console_force_unlock();
595 printk("\n\nNMI - MEMORY ERROR\n");
596 fatal_trap(TRAP_nmi, regs);
597 }
598 }
600 asmlinkage void io_check_error(struct xen_regs *regs)
601 {
602 /* Clear and disable the I/O-error line. */
603 outb((inb(0x61)&15)|8,0x61);
605 switch ( opt_nmi[0] )
606 {
607 case 'd': /* 'dom0' */
608 set_bit(0, &nmi_softirq_reason);
609 raise_softirq(NMI_SOFTIRQ);
610 case 'i': /* 'ignore' */
611 break;
612 default: /* 'fatal' */
613 console_force_unlock();
614 printk("\n\nNMI - I/O ERROR\n");
615 fatal_trap(TRAP_nmi, regs);
616 }
617 }
619 static void unknown_nmi_error(unsigned char reason)
620 {
621 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
622 printk("Dazed and confused, but trying to continue\n");
623 printk("Do you have a strange power saving mode enabled?\n");
624 }
626 asmlinkage void do_nmi(struct xen_regs *regs, unsigned long reason)
627 {
628 ++nmi_count(smp_processor_id());
630 if ( nmi_watchdog )
631 nmi_watchdog_tick(regs);
633 if ( reason & 0x80 )
634 mem_parity_error(regs);
635 else if ( reason & 0x40 )
636 io_check_error(regs);
637 else if ( !nmi_watchdog )
638 unknown_nmi_error((unsigned char)(reason&0xff));
639 }
641 asmlinkage int math_state_restore(struct xen_regs *regs)
642 {
643 /* Prevent recursion. */
644 clts();
646 if ( !test_bit(EDF_USEDFPU, &current->ed_flags) )
647 {
648 if ( test_bit(EDF_DONEFPUINIT, &current->ed_flags) )
649 restore_fpu(current);
650 else
651 init_fpu();
652 set_bit(EDF_USEDFPU, &current->ed_flags); /* so we fnsave on switch_to() */
653 }
655 if ( test_and_clear_bit(EDF_GUEST_STTS, &current->ed_flags) )
656 {
657 struct trap_bounce *tb = &current->arch.trap_bounce;
658 tb->flags = TBF_EXCEPTION;
659 tb->cs = current->arch.traps[7].cs;
660 tb->eip = current->arch.traps[7].address;
661 }
663 return EXCRET_fault_fixed;
664 }
666 asmlinkage int do_debug(struct xen_regs *regs)
667 {
668 unsigned long condition;
669 struct exec_domain *d = current;
670 struct trap_bounce *tb = &d->arch.trap_bounce;
672 DEBUGGER_trap_entry(TRAP_debug, regs);
674 __asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
676 /* Mask out spurious debug traps due to lazy DR7 setting */
677 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
678 (d->arch.debugreg[7] == 0) )
679 {
680 __asm__("mov %0,%%db7" : : "r" (0UL));
681 goto out;
682 }
684 if ( !GUEST_MODE(regs) )
685 {
686 /* Clear TF just for absolute sanity. */
687 regs->eflags &= ~EF_TF;
688 /*
689 * We ignore watchpoints when they trigger within Xen. This may happen
690 * when a buffer is passed to us which previously had a watchpoint set
691 * on it. No need to bump EIP; the only faulting trap is an instruction
692 * breakpoint, which can't happen to us.
693 */
694 goto out;
695 }
697 /* Save debug status register where guest OS can peek at it */
698 d->arch.debugreg[6] = condition;
700 tb->flags = TBF_EXCEPTION;
701 tb->cs = d->arch.traps[1].cs;
702 tb->eip = d->arch.traps[1].address;
704 out:
705 return EXCRET_not_a_fault;
706 }
708 asmlinkage int do_spurious_interrupt_bug(struct xen_regs *regs)
709 {
710 return EXCRET_not_a_fault;
711 }
713 void set_intr_gate(unsigned int n, void *addr)
714 {
715 _set_gate(idt_table+n,14,0,addr);
716 }
718 void set_system_gate(unsigned int n, void *addr)
719 {
720 _set_gate(idt_table+n,14,3,addr);
721 }
723 void set_task_gate(unsigned int n, unsigned int sel)
724 {
725 idt_table[n].a = sel << 16;
726 idt_table[n].b = 0x8500;
727 }
729 void set_tss_desc(unsigned int n, void *addr)
730 {
731 _set_tssldt_desc(
732 gdt_table + __TSS(n),
733 (unsigned long)addr,
734 offsetof(struct tss_struct, __cacheline_filler) - 1,
735 9);
736 }
738 void __init trap_init(void)
739 {
740 extern void percpu_traps_init(void);
741 extern void cpu_init(void);
743 /*
744 * Note that interrupt gates are always used, rather than trap gates. We
745 * must have interrupts disabled until DS/ES/FS/GS are saved because the
746 * first activation must have the "bad" value(s) for these registers and
747 * we may lose them if another activation is installed before they are
748 * saved. The page-fault handler also needs interrupts disabled until %cr2
749 * has been read and saved on the stack.
750 */
751 set_intr_gate(TRAP_divide_error,&divide_error);
752 set_intr_gate(TRAP_debug,&debug);
753 set_intr_gate(TRAP_nmi,&nmi);
754 set_system_gate(TRAP_int3,&int3); /* usable from all privileges */
755 set_system_gate(TRAP_overflow,&overflow); /* usable from all privileges */
756 set_intr_gate(TRAP_bounds,&bounds);
757 set_intr_gate(TRAP_invalid_op,&invalid_op);
758 set_intr_gate(TRAP_no_device,&device_not_available);
759 set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
760 set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
761 set_intr_gate(TRAP_no_segment,&segment_not_present);
762 set_intr_gate(TRAP_stack_error,&stack_segment);
763 set_intr_gate(TRAP_gp_fault,&general_protection);
764 set_intr_gate(TRAP_page_fault,&page_fault);
765 set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
766 set_intr_gate(TRAP_copro_error,&coprocessor_error);
767 set_intr_gate(TRAP_alignment_check,&alignment_check);
768 set_intr_gate(TRAP_machine_check,&machine_check);
769 set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
771 percpu_traps_init();
773 cpu_init();
775 open_softirq(NMI_SOFTIRQ, nmi_softirq);
776 }
779 long do_set_trap_table(trap_info_t *traps)
780 {
781 trap_info_t cur;
782 trap_info_t *dst = current->arch.traps;
784 LOCK_BIGLOCK(current->domain);
786 for ( ; ; )
787 {
788 if ( hypercall_preempt_check() )
789 {
790 UNLOCK_BIGLOCK(current->domain);
791 return hypercall1_create_continuation(
792 __HYPERVISOR_set_trap_table, traps);
793 }
795 if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
797 if ( cur.address == 0 ) break;
799 if ( !VALID_CODESEL(cur.cs) ) return -EPERM;
801 memcpy(dst+cur.vector, &cur, sizeof(cur));
802 traps++;
803 }
805 UNLOCK_BIGLOCK(current->domain);
807 return 0;
808 }
811 long do_fpu_taskswitch(void)
812 {
813 set_bit(EDF_GUEST_STTS, &current->ed_flags);
814 stts();
815 return 0;
816 }
819 #if defined(__i386__)
820 #define DB_VALID_ADDR(_a) \
821 ((_a) <= (PAGE_OFFSET - 4))
822 #elif defined(__x86_64__)
823 #define DB_VALID_ADDR(_a) \
824 ((_a) >= HYPERVISOR_VIRT_END) || ((_a) <= (HYPERVISOR_VIRT_START-8))
825 #endif
826 long set_debugreg(struct exec_domain *p, int reg, unsigned long value)
827 {
828 int i;
830 switch ( reg )
831 {
832 case 0:
833 if ( !DB_VALID_ADDR(value) ) return -EPERM;
834 if ( p == current )
835 __asm__ ( "mov %0, %%db0" : : "r" (value) );
836 break;
837 case 1:
838 if ( !DB_VALID_ADDR(value) ) return -EPERM;
839 if ( p == current )
840 __asm__ ( "mov %0, %%db1" : : "r" (value) );
841 break;
842 case 2:
843 if ( !DB_VALID_ADDR(value) ) return -EPERM;
844 if ( p == current )
845 __asm__ ( "mov %0, %%db2" : : "r" (value) );
846 break;
847 case 3:
848 if ( !DB_VALID_ADDR(value) ) return -EPERM;
849 if ( p == current )
850 __asm__ ( "mov %0, %%db3" : : "r" (value) );
851 break;
852 case 6:
853 /*
854 * DR6: Bits 4-11,16-31 reserved (set to 1).
855 * Bit 12 reserved (set to 0).
856 */
857 value &= 0xffffefff; /* reserved bits => 0 */
858 value |= 0xffff0ff0; /* reserved bits => 1 */
859 if ( p == current )
860 __asm__ ( "mov %0, %%db6" : : "r" (value) );
861 break;
862 case 7:
863 /*
864 * DR7: Bit 10 reserved (set to 1).
865 * Bits 11-12,14-15 reserved (set to 0).
866 * Privileged bits:
867 * GD (bit 13): must be 0.
868 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
869 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
870 */
871 /* DR7 == 0 => debugging disabled for this domain. */
872 if ( value != 0 )
873 {
874 value &= 0xffff27ff; /* reserved bits => 0 */
875 value |= 0x00000400; /* reserved bits => 1 */
876 if ( (value & (1<<13)) != 0 ) return -EPERM;
877 for ( i = 0; i < 16; i += 2 )
878 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
879 }
880 if ( p == current )
881 __asm__ ( "mov %0, %%db7" : : "r" (value) );
882 break;
883 default:
884 return -EINVAL;
885 }
887 p->arch.debugreg[reg] = value;
888 return 0;
889 }
891 long do_set_debugreg(int reg, unsigned long value)
892 {
893 return set_debugreg(current, reg, value);
894 }
896 unsigned long do_get_debugreg(int reg)
897 {
898 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
899 return current->arch.debugreg[reg];
900 }