|
|
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 = ®s1;
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.