⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 traps.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
{    unsigned int width, i, match = 0;    unsigned long start;    if ( !(v->arch.guest_context.debugreg[5]) ||          !(v->arch.guest_context.ctrlreg[4] & X86_CR4_DE) )        return 0;    for ( i = 0; i < 4; i++ )    {        if ( !(v->arch.guest_context.debugreg[5] &               (3 << (i * DR_ENABLE_SIZE))) )            continue;        start = v->arch.guest_context.debugreg[i];        width = 0;        switch ( (v->arch.guest_context.debugreg[7] >>                  (DR_CONTROL_SHIFT + i * DR_CONTROL_SIZE)) & 0xc )        {        case DR_LEN_1: width = 1; break;        case DR_LEN_2: width = 2; break;        case DR_LEN_4: width = 4; break;        case DR_LEN_8: width = 8; break;        }        if ( (start < (port + len)) && ((start + width) > port) )            match |= 1 << i;    }    return match;}/* * Called from asm to set up the NMI trapbounce info. * Returns 0 if no callback is set up, else 1. */asmlinkage int set_guest_nmi_trapbounce(void){    struct vcpu *v = current;    struct trap_bounce *tb = &v->arch.trap_bounce;    do_guest_trap(TRAP_nmi, guest_cpu_user_regs(), 0);    tb->flags &= ~TBF_EXCEPTION; /* not needed for NMI delivery path */    return !null_trap_bounce(v, tb);}static inline void do_trap(    int trapnr, struct cpu_user_regs *regs, int use_error_code){    unsigned long fixup;    DEBUGGER_trap_entry(trapnr, regs);    if ( guest_mode(regs) )    {        do_guest_trap(trapnr, regs, use_error_code);        return;    }    if ( likely((fixup = search_exception_table(regs->eip)) != 0) )    {        dprintk(XENLOG_ERR, "Trap %d: %p -> %p\n",                trapnr, _p(regs->eip), _p(fixup));        regs->eip = fixup;        return;    }    DEBUGGER_trap_fatal(trapnr, regs);    show_execution_state(regs);    panic("FATAL TRAP: vector = %d (%s)\n"          "[error_code=%04x]\n",          trapnr, trapstr(trapnr), regs->error_code);}#define DO_ERROR_NOCODE(trapnr, name)                   \asmlinkage void do_##name(struct cpu_user_regs *regs)   \{                                                       \    do_trap(trapnr, regs, 0);                           \}#define DO_ERROR(trapnr, name)                          \asmlinkage void do_##name(struct cpu_user_regs *regs)   \{                                                       \    do_trap(trapnr, regs, 1);                           \}DO_ERROR_NOCODE(TRAP_divide_error,    divide_error)DO_ERROR_NOCODE(TRAP_overflow,        overflow)DO_ERROR_NOCODE(TRAP_bounds,          bounds)DO_ERROR_NOCODE(TRAP_copro_seg,       coprocessor_segment_overrun)DO_ERROR(       TRAP_invalid_tss,     invalid_TSS)DO_ERROR(       TRAP_no_segment,      segment_not_present)DO_ERROR(       TRAP_stack_error,     stack_segment)DO_ERROR_NOCODE(TRAP_copro_error,     coprocessor_error)DO_ERROR(       TRAP_alignment_check, alignment_check)DO_ERROR_NOCODE(TRAP_simd_error,      simd_coprocessor_error)int rdmsr_hypervisor_regs(    uint32_t idx, uint32_t *eax, uint32_t *edx){    idx -= 0x40000000;    if ( idx > 0 )        return 0;    switch ( idx )    {    case 0:    {        *eax = *edx = 0;        break;    }    default:        BUG();    }    return 1;}int wrmsr_hypervisor_regs(    uint32_t idx, uint32_t eax, uint32_t edx){    struct domain *d = current->domain;    idx -= 0x40000000;    if ( idx > 0 )        return 0;    switch ( idx )    {    case 0:    {        void         *hypercall_page;        unsigned long mfn;        unsigned long gmfn = ((unsigned long)edx << 20) | (eax >> 12);        unsigned int  idx  = eax & 0xfff;        if ( idx > 0 )        {            gdprintk(XENLOG_WARNING,                     "Out of range index %u to MSR %08x\n",                     idx, 0x40000000);            return 0;        }        mfn = gmfn_to_mfn(d, gmfn);        if ( !mfn_valid(mfn) ||             !get_page_and_type(mfn_to_page(mfn), d, PGT_writable_page) )        {            gdprintk(XENLOG_WARNING,                     "Bad GMFN %lx (MFN %lx) to MSR %08x\n",                     gmfn, mfn, 0x40000000);            return 0;        }        hypercall_page = map_domain_page(mfn);        hypercall_page_initialise(d, hypercall_page);        unmap_domain_page(hypercall_page);        put_page_and_type(mfn_to_page(mfn));        break;    }    default:        BUG();    }    return 1;}int cpuid_hypervisor_leaves(    uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx){    idx -= 0x40000000;    if ( idx > 2 )        return 0;    switch ( idx )    {    case 0:        *eax = 0x40000002; /* Largest leaf        */        *ebx = 0x566e6558; /* Signature 1: "XenV" */        *ecx = 0x65584d4d; /* Signature 2: "MMXe" */        *edx = 0x4d4d566e; /* Signature 3: "nVMM" */        break;    case 1:        *eax = (xen_major_version() << 16) | xen_minor_version();        *ebx = 0;          /* Reserved */        *ecx = 0;          /* Reserved */        *edx = 0;          /* Reserved */        break;    case 2:        *eax = 1;          /* Number of hypercall-transfer pages */        *ebx = 0x40000000; /* MSR base address */        *ecx = 0;          /* Features 1 */        *edx = 0;          /* Features 2 */        break;    default:        BUG();    }    return 1;}static int emulate_forced_invalid_op(struct cpu_user_regs *regs){    char sig[5], instr[2];    uint32_t a, b, c, d;    unsigned long eip, rc;    a = regs->eax;    b = regs->ebx;    c = regs->ecx;    d = regs->edx;    eip = regs->eip;    /* Check for forced emulation signature: ud2 ; .ascii "xen". */    if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 )    {        propagate_page_fault(eip + sizeof(sig) - rc, 0);        return EXCRET_fault_fixed;    }    if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) )        return 0;    eip += sizeof(sig);    /* We only emulate CPUID. */    if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 )    {        propagate_page_fault(eip + sizeof(instr) - rc, 0);        return EXCRET_fault_fixed;    }    if ( memcmp(instr, "\xf\xa2", sizeof(instr)) )        return 0;    eip += sizeof(instr);    asm (         "cpuid"        : "=a" (a), "=b" (b), "=c" (c), "=d" (d)        : "0" (a), "1" (b), "2" (c), "3" (d) );    if ( (regs->eax & 0x7fffffff) == 1 )    {        /* Modify Feature Information. */        __clear_bit(X86_FEATURE_VME, &d);        __clear_bit(X86_FEATURE_PSE, &d);        __clear_bit(X86_FEATURE_PGE, &d);        __clear_bit(X86_FEATURE_MCE, &d);        __clear_bit(X86_FEATURE_MCA, &d);        if ( !IS_PRIV(current->domain) )            __clear_bit(X86_FEATURE_MTRR, &d);        __clear_bit(X86_FEATURE_PSE36, &d);    }    switch ( (uint32_t)regs->eax )    {    case 1:        /* Modify Feature Information. */        if ( !cpu_has_sep )            __clear_bit(X86_FEATURE_SEP, &d);#ifdef __i386__        if ( !supervisor_mode_kernel )            __clear_bit(X86_FEATURE_SEP, &d);#endif        __clear_bit(X86_FEATURE_DS, &d);        __clear_bit(X86_FEATURE_ACC, &d);        __clear_bit(X86_FEATURE_PBE, &d);        __clear_bit(X86_FEATURE_DTES64 % 32, &c);        __clear_bit(X86_FEATURE_MWAIT % 32, &c);        __clear_bit(X86_FEATURE_DSCPL % 32, &c);        __clear_bit(X86_FEATURE_VMXE % 32, &c);        __clear_bit(X86_FEATURE_SMXE % 32, &c);        __clear_bit(X86_FEATURE_EST % 32, &c);        __clear_bit(X86_FEATURE_TM2 % 32, &c);        if ( is_pv_32bit_vcpu(current) )            __clear_bit(X86_FEATURE_CX16 % 32, &c);        __clear_bit(X86_FEATURE_XTPR % 32, &c);        __clear_bit(X86_FEATURE_PDCM % 32, &c);        __clear_bit(X86_FEATURE_DCA % 32, &c);        break;    case 0x80000001:        /* Modify Feature Information. */        if ( is_pv_32bit_vcpu(current) )        {            __clear_bit(X86_FEATURE_LM % 32, &d);            __clear_bit(X86_FEATURE_LAHF_LM % 32, &c);        }#ifndef __i386__        if ( is_pv_32on64_vcpu(current) &&             boot_cpu_data.x86_vendor != X86_VENDOR_AMD )#endif            __clear_bit(X86_FEATURE_SYSCALL % 32, &d);        __clear_bit(X86_FEATURE_PAGE1GB % 32, &d);        __clear_bit(X86_FEATURE_RDTSCP % 32, &d);        __clear_bit(X86_FEATURE_SVME % 32, &c);        __clear_bit(X86_FEATURE_OSVW % 32, &c);        __clear_bit(X86_FEATURE_IBS % 32, &c);        __clear_bit(X86_FEATURE_SKINIT % 32, &c);        __clear_bit(X86_FEATURE_WDT % 32, &c);        break;    case 5: /* MONITOR/MWAIT */    case 0xa: /* Architectural Performance Monitor Features */    case 0x8000000a: /* SVM revision and features */    case 0x8000001b: /* Instruction Based Sampling */        a = b = c = d = 0;        break;    default:        (void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d);        break;    }    regs->eax = a;    regs->ebx = b;    regs->ecx = c;    regs->edx = d;    instruction_done(regs, eip, 0);    trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->eip);    return EXCRET_fault_fixed;}asmlinkage void do_invalid_op(struct cpu_user_regs *regs){    struct bug_frame bug;    struct bug_frame_str bug_str;    char *filename, *predicate, *eip = (char *)regs->eip;    unsigned long fixup;    int id, lineno;    DEBUGGER_trap_entry(TRAP_invalid_op, regs);    if ( likely(guest_mode(regs)) )    {        if ( !emulate_forced_invalid_op(regs) )            do_guest_trap(TRAP_invalid_op, regs, 0);        return;    }    if ( !is_kernel(eip) ||         __copy_from_user(&bug, eip, sizeof(bug)) ||         memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) ||         (bug.ret != 0xc2) )        goto die;    eip += sizeof(bug);    id = bug.id & 3;    if ( id == BUGFRAME_dump )    {        show_execution_state(regs);        regs->eip = (unsigned long)eip;        return;    }    /* WARN, BUG or ASSERT: decode the filename pointer and line number. */    if ( !is_kernel(eip) ||         __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||         memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )        goto die;    eip += sizeof(bug_str);    filename = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";    lineno   = bug.id >> 2;    if ( id == BUGFRAME_warn )    {        printk("Xen WARN at %.50s:%d\n", filename, lineno);        show_execution_state(regs);        regs->eip = (unsigned long)eip;        return;    }    if ( id == BUGFRAME_bug )    {        printk("Xen BUG at %.50s:%d\n", filename, lineno);        DEBUGGER_trap_fatal(TRAP_invalid_op, regs);        show_execution_state(regs);        panic("Xen BUG at %.50s:%d\n", filename, lineno);    }    /* ASSERT: decode the predicate string pointer. */    ASSERT(id == BUGFRAME_assert);    if ( !is_kernel(eip) ||         __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||         memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )        goto die;    eip += sizeof(bug_str);    predicate = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";    printk("Assertion '%s' failed at %.50s:%d\n",           predicate, filename, lineno);    DEBUGGER_trap_fatal(TRAP_invalid_op, regs);    show_execution_state(regs);    panic("Assertion '%s' failed at %.50s:%d\n",          predicate, filename, lineno); die:    if ( (fixup = search_exception_table(regs->eip)) != 0 )    {        regs->eip = fixup;        return;    }    DEBUGGER_trap_fatal(TRAP_invalid_op, regs);    show_execution_state(regs);    panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);}asmlinkage void do_int3(struct cpu_user_regs *regs){    DEBUGGER_trap_entry(TRAP_int3, regs);    if ( !guest_mode(regs) )    {        debugger_trap_fatal(TRAP_int3, regs);        return;    }     do_guest_trap(TRAP_int3, regs, 0);}asmlinkage void do_machine_check(struct cpu_user_regs *regs){    extern fastcall void (*machine_check_vector)(        struct cpu_user_regs *, long error_code);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -