ia64/xen-unstable

view xen/arch/x86/traps.c @ 8584:8531996d207f

Fix compile warning about uninitialised vars.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Jan 12 21:48:51 2006 +0100 (2006-01-12)
parents 411e66a837a1
children 3f702887d4a6
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 = (unsigned long *)regs->esp, addr;
135 printk("Guest stack trace from "__OP"sp=%p:\n ", stack);
137 for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
138 {
139 if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
140 break;
141 if ( get_user(addr, stack) )
142 {
143 if ( i != 0 )
144 printk("\n ");
145 printk("Fault while accessing guest memory.");
146 i = 1;
147 break;
148 }
149 if ( (i != 0) && ((i % stack_words_per_line) == 0) )
150 printk("\n ");
151 printk("%p ", _p(addr));
152 stack++;
153 }
154 if ( i == 0 )
155 printk("Stack empty.");
156 printk("\n");
157 }
159 #ifdef NDEBUG
161 static void show_trace(struct cpu_user_regs *regs)
162 {
163 unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
165 printk("Xen call trace:\n ");
167 printk("[<%p>]", _p(regs->eip));
168 print_symbol(" %s\n ", regs->eip);
170 while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 )
171 {
172 addr = *stack++;
173 if ( is_kernel_text(addr) )
174 {
175 printk("[<%p>]", _p(addr));
176 print_symbol(" %s\n ", addr);
177 }
178 }
180 printk("\n");
181 }
183 #else
185 static void show_trace(struct cpu_user_regs *regs)
186 {
187 unsigned long *frame, next, addr, low, high;
189 printk("Xen call trace:\n ");
191 printk("[<%p>]", _p(regs->eip));
192 print_symbol(" %s\n ", regs->eip);
194 /* Bounds for range of valid frame pointer. */
195 low = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);
196 high = (low & ~(STACK_SIZE - 1)) +
197 (STACK_SIZE - sizeof(struct cpu_info) - 2*sizeof(unsigned long));
199 /* The initial frame pointer. */
200 next = regs->ebp;
202 for ( ; ; )
203 {
204 /* Valid frame pointer? */
205 if ( (next < low) || (next >= high) )
206 {
207 /*
208 * Exception stack frames have a different layout, denoted by an
209 * inverted frame pointer.
210 */
211 next = ~next;
212 if ( (next < low) || (next >= high) )
213 break;
214 frame = (unsigned long *)next;
215 next = frame[0];
216 addr = frame[(offsetof(struct cpu_user_regs, eip) -
217 offsetof(struct cpu_user_regs, ebp))
218 / BYTES_PER_LONG];
219 }
220 else
221 {
222 /* Ordinary stack frame. */
223 frame = (unsigned long *)next;
224 next = frame[0];
225 addr = frame[1];
226 }
228 printk("[<%p>]", _p(addr));
229 print_symbol(" %s\n ", addr);
231 low = (unsigned long)&frame[2];
232 }
234 printk("\n");
235 }
237 #endif
239 void show_stack(struct cpu_user_regs *regs)
240 {
241 unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
242 int i;
244 if ( GUEST_CONTEXT(current, regs) )
245 return show_guest_stack(regs);
247 printk("Xen stack trace from "__OP"sp=%p:\n ", stack);
249 for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
250 {
251 if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
252 break;
253 if ( (i != 0) && ((i % stack_words_per_line) == 0) )
254 printk("\n ");
255 addr = *stack++;
256 printk("%p ", _p(addr));
257 }
258 if ( i == 0 )
259 printk("Stack empty.");
260 printk("\n");
262 show_trace(regs);
263 }
265 /*
266 * This is called for faults at very unexpected times (e.g., when interrupts
267 * are disabled). In such situations we can't do much that is safe. We try to
268 * print out some tracing and then we just spin.
269 */
270 asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs)
271 {
272 int cpu = smp_processor_id();
273 unsigned long cr2;
274 static char *trapstr[] = {
275 "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
276 "invalid operation", "device not available", "double fault",
277 "coprocessor segment", "invalid tss", "segment not found",
278 "stack error", "general protection fault", "page fault",
279 "spurious interrupt", "coprocessor error", "alignment check",
280 "machine check", "simd error"
281 };
283 watchdog_disable();
284 console_start_sync();
286 show_registers(regs);
288 if ( trapnr == TRAP_page_fault )
289 {
290 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (cr2) : );
291 printk("Faulting linear address: %p\n", _p(cr2));
292 show_page_walk(cr2);
293 }
295 printk("************************************\n");
296 printk("CPU%d FATAL TRAP %d (%s), ERROR_CODE %04x%s.\n",
297 cpu, trapnr, trapstr[trapnr], regs->error_code,
298 (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");
299 printk("System shutting down -- need manual reset.\n");
300 printk("************************************\n");
302 (void)debugger_trap_fatal(trapnr, regs);
304 /* Lock up the console to prevent spurious output from other CPUs. */
305 console_force_lock();
307 /* Wait for manual reset. */
308 for ( ; ; )
309 __asm__ __volatile__ ( "hlt" );
310 }
312 static inline int do_trap(int trapnr, char *str,
313 struct cpu_user_regs *regs,
314 int use_error_code)
315 {
316 struct vcpu *v = current;
317 struct trap_bounce *tb = &v->arch.trap_bounce;
318 trap_info_t *ti;
319 unsigned long fixup;
321 DEBUGGER_trap_entry(trapnr, regs);
323 if ( !GUEST_MODE(regs) )
324 goto xen_fault;
326 ti = &current->arch.guest_context.trap_ctxt[trapnr];
327 tb->flags = TBF_EXCEPTION;
328 tb->cs = ti->cs;
329 tb->eip = ti->address;
330 if ( use_error_code )
331 {
332 tb->flags |= TBF_EXCEPTION_ERRCODE;
333 tb->error_code = regs->error_code;
334 }
335 if ( TI_GET_IF(ti) )
336 tb->flags |= TBF_INTERRUPT;
337 return 0;
339 xen_fault:
341 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
342 {
343 DPRINTK("Trap %d: %p -> %p\n", trapnr, _p(regs->eip), _p(fixup));
344 regs->eip = fixup;
345 return 0;
346 }
348 DEBUGGER_trap_fatal(trapnr, regs);
350 show_registers(regs);
351 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
352 "[error_code=%04x]\n",
353 smp_processor_id(), trapnr, str, regs->error_code);
354 return 0;
355 }
357 #define DO_ERROR_NOCODE(trapnr, str, name) \
358 asmlinkage int do_##name(struct cpu_user_regs *regs) \
359 { \
360 return do_trap(trapnr, str, regs, 0); \
361 }
363 #define DO_ERROR(trapnr, str, name) \
364 asmlinkage int do_##name(struct cpu_user_regs *regs) \
365 { \
366 return do_trap(trapnr, str, regs, 1); \
367 }
369 DO_ERROR_NOCODE( 0, "divide error", divide_error)
370 DO_ERROR_NOCODE( 4, "overflow", overflow)
371 DO_ERROR_NOCODE( 5, "bounds", bounds)
372 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
373 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
374 DO_ERROR(10, "invalid TSS", invalid_TSS)
375 DO_ERROR(11, "segment not present", segment_not_present)
376 DO_ERROR(12, "stack segment", stack_segment)
377 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
378 DO_ERROR(17, "alignment check", alignment_check)
379 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
381 asmlinkage int do_int3(struct cpu_user_regs *regs)
382 {
383 struct vcpu *v = current;
384 struct trap_bounce *tb = &v->arch.trap_bounce;
385 trap_info_t *ti;
387 DEBUGGER_trap_entry(TRAP_int3, regs);
389 if ( !GUEST_MODE(regs) )
390 {
391 DEBUGGER_trap_fatal(TRAP_int3, regs);
392 show_registers(regs);
393 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
394 }
396 ti = &current->arch.guest_context.trap_ctxt[TRAP_int3];
397 tb->flags = TBF_EXCEPTION;
398 tb->cs = ti->cs;
399 tb->eip = ti->address;
400 if ( TI_GET_IF(ti) )
401 tb->flags |= TBF_INTERRUPT;
403 return 0;
404 }
406 asmlinkage int do_machine_check(struct cpu_user_regs *regs)
407 {
408 fatal_trap(TRAP_machine_check, regs);
409 return 0;
410 }
412 void propagate_page_fault(unsigned long addr, u16 error_code)
413 {
414 trap_info_t *ti;
415 struct vcpu *v = current;
416 struct trap_bounce *tb = &v->arch.trap_bounce;
418 v->arch.guest_context.ctrlreg[2] = addr;
419 v->vcpu_info->arch.cr2 = addr;
421 ti = &v->arch.guest_context.trap_ctxt[TRAP_page_fault];
422 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
423 tb->error_code = error_code;
424 tb->cs = ti->cs;
425 tb->eip = ti->address;
426 if ( TI_GET_IF(ti) )
427 tb->flags |= TBF_INTERRUPT;
428 }
430 static int handle_gdt_ldt_mapping_fault(
431 unsigned long offset, struct cpu_user_regs *regs)
432 {
433 extern int map_ldt_shadow_page(unsigned int);
435 struct vcpu *v = current;
436 struct domain *d = v->domain;
437 int ret;
439 /* Which vcpu's area did we fault in, and is it in the ldt sub-area? */
440 unsigned int is_ldt_area = (offset >> (GDT_LDT_VCPU_VA_SHIFT-1)) & 1;
441 unsigned int vcpu_area = (offset >> GDT_LDT_VCPU_VA_SHIFT);
443 /* Should never fault in another vcpu's area. */
444 BUG_ON(vcpu_area != current->vcpu_id);
446 /* Byte offset within the gdt/ldt sub-area. */
447 offset &= (1UL << (GDT_LDT_VCPU_VA_SHIFT-1)) - 1UL;
449 if ( likely(is_ldt_area) )
450 {
451 /* LDT fault: Copy a mapping from the guest's LDT, if it is valid. */
452 LOCK_BIGLOCK(d);
453 ret = map_ldt_shadow_page(offset >> PAGE_SHIFT);
454 UNLOCK_BIGLOCK(d);
456 if ( unlikely(ret == 0) )
457 {
458 /* In hypervisor mode? Leave it to the #PF handler to fix up. */
459 if ( !GUEST_MODE(regs) )
460 return 0;
461 /* In guest mode? Propagate #PF to guest, with adjusted %cr2. */
462 propagate_page_fault(
463 v->arch.guest_context.ldt_base + offset, regs->error_code);
464 }
465 }
466 else
467 {
468 /* GDT fault: handle the fault as #GP(selector). */
469 regs->error_code = (u16)offset & ~7;
470 (void)do_general_protection(regs);
471 }
473 return EXCRET_fault_fixed;
474 }
476 #ifdef HYPERVISOR_VIRT_END
477 #define IN_HYPERVISOR_RANGE(va) \
478 (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END))
479 #else
480 #define IN_HYPERVISOR_RANGE(va) \
481 (((va) >= HYPERVISOR_VIRT_START))
482 #endif
484 static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs)
485 {
486 struct vcpu *v = current;
487 struct domain *d = v->domain;
489 if ( unlikely(IN_HYPERVISOR_RANGE(addr)) )
490 {
491 if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) )
492 return shadow_fault(addr, regs);
493 if ( (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) )
494 return handle_gdt_ldt_mapping_fault(
495 addr - GDT_LDT_VIRT_START, regs);
496 }
497 else if ( unlikely(shadow_mode_enabled(d)) )
498 {
499 return shadow_fault(addr, regs);
500 }
501 else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
502 {
503 LOCK_BIGLOCK(d);
504 if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) &&
505 unlikely(l2_linear_offset(addr) ==
506 d->arch.ptwr[PTWR_PT_ACTIVE].l2_idx) )
507 {
508 ptwr_flush(d, PTWR_PT_ACTIVE);
509 UNLOCK_BIGLOCK(d);
510 return EXCRET_fault_fixed;
511 }
513 if ( KERNEL_MODE(v, regs) &&
514 /* Protection violation on write? No reserved-bit violation? */
515 ((regs->error_code & 0xb) == 0x3) &&
516 ptwr_do_page_fault(d, addr, regs) )
517 {
518 UNLOCK_BIGLOCK(d);
519 return EXCRET_fault_fixed;
520 }
521 UNLOCK_BIGLOCK(d);
522 }
524 return 0;
525 }
527 /*
528 * #PF error code:
529 * Bit 0: Protection violation (=1) ; Page not present (=0)
530 * Bit 1: Write access
531 * Bit 2: Supervisor mode
532 * Bit 3: Reserved bit violation
533 * Bit 4: Instruction fetch
534 */
535 asmlinkage int do_page_fault(struct cpu_user_regs *regs)
536 {
537 unsigned long addr, fixup;
538 int rc;
540 __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : );
542 DEBUGGER_trap_entry(TRAP_page_fault, regs);
544 perfc_incrc(page_faults);
546 if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) )
547 return rc;
549 if ( unlikely(!GUEST_MODE(regs)) )
550 {
551 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
552 {
553 perfc_incrc(copy_user_faults);
554 regs->eip = fixup;
555 return 0;
556 }
558 DEBUGGER_trap_fatal(TRAP_page_fault, regs);
560 show_registers(regs);
561 show_page_walk(addr);
562 panic("CPU%d FATAL PAGE FAULT\n"
563 "[error_code=%04x]\n"
564 "Faulting linear address: %p\n",
565 smp_processor_id(), regs->error_code, addr);
566 }
568 propagate_page_fault(addr, regs->error_code);
569 return 0;
570 }
572 long do_fpu_taskswitch(int set)
573 {
574 struct vcpu *v = current;
576 if ( set )
577 {
578 v->arch.guest_context.ctrlreg[0] |= X86_CR0_TS;
579 stts();
580 }
581 else
582 {
583 v->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
584 if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
585 clts();
586 }
588 return 0;
589 }
591 /* Has the guest requested sufficient permission for this I/O access? */
592 static inline int guest_io_okay(
593 unsigned int port, unsigned int bytes,
594 struct vcpu *v, struct cpu_user_regs *regs)
595 {
596 u16 x;
597 #if defined(__x86_64__)
598 /* If in user mode, switch to kernel mode just to read I/O bitmap. */
599 int user_mode = !(v->arch.flags & TF_kernel_mode);
600 #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v)
601 #elif defined(__i386__)
602 #define TOGGLE_MODE() ((void)0)
603 #endif
605 if ( v->arch.iopl >= (KERNEL_MODE(v, regs) ? 1 : 3) )
606 return 1;
608 if ( v->arch.iobmp_limit > (port + bytes) )
609 {
610 TOGGLE_MODE();
611 __get_user(x, (u16 *)(v->arch.iobmp+(port>>3)));
612 TOGGLE_MODE();
613 if ( (x & (((1<<bytes)-1) << (port&7))) == 0 )
614 return 1;
615 }
617 return 0;
618 }
620 /* Has the administrator granted sufficient permission for this I/O access? */
621 static inline int admin_io_okay(
622 unsigned int port, unsigned int bytes,
623 struct vcpu *v, struct cpu_user_regs *regs)
624 {
625 return ioports_access_permitted(v->domain, port, port + bytes - 1);
626 }
628 /* Check admin limits. Silently fail the access if it is disallowed. */
629 #define inb_user(_p, _d, _r) (admin_io_okay(_p, 1, _d, _r) ? inb(_p) : ~0)
630 #define inw_user(_p, _d, _r) (admin_io_okay(_p, 2, _d, _r) ? inw(_p) : ~0)
631 #define inl_user(_p, _d, _r) (admin_io_okay(_p, 4, _d, _r) ? inl(_p) : ~0)
632 #define outb_user(_v, _p, _d, _r) \
633 (admin_io_okay(_p, 1, _d, _r) ? outb(_v, _p) : ((void)0))
634 #define outw_user(_v, _p, _d, _r) \
635 (admin_io_okay(_p, 2, _d, _r) ? outw(_v, _p) : ((void)0))
636 #define outl_user(_v, _p, _d, _r) \
637 (admin_io_okay(_p, 4, _d, _r) ? outl(_v, _p) : ((void)0))
639 /* Propagate a fault back to the guest kernel. */
640 #define USER_READ_FAULT 4 /* user mode, read fault */
641 #define USER_WRITE_FAULT 6 /* user mode, write fault */
642 #define PAGE_FAULT(_faultaddr, _errcode) \
643 ({ propagate_page_fault(_faultaddr, _errcode); \
644 return EXCRET_fault_fixed; \
645 })
647 /* Isntruction fetch with error handling. */
648 #define insn_fetch(_type, _size, _ptr) \
649 ({ unsigned long _x; \
650 if ( get_user(_x, (_type *)eip) ) \
651 PAGE_FAULT(eip, USER_READ_FAULT); \
652 eip += _size; (_type)_x; })
654 static int emulate_privileged_op(struct cpu_user_regs *regs)
655 {
656 struct vcpu *v = current;
657 unsigned long *reg, eip = regs->eip, res;
658 u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0;
659 unsigned int port, i, op_bytes = 4, data;
661 /* Legacy prefixes. */
662 for ( i = 0; i < 8; i++ )
663 {
664 switch ( opcode = insn_fetch(u8, 1, eip) )
665 {
666 case 0x66: /* operand-size override */
667 op_bytes ^= 6; /* switch between 2/4 bytes */
668 break;
669 case 0x67: /* address-size override */
670 case 0x2e: /* CS override */
671 case 0x3e: /* DS override */
672 case 0x26: /* ES override */
673 case 0x64: /* FS override */
674 case 0x65: /* GS override */
675 case 0x36: /* SS override */
676 case 0xf0: /* LOCK */
677 case 0xf2: /* REPNE/REPNZ */
678 break;
679 case 0xf3: /* REP/REPE/REPZ */
680 rep_prefix = 1;
681 break;
682 default:
683 goto done_prefixes;
684 }
685 }
686 done_prefixes:
688 #ifdef __x86_64__
689 /* REX prefix. */
690 if ( (opcode & 0xf0) == 0x40 )
691 {
692 modrm_reg = (opcode & 4) << 1; /* REX.R */
693 modrm_rm = (opcode & 1) << 3; /* REX.B */
695 /* REX.W and REX.X do not need to be decoded. */
696 opcode = insn_fetch(u8, 1, eip);
697 }
698 #endif
700 /* Input/Output String instructions. */
701 if ( (opcode >= 0x6c) && (opcode <= 0x6f) )
702 {
703 if ( rep_prefix && (regs->ecx == 0) )
704 goto done;
706 continue_io_string:
707 switch ( opcode )
708 {
709 case 0x6c: /* INSB */
710 op_bytes = 1;
711 case 0x6d: /* INSW/INSL */
712 if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) )
713 goto fail;
714 switch ( op_bytes )
715 {
716 case 1:
717 data = (u8)inb_user((u16)regs->edx, v, regs);
718 if ( put_user((u8)data, (u8 *)regs->edi) )
719 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
720 break;
721 case 2:
722 data = (u16)inw_user((u16)regs->edx, v, regs);
723 if ( put_user((u16)data, (u16 *)regs->edi) )
724 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
725 break;
726 case 4:
727 data = (u32)inl_user((u16)regs->edx, v, regs);
728 if ( put_user((u32)data, (u32 *)regs->edi) )
729 PAGE_FAULT(regs->edi, USER_WRITE_FAULT);
730 break;
731 }
732 regs->edi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
733 break;
735 case 0x6e: /* OUTSB */
736 op_bytes = 1;
737 case 0x6f: /* OUTSW/OUTSL */
738 if ( !guest_io_okay((u16)regs->edx, op_bytes, v, regs) )
739 goto fail;
740 switch ( op_bytes )
741 {
742 case 1:
743 if ( get_user(data, (u8 *)regs->esi) )
744 PAGE_FAULT(regs->esi, USER_READ_FAULT);
745 outb_user((u8)data, (u16)regs->edx, v, regs);
746 break;
747 case 2:
748 if ( get_user(data, (u16 *)regs->esi) )
749 PAGE_FAULT(regs->esi, USER_READ_FAULT);
750 outw_user((u16)data, (u16)regs->edx, v, regs);
751 break;
752 case 4:
753 if ( get_user(data, (u32 *)regs->esi) )
754 PAGE_FAULT(regs->esi, USER_READ_FAULT);
755 outl_user((u32)data, (u16)regs->edx, v, regs);
756 break;
757 }
758 regs->esi += (regs->eflags & EF_DF) ? -op_bytes : op_bytes;
759 break;
760 }
762 if ( rep_prefix && (--regs->ecx != 0) )
763 {
764 if ( !hypercall_preempt_check() )
765 goto continue_io_string;
766 eip = regs->eip;
767 }
769 goto done;
770 }
772 /* I/O Port and Interrupt Flag instructions. */
773 switch ( opcode )
774 {
775 case 0xe4: /* IN imm8,%al */
776 op_bytes = 1;
777 case 0xe5: /* IN imm8,%eax */
778 port = insn_fetch(u8, 1, eip);
779 exec_in:
780 if ( !guest_io_okay(port, op_bytes, v, regs) )
781 goto fail;
782 switch ( op_bytes )
783 {
784 case 1:
785 regs->eax &= ~0xffUL;
786 regs->eax |= (u8)inb_user(port, v, regs);
787 break;
788 case 2:
789 regs->eax &= ~0xffffUL;
790 regs->eax |= (u16)inw_user(port, v, regs);
791 break;
792 case 4:
793 regs->eax = (u32)inl_user(port, v, regs);
794 break;
795 }
796 goto done;
798 case 0xec: /* IN %dx,%al */
799 op_bytes = 1;
800 case 0xed: /* IN %dx,%eax */
801 port = (u16)regs->edx;
802 goto exec_in;
804 case 0xe6: /* OUT %al,imm8 */
805 op_bytes = 1;
806 case 0xe7: /* OUT %eax,imm8 */
807 port = insn_fetch(u8, 1, eip);
808 exec_out:
809 if ( !guest_io_okay(port, op_bytes, v, regs) )
810 goto fail;
811 switch ( op_bytes )
812 {
813 case 1:
814 outb_user((u8)regs->eax, port, v, regs);
815 break;
816 case 2:
817 outw_user((u16)regs->eax, port, v, regs);
818 break;
819 case 4:
820 outl_user((u32)regs->eax, port, v, regs);
821 break;
822 }
823 goto done;
825 case 0xee: /* OUT %al,%dx */
826 op_bytes = 1;
827 case 0xef: /* OUT %eax,%dx */
828 port = (u16)regs->edx;
829 goto exec_out;
831 case 0xfa: /* CLI */
832 case 0xfb: /* STI */
833 if ( v->arch.iopl < (KERNEL_MODE(v, regs) ? 1 : 3) )
834 goto fail;
835 /*
836 * This is just too dangerous to allow, in my opinion. Consider if the
837 * caller then tries to reenable interrupts using POPF: we can't trap
838 * that and we'll end up with hard-to-debug lockups. Fast & loose will
839 * do for us. :-)
840 */
841 /*v->vcpu_info->evtchn_upcall_mask = (opcode == 0xfa);*/
842 goto done;
844 case 0x0f: /* Two-byte opcode */
845 break;
847 default:
848 goto fail;
849 }
851 /* Remaining instructions only emulated from guest kernel. */
852 if ( !KERNEL_MODE(v, regs) )
853 goto fail;
855 /* Privileged (ring 0) instructions. */
856 opcode = insn_fetch(u8, 1, eip);
857 switch ( opcode )
858 {
859 case 0x06: /* CLTS */
860 (void)do_fpu_taskswitch(0);
861 break;
863 case 0x09: /* WBINVD */
864 /* Ignore the instruction if unprivileged. */
865 if ( !cache_flush_permitted(v->domain) )
866 DPRINTK("Non-physdev domain attempted WBINVD.\n");
867 else
868 wbinvd();
869 break;
871 case 0x20: /* MOV CR?,<reg> */
872 opcode = insn_fetch(u8, 1, eip);
873 modrm_reg |= (opcode >> 3) & 7;
874 modrm_rm |= (opcode >> 0) & 7;
875 reg = decode_register(modrm_rm, regs, 0);
876 switch ( modrm_reg )
877 {
878 case 0: /* Read CR0 */
879 *reg = (read_cr0() & ~X86_CR0_TS) |
880 v->arch.guest_context.ctrlreg[0];
881 break;
883 case 2: /* Read CR2 */
884 *reg = v->arch.guest_context.ctrlreg[2];
885 break;
887 case 3: /* Read CR3 */
888 *reg = pagetable_get_paddr(v->arch.guest_table);
889 break;
891 case 4: /* Read CR4 */
892 /*
893 * Guests can read CR4 to see what features Xen has enabled. We
894 * therefore lie about PGE & PSE as they are unavailable to guests.
895 */
896 *reg = read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE);
897 break;
899 default:
900 goto fail;
901 }
902 break;
904 case 0x21: /* MOV DR?,<reg> */
905 opcode = insn_fetch(u8, 1, eip);
906 modrm_reg |= (opcode >> 3) & 7;
907 modrm_rm |= (opcode >> 0) & 7;
908 reg = decode_register(modrm_rm, regs, 0);
909 if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
910 goto fail;
911 *reg = res;
912 break;
914 case 0x22: /* MOV <reg>,CR? */
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 switch ( modrm_reg )
920 {
921 case 0: /* Write CR0 */
922 if ( (*reg ^ read_cr0()) & ~X86_CR0_TS )
923 {
924 DPRINTK("Attempt to change unmodifiable CR0 flags.\n");
925 goto fail;
926 }
927 (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS));
928 break;
930 case 2: /* Write CR2 */
931 v->arch.guest_context.ctrlreg[2] = *reg;
932 v->vcpu_info->arch.cr2 = *reg;
933 break;
935 case 3: /* Write CR3 */
936 LOCK_BIGLOCK(v->domain);
937 (void)new_guest_cr3(*reg);
938 UNLOCK_BIGLOCK(v->domain);
939 break;
941 case 4:
942 if ( *reg != (read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE)) )
943 {
944 DPRINTK("Attempt to change CR4 flags.\n");
945 goto fail;
946 }
947 break;
949 default:
950 goto fail;
951 }
952 break;
954 case 0x23: /* MOV <reg>,DR? */
955 opcode = insn_fetch(u8, 1, eip);
956 modrm_reg |= (opcode >> 3) & 7;
957 modrm_rm |= (opcode >> 0) & 7;
958 reg = decode_register(modrm_rm, regs, 0);
959 if ( do_set_debugreg(modrm_reg, *reg) != 0 )
960 goto fail;
961 break;
963 case 0x30: /* WRMSR */
964 /* Ignore the instruction if unprivileged. */
965 if ( !IS_PRIV(v->domain) )
966 {
967 u32 l, h;
968 if ( (rdmsr_user(regs->ecx, l, h) != 0) ||
969 (regs->ecx != MSR_EFER) ||
970 (regs->eax != l) || (regs->edx != h) )
971 DPRINTK("Non-priv domain attempted WRMSR %p from "
972 "%08x:%08x to %08lx:%08lx.\n",
973 _p(regs->ecx), h, l, (long)regs->edx, (long)regs->eax);
974 }
975 else if ( wrmsr_user(regs->ecx, regs->eax, regs->edx) )
976 goto fail;
977 break;
979 case 0x32: /* RDMSR */
980 if ( !IS_PRIV(v->domain) )
981 {
982 if ( regs->ecx != MSR_EFER )
983 DPRINTK("Non-priv domain attempted RDMSR %p.\n",
984 _p(regs->ecx));
985 }
986 /* Everyone can read the MSR space. */
987 if ( rdmsr_user(regs->ecx, regs->eax, regs->edx) )
988 goto fail;
989 break;
991 default:
992 goto fail;
993 }
995 done:
996 regs->eip = eip;
997 return EXCRET_fault_fixed;
999 fail:
1000 return 0;
1003 asmlinkage int do_general_protection(struct cpu_user_regs *regs)
1005 struct vcpu *v = current;
1006 struct trap_bounce *tb = &v->arch.trap_bounce;
1007 trap_info_t *ti;
1008 unsigned long fixup;
1010 DEBUGGER_trap_entry(TRAP_gp_fault, regs);
1012 if ( regs->error_code & 1 )
1013 goto hardware_gp;
1015 if ( !GUEST_MODE(regs) )
1016 goto gp_in_kernel;
1018 /*
1019 * Cunning trick to allow arbitrary "INT n" handling.
1021 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
1022 * instruction from trapping to the appropriate vector, when that might not
1023 * be expected by Xen or the guest OS. For example, that entry might be for
1024 * a fault handler (unlike traps, faults don't increment EIP), or might
1025 * expect an error code on the stack (which a software trap never
1026 * provides), or might be a hardware interrupt handler that doesn't like
1027 * being called spuriously.
1029 * Instead, a GPF occurs with the faulting IDT vector in the error code.
1030 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
1031 * clear to indicate that it's a software fault, not hardware.
1033 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
1034 * okay because they can only be triggered by an explicit DPL-checked
1035 * instruction. The DPL specified by the guest OS for these vectors is NOT
1036 * CHECKED!!
1037 */
1038 if ( (regs->error_code & 3) == 2 )
1040 /* This fault must be due to <INT n> instruction. */
1041 ti = &current->arch.guest_context.trap_ctxt[regs->error_code>>3];
1042 if ( PERMIT_SOFTINT(TI_GET_DPL(ti), v, regs) )
1044 tb->flags = TBF_EXCEPTION;
1045 regs->eip += 2;
1046 goto finish_propagation;
1050 /* Emulate some simple privileged and I/O instructions. */
1051 if ( (regs->error_code == 0) &&
1052 emulate_privileged_op(regs) )
1053 return 0;
1055 #if defined(__i386__)
1056 if ( VM_ASSIST(v->domain, VMASST_TYPE_4gb_segments) &&
1057 (regs->error_code == 0) &&
1058 gpf_emulate_4gb(regs) )
1059 return 0;
1060 #endif
1062 /* Pass on GPF as is. */
1063 ti = &current->arch.guest_context.trap_ctxt[TRAP_gp_fault];
1064 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
1065 tb->error_code = regs->error_code;
1066 finish_propagation:
1067 tb->cs = ti->cs;
1068 tb->eip = ti->address;
1069 if ( TI_GET_IF(ti) )
1070 tb->flags |= TBF_INTERRUPT;
1071 return 0;
1073 gp_in_kernel:
1075 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
1077 DPRINTK("GPF (%04x): %p -> %p\n",
1078 regs->error_code, _p(regs->eip), _p(fixup));
1079 regs->eip = fixup;
1080 return 0;
1083 DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
1085 hardware_gp:
1086 show_registers(regs);
1087 panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
1088 smp_processor_id(), regs->error_code);
1089 return 0;
1092 static void nmi_softirq(void)
1094 /* Only used to defer wakeup of dom0,vcpu0 to a safe (non-NMI) context. */
1095 evtchn_notify(dom0->vcpu[0]);
1098 static void nmi_dom0_report(unsigned int reason_idx)
1100 struct domain *d;
1102 if ( (d = dom0) == NULL )
1103 return;
1105 set_bit(reason_idx, &d->shared_info->arch.nmi_reason);
1107 if ( test_and_set_bit(_VCPUF_nmi_pending, &d->vcpu[0]->vcpu_flags) )
1108 raise_softirq(NMI_SOFTIRQ); /* not safe to wake up a vcpu here */
1111 asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
1113 switch ( opt_nmi[0] )
1115 case 'd': /* 'dom0' */
1116 nmi_dom0_report(_XEN_NMIREASON_parity_error);
1117 case 'i': /* 'ignore' */
1118 break;
1119 default: /* 'fatal' */
1120 console_force_unlock();
1121 printk("\n\nNMI - MEMORY ERROR\n");
1122 fatal_trap(TRAP_nmi, regs);
1125 outb((inb(0x61) & 0x0f) | 0x04, 0x61); /* clear-and-disable parity check */
1126 mdelay(1);
1127 outb((inb(0x61) & 0x0b) | 0x00, 0x61); /* enable parity check */
1130 asmlinkage void io_check_error(struct cpu_user_regs *regs)
1132 switch ( opt_nmi[0] )
1134 case 'd': /* 'dom0' */
1135 nmi_dom0_report(_XEN_NMIREASON_io_error);
1136 case 'i': /* 'ignore' */
1137 break;
1138 default: /* 'fatal' */
1139 console_force_unlock();
1140 printk("\n\nNMI - I/O ERROR\n");
1141 fatal_trap(TRAP_nmi, regs);
1144 outb((inb(0x61) & 0x0f) | 0x08, 0x61); /* clear-and-disable IOCK */
1145 mdelay(1);
1146 outb((inb(0x61) & 0x07) | 0x00, 0x61); /* enable IOCK */
1149 static void unknown_nmi_error(unsigned char reason)
1151 switch ( opt_nmi[0] )
1153 case 'd': /* 'dom0' */
1154 nmi_dom0_report(_XEN_NMIREASON_unknown);
1155 case 'i': /* 'ignore' */
1156 break;
1157 default: /* 'fatal' */
1158 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
1159 printk("Dazed and confused, but trying to continue\n");
1160 printk("Do you have a strange power saving mode enabled?\n");
1164 static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu)
1166 return 0;
1169 static nmi_callback_t nmi_callback = dummy_nmi_callback;
1171 asmlinkage void do_nmi(struct cpu_user_regs *regs)
1173 unsigned int cpu = smp_processor_id();
1174 unsigned char reason;
1176 ++nmi_count(cpu);
1178 if ( nmi_callback(regs, cpu) )
1179 return;
1181 if ( nmi_watchdog )
1182 nmi_watchdog_tick(regs);
1184 /* Only the BSP gets external NMIs from the system. */
1185 if ( cpu == 0 )
1187 reason = inb(0x61);
1188 if ( reason & 0x80 )
1189 mem_parity_error(regs);
1190 else if ( reason & 0x40 )
1191 io_check_error(regs);
1192 else if ( !nmi_watchdog )
1193 unknown_nmi_error((unsigned char)(reason&0xff));
1197 void set_nmi_callback(nmi_callback_t callback)
1199 nmi_callback = callback;
1202 void unset_nmi_callback(void)
1204 nmi_callback = dummy_nmi_callback;
1207 asmlinkage int math_state_restore(struct cpu_user_regs *regs)
1209 struct trap_bounce *tb;
1210 trap_info_t *ti;
1212 /* Prevent recursion. */
1213 clts();
1215 setup_fpu(current);
1217 if ( current->arch.guest_context.ctrlreg[0] & X86_CR0_TS )
1219 tb = &current->arch.trap_bounce;
1220 ti = &current->arch.guest_context.trap_ctxt[TRAP_no_device];
1222 tb->flags = TBF_EXCEPTION;
1223 tb->cs = ti->cs;
1224 tb->eip = ti->address;
1225 if ( TI_GET_IF(ti) )
1226 tb->flags |= TBF_INTERRUPT;
1228 current->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
1231 return EXCRET_fault_fixed;
1234 asmlinkage int do_debug(struct cpu_user_regs *regs)
1236 unsigned long condition;
1237 struct vcpu *v = current;
1238 struct trap_bounce *tb = &v->arch.trap_bounce;
1239 trap_info_t *ti;
1241 __asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
1243 /* Mask out spurious debug traps due to lazy DR7 setting */
1244 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
1245 (v->arch.guest_context.debugreg[7] == 0) )
1247 __asm__("mov %0,%%db7" : : "r" (0UL));
1248 goto out;
1251 DEBUGGER_trap_entry(TRAP_debug, regs);
1253 if ( !GUEST_MODE(regs) )
1255 /* Clear TF just for absolute sanity. */
1256 regs->eflags &= ~EF_TF;
1257 /*
1258 * We ignore watchpoints when they trigger within Xen. This may happen
1259 * when a buffer is passed to us which previously had a watchpoint set
1260 * on it. No need to bump EIP; the only faulting trap is an instruction
1261 * breakpoint, which can't happen to us.
1262 */
1263 goto out;
1266 /* Save debug status register where guest OS can peek at it */
1267 v->arch.guest_context.debugreg[6] = condition;
1269 ti = &v->arch.guest_context.trap_ctxt[TRAP_debug];
1270 tb->flags = TBF_EXCEPTION;
1271 tb->cs = ti->cs;
1272 tb->eip = ti->address;
1273 if ( TI_GET_IF(ti) )
1274 tb->flags |= TBF_INTERRUPT;
1276 out:
1277 return EXCRET_not_a_fault;
1280 asmlinkage int do_spurious_interrupt_bug(struct cpu_user_regs *regs)
1282 return EXCRET_not_a_fault;
1285 void set_intr_gate(unsigned int n, void *addr)
1287 #ifdef __i386__
1288 int i;
1289 /* Keep secondary tables in sync with IRQ updates. */
1290 for ( i = 1; i < NR_CPUS; i++ )
1291 if ( idt_tables[i] != NULL )
1292 _set_gate(&idt_tables[i][n], 14, 0, addr);
1293 #endif
1294 _set_gate(&idt_table[n], 14, 0, addr);
1297 void set_system_gate(unsigned int n, void *addr)
1299 _set_gate(idt_table+n,14,3,addr);
1302 void set_task_gate(unsigned int n, unsigned int sel)
1304 idt_table[n].a = sel << 16;
1305 idt_table[n].b = 0x8500;
1308 void set_tss_desc(unsigned int n, void *addr)
1310 _set_tssldt_desc(
1311 gdt_table + __TSS(n) - FIRST_RESERVED_GDT_ENTRY,
1312 (unsigned long)addr,
1313 offsetof(struct tss_struct, __cacheline_filler) - 1,
1314 9);
1317 void __init trap_init(void)
1319 extern void percpu_traps_init(void);
1321 /*
1322 * Note that interrupt gates are always used, rather than trap gates. We
1323 * must have interrupts disabled until DS/ES/FS/GS are saved because the
1324 * first activation must have the "bad" value(s) for these registers and
1325 * we may lose them if another activation is installed before they are
1326 * saved. The page-fault handler also needs interrupts disabled until %cr2
1327 * has been read and saved on the stack.
1328 */
1329 set_intr_gate(TRAP_divide_error,&divide_error);
1330 set_intr_gate(TRAP_debug,&debug);
1331 set_intr_gate(TRAP_nmi,&nmi);
1332 set_system_gate(TRAP_int3,&int3); /* usable from all privileges */
1333 set_system_gate(TRAP_overflow,&overflow); /* usable from all privileges */
1334 set_intr_gate(TRAP_bounds,&bounds);
1335 set_intr_gate(TRAP_invalid_op,&invalid_op);
1336 set_intr_gate(TRAP_no_device,&device_not_available);
1337 set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
1338 set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
1339 set_intr_gate(TRAP_no_segment,&segment_not_present);
1340 set_intr_gate(TRAP_stack_error,&stack_segment);
1341 set_intr_gate(TRAP_gp_fault,&general_protection);
1342 set_intr_gate(TRAP_page_fault,&page_fault);
1343 set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
1344 set_intr_gate(TRAP_copro_error,&coprocessor_error);
1345 set_intr_gate(TRAP_alignment_check,&alignment_check);
1346 set_intr_gate(TRAP_machine_check,&machine_check);
1347 set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
1349 percpu_traps_init();
1351 cpu_init();
1353 open_softirq(NMI_SOFTIRQ, nmi_softirq);
1357 long do_set_trap_table(trap_info_t *traps)
1359 trap_info_t cur;
1360 trap_info_t *dst = current->arch.guest_context.trap_ctxt;
1361 long rc = 0;
1363 LOCK_BIGLOCK(current->domain);
1365 for ( ; ; )
1367 if ( hypercall_preempt_check() )
1369 rc = hypercall1_create_continuation(
1370 __HYPERVISOR_set_trap_table, traps);
1371 break;
1374 if ( copy_from_user(&cur, traps, sizeof(cur)) )
1376 rc = -EFAULT;
1377 break;
1380 if ( cur.address == 0 )
1381 break;
1383 if ( !VALID_CODESEL(cur.cs) )
1385 rc = -EPERM;
1386 break;
1389 memcpy(&dst[cur.vector], &cur, sizeof(cur));
1391 if ( cur.vector == 0x80 )
1392 init_int80_direct_trap(current);
1394 traps++;
1397 UNLOCK_BIGLOCK(current->domain);
1399 return rc;
1403 long set_debugreg(struct vcpu *p, int reg, unsigned long value)
1405 int i;
1407 switch ( reg )
1409 case 0:
1410 if ( !access_ok(value, sizeof(long)) )
1411 return -EPERM;
1412 if ( p == current )
1413 __asm__ ( "mov %0, %%db0" : : "r" (value) );
1414 break;
1415 case 1:
1416 if ( !access_ok(value, sizeof(long)) )
1417 return -EPERM;
1418 if ( p == current )
1419 __asm__ ( "mov %0, %%db1" : : "r" (value) );
1420 break;
1421 case 2:
1422 if ( !access_ok(value, sizeof(long)) )
1423 return -EPERM;
1424 if ( p == current )
1425 __asm__ ( "mov %0, %%db2" : : "r" (value) );
1426 break;
1427 case 3:
1428 if ( !access_ok(value, sizeof(long)) )
1429 return -EPERM;
1430 if ( p == current )
1431 __asm__ ( "mov %0, %%db3" : : "r" (value) );
1432 break;
1433 case 6:
1434 /*
1435 * DR6: Bits 4-11,16-31 reserved (set to 1).
1436 * Bit 12 reserved (set to 0).
1437 */
1438 value &= 0xffffefff; /* reserved bits => 0 */
1439 value |= 0xffff0ff0; /* reserved bits => 1 */
1440 if ( p == current )
1441 __asm__ ( "mov %0, %%db6" : : "r" (value) );
1442 break;
1443 case 7:
1444 /*
1445 * DR7: Bit 10 reserved (set to 1).
1446 * Bits 11-12,14-15 reserved (set to 0).
1447 * Privileged bits:
1448 * GD (bit 13): must be 0.
1449 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
1450 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
1451 */
1452 /* DR7 == 0 => debugging disabled for this domain. */
1453 if ( value != 0 )
1455 value &= 0xffff27ff; /* reserved bits => 0 */
1456 value |= 0x00000400; /* reserved bits => 1 */
1457 if ( (value & (1<<13)) != 0 ) return -EPERM;
1458 for ( i = 0; i < 16; i += 2 )
1459 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
1461 if ( p == current )
1462 __asm__ ( "mov %0, %%db7" : : "r" (value) );
1463 break;
1464 default:
1465 return -EINVAL;
1468 p->arch.guest_context.debugreg[reg] = value;
1469 return 0;
1472 long do_set_debugreg(int reg, unsigned long value)
1474 return set_debugreg(current, reg, value);
1477 unsigned long do_get_debugreg(int reg)
1479 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
1480 return current->arch.guest_context.debugreg[reg];
1483 /*
1484 * Local variables:
1485 * mode: C
1486 * c-set-style: "BSD"
1487 * c-basic-offset: 4
1488 * tab-width: 4
1489 * indent-tabs-mode: nil
1490 * End:
1491 */