ia64/xen-unstable

view xen/arch/x86/traps.c @ 8597:3f702887d4a6

Correctly handle dumping a VM86 guest's stack.

If the guest context is VM86 then we need to treat ss:sp as 16 bit
segment:offset rather than 32 bit selector:offset.

Signed-off-by: Ian Campbell <Ian.Campbell@XenSource.com>
author Ian.Campbell@xensource.com
date Fri Jan 13 16:56:09 2006 +0000 (2006-01-13)
parents 8531996d207f
children 98c8afe4c433
line source
1 /******************************************************************************
2 * arch/x86/traps.c
3 *
4 * Modifications to Linux original are copyright (c) 2002-2004, 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 * Copyright (C) 1991, 1992 Linus Torvalds
23 *
24 * Pentium III FXSR, SSE support
25 * Gareth Hughes <gareth@valinux.com>, May 2000
26 */
28 #include <xen/config.h>
29 #include <xen/init.h>
30 #include <xen/sched.h>
31 #include <xen/lib.h>
32 #include <xen/errno.h>
33 #include <xen/mm.h>
34 #include <xen/console.h>
35 #include <asm/regs.h>
36 #include <xen/delay.h>
37 #include <xen/event.h>
38 #include <xen/spinlock.h>
39 #include <xen/irq.h>
40 #include <xen/perfc.h>
41 #include <xen/softirq.h>
42 #include <xen/domain_page.h>
43 #include <xen/symbols.h>
44 #include <xen/iocap.h>
45 #include <asm/shadow.h>
46 #include <asm/system.h>
47 #include <asm/io.h>
48 #include <asm/atomic.h>
49 #include <asm/desc.h>
50 #include <asm/debugreg.h>
51 #include <asm/smp.h>
52 #include <asm/flushtlb.h>
53 #include <asm/uaccess.h>
54 #include <asm/i387.h>
55 #include <asm/debugger.h>
56 #include <asm/msr.h>
57 #include <asm/x86_emulate.h>
58 #include <asm/nmi.h>
60 /*
61 * opt_nmi: one of 'ignore', 'dom0', or 'fatal'.
62 * fatal: Xen prints diagnostic message and then hangs.
63 * dom0: The NMI is virtualised to DOM0.
64 * ignore: The NMI error is cleared and ignored.
65 */
66 #ifdef NDEBUG
67 char opt_nmi[10] = "dom0";
68 #else
69 char opt_nmi[10] = "fatal";
70 #endif
71 string_param("nmi", opt_nmi);
73 /* Master table, used by all CPUs on x86/64, and by CPU0 on x86/32.*/
74 idt_entry_t idt_table[IDT_ENTRIES];
76 #define DECLARE_TRAP_HANDLER(_name) \
77 asmlinkage void _name(void); \
78 asmlinkage int do_ ## _name(struct cpu_user_regs *regs)
80 asmlinkage void nmi(void);
81 DECLARE_TRAP_HANDLER(divide_error);
82 DECLARE_TRAP_HANDLER(debug);
83 DECLARE_TRAP_HANDLER(int3);
84 DECLARE_TRAP_HANDLER(overflow);
85 DECLARE_TRAP_HANDLER(bounds);
86 DECLARE_TRAP_HANDLER(invalid_op);
87 DECLARE_TRAP_HANDLER(device_not_available);
88 DECLARE_TRAP_HANDLER(coprocessor_segment_overrun);
89 DECLARE_TRAP_HANDLER(invalid_TSS);
90 DECLARE_TRAP_HANDLER(segment_not_present);
91 DECLARE_TRAP_HANDLER(stack_segment);
92 DECLARE_TRAP_HANDLER(general_protection);
93 DECLARE_TRAP_HANDLER(page_fault);
94 DECLARE_TRAP_HANDLER(coprocessor_error);
95 DECLARE_TRAP_HANDLER(simd_coprocessor_error);
96 DECLARE_TRAP_HANDLER(alignment_check);
97 DECLARE_TRAP_HANDLER(spurious_interrupt_bug);
98 DECLARE_TRAP_HANDLER(machine_check);
100 long do_set_debugreg(int reg, unsigned long value);
101 unsigned long do_get_debugreg(int reg);
103 static int debug_stack_lines = 20;
104 integer_param("debug_stack_lines", debug_stack_lines);
106 #ifdef CONFIG_X86_32
107 #define stack_words_per_line 8
108 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)&regs->esp)
109 #else
110 #define stack_words_per_line 4
111 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->rsp)
112 #endif
114 int is_kernel_text(unsigned long addr)
115 {
116 extern char _stext, _etext;
117 if (addr >= (unsigned long) &_stext &&
118 addr <= (unsigned long) &_etext)
119 return 1;
120 return 0;
122 }
124 unsigned long kernel_text_end(void)
125 {
126 extern char _etext;
127 return (unsigned long) &_etext;
128 }
130 static void show_guest_stack(struct cpu_user_regs *regs)
131 {
132 int i;
133 unsigned long *stack, addr;
135 if ( VM86_MODE(regs) )
136 {
137 stack = (unsigned long *)((regs->ss << 4) + (regs->esp & 0xffff));
138 printk("Guest stack trace from ss:sp = %04x:%04x (VM86)\n ",
139 regs->ss, (uint16_t)(regs->esp & 0xffff));
140 }
141 else
142 {
143 stack = (unsigned long *)regs->esp;
144 printk("Guest stack trace from "__OP"sp=%p:\n ", stack);
145 }
147 for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
148 {
149 if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
150 break;
151 if ( get_user(addr, stack) )
152 {
153 if ( i != 0 )
154 printk("\n ");
155 printk("Fault while accessing guest memory.");
156 i = 1;
157 break;
158 }
159 if ( (i != 0) && ((i % stack_words_per_line) == 0) )
160 printk("\n ");
161 printk("%p ", _p(addr));
162 stack++;
163 }
164 if ( i == 0 )
165 printk("Stack empty.");
166 printk("\n");
167 }
169 #ifdef NDEBUG
171 static void show_trace(struct cpu_user_regs *regs)
172 {
173 unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
175 printk("Xen call trace:\n ");
177 printk("[<%p>]", _p(regs->eip));
178 print_symbol(" %s\n ", regs->eip);
180 while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )
181 {
182 addr = *stack++;
183 if ( is_kernel_text(addr) )
184 {
185 printk("[<%p>]", _p(addr));
186 print_symbol(" %s\n ", addr);
187 }
188 }
190 printk("\n");
191 }
193 #else
195 static void show_trace(struct cpu_user_regs *regs)
196 {
197 unsigned long *frame, next, addr, low, high;
199 printk("Xen call trace:\n ");
201 printk("[<%p>]", _p(regs->eip));
202 print_symbol(" %s\n ", regs->eip);
204 /* Bounds for range of valid frame pointer. */
205 low = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);
206 high = (low & ~(STACK_SIZE - 1)) +
207 (STACK_SIZE - sizeof(struct cpu_info) - 2*sizeof(unsigned long));
209 /* The initial frame pointer. */
210 next = regs->ebp;
212 for ( ; ; )
213 {
214 /* Valid frame pointer? */
215 if ( (next < low) || (next >= high) )
216 {
217 /*
218 * Exception stack frames have a different layout, denoted by an
219 * inverted frame pointer.
220 */
221 next = ~next;
222 if ( (next < low) || (next >= high) )
223 break;
224 frame = (unsigned long *)next;
225 next = frame[0];
226 addr = frame[(offsetof(struct cpu_user_regs, eip) -
227 offsetof(struct cpu_user_regs, ebp))
228 / BYTES_PER_LONG];
229 }
230 else
231 {
232 /* Ordinary stack frame. */
233 frame = (unsigned long *)next;
234 next = frame[0];
235 addr = frame[1];
236 }
238 printk("[<%p>]", _p(addr));
239 print_symbol(" %s\n ", addr);
241 low = (unsigned long)&frame[2];
242 }
244 printk("\n");
245 }
247 #endif
249 void show_stack(struct cpu_user_regs *regs)
250 {
251 unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
252 int i;
254 if ( GUEST_CONTEXT(current, regs) )
255 return show_guest_stack(regs);
257 printk("Xen stack trace from "__OP"sp=%p:\n ", stack);
259 for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
260 {
261 if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
262 break;
263 if ( (i != 0) && ((i % stack_words_per_line) == 0) )
264 printk("\n ");
265 addr = *stack++;
266 printk("%p ", _p(addr));
267 }
268 if ( i == 0 )
269 printk("Stack empty.");
270 printk("\n");
272 show_trace(regs);
273 }
275 /*
276 * This is called for faults at very unexpected times (e.g., when interrupts
277 * are disabled). In such situations we can't do much that is safe. We try to
278 * print out some tracing and then we just spin.
279 */
280 asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs)
281 {
282 int cpu = smp_processor_id();
283 unsigned long cr2;
284 static char *trapstr[] = {
285 "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
286 "invalid operation", "device not available", "double fault",
287 "coprocessor segment", "invalid tss", "segment not found",
288 "stack error", "general protection fault", "page fault",
289 "spurious interrupt", "coprocessor error", "alignment check",
290 "machine check", "simd error"
291 };
293 watchdog_disable();
294 console_start_sync();
296 show_registers(regs);
298 if ( trapnr == TRAP_page_fault )
299 {
300 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (cr2) : );
301 printk("Faulting linear address: %p\n", _p(cr2));
302 show_page_walk(cr2);
303 }
305 printk("************************************\n");
306 printk("CPU%d FATAL TRAP %d (%s), ERROR_CODE %04x%s.\n",
307 cpu, trapnr, trapstr[trapnr], regs->error_code,
308 (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");
309 printk("System shutting down -- need manual reset.\n");
310 printk("************************************\n");
312 (void)debugger_trap_fatal(trapnr, regs);
314 /* Lock up the console to prevent spurious output from other CPUs. */
315 console_force_lock();
317 /* Wait for manual reset. */
318 for ( ; ; )
319 __asm__ __volatile__ ( "hlt" );
320 }
322 static inline int do_trap(int trapnr, char *str,
323 struct cpu_user_regs *regs,
324 int use_error_code)
325 {
326 struct vcpu *v = current;
327 struct trap_bounce *tb = &v->arch.trap_bounce;
328 trap_info_t *ti;
329 unsigned long fixup;
331 DEBUGGER_trap_entry(trapnr, regs);
333 if ( !GUEST_MODE(regs) )
334 goto xen_fault;
336 ti = &current->arch.guest_context.trap_ctxt[trapnr];
337 tb->flags = TBF_EXCEPTION;
338 tb->cs = ti->cs;
339 tb->eip = ti->address;
340 if ( use_error_code )
341 {
342 tb->flags |= TBF_EXCEPTION_ERRCODE;
343 tb->error_code = regs->error_code;
344 }
345 if ( TI_GET_IF(ti) )
346 tb->flags |= TBF_INTERRUPT;
347 return 0;
349 xen_fault:
351 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
352 {
353 DPRINTK("Trap %d: %p -> %p\n", trapnr, _p(regs->eip), _p(fixup));
354 regs->eip = fixup;
355 return 0;
356 }
358 DEBUGGER_trap_fatal(trapnr, regs);
360 show_registers(regs);
361 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
362 "[error_code=%04x]\n",
363 smp_processor_id(), trapnr, str, regs->error_code);
364 return 0;
365 }
367 #define DO_ERROR_NOCODE(trapnr, str, name) \
368 asmlinkage int do_##name(struct cpu_user_regs *regs) \
369 { \
370 return do_trap(trapnr, str, regs, 0); \
371 }
373 #define DO_ERROR(trapnr, str, name) \
374 asmlinkage int do_##name(struct cpu_user_regs *regs) \
375 { \
376 return do_trap(trapnr, str, regs, 1); \
377 }
379 DO_ERROR_NOCODE( 0, "divide error", divide_error)
380 DO_ERROR_NOCODE( 4, "overflow", overflow)
381 DO_ERROR_NOCODE( 5, "bounds", bounds)
382 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
383 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
384 DO_ERROR(10, "invalid TSS", invalid_TSS)
385 DO_ERROR(11, "segment not present", segment_not_present)
386 DO_ERROR(12, "stack segment", stack_segment)
387 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
388 DO_ERROR(17, "alignment check", alignment_check)
389 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
391 asmlinkage int do_int3(struct cpu_user_regs *regs)
392 {
393 struct vcpu *v = current;
394 struct trap_bounce *tb = &v->arch.trap_bounce;
395 trap_info_t *ti;
397 DEBUGGER_trap_entry(TRAP_int3, regs);
399 if ( !GUEST_MODE(regs) )
400 {
401 DEBUGGER_trap_fatal(TRAP_int3, regs);
402 show_registers(regs);
403 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
404 }
406 ti = &current->arch.guest_context.trap_ctxt[TRAP_int3];
407 tb->flags = TBF_EXCEPTION;
408 tb->cs = ti->cs;
409 tb->eip = ti->address;
410 if ( TI_GET_IF(ti) )
411 tb->flags |= TBF_INTERRUPT;
413 return 0;
414 }
416 asmlinkage int do_machine_check(struct cpu_user_regs *regs)
417 {
418 fatal_trap(TRAP_machine_check, regs);
419 return 0;
420 }
422 void propagate_page_fault(unsigned long addr, u16 error_code)
423 {
424 trap_info_t *ti;
425 struct vcpu *v = current;
426 struct trap_bounce *tb = &v->arch.trap_bounce;
428 v->arch.guest_context.ctrlreg[2] = addr;
429 v->vcpu_info->arch.cr2 = addr;
431 ti = &v->arch.guest_context.trap_ctxt[TRAP_page_fault];
432 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
433 tb->error_code = error_code;
434 tb->cs = ti->cs;
435 tb->eip = ti->address;
436 if ( TI_GET_IF(ti) )
437 tb->flags |= TBF_INTERRUPT;
438 }
440 static int handle_gdt_ldt_mapping_fault(
441 unsigned long offset, struct cpu_user_regs *regs)
442 {
443 extern int map_ldt_shadow_page(unsigned int);
445 struct vcpu *v = current;
446 struct domain *d = v->domain;
447 int ret;
449 /* Which vcpu's area did we fault in, and is it in the ldt sub-area? */
450 unsigned int is_ldt_area = (offset >> (GDT_LDT_VCPU_VA_SHIFT-1)) & 1;
451 unsigned int vcpu_area = (offset >> GDT_LDT_VCPU_VA_SHIFT);
453 /* Should never fault in another vcpu's area. */
454 BUG_ON(vcpu_area != current->vcpu_id);
456 /* Byte offset within the gdt/ldt sub-area. */
457 offset &= (1UL << (GDT_LDT_VCPU_VA_SHIFT-1)) - 1UL;
459 if ( likely(is_ldt_area) )
460 {
461 /* LDT fault: Copy a mapping from the guest's LDT, if it is valid. */
462 LOCK_BIGLOCK(d);
463 ret = map_ldt_shadow_page(offset >> PAGE_SHIFT);
464 UNLOCK_BIGLOCK(d);
466 if ( unlikely(ret == 0) )
467 {
468 /* In hypervisor mode? Leave it to the #PF handler to fix up. */
469 if ( !GUEST_MODE(regs) )
470 return 0;
471 /* In guest mode? Propagate #PF to guest, with adjusted %cr2. */
472 propagate_page_fault(
473 v->arch.guest_context.ldt_base + offset, regs->error_code);
474 }
475 }
476 else
477 {
478 /* GDT fault: handle the fault as #GP(selector). */
479 regs->error_code = (u16)offset & ~7;
480 (void)do_general_protection(regs);
481 }
483 return EXCRET_fault_fixed;
484 }
486 #ifdef HYPERVISOR_VIRT_END
487 #define IN_HYPERVISOR_RANGE(va) \
488 (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
489 #else
490 #define IN_HYPERVISOR_RANGE(va) \
491 (((va) >= HYPERVISOR_VIRT_START))
492 #endif
494 static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
495 {
496 struct vcpu *v = current;
497 struct domain *d = v->domain;
499 if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
500 {
501 if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) )
502 return shadow_fault(addr, regs);
503 if ( (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) )
504 return handle_gdt_ldt_mapping_fault(
505 addr - GDT_LDT_VIRT_START, regs);
506 }
507 else if ( unlikely(shadow_mode_enabled(d)) )
508 {
509 return shadow_fault(addr, regs);
510 }
511 else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
512 {
513 LOCK_BIGLOCK(d);
514 if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) &&
515 unlikely(l2_linear_offset(addr) ==
516 d->arch.ptwr[PTWR_PT_ACTIVE].l2_idx) )
517 {
518 ptwr_flush(d, PTWR_PT_ACTIVE);
519 UNLOCK_BIGLOCK(d);
520 return EXCRET_fault_fixed;
521 }
523 if ( KERNEL_MODE(v, regs) &&
524 /* Protection violation on write? No reserved-bit violation? */
525 ((regs->error_code & 0xb) == 0x3) &&
526 ptwr_do_page_fault(d, addr, regs) )
527 {
528 UNLOCK_BIGLOCK(d);
529 return EXCRET_fault_fixed;
530 }
531 UNLOCK_BIGLOCK(d);
532 }
534 return 0;
535 }
537 /*
538 * #PF error code:
539 * Bit 0: Protection violation (=1) ; Page not present (=0)
540 * Bit 1: Write access
541 * Bit 2: Supervisor mode
542 * Bit 3: Reserved bit violation
543 * Bit 4: Instruction fetch
544 */
545 asmlinkage int do_page_fault(struct cpu_user_regs *regs)
546 {
547 unsigned long addr, fixup;
548 int rc;
550 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
552 DEBUGGER_trap_entry(TRAP_page_fault, regs);
554 perfc_incrc(page_faults);
556 if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) )
557 return rc;
559 if ( unlikely(!GUEST_MODE(regs)) )
560 {
561 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
562 {
563 perfc_incrc(copy_user_faults);
564 regs->eip = fixup;
565 return 0;
566 }
568 DEBUGGER_trap_fatal(TRAP_page_fault, regs);
570 show_registers(regs);
571 show_page_walk(addr);
572 panic("CPU%d FATAL PAGE FAULT\n"
573 "[error_code=%04x]\n"
574 "Faulting linear address: %p\n",
575 smp_processor_id(), regs->error_code, addr);
576 }
578 propagate_page_fault(addr, regs->error_code);
579 return 0;
580 }
582 long do_fpu_taskswitch(int set)
583 {
584 struct vcpu *v = current;
586 if ( set )
587 {
588 v->arch.guest_context.ctrlreg[0] |= X86_CR0_TS;
589 stts();
590 }
591 else
592 {
593 v->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
594 if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
595 clts();
596 }
598 return 0;
599 }
601 /* Has the guest requested sufficient permission for this I/O access? */
602 static inline int guest_io_okay(
603 unsigned int port, unsigned int bytes,
604 struct vcpu *v, struct cpu_user_regs *regs)
605 {
606 u16 x;
607 #if defined(__x86_64__)
608 /* If in user mode, switch to kernel mode just to read I/O bitmap. */
609 int user_mode = !(v->arch.flags & TF_kernel_mode);
610 #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v)
611 #elif defined(__i386__)
612 #define TOGGLE_MODE() ((void)0)
613 #endif
615 if ( v->arch.iopl >= (KERNEL_MODE(v, regs) ? 1 : 3) )
616 return 1;
618 if ( v->arch.iobmp_limit > (port + bytes) )
619 {
620 TOGGLE_MODE();
621 __get_user(x, (u16 *)(v->arch.iobmp+(port>>3)));
622 TOGGLE_MODE();
623 if ( (x & (((1<<bytes)-1) << (port&7))) == 0 )
624 return 1;
625 }
627 return 0;
628 }
630 /* Has the administrator granted sufficient permission for this I/O access? */
631 static inline int admin_io_okay(
632 unsigned int port, unsigned int bytes,
633 struct vcpu *v, struct cpu_user_regs *regs)
634 {
635 return ioports_access_permitted(v->domain, port, port + bytes - 1);
636 }
638 /* Check admin limits. Silently fail the access if it is disallowed. */
639 #define inb_user(_p, _d, _r) (admin_io_okay(_p, 1, _d, _r) ? inb(_p) : ~0)
640 #define inw_user(_p, _d, _r) (admin_io_okay(_p, 2, _d, _r) ? inw(_p) : ~0)
641 #define inl_user(_p, _d, _r) (admin_io_okay(_p, 4, _d, _r) ? inl(_p) : ~0)
642 #define outb_user(_v, _p, _d, _r) \
643 (admin_io_okay(_p, 1, _d, _r) ? outb(_v, _p) : ((void)0))
644 #define outw_user(_v, _p, _d, _r) \
645 (admin_io_okay(_p, 2, _d, _r) ? outw(_v, _p) : ((void)0))
646 #define outl_user(_v, _p, _d, _r) \
647 (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0))
649 /* Propagate a fault back to the guest kernel. */
650 #define USER_READ_FAULT 4 /* user mode, read fault */
651 #define USER_WRITE_FAULT 6 /* user mode, write fault */
652 #define PAGE_FAULT(_faultaddr, _errcode) \
653 ({ propagate_page_fault(_faultaddr, _errcode); \
654 return EXCRET_fault_fixed; \
655 })
657 /* Isntruction fetch with error handling. */
658 #define insn_fetch(_type, _size, _ptr) \
659 ({ unsigned long _x; \
660 if ( get_user(_x, (_type *)eip) ) \
661 PAGE_FAULT(eip, USER_READ_FAULT); \
662 eip += _size; (_type)_x; })
664 static int emulate_privileged_op(struct cpu_user_regs *regs)
665 {
666 struct vcpu *v = current;
667 unsigned long *reg, eip = regs->eip, res;
668 u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0;
669 unsigned int port, i, op_bytes = 4, data;
671 /* Legacy prefixes. */
672 for ( i = 0; i < 8; i++ )
673 {
674 switch ( opcode = insn_fetch(u8, 1, eip) )
675 {
676 case 0x66: /* operand-size override */
677 op_bytes ^= 6; /* switch between 2/4 bytes */
678 break;
679 case 0x67: /* address-size override */
680 case 0x2e: /* CS override */
681 case 0x3e: /* DS override */
682 case 0x26: /* ES override */
683 case 0x64: /* FS override */
684 case 0x65: /* GS override */
685 case 0x36: /* SS override */
686 case 0xf0: /* LOCK */
687 case 0xf2: /* REPNE/REPNZ */
688 break;
689 case 0xf3: /* REP/REPE/REPZ */
690 rep_prefix = 1;
691 break;
692 default:
693 goto done_prefixes;
694 }
695 }
696 done_prefixes:
698 #ifdef __x86_64__
699 /* REX prefix. */
700 if ( (opcode & 0xf0) == 0x40 )
701 {
702 modrm_reg = (opcode & 4) << 1; /* REX.R */
703 modrm_rm = (opcode & 1) << 3; /* REX.B */
705 /* REX.W and REX.X do not need to be decoded. */
706 opcode = insn_fetch(u8, 1, eip);
707 }
708 #endif
710 /* Input/Output String instructions. */
711 if ( (opcode >= 0x6c) && (opcode <= 0x6f) )
712 {
713 if ( rep_prefix && (regs->ecx == 0) )
714 goto done;
716 continue_io_string:
717 switch ( opcode )
718 {
719 case 0x6c: /* INSB */
720 op_bytes = 1;
721 case 0x6d: /* INSW/INSL */
722 if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) )
723 goto fail;
724 switch ( op_bytes )
725 {
726 case 1:
727 data = (u8)inb_user((u16)regs->edx, v, regs);
728 if ( put_user((u8)data, (u8 *)regs->edi) )
729 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
730 break;
731 case 2:
732 data = (u16)inw_user((u16)regs->edx, v, regs);
733 if ( put_user((u16)data, (u16 *)regs->edi) )
734 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
735 break;
736 case 4:
737 data = (u32)inl_user((u16)regs->edx, v, regs);
738 if ( put_user((u32)data, (u32 *)regs->edi) )
739 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
740 break;
741 }
742 regs->edi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
743 break;
745 case 0x6e: /* OUTSB */
746 op_bytes = 1;
747 case 0x6f: /* OUTSW/OUTSL */
748 if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) )
749 goto fail;
750 switch ( op_bytes )
751 {
752 case 1:
753 if ( get_user(data, (u8 *)regs->esi) )
754 PAGE_FAULT(regs->esi, USER_READ_FAULT);
755 outb_user((u8)data, (u16)regs->edx, v, regs);
756 break;
757 case 2:
758 if ( get_user(data, (u16 *)regs->esi) )
759 PAGE_FAULT(regs->esi, USER_READ_FAULT);
760 outw_user((u16)data, (u16)regs->edx, v, regs);
761 break;
762 case 4:
763 if ( get_user(data, (u32 *)regs->esi) )
764 PAGE_FAULT(regs->esi, USER_READ_FAULT);
765 outl_user((u32)data, (u16)regs->edx, v, regs);
766 break;
767 }
768 regs->esi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
769 break;
770 }
772 if ( rep_prefix && (--regs->ecx != 0) )
773 {
774 if ( !hypercall_preempt_check() )
775 goto continue_io_string;
776 eip = regs->eip;
777 }
779 goto done;
780 }
782 /* I/O Port and Interrupt Flag instructions. */
783 switch ( opcode )
784 {
785 case 0xe4: /* IN imm8,%al */
786 op_bytes = 1;
787 case 0xe5: /* IN imm8,%eax */
788 port = insn_fetch(u8, 1, eip);
789 exec_in:
790 if ( !guest_io_okay(port, op_bytes, v, regs) )
791 goto fail;
792 switch ( op_bytes )
793 {
794 case 1:
795 regs->eax &= ~0xffUL;
796 regs->eax |= (u8)inb_user(port, v, regs);
797 break;
798 case 2:
799 regs->eax &= ~0xffffUL;
800 regs->eax |= (u16)inw_user(port, v, regs);
801 break;
802 case 4:
803 regs->eax = (u32)inl_user(port, v, regs);
804 break;
805 }
806 goto done;
808 case 0xec: /* IN %dx,%al */
809 op_bytes = 1;
810 case 0xed: /* IN %dx,%eax */
811 port = (u16)regs->edx;
812 goto exec_in;
814 case 0xe6: /* OUT %al,imm8 */
815 op_bytes = 1;
816 case 0xe7: /* OUT %eax,imm8 */
817 port = insn_fetch(u8, 1, eip);
818 exec_out:
819 if ( !guest_io_okay(port, op_bytes, v, regs) )
820 goto fail;
821 switch ( op_bytes )
822 {
823 case 1:
824 outb_user((u8)regs->eax, port, v, regs);
825 break;
826 case 2:
827 outw_user((u16)regs->eax, port, v, regs);
828 break;
829 case 4:
830 outl_user((u32)regs->eax, port, v, regs);
831 break;
832 }
833 goto done;
835 case 0xee: /* OUT %al,%dx */
836 op_bytes = 1;
837 case 0xef: /* OUT %eax,%dx */
838 port = (u16)regs->edx;
839 goto exec_out;
841 case 0xfa: /* CLI */
842 case 0xfb: /* STI */
843 if ( v->arch.iopl < (KERNEL_MODE(v, regs) ? 1 : 3) )
844 goto fail;
845 /*
846 * This is just too dangerous to allow, in my opinion. Consider if the
847 * caller then tries to reenable interrupts using POPF: we can't trap
848 * that and we'll end up with hard-to-debug lockups. Fast & loose will
849 * do for us. :-)
850 */
851 /*v->vcpu_info->evtchn_upcall_mask = (opcode == 0xfa);*/
852 goto done;
854 case 0x0f: /* Two-byte opcode */
855 break;
857 default:
858 goto fail;
859 }
861 /* Remaining instructions only emulated from guest kernel. */
862 if ( !KERNEL_MODE(v, regs) )
863 goto fail;
865 /* Privileged (ring 0) instructions. */
866 opcode = insn_fetch(u8, 1, eip);
867 switch ( opcode )
868 {
869 case 0x06: /* CLTS */
870 (void)do_fpu_taskswitch(0);
871 break;
873 case 0x09: /* WBINVD */
874 /* Ignore the instruction if unprivileged. */
875 if ( !cache_flush_permitted(v->domain) )
876 DPRINTK("Non-physdev domain attempted WBINVD.\n");
877 else
878 wbinvd();
879 break;
881 case 0x20: /* MOV CR?,<reg> */
882 opcode = insn_fetch(u8, 1, eip);
883 modrm_reg |= (opcode >> 3) & 7;
884 modrm_rm |= (opcode >> 0) & 7;
885 reg = decode_register(modrm_rm, regs, 0);
886 switch ( modrm_reg )
887 {
888 case 0: /* Read CR0 */
889 *reg = (read_cr0() & ~X86_CR0_TS) |
890 v->arch.guest_context.ctrlreg[0];
891 break;
893 case 2: /* Read CR2 */
894 *reg = v->arch.guest_context.ctrlreg[2];
895 break;
897 case 3: /* Read CR3 */
898 *reg = pagetable_get_paddr(v->arch.guest_table);
899 break;
901 case 4: /* Read CR4 */
902 /*
903 * Guests can read CR4 to see what features Xen has enabled. We
904 * therefore lie about PGE & PSE as they are unavailable to guests.
905 */
906 *reg = read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE);
907 break;
909 default:
910 goto fail;
911 }
912 break;
914 case 0x21: /* MOV DR?,<reg> */
915 opcode = insn_fetch(u8, 1, eip);
916 modrm_reg |= (opcode >> 3) & 7;
917 modrm_rm |= (opcode >> 0) & 7;
918 reg = decode_register(modrm_rm, regs, 0);
919 if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
920 goto fail;
921 *reg = res;
922 break;
924 case 0x22: /* MOV <reg>,CR? */
925 opcode = insn_fetch(u8, 1, eip);
926 modrm_reg |= (opcode >> 3) & 7;
927 modrm_rm |= (opcode >> 0) & 7;
928 reg = decode_register(modrm_rm, regs, 0);
929 switch ( modrm_reg )
930 {
931 case 0: /* Write CR0 */
932 if ( (*reg ^ read_cr0()) & ~X86_CR0_TS )
933 {
934 DPRINTK("Attempt to change unmodifiable CR0 flags.\n");
935 goto fail;
936 }
937 (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS));
938 break;
940 case 2: /* Write CR2 */
941 v->arch.guest_context.ctrlreg[2] = *reg;
942 v->vcpu_info->arch.cr2 = *reg;
943 break;
945 case 3: /* Write CR3 */
946 LOCK_BIGLOCK(v->domain);
947 (void)new_guest_cr3(*reg);
948 UNLOCK_BIGLOCK(v->domain);
949 break;
951 case 4:
952 if ( *reg != (read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE)) )
953 {
954 DPRINTK("Attempt to change CR4 flags.\n");
955 goto fail;
956 }
957 break;
959 default:
960 goto fail;
961 }
962 break;
964 case 0x23: /* MOV <reg>,DR? */
965 opcode = insn_fetch(u8, 1, eip);
966 modrm_reg |= (opcode >> 3) & 7;
967 modrm_rm |= (opcode >> 0) & 7;
968 reg = decode_register(modrm_rm, regs, 0);
969 if ( do_set_debugreg(modrm_reg, *reg) != 0 )
970 goto fail;
971 break;
973 case 0x30: /* WRMSR */
974 /* Ignore the instruction if unprivileged. */
975 if ( !IS_PRIV(v->domain) )
976 {
977 u32 l, h;
978 if ( (rdmsr_user(regs->ecx, l, h) != 0) ||
979 (regs->ecx != MSR_EFER) ||
980 (regs->eax != l) || (regs->edx != h) )
981 DPRINTK("Non-priv domain attempted WRMSR %p from "
982 "%08x:%08x to %08lx:%08lx.\n",
983 _p(regs->ecx), h, l, (long)regs->edx, (long)regs->eax);
984 }
985 else if ( wrmsr_user(regs->ecx, regs->eax, regs->edx) )
986 goto fail;
987 break;
989 case 0x32: /* RDMSR */
990 if ( !IS_PRIV(v->domain) )
991 {
992 if ( regs->ecx != MSR_EFER )
993 DPRINTK("Non-priv domain attempted RDMSR %p.\n",
994 _p(regs->ecx));
995 }
996 /* Everyone can read the MSR space. */
997 if ( rdmsr_user(regs->ecx, regs->eax, regs->edx) )
998 goto fail;
999 break;
1001 default:
1002 goto fail;
1005 done:
1006 regs->eip = eip;
1007 return EXCRET_fault_fixed;
1009 fail:
1010 return 0;
1013 asmlinkage int do_general_protection(struct cpu_user_regs *regs)
1015 struct vcpu *v = current;
1016 struct trap_bounce *tb = &v->arch.trap_bounce;
1017 trap_info_t *ti;
1018 unsigned long fixup;
1020 DEBUGGER_trap_entry(TRAP_gp_fault, regs);
1022 if ( regs->error_code & 1 )
1023 goto hardware_gp;
1025 if ( !GUEST_MODE(regs) )
1026 goto gp_in_kernel;
1028 /*
1029 * Cunning trick to allow arbitrary "INT n" handling.
1031 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
1032 * instruction from trapping to the appropriate vector, when that might not
1033 * be expected by Xen or the guest OS. For example, that entry might be for
1034 * a fault handler (unlike traps, faults don't increment EIP), or might
1035 * expect an error code on the stack (which a software trap never
1036 * provides), or might be a hardware interrupt handler that doesn't like
1037 * being called spuriously.
1039 * Instead, a GPF occurs with the faulting IDT vector in the error code.
1040 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
1041 * clear to indicate that it's a software fault, not hardware.
1043 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
1044 * okay because they can only be triggered by an explicit DPL-checked
1045 * instruction. The DPL specified by the guest OS for these vectors is NOT
1046 * CHECKED!!
1047 */
1048 if ( (regs->error_code & 3) == 2 )
1050 /* This fault must be due to <INT n> instruction. */
1051 ti = &current->arch.guest_context.trap_ctxt[regs->error_code>>3];
1052 if ( PERMIT_SOFTINT(TI_GET_DPL(ti), v, regs) )
1054 tb->flags = TBF_EXCEPTION;
1055 regs->eip += 2;
1056 goto finish_propagation;
1060 /* Emulate some simple privileged and I/O instructions. */
1061 if ( (regs->error_code == 0) &&
1062 emulate_privileged_op(regs) )
1063 return 0;
1065 #if defined(__i386__)
1066 if ( VM_ASSIST(v->domain, VMASST_TYPE_4gb_segments) &&
1067 (regs->error_code == 0) &&
1068 gpf_emulate_4gb(regs) )
1069 return 0;
1070 #endif
1072 /* Pass on GPF as is. */
1073 ti = &current->arch.guest_context.trap_ctxt[TRAP_gp_fault];
1074 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
1075 tb->error_code = regs->error_code;
1076 finish_propagation:
1077 tb->cs = ti->cs;
1078 tb->eip = ti->address;
1079 if ( TI_GET_IF(ti) )
1080 tb->flags |= TBF_INTERRUPT;
1081 return 0;
1083 gp_in_kernel:
1085 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
1087 DPRINTK("GPF (%04x): %p -> %p\n",
1088 regs->error_code, _p(regs->eip), _p(fixup));
1089 regs->eip = fixup;
1090 return 0;
1093 DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
1095 hardware_gp:
1096 show_registers(regs);
1097 panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
1098 smp_processor_id(), regs->error_code);
1099 return 0;
1102 static void nmi_softirq(void)
1104 /* Only used to defer wakeup of dom0,vcpu0 to a safe (non-NMI) context. */
1105 evtchn_notify(dom0->vcpu[0]);
1108 static void nmi_dom0_report(unsigned int reason_idx)
1110 struct domain *d;
1112 if ( (d = dom0) == NULL )
1113 return;
1115 set_bit(reason_idx, &d->shared_info->arch.nmi_reason);
1117 if ( test_and_set_bit(_VCPUF_nmi_pending, &d->vcpu[0]->vcpu_flags) )
1118 raise_softirq(NMI_SOFTIRQ); /* not safe to wake up a vcpu here */
1121 asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
1123 switch ( opt_nmi[0] )
1125 case 'd': /* 'dom0' */
1126 nmi_dom0_report(_XEN_NMIREASON_parity_error);
1127 case 'i': /* 'ignore' */
1128 break;
1129 default: /* 'fatal' */
1130 console_force_unlock();
1131 printk("\n\nNMI - MEMORY ERROR\n");
1132 fatal_trap(TRAP_nmi, regs);
1135 outb((inb(0x61) & 0x0f) | 0x04, 0x61); /* clear-and-disable parity check */
1136 mdelay(1);
1137 outb((inb(0x61) & 0x0b) | 0x00, 0x61); /* enable parity check */
1140 asmlinkage void io_check_error(struct cpu_user_regs *regs)
1142 switch ( opt_nmi[0] )
1144 case 'd': /* 'dom0' */
1145 nmi_dom0_report(_XEN_NMIREASON_io_error);
1146 case 'i': /* 'ignore' */
1147 break;
1148 default: /* 'fatal' */
1149 console_force_unlock();
1150 printk("\n\nNMI - I/O ERROR\n");
1151 fatal_trap(TRAP_nmi, regs);
1154 outb((inb(0x61) & 0x0f) | 0x08, 0x61); /* clear-and-disable IOCK */
1155 mdelay(1);
1156 outb((inb(0x61) & 0x07) | 0x00, 0x61); /* enable IOCK */
1159 static void unknown_nmi_error(unsigned char reason)
1161 switch ( opt_nmi[0] )
1163 case 'd': /* 'dom0' */
1164 nmi_dom0_report(_XEN_NMIREASON_unknown);
1165 case 'i': /* 'ignore' */
1166 break;
1167 default: /* 'fatal' */
1168 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
1169 printk("Dazed and confused, but trying to continue\n");
1170 printk("Do you have a strange power saving mode enabled?\n");
1174 static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu)
1176 return 0;
1179 static nmi_callback_t nmi_callback = dummy_nmi_callback;
1181 asmlinkage void do_nmi(struct cpu_user_regs *regs)
1183 unsigned int cpu = smp_processor_id();
1184 unsigned char reason;
1186 ++nmi_count(cpu);
1188 if ( nmi_callback(regs, cpu) )
1189 return;
1191 if ( nmi_watchdog )
1192 nmi_watchdog_tick(regs);
1194 /* Only the BSP gets external NMIs from the system. */
1195 if ( cpu == 0 )
1197 reason = inb(0x61);
1198 if ( reason & 0x80 )
1199 mem_parity_error(regs);
1200 else if ( reason & 0x40 )
1201 io_check_error(regs);
1202 else if ( !nmi_watchdog )
1203 unknown_nmi_error((unsigned char)(reason&0xff));
1207 void set_nmi_callback(nmi_callback_t callback)
1209 nmi_callback = callback;
1212 void unset_nmi_callback(void)
1214 nmi_callback = dummy_nmi_callback;
1217 asmlinkage int math_state_restore(struct cpu_user_regs *regs)
1219 struct trap_bounce *tb;
1220 trap_info_t *ti;
1222 /* Prevent recursion. */
1223 clts();
1225 setup_fpu(current);
1227 if ( current->arch.guest_context.ctrlreg[0] & X86_CR0_TS )
1229 tb = &current->arch.trap_bounce;
1230 ti = &current->arch.guest_context.trap_ctxt[TRAP_no_device];
1232 tb->flags = TBF_EXCEPTION;
1233 tb->cs = ti->cs;
1234 tb->eip = ti->address;
1235 if ( TI_GET_IF(ti) )
1236 tb->flags |= TBF_INTERRUPT;
1238 current->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
1241 return EXCRET_fault_fixed;
1244 asmlinkage int do_debug(struct cpu_user_regs *regs)
1246 unsigned long condition;
1247 struct vcpu *v = current;
1248 struct trap_bounce *tb = &v->arch.trap_bounce;
1249 trap_info_t *ti;
1251 __asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
1253 /* Mask out spurious debug traps due to lazy DR7 setting */
1254 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
1255 (v->arch.guest_context.debugreg[7] == 0) )
1257 __asm__("mov %0,%%db7" : : "r" (0UL));
1258 goto out;
1261 DEBUGGER_trap_entry(TRAP_debug, regs);
1263 if ( !GUEST_MODE(regs) )
1265 /* Clear TF just for absolute sanity. */
1266 regs->eflags &= ~EF_TF;
1267 /*
1268 * We ignore watchpoints when they trigger within Xen. This may happen
1269 * when a buffer is passed to us which previously had a watchpoint set
1270 * on it. No need to bump EIP; the only faulting trap is an instruction
1271 * breakpoint, which can't happen to us.
1272 */
1273 goto out;
1276 /* Save debug status register where guest OS can peek at it */
1277 v->arch.guest_context.debugreg[6] = condition;
1279 ti = &v->arch.guest_context.trap_ctxt[TRAP_debug];
1280 tb->flags = TBF_EXCEPTION;
1281 tb->cs = ti->cs;
1282 tb->eip = ti->address;
1283 if ( TI_GET_IF(ti) )
1284 tb->flags |= TBF_INTERRUPT;
1286 out:
1287 return EXCRET_not_a_fault;
1290 asmlinkage int do_spurious_interrupt_bug(struct cpu_user_regs *regs)
1292 return EXCRET_not_a_fault;
1295 void set_intr_gate(unsigned int n, void *addr)
1297 #ifdef __i386__
1298 int i;
1299 /* Keep secondary tables in sync with IRQ updates. */
1300 for ( i = 1; i < NR_CPUS; i++ )
1301 if ( idt_tables[i] != NULL )
1302 _set_gate(&idt_tables[i][n], 14, 0, addr);
1303 #endif
1304 _set_gate(&idt_table[n], 14, 0, addr);
1307 void set_system_gate(unsigned int n, void *addr)
1309 _set_gate(idt_table+n,14,3,addr);
1312 void set_task_gate(unsigned int n, unsigned int sel)
1314 idt_table[n].a = sel << 16;
1315 idt_table[n].b = 0x8500;
1318 void set_tss_desc(unsigned int n, void *addr)
1320 _set_tssldt_desc(
1321 gdt_table + __TSS(n) - FIRST_RESERVED_GDT_ENTRY,
1322 (unsigned long)addr,
1323 offsetof(struct tss_struct, __cacheline_filler) - 1,
1324 9);
1327 void __init trap_init(void)
1329 extern void percpu_traps_init(void);
1331 /*
1332 * Note that interrupt gates are always used, rather than trap gates. We
1333 * must have interrupts disabled until DS/ES/FS/GS are saved because the
1334 * first activation must have the "bad" value(s) for these registers and
1335 * we may lose them if another activation is installed before they are
1336 * saved. The page-fault handler also needs interrupts disabled until %cr2
1337 * has been read and saved on the stack.
1338 */
1339 set_intr_gate(TRAP_divide_error,&divide_error);
1340 set_intr_gate(TRAP_debug,&debug);
1341 set_intr_gate(TRAP_nmi,&nmi);
1342 set_system_gate(TRAP_int3,&int3); /* usable from all privileges */
1343 set_system_gate(TRAP_overflow,&overflow); /* usable from all privileges */
1344 set_intr_gate(TRAP_bounds,&bounds);
1345 set_intr_gate(TRAP_invalid_op,&invalid_op);
1346 set_intr_gate(TRAP_no_device,&device_not_available);
1347 set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
1348 set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
1349 set_intr_gate(TRAP_no_segment,&segment_not_present);
1350 set_intr_gate(TRAP_stack_error,&stack_segment);
1351 set_intr_gate(TRAP_gp_fault,&general_protection);
1352 set_intr_gate(TRAP_page_fault,&page_fault);
1353 set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
1354 set_intr_gate(TRAP_copro_error,&coprocessor_error);
1355 set_intr_gate(TRAP_alignment_check,&alignment_check);
1356 set_intr_gate(TRAP_machine_check,&machine_check);
1357 set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
1359 percpu_traps_init();
1361 cpu_init();
1363 open_softirq(NMI_SOFTIRQ, nmi_softirq);
1367 long do_set_trap_table(trap_info_t *traps)
1369 trap_info_t cur;
1370 trap_info_t *dst = current->arch.guest_context.trap_ctxt;
1371 long rc = 0;
1373 LOCK_BIGLOCK(current->domain);
1375 for ( ; ; )
1377 if ( hypercall_preempt_check() )
1379 rc = hypercall1_create_continuation(
1380 __HYPERVISOR_set_trap_table, traps);
1381 break;
1384 if ( copy_from_user(&cur, traps, sizeof(cur)) )
1386 rc = -EFAULT;
1387 break;
1390 if ( cur.address == 0 )
1391 break;
1393 if ( !VALID_CODESEL(cur.cs) )
1395 rc = -EPERM;
1396 break;
1399 memcpy(&dst[cur.vector], &cur, sizeof(cur));
1401 if ( cur.vector == 0x80 )
1402 init_int80_direct_trap(current);
1404 traps++;
1407 UNLOCK_BIGLOCK(current->domain);
1409 return rc;
1413 long set_debugreg(struct vcpu *p, int reg, unsigned long value)
1415 int i;
1417 switch ( reg )
1419 case 0:
1420 if ( !access_ok(value, sizeof(long)) )
1421 return -EPERM;
1422 if ( p == current )
1423 __asm__ ( "mov %0, %%db0" : : "r" (value) );
1424 break;
1425 case 1:
1426 if ( !access_ok(value, sizeof(long)) )
1427 return -EPERM;
1428 if ( p == current )
1429 __asm__ ( "mov %0, %%db1" : : "r" (value) );
1430 break;
1431 case 2:
1432 if ( !access_ok(value, sizeof(long)) )
1433 return -EPERM;
1434 if ( p == current )
1435 __asm__ ( "mov %0, %%db2" : : "r" (value) );
1436 break;
1437 case 3:
1438 if ( !access_ok(value, sizeof(long)) )
1439 return -EPERM;
1440 if ( p == current )
1441 __asm__ ( "mov %0, %%db3" : : "r" (value) );
1442 break;
1443 case 6:
1444 /*
1445 * DR6: Bits 4-11,16-31 reserved (set to 1).
1446 * Bit 12 reserved (set to 0).
1447 */
1448 value &= 0xffffefff; /* reserved bits => 0 */
1449 value |= 0xffff0ff0; /* reserved bits => 1 */
1450 if ( p == current )
1451 __asm__ ( "mov %0, %%db6" : : "r" (value) );
1452 break;
1453 case 7:
1454 /*
1455 * DR7: Bit 10 reserved (set to 1).
1456 * Bits 11-12,14-15 reserved (set to 0).
1457 * Privileged bits:
1458 * GD (bit 13): must be 0.
1459 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
1460 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
1461 */
1462 /* DR7 == 0 => debugging disabled for this domain. */
1463 if ( value != 0 )
1465 value &= 0xffff27ff; /* reserved bits => 0 */
1466 value |= 0x00000400; /* reserved bits => 1 */
1467 if ( (value & (1<<13)) != 0 ) return -EPERM;
1468 for ( i = 0; i < 16; i += 2 )
1469 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
1471 if ( p == current )
1472 __asm__ ( "mov %0, %%db7" : : "r" (value) );
1473 break;
1474 default:
1475 return -EINVAL;
1478 p->arch.guest_context.debugreg[reg] = value;
1479 return 0;
1482 long do_set_debugreg(int reg, unsigned long value)
1484 return set_debugreg(current, reg, value);
1487 unsigned long do_get_debugreg(int reg)
1489 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
1490 return current->arch.guest_context.debugreg[reg];
1493 /*
1494 * Local variables:
1495 * mode: C
1496 * c-set-style: "BSD"
1497 * c-basic-offset: 4
1498 * tab-width: 4
1499 * indent-tabs-mode: nil
1500 * End:
1501 */