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

📄 helper.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
        if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {        cpu_x86_update_cr3(env, new_cr3);    }        /* load all registers without an exception, then reload them with       possible exception */    env->eip = new_eip;    eflags_mask = TF_MASK | AC_MASK | ID_MASK |         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;    if (!(type & 8))        eflags_mask &= 0xffff;    load_eflags(new_eflags, eflags_mask);    /* XXX: what to do in 16 bit case ? */    EAX = new_regs[0];    ECX = new_regs[1];    EDX = new_regs[2];    EBX = new_regs[3];    ESP = new_regs[4];    EBP = new_regs[5];    ESI = new_regs[6];    EDI = new_regs[7];    if (new_eflags & VM_MASK) {        for(i = 0; i < 6; i++)             load_seg_vm(i, new_segs[i]);        /* in vm86, CPL is always 3 */        cpu_x86_set_cpl(env, 3);    } else {        /* CPL is set the RPL of CS */        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);        /* first just selectors as the rest may trigger exceptions */        for(i = 0; i < 6; i++)            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);    }        env->ldt.selector = new_ldt & ~4;    env->ldt.base = 0;    env->ldt.limit = 0;    env->ldt.flags = 0;    /* load the LDT */    if (new_ldt & 4)        raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);    if ((new_ldt & 0xfffc) != 0) {        dt = &env->gdt;        index = new_ldt & ~7;        if ((index + 7) > dt->limit)            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);        ptr = dt->base + index;        e1 = ldl_kernel(ptr);        e2 = ldl_kernel(ptr + 4);        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);        if (!(e2 & DESC_P_MASK))            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);        load_seg_cache_raw_dt(&env->ldt, e1, e2);    }        /* load the segments */    if (!(new_eflags & VM_MASK)) {        tss_load_seg(R_CS, new_segs[R_CS]);        tss_load_seg(R_SS, new_segs[R_SS]);        tss_load_seg(R_ES, new_segs[R_ES]);        tss_load_seg(R_DS, new_segs[R_DS]);        tss_load_seg(R_FS, new_segs[R_FS]);        tss_load_seg(R_GS, new_segs[R_GS]);    }        /* check that EIP is in the CS segment limits */    if (new_eip > env->segs[R_CS].limit) {        /* XXX: different exception if CALL ? */        raise_exception_err(EXCP0D_GPF, 0);    }}/* check if Port I/O is allowed in TSS */static inline void check_io(int addr, int size){    int io_offset, val, mask;        /* TSS must be a valid 32 bit one */    if (!(env->tr.flags & DESC_P_MASK) ||        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||        env->tr.limit < 103)        goto fail;    io_offset = lduw_kernel(env->tr.base + 0x66);    io_offset += (addr >> 3);    /* Note: the check needs two bytes */    if ((io_offset + 1) > env->tr.limit)        goto fail;    val = lduw_kernel(env->tr.base + io_offset);    val >>= (addr & 7);    mask = (1 << size) - 1;    /* all bits must be zero to allow the I/O */    if ((val & mask) != 0) {    fail:        raise_exception_err(EXCP0D_GPF, 0);    }}void check_iob_T0(void){    check_io(T0, 1);}void check_iow_T0(void){    check_io(T0, 2);}void check_iol_T0(void){    check_io(T0, 4);}void check_iob_DX(void){    check_io(EDX & 0xffff, 1);}void check_iow_DX(void){    check_io(EDX & 0xffff, 2);}void check_iol_DX(void){    check_io(EDX & 0xffff, 4);}static inline unsigned int get_sp_mask(unsigned int e2){    if (e2 & DESC_B_MASK)        return 0xffffffff;    else        return 0xffff;}#ifdef TARGET_X86_64#define SET_ESP(val, sp_mask)\do {\    if ((sp_mask) == 0xffff)\        ESP = (ESP & ~0xffff) | ((val) & 0xffff);\    else if ((sp_mask) == 0xffffffffLL)\        ESP = (uint32_t)(val);\    else\        ESP = (val);\} while (0)#else#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))#endif/* XXX: add a is_user flag to have proper security support */#define PUSHW(ssp, sp, sp_mask, val)\{\    sp -= 2;\    stw_kernel((ssp) + (sp & (sp_mask)), (val));\}#define PUSHL(ssp, sp, sp_mask, val)\{\    sp -= 4;\    stl_kernel((ssp) + (sp & (sp_mask)), (val));\}#define POPW(ssp, sp, sp_mask, val)\{\    val = lduw_kernel((ssp) + (sp & (sp_mask)));\    sp += 2;\}#define POPL(ssp, sp, sp_mask, val)\{\    val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\    sp += 4;\}/* protected mode interrupt */static void do_interrupt_protected(int intno, int is_int, int error_code,                                   unsigned int next_eip, int is_hw){    SegmentCache *dt;    target_ulong ptr, ssp;    int type, dpl, selector, ss_dpl, cpl;    int has_error_code, new_stack, shift;    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;    uint32_t old_eip, sp_mask;    has_error_code = 0;    if (!is_int && !is_hw) {        switch(intno) {        case 8:        case 10:        case 11:        case 12:        case 13:        case 14:        case 17:            has_error_code = 1;            break;        }    }    if (is_int)        old_eip = next_eip;    else        old_eip = env->eip;    dt = &env->idt;    if (intno * 8 + 7 > dt->limit)        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);    ptr = dt->base + intno * 8;    e1 = ldl_kernel(ptr);    e2 = ldl_kernel(ptr + 4);    /* check gate type */    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;    switch(type) {    case 5: /* task gate */        /* must do that check here to return the correct error code */        if (!(e2 & DESC_P_MASK))            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);        switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);        if (has_error_code) {            int type;            uint32_t mask;            /* push the error code */            type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;            shift = type >> 3;            if (env->segs[R_SS].flags & DESC_B_MASK)                mask = 0xffffffff;            else                mask = 0xffff;            esp = (ESP - (2 << shift)) & mask;            ssp = env->segs[R_SS].base + esp;            if (shift)                stl_kernel(ssp, error_code);            else                stw_kernel(ssp, error_code);            SET_ESP(esp, mask);        }        return;    case 6: /* 286 interrupt gate */    case 7: /* 286 trap gate */    case 14: /* 386 interrupt gate */    case 15: /* 386 trap gate */        break;    default:        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);        break;    }    dpl = (e2 >> DESC_DPL_SHIFT) & 3;    cpl = env->hflags & HF_CPL_MASK;    /* check privledge if software int */    if (is_int && dpl < cpl)        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);    /* check valid bit */    if (!(e2 & DESC_P_MASK))        raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);    selector = e1 >> 16;    offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);    if ((selector & 0xfffc) == 0)        raise_exception_err(EXCP0D_GPF, 0);    if (load_segment(&e1, &e2, selector) != 0)        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);    dpl = (e2 >> DESC_DPL_SHIFT) & 3;    if (dpl > cpl)        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);    if (!(e2 & DESC_P_MASK))        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);    if (!(e2 & DESC_C_MASK) && dpl < cpl) {        /* to inner priviledge */        get_ss_esp_from_tss(&ss, &esp, dpl);        if ((ss & 0xfffc) == 0)            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);        if ((ss & 3) != dpl)            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);        if (load_segment(&ss_e1, &ss_e2, ss) != 0)            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);        ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;        if (ss_dpl != dpl)            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);        if (!(ss_e2 & DESC_S_MASK) ||            (ss_e2 & DESC_CS_MASK) ||            !(ss_e2 & DESC_W_MASK))            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);        if (!(ss_e2 & DESC_P_MASK))            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);        new_stack = 1;        sp_mask = get_sp_mask(ss_e2);        ssp = get_seg_base(ss_e1, ss_e2);    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {        /* to same priviledge */        if (env->eflags & VM_MASK)            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        new_stack = 0;        sp_mask = get_sp_mask(env->segs[R_SS].flags);        ssp = env->segs[R_SS].base;        esp = ESP;        dpl = cpl;    } else {        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        new_stack = 0; /* avoid warning */        sp_mask = 0; /* avoid warning */        ssp = 0; /* avoid warning */        esp = 0; /* avoid warning */    }    shift = type >> 3;#if 0    /* XXX: check that enough room is available */    push_size = 6 + (new_stack << 2) + (has_error_code << 1);    if (env->eflags & VM_MASK)        push_size += 8;    push_size <<= shift;#endif    if (shift == 1) {        if (new_stack) {            if (env->eflags & VM_MASK) {                PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);                PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);                PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);                PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);            }            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);            PUSHL(ssp, esp, sp_mask, ESP);        }        PUSHL(ssp, esp, sp_mask, compute_eflags());        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);        PUSHL(ssp, esp, sp_mask, old_eip);        if (has_error_code) {            PUSHL(ssp, esp, sp_mask, error_code);        }    } else {        if (new_stack) {            if (env->eflags & VM_MASK) {                PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);                PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);                PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);                PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);            }            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);            PUSHW(ssp, esp, sp_mask, ESP);        }        PUSHW(ssp, esp, sp_mask, compute_eflags());        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);        PUSHW(ssp, esp, sp_mask, old_eip);        if (has_error_code) {            PUSHW(ssp, esp, sp_mask, error_code);        }    }        if (new_stack) {        if (env->eflags & VM_MASK) {            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);        }        ss = (ss & ~3) | dpl;        cpu_x86_load_seg_cache(env, R_SS, ss,                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);    }    SET_ESP(esp, sp_mask);    selector = (selector & ~3) | dpl;    cpu_x86_load_seg_cache(env, R_CS, selector,                    get_seg_base(e1, e2),                   get_seg_limit(e1, e2),                   e2);    cpu_x86_set_cpl(env, dpl);    env->eip = offset;    /* interrupt gate clear IF mask */    if ((type & 1) == 0) {        env->eflags &= ~IF_MASK;    }    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);}#ifdef TARGET_X86_64#define PUSHQ(sp, val)\{\    sp -= 8;\    stq_kernel(sp, (val));\}#define POPQ(sp, val)\{\    val = ldq_kernel(sp);\    sp += 8;\}static inline target_ulong get_rsp_from_tss(int level){    int index;    #if 0    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",            env->tr.base, env->tr.limit);#endif    if (!(env->tr.flags & DESC_P_MASK))        cpu_abort(env, "invalid tss");    index = 8 * level + 4;    if ((index + 7) > env->tr.limit)        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);    return ldq_kernel(env->tr.base + index);}/* 64 bit interrupt */static void do_interrupt64(int intno, int is_int, int error_code,

⌨️ 快捷键说明

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