xen-vtx-unstable
annotate xen/arch/x86/x86_64/traps.c @ 6756:69bf4490062f
domain_crash_synchronous() on x86_64 causes Xen to crash because
it tries to dereference an invalid stack address. The patch below
fixes this. The patch also updates show_registers() to print the
same information as its x86_32 equivalent.
Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
it tries to dereference an invalid stack address. The patch below
fixes this. The patch also updates show_registers() to print the
same information as its x86_32 equivalent.
Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Tue Sep 13 10:12:40 2005 +0000 (2005-09-13) |
parents | 291e816acbf4 |
children | bd951d23d713 |
rev | line source |
---|---|
kaf24@3602 | 1 |
kaf24@3602 | 2 #include <xen/config.h> |
kaf24@3602 | 3 #include <xen/init.h> |
kaf24@3602 | 4 #include <xen/sched.h> |
kaf24@3602 | 5 #include <xen/lib.h> |
kaf24@3602 | 6 #include <xen/errno.h> |
kaf24@3602 | 7 #include <xen/mm.h> |
kaf24@3602 | 8 #include <xen/irq.h> |
kaf24@5824 | 9 #include <xen/symbols.h> |
kaf24@3630 | 10 #include <xen/console.h> |
kaf24@3650 | 11 #include <xen/sched.h> |
cl349@5291 | 12 #include <asm/current.h> |
kaf24@5159 | 13 #include <asm/flushtlb.h> |
kaf24@3650 | 14 #include <asm/msr.h> |
kaf24@6756 | 15 #include <asm/vmx.h> |
kaf24@3602 | 16 |
kaf24@4683 | 17 void show_registers(struct cpu_user_regs *regs) |
kaf24@3602 | 18 { |
kaf24@6756 | 19 unsigned long rip, rsp, rflags, cs, cr0, cr3; |
kaf24@6756 | 20 const char *context; |
kaf24@6756 | 21 |
kaf24@6756 | 22 if ( VMX_DOMAIN(current) && (regs->eflags == 0) ) |
kaf24@6756 | 23 { |
kaf24@6756 | 24 __vmread(GUEST_RIP, &rip); |
kaf24@6756 | 25 __vmread(GUEST_RSP, &rsp); |
kaf24@6756 | 26 __vmread(GUEST_RFLAGS, &rflags); |
kaf24@6756 | 27 __vmread(GUEST_CS_SELECTOR, &cs); |
kaf24@6756 | 28 __vmread(CR0_READ_SHADOW, &cr0); |
kaf24@6756 | 29 __vmread(GUEST_CR3, &cr3); |
kaf24@6756 | 30 context = "vmx guest"; |
kaf24@6756 | 31 } |
kaf24@6756 | 32 else |
kaf24@6756 | 33 { |
kaf24@6756 | 34 rip = regs->rip; |
kaf24@6756 | 35 rflags = regs->rflags; |
kaf24@6756 | 36 cr0 = read_cr0(); |
kaf24@6756 | 37 cr3 = read_cr3(); |
kaf24@6756 | 38 rsp = regs->rsp; |
kaf24@6756 | 39 cs = regs->cs & 0xffff; |
kaf24@6756 | 40 context = GUEST_MODE(regs) ? "guest" : "hypervisor"; |
kaf24@6756 | 41 } |
kaf24@6756 | 42 |
kaf24@6756 | 43 printk("CPU: %d\nRIP: %04lx:[<%016lx>]", |
kaf24@6756 | 44 smp_processor_id(), cs, rip); |
kaf24@6232 | 45 if ( !GUEST_MODE(regs) ) |
kaf24@6756 | 46 print_symbol(" %s", rip); |
kaf24@6756 | 47 printk("\nRFLAGS: %016lx CONTEXT: %s\n", rflags, context); |
kaf24@6477 | 48 printk("rax: %016lx rbx: %016lx rcx: %016lx\n", |
kaf24@6477 | 49 regs->rax, regs->rbx, regs->rcx); |
kaf24@6477 | 50 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n", |
kaf24@6477 | 51 regs->rdx, regs->rsi, regs->rdi); |
kaf24@6477 | 52 printk("rbp: %016lx rsp: %016lx r8: %016lx\n", |
kaf24@6756 | 53 regs->rbp, rsp, regs->r8); |
kaf24@6477 | 54 printk("r9: %016lx r10: %016lx r11: %016lx\n", |
kaf24@6477 | 55 regs->r9, regs->r10, regs->r11); |
kaf24@6477 | 56 printk("r12: %016lx r13: %016lx r14: %016lx\n", |
kaf24@6477 | 57 regs->r12, regs->r13, regs->r14); |
kaf24@6756 | 58 printk("r15: %016lx cr0: %016lx cr3: %016lx\n", |
kaf24@6756 | 59 regs->r15, cr0, cr3); |
kaf24@3602 | 60 |
kaf24@6573 | 61 show_stack(regs); |
kaf24@5073 | 62 } |
kaf24@3602 | 63 |
kaf24@3630 | 64 void show_page_walk(unsigned long addr) |
kaf24@3630 | 65 { |
kaf24@3630 | 66 unsigned long page = read_cr3(); |
kaf24@3630 | 67 |
kaf24@4654 | 68 printk("Pagetable walk from %016lx:\n", addr); |
kaf24@3630 | 69 |
kaf24@3630 | 70 page &= PAGE_MASK; |
kaf24@3630 | 71 page = ((unsigned long *) __va(page))[l4_table_offset(addr)]; |
kaf24@4654 | 72 printk(" L4 = %016lx\n", page); |
kaf24@3630 | 73 if ( !(page & _PAGE_PRESENT) ) |
kaf24@3630 | 74 return; |
kaf24@3630 | 75 |
kaf24@3630 | 76 page &= PAGE_MASK; |
kaf24@3630 | 77 page = ((unsigned long *) __va(page))[l3_table_offset(addr)]; |
kaf24@4654 | 78 printk(" L3 = %016lx\n", page); |
kaf24@3630 | 79 if ( !(page & _PAGE_PRESENT) ) |
kaf24@3630 | 80 return; |
kaf24@3630 | 81 |
kaf24@3630 | 82 page &= PAGE_MASK; |
kaf24@3630 | 83 page = ((unsigned long *) __va(page))[l2_table_offset(addr)]; |
kaf24@4654 | 84 printk(" L2 = %016lx %s\n", page, (page & _PAGE_PSE) ? "(2MB)" : ""); |
kaf24@3630 | 85 if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) ) |
kaf24@3630 | 86 return; |
kaf24@3630 | 87 |
kaf24@3630 | 88 page &= PAGE_MASK; |
kaf24@3630 | 89 page = ((unsigned long *) __va(page))[l1_table_offset(addr)]; |
kaf24@4654 | 90 printk(" L1 = %016lx\n", page); |
kaf24@3630 | 91 } |
kaf24@3630 | 92 |
kaf24@3630 | 93 asmlinkage void double_fault(void); |
kaf24@4683 | 94 asmlinkage void do_double_fault(struct cpu_user_regs *regs) |
kaf24@3630 | 95 { |
kaf24@4926 | 96 watchdog_disable(); |
kaf24@3630 | 97 |
kaf24@3686 | 98 console_force_unlock(); |
kaf24@3686 | 99 |
kaf24@3630 | 100 /* Find information saved during fault and dump it to the console. */ |
kaf24@3630 | 101 printk("************************************\n"); |
kaf24@3695 | 102 show_registers(regs); |
kaf24@3630 | 103 printk("************************************\n"); |
kaf24@3695 | 104 printk("CPU%d DOUBLE FAULT -- system shutdown\n", smp_processor_id()); |
kaf24@3630 | 105 printk("System needs manual reset.\n"); |
kaf24@3630 | 106 printk("************************************\n"); |
kaf24@3630 | 107 |
kaf24@3630 | 108 /* Lock up the console to prevent spurious output from other CPUs. */ |
kaf24@3630 | 109 console_force_lock(); |
kaf24@3630 | 110 |
kaf24@3630 | 111 /* Wait for manual reset. */ |
kaf24@3630 | 112 for ( ; ; ) |
kaf24@3630 | 113 __asm__ __volatile__ ( "hlt" ); |
kaf24@3630 | 114 } |
kaf24@3630 | 115 |
kaf24@3761 | 116 asmlinkage void syscall_enter(void); |
kaf24@3650 | 117 void __init percpu_traps_init(void) |
kaf24@3650 | 118 { |
kaf24@3761 | 119 char *stack_bottom, *stack; |
kaf24@3761 | 120 int cpu = smp_processor_id(); |
kaf24@3761 | 121 |
kaf24@3774 | 122 if ( cpu == 0 ) |
kaf24@3774 | 123 { |
kaf24@3774 | 124 /* Specify dedicated interrupt stacks for NMIs and double faults. */ |
kaf24@3774 | 125 set_intr_gate(TRAP_double_fault, &double_fault); |
kaf24@3774 | 126 idt_table[TRAP_double_fault].a |= 1UL << 32; /* IST1 */ |
kaf24@3774 | 127 idt_table[TRAP_nmi].a |= 2UL << 32; /* IST2 */ |
kaf24@3774 | 128 } |
kaf24@3774 | 129 |
kaf24@3761 | 130 stack_bottom = (char *)get_stack_bottom(); |
kaf24@3761 | 131 stack = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1)); |
kaf24@3695 | 132 |
kaf24@3695 | 133 /* Double-fault handler has its own per-CPU 1kB stack. */ |
kaf24@3695 | 134 init_tss[cpu].ist[0] = (unsigned long)&stack[1024]; |
kaf24@3695 | 135 |
kaf24@3695 | 136 /* NMI handler has its own per-CPU 1kB stack. */ |
kaf24@3695 | 137 init_tss[cpu].ist[1] = (unsigned long)&stack[2048]; |
kaf24@3695 | 138 |
kaf24@3695 | 139 /* |
kaf24@3695 | 140 * Trampoline for SYSCALL entry from long mode. |
kaf24@3695 | 141 */ |
kaf24@3695 | 142 |
kaf24@3695 | 143 /* Skip the NMI and DF stacks. */ |
kaf24@3695 | 144 stack = &stack[2048]; |
kaf24@3695 | 145 wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32)); |
kaf24@3650 | 146 |
kaf24@3650 | 147 /* movq %rsp, saversp(%rip) */ |
kaf24@3650 | 148 stack[0] = 0x48; |
kaf24@3650 | 149 stack[1] = 0x89; |
kaf24@3650 | 150 stack[2] = 0x25; |
kaf24@3761 | 151 *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16; |
kaf24@3650 | 152 |
kaf24@3650 | 153 /* leaq saversp(%rip), %rsp */ |
kaf24@3650 | 154 stack[7] = 0x48; |
kaf24@3650 | 155 stack[8] = 0x8d; |
kaf24@3650 | 156 stack[9] = 0x25; |
kaf24@3761 | 157 *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16; |
kaf24@3650 | 158 |
kaf24@3783 | 159 /* pushq %r11 */ |
kaf24@3783 | 160 stack[14] = 0x41; |
kaf24@3783 | 161 stack[15] = 0x53; |
kaf24@3783 | 162 |
kaf24@3783 | 163 /* pushq $__GUEST_CS64 */ |
kaf24@3783 | 164 stack[16] = 0x68; |
kaf24@3783 | 165 *(u32 *)&stack[17] = __GUEST_CS64; |
kaf24@3783 | 166 |
kaf24@3761 | 167 /* jmp syscall_enter */ |
kaf24@3783 | 168 stack[21] = 0xe9; |
kaf24@3783 | 169 *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26]; |
kaf24@3650 | 170 |
kaf24@3695 | 171 /* |
kaf24@3695 | 172 * Trampoline for SYSCALL entry from compatibility mode. |
kaf24@3695 | 173 */ |
kaf24@3695 | 174 |
kaf24@3695 | 175 /* Skip the long-mode entry trampoline. */ |
kaf24@3783 | 176 stack = &stack[26]; |
kaf24@3695 | 177 wrmsr(MSR_CSTAR, (unsigned long)stack, ((unsigned long)stack>>32)); |
kaf24@3695 | 178 |
kaf24@3695 | 179 /* movq %rsp, saversp(%rip) */ |
kaf24@3695 | 180 stack[0] = 0x48; |
kaf24@3695 | 181 stack[1] = 0x89; |
kaf24@3695 | 182 stack[2] = 0x25; |
kaf24@3761 | 183 *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16; |
kaf24@3695 | 184 |
kaf24@3695 | 185 /* leaq saversp(%rip), %rsp */ |
kaf24@3695 | 186 stack[7] = 0x48; |
kaf24@3695 | 187 stack[8] = 0x8d; |
kaf24@3695 | 188 stack[9] = 0x25; |
kaf24@3761 | 189 *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16; |
kaf24@3695 | 190 |
kaf24@3783 | 191 /* pushq %r11 */ |
kaf24@3783 | 192 stack[14] = 0x41; |
kaf24@3783 | 193 stack[15] = 0x53; |
kaf24@3783 | 194 |
kaf24@3783 | 195 /* pushq $__GUEST_CS32 */ |
kaf24@3783 | 196 stack[16] = 0x68; |
kaf24@3783 | 197 *(u32 *)&stack[17] = __GUEST_CS32; |
kaf24@3783 | 198 |
kaf24@3761 | 199 /* jmp syscall_enter */ |
kaf24@3783 | 200 stack[21] = 0xe9; |
kaf24@3783 | 201 *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26]; |
kaf24@3695 | 202 |
kaf24@3695 | 203 /* |
kaf24@3695 | 204 * Common SYSCALL parameters. |
kaf24@3695 | 205 */ |
kaf24@3695 | 206 |
kaf24@3696 | 207 wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS); |
kaf24@3822 | 208 wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U); |
kaf24@3650 | 209 } |
kaf24@3650 | 210 |
kaf24@3780 | 211 long do_set_callbacks(unsigned long event_address, |
kaf24@3780 | 212 unsigned long failsafe_address, |
kaf24@3780 | 213 unsigned long syscall_address) |
kaf24@3780 | 214 { |
kaf24@5289 | 215 struct vcpu *d = current; |
kaf24@3780 | 216 |
kaf24@4689 | 217 d->arch.guest_context.event_callback_eip = event_address; |
kaf24@4689 | 218 d->arch.guest_context.failsafe_callback_eip = failsafe_address; |
kaf24@4689 | 219 d->arch.guest_context.syscall_callback_eip = syscall_address; |
kaf24@3780 | 220 |
kaf24@3780 | 221 return 0; |
kaf24@3780 | 222 } |
kaf24@6756 | 223 |
kaf24@6756 | 224 /* |
kaf24@6756 | 225 * Local variables: |
kaf24@6756 | 226 * mode: C |
kaf24@6756 | 227 * c-set-style: "BSD" |
kaf24@6756 | 228 * c-basic-offset: 4 |
kaf24@6756 | 229 * tab-width: 4 |
kaf24@6756 | 230 * indent-tabs-mode: nil |
kaf24@6756 | 231 * End: |
kaf24@6756 | 232 */ |