|
|
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:
1.1.1.3 ! root 34:
! 35: #include "envlist.h"
! 36:
1.1 root 37: #define DEBUG_LOGFILE "/tmp/qemu.log"
38:
1.1.1.2 root 39: int singlestep;
1.1.1.3 ! root 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
1.1.1.2 root 45:
1.1 root 46: static const char *interp_prefix = CONFIG_QEMU_PREFIX;
47: const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
48: extern char **environ;
1.1.1.3 ! root 49: enum BSDType bsd_type;
1.1 root 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: }
1.1.1.2 root 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:
1.1.1.3 ! root 172: void cpu_loop(CPUX86State *env)
1.1.1.2 root 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 */
1.1.1.3 ! root 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: }
1.1.1.2 root 237: break;
238: #ifndef TARGET_ABI32
239: case EXCP_SYSCALL:
1.1.1.3 ! root 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: }
1.1.1.2 root 260: env->eip = env->exception_next_eip;
1.1.1.3 ! root 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: }
1.1.1.2 root 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:
1.1 root 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:
1.1.1.3 ! root 513: void cpu_loop(CPUSPARCState *env)
1.1 root 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
1.1.1.3 ! root 525: /* FreeBSD uses 0x141 for syscalls too */
! 526: case 0x141:
! 527: if (bsd_type != target_freebsd)
! 528: goto badtrap;
1.1 root 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],
1.1.1.3 ! root 536: env->regwptr[4], env->regwptr[5], 0, 0);
1.1 root 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)) {
1.1.1.3 ! root 553: ret = -ret;
1.1 root 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:
1.1.1.3 ! root 659: #ifdef TARGET_SPARC64
! 660: badtrap:
! 661: #endif
1.1 root 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"
1.1.1.3 ! root 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
1.1 root 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"
1.1.1.2 root 695: "-singlestep always run in singlestep mode\n"
1.1 root 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"
1.1.1.3 ! root 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"
1.1 root 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 = ®s1;
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;
1.1.1.3 ! root 741: char **target_environ, **wrk;
! 742: envlist_t *envlist = NULL;
! 743: bsd_type = target_openbsd;
1.1 root 744:
745: if (argc <= 1)
746: usage();
747:
748: /* init debug */
749: cpu_set_log_filename(DEBUG_LOGFILE);
750:
1.1.1.3 ! root 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:
1.1 root 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);
1.1.1.3 ! root 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();
1.1 root 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: }
1.1.1.3 ! root 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
1.1 root 834: } else if (!strcmp(r, "drop-ld-preload")) {
1.1.1.3 ! root 835: (void) envlist_unsetenv(envlist, "LD_PRELOAD");
1.1 root 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++;
1.1.1.2 root 847: } else if (!strcmp(r, "singlestep")) {
848: singlestep = 1;
1.1 root 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) {
1.1.1.2 root 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)
1.1 root 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: }
1.1.1.3 ! root 894: #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
! 895: cpu_reset(env);
! 896: #endif
1.1 root 897: thread_env = env;
898:
899: if (getenv("QEMU_STRACE")) {
900: do_strace = 1;
901: }
902:
1.1.1.3 ! root 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: }
1.1 root 932: }
1.1.1.3 ! root 933: #endif /* CONFIG_USE_GUEST_BASE */
1.1 root 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()) {
1.1.1.3 ! root 947: #if defined(CONFIG_USE_GUEST_BASE)
! 948: qemu_log("guest_base 0x%lx\n", guest_base);
! 949: #endif
1.1 root 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:
1.1.1.2 root 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)
1.1 root 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: }
1.1.1.3 ! root 1111: cpu_loop(env);
1.1 root 1112: /* never exits */
1113: return 0;
1114: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.