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

📄 helper.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
                           target_ulong next_eip, int is_hw){    SegmentCache *dt;    target_ulong ptr;    int type, dpl, selector, cpl, ist;    int has_error_code, new_stack;    uint32_t e1, e2, e3, ss;    target_ulong old_eip, esp, offset;    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 * 16 + 15 > dt->limit)        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);    ptr = dt->base + intno * 16;    e1 = ldl_kernel(ptr);    e2 = ldl_kernel(ptr + 4);    e3 = ldl_kernel(ptr + 8);    /* check gate type */    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;    switch(type) {    case 14: /* 386 interrupt gate */    case 15: /* 386 trap gate */        break;    default:        raise_exception_err(EXCP0D_GPF, intno * 16 + 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 * 16 + 2);    /* check valid bit */    if (!(e2 & DESC_P_MASK))        raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);    selector = e1 >> 16;    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);    ist = e2 & 7;    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_L_MASK) || (e2 & DESC_B_MASK))        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {        /* to inner priviledge */        if (ist != 0)            esp = get_rsp_from_tss(ist + 3);        else            esp = get_rsp_from_tss(dpl);        esp &= ~0xfLL; /* align stack */        ss = 0;        new_stack = 1;    } 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;        if (ist != 0)            esp = get_rsp_from_tss(ist + 3);        else            esp = ESP;        esp &= ~0xfLL; /* align stack */        dpl = cpl;    } else {        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        new_stack = 0; /* avoid warning */        esp = 0; /* avoid warning */    }    PUSHQ(esp, env->segs[R_SS].selector);    PUSHQ(esp, ESP);    PUSHQ(esp, compute_eflags());    PUSHQ(esp, env->segs[R_CS].selector);    PUSHQ(esp, old_eip);    if (has_error_code) {        PUSHQ(esp, error_code);    }        if (new_stack) {        ss = 0 | dpl;        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);    }    ESP = esp;    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);}#endifvoid helper_syscall(int next_eip_addend){    int selector;    if (!(env->efer & MSR_EFER_SCE)) {        raise_exception_err(EXCP06_ILLOP, 0);    }    selector = (env->star >> 32) & 0xffff;#ifdef TARGET_X86_64    if (env->hflags & HF_LMA_MASK) {        int code64;        ECX = env->eip + next_eip_addend;        env->regs[11] = compute_eflags();                code64 = env->hflags & HF_CS64_MASK;        cpu_x86_set_cpl(env, 0);        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,                            0, 0xffffffff,                                DESC_G_MASK | DESC_P_MASK |                               DESC_S_MASK |                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,                                0, 0xffffffff,                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                               DESC_S_MASK |                               DESC_W_MASK | DESC_A_MASK);        env->eflags &= ~env->fmask;        if (code64)            env->eip = env->lstar;        else            env->eip = env->cstar;    } else #endif    {        ECX = (uint32_t)(env->eip + next_eip_addend);                cpu_x86_set_cpl(env, 0);        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,                            0, 0xffffffff,                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                               DESC_S_MASK |                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc,                                0, 0xffffffff,                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                               DESC_S_MASK |                               DESC_W_MASK | DESC_A_MASK);        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);        env->eip = (uint32_t)env->star;    }}void helper_sysret(int dflag){    int cpl, selector;    if (!(env->efer & MSR_EFER_SCE)) {        raise_exception_err(EXCP06_ILLOP, 0);    }    cpl = env->hflags & HF_CPL_MASK;    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {        raise_exception_err(EXCP0D_GPF, 0);    }    selector = (env->star >> 48) & 0xffff;#ifdef TARGET_X86_64    if (env->hflags & HF_LMA_MASK) {        if (dflag == 2) {            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,                                    0, 0xffffffff,                                    DESC_G_MASK | DESC_P_MASK |                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |                                    DESC_L_MASK);            env->eip = ECX;        } else {            cpu_x86_load_seg_cache(env, R_CS, selector | 3,                                    0, 0xffffffff,                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);            env->eip = (uint32_t)ECX;        }        cpu_x86_load_seg_cache(env, R_SS, selector + 8,                                0, 0xffffffff,                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |                               DESC_W_MASK | DESC_A_MASK);        load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK |                     IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);        cpu_x86_set_cpl(env, 3);    } else #endif    {        cpu_x86_load_seg_cache(env, R_CS, selector | 3,                                0, 0xffffffff,                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);        env->eip = (uint32_t)ECX;        cpu_x86_load_seg_cache(env, R_SS, selector + 8,                                0, 0xffffffff,                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |                               DESC_W_MASK | DESC_A_MASK);        env->eflags |= IF_MASK;        cpu_x86_set_cpl(env, 3);    }#ifdef USE_KQEMU    if (kqemu_is_ok(env)) {        if (env->hflags & HF_LMA_MASK)            CC_OP = CC_OP_EFLAGS;        env->exception_index = -1;        cpu_loop_exit();    }#endif}/* real mode interrupt */static void do_interrupt_real(int intno, int is_int, int error_code,                              unsigned int next_eip){    SegmentCache *dt;    target_ulong ptr, ssp;    int selector;    uint32_t offset, esp;    uint32_t old_cs, old_eip;    /* real mode (simpler !) */    dt = &env->idt;    if (intno * 4 + 3 > dt->limit)        raise_exception_err(EXCP0D_GPF, intno * 8 + 2);    ptr = dt->base + intno * 4;    offset = lduw_kernel(ptr);    selector = lduw_kernel(ptr + 2);    esp = ESP;    ssp = env->segs[R_SS].base;    if (is_int)        old_eip = next_eip;    else        old_eip = env->eip;    old_cs = env->segs[R_CS].selector;    /* XXX: use SS segment size ? */    PUSHW(ssp, esp, 0xffff, compute_eflags());    PUSHW(ssp, esp, 0xffff, old_cs);    PUSHW(ssp, esp, 0xffff, old_eip);        /* update processor state */    ESP = (ESP & ~0xffff) | (esp & 0xffff);    env->eip = offset;    env->segs[R_CS].selector = selector;    env->segs[R_CS].base = (selector << 4);    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);}/* fake user mode interrupt */void do_interrupt_user(int intno, int is_int, int error_code,                        target_ulong next_eip){    SegmentCache *dt;    target_ulong ptr;    int dpl, cpl;    uint32_t e2;    dt = &env->idt;    ptr = dt->base + (intno * 8);    e2 = ldl_kernel(ptr + 4);        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);    /* Since we emulate only user space, we cannot do more than       exiting the emulation with the suitable exception and error       code */    if (is_int)        EIP = next_eip;}/* * Begin execution of an interruption. is_int is TRUE if coming from * the int instruction. next_eip is the EIP value AFTER the interrupt * instruction. It is only relevant if is_int is TRUE.   */void do_interrupt(int intno, int is_int, int error_code,                   target_ulong next_eip, int is_hw){    if (loglevel & CPU_LOG_INT) {        if ((env->cr[0] & CR0_PE_MASK)) {            static int count;            fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,                    count, intno, error_code, is_int,                    env->hflags & HF_CPL_MASK,                    env->segs[R_CS].selector, EIP,                    (int)env->segs[R_CS].base + EIP,                    env->segs[R_SS].selector, ESP);            if (intno == 0x0e) {                fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);            } else {                fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);            }            fprintf(logfile, "\n");            cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);#if 0            {                int i;                uint8_t *ptr;                fprintf(logfile, "       code=");                ptr = env->segs[R_CS].base + env->eip;                for(i = 0; i < 16; i++) {                    fprintf(logfile, " %02x", ldub(ptr + i));                }                fprintf(logfile, "\n");            }#endif            count++;        }    }    if (env->cr[0] & CR0_PE_MASK) {#if TARGET_X86_64        if (env->hflags & HF_LMA_MASK) {            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);        } else#endif        {            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);        }    } else {        do_interrupt_real(intno, is_int, error_code, next_eip);    }}/* * Signal an interruption. It is executed in the main CPU loop. * is_int is TRUE if coming from the int instruction. next_eip is the * EIP value AFTER the interrupt instruction. It is only relevant if * is_int is TRUE.   */void raise_interrupt(int intno, int is_int, int error_code,                      int next_eip_addend){    env->exception_index = intno;    env->error_code = error_code;    env->exception_is_int = is_int;    env->exception_next_eip = env->eip + next_eip_addend;    cpu_loop_exit();}/* same as raise_exception_err, but do not restore global registers */static void raise_exception_err_norestore(int exception_index, int error_code){    env->exception_index = exception_index;    env->error_code = error_code;    env->exception_is_int = 0;    env->exception_next_eip = 0;    longjmp(env->jmp_env, 1);}/* shortcuts to generate exceptions */void (raise_exception_err)(int exception_index, int error_code){    raise_interrupt(exception_index, 0, error_code, 0);}void raise_exception(int exception_index){    raise_interrupt(exception_index, 0, 0, 0);}/* SMM support */#if defined(CONFIG_USER_ONLY) void do_smm_enter(void){}void helper_rsm(void){}#else#ifdef TARGET_X86_64#define SMM_REVISION_ID 0x00020064

⌨️ 快捷键说明

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