📄 traps.c
字号:
#include <xen/config.h>#include <xen/version.h>#include <xen/init.h>#include <xen/sched.h>#include <xen/lib.h>#include <xen/errno.h>#include <xen/mm.h>#include <xen/irq.h>#include <xen/symbols.h>#include <xen/console.h>#include <xen/sched.h>#include <xen/shutdown.h>#include <xen/nmi.h>#include <asm/current.h>#include <asm/flushtlb.h>#include <asm/msr.h>#include <asm/page.h>#include <asm/shared.h>#include <asm/hvm/hvm.h>#include <asm/hvm/support.h>#include <public/callback.h>asmlinkage void syscall_enter(void);asmlinkage void sysenter_entry(void);asmlinkage void compat_hypercall(void);asmlinkage void int80_direct_trap(void);static void print_xen_info(void){ char taint_str[TAINT_STRING_MAX_LEN]; char debug = 'n';#ifndef NDEBUG debug = 'y';#endif printk("----[ Xen-%d.%d%s x86_64 debug=%c %s ]----\n", xen_major_version(), xen_minor_version(), xen_extra_version(), debug, print_tainted(taint_str));}enum context { CTXT_hypervisor, CTXT_pv_guest, CTXT_hvm_guest };static void _show_registers( const struct cpu_user_regs *regs, unsigned long crs[8], enum context context, const struct vcpu *v){ const static char *context_names[] = { [CTXT_hypervisor] = "hypervisor", [CTXT_pv_guest] = "pv guest", [CTXT_hvm_guest] = "hvm guest" }; printk("RIP: %04x:[<%016lx>]", regs->cs, regs->rip); if ( context == CTXT_hypervisor ) print_symbol(" %s", regs->rip); printk("\nRFLAGS: %016lx ", regs->rflags); if ( (context == CTXT_pv_guest) && v && v->vcpu_info ) printk("EM: %d ", !!vcpu_info(v, evtchn_upcall_mask)); printk("CONTEXT: %s\n", context_names[context]); printk("rax: %016lx rbx: %016lx rcx: %016lx\n", regs->rax, regs->rbx, regs->rcx); printk("rdx: %016lx rsi: %016lx rdi: %016lx\n", regs->rdx, regs->rsi, regs->rdi); printk("rbp: %016lx rsp: %016lx r8: %016lx\n", regs->rbp, regs->rsp, regs->r8); printk("r9: %016lx r10: %016lx r11: %016lx\n", regs->r9, regs->r10, regs->r11); printk("r12: %016lx r13: %016lx r14: %016lx\n", regs->r12, regs->r13, regs->r14); printk("r15: %016lx cr0: %016lx cr4: %016lx\n", regs->r15, crs[0], crs[4]); printk("cr3: %016lx cr2: %016lx\n", crs[3], crs[2]); printk("ds: %04x es: %04x fs: %04x gs: %04x " "ss: %04x cs: %04x\n", regs->ds, regs->es, regs->fs, regs->gs, regs->ss, regs->cs);}void show_registers(struct cpu_user_regs *regs){ struct cpu_user_regs fault_regs = *regs; unsigned long fault_crs[8]; enum context context; struct vcpu *v = current; if ( is_hvm_vcpu(v) && guest_mode(regs) ) { struct segment_register sreg; context = CTXT_hvm_guest; fault_crs[0] = v->arch.hvm_vcpu.guest_cr[0]; fault_crs[2] = v->arch.hvm_vcpu.guest_cr[2]; fault_crs[3] = v->arch.hvm_vcpu.guest_cr[3]; fault_crs[4] = v->arch.hvm_vcpu.guest_cr[4]; hvm_get_segment_register(v, x86_seg_cs, &sreg); fault_regs.cs = sreg.sel; hvm_get_segment_register(v, x86_seg_ds, &sreg); fault_regs.ds = sreg.sel; hvm_get_segment_register(v, x86_seg_es, &sreg); fault_regs.es = sreg.sel; hvm_get_segment_register(v, x86_seg_fs, &sreg); fault_regs.fs = sreg.sel; hvm_get_segment_register(v, x86_seg_gs, &sreg); fault_regs.gs = sreg.sel; hvm_get_segment_register(v, x86_seg_ss, &sreg); fault_regs.ss = sreg.sel; } else { if ( guest_mode(regs) ) { context = CTXT_pv_guest; fault_crs[2] = arch_get_cr2(v); } else { context = CTXT_hypervisor; fault_crs[2] = read_cr2(); } fault_crs[0] = read_cr0(); fault_crs[3] = read_cr3(); fault_crs[4] = read_cr4(); fault_regs.ds = read_segment_register(ds); fault_regs.es = read_segment_register(es); fault_regs.fs = read_segment_register(fs); fault_regs.gs = read_segment_register(gs); } print_xen_info(); printk("CPU: %d\n", smp_processor_id()); _show_registers(&fault_regs, fault_crs, context, v); if ( this_cpu(ler_msr) && !guest_mode(regs) ) { u64 from, to; rdmsrl(this_cpu(ler_msr), from); rdmsrl(this_cpu(ler_msr) + 1, to); printk("ler: %016lx -> %016lx\n", from, to); }}void vcpu_show_registers(const struct vcpu *v){ const struct cpu_user_regs *regs = &v->arch.guest_context.user_regs; unsigned long crs[8]; /* No need to handle HVM for now. */ if ( is_hvm_vcpu(v) ) return; crs[0] = v->arch.guest_context.ctrlreg[0]; crs[2] = arch_get_cr2(v); crs[3] = pagetable_get_paddr(guest_kernel_mode(v, regs) ? v->arch.guest_table : v->arch.guest_table_user); crs[4] = v->arch.guest_context.ctrlreg[4]; _show_registers(regs, crs, CTXT_pv_guest, v);}void show_page_walk(unsigned long addr){ unsigned long pfn, mfn = read_cr3() >> PAGE_SHIFT; l4_pgentry_t l4e, *l4t; l3_pgentry_t l3e, *l3t; l2_pgentry_t l2e, *l2t; l1_pgentry_t l1e, *l1t; printk("Pagetable walk from %016lx:\n", addr); l4t = mfn_to_virt(mfn); l4e = l4t[l4_table_offset(addr)]; mfn = l4e_get_pfn(l4e); pfn = mfn_valid(mfn) ? get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY; printk(" L4[0x%03lx] = %"PRIpte" %016lx\n", l4_table_offset(addr), l4e_get_intpte(l4e), pfn); if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) return; l3t = mfn_to_virt(mfn); l3e = l3t[l3_table_offset(addr)]; mfn = l3e_get_pfn(l3e); pfn = mfn_valid(mfn) ? get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY; printk(" L3[0x%03lx] = %"PRIpte" %016lx%s\n", l3_table_offset(addr), l3e_get_intpte(l3e), pfn, (l3e_get_flags(l3e) & _PAGE_PSE) ? " (PSE)" : ""); if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) || (l3e_get_flags(l3e) & _PAGE_PSE) ) return; l2t = mfn_to_virt(mfn); l2e = l2t[l2_table_offset(addr)]; mfn = l2e_get_pfn(l2e); pfn = mfn_valid(mfn) ? get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY; printk(" L2[0x%03lx] = %"PRIpte" %016lx %s\n", l2_table_offset(addr), l2e_get_intpte(l2e), pfn, (l2e_get_flags(l2e) & _PAGE_PSE) ? "(PSE)" : ""); if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || (l2e_get_flags(l2e) & _PAGE_PSE) ) return; l1t = mfn_to_virt(mfn); l1e = l1t[l1_table_offset(addr)]; mfn = l1e_get_pfn(l1e); pfn = mfn_valid(mfn) ? get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY; printk(" L1[0x%03lx] = %"PRIpte" %016lx\n", l1_table_offset(addr), l1e_get_intpte(l1e), pfn);}asmlinkage void double_fault(void);asmlinkage void do_double_fault(struct cpu_user_regs *regs){ unsigned int cpu, tr; asm volatile ( "str %0" : "=r" (tr) ); cpu = ((tr >> 3) - __FIRST_TSS_ENTRY) >> 2; watchdog_disable(); console_force_unlock(); /* Find information saved during fault and dump it to the console. */ printk("*** DOUBLE FAULT ***\n"); print_xen_info(); printk("CPU: %d\nRIP: %04x:[<%016lx>]", cpu, regs->cs, regs->rip); print_symbol(" %s", regs->rip); printk("\nRFLAGS: %016lx\n", regs->rflags); printk("rax: %016lx rbx: %016lx rcx: %016lx\n", regs->rax, regs->rbx, regs->rcx); printk("rdx: %016lx rsi: %016lx rdi: %016lx\n", regs->rdx, regs->rsi, regs->rdi); printk("rbp: %016lx rsp: %016lx r8: %016lx\n", regs->rbp, regs->rsp, regs->r8); printk("r9: %016lx r10: %016lx r11: %016lx\n", regs->r9, regs->r10, regs->r11); printk("r12: %016lx r13: %016lx r14: %016lx\n", regs->r12, regs->r13, regs->r14); printk("r15: %016lx cs: %016lx ss: %016lx\n", regs->r15, (long)regs->cs, (long)regs->ss); show_stack_overflow(cpu, regs->rsp); panic("DOUBLE FAULT -- system shutdown\n");}void toggle_guest_mode(struct vcpu *v){ if ( is_pv_32bit_vcpu(v) ) return; v->arch.flags ^= TF_kernel_mode; asm volatile ( "swapgs" ); update_cr3(v);#ifdef USER_MAPPINGS_ARE_GLOBAL /* Don't flush user global mappings from the TLB. Don't tick TLB clock. */ asm volatile ( "mov %0, %%cr3" : : "r" (v->arch.cr3) : "memory" );#else write_ptbase(v);#endif}unsigned long do_iret(void){ struct cpu_user_regs *regs = guest_cpu_user_regs(); struct iret_context iret_saved; struct vcpu *v = current; if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, sizeof(iret_saved))) ) { gdprintk(XENLOG_ERR, "Fault while reading IRET context from " "guest stack\n"); goto exit_and_crash; } /* Returning to user mode? */ if ( (iret_saved.cs & 3) == 3 ) { if ( unlikely(pagetable_is_null(v->arch.guest_table_user)) ) { gdprintk(XENLOG_ERR, "Guest switching to user mode with no " "user page tables\n"); goto exit_and_crash; } toggle_guest_mode(v); } regs->rip = iret_saved.rip; regs->cs = iret_saved.cs | 3; /* force guest privilege */ regs->rflags = (iret_saved.rflags & ~(EF_IOPL|EF_VM)) | EF_IE; regs->rsp = iret_saved.rsp; regs->ss = iret_saved.ss | 3; /* force guest privilege */ if ( !(iret_saved.flags & VGCF_in_syscall) ) { regs->entry_vector = 0; regs->r11 = iret_saved.r11; regs->rcx = iret_saved.rcx; } /* Restore affinity. */ if ((v->trap_priority >= VCPU_TRAP_NMI) && !cpus_equal(v->cpu_affinity_tmp, v->cpu_affinity)) vcpu_set_affinity(v, &v->cpu_affinity_tmp); /* Restore previous trap priority */ v->trap_priority = v->old_trap_priority; /* Restore upcall mask from supplied EFLAGS.IF. */ vcpu_info(v, evtchn_upcall_mask) = !(iret_saved.rflags & EF_IE); /* Saved %rax gets written back to regs->rax in entry.S. */ return iret_saved.rax; exit_and_crash: gdprintk(XENLOG_ERR, "Fatal error\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -