File:  [Qemu by Fabrice Bellard] / qemu / bsd-user / main.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:42:44 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

    1: /*
    2:  *  qemu user main
    3:  *
    4:  *  Copyright (c) 2003-2008 Fabrice Bellard
    5:  *
    6:  *  This program is free software; you can redistribute it and/or modify
    7:  *  it under the terms of the GNU General Public License as published by
    8:  *  the Free Software Foundation; either version 2 of the License, or
    9:  *  (at your option) any later version.
   10:  *
   11:  *  This program is distributed in the hope that it will be useful,
   12:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14:  *  GNU General Public License for more details.
   15:  *
   16:  *  You should have received a copy of the GNU General Public License
   17:  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
   18:  */
   19: #include <stdlib.h>
   20: #include <stdio.h>
   21: #include <stdarg.h>
   22: #include <string.h>
   23: #include <errno.h>
   24: #include <unistd.h>
   25: #include <machine/trap.h>
   26: #include <sys/types.h>
   27: #include <sys/mman.h>
   28: 
   29: #include "qemu.h"
   30: #include "qemu-common.h"
   31: /* For tb_lock */
   32: #include "exec-all.h"
   33: #include "tcg.h"
   34: #include "qemu-timer.h"
   35: #include "envlist.h"
   36: 
   37: #define DEBUG_LOGFILE "/tmp/qemu.log"
   38: 
   39: int singlestep;
   40: #if defined(CONFIG_USE_GUEST_BASE)
   41: unsigned long mmap_min_addr;
   42: unsigned long guest_base;
   43: int have_guest_base;
   44: #endif
   45: 
   46: static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
   47: const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
   48: extern char **environ;
   49: enum BSDType bsd_type;
   50: 
   51: /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
   52:    we allocate a bigger stack. Need a better solution, for example
   53:    by remapping the process stack directly at the right place */
   54: unsigned long x86_stack_size = 512 * 1024;
   55: 
   56: void gemu_log(const char *fmt, ...)
   57: {
   58:     va_list ap;
   59: 
   60:     va_start(ap, fmt);
   61:     vfprintf(stderr, fmt, ap);
   62:     va_end(ap);
   63: }
   64: 
   65: #if defined(TARGET_I386)
   66: int cpu_get_pic_interrupt(CPUState *env)
   67: {
   68:     return -1;
   69: }
   70: #endif
   71: 
   72: /* These are no-ops because we are not threadsafe.  */
   73: static inline void cpu_exec_start(CPUState *env)
   74: {
   75: }
   76: 
   77: static inline void cpu_exec_end(CPUState *env)
   78: {
   79: }
   80: 
   81: static inline void start_exclusive(void)
   82: {
   83: }
   84: 
   85: static inline void end_exclusive(void)
   86: {
   87: }
   88: 
   89: void fork_start(void)
   90: {
   91: }
   92: 
   93: void fork_end(int child)
   94: {
   95:     if (child) {
   96:         gdbserver_fork(thread_env);
   97:     }
   98: }
   99: 
  100: void cpu_list_lock(void)
  101: {
  102: }
  103: 
  104: void cpu_list_unlock(void)
  105: {
  106: }
  107: 
  108: #ifdef TARGET_I386
  109: /***********************************************************/
  110: /* CPUX86 core interface */
  111: 
  112: void cpu_smm_update(CPUState *env)
  113: {
  114: }
  115: 
  116: uint64_t cpu_get_tsc(CPUX86State *env)
  117: {
  118:     return cpu_get_real_ticks();
  119: }
  120: 
  121: static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
  122:                      int flags)
  123: {
  124:     unsigned int e1, e2;
  125:     uint32_t *p;
  126:     e1 = (addr << 16) | (limit & 0xffff);
  127:     e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
  128:     e2 |= flags;
  129:     p = ptr;
  130:     p[0] = tswap32(e1);
  131:     p[1] = tswap32(e2);
  132: }
  133: 
  134: static uint64_t *idt_table;
  135: #ifdef TARGET_X86_64
  136: static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
  137:                        uint64_t addr, unsigned int sel)
  138: {
  139:     uint32_t *p, e1, e2;
  140:     e1 = (addr & 0xffff) | (sel << 16);
  141:     e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
  142:     p = ptr;
  143:     p[0] = tswap32(e1);
  144:     p[1] = tswap32(e2);
  145:     p[2] = tswap32(addr >> 32);
  146:     p[3] = 0;
  147: }
  148: /* only dpl matters as we do only user space emulation */
  149: static void set_idt(int n, unsigned int dpl)
  150: {
  151:     set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
  152: }
  153: #else
  154: static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
  155:                      uint32_t addr, unsigned int sel)
  156: {
  157:     uint32_t *p, e1, e2;
  158:     e1 = (addr & 0xffff) | (sel << 16);
  159:     e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
  160:     p = ptr;
  161:     p[0] = tswap32(e1);
  162:     p[1] = tswap32(e2);
  163: }
  164: 
  165: /* only dpl matters as we do only user space emulation */
  166: static void set_idt(int n, unsigned int dpl)
  167: {
  168:     set_gate(idt_table + n, 0, dpl, 0, 0);
  169: }
  170: #endif
  171: 
  172: void cpu_loop(CPUX86State *env)
  173: {
  174:     int trapnr;
  175:     abi_ulong pc;
  176:     //target_siginfo_t info;
  177: 
  178:     for(;;) {
  179:         trapnr = cpu_x86_exec(env);
  180:         switch(trapnr) {
  181:         case 0x80:
  182:             /* syscall from int $0x80 */
  183:             if (bsd_type == target_freebsd) {
  184:                 abi_ulong params = (abi_ulong) env->regs[R_ESP] +
  185:                     sizeof(int32_t);
  186:                 int32_t syscall_nr = env->regs[R_EAX];
  187:                 int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
  188: 
  189:                 if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
  190:                     get_user_s32(syscall_nr, params);
  191:                     params += sizeof(int32_t);
  192:                 } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
  193:                     get_user_s32(syscall_nr, params);
  194:                     params += sizeof(int64_t);
  195:                 }
  196:                 get_user_s32(arg1, params);
  197:                 params += sizeof(int32_t);
  198:                 get_user_s32(arg2, params);
  199:                 params += sizeof(int32_t);
  200:                 get_user_s32(arg3, params);
  201:                 params += sizeof(int32_t);
  202:                 get_user_s32(arg4, params);
  203:                 params += sizeof(int32_t);
  204:                 get_user_s32(arg5, params);
  205:                 params += sizeof(int32_t);
  206:                 get_user_s32(arg6, params);
  207:                 params += sizeof(int32_t);
  208:                 get_user_s32(arg7, params);
  209:                 params += sizeof(int32_t);
  210:                 get_user_s32(arg8, params);
  211:                 env->regs[R_EAX] = do_freebsd_syscall(env,
  212:                                                       syscall_nr,
  213:                                                       arg1,
  214:                                                       arg2,
  215:                                                       arg3,
  216:                                                       arg4,
  217:                                                       arg5,
  218:                                                       arg6,
  219:                                                       arg7,
  220:                                                       arg8);
  221:             } else { //if (bsd_type == target_openbsd)
  222:                 env->regs[R_EAX] = do_openbsd_syscall(env,
  223:                                                       env->regs[R_EAX],
  224:                                                       env->regs[R_EBX],
  225:                                                       env->regs[R_ECX],
  226:                                                       env->regs[R_EDX],
  227:                                                       env->regs[R_ESI],
  228:                                                       env->regs[R_EDI],
  229:                                                       env->regs[R_EBP]);
  230:             }
  231:             if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
  232:                 env->regs[R_EAX] = -env->regs[R_EAX];
  233:                 env->eflags |= CC_C;
  234:             } else {
  235:                 env->eflags &= ~CC_C;
  236:             }
  237:             break;
  238: #ifndef TARGET_ABI32
  239:         case EXCP_SYSCALL:
  240:             /* syscall from syscall intruction */
  241:             if (bsd_type == target_freebsd)
  242:                 env->regs[R_EAX] = do_freebsd_syscall(env,
  243:                                                       env->regs[R_EAX],
  244:                                                       env->regs[R_EDI],
  245:                                                       env->regs[R_ESI],
  246:                                                       env->regs[R_EDX],
  247:                                                       env->regs[R_ECX],
  248:                                                       env->regs[8],
  249:                                                       env->regs[9], 0, 0);
  250:             else { //if (bsd_type == target_openbsd)
  251:                 env->regs[R_EAX] = do_openbsd_syscall(env,
  252:                                                       env->regs[R_EAX],
  253:                                                       env->regs[R_EDI],
  254:                                                       env->regs[R_ESI],
  255:                                                       env->regs[R_EDX],
  256:                                                       env->regs[10],
  257:                                                       env->regs[8],
  258:                                                       env->regs[9]);
  259:             }
  260:             env->eip = env->exception_next_eip;
  261:             if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
  262:                 env->regs[R_EAX] = -env->regs[R_EAX];
  263:                 env->eflags |= CC_C;
  264:             } else {
  265:                 env->eflags &= ~CC_C;
  266:             }
  267:             break;
  268: #endif
  269: #if 0
  270:         case EXCP0B_NOSEG:
  271:         case EXCP0C_STACK:
  272:             info.si_signo = SIGBUS;
  273:             info.si_errno = 0;
  274:             info.si_code = TARGET_SI_KERNEL;
  275:             info._sifields._sigfault._addr = 0;
  276:             queue_signal(env, info.si_signo, &info);
  277:             break;
  278:         case EXCP0D_GPF:
  279:             /* XXX: potential problem if ABI32 */
  280: #ifndef TARGET_X86_64
  281:             if (env->eflags & VM_MASK) {
  282:                 handle_vm86_fault(env);
  283:             } else
  284: #endif
  285:             {
  286:                 info.si_signo = SIGSEGV;
  287:                 info.si_errno = 0;
  288:                 info.si_code = TARGET_SI_KERNEL;
  289:                 info._sifields._sigfault._addr = 0;
  290:                 queue_signal(env, info.si_signo, &info);
  291:             }
  292:             break;
  293:         case EXCP0E_PAGE:
  294:             info.si_signo = SIGSEGV;
  295:             info.si_errno = 0;
  296:             if (!(env->error_code & 1))
  297:                 info.si_code = TARGET_SEGV_MAPERR;
  298:             else
  299:                 info.si_code = TARGET_SEGV_ACCERR;
  300:             info._sifields._sigfault._addr = env->cr[2];
  301:             queue_signal(env, info.si_signo, &info);
  302:             break;
  303:         case EXCP00_DIVZ:
  304: #ifndef TARGET_X86_64
  305:             if (env->eflags & VM_MASK) {
  306:                 handle_vm86_trap(env, trapnr);
  307:             } else
  308: #endif
  309:             {
  310:                 /* division by zero */
  311:                 info.si_signo = SIGFPE;
  312:                 info.si_errno = 0;
  313:                 info.si_code = TARGET_FPE_INTDIV;
  314:                 info._sifields._sigfault._addr = env->eip;
  315:                 queue_signal(env, info.si_signo, &info);
  316:             }
  317:             break;
  318:         case EXCP01_DB:
  319:         case EXCP03_INT3:
  320: #ifndef TARGET_X86_64
  321:             if (env->eflags & VM_MASK) {
  322:                 handle_vm86_trap(env, trapnr);
  323:             } else
  324: #endif
  325:             {
  326:                 info.si_signo = SIGTRAP;
  327:                 info.si_errno = 0;
  328:                 if (trapnr == EXCP01_DB) {
  329:                     info.si_code = TARGET_TRAP_BRKPT;
  330:                     info._sifields._sigfault._addr = env->eip;
  331:                 } else {
  332:                     info.si_code = TARGET_SI_KERNEL;
  333:                     info._sifields._sigfault._addr = 0;
  334:                 }
  335:                 queue_signal(env, info.si_signo, &info);
  336:             }
  337:             break;
  338:         case EXCP04_INTO:
  339:         case EXCP05_BOUND:
  340: #ifndef TARGET_X86_64
  341:             if (env->eflags & VM_MASK) {
  342:                 handle_vm86_trap(env, trapnr);
  343:             } else
  344: #endif
  345:             {
  346:                 info.si_signo = SIGSEGV;
  347:                 info.si_errno = 0;
  348:                 info.si_code = TARGET_SI_KERNEL;
  349:                 info._sifields._sigfault._addr = 0;
  350:                 queue_signal(env, info.si_signo, &info);
  351:             }
  352:             break;
  353:         case EXCP06_ILLOP:
  354:             info.si_signo = SIGILL;
  355:             info.si_errno = 0;
  356:             info.si_code = TARGET_ILL_ILLOPN;
  357:             info._sifields._sigfault._addr = env->eip;
  358:             queue_signal(env, info.si_signo, &info);
  359:             break;
  360: #endif
  361:         case EXCP_INTERRUPT:
  362:             /* just indicate that signals should be handled asap */
  363:             break;
  364: #if 0
  365:         case EXCP_DEBUG:
  366:             {
  367:                 int sig;
  368: 
  369:                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
  370:                 if (sig)
  371:                   {
  372:                     info.si_signo = sig;
  373:                     info.si_errno = 0;
  374:                     info.si_code = TARGET_TRAP_BRKPT;
  375:                     queue_signal(env, info.si_signo, &info);
  376:                   }
  377:             }
  378:             break;
  379: #endif
  380:         default:
  381:             pc = env->segs[R_CS].base + env->eip;
  382:             fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
  383:                     (long)pc, trapnr);
  384:             abort();
  385:         }
  386:         process_pending_signals(env);
  387:     }
  388: }
  389: #endif
  390: 
  391: #ifdef TARGET_SPARC
  392: #define SPARC64_STACK_BIAS 2047
  393: 
  394: //#define DEBUG_WIN
  395: /* WARNING: dealing with register windows _is_ complicated. More info
  396:    can be found at http://www.sics.se/~psm/sparcstack.html */
  397: static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
  398: {
  399:     index = (index + cwp * 16) % (16 * env->nwindows);
  400:     /* wrap handling : if cwp is on the last window, then we use the
  401:        registers 'after' the end */
  402:     if (index < 8 && env->cwp == env->nwindows - 1)
  403:         index += 16 * env->nwindows;
  404:     return index;
  405: }
  406: 
  407: /* save the register window 'cwp1' */
  408: static inline void save_window_offset(CPUSPARCState *env, int cwp1)
  409: {
  410:     unsigned int i;
  411:     abi_ulong sp_ptr;
  412: 
  413:     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
  414: #ifdef TARGET_SPARC64
  415:     if (sp_ptr & 3)
  416:         sp_ptr += SPARC64_STACK_BIAS;
  417: #endif
  418: #if defined(DEBUG_WIN)
  419:     printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
  420:            sp_ptr, cwp1);
  421: #endif
  422:     for(i = 0; i < 16; i++) {
  423:         /* FIXME - what to do if put_user() fails? */
  424:         put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
  425:         sp_ptr += sizeof(abi_ulong);
  426:     }
  427: }
  428: 
  429: static void save_window(CPUSPARCState *env)
  430: {
  431: #ifndef TARGET_SPARC64
  432:     unsigned int new_wim;
  433:     new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
  434:         ((1LL << env->nwindows) - 1);
  435:     save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
  436:     env->wim = new_wim;
  437: #else
  438:     save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
  439:     env->cansave++;
  440:     env->canrestore--;
  441: #endif
  442: }
  443: 
  444: static void restore_window(CPUSPARCState *env)
  445: {
  446: #ifndef TARGET_SPARC64
  447:     unsigned int new_wim;
  448: #endif
  449:     unsigned int i, cwp1;
  450:     abi_ulong sp_ptr;
  451: 
  452: #ifndef TARGET_SPARC64
  453:     new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
  454:         ((1LL << env->nwindows) - 1);
  455: #endif
  456: 
  457:     /* restore the invalid window */
  458:     cwp1 = cpu_cwp_inc(env, env->cwp + 1);
  459:     sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
  460: #ifdef TARGET_SPARC64
  461:     if (sp_ptr & 3)
  462:         sp_ptr += SPARC64_STACK_BIAS;
  463: #endif
  464: #if defined(DEBUG_WIN)
  465:     printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
  466:            sp_ptr, cwp1);
  467: #endif
  468:     for(i = 0; i < 16; i++) {
  469:         /* FIXME - what to do if get_user() fails? */
  470:         get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
  471:         sp_ptr += sizeof(abi_ulong);
  472:     }
  473: #ifdef TARGET_SPARC64
  474:     env->canrestore++;
  475:     if (env->cleanwin < env->nwindows - 1)
  476:         env->cleanwin++;
  477:     env->cansave--;
  478: #else
  479:     env->wim = new_wim;
  480: #endif
  481: }
  482: 
  483: static void flush_windows(CPUSPARCState *env)
  484: {
  485:     int offset, cwp1;
  486: 
  487:     offset = 1;
  488:     for(;;) {
  489:         /* if restore would invoke restore_window(), then we can stop */
  490:         cwp1 = cpu_cwp_inc(env, env->cwp + offset);
  491: #ifndef TARGET_SPARC64
  492:         if (env->wim & (1 << cwp1))
  493:             break;
  494: #else
  495:         if (env->canrestore == 0)
  496:             break;
  497:         env->cansave++;
  498:         env->canrestore--;
  499: #endif
  500:         save_window_offset(env, cwp1);
  501:         offset++;
  502:     }
  503:     cwp1 = cpu_cwp_inc(env, env->cwp + 1);
  504: #ifndef TARGET_SPARC64
  505:     /* set wim so that restore will reload the registers */
  506:     env->wim = 1 << cwp1;
  507: #endif
  508: #if defined(DEBUG_WIN)
  509:     printf("flush_windows: nb=%d\n", offset - 1);
  510: #endif
  511: }
  512: 
  513: void cpu_loop(CPUSPARCState *env)
  514: {
  515:     int trapnr, ret, syscall_nr;
  516:     //target_siginfo_t info;
  517: 
  518:     while (1) {
  519:         trapnr = cpu_sparc_exec (env);
  520: 
  521:         switch (trapnr) {
  522: #ifndef TARGET_SPARC64
  523:         case 0x80:
  524: #else
  525:         /* FreeBSD uses 0x141 for syscalls too */
  526:         case 0x141:
  527:             if (bsd_type != target_freebsd)
  528:                 goto badtrap;
  529:         case 0x100:
  530: #endif
  531:             syscall_nr = env->gregs[1];
  532:             if (bsd_type == target_freebsd)
  533:                 ret = do_freebsd_syscall(env, syscall_nr,
  534:                                          env->regwptr[0], env->regwptr[1],
  535:                                          env->regwptr[2], env->regwptr[3],
  536:                                          env->regwptr[4], env->regwptr[5], 0, 0);
  537:             else if (bsd_type == target_netbsd)
  538:                 ret = do_netbsd_syscall(env, syscall_nr,
  539:                                         env->regwptr[0], env->regwptr[1],
  540:                                         env->regwptr[2], env->regwptr[3],
  541:                                         env->regwptr[4], env->regwptr[5]);
  542:             else { //if (bsd_type == target_openbsd)
  543: #if defined(TARGET_SPARC64)
  544:                 syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
  545:                                 TARGET_OPENBSD_SYSCALL_G2RFLAG);
  546: #endif
  547:                 ret = do_openbsd_syscall(env, syscall_nr,
  548:                                          env->regwptr[0], env->regwptr[1],
  549:                                          env->regwptr[2], env->regwptr[3],
  550:                                          env->regwptr[4], env->regwptr[5]);
  551:             }
  552:             if ((unsigned int)ret >= (unsigned int)(-515)) {
  553:                 ret = -ret;
  554: #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
  555:                 env->xcc |= PSR_CARRY;
  556: #else
  557:                 env->psr |= PSR_CARRY;
  558: #endif
  559:             } else {
  560: #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
  561:                 env->xcc &= ~PSR_CARRY;
  562: #else
  563:                 env->psr &= ~PSR_CARRY;
  564: #endif
  565:             }
  566:             env->regwptr[0] = ret;
  567:             /* next instruction */
  568: #if defined(TARGET_SPARC64)
  569:             if (bsd_type == target_openbsd &&
  570:                 env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
  571:                 env->pc = env->gregs[2];
  572:                 env->npc = env->pc + 4;
  573:             } else if (bsd_type == target_openbsd &&
  574:                        env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
  575:                 env->pc = env->gregs[7];
  576:                 env->npc = env->pc + 4;
  577:             } else {
  578:                 env->pc = env->npc;
  579:                 env->npc = env->npc + 4;
  580:             }
  581: #else
  582:             env->pc = env->npc;
  583:             env->npc = env->npc + 4;
  584: #endif
  585:             break;
  586:         case 0x83: /* flush windows */
  587: #ifdef TARGET_ABI32
  588:         case 0x103:
  589: #endif
  590:             flush_windows(env);
  591:             /* next instruction */
  592:             env->pc = env->npc;
  593:             env->npc = env->npc + 4;
  594:             break;
  595: #ifndef TARGET_SPARC64
  596:         case TT_WIN_OVF: /* window overflow */
  597:             save_window(env);
  598:             break;
  599:         case TT_WIN_UNF: /* window underflow */
  600:             restore_window(env);
  601:             break;
  602:         case TT_TFAULT:
  603:         case TT_DFAULT:
  604: #if 0
  605:             {
  606:                 info.si_signo = SIGSEGV;
  607:                 info.si_errno = 0;
  608:                 /* XXX: check env->error_code */
  609:                 info.si_code = TARGET_SEGV_MAPERR;
  610:                 info._sifields._sigfault._addr = env->mmuregs[4];
  611:                 queue_signal(env, info.si_signo, &info);
  612:             }
  613: #endif
  614:             break;
  615: #else
  616:         case TT_SPILL: /* window overflow */
  617:             save_window(env);
  618:             break;
  619:         case TT_FILL: /* window underflow */
  620:             restore_window(env);
  621:             break;
  622:         case TT_TFAULT:
  623:         case TT_DFAULT:
  624: #if 0
  625:             {
  626:                 info.si_signo = SIGSEGV;
  627:                 info.si_errno = 0;
  628:                 /* XXX: check env->error_code */
  629:                 info.si_code = TARGET_SEGV_MAPERR;
  630:                 if (trapnr == TT_DFAULT)
  631:                     info._sifields._sigfault._addr = env->dmmuregs[4];
  632:                 else
  633:                     info._sifields._sigfault._addr = env->tsptr->tpc;
  634:                 //queue_signal(env, info.si_signo, &info);
  635:             }
  636: #endif
  637:             break;
  638: #endif
  639:         case EXCP_INTERRUPT:
  640:             /* just indicate that signals should be handled asap */
  641:             break;
  642:         case EXCP_DEBUG:
  643:             {
  644:                 int sig;
  645: 
  646:                 sig = gdb_handlesig (env, TARGET_SIGTRAP);
  647: #if 0
  648:                 if (sig)
  649:                   {
  650:                     info.si_signo = sig;
  651:                     info.si_errno = 0;
  652:                     info.si_code = TARGET_TRAP_BRKPT;
  653:                     //queue_signal(env, info.si_signo, &info);
  654:                   }
  655: #endif
  656:             }
  657:             break;
  658:         default:
  659: #ifdef TARGET_SPARC64
  660:         badtrap:
  661: #endif
  662:             printf ("Unhandled trap: 0x%x\n", trapnr);
  663:             cpu_dump_state(env, stderr, fprintf, 0);
  664:             exit (1);
  665:         }
  666:         process_pending_signals (env);
  667:     }
  668: }
  669: 
  670: #endif
  671: 
  672: static void usage(void)
  673: {
  674:     printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
  675:            "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
  676:            "BSD CPU emulator (compiled for %s emulation)\n"
  677:            "\n"
  678:            "Standard options:\n"
  679:            "-h                print this help\n"
  680:            "-g port           wait gdb connection to port\n"
  681:            "-L path           set the elf interpreter prefix (default=%s)\n"
  682:            "-s size           set the stack size in bytes (default=%ld)\n"
  683:            "-cpu model        select CPU (-cpu ? for list)\n"
  684:            "-drop-ld-preload  drop LD_PRELOAD for target process\n"
  685:            "-E var=value      sets/modifies targets environment variable(s)\n"
  686:            "-U var            unsets targets environment variable(s)\n"
  687: #if defined(CONFIG_USE_GUEST_BASE)
  688:            "-B address        set guest_base address to address\n"
  689: #endif
  690:            "-bsd type         select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
  691:            "\n"
  692:            "Debug options:\n"
  693:            "-d options   activate log (logfile=%s)\n"
  694:            "-p pagesize  set the host page size to 'pagesize'\n"
  695:            "-singlestep  always run in singlestep mode\n"
  696:            "-strace      log system calls\n"
  697:            "\n"
  698:            "Environment variables:\n"
  699:            "QEMU_STRACE       Print system calls and arguments similar to the\n"
  700:            "                  'strace' program.  Enable by setting to any value.\n"
  701:            "You can use -E and -U options to set/unset environment variables\n"
  702:            "for target process.  It is possible to provide several variables\n"
  703:            "by repeating the option.  For example:\n"
  704:            "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
  705:            "Note that if you provide several changes to single variable\n"
  706:            "last change will stay in effect.\n"
  707:            ,
  708:            TARGET_ARCH,
  709:            interp_prefix,
  710:            x86_stack_size,
  711:            DEBUG_LOGFILE);
  712:     exit(1);
  713: }
  714: 
  715: THREAD CPUState *thread_env;
  716: 
  717: /* Assumes contents are already zeroed.  */
  718: void init_task_state(TaskState *ts)
  719: {
  720:     int i;
  721: 
  722:     ts->used = 1;
  723:     ts->first_free = ts->sigqueue_table;
  724:     for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
  725:         ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
  726:     }
  727:     ts->sigqueue_table[i].next = NULL;
  728: }
  729: 
  730: int main(int argc, char **argv)
  731: {
  732:     const char *filename;
  733:     const char *cpu_model;
  734:     struct target_pt_regs regs1, *regs = &regs1;
  735:     struct image_info info1, *info = &info1;
  736:     TaskState ts1, *ts = &ts1;
  737:     CPUState *env;
  738:     int optind;
  739:     const char *r;
  740:     int gdbstub_port = 0;
  741:     char **target_environ, **wrk;
  742:     envlist_t *envlist = NULL;
  743:     bsd_type = target_openbsd;
  744: 
  745:     if (argc <= 1)
  746:         usage();
  747: 
  748:     /* init debug */
  749:     cpu_set_log_filename(DEBUG_LOGFILE);
  750: 
  751:     if ((envlist = envlist_create()) == NULL) {
  752:         (void) fprintf(stderr, "Unable to allocate envlist\n");
  753:         exit(1);
  754:     }
  755: 
  756:     /* add current environment into the list */
  757:     for (wrk = environ; *wrk != NULL; wrk++) {
  758:         (void) envlist_setenv(envlist, *wrk);
  759:     }
  760: 
  761:     cpu_model = NULL;
  762: #if defined(cpudef_setup)
  763:     cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
  764: #endif
  765: 
  766:     optind = 1;
  767:     for(;;) {
  768:         if (optind >= argc)
  769:             break;
  770:         r = argv[optind];
  771:         if (r[0] != '-')
  772:             break;
  773:         optind++;
  774:         r++;
  775:         if (!strcmp(r, "-")) {
  776:             break;
  777:         } else if (!strcmp(r, "d")) {
  778:             int mask;
  779:             const CPULogItem *item;
  780: 
  781:             if (optind >= argc)
  782:                 break;
  783: 
  784:             r = argv[optind++];
  785:             mask = cpu_str_to_log_mask(r);
  786:             if (!mask) {
  787:                 printf("Log items (comma separated):\n");
  788:                 for(item = cpu_log_items; item->mask != 0; item++) {
  789:                     printf("%-10s %s\n", item->name, item->help);
  790:                 }
  791:                 exit(1);
  792:             }
  793:             cpu_set_log(mask);
  794:         } else if (!strcmp(r, "E")) {
  795:             r = argv[optind++];
  796:             if (envlist_setenv(envlist, r) != 0)
  797:                 usage();
  798:         } else if (!strcmp(r, "ignore-environment")) {
  799:             envlist_free(envlist);
  800:             if ((envlist = envlist_create()) == NULL) {
  801:                 (void) fprintf(stderr, "Unable to allocate envlist\n");
  802:                 exit(1);
  803:             }
  804:         } else if (!strcmp(r, "U")) {
  805:             r = argv[optind++];
  806:             if (envlist_unsetenv(envlist, r) != 0)
  807:                 usage();
  808:         } else if (!strcmp(r, "s")) {
  809:             r = argv[optind++];
  810:             x86_stack_size = strtol(r, (char **)&r, 0);
  811:             if (x86_stack_size <= 0)
  812:                 usage();
  813:             if (*r == 'M')
  814:                 x86_stack_size *= 1024 * 1024;
  815:             else if (*r == 'k' || *r == 'K')
  816:                 x86_stack_size *= 1024;
  817:         } else if (!strcmp(r, "L")) {
  818:             interp_prefix = argv[optind++];
  819:         } else if (!strcmp(r, "p")) {
  820:             qemu_host_page_size = atoi(argv[optind++]);
  821:             if (qemu_host_page_size == 0 ||
  822:                 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
  823:                 fprintf(stderr, "page size must be a power of two\n");
  824:                 exit(1);
  825:             }
  826:         } else if (!strcmp(r, "g")) {
  827:             gdbstub_port = atoi(argv[optind++]);
  828:         } else if (!strcmp(r, "r")) {
  829:             qemu_uname_release = argv[optind++];
  830:         } else if (!strcmp(r, "cpu")) {
  831:             cpu_model = argv[optind++];
  832:             if (strcmp(cpu_model, "?") == 0) {
  833: /* XXX: implement xxx_cpu_list for targets that still miss it */
  834: #if defined(cpu_list)
  835:                     cpu_list(stdout, &fprintf);
  836: #endif
  837:                 exit(1);
  838:             }
  839: #if defined(CONFIG_USE_GUEST_BASE)
  840:         } else if (!strcmp(r, "B")) {
  841:            guest_base = strtol(argv[optind++], NULL, 0);
  842:            have_guest_base = 1;
  843: #endif
  844:         } else if (!strcmp(r, "drop-ld-preload")) {
  845:             (void) envlist_unsetenv(envlist, "LD_PRELOAD");
  846:         } else if (!strcmp(r, "bsd")) {
  847:             if (!strcasecmp(argv[optind], "freebsd")) {
  848:                 bsd_type = target_freebsd;
  849:             } else if (!strcasecmp(argv[optind], "netbsd")) {
  850:                 bsd_type = target_netbsd;
  851:             } else if (!strcasecmp(argv[optind], "openbsd")) {
  852:                 bsd_type = target_openbsd;
  853:             } else {
  854:                 usage();
  855:             }
  856:             optind++;
  857:         } else if (!strcmp(r, "singlestep")) {
  858:             singlestep = 1;
  859:         } else if (!strcmp(r, "strace")) {
  860:             do_strace = 1;
  861:         } else
  862:         {
  863:             usage();
  864:         }
  865:     }
  866:     if (optind >= argc)
  867:         usage();
  868:     filename = argv[optind];
  869: 
  870:     /* Zero out regs */
  871:     memset(regs, 0, sizeof(struct target_pt_regs));
  872: 
  873:     /* Zero out image_info */
  874:     memset(info, 0, sizeof(struct image_info));
  875: 
  876:     /* Scan interp_prefix dir for replacement files. */
  877:     init_paths(interp_prefix);
  878: 
  879:     if (cpu_model == NULL) {
  880: #if defined(TARGET_I386)
  881: #ifdef TARGET_X86_64
  882:         cpu_model = "qemu64";
  883: #else
  884:         cpu_model = "qemu32";
  885: #endif
  886: #elif defined(TARGET_SPARC)
  887: #ifdef TARGET_SPARC64
  888:         cpu_model = "TI UltraSparc II";
  889: #else
  890:         cpu_model = "Fujitsu MB86904";
  891: #endif
  892: #else
  893:         cpu_model = "any";
  894: #endif
  895:     }
  896:     cpu_exec_init_all(0);
  897:     /* NOTE: we need to init the CPU at this stage to get
  898:        qemu_host_page_size */
  899:     env = cpu_init(cpu_model);
  900:     if (!env) {
  901:         fprintf(stderr, "Unable to find CPU definition\n");
  902:         exit(1);
  903:     }
  904: #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
  905:     cpu_reset(env);
  906: #endif
  907:     thread_env = env;
  908: 
  909:     if (getenv("QEMU_STRACE")) {
  910:         do_strace = 1;
  911:     }
  912: 
  913:     target_environ = envlist_to_environ(envlist, NULL);
  914:     envlist_free(envlist);
  915: 
  916: #if defined(CONFIG_USE_GUEST_BASE)
  917:     /*
  918:      * Now that page sizes are configured in cpu_init() we can do
  919:      * proper page alignment for guest_base.
  920:      */
  921:     guest_base = HOST_PAGE_ALIGN(guest_base);
  922: 
  923:     /*
  924:      * Read in mmap_min_addr kernel parameter.  This value is used
  925:      * When loading the ELF image to determine whether guest_base
  926:      * is needed.
  927:      *
  928:      * When user has explicitly set the quest base, we skip this
  929:      * test.
  930:      */
  931:     if (!have_guest_base) {
  932:         FILE *fp;
  933: 
  934:         if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
  935:             unsigned long tmp;
  936:             if (fscanf(fp, "%lu", &tmp) == 1) {
  937:                 mmap_min_addr = tmp;
  938:                 qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
  939:             }
  940:             fclose(fp);
  941:         }
  942:     }
  943: #endif /* CONFIG_USE_GUEST_BASE */
  944: 
  945:     if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
  946:         printf("Error loading %s\n", filename);
  947:         _exit(1);
  948:     }
  949: 
  950:     for (wrk = target_environ; *wrk; wrk++) {
  951:         free(*wrk);
  952:     }
  953: 
  954:     free(target_environ);
  955: 
  956:     if (qemu_log_enabled()) {
  957: #if defined(CONFIG_USE_GUEST_BASE)
  958:         qemu_log("guest_base  0x%lx\n", guest_base);
  959: #endif
  960:         log_page_dump();
  961: 
  962:         qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
  963:         qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
  964:         qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n",
  965:                  info->start_code);
  966:         qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n",
  967:                  info->start_data);
  968:         qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
  969:         qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
  970:                  info->start_stack);
  971:         qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
  972:         qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
  973:     }
  974: 
  975:     target_set_brk(info->brk);
  976:     syscall_init();
  977:     signal_init();
  978: 
  979: #if defined(CONFIG_USE_GUEST_BASE)
  980:     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
  981:        generating the prologue until now so that the prologue can take
  982:        the real value of GUEST_BASE into account.  */
  983:     tcg_prologue_init(&tcg_ctx);
  984: #endif
  985: 
  986:     /* build Task State */
  987:     memset(ts, 0, sizeof(TaskState));
  988:     init_task_state(ts);
  989:     ts->info = info;
  990:     env->opaque = ts;
  991: 
  992: #if defined(TARGET_I386)
  993:     cpu_x86_set_cpl(env, 3);
  994: 
  995:     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
  996:     env->hflags |= HF_PE_MASK;
  997:     if (env->cpuid_features & CPUID_SSE) {
  998:         env->cr[4] |= CR4_OSFXSR_MASK;
  999:         env->hflags |= HF_OSFXSR_MASK;
 1000:     }
 1001: #ifndef TARGET_ABI32
 1002:     /* enable 64 bit mode if possible */
 1003:     if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
 1004:         fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
 1005:         exit(1);
 1006:     }
 1007:     env->cr[4] |= CR4_PAE_MASK;
 1008:     env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
 1009:     env->hflags |= HF_LMA_MASK;
 1010: #endif
 1011: 
 1012:     /* flags setup : we activate the IRQs by default as in user mode */
 1013:     env->eflags |= IF_MASK;
 1014: 
 1015:     /* linux register setup */
 1016: #ifndef TARGET_ABI32
 1017:     env->regs[R_EAX] = regs->rax;
 1018:     env->regs[R_EBX] = regs->rbx;
 1019:     env->regs[R_ECX] = regs->rcx;
 1020:     env->regs[R_EDX] = regs->rdx;
 1021:     env->regs[R_ESI] = regs->rsi;
 1022:     env->regs[R_EDI] = regs->rdi;
 1023:     env->regs[R_EBP] = regs->rbp;
 1024:     env->regs[R_ESP] = regs->rsp;
 1025:     env->eip = regs->rip;
 1026: #else
 1027:     env->regs[R_EAX] = regs->eax;
 1028:     env->regs[R_EBX] = regs->ebx;
 1029:     env->regs[R_ECX] = regs->ecx;
 1030:     env->regs[R_EDX] = regs->edx;
 1031:     env->regs[R_ESI] = regs->esi;
 1032:     env->regs[R_EDI] = regs->edi;
 1033:     env->regs[R_EBP] = regs->ebp;
 1034:     env->regs[R_ESP] = regs->esp;
 1035:     env->eip = regs->eip;
 1036: #endif
 1037: 
 1038:     /* linux interrupt setup */
 1039: #ifndef TARGET_ABI32
 1040:     env->idt.limit = 511;
 1041: #else
 1042:     env->idt.limit = 255;
 1043: #endif
 1044:     env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
 1045:                                 PROT_READ|PROT_WRITE,
 1046:                                 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
 1047:     idt_table = g2h(env->idt.base);
 1048:     set_idt(0, 0);
 1049:     set_idt(1, 0);
 1050:     set_idt(2, 0);
 1051:     set_idt(3, 3);
 1052:     set_idt(4, 3);
 1053:     set_idt(5, 0);
 1054:     set_idt(6, 0);
 1055:     set_idt(7, 0);
 1056:     set_idt(8, 0);
 1057:     set_idt(9, 0);
 1058:     set_idt(10, 0);
 1059:     set_idt(11, 0);
 1060:     set_idt(12, 0);
 1061:     set_idt(13, 0);
 1062:     set_idt(14, 0);
 1063:     set_idt(15, 0);
 1064:     set_idt(16, 0);
 1065:     set_idt(17, 0);
 1066:     set_idt(18, 0);
 1067:     set_idt(19, 0);
 1068:     set_idt(0x80, 3);
 1069: 
 1070:     /* linux segment setup */
 1071:     {
 1072:         uint64_t *gdt_table;
 1073:         env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
 1074:                                     PROT_READ|PROT_WRITE,
 1075:                                     MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
 1076:         env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
 1077:         gdt_table = g2h(env->gdt.base);
 1078: #ifdef TARGET_ABI32
 1079:         write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
 1080:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 1081:                  (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
 1082: #else
 1083:         /* 64 bit code segment */
 1084:         write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
 1085:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 1086:                  DESC_L_MASK |
 1087:                  (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
 1088: #endif
 1089:         write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
 1090:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 1091:                  (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
 1092:     }
 1093: 
 1094:     cpu_x86_load_seg(env, R_CS, __USER_CS);
 1095:     cpu_x86_load_seg(env, R_SS, __USER_DS);
 1096: #ifdef TARGET_ABI32
 1097:     cpu_x86_load_seg(env, R_DS, __USER_DS);
 1098:     cpu_x86_load_seg(env, R_ES, __USER_DS);
 1099:     cpu_x86_load_seg(env, R_FS, __USER_DS);
 1100:     cpu_x86_load_seg(env, R_GS, __USER_DS);
 1101:     /* This hack makes Wine work... */
 1102:     env->segs[R_FS].selector = 0;
 1103: #else
 1104:     cpu_x86_load_seg(env, R_DS, 0);
 1105:     cpu_x86_load_seg(env, R_ES, 0);
 1106:     cpu_x86_load_seg(env, R_FS, 0);
 1107:     cpu_x86_load_seg(env, R_GS, 0);
 1108: #endif
 1109: #elif defined(TARGET_SPARC)
 1110:     {
 1111:         int i;
 1112:         env->pc = regs->pc;
 1113:         env->npc = regs->npc;
 1114:         env->y = regs->y;
 1115:         for(i = 0; i < 8; i++)
 1116:             env->gregs[i] = regs->u_regs[i];
 1117:         for(i = 0; i < 8; i++)
 1118:             env->regwptr[i] = regs->u_regs[i + 8];
 1119:     }
 1120: #else
 1121: #error unsupported target CPU
 1122: #endif
 1123: 
 1124:     if (gdbstub_port) {
 1125:         gdbserver_start (gdbstub_port);
 1126:         gdb_handlesig(env, 0);
 1127:     }
 1128:     cpu_loop(env);
 1129:     /* never exits */
 1130:     return 0;
 1131: }

unix.superglobalmegacorp.com