Annotation of qemu/bsd-user/main.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.