debuggers.hg

view xen/arch/x86/traps.c @ 2663:f0ed7653341e

bitkeeper revision 1.1159.1.222 (416c00558HL2Jw-kOYa6NaZn4JiaJQ)

Cleaned up the writable p.t. code and fixed a bug when shadow mode
is enabled.
author kaf24@freefall.cl.cam.ac.uk
date Tue Oct 12 16:03:33 2004 +0000 (2004-10-12)
parents 4ecd18756ef8
children 855925dd3bae
line source
1 /******************************************************************************
2 * arch/i386/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/ptrace.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 <asm/shadow.h>
43 #include <asm/domain_page.h>
44 #include <asm/system.h>
45 #include <asm/io.h>
46 #include <asm/atomic.h>
47 #include <asm/desc.h>
48 #include <asm/debugreg.h>
49 #include <asm/smp.h>
50 #include <asm/flushtlb.h>
51 #include <asm/uaccess.h>
52 #include <asm/i387.h>
53 #include <asm/pdb.h>
55 extern char opt_nmi[];
57 struct guest_trap_bounce guest_trap_bounce[NR_CPUS] = { { 0 } };
59 #if defined(__i386__)
61 #define DOUBLEFAULT_STACK_SIZE 1024
62 static struct tss_struct doublefault_tss;
63 static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
65 asmlinkage int hypercall(void);
66 asmlinkage void lcall7(void);
67 asmlinkage void lcall27(void);
69 /* Master table, and the one used by CPU0. */
70 struct desc_struct idt_table[256] = { {0, 0}, };
71 /* All other CPUs have their own copy. */
72 struct desc_struct *idt_tables[NR_CPUS] = { 0 };
74 asmlinkage void divide_error(void);
75 asmlinkage void debug(void);
76 asmlinkage void nmi(void);
77 asmlinkage void int3(void);
78 asmlinkage void overflow(void);
79 asmlinkage void bounds(void);
80 asmlinkage void invalid_op(void);
81 asmlinkage void device_not_available(void);
82 asmlinkage void coprocessor_segment_overrun(void);
83 asmlinkage void invalid_TSS(void);
84 asmlinkage void segment_not_present(void);
85 asmlinkage void stack_segment(void);
86 asmlinkage void general_protection(void);
87 asmlinkage void page_fault(void);
88 asmlinkage void coprocessor_error(void);
89 asmlinkage void simd_coprocessor_error(void);
90 asmlinkage void alignment_check(void);
91 asmlinkage void spurious_interrupt_bug(void);
92 asmlinkage void machine_check(void);
94 int kstack_depth_to_print = 8*20;
96 static inline int kernel_text_address(unsigned long addr)
97 {
98 if (addr >= (unsigned long) &_stext &&
99 addr <= (unsigned long) &_etext)
100 return 1;
101 return 0;
103 }
105 void show_guest_stack()
106 {
107 int i;
108 execution_context_t *ec = get_execution_context();
109 unsigned long *stack = (unsigned long *)ec->esp;
110 printk("Guest EIP is %lx\n",ec->eip);
112 for ( i = 0; i < kstack_depth_to_print; i++ )
113 {
114 if ( ((long)stack & (STACK_SIZE-1)) == 0 )
115 break;
116 if ( i && ((i % 8) == 0) )
117 printk("\n ");
118 printk("%08lx ", *stack++);
119 }
120 printk("\n");
122 }
124 void show_trace(unsigned long *esp)
125 {
126 unsigned long *stack, addr;
127 int i;
129 printk("Call Trace from ESP=%p: ", esp);
130 stack = esp;
131 i = 0;
132 while (((long) stack & (STACK_SIZE-1)) != 0) {
133 addr = *stack++;
134 if (kernel_text_address(addr)) {
135 if (i && ((i % 6) == 0))
136 printk("\n ");
137 printk("[<%08lx>] ", addr);
138 i++;
139 }
140 }
141 printk("\n");
142 }
144 void show_stack(unsigned long *esp)
145 {
146 unsigned long *stack;
147 int i;
149 printk("Stack trace from ESP=%p:\n", esp);
151 stack = esp;
152 for ( i = 0; i < kstack_depth_to_print; i++ )
153 {
154 if ( ((long)stack & (STACK_SIZE-1)) == 0 )
155 break;
156 if ( i && ((i % 8) == 0) )
157 printk("\n ");
158 if ( kernel_text_address(*stack) )
159 printk("[%08lx] ", *stack++);
160 else
161 printk("%08lx ", *stack++);
162 }
163 printk("\n");
165 show_trace( esp );
166 }
168 void show_registers(struct pt_regs *regs)
169 {
170 unsigned long esp;
171 unsigned short ss;
173 esp = (unsigned long)(&regs->esp);
174 ss = __HYPERVISOR_DS;
175 if ( regs->xcs & 3 )
176 {
177 esp = regs->esp;
178 ss = regs->xss & 0xffff;
179 }
181 printk("CPU: %d\nEIP: %04x:[<%08lx>] \nEFLAGS: %08lx\n",
182 smp_processor_id(), 0xffff & regs->xcs, regs->eip, regs->eflags);
183 printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
184 regs->eax, regs->ebx, regs->ecx, regs->edx);
185 printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
186 regs->esi, regs->edi, regs->ebp, esp);
187 printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
188 regs->xds & 0xffff, regs->xes & 0xffff,
189 regs->xfs & 0xffff, regs->xgs & 0xffff, ss);
191 show_stack(&regs->esp);
192 }
195 spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
197 void die(const char *str, struct pt_regs * regs, long err)
198 {
199 unsigned long flags;
200 spin_lock_irqsave(&die_lock, flags);
201 printk("%s: %04lx,%04lx\n", str, err >> 16, err & 0xffff);
202 show_registers(regs);
203 spin_unlock_irqrestore(&die_lock, flags);
204 panic("Fatal crash within Xen.\n");
205 }
208 static inline void do_trap(int trapnr, char *str,
209 struct pt_regs *regs,
210 long error_code, int use_error_code)
211 {
212 struct domain *p = current;
213 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
214 trap_info_t *ti;
215 unsigned long fixup;
217 if (!(regs->xcs & 3))
218 goto xen_fault;
220 ti = current->thread.traps + trapnr;
221 gtb->flags = use_error_code ? GTBF_TRAP : GTBF_TRAP_NOCODE;
222 gtb->error_code = error_code;
223 gtb->cs = ti->cs;
224 gtb->eip = ti->address;
225 if ( TI_GET_IF(ti) )
226 p->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
227 return;
229 xen_fault:
231 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
232 {
233 DPRINTK("Trap %d: %08lx -> %08lx\n", trapnr, regs->eip, fixup);
234 regs->eip = fixup;
235 regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
236 return;
237 }
239 show_registers(regs);
240 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
241 "[error_code=%08x]\n",
242 smp_processor_id(), trapnr, str, error_code);
243 }
245 #define DO_ERROR_NOCODE(trapnr, str, name) \
246 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
247 { \
248 do_trap(trapnr, str, regs, error_code, 0); \
249 }
251 #define DO_ERROR(trapnr, str, name) \
252 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
253 { \
254 do_trap(trapnr, str, regs, error_code, 1); \
255 }
257 DO_ERROR_NOCODE( 0, "divide error", divide_error)
258 DO_ERROR_NOCODE( 4, "overflow", overflow)
259 DO_ERROR_NOCODE( 5, "bounds", bounds)
260 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
261 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
262 DO_ERROR(10, "invalid TSS", invalid_TSS)
263 DO_ERROR(11, "segment not present", segment_not_present)
264 DO_ERROR(12, "stack segment", stack_segment)
265 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
266 DO_ERROR(17, "alignment check", alignment_check)
267 DO_ERROR_NOCODE(18, "machine check", machine_check)
268 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
270 asmlinkage void do_int3(struct pt_regs *regs, long error_code)
271 {
272 struct domain *p = current;
273 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
274 trap_info_t *ti;
276 #ifdef XEN_DEBUGGER
277 if ( pdb_initialized && pdb_handle_exception(3, regs) == 0 )
278 return;
279 #endif
281 if ( (regs->xcs & 3) != 3 )
282 {
283 if ( unlikely((regs->xcs & 3) == 0) )
284 {
285 show_registers(regs);
286 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n"
287 "[error_code=%08x]\n",
288 smp_processor_id(), error_code);
289 }
290 }
292 ti = current->thread.traps + 3;
293 gtb->flags = GTBF_TRAP_NOCODE;
294 gtb->error_code = error_code;
295 gtb->cs = ti->cs;
296 gtb->eip = ti->address;
297 if ( TI_GET_IF(ti) )
298 p->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
299 }
301 asmlinkage void do_double_fault(void)
302 {
303 struct tss_struct *tss = &doublefault_tss;
304 unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1;
306 /* Disable the NMI watchdog. It's useless now. */
307 watchdog_on = 0;
309 /* Find information saved during fault and dump it to the console. */
310 tss = &init_tss[cpu];
311 printk("CPU: %d\nEIP: %04x:[<%08x>] \nEFLAGS: %08x\n",
312 cpu, tss->cs, tss->eip, tss->eflags);
313 printk("CR3: %08x\n", tss->__cr3);
314 printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
315 tss->eax, tss->ebx, tss->ecx, tss->edx);
316 printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n",
317 tss->esi, tss->edi, tss->ebp, tss->esp);
318 printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
319 tss->ds, tss->es, tss->fs, tss->gs, tss->ss);
320 printk("************************************\n");
321 printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu);
322 printk("System needs manual reset.\n");
323 printk("************************************\n");
325 /* Lock up the console to prevent spurious output from other CPUs. */
326 console_force_lock();
328 /* Wait for manual reset. */
329 for ( ; ; ) ;
330 }
332 asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
333 {
334 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
335 trap_info_t *ti;
336 unsigned long off, addr, fixup;
337 struct domain *d = current;
338 extern int map_ldt_shadow_page(unsigned int);
339 int cpu = d->processor;
341 __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
343 perfc_incrc(page_faults);
345 ASSERT_no_criticalregion();
348 if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
349 {
350 if ( unlikely(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) &&
351 unlikely((addr >> L2_PAGETABLE_SHIFT) ==
352 ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
353 {
354 ptwr_flush(PTWR_PT_ACTIVE);
355 return;
356 }
358 if ( (addr < PAGE_OFFSET) &&
359 ((error_code & 3) == 3) && /* write-protection fault */
360 ptwr_do_page_fault(addr) )
361 return;
362 }
364 if ( unlikely(d->mm.shadow_mode) &&
365 (addr < PAGE_OFFSET) && shadow_fault(addr, error_code) )
366 return; /* Returns TRUE if fault was handled. */
368 if ( unlikely(addr >= LDT_VIRT_START) &&
369 (addr < (LDT_VIRT_START + (d->mm.ldt_ents*LDT_ENTRY_SIZE))) )
370 {
371 /*
372 * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
373 * send the fault up to the guest OS to be handled.
374 */
375 off = addr - LDT_VIRT_START;
376 addr = d->mm.ldt_base + off;
377 if ( likely(map_ldt_shadow_page(off >> PAGE_SHIFT)) )
378 return; /* successfully copied the mapping */
379 }
381 if ( unlikely(!(regs->xcs & 3)) )
382 goto xen_fault;
384 ti = d->thread.traps + 14;
385 gtb->flags = GTBF_TRAP_CR2; /* page fault pushes %cr2 */
386 gtb->cr2 = addr;
387 gtb->error_code = error_code;
388 gtb->cs = ti->cs;
389 gtb->eip = ti->address;
390 if ( TI_GET_IF(ti) )
391 d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
392 return;
394 xen_fault:
396 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
397 {
398 perfc_incrc(copy_user_faults);
399 if ( !d->mm.shadow_mode )
400 DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup);
401 regs->eip = fixup;
402 regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
403 return;
404 }
406 if ( addr >= PAGE_OFFSET )
407 {
408 unsigned long page;
409 page = l2_pgentry_val(idle_pg_table[addr >> L2_PAGETABLE_SHIFT]);
410 printk("*pde = %08lx\n", page);
411 if ( page & _PAGE_PRESENT )
412 {
413 page &= PAGE_MASK;
414 page = ((unsigned long *) __va(page))[(addr&0x3ff000)>>PAGE_SHIFT];
415 printk(" *pte = %08lx\n", page);
416 }
417 #ifdef MEMORY_GUARD
418 if ( !(error_code & 1) )
419 printk(" -- POSSIBLY AN ACCESS TO FREED MEMORY? --\n");
420 #endif
421 }
423 #ifdef XEN_DEBUGGER
424 if ( pdb_page_fault_possible )
425 {
426 pdb_page_fault = 1;
427 /* make eax & edx valid to complete the instruction */
428 regs->eax = (long)&pdb_page_fault_scratch;
429 regs->edx = (long)&pdb_page_fault_scratch;
430 return;
431 }
432 #endif
434 show_registers(regs);
435 panic("CPU%d FATAL PAGE FAULT\n"
436 "[error_code=%08x]\n"
437 "Faulting linear address might be %08lx\n",
438 smp_processor_id(), error_code, addr);
439 }
441 asmlinkage void do_general_protection(struct pt_regs *regs, long error_code)
442 {
443 struct domain *d = current;
444 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
445 trap_info_t *ti;
446 unsigned long fixup;
448 ASSERT_no_criticalregion();
450 /* Badness if error in ring 0, or result of an interrupt. */
451 if ( !(regs->xcs & 3) || (error_code & 1) )
452 goto gp_in_kernel;
454 /*
455 * Cunning trick to allow arbitrary "INT n" handling.
456 *
457 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
458 * instruction from trapping to the appropriate vector, when that might not
459 * be expected by Xen or the guest OS. For example, that entry might be for
460 * a fault handler (unlike traps, faults don't increment EIP), or might
461 * expect an error code on the stack (which a software trap never
462 * provides), or might be a hardware interrupt handler that doesn't like
463 * being called spuriously.
464 *
465 * Instead, a GPF occurs with the faulting IDT vector in the error code.
466 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
467 * clear to indicate that it's a software fault, not hardware.
468 *
469 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
470 * okay because they can only be triggered by an explicit DPL-checked
471 * instruction. The DPL specified by the guest OS for these vectors is NOT
472 * CHECKED!!
473 */
474 if ( (error_code & 3) == 2 )
475 {
476 /* This fault must be due to <INT n> instruction. */
477 ti = current->thread.traps + (error_code>>3);
478 if ( TI_GET_DPL(ti) >= (regs->xcs & 3) )
479 {
480 #ifdef XEN_DEBUGGER
481 if ( pdb_initialized && (pdb_ctx.system_call != 0) )
482 {
483 unsigned long cr3;
484 __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : );
485 if ( cr3 == pdb_ctx.ptbr )
486 pdb_linux_syscall_enter_bkpt(regs, error_code, ti);
487 }
488 #endif
490 gtb->flags = GTBF_TRAP_NOCODE;
491 regs->eip += 2;
492 goto finish_propagation;
493 }
494 }
496 #if defined(__i386__)
497 if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments) &&
498 (error_code == 0) &&
499 gpf_emulate_4gb(regs) )
500 return;
501 #endif
503 /* Pass on GPF as is. */
504 ti = current->thread.traps + 13;
505 gtb->flags = GTBF_TRAP;
506 gtb->error_code = error_code;
507 finish_propagation:
508 gtb->cs = ti->cs;
509 gtb->eip = ti->address;
510 if ( TI_GET_IF(ti) )
511 d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
512 return;
514 gp_in_kernel:
516 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
517 {
518 DPRINTK("GPF (%04lx): %08lx -> %08lx\n", error_code, regs->eip, fixup);
519 regs->eip = fixup;
520 regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
521 return;
522 }
524 die("general protection fault", regs, error_code);
525 }
527 asmlinkage void mem_parity_error(struct pt_regs *regs)
528 {
529 console_force_unlock();
530 disable_criticalregion_checking();
532 printk("\n\n");
534 show_registers(regs);
536 printk("************************************\n");
537 printk("CPU%d MEMORY ERROR -- system shutdown\n", smp_processor_id());
538 printk("System needs manual reset.\n");
539 printk("************************************\n");
541 /* Lock up the console to prevent spurious output from other CPUs. */
542 console_force_lock();
544 /* Wait for manual reset. */
545 for ( ; ; ) ;
546 }
548 asmlinkage void io_check_error(struct pt_regs *regs)
549 {
550 console_force_unlock();
551 disable_criticalregion_checking();
553 printk("\n\n");
555 show_registers(regs);
557 printk("************************************\n");
558 printk("CPU%d I/O ERROR -- system shutdown\n", smp_processor_id());
559 printk("System needs manual reset.\n");
560 printk("************************************\n");
562 /* Lock up the console to prevent spurious output from other CPUs. */
563 console_force_lock();
565 /* Wait for manual reset. */
566 for ( ; ; ) ;
567 }
569 static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
570 {
571 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
572 printk("Dazed and confused, but trying to continue\n");
573 printk("Do you have a strange power saving mode enabled?\n");
574 }
576 asmlinkage void do_nmi(struct pt_regs * regs, unsigned long reason)
577 {
578 ++nmi_count(smp_processor_id());
580 #if CONFIG_X86_LOCAL_APIC
581 if ( nmi_watchdog )
582 nmi_watchdog_tick(regs);
583 else
584 #endif
585 unknown_nmi_error((unsigned char)(reason&0xff), regs);
586 }
588 unsigned long nmi_softirq_reason;
589 static void nmi_softirq(void)
590 {
591 struct domain *d = find_domain_by_id(0);
593 if ( d == NULL )
594 return;
596 if ( test_and_clear_bit(0, &nmi_softirq_reason) )
597 send_guest_virq(d, VIRQ_PARITY_ERR);
599 if ( test_and_clear_bit(1, &nmi_softirq_reason) )
600 send_guest_virq(d, VIRQ_IO_ERR);
602 put_domain(d);
603 }
605 asmlinkage void math_state_restore(struct pt_regs *regs, long error_code)
606 {
607 /* Prevent recursion. */
608 clts();
610 if ( !test_bit(DF_USEDFPU, &current->flags) )
611 {
612 if ( test_bit(DF_DONEFPUINIT, &current->flags) )
613 restore_fpu(current);
614 else
615 init_fpu();
616 set_bit(DF_USEDFPU, &current->flags); /* so we fnsave on switch_to() */
617 }
619 if ( test_and_clear_bit(DF_GUEST_STTS, &current->flags) )
620 {
621 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
622 gtb->flags = GTBF_TRAP_NOCODE;
623 gtb->cs = current->thread.traps[7].cs;
624 gtb->eip = current->thread.traps[7].address;
625 }
626 }
628 #ifdef XEN_DEBUGGER
629 asmlinkage void do_pdb_debug(struct pt_regs *regs, long error_code)
630 {
631 unsigned int condition;
632 struct domain *tsk = current;
633 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
635 __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
636 if ( (condition & (1 << 14)) != (1 << 14) )
637 printk("\nwarning: debug trap w/o BS bit [0x%x]\n\n", condition);
638 __asm__("movl %0,%%db6" : : "r" (0));
640 if ( pdb_handle_exception(1, regs) != 0 )
641 {
642 tsk->thread.debugreg[6] = condition;
644 gtb->flags = GTBF_TRAP_NOCODE;
645 gtb->cs = tsk->thread.traps[1].cs;
646 gtb->eip = tsk->thread.traps[1].address;
647 }
648 }
649 #endif
651 asmlinkage void do_debug(struct pt_regs *regs, long error_code)
652 {
653 unsigned int condition;
654 struct domain *tsk = current;
655 struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id();
657 #ifdef XEN_DEBUGGER
658 if ( pdb_initialized )
659 return do_pdb_debug(regs, error_code);
660 #endif
662 __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
664 /* Mask out spurious debug traps due to lazy DR7 setting */
665 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
666 (tsk->thread.debugreg[7] == 0) )
667 {
668 __asm__("movl %0,%%db7" : : "r" (0));
669 return;
670 }
672 if ( (regs->xcs & 3) == 0 )
673 {
674 /* Clear TF just for absolute sanity. */
675 regs->eflags &= ~EF_TF;
676 /*
677 * We ignore watchpoints when they trigger within Xen. This may happen
678 * when a buffer is passed to us which previously had a watchpoint set
679 * on it. No need to bump EIP; the only faulting trap is an instruction
680 * breakpoint, which can't happen to us.
681 */
682 return;
683 }
685 /* Save debug status register where guest OS can peek at it */
686 tsk->thread.debugreg[6] = condition;
688 gtb->flags = GTBF_TRAP_NOCODE;
689 gtb->cs = tsk->thread.traps[1].cs;
690 gtb->eip = tsk->thread.traps[1].address;
691 }
694 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
695 long error_code)
696 { /* nothing */ }
699 #define _set_gate(gate_addr,type,dpl,addr) \
700 do { \
701 int __d0, __d1; \
702 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
703 "movw %4,%%dx\n\t" \
704 "movl %%eax,%0\n\t" \
705 "movl %%edx,%1" \
706 :"=m" (*((long *) (gate_addr))), \
707 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
708 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
709 "3" ((char *) (addr)),"2" (__HYPERVISOR_CS << 16)); \
710 } while (0)
712 void set_intr_gate(unsigned int n, void *addr)
713 {
714 _set_gate(idt_table+n,14,0,addr);
715 }
717 static void __init set_system_gate(unsigned int n, void *addr)
718 {
719 _set_gate(idt_table+n,14,3,addr);
720 }
722 static void set_task_gate(unsigned int n, unsigned int sel)
723 {
724 idt_table[n].a = sel << 16;
725 idt_table[n].b = 0x8500;
726 }
728 #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
729 *((gate_addr)+1) = ((base) & 0xff000000) | \
730 (((base) & 0x00ff0000)>>16) | \
731 ((limit) & 0xf0000) | \
732 ((dpl)<<13) | \
733 (0x00408000) | \
734 ((type)<<8); \
735 *(gate_addr) = (((base) & 0x0000ffff)<<16) | \
736 ((limit) & 0x0ffff); }
738 #define _set_tssldt_desc(n,addr,limit,type) \
739 __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
740 "movw %%ax,2(%2)\n\t" \
741 "rorl $16,%%eax\n\t" \
742 "movb %%al,4(%2)\n\t" \
743 "movb %4,5(%2)\n\t" \
744 "movb $0,6(%2)\n\t" \
745 "movb %%ah,7(%2)\n\t" \
746 "rorl $16,%%eax" \
747 : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
749 void set_tss_desc(unsigned int n, void *addr)
750 {
751 _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 8299, 0x89);
752 }
754 void __init trap_init(void)
755 {
756 /*
757 * Make a separate task for double faults. This will get us debug output if
758 * we blow the kernel stack.
759 */
760 struct tss_struct *tss = &doublefault_tss;
761 memset(tss, 0, sizeof(*tss));
762 tss->ds = __HYPERVISOR_DS;
763 tss->es = __HYPERVISOR_DS;
764 tss->ss = __HYPERVISOR_DS;
765 tss->esp = (unsigned long)
766 &doublefault_stack[DOUBLEFAULT_STACK_SIZE];
767 tss->__cr3 = __pa(idle_pg_table);
768 tss->cs = __HYPERVISOR_CS;
769 tss->eip = (unsigned long)do_double_fault;
770 tss->eflags = 2;
771 tss->bitmap = INVALID_IO_BITMAP_OFFSET;
772 _set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY,
773 (int)tss, 235, 0x89);
775 /*
776 * Note that interrupt gates are always used, rather than trap gates. We
777 * must have interrupts disabled until DS/ES/FS/GS are saved because the
778 * first activation must have the "bad" value(s) for these registers and
779 * we may lose them if another activation is installed before they are
780 * saved. The page-fault handler also needs interrupts disabled until %cr2
781 * has been read and saved on the stack.
782 */
783 set_intr_gate(0,&divide_error);
784 set_intr_gate(1,&debug);
785 set_intr_gate(2,&nmi);
786 set_system_gate(3,&int3); /* usable from all privilege levels */
787 set_system_gate(4,&overflow); /* usable from all privilege levels */
788 set_intr_gate(5,&bounds);
789 set_intr_gate(6,&invalid_op);
790 set_intr_gate(7,&device_not_available);
791 set_task_gate(8,__DOUBLEFAULT_TSS_ENTRY<<3);
792 set_intr_gate(9,&coprocessor_segment_overrun);
793 set_intr_gate(10,&invalid_TSS);
794 set_intr_gate(11,&segment_not_present);
795 set_intr_gate(12,&stack_segment);
796 set_intr_gate(13,&general_protection);
797 set_intr_gate(14,&page_fault);
798 set_intr_gate(15,&spurious_interrupt_bug);
799 set_intr_gate(16,&coprocessor_error);
800 set_intr_gate(17,&alignment_check);
801 set_intr_gate(18,&machine_check);
802 set_intr_gate(19,&simd_coprocessor_error);
804 /* Only ring 1 can access Xen services. */
805 _set_gate(idt_table+HYPERCALL_VECTOR,14,1,&hypercall);
807 /* CPU0 uses the master IDT. */
808 idt_tables[0] = idt_table;
810 /*
811 * Should be a barrier for any external CPU state.
812 */
813 {
814 extern void cpu_init(void);
815 cpu_init();
816 }
818 open_softirq(NMI_SOFTIRQ, nmi_softirq);
819 }
822 long do_set_trap_table(trap_info_t *traps)
823 {
824 trap_info_t cur;
825 trap_info_t *dst = current->thread.traps;
827 for ( ; ; )
828 {
829 if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
831 if ( cur.address == 0 ) break;
833 if ( !VALID_CODESEL(cur.cs) ) return -EPERM;
835 memcpy(dst+cur.vector, &cur, sizeof(cur));
836 traps++;
837 }
839 return 0;
840 }
843 long do_set_callbacks(unsigned long event_selector,
844 unsigned long event_address,
845 unsigned long failsafe_selector,
846 unsigned long failsafe_address)
847 {
848 struct domain *p = current;
850 if ( !VALID_CODESEL(event_selector) || !VALID_CODESEL(failsafe_selector) )
851 return -EPERM;
853 p->event_selector = event_selector;
854 p->event_address = event_address;
855 p->failsafe_selector = failsafe_selector;
856 p->failsafe_address = failsafe_address;
858 return 0;
859 }
862 long set_fast_trap(struct domain *p, int idx)
863 {
864 trap_info_t *ti;
866 /* Index 0 is special: it disables fast traps. */
867 if ( idx == 0 )
868 {
869 if ( p == current )
870 CLEAR_FAST_TRAP(&p->thread);
871 SET_DEFAULT_FAST_TRAP(&p->thread);
872 return 0;
873 }
875 /*
876 * We only fast-trap vectors 0x20-0x2f, and vector 0x80.
877 * The former range is used by Windows and MS-DOS.
878 * Vector 0x80 is used by Linux and the BSD variants.
879 */
880 if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) )
881 return -1;
883 ti = p->thread.traps + idx;
885 /*
886 * We can't virtualise interrupt gates, as there's no way to get
887 * the CPU to automatically clear the events_mask variable.
888 */
889 if ( TI_GET_IF(ti) )
890 return -1;
892 if ( p == current )
893 CLEAR_FAST_TRAP(&p->thread);
895 p->thread.fast_trap_idx = idx;
896 p->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
897 p->thread.fast_trap_desc.b =
898 (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13;
900 if ( p == current )
901 SET_FAST_TRAP(&p->thread);
903 return 0;
904 }
907 long do_set_fast_trap(int idx)
908 {
909 return set_fast_trap(current, idx);
910 }
913 long do_fpu_taskswitch(void)
914 {
915 set_bit(DF_GUEST_STTS, &current->flags);
916 stts();
917 return 0;
918 }
921 long set_debugreg(struct domain *p, int reg, unsigned long value)
922 {
923 int i;
925 switch ( reg )
926 {
927 case 0:
928 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
929 if ( p == current )
930 __asm__ ( "movl %0, %%db0" : : "r" (value) );
931 break;
932 case 1:
933 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
934 if ( p == current )
935 __asm__ ( "movl %0, %%db1" : : "r" (value) );
936 break;
937 case 2:
938 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
939 if ( p == current )
940 __asm__ ( "movl %0, %%db2" : : "r" (value) );
941 break;
942 case 3:
943 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
944 if ( p == current )
945 __asm__ ( "movl %0, %%db3" : : "r" (value) );
946 break;
947 case 6:
948 /*
949 * DR6: Bits 4-11,16-31 reserved (set to 1).
950 * Bit 12 reserved (set to 0).
951 */
952 value &= 0xffffefff; /* reserved bits => 0 */
953 value |= 0xffff0ff0; /* reserved bits => 1 */
954 if ( p == current )
955 __asm__ ( "movl %0, %%db6" : : "r" (value) );
956 break;
957 case 7:
958 /*
959 * DR7: Bit 10 reserved (set to 1).
960 * Bits 11-12,14-15 reserved (set to 0).
961 * Privileged bits:
962 * GD (bit 13): must be 0.
963 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
964 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
965 */
966 /* DR7 == 0 => debugging disabled for this domain. */
967 if ( value != 0 )
968 {
969 value &= 0xffff27ff; /* reserved bits => 0 */
970 value |= 0x00000400; /* reserved bits => 1 */
971 if ( (value & (1<<13)) != 0 ) return -EPERM;
972 for ( i = 0; i < 16; i += 2 )
973 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
974 }
975 if ( p == current )
976 __asm__ ( "movl %0, %%db7" : : "r" (value) );
977 break;
978 default:
979 return -EINVAL;
980 }
982 p->thread.debugreg[reg] = value;
983 return 0;
984 }
986 long do_set_debugreg(int reg, unsigned long value)
987 {
988 return set_debugreg(current, reg, value);
989 }
991 unsigned long do_get_debugreg(int reg)
992 {
993 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
994 return current->thread.debugreg[reg];
995 }
997 #endif /* __i386__ */