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

📄 main.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  qemu user main * *  Copyright (c) 2003 Fabrice Bellard *  Copyright (c) 2006 Pierre d'Herbemont * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/syscall.h>#include <sys/mman.h>#include "qemu.h"#define DEBUG_LOGFILE "/tmp/qemu.log"#ifdef __APPLE__#include <crt_externs.h># define environ  (*_NSGetEnviron())#endif#include <mach/mach_init.h>#include <mach/vm_map.h>const char *interp_prefix = "";asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so   we allocate a bigger stack. Need a better solution, for example   by remapping the process stack directly at the right place */unsigned long stack_size = 512 * 1024;void qerror(const char *fmt, ...){    va_list ap;    va_start(ap, fmt);    vfprintf(stderr, fmt, ap);    va_end(ap);    fprintf(stderr, "\n");    exit(1);}void gemu_log(const char *fmt, ...){    va_list ap;    va_start(ap, fmt);    vfprintf(stderr, fmt, ap);    va_end(ap);}void cpu_outb(CPUState *env, int addr, int val){    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);}void cpu_outw(CPUState *env, int addr, int val){    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);}void cpu_outl(CPUState *env, int addr, int val){    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);}int cpu_inb(CPUState *env, int addr){    fprintf(stderr, "inb: port=0x%04x\n", addr);    return 0;}int cpu_inw(CPUState *env, int addr){    fprintf(stderr, "inw: port=0x%04x\n", addr);    return 0;}int cpu_inl(CPUState *env, int addr){    fprintf(stderr, "inl: port=0x%04x\n", addr);    return 0;}int cpu_get_pic_interrupt(CPUState *env){    return -1;}#ifdef TARGET_PPCstatic inline uint64_t cpu_ppc_get_tb (CPUState *env){    /* TO FIX */    return 0;}uint32_t cpu_ppc_load_tbl (CPUState *env){    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;}uint32_t cpu_ppc_load_tbu (CPUState *env){    return cpu_ppc_get_tb(env) >> 32;}static void cpu_ppc_store_tb (CPUState *env, uint64_t value){    /* TO FIX */}void cpu_ppc_store_tbu (CPUState *env, uint32_t value){    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));}void cpu_ppc_store_tbl (CPUState *env, uint32_t value){    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);}uint32_t cpu_ppc_load_decr (CPUState *env){    /* TO FIX */    return -1;}void cpu_ppc_store_decr (CPUState *env, uint32_t value){    /* TO FIX */}void cpu_loop(CPUPPCState *env){    int trapnr;    uint32_t ret;    target_siginfo_t info;    for(;;) {        trapnr = cpu_ppc_exec(env);        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&            trapnr != EXCP_TRACE) {            if (loglevel > 0) {                cpu_dump_state(env, logfile, fprintf, 0);            }        }        switch(trapnr) {        case EXCP_NONE:            break;        case EXCP_SYSCALL_USER:            /* system call */            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)                ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],                                      env->gpr[5], env->gpr[6], env->gpr[7],                                      env->gpr[8], env->gpr[9], env->gpr[10]*/);            else if(((int)env->gpr[0])<0)                ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],                                      env->gpr[5], env->gpr[6], env->gpr[7],                                      env->gpr[8], env->gpr[9], env->gpr[10]);            else                ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],                                        env->gpr[5], env->gpr[6], env->gpr[7],                                        env->gpr[8], env->gpr[9], env->gpr[10]);            /* Unix syscall error signaling */            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)            {                if( (int)ret < 0 )                    env->nip += 0;                else                    env->nip += 4;            }            /* Return value */            env->gpr[3] = ret;            break;        case EXCP_RESET:            /* Should not happen ! */            fprintf(stderr, "RESET asked... Stop emulation\n");            if (loglevel)                fprintf(logfile, "RESET asked... Stop emulation\n");                abort();        case EXCP_MACHINE_CHECK:            fprintf(stderr, "Machine check exeption...  Stop emulation\n");            if (loglevel)                fprintf(logfile, "RESET asked... Stop emulation\n");                info.si_signo = SIGBUS;            info.si_errno = 0;            info.si_code = BUS_OBJERR;            info.si_addr = (void*)(env->nip - 4);            queue_signal(info.si_signo, &info);        case EXCP_DSI:#ifndef DAR/* To deal with multiple qemu header version as host for the darwin-user code */# define DAR SPR_DAR#endif            fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);            if (loglevel) {                fprintf(logfile, "Invalid data memory access: 0x%08x\n",                        env->spr[DAR]);            }            /* Handle this via the gdb */            gdb_handlesig (env, SIGSEGV);            info.si_addr = (void*)env->nip;            queue_signal(info.si_signo, &info);            break;        case EXCP_ISI:            fprintf(stderr, "Invalid instruction fetch\n");            if (loglevel)                fprintf(logfile, "Invalid instruction fetch\n");            /* Handle this via the gdb */            gdb_handlesig (env, SIGSEGV);            info.si_addr = (void*)(env->nip - 4);            queue_signal(info.si_signo, &info);            break;        case EXCP_EXTERNAL:            /* Should not happen ! */            fprintf(stderr, "External interruption... Stop emulation\n");            if (loglevel)                fprintf(logfile, "External interruption... Stop emulation\n");                abort();        case EXCP_ALIGN:            fprintf(stderr, "Invalid unaligned memory access\n");            if (loglevel)                fprintf(logfile, "Invalid unaligned memory access\n");                info.si_signo = SIGBUS;            info.si_errno = 0;            info.si_code = BUS_ADRALN;            info.si_addr = (void*)(env->nip - 4);            queue_signal(info.si_signo, &info);            break;        case EXCP_PROGRAM:            switch (env->error_code & ~0xF) {                case EXCP_FP:                    fprintf(stderr, "Program exception\n");                    if (loglevel)                        fprintf(logfile, "Program exception\n");                        /* Set FX */                        env->fpscr[7] |= 0x8;                    /* Finally, update FEX */                    if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &                        ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))                        env->fpscr[7] |= 0x4;                        info.si_signo = SIGFPE;                    info.si_errno = 0;                    switch (env->error_code & 0xF) {                        case EXCP_FP_OX:                            info.si_code = FPE_FLTOVF;                            break;                        case EXCP_FP_UX:                            info.si_code = FPE_FLTUND;                            break;                        case EXCP_FP_ZX:                        case EXCP_FP_VXZDZ:                            info.si_code = FPE_FLTDIV;                            break;                        case EXCP_FP_XX:                            info.si_code = FPE_FLTRES;                            break;                        case EXCP_FP_VXSOFT:                            info.si_code = FPE_FLTINV;                            break;                        case EXCP_FP_VXNAN:                        case EXCP_FP_VXISI:                        case EXCP_FP_VXIDI:                        case EXCP_FP_VXIMZ:                        case EXCP_FP_VXVC:                        case EXCP_FP_VXSQRT:                        case EXCP_FP_VXCVI:                            info.si_code = FPE_FLTSUB;                            break;                        default:                            fprintf(stderr, "Unknown floating point exception "                                    "(%02x)\n", env->error_code);                            if (loglevel) {                                fprintf(logfile, "Unknown floating point exception "                                        "(%02x)\n", env->error_code & 0xF);                            }                    }                        break;                case EXCP_INVAL:                    fprintf(stderr, "Invalid instruction\n");                    if (loglevel)                        fprintf(logfile, "Invalid instruction\n");                        info.si_signo = SIGILL;                    info.si_errno = 0;                    switch (env->error_code & 0xF) {                        case EXCP_INVAL_INVAL:                            info.si_code = ILL_ILLOPC;                            break;                        case EXCP_INVAL_LSWX:                            info.si_code = ILL_ILLOPN;                            break;                        case EXCP_INVAL_SPR:                            info.si_code = ILL_PRVREG;                            break;                        case EXCP_INVAL_FP:                            info.si_code = ILL_COPROC;                            break;                        default:                            fprintf(stderr, "Unknown invalid operation (%02x)\n",                                    env->error_code & 0xF);                            if (loglevel) {                                fprintf(logfile, "Unknown invalid operation (%02x)\n",                                        env->error_code & 0xF);                            }                                info.si_code = ILL_ILLADR;                            break;                    }                        /* Handle this via the gdb */                        gdb_handlesig (env, SIGSEGV);                    break;                case EXCP_PRIV:                    fprintf(stderr, "Privilege violation\n");                    if (loglevel)                        fprintf(logfile, "Privilege violation\n");                        info.si_signo = SIGILL;                    info.si_errno = 0;                    switch (env->error_code & 0xF) {                        case EXCP_PRIV_OPC:                            info.si_code = ILL_PRVOPC;                            break;                        case EXCP_PRIV_REG:                            info.si_code = ILL_PRVREG;                            break;                        default:                            fprintf(stderr, "Unknown privilege violation (%02x)\n",                                    env->error_code & 0xF);                            info.si_code = ILL_PRVOPC;                            break;                    }                        break;                case EXCP_TRAP:                    fprintf(stderr, "Tried to call a TRAP\n");                    if (loglevel)                        fprintf(logfile, "Tried to call a TRAP\n");                        abort();                default:                    /* Should not happen ! */                    fprintf(stderr, "Unknown program exception (%02x)\n",                            env->error_code);                    if (loglevel) {                        fprintf(logfile, "Unknwon program exception (%02x)\n",                                env->error_code);                    }                        abort();            }            info.si_addr = (void*)(env->nip - 4);            queue_signal(info.si_signo, &info);            break;        case EXCP_NO_FP:            fprintf(stderr, "No floating point allowed\n");            if (loglevel)                fprintf(logfile, "No floating point allowed\n");                info.si_signo = SIGILL;            info.si_errno = 0;            info.si_code = ILL_COPROC;            info.si_addr = (void*)(env->nip - 4);            queue_signal(info.si_signo, &info);            break;        case EXCP_DECR:            /* Should not happen ! */            fprintf(stderr, "Decrementer exception\n");            if (loglevel)                fprintf(logfile, "Decrementer exception\n");            abort();        case EXCP_TRACE:            /* Pass to gdb: we use this to trace execution */            gdb_handlesig (env, SIGTRAP);            break;        case EXCP_FP_ASSIST:            /* Should not happen ! */            fprintf(stderr, "Floating point assist exception\n");            if (loglevel)                fprintf(logfile, "Floating point assist exception\n");            abort();        case EXCP_MTMSR:            /* We reloaded the msr, just go on */            if (msr_pr == 0) {                fprintf(stderr, "Tried to go into supervisor mode !\n");                if (loglevel)                    fprintf(logfile, "Tried to go into supervisor mode !\n");                abort();            }            break;        case EXCP_BRANCH:            /* We stopped because of a jump... */            break;        case EXCP_INTERRUPT:            /* Don't know why this should ever happen... */            fprintf(stderr, "EXCP_INTERRUPT\n");            break;        case EXCP_DEBUG:            gdb_handlesig (env, SIGTRAP);            break;        default:            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",                    trapnr);            if (loglevel) {                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "                        "0x%02x - aborting\n", trapnr, env->error_code);            }                abort();        }        process_pending_signals(env);    }}#endif#ifdef TARGET_I386/***********************************************************//* CPUX86 core interface */uint64_t cpu_get_tsc(CPUX86State *env){    return cpu_get_real_ticks();}voidwrite_dt(void *ptr, unsigned long addr, unsigned long limit,                     int flags){    unsigned int e1, e2;    e1 = (addr << 16) | (limit & 0xffff);    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);    e2 |= flags;    stl((uint8_t *)ptr, e1);    stl((uint8_t *)ptr + 4, e2);}static void set_gate(void *ptr, unsigned int type, unsigned int dpl,                     unsigned long addr, unsigned int sel){    unsigned int e1, e2;    e1 = (addr & 0xffff) | (sel << 16);    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);

⌨️ 快捷键说明

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