File:  [Qemu by Fabrice Bellard] / qemu / bsd-user / main.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:42:39 2018 UTC (3 years, 8 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, HEAD
qemu 0.12.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: 
   34: 
   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_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:     optind = 1;
  763:     for(;;) {
  764:         if (optind >= argc)
  765:             break;
  766:         r = argv[optind];
  767:         if (r[0] != '-')
  768:             break;
  769:         optind++;
  770:         r++;
  771:         if (!strcmp(r, "-")) {
  772:             break;
  773:         } else if (!strcmp(r, "d")) {
  774:             int mask;
  775:             const CPULogItem *item;
  776: 
  777:             if (optind >= argc)
  778:                 break;
  779: 
  780:             r = argv[optind++];
  781:             mask = cpu_str_to_log_mask(r);
  782:             if (!mask) {
  783:                 printf("Log items (comma separated):\n");
  784:                 for(item = cpu_log_items; item->mask != 0; item++) {
  785:                     printf("%-10s %s\n", item->name, item->help);
  786:                 }
  787:                 exit(1);
  788:             }
  789:             cpu_set_log(mask);
  790:         } else if (!strcmp(r, "E")) {
  791:             r = argv[optind++];
  792:             if (envlist_setenv(envlist, r) != 0)
  793:                 usage();
  794:         } else if (!strcmp(r, "U")) {
  795:             r = argv[optind++];
  796:             if (envlist_unsetenv(envlist, r) != 0)
  797:                 usage();
  798:         } else if (!strcmp(r, "s")) {
  799:             r = argv[optind++];
  800:             x86_stack_size = strtol(r, (char **)&r, 0);
  801:             if (x86_stack_size <= 0)
  802:                 usage();
  803:             if (*r == 'M')
  804:                 x86_stack_size *= 1024 * 1024;
  805:             else if (*r == 'k' || *r == 'K')
  806:                 x86_stack_size *= 1024;
  807:         } else if (!strcmp(r, "L")) {
  808:             interp_prefix = argv[optind++];
  809:         } else if (!strcmp(r, "p")) {
  810:             qemu_host_page_size = atoi(argv[optind++]);
  811:             if (qemu_host_page_size == 0 ||
  812:                 (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
  813:                 fprintf(stderr, "page size must be a power of two\n");
  814:                 exit(1);
  815:             }
  816:         } else if (!strcmp(r, "g")) {
  817:             gdbstub_port = atoi(argv[optind++]);
  818:         } else if (!strcmp(r, "r")) {
  819:             qemu_uname_release = argv[optind++];
  820:         } else if (!strcmp(r, "cpu")) {
  821:             cpu_model = argv[optind++];
  822:             if (strcmp(cpu_model, "?") == 0) {
  823: /* XXX: implement xxx_cpu_list for targets that still miss it */
  824: #if defined(cpu_list)
  825:                     cpu_list(stdout, &fprintf);
  826: #endif
  827:                 exit(1);
  828:             }
  829: #if defined(CONFIG_USE_GUEST_BASE)
  830:         } else if (!strcmp(r, "B")) {
  831:            guest_base = strtol(argv[optind++], NULL, 0);
  832:            have_guest_base = 1;
  833: #endif
  834:         } else if (!strcmp(r, "drop-ld-preload")) {
  835:             (void) envlist_unsetenv(envlist, "LD_PRELOAD");
  836:         } else if (!strcmp(r, "bsd")) {
  837:             if (!strcasecmp(argv[optind], "freebsd")) {
  838:                 bsd_type = target_freebsd;
  839:             } else if (!strcasecmp(argv[optind], "netbsd")) {
  840:                 bsd_type = target_netbsd;
  841:             } else if (!strcasecmp(argv[optind], "openbsd")) {
  842:                 bsd_type = target_openbsd;
  843:             } else {
  844:                 usage();
  845:             }
  846:             optind++;
  847:         } else if (!strcmp(r, "singlestep")) {
  848:             singlestep = 1;
  849:         } else if (!strcmp(r, "strace")) {
  850:             do_strace = 1;
  851:         } else
  852:         {
  853:             usage();
  854:         }
  855:     }
  856:     if (optind >= argc)
  857:         usage();
  858:     filename = argv[optind];
  859: 
  860:     /* Zero out regs */
  861:     memset(regs, 0, sizeof(struct target_pt_regs));
  862: 
  863:     /* Zero out image_info */
  864:     memset(info, 0, sizeof(struct image_info));
  865: 
  866:     /* Scan interp_prefix dir for replacement files. */
  867:     init_paths(interp_prefix);
  868: 
  869:     if (cpu_model == NULL) {
  870: #if defined(TARGET_I386)
  871: #ifdef TARGET_X86_64
  872:         cpu_model = "qemu64";
  873: #else
  874:         cpu_model = "qemu32";
  875: #endif
  876: #elif defined(TARGET_SPARC)
  877: #ifdef TARGET_SPARC64
  878:         cpu_model = "TI UltraSparc II";
  879: #else
  880:         cpu_model = "Fujitsu MB86904";
  881: #endif
  882: #else
  883:         cpu_model = "any";
  884: #endif
  885:     }
  886:     cpu_exec_init_all(0);
  887:     /* NOTE: we need to init the CPU at this stage to get
  888:        qemu_host_page_size */
  889:     env = cpu_init(cpu_model);
  890:     if (!env) {
  891:         fprintf(stderr, "Unable to find CPU definition\n");
  892:         exit(1);
  893:     }
  894: #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
  895:     cpu_reset(env);
  896: #endif
  897:     thread_env = env;
  898: 
  899:     if (getenv("QEMU_STRACE")) {
  900:         do_strace = 1;
  901:     }
  902: 
  903:     target_environ = envlist_to_environ(envlist, NULL);
  904:     envlist_free(envlist);
  905: 
  906: #if defined(CONFIG_USE_GUEST_BASE)
  907:     /*
  908:      * Now that page sizes are configured in cpu_init() we can do
  909:      * proper page alignment for guest_base.
  910:      */
  911:     guest_base = HOST_PAGE_ALIGN(guest_base);
  912: 
  913:     /*
  914:      * Read in mmap_min_addr kernel parameter.  This value is used
  915:      * When loading the ELF image to determine whether guest_base
  916:      * is needed.
  917:      *
  918:      * When user has explicitly set the quest base, we skip this
  919:      * test.
  920:      */
  921:     if (!have_guest_base) {
  922:         FILE *fp;
  923: 
  924:         if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
  925:             unsigned long tmp;
  926:             if (fscanf(fp, "%lu", &tmp) == 1) {
  927:                 mmap_min_addr = tmp;
  928:                 qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
  929:             }
  930:             fclose(fp);
  931:         }
  932:     }
  933: #endif /* CONFIG_USE_GUEST_BASE */
  934: 
  935:     if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
  936:         printf("Error loading %s\n", filename);
  937:         _exit(1);
  938:     }
  939: 
  940:     for (wrk = target_environ; *wrk; wrk++) {
  941:         free(*wrk);
  942:     }
  943: 
  944:     free(target_environ);
  945: 
  946:     if (qemu_log_enabled()) {
  947: #if defined(CONFIG_USE_GUEST_BASE)
  948:         qemu_log("guest_base  0x%lx\n", guest_base);
  949: #endif
  950:         log_page_dump();
  951: 
  952:         qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
  953:         qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
  954:         qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n",
  955:                  info->start_code);
  956:         qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n",
  957:                  info->start_data);
  958:         qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
  959:         qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
  960:                  info->start_stack);
  961:         qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
  962:         qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
  963:     }
  964: 
  965:     target_set_brk(info->brk);
  966:     syscall_init();
  967:     signal_init();
  968: 
  969:     /* build Task State */
  970:     memset(ts, 0, sizeof(TaskState));
  971:     init_task_state(ts);
  972:     ts->info = info;
  973:     env->opaque = ts;
  974: 
  975: #if defined(TARGET_I386)
  976:     cpu_x86_set_cpl(env, 3);
  977: 
  978:     env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
  979:     env->hflags |= HF_PE_MASK;
  980:     if (env->cpuid_features & CPUID_SSE) {
  981:         env->cr[4] |= CR4_OSFXSR_MASK;
  982:         env->hflags |= HF_OSFXSR_MASK;
  983:     }
  984: #ifndef TARGET_ABI32
  985:     /* enable 64 bit mode if possible */
  986:     if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
  987:         fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
  988:         exit(1);
  989:     }
  990:     env->cr[4] |= CR4_PAE_MASK;
  991:     env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
  992:     env->hflags |= HF_LMA_MASK;
  993: #endif
  994: 
  995:     /* flags setup : we activate the IRQs by default as in user mode */
  996:     env->eflags |= IF_MASK;
  997: 
  998:     /* linux register setup */
  999: #ifndef TARGET_ABI32
 1000:     env->regs[R_EAX] = regs->rax;
 1001:     env->regs[R_EBX] = regs->rbx;
 1002:     env->regs[R_ECX] = regs->rcx;
 1003:     env->regs[R_EDX] = regs->rdx;
 1004:     env->regs[R_ESI] = regs->rsi;
 1005:     env->regs[R_EDI] = regs->rdi;
 1006:     env->regs[R_EBP] = regs->rbp;
 1007:     env->regs[R_ESP] = regs->rsp;
 1008:     env->eip = regs->rip;
 1009: #else
 1010:     env->regs[R_EAX] = regs->eax;
 1011:     env->regs[R_EBX] = regs->ebx;
 1012:     env->regs[R_ECX] = regs->ecx;
 1013:     env->regs[R_EDX] = regs->edx;
 1014:     env->regs[R_ESI] = regs->esi;
 1015:     env->regs[R_EDI] = regs->edi;
 1016:     env->regs[R_EBP] = regs->ebp;
 1017:     env->regs[R_ESP] = regs->esp;
 1018:     env->eip = regs->eip;
 1019: #endif
 1020: 
 1021:     /* linux interrupt setup */
 1022: #ifndef TARGET_ABI32
 1023:     env->idt.limit = 511;
 1024: #else
 1025:     env->idt.limit = 255;
 1026: #endif
 1027:     env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
 1028:                                 PROT_READ|PROT_WRITE,
 1029:                                 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
 1030:     idt_table = g2h(env->idt.base);
 1031:     set_idt(0, 0);
 1032:     set_idt(1, 0);
 1033:     set_idt(2, 0);
 1034:     set_idt(3, 3);
 1035:     set_idt(4, 3);
 1036:     set_idt(5, 0);
 1037:     set_idt(6, 0);
 1038:     set_idt(7, 0);
 1039:     set_idt(8, 0);
 1040:     set_idt(9, 0);
 1041:     set_idt(10, 0);
 1042:     set_idt(11, 0);
 1043:     set_idt(12, 0);
 1044:     set_idt(13, 0);
 1045:     set_idt(14, 0);
 1046:     set_idt(15, 0);
 1047:     set_idt(16, 0);
 1048:     set_idt(17, 0);
 1049:     set_idt(18, 0);
 1050:     set_idt(19, 0);
 1051:     set_idt(0x80, 3);
 1052: 
 1053:     /* linux segment setup */
 1054:     {
 1055:         uint64_t *gdt_table;
 1056:         env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
 1057:                                     PROT_READ|PROT_WRITE,
 1058:                                     MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
 1059:         env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
 1060:         gdt_table = g2h(env->gdt.base);
 1061: #ifdef TARGET_ABI32
 1062:         write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
 1063:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 1064:                  (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
 1065: #else
 1066:         /* 64 bit code segment */
 1067:         write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
 1068:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 1069:                  DESC_L_MASK |
 1070:                  (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
 1071: #endif
 1072:         write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
 1073:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 1074:                  (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
 1075:     }
 1076: 
 1077:     cpu_x86_load_seg(env, R_CS, __USER_CS);
 1078:     cpu_x86_load_seg(env, R_SS, __USER_DS);
 1079: #ifdef TARGET_ABI32
 1080:     cpu_x86_load_seg(env, R_DS, __USER_DS);
 1081:     cpu_x86_load_seg(env, R_ES, __USER_DS);
 1082:     cpu_x86_load_seg(env, R_FS, __USER_DS);
 1083:     cpu_x86_load_seg(env, R_GS, __USER_DS);
 1084:     /* This hack makes Wine work... */
 1085:     env->segs[R_FS].selector = 0;
 1086: #else
 1087:     cpu_x86_load_seg(env, R_DS, 0);
 1088:     cpu_x86_load_seg(env, R_ES, 0);
 1089:     cpu_x86_load_seg(env, R_FS, 0);
 1090:     cpu_x86_load_seg(env, R_GS, 0);
 1091: #endif
 1092: #elif defined(TARGET_SPARC)
 1093:     {
 1094:         int i;
 1095:         env->pc = regs->pc;
 1096:         env->npc = regs->npc;
 1097:         env->y = regs->y;
 1098:         for(i = 0; i < 8; i++)
 1099:             env->gregs[i] = regs->u_regs[i];
 1100:         for(i = 0; i < 8; i++)
 1101:             env->regwptr[i] = regs->u_regs[i + 8];
 1102:     }
 1103: #else
 1104: #error unsupported target CPU
 1105: #endif
 1106: 
 1107:     if (gdbstub_port) {
 1108:         gdbserver_start (gdbstub_port);
 1109:         gdb_handlesig(env, 0);
 1110:     }
 1111:     cpu_loop(env);
 1112:     /* never exits */
 1113:     return 0;
 1114: }

unix.superglobalmegacorp.com