📄 main.c.svn-base
字号:
/* * qemu user main * * Copyright (c) 2003-2008 Fabrice Bellard * * 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 "qemu.h"#define DEBUG_LOGFILE "/tmp/qemu.log"static const char *interp_prefix = CONFIG_QEMU_PREFIX;const char *qemu_uname_release = CONFIG_UNAME_RELEASE;#if defined(__i386__) && !defined(CONFIG_STATIC)/* Force usage of an ELF interpreter even if it is an ELF shared object ! */const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";#endif/* for recent libc, we add these dummy symbols which are not declared when generating a linked object (bug in ld ?) */#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)asm(".globl __preinit_array_start\n" ".globl __preinit_array_end\n" ".globl __init_array_start\n" ".globl __init_array_end\n" ".globl __fini_array_start\n" ".globl __fini_array_end\n" ".section \".rodata\"\n" "__preinit_array_start:\n" "__preinit_array_end:\n" "__init_array_start:\n" "__init_array_end:\n" "__fini_array_start:\n" "__fini_array_end:\n" ".long 0\n");#endif/* 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 x86_stack_size = 512 * 1024;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;}/* timers for rdtsc */#if 0static uint64_t emu_time;int64_t cpu_get_real_ticks(void){ return emu_time++;}#endif#ifdef TARGET_I386/***********************************************************//* CPUX86 core interface */void cpu_smm_update(CPUState *env){}uint64_t cpu_get_tsc(CPUX86State *env){ return cpu_get_real_ticks();}static void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags){ unsigned int e1, e2; uint32_t *p; e1 = (addr << 16) | (limit & 0xffff); e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); e2 |= flags; p = ptr; p[0] = tswapl(e1); p[1] = tswapl(e2);}#if TARGET_X86_64uint64_t idt_table[512];static void set_gate64(void *ptr, unsigned int type, unsigned int dpl, uint64_t addr, unsigned int sel){ uint32_t *p, e1, e2; e1 = (addr & 0xffff) | (sel << 16); e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); p = ptr; p[0] = tswap32(e1); p[1] = tswap32(e2); p[2] = tswap32(addr >> 32); p[3] = 0;}/* only dpl matters as we do only user space emulation */static void set_idt(int n, unsigned int dpl){ set_gate64(idt_table + n * 2, 0, dpl, 0, 0);}#elseuint64_t idt_table[256];static void set_gate(void *ptr, unsigned int type, unsigned int dpl, uint32_t addr, unsigned int sel){ uint32_t *p, e1, e2; e1 = (addr & 0xffff) | (sel << 16); e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); p = ptr; p[0] = tswap32(e1); p[1] = tswap32(e2);}/* only dpl matters as we do only user space emulation */static void set_idt(int n, unsigned int dpl){ set_gate(idt_table + n, 0, dpl, 0, 0);}#endifvoid cpu_loop(CPUX86State *env){ int trapnr; abi_ulong pc; target_siginfo_t info; for(;;) { trapnr = cpu_x86_exec(env); switch(trapnr) { case 0x80: /* linux syscall from int $0x80 */ env->regs[R_EAX] = do_syscall(env, env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP]); break;#ifndef TARGET_ABI32 case EXCP_SYSCALL: /* linux syscall from syscall intruction */ env->regs[R_EAX] = do_syscall(env, env->regs[R_EAX], env->regs[R_EDI], env->regs[R_ESI], env->regs[R_EDX], env->regs[10], env->regs[8], env->regs[9]); env->eip = env->exception_next_eip; break;#endif case EXCP0B_NOSEG: case EXCP0C_STACK: info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = TARGET_SI_KERNEL; info._sifields._sigfault._addr = 0; queue_signal(info.si_signo, &info); break; case EXCP0D_GPF: /* XXX: potential problem if ABI32 */#ifndef TARGET_X86_64 if (env->eflags & VM_MASK) { handle_vm86_fault(env); } else#endif { info.si_signo = SIGSEGV; info.si_errno = 0; info.si_code = TARGET_SI_KERNEL; info._sifields._sigfault._addr = 0; queue_signal(info.si_signo, &info); } break; case EXCP0E_PAGE: info.si_signo = SIGSEGV; info.si_errno = 0; if (!(env->error_code & 1)) info.si_code = TARGET_SEGV_MAPERR; else info.si_code = TARGET_SEGV_ACCERR; info._sifields._sigfault._addr = env->cr[2]; queue_signal(info.si_signo, &info); break; case EXCP00_DIVZ:#ifndef TARGET_X86_64 if (env->eflags & VM_MASK) { handle_vm86_trap(env, trapnr); } else#endif { /* division by zero */ info.si_signo = SIGFPE; info.si_errno = 0; info.si_code = TARGET_FPE_INTDIV; info._sifields._sigfault._addr = env->eip; queue_signal(info.si_signo, &info); } break; case EXCP01_SSTP: case EXCP03_INT3:#ifndef TARGET_X86_64 if (env->eflags & VM_MASK) { handle_vm86_trap(env, trapnr); } else#endif { info.si_signo = SIGTRAP; info.si_errno = 0; if (trapnr == EXCP01_SSTP) { info.si_code = TARGET_TRAP_BRKPT; info._sifields._sigfault._addr = env->eip; } else { info.si_code = TARGET_SI_KERNEL; info._sifields._sigfault._addr = 0; } queue_signal(info.si_signo, &info); } break; case EXCP04_INTO: case EXCP05_BOUND:#ifndef TARGET_X86_64 if (env->eflags & VM_MASK) { handle_vm86_trap(env, trapnr); } else#endif { info.si_signo = SIGSEGV; info.si_errno = 0; info.si_code = TARGET_SI_KERNEL; info._sifields._sigfault._addr = 0; queue_signal(info.si_signo, &info); } break; case EXCP06_ILLOP: info.si_signo = SIGILL; info.si_errno = 0; info.si_code = TARGET_ILL_ILLOPN; info._sifields._sigfault._addr = env->eip; queue_signal(info.si_signo, &info); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; case EXCP_DEBUG: { int sig; sig = gdb_handlesig (env, TARGET_SIGTRAP); if (sig) { info.si_signo = sig; info.si_errno = 0; info.si_code = TARGET_TRAP_BRKPT; queue_signal(info.si_signo, &info); } } break; default: pc = env->segs[R_CS].base + env->eip; fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", (long)pc, trapnr); abort(); } process_pending_signals(env); }}#endif#ifdef TARGET_ARM/* XXX: find a better solution */extern void tb_invalidate_page_range(abi_ulong start, abi_ulong end);static void arm_cache_flush(abi_ulong start, abi_ulong last){ abi_ulong addr, last1; if (last < start) return; addr = start; for(;;) { last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1; if (last1 > last) last1 = last; tb_invalidate_page_range(addr, last1 + 1); if (last1 == last) break; addr = last1 + 1; }}void cpu_loop(CPUARMState *env){ int trapnr; unsigned int n, insn; target_siginfo_t info; uint32_t addr; for(;;) { trapnr = cpu_arm_exec(env); switch(trapnr) { case EXCP_UDEF: { TaskState *ts = env->opaque; uint32_t opcode; /* we handle the FPU emulation here, as Linux */ /* we get the opcode */ /* FIXME - what to do if get_user() fails? */ get_user_u32(opcode, env->regs[15]); if (EmulateAll(opcode, &ts->fpa, env) == 0) { info.si_signo = SIGILL; info.si_errno = 0; info.si_code = TARGET_ILL_ILLOPN; info._sifields._sigfault._addr = env->regs[15]; queue_signal(info.si_signo, &info);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -