kaf24@3602: kaf24@3602: #include kaf24@3602: #include kaf24@3602: #include kaf24@3602: #include kaf24@3602: #include kaf24@3602: #include kaf24@3602: #include kaf24@5824: #include kaf24@3630: #include kaf24@3650: #include cl349@5291: #include kaf24@5159: #include kaf24@3650: #include kaf24@6756: #include kaf24@3602: kaf24@4683: void show_registers(struct cpu_user_regs *regs) kaf24@3602: { kaf24@6756: unsigned long rip, rsp, rflags, cs, cr0, cr3; kaf24@6756: const char *context; kaf24@6756: kaf24@6756: if ( VMX_DOMAIN(current) && (regs->eflags == 0) ) kaf24@6756: { kaf24@6756: __vmread(GUEST_RIP, &rip); kaf24@6756: __vmread(GUEST_RSP, &rsp); kaf24@6756: __vmread(GUEST_RFLAGS, &rflags); kaf24@6756: __vmread(GUEST_CS_SELECTOR, &cs); kaf24@6756: __vmread(CR0_READ_SHADOW, &cr0); kaf24@6756: __vmread(GUEST_CR3, &cr3); kaf24@6756: context = "vmx guest"; kaf24@6756: } kaf24@6756: else kaf24@6756: { kaf24@6756: rip = regs->rip; kaf24@6756: rflags = regs->rflags; kaf24@6756: cr0 = read_cr0(); kaf24@6756: cr3 = read_cr3(); kaf24@6756: rsp = regs->rsp; kaf24@6756: cs = regs->cs & 0xffff; kaf24@6756: context = GUEST_MODE(regs) ? "guest" : "hypervisor"; kaf24@6756: } kaf24@6756: kaf24@6756: printk("CPU: %d\nRIP: %04lx:[<%016lx>]", kaf24@6756: smp_processor_id(), cs, rip); kaf24@6232: if ( !GUEST_MODE(regs) ) kaf24@6756: print_symbol(" %s", rip); kaf24@6756: printk("\nRFLAGS: %016lx CONTEXT: %s\n", rflags, context); kaf24@6477: printk("rax: %016lx rbx: %016lx rcx: %016lx\n", kaf24@6477: regs->rax, regs->rbx, regs->rcx); kaf24@6477: printk("rdx: %016lx rsi: %016lx rdi: %016lx\n", kaf24@6477: regs->rdx, regs->rsi, regs->rdi); kaf24@6477: printk("rbp: %016lx rsp: %016lx r8: %016lx\n", kaf24@6756: regs->rbp, rsp, regs->r8); kaf24@6477: printk("r9: %016lx r10: %016lx r11: %016lx\n", kaf24@6477: regs->r9, regs->r10, regs->r11); kaf24@6477: printk("r12: %016lx r13: %016lx r14: %016lx\n", kaf24@6477: regs->r12, regs->r13, regs->r14); kaf24@6756: printk("r15: %016lx cr0: %016lx cr3: %016lx\n", kaf24@6756: regs->r15, cr0, cr3); kaf24@3602: kaf24@6573: show_stack(regs); kaf24@5073: } kaf24@3602: kaf24@3630: void show_page_walk(unsigned long addr) kaf24@3630: { kaf24@3630: unsigned long page = read_cr3(); kaf24@3630: kaf24@4654: printk("Pagetable walk from %016lx:\n", addr); kaf24@3630: kaf24@3630: page &= PAGE_MASK; kaf24@3630: page = ((unsigned long *) __va(page))[l4_table_offset(addr)]; kaf24@4654: printk(" L4 = %016lx\n", page); kaf24@3630: if ( !(page & _PAGE_PRESENT) ) kaf24@3630: return; kaf24@3630: kaf24@3630: page &= PAGE_MASK; kaf24@3630: page = ((unsigned long *) __va(page))[l3_table_offset(addr)]; kaf24@4654: printk(" L3 = %016lx\n", page); kaf24@3630: if ( !(page & _PAGE_PRESENT) ) kaf24@3630: return; kaf24@3630: kaf24@3630: page &= PAGE_MASK; kaf24@3630: page = ((unsigned long *) __va(page))[l2_table_offset(addr)]; kaf24@4654: printk(" L2 = %016lx %s\n", page, (page & _PAGE_PSE) ? "(2MB)" : ""); kaf24@3630: if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) ) kaf24@3630: return; kaf24@3630: kaf24@3630: page &= PAGE_MASK; kaf24@3630: page = ((unsigned long *) __va(page))[l1_table_offset(addr)]; kaf24@4654: printk(" L1 = %016lx\n", page); kaf24@3630: } kaf24@3630: kaf24@3630: asmlinkage void double_fault(void); kaf24@4683: asmlinkage void do_double_fault(struct cpu_user_regs *regs) kaf24@3630: { kaf24@4926: watchdog_disable(); kaf24@3630: kaf24@3686: console_force_unlock(); kaf24@3686: kaf24@3630: /* Find information saved during fault and dump it to the console. */ kaf24@3630: printk("************************************\n"); kaf24@3695: show_registers(regs); kaf24@3630: printk("************************************\n"); kaf24@3695: printk("CPU%d DOUBLE FAULT -- system shutdown\n", smp_processor_id()); kaf24@3630: printk("System needs manual reset.\n"); kaf24@3630: printk("************************************\n"); kaf24@3630: kaf24@3630: /* Lock up the console to prevent spurious output from other CPUs. */ kaf24@3630: console_force_lock(); kaf24@3630: kaf24@3630: /* Wait for manual reset. */ kaf24@3630: for ( ; ; ) kaf24@3630: __asm__ __volatile__ ( "hlt" ); kaf24@3630: } kaf24@3630: kaf24@3761: asmlinkage void syscall_enter(void); kaf24@3650: void __init percpu_traps_init(void) kaf24@3650: { kaf24@3761: char *stack_bottom, *stack; kaf24@3761: int cpu = smp_processor_id(); kaf24@3761: kaf24@3774: if ( cpu == 0 ) kaf24@3774: { kaf24@3774: /* Specify dedicated interrupt stacks for NMIs and double faults. */ kaf24@3774: set_intr_gate(TRAP_double_fault, &double_fault); kaf24@3774: idt_table[TRAP_double_fault].a |= 1UL << 32; /* IST1 */ kaf24@3774: idt_table[TRAP_nmi].a |= 2UL << 32; /* IST2 */ kaf24@3774: } kaf24@3774: kaf24@3761: stack_bottom = (char *)get_stack_bottom(); kaf24@3761: stack = (char *)((unsigned long)stack_bottom & ~(STACK_SIZE - 1)); kaf24@3695: kaf24@3695: /* Double-fault handler has its own per-CPU 1kB stack. */ kaf24@3695: init_tss[cpu].ist[0] = (unsigned long)&stack[1024]; kaf24@3695: kaf24@3695: /* NMI handler has its own per-CPU 1kB stack. */ kaf24@3695: init_tss[cpu].ist[1] = (unsigned long)&stack[2048]; kaf24@3695: kaf24@3695: /* kaf24@3695: * Trampoline for SYSCALL entry from long mode. kaf24@3695: */ kaf24@3695: kaf24@3695: /* Skip the NMI and DF stacks. */ kaf24@3695: stack = &stack[2048]; kaf24@3695: wrmsr(MSR_LSTAR, (unsigned long)stack, ((unsigned long)stack>>32)); kaf24@3650: kaf24@3650: /* movq %rsp, saversp(%rip) */ kaf24@3650: stack[0] = 0x48; kaf24@3650: stack[1] = 0x89; kaf24@3650: stack[2] = 0x25; kaf24@3761: *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16; kaf24@3650: kaf24@3650: /* leaq saversp(%rip), %rsp */ kaf24@3650: stack[7] = 0x48; kaf24@3650: stack[8] = 0x8d; kaf24@3650: stack[9] = 0x25; kaf24@3761: *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16; kaf24@3650: kaf24@3783: /* pushq %r11 */ kaf24@3783: stack[14] = 0x41; kaf24@3783: stack[15] = 0x53; kaf24@3783: kaf24@3783: /* pushq $__GUEST_CS64 */ kaf24@3783: stack[16] = 0x68; kaf24@3783: *(u32 *)&stack[17] = __GUEST_CS64; kaf24@3783: kaf24@3761: /* jmp syscall_enter */ kaf24@3783: stack[21] = 0xe9; kaf24@3783: *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26]; kaf24@3650: kaf24@3695: /* kaf24@3695: * Trampoline for SYSCALL entry from compatibility mode. kaf24@3695: */ kaf24@3695: kaf24@3695: /* Skip the long-mode entry trampoline. */ kaf24@3783: stack = &stack[26]; kaf24@3695: wrmsr(MSR_CSTAR, (unsigned long)stack, ((unsigned long)stack>>32)); kaf24@3695: kaf24@3695: /* movq %rsp, saversp(%rip) */ kaf24@3695: stack[0] = 0x48; kaf24@3695: stack[1] = 0x89; kaf24@3695: stack[2] = 0x25; kaf24@3761: *(u32 *)&stack[3] = (stack_bottom - &stack[7]) - 16; kaf24@3695: kaf24@3695: /* leaq saversp(%rip), %rsp */ kaf24@3695: stack[7] = 0x48; kaf24@3695: stack[8] = 0x8d; kaf24@3695: stack[9] = 0x25; kaf24@3761: *(u32 *)&stack[10] = (stack_bottom - &stack[14]) - 16; kaf24@3695: kaf24@3783: /* pushq %r11 */ kaf24@3783: stack[14] = 0x41; kaf24@3783: stack[15] = 0x53; kaf24@3783: kaf24@3783: /* pushq $__GUEST_CS32 */ kaf24@3783: stack[16] = 0x68; kaf24@3783: *(u32 *)&stack[17] = __GUEST_CS32; kaf24@3783: kaf24@3761: /* jmp syscall_enter */ kaf24@3783: stack[21] = 0xe9; kaf24@3783: *(u32 *)&stack[22] = (char *)syscall_enter - &stack[26]; kaf24@3695: kaf24@3695: /* kaf24@3695: * Common SYSCALL parameters. kaf24@3695: */ kaf24@3695: kaf24@3696: wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS); kaf24@3822: wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U); kaf24@3650: } kaf24@3650: kaf24@3780: long do_set_callbacks(unsigned long event_address, kaf24@3780: unsigned long failsafe_address, kaf24@3780: unsigned long syscall_address) kaf24@3780: { kaf24@5289: struct vcpu *d = current; kaf24@3780: kaf24@4689: d->arch.guest_context.event_callback_eip = event_address; kaf24@4689: d->arch.guest_context.failsafe_callback_eip = failsafe_address; kaf24@4689: d->arch.guest_context.syscall_callback_eip = syscall_address; kaf24@3780: kaf24@3780: return 0; kaf24@3780: } kaf24@6756: kaf24@6756: /* kaf24@6756: * Local variables: kaf24@6756: * mode: C kaf24@6756: * c-set-style: "BSD" kaf24@6756: * c-basic-offset: 4 kaf24@6756: * tab-width: 4 kaf24@6756: * indent-tabs-mode: nil kaf24@6756: * End: kaf24@6756: */