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

📄 kqemu.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    }    /* we must restore the default rounding state */    asm volatile ("fninit");    fpuc = 0x037f | (env->fpuc & (3 << 10));    asm volatile("fldcw %0" : : "m" (fpuc));}static int do_syscall(CPUState *env,                      struct kqemu_cpu_state *kenv){    int selector;        selector = (env->star >> 32) & 0xffff;#ifdef __x86_64__    if (env->hflags & HF_LMA_MASK) {        env->regs[R_ECX] = kenv->next_eip;        env->regs[11] = env->eflags;        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 | 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 (env->hflags & HF_CS64_MASK)            env->eip = env->lstar;        else            env->eip = env->cstar;    } else #endif    {        env->regs[R_ECX] = (uint32_t)kenv->next_eip;                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;    }    return 2;}#ifdef CONFIG_PROFILER#define PC_REC_SIZE 1#define PC_REC_HASH_BITS 16#define PC_REC_HASH_SIZE (1 << PC_REC_HASH_BITS)typedef struct PCRecord {    unsigned long pc;    int64_t count;    struct PCRecord *next;} PCRecord;static PCRecord *pc_rec_hash[PC_REC_HASH_SIZE];static int nb_pc_records;static void kqemu_record_pc(unsigned long pc){    unsigned long h;    PCRecord **pr, *r;    h = pc / PC_REC_SIZE;    h = h ^ (h >> PC_REC_HASH_BITS);    h &= (PC_REC_HASH_SIZE - 1);    pr = &pc_rec_hash[h];    for(;;) {        r = *pr;        if (r == NULL)            break;        if (r->pc == pc) {            r->count++;            return;        }        pr = &r->next;    }    r = malloc(sizeof(PCRecord));    r->count = 1;    r->pc = pc;    r->next = NULL;    *pr = r;    nb_pc_records++;}static int pc_rec_cmp(const void *p1, const void *p2){    PCRecord *r1 = *(PCRecord **)p1;    PCRecord *r2 = *(PCRecord **)p2;    if (r1->count < r2->count)        return 1;    else if (r1->count == r2->count)        return 0;    else        return -1;}static void kqemu_record_flush(void){    PCRecord *r, *r_next;    int h;    for(h = 0; h < PC_REC_HASH_SIZE; h++) {        for(r = pc_rec_hash[h]; r != NULL; r = r_next) {            r_next = r->next;            free(r);        }        pc_rec_hash[h] = NULL;    }    nb_pc_records = 0;}void kqemu_record_dump(void){    PCRecord **pr, *r;    int i, h;    FILE *f;    int64_t total, sum;    pr = malloc(sizeof(PCRecord *) * nb_pc_records);    i = 0;    total = 0;    for(h = 0; h < PC_REC_HASH_SIZE; h++) {        for(r = pc_rec_hash[h]; r != NULL; r = r->next) {            pr[i++] = r;            total += r->count;        }    }    qsort(pr, nb_pc_records, sizeof(PCRecord *), pc_rec_cmp);        f = fopen("/tmp/kqemu.stats", "w");    if (!f) {        perror("/tmp/kqemu.stats");        exit(1);    }    fprintf(f, "total: %lld\n", total);    sum = 0;    for(i = 0; i < nb_pc_records; i++) {        r = pr[i];        sum += r->count;        fprintf(f, "%08lx: %lld %0.2f%% %0.2f%%\n",                 r->pc,                 r->count,                 (double)r->count / (double)total * 100.0,                (double)sum / (double)total * 100.0);    }    fclose(f);    free(pr);    kqemu_record_flush();}#endifint kqemu_cpu_exec(CPUState *env){    struct kqemu_cpu_state kcpu_state, *kenv = &kcpu_state;    int ret, cpl, i;#ifdef CONFIG_PROFILER    int64_t ti;#endif#ifdef _WIN32    DWORD temp;#endif#ifdef CONFIG_PROFILER    ti = profile_getclock();#endif#ifdef DEBUG    if (loglevel & CPU_LOG_INT) {        fprintf(logfile, "kqemu: cpu_exec: enter\n");        cpu_dump_state(env, logfile, fprintf, 0);    }#endif    memcpy(kenv->regs, env->regs, sizeof(kenv->regs));    kenv->eip = env->eip;    kenv->eflags = env->eflags;    memcpy(&kenv->segs, &env->segs, sizeof(env->segs));    memcpy(&kenv->ldt, &env->ldt, sizeof(env->ldt));    memcpy(&kenv->tr, &env->tr, sizeof(env->tr));    memcpy(&kenv->gdt, &env->gdt, sizeof(env->gdt));    memcpy(&kenv->idt, &env->idt, sizeof(env->idt));    kenv->cr0 = env->cr[0];    kenv->cr2 = env->cr[2];    kenv->cr3 = env->cr[3];    kenv->cr4 = env->cr[4];    kenv->a20_mask = env->a20_mask;#if KQEMU_VERSION >= 0x010100    kenv->efer = env->efer;#endif#if KQEMU_VERSION >= 0x010300    kenv->tsc_offset = 0;    kenv->star = env->star;    kenv->sysenter_cs = env->sysenter_cs;    kenv->sysenter_esp = env->sysenter_esp;    kenv->sysenter_eip = env->sysenter_eip;#ifdef __x86_64__    kenv->lstar = env->lstar;    kenv->cstar = env->cstar;    kenv->fmask = env->fmask;    kenv->kernelgsbase = env->kernelgsbase;#endif#endif    if (env->dr[7] & 0xff) {        kenv->dr7 = env->dr[7];        kenv->dr0 = env->dr[0];        kenv->dr1 = env->dr[1];        kenv->dr2 = env->dr[2];        kenv->dr3 = env->dr[3];    } else {        kenv->dr7 = 0;    }    kenv->dr6 = env->dr[6];    cpl = (env->hflags & HF_CPL_MASK);    kenv->cpl = cpl;    kenv->nb_pages_to_flush = nb_pages_to_flush;#if KQEMU_VERSION >= 0x010200    kenv->user_only = (env->kqemu_enabled == 1);    kenv->nb_ram_pages_to_update = nb_ram_pages_to_update;#endif    nb_ram_pages_to_update = 0;    #if KQEMU_VERSION >= 0x010300    kenv->nb_modified_ram_pages = nb_modified_ram_pages;#endif    kqemu_reset_modified_ram_pages();    if (env->cpuid_features & CPUID_FXSR)        restore_native_fp_fxrstor(env);    else        restore_native_fp_frstor(env);#ifdef _WIN32    if (DeviceIoControl(kqemu_fd, KQEMU_EXEC,                        kenv, sizeof(struct kqemu_cpu_state),                        kenv, sizeof(struct kqemu_cpu_state),                        &temp, NULL)) {        ret = kenv->retval;    } else {        ret = -1;    }#else#if KQEMU_VERSION >= 0x010100    ioctl(kqemu_fd, KQEMU_EXEC, kenv);    ret = kenv->retval;#else    ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);#endif#endif    if (env->cpuid_features & CPUID_FXSR)        save_native_fp_fxsave(env);    else        save_native_fp_fsave(env);    memcpy(env->regs, kenv->regs, sizeof(env->regs));    env->eip = kenv->eip;    env->eflags = kenv->eflags;    memcpy(env->segs, kenv->segs, sizeof(env->segs));    cpu_x86_set_cpl(env, kenv->cpl);    memcpy(&env->ldt, &kenv->ldt, sizeof(env->ldt));#if 0    /* no need to restore that */    memcpy(env->tr, kenv->tr, sizeof(env->tr));    memcpy(env->gdt, kenv->gdt, sizeof(env->gdt));    memcpy(env->idt, kenv->idt, sizeof(env->idt));    env->a20_mask = kenv->a20_mask;#endif    env->cr[0] = kenv->cr0;    env->cr[4] = kenv->cr4;    env->cr[3] = kenv->cr3;    env->cr[2] = kenv->cr2;    env->dr[6] = kenv->dr6;#if KQEMU_VERSION >= 0x010300#ifdef __x86_64__    env->kernelgsbase = kenv->kernelgsbase;#endif#endif    /* flush pages as indicated by kqemu */    if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {        tlb_flush(env, 1);    } else {        for(i = 0; i < kenv->nb_pages_to_flush; i++) {            tlb_flush_page(env, pages_to_flush[i]);        }    }    nb_pages_to_flush = 0;#ifdef CONFIG_PROFILER    kqemu_time += profile_getclock() - ti;    kqemu_exec_count++;#endif#if KQEMU_VERSION >= 0x010200    if (kenv->nb_ram_pages_to_update > 0) {        cpu_tlb_update_dirty(env);    }#endif#if KQEMU_VERSION >= 0x010300    if (kenv->nb_modified_ram_pages > 0) {        for(i = 0; i < kenv->nb_modified_ram_pages; i++) {            unsigned long addr;            addr = modified_ram_pages[i];            tb_invalidate_phys_page_range(addr, addr + TARGET_PAGE_SIZE, 0);        }    }#endif    /* restore the hidden flags */    {        unsigned int new_hflags;#ifdef TARGET_X86_64        if ((env->hflags & HF_LMA_MASK) &&             (env->segs[R_CS].flags & DESC_L_MASK)) {            /* long mode */            new_hflags = HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;        } else#endif        {            /* legacy / compatibility case */            new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)                >> (DESC_B_SHIFT - HF_CS32_SHIFT);            new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)                >> (DESC_B_SHIFT - HF_SS32_SHIFT);            if (!(env->cr[0] & CR0_PE_MASK) ||                    (env->eflags & VM_MASK) ||                   !(env->hflags & HF_CS32_MASK)) {                /* XXX: try to avoid this test. The problem comes from the                   fact that is real mode or vm86 mode we only modify the                   'base' and 'selector' fields of the segment cache to go                   faster. A solution may be to force addseg to one in                   translate-i386.c. */                new_hflags |= HF_ADDSEG_MASK;            } else {                new_hflags |= ((env->segs[R_DS].base |                                 env->segs[R_ES].base |                                env->segs[R_SS].base) != 0) <<                     HF_ADDSEG_SHIFT;            }        }        env->hflags = (env->hflags &            ~(HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)) |            new_hflags;    }    /* update FPU flags */    env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) |        ((env->cr[0] << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK));    if (env->cr[4] & CR4_OSFXSR_MASK)        env->hflags |= HF_OSFXSR_MASK;    else        env->hflags &= ~HF_OSFXSR_MASK;        #ifdef DEBUG    if (loglevel & CPU_LOG_INT) {        fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);    }#endif    if (ret == KQEMU_RET_SYSCALL) {        /* syscall instruction */        return do_syscall(env, kenv);    } else     if ((ret & 0xff00) == KQEMU_RET_INT) {        env->exception_index = ret & 0xff;        env->error_code = 0;        env->exception_is_int = 1;        env->exception_next_eip = kenv->next_eip;#ifdef CONFIG_PROFILER        kqemu_ret_int_count++;#endif#ifdef DEBUG        if (loglevel & CPU_LOG_INT) {            fprintf(logfile, "kqemu: interrupt v=%02x:\n",                     env->exception_index);            cpu_dump_state(env, logfile, fprintf, 0);        }#endif        return 1;    } else if ((ret & 0xff00) == KQEMU_RET_EXCEPTION) {        env->exception_index = ret & 0xff;        env->error_code = kenv->error_code;        env->exception_is_int = 0;        env->exception_next_eip = 0;#ifdef CONFIG_PROFILER        kqemu_ret_excp_count++;#endif#ifdef DEBUG        if (loglevel & CPU_LOG_INT) {            fprintf(logfile, "kqemu: exception v=%02x e=%04x:\n",                    env->exception_index, env->error_code);            cpu_dump_state(env, logfile, fprintf, 0);        }#endif        return 1;    } else if (ret == KQEMU_RET_INTR) {#ifdef CONFIG_PROFILER        kqemu_ret_intr_count++;#endif#ifdef DEBUG        if (loglevel & CPU_LOG_INT) {            cpu_dump_state(env, logfile, fprintf, 0);        }#endif        return 0;    } else if (ret == KQEMU_RET_SOFTMMU) { #ifdef CONFIG_PROFILER        {            unsigned long pc = env->eip + env->segs[R_CS].base;            kqemu_record_pc(pc);        }#endif#ifdef DEBUG        if (loglevel & CPU_LOG_INT) {            cpu_dump_state(env, logfile, fprintf, 0);        }#endif        return 2;    } else {        cpu_dump_state(env, stderr, fprintf, 0);        fprintf(stderr, "Unsupported return value: 0x%x\n", ret);        exit(1);    }    return 0;}void kqemu_cpu_interrupt(CPUState *env){#if defined(_WIN32) && KQEMU_VERSION >= 0x010101    /* cancelling the I/O request causes KQEMU to finish executing the        current block and successfully returning. */    CancelIo(kqemu_fd);#endif}#endif

⌨️ 快捷键说明

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