📄 traps.c
字号:
#include <xen/config.h>#include <xen/version.h>#include <xen/domain_page.h>#include <xen/init.h>#include <xen/sched.h>#include <xen/lib.h>#include <xen/console.h>#include <xen/mm.h>#include <xen/irq.h>#include <xen/symbols.h>#include <xen/shutdown.h>#include <xen/nmi.h>#include <asm/current.h>#include <asm/flushtlb.h>#include <asm/hvm/hvm.h>#include <asm/hvm/support.h>#include <public/callback.h>static void print_xen_info(void){ char taint_str[TAINT_STRING_MAX_LEN]; char debug = 'n', *arch = "x86_32p";#ifndef NDEBUG debug = 'y';#endif printk("----[ Xen-%d.%d%s %s debug=%c %s ]----\n", xen_major_version(), xen_minor_version(), xen_extra_version(), arch, 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("EIP: %04x:[<%08x>]", regs->cs, regs->eip); if ( context == CTXT_hypervisor ) print_symbol(" %s", regs->eip); printk("\nEFLAGS: %08x ", regs->eflags); if ( (context == CTXT_pv_guest) && v && v->vcpu_info ) printk("EM: %d ", !!v->vcpu_info->evtchn_upcall_mask); printk("CONTEXT: %s\n", context_names[context]); printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n", regs->eax, regs->ebx, regs->ecx, regs->edx); printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n", regs->esi, regs->edi, regs->ebp, regs->esp); printk("cr0: %08lx cr4: %08lx cr3: %08lx cr2: %08lx\n", crs[0], crs[4], 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_hypervisor; fault_regs.esp = (unsigned long)®s->esp; fault_regs.ss = read_segment_register(ss); 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); fault_crs[2] = read_cr2(); } else { context = CTXT_pv_guest; fault_crs[2] = v->vcpu_info->arch.cr2; } fault_crs[0] = read_cr0(); fault_crs[3] = read_cr3(); fault_crs[4] = read_cr4(); } 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) ) { u32 from, to, hi; rdmsr(this_cpu(ler_msr), from, hi); rdmsr(this_cpu(ler_msr) + 1, to, hi); printk("ler: %08x -> %08x\n", from, to); }}void vcpu_show_registers(const struct vcpu *v){ 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] = v->vcpu_info->arch.cr2; crs[3] = pagetable_get_paddr(v->arch.guest_table); crs[4] = v->arch.guest_context.ctrlreg[4]; _show_registers(&v->arch.guest_context.user_regs, crs, CTXT_pv_guest, v);}void show_page_walk(unsigned long addr){ unsigned long pfn, mfn, cr3 = read_cr3(); l3_pgentry_t l3e, *l3t; l2_pgentry_t l2e, *l2t; l1_pgentry_t l1e, *l1t; printk("Pagetable walk from %08lx:\n", addr); mfn = cr3 >> PAGE_SHIFT; l3t = map_domain_page(mfn); l3t += (cr3 & 0xFE0UL) >> 3; 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" %08lx\n", l3_table_offset(addr), l3e_get_intpte(l3e), pfn); unmap_domain_page(l3t); if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) return; l2t = map_domain_page(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" %08lx %s\n", l2_table_offset(addr), l2e_get_intpte(l2e), pfn, (l2e_get_flags(l2e) & _PAGE_PSE) ? "(PSE)" : ""); unmap_domain_page(l2t); if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || (l2e_get_flags(l2e) & _PAGE_PSE) ) return; l1t = map_domain_page(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" %08lx\n", l1_table_offset(addr), l1e_get_intpte(l1e), pfn); unmap_domain_page(l1t);}#define DOUBLEFAULT_STACK_SIZE 2048static struct tss_struct doublefault_tss;static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];asmlinkage void do_double_fault(void){ struct tss_struct *tss = &doublefault_tss; unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1; watchdog_disable(); console_force_unlock(); /* Find information saved during fault and dump it to the console. */ tss = &init_tss[cpu]; printk("*** DOUBLE FAULT ***\n"); print_xen_info(); printk("CPU: %d\nEIP: %04x:[<%08x>]", cpu, tss->cs, tss->eip); print_symbol(" %s\n", tss->eip); printk("EFLAGS: %08x\n", tss->eflags); printk("CR3: %08x\n", tss->__cr3); printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n", tss->eax, tss->ebx, tss->ecx, tss->edx); printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n", tss->esi, tss->edi, tss->ebp, tss->esp); printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", tss->ds, tss->es, tss->fs, tss->gs, tss->ss); show_stack_overflow(cpu, tss->esp); panic("DOUBLE FAULT -- system shutdown\n");}unsigned long do_iret(void){ struct cpu_user_regs *regs = guest_cpu_user_regs(); struct vcpu *v = current; u32 eflags; /* Check worst-case stack frame for overlap with Xen protected area. */ if ( unlikely(!access_ok(regs->esp, 40)) ) goto exit_and_crash; /* Pop and restore EAX (clobbered by hypercall). */ if ( unlikely(__copy_from_user(®s->eax, (void *)regs->esp, 4)) ) goto exit_and_crash; regs->esp += 4; /* Pop and restore CS and EIP. */ if ( unlikely(__copy_from_user(®s->eip, (void *)regs->esp, 8)) ) goto exit_and_crash; regs->esp += 8; /* * Pop, fix up and restore EFLAGS. We fix up in a local staging area * to avoid firing the BUG_ON(IOPL) check in arch_get_info_guest. */ if ( unlikely(__copy_from_user(&eflags, (void *)regs->esp, 4)) ) goto exit_and_crash; regs->esp += 4; regs->eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF; if ( vm86_mode(regs) ) { /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */ if ( __copy_from_user(®s->esp, (void *)regs->esp, 24) ) goto exit_and_crash; } else if ( unlikely(ring_0(regs)) ) { goto exit_and_crash; } else if ( !ring_1(regs) ) { /* Return to ring 2/3: pop and restore ESP and SS. */ if ( __copy_from_user(®s->esp, (void *)regs->esp, 8) ) goto exit_and_crash; } /* 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) = !(eflags & X86_EFLAGS_IF); /* * The hypercall exit path will overwrite EAX with this return * value. */ return regs->eax; exit_and_crash: gdprintk(XENLOG_ERR, "Fatal error\n"); domain_crash(v->domain); return 0;}static void set_task_gate(unsigned int n, unsigned int sel){ idt_table[n].b = 0; wmb(); /* disable gate /then/ rewrite */ idt_table[n].a = sel << 16; wmb(); /* rewrite /then/ enable gate */ idt_table[n].b = 0x8500;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -