xen-vtx-unstable

annotate xen/arch/x86/x86_64/traps.c @ 3695:ff48344d34df

bitkeeper revision 1.1159.212.110 (42079080u5EKN2Dp7MbOEM7lnEs4gg)

Various bug fixes, and NMI/DF improvements for x86_64.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Mon Feb 07 16:00:00 2005 +0000 (2005-02-07)
parents 253e8e10e986
children aa3214cefa34
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@3630 9 #include <xen/console.h>
kaf24@3650 10 #include <xen/sched.h>
kaf24@3650 11 #include <asm/msr.h>
kaf24@3602 12
kaf24@3602 13 static int kstack_depth_to_print = 8*20;
kaf24@3602 14
kaf24@3602 15 static inline int kernel_text_address(unsigned long addr)
kaf24@3602 16 {
kaf24@3602 17 if (addr >= (unsigned long) &_stext &&
kaf24@3602 18 addr <= (unsigned long) &_etext)
kaf24@3602 19 return 1;
kaf24@3602 20 return 0;
kaf24@3602 21
kaf24@3602 22 }
kaf24@3602 23
kaf24@3602 24 void show_guest_stack(void)
kaf24@3602 25 {
kaf24@3602 26 int i;
kaf24@3602 27 execution_context_t *ec = get_execution_context();
kaf24@3602 28 unsigned long *stack = (unsigned long *)ec->rsp;
kaf24@3621 29 printk("Guest RIP is %lx\n ", ec->rip);
kaf24@3602 30
kaf24@3602 31 for ( i = 0; i < kstack_depth_to_print; i++ )
kaf24@3602 32 {
kaf24@3602 33 if ( ((long)stack & (STACK_SIZE-1)) == 0 )
kaf24@3602 34 break;
kaf24@3602 35 if ( i && ((i % 8) == 0) )
kaf24@3621 36 printk("\n ");
kaf24@3621 37 printk("%p ", *stack++);
kaf24@3602 38 }
kaf24@3602 39 printk("\n");
kaf24@3602 40
kaf24@3602 41 }
kaf24@3602 42
kaf24@3602 43 void show_trace(unsigned long *rsp)
kaf24@3602 44 {
kaf24@3602 45 unsigned long *stack, addr;
kaf24@3602 46 int i;
kaf24@3602 47
kaf24@3621 48 printk("Call Trace from RSP=%p:\n ", rsp);
kaf24@3602 49 stack = rsp;
kaf24@3602 50 i = 0;
kaf24@3602 51 while (((long) stack & (STACK_SIZE-1)) != 0) {
kaf24@3602 52 addr = *stack++;
kaf24@3602 53 if (kernel_text_address(addr)) {
kaf24@3602 54 if (i && ((i % 6) == 0))
kaf24@3602 55 printk("\n ");
kaf24@3621 56 printk("[<%p>] ", addr);
kaf24@3602 57 i++;
kaf24@3602 58 }
kaf24@3602 59 }
kaf24@3602 60 printk("\n");
kaf24@3602 61 }
kaf24@3602 62
kaf24@3602 63 void show_stack(unsigned long *rsp)
kaf24@3602 64 {
kaf24@3602 65 unsigned long *stack;
kaf24@3602 66 int i;
kaf24@3602 67
kaf24@3621 68 printk("Stack trace from RSP=%p:\n ", rsp);
kaf24@3602 69
kaf24@3602 70 stack = rsp;
kaf24@3602 71 for ( i = 0; i < kstack_depth_to_print; i++ )
kaf24@3602 72 {
kaf24@3602 73 if ( ((long)stack & (STACK_SIZE-1)) == 0 )
kaf24@3602 74 break;
kaf24@3602 75 if ( i && ((i % 8) == 0) )
kaf24@3621 76 printk("\n ");
kaf24@3602 77 if ( kernel_text_address(*stack) )
kaf24@3621 78 printk("[%p] ", *stack++);
kaf24@3602 79 else
kaf24@3621 80 printk("%p ", *stack++);
kaf24@3602 81 }
kaf24@3602 82 printk("\n");
kaf24@3602 83
kaf24@3602 84 show_trace(rsp);
kaf24@3602 85 }
kaf24@3602 86
kaf24@3602 87 void show_registers(struct xen_regs *regs)
kaf24@3602 88 {
kaf24@3621 89 printk("CPU: %d\nEIP: %04lx:[<%p>] \nEFLAGS: %p\n",
kaf24@3602 90 smp_processor_id(), 0xffff & regs->cs, regs->rip, regs->eflags);
kaf24@3621 91 printk("rax: %p rbx: %p rcx: %p rdx: %p\n",
kaf24@3602 92 regs->rax, regs->rbx, regs->rcx, regs->rdx);
kaf24@3621 93 printk("rsi: %p rdi: %p rbp: %p rsp: %p\n",
kaf24@3621 94 regs->rsi, regs->rdi, regs->rbp, regs->rsp);
kaf24@3621 95 printk("r8: %p r9: %p r10: %p r11: %p\n",
kaf24@3602 96 regs->r8, regs->r9, regs->r10, regs->r11);
kaf24@3621 97 printk("r12: %p r13: %p r14: %p r15: %p\n",
kaf24@3602 98 regs->r12, regs->r13, regs->r14, regs->r15);
kaf24@3602 99
kaf24@3602 100 show_stack((unsigned long *)regs->rsp);
kaf24@3602 101 }
kaf24@3602 102
kaf24@3630 103 void show_page_walk(unsigned long addr)
kaf24@3630 104 {
kaf24@3630 105 unsigned long page = read_cr3();
kaf24@3630 106
kaf24@3630 107 printk("Pagetable walk from %p:\n", addr);
kaf24@3630 108
kaf24@3630 109 page &= PAGE_MASK;
kaf24@3630 110 page = ((unsigned long *) __va(page))[l4_table_offset(addr)];
kaf24@3630 111 printk(" L4 = %p\n", page);
kaf24@3630 112 if ( !(page & _PAGE_PRESENT) )
kaf24@3630 113 return;
kaf24@3630 114
kaf24@3630 115 page &= PAGE_MASK;
kaf24@3630 116 page = ((unsigned long *) __va(page))[l3_table_offset(addr)];
kaf24@3630 117 printk(" L3 = %p\n", page);
kaf24@3630 118 if ( !(page & _PAGE_PRESENT) )
kaf24@3630 119 return;
kaf24@3630 120
kaf24@3630 121 page &= PAGE_MASK;
kaf24@3630 122 page = ((unsigned long *) __va(page))[l2_table_offset(addr)];
kaf24@3630 123 printk(" L2 = %p %s\n", page, (page & _PAGE_PSE) ? "(2MB)" : "");
kaf24@3630 124 if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) )
kaf24@3630 125 return;
kaf24@3630 126
kaf24@3630 127 page &= PAGE_MASK;
kaf24@3630 128 page = ((unsigned long *) __va(page))[l1_table_offset(addr)];
kaf24@3630 129 printk(" L1 = %p\n", page);
kaf24@3630 130 }
kaf24@3630 131
kaf24@3630 132 asmlinkage void double_fault(void);
kaf24@3630 133 asmlinkage void do_double_fault(struct xen_regs *regs)
kaf24@3630 134 {
kaf24@3630 135 /* Disable the NMI watchdog. It's useless now. */
kaf24@3630 136 watchdog_on = 0;
kaf24@3630 137
kaf24@3686 138 console_force_unlock();
kaf24@3686 139
kaf24@3630 140 /* Find information saved during fault and dump it to the console. */
kaf24@3630 141 printk("************************************\n");
kaf24@3695 142 show_registers(regs);
kaf24@3630 143 printk("************************************\n");
kaf24@3695 144 printk("CPU%d DOUBLE FAULT -- system shutdown\n", smp_processor_id());
kaf24@3630 145 printk("System needs manual reset.\n");
kaf24@3630 146 printk("************************************\n");
kaf24@3630 147
kaf24@3630 148 /* Lock up the console to prevent spurious output from other CPUs. */
kaf24@3630 149 console_force_lock();
kaf24@3630 150
kaf24@3630 151 /* Wait for manual reset. */
kaf24@3630 152 for ( ; ; )
kaf24@3630 153 __asm__ __volatile__ ( "hlt" );
kaf24@3630 154 }
kaf24@3630 155
kaf24@3650 156 asmlinkage void hypercall(void);
kaf24@3650 157 void __init percpu_traps_init(void)
kaf24@3650 158 {
kaf24@3650 159 char *stack_top = (char *)get_stack_top();
kaf24@3650 160 char *stack = (char *)((unsigned long)stack_top & ~(STACK_SIZE - 1));
kaf24@3695 161 int cpu = smp_processor_id();
kaf24@3695 162
kaf24@3695 163 /* Double-fault handler has its own per-CPU 1kB stack. */
kaf24@3695 164 init_tss[cpu].ist[0] = (unsigned long)&stack[1024];
kaf24@3695 165 set_intr_gate(TRAP_double_fault, &double_fault);
kaf24@3695 166 idt_tables[cpu][TRAP_double_fault].a |= 1UL << 32; /* IST1 */
kaf24@3695 167
kaf24@3695 168 /* NMI handler has its own per-CPU 1kB stack. */
kaf24@3695 169 init_tss[cpu].ist[1] = (unsigned long)&stack[2048];
kaf24@3695 170 idt_tables[cpu][TRAP_nmi].a |= 2UL << 32; /* IST2 */
kaf24@3695 171
kaf24@3695 172 /*
kaf24@3695 173 * Trampoline for SYSCALL entry from long mode.
kaf24@3695 174 */
kaf24@3695 175
kaf24@3695 176 /* Skip the NMI and DF stacks. */
kaf24@3695 177 stack = &stack[2048];
kaf24@3695 178 wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
kaf24@3650 179
kaf24@3650 180 /* movq %rsp, saversp(%rip) */
kaf24@3650 181 stack[0] = 0x48;
kaf24@3650 182 stack[1] = 0x89;
kaf24@3650 183 stack[2] = 0x25;
kaf24@3650 184 *(u32 *)&stack[3] = (stack_top - &stack[7]) - 16;
kaf24@3650 185
kaf24@3650 186 /* leaq saversp(%rip), %rsp */
kaf24@3650 187 stack[7] = 0x48;
kaf24@3650 188 stack[8] = 0x8d;
kaf24@3650 189 stack[9] = 0x25;
kaf24@3650 190 *(u32 *)&stack[10] = (stack_top - &stack[14]) - 16;
kaf24@3650 191
kaf24@3650 192 /* jmp hypercall */
kaf24@3650 193 stack[14] = 0xe9;
kaf24@3650 194 *(u32 *)&stack[15] = (char *)hypercall - &stack[19];
kaf24@3650 195
kaf24@3695 196 /*
kaf24@3695 197 * Trampoline for SYSCALL entry from compatibility mode.
kaf24@3695 198 */
kaf24@3695 199
kaf24@3695 200 /* Skip the long-mode entry trampoline. */
kaf24@3695 201 stack = &stack[19];
kaf24@3695 202 wrmsr(MSR_CSTAR, (unsigned long)stack, ((unsigned long)stack>>32));
kaf24@3695 203
kaf24@3695 204 /* movq %rsp, saversp(%rip) */
kaf24@3695 205 stack[0] = 0x48;
kaf24@3695 206 stack[1] = 0x89;
kaf24@3695 207 stack[2] = 0x25;
kaf24@3695 208 *(u32 *)&stack[3] = (stack_top - &stack[7]) - 16;
kaf24@3695 209
kaf24@3695 210 /* leaq saversp(%rip), %rsp */
kaf24@3695 211 stack[7] = 0x48;
kaf24@3695 212 stack[8] = 0x8d;
kaf24@3695 213 stack[9] = 0x25;
kaf24@3695 214 *(u32 *)&stack[10] = (stack_top - &stack[14]) - 16;
kaf24@3695 215
kaf24@3695 216 /* jmp hypercall */
kaf24@3695 217 stack[14] = 0xe9;
kaf24@3695 218 *(u32 *)&stack[15] = (char *)hypercall - &stack[19];
kaf24@3695 219
kaf24@3695 220 /*
kaf24@3695 221 * Common SYSCALL parameters.
kaf24@3695 222 */
kaf24@3695 223
kaf24@3650 224 wrmsr(MSR_STAR, 0, (FLAT_RING3_CS64<<16) | __HYPERVISOR_CS);
kaf24@3695 225 wrmsr(MSR_SYSCALL_MASK, ~EF_IE, 0U); /* disable interrupts */
kaf24@3650 226 }
kaf24@3650 227
kaf24@3602 228 void *decode_reg(struct xen_regs *regs, u8 b)
kaf24@3602 229 {
kaf24@3602 230 switch ( b )
kaf24@3602 231 {
kaf24@3602 232 case 0: return &regs->rax;
kaf24@3602 233 case 1: return &regs->rcx;
kaf24@3602 234 case 2: return &regs->rdx;
kaf24@3602 235 case 3: return &regs->rbx;
kaf24@3602 236 case 4: return &regs->rsp;
kaf24@3602 237 case 5: return &regs->rbp;
kaf24@3602 238 case 6: return &regs->rsi;
kaf24@3602 239 case 7: return &regs->rdi;
kaf24@3602 240 case 8: return &regs->r8;
kaf24@3602 241 case 9: return &regs->r9;
kaf24@3602 242 case 10: return &regs->r10;
kaf24@3602 243 case 11: return &regs->r11;
kaf24@3602 244 case 12: return &regs->r12;
kaf24@3602 245 case 13: return &regs->r13;
kaf24@3602 246 case 14: return &regs->r14;
kaf24@3602 247 case 15: return &regs->r15;
kaf24@3602 248 }
kaf24@3602 249
kaf24@3602 250 return NULL;
kaf24@3602 251 }