|
|
1.1 root 1: /*
2: * qemu user main
3: *
4: * Copyright (c) 2003 Fabrice Bellard
5: * Copyright (c) 2006 Pierre d'Herbemont
6: *
7: * This program is free software; you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as published by
9: * the Free Software Foundation; either version 2 of the License, or
10: * (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with this program; if not, write to the Free Software
19: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20: */
21: #include <stdlib.h>
22: #include <stdio.h>
23: #include <stdarg.h>
24: #include <string.h>
25: #include <errno.h>
26: #include <unistd.h>
27:
28: #include <sys/syscall.h>
29: #include <sys/mman.h>
30:
31: #include "qemu.h"
32:
33: #define DEBUG_LOGFILE "/tmp/qemu.log"
34:
35: #ifdef __APPLE__
36: #include <crt_externs.h>
37: # define environ (*_NSGetEnviron())
38: #endif
39:
40: #include <mach/mach_init.h>
41: #include <mach/vm_map.h>
42:
43: const char *interp_prefix = "";
44:
45: asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
46:
47: /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
48: we allocate a bigger stack. Need a better solution, for example
49: by remapping the process stack directly at the right place */
50: unsigned long stack_size = 512 * 1024;
51:
52: void qerror(const char *fmt, ...)
53: {
54: va_list ap;
55:
56: va_start(ap, fmt);
57: vfprintf(stderr, fmt, ap);
58: va_end(ap);
59: fprintf(stderr, "\n");
60: exit(1);
61: }
62:
63: void gemu_log(const char *fmt, ...)
64: {
65: va_list ap;
66:
67: va_start(ap, fmt);
68: vfprintf(stderr, fmt, ap);
69: va_end(ap);
70: }
71:
72: void cpu_outb(CPUState *env, int addr, int val)
73: {
74: fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
75: }
76:
77: void cpu_outw(CPUState *env, int addr, int val)
78: {
79: fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
80: }
81:
82: void cpu_outl(CPUState *env, int addr, int val)
83: {
84: fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
85: }
86:
87: int cpu_inb(CPUState *env, int addr)
88: {
89: fprintf(stderr, "inb: port=0x%04x\n", addr);
90: return 0;
91: }
92:
93: int cpu_inw(CPUState *env, int addr)
94: {
95: fprintf(stderr, "inw: port=0x%04x\n", addr);
96: return 0;
97: }
98:
99: int cpu_inl(CPUState *env, int addr)
100: {
101: fprintf(stderr, "inl: port=0x%04x\n", addr);
102: return 0;
103: }
104:
105: int cpu_get_pic_interrupt(CPUState *env)
106: {
107: return -1;
108: }
109: #ifdef TARGET_PPC
110:
111: static inline uint64_t cpu_ppc_get_tb (CPUState *env)
112: {
113: /* TO FIX */
114: return 0;
115: }
116:
117: uint32_t cpu_ppc_load_tbl (CPUState *env)
118: {
119: return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
120: }
121:
122: uint32_t cpu_ppc_load_tbu (CPUState *env)
123: {
124: return cpu_ppc_get_tb(env) >> 32;
125: }
126:
127: static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
128: {
129: /* TO FIX */
130: }
131:
132: void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
133: {
134: cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
135: }
136:
137: void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
138: {
139: cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
140: }
141:
142: uint32_t cpu_ppc_load_decr (CPUState *env)
143: {
144: /* TO FIX */
145: return -1;
146: }
147:
148: void cpu_ppc_store_decr (CPUState *env, uint32_t value)
149: {
150: /* TO FIX */
151: }
152:
153: void cpu_loop(CPUPPCState *env)
154: {
155: int trapnr;
156: uint32_t ret;
157: target_siginfo_t info;
158:
159: for(;;) {
160: trapnr = cpu_ppc_exec(env);
161: if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
162: trapnr != EXCP_TRACE) {
163: if (loglevel > 0) {
164: cpu_dump_state(env, logfile, fprintf, 0);
165: }
166: }
167: switch(trapnr) {
168: case EXCP_NONE:
169: break;
170: case EXCP_SYSCALL_USER:
171: /* system call */
172: if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
173: ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
174: env->gpr[5], env->gpr[6], env->gpr[7],
175: env->gpr[8], env->gpr[9], env->gpr[10]*/);
176: else if(((int)env->gpr[0])<0)
177: ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
178: env->gpr[5], env->gpr[6], env->gpr[7],
179: env->gpr[8], env->gpr[9], env->gpr[10]);
180: else
181: ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
182: env->gpr[5], env->gpr[6], env->gpr[7],
183: env->gpr[8], env->gpr[9], env->gpr[10]);
184:
185: /* Unix syscall error signaling */
186: if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
187: {
188: if( (int)ret < 0 )
189: env->nip += 0;
190: else
191: env->nip += 4;
192: }
193:
194: /* Return value */
195: env->gpr[3] = ret;
196: break;
197: case EXCP_RESET:
198: /* Should not happen ! */
199: fprintf(stderr, "RESET asked... Stop emulation\n");
200: if (loglevel)
201: fprintf(logfile, "RESET asked... Stop emulation\n");
202: abort();
203: case EXCP_MACHINE_CHECK:
204: fprintf(stderr, "Machine check exeption... Stop emulation\n");
205: if (loglevel)
206: fprintf(logfile, "RESET asked... Stop emulation\n");
207: info.si_signo = SIGBUS;
208: info.si_errno = 0;
209: info.si_code = BUS_OBJERR;
210: info.si_addr = (void*)(env->nip - 4);
211: queue_signal(info.si_signo, &info);
212: case EXCP_DSI:
213: #ifndef DAR
214: /* To deal with multiple qemu header version as host for the darwin-user code */
215: # define DAR SPR_DAR
216: #endif
217: fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
218: if (loglevel) {
219: fprintf(logfile, "Invalid data memory access: 0x%08x\n",
220: env->spr[DAR]);
221: }
222: /* Handle this via the gdb */
223: gdb_handlesig (env, SIGSEGV);
224:
225: info.si_addr = (void*)env->nip;
226: queue_signal(info.si_signo, &info);
227: break;
228: case EXCP_ISI:
229: fprintf(stderr, "Invalid instruction fetch\n");
230: if (loglevel)
231: fprintf(logfile, "Invalid instruction fetch\n");
232: /* Handle this via the gdb */
233: gdb_handlesig (env, SIGSEGV);
234:
235: info.si_addr = (void*)(env->nip - 4);
236: queue_signal(info.si_signo, &info);
237: break;
238: case EXCP_EXTERNAL:
239: /* Should not happen ! */
240: fprintf(stderr, "External interruption... Stop emulation\n");
241: if (loglevel)
242: fprintf(logfile, "External interruption... Stop emulation\n");
243: abort();
244: case EXCP_ALIGN:
245: fprintf(stderr, "Invalid unaligned memory access\n");
246: if (loglevel)
247: fprintf(logfile, "Invalid unaligned memory access\n");
248: info.si_signo = SIGBUS;
249: info.si_errno = 0;
250: info.si_code = BUS_ADRALN;
251: info.si_addr = (void*)(env->nip - 4);
252: queue_signal(info.si_signo, &info);
253: break;
254: case EXCP_PROGRAM:
255: switch (env->error_code & ~0xF) {
256: case EXCP_FP:
257: fprintf(stderr, "Program exception\n");
258: if (loglevel)
259: fprintf(logfile, "Program exception\n");
260: /* Set FX */
261: env->fpscr[7] |= 0x8;
262: /* Finally, update FEX */
263: if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
264: ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
265: env->fpscr[7] |= 0x4;
266: info.si_signo = SIGFPE;
267: info.si_errno = 0;
268: switch (env->error_code & 0xF) {
269: case EXCP_FP_OX:
270: info.si_code = FPE_FLTOVF;
271: break;
272: case EXCP_FP_UX:
273: info.si_code = FPE_FLTUND;
274: break;
275: case EXCP_FP_ZX:
276: case EXCP_FP_VXZDZ:
277: info.si_code = FPE_FLTDIV;
278: break;
279: case EXCP_FP_XX:
280: info.si_code = FPE_FLTRES;
281: break;
282: case EXCP_FP_VXSOFT:
283: info.si_code = FPE_FLTINV;
284: break;
285: case EXCP_FP_VXNAN:
286: case EXCP_FP_VXISI:
287: case EXCP_FP_VXIDI:
288: case EXCP_FP_VXIMZ:
289: case EXCP_FP_VXVC:
290: case EXCP_FP_VXSQRT:
291: case EXCP_FP_VXCVI:
292: info.si_code = FPE_FLTSUB;
293: break;
294: default:
295: fprintf(stderr, "Unknown floating point exception "
296: "(%02x)\n", env->error_code);
297: if (loglevel) {
298: fprintf(logfile, "Unknown floating point exception "
299: "(%02x)\n", env->error_code & 0xF);
300: }
301: }
302: break;
303: case EXCP_INVAL:
304: fprintf(stderr, "Invalid instruction\n");
305: if (loglevel)
306: fprintf(logfile, "Invalid instruction\n");
307: info.si_signo = SIGILL;
308: info.si_errno = 0;
309: switch (env->error_code & 0xF) {
310: case EXCP_INVAL_INVAL:
311: info.si_code = ILL_ILLOPC;
312: break;
313: case EXCP_INVAL_LSWX:
314: info.si_code = ILL_ILLOPN;
315: break;
316: case EXCP_INVAL_SPR:
317: info.si_code = ILL_PRVREG;
318: break;
319: case EXCP_INVAL_FP:
320: info.si_code = ILL_COPROC;
321: break;
322: default:
323: fprintf(stderr, "Unknown invalid operation (%02x)\n",
324: env->error_code & 0xF);
325: if (loglevel) {
326: fprintf(logfile, "Unknown invalid operation (%02x)\n",
327: env->error_code & 0xF);
328: }
329: info.si_code = ILL_ILLADR;
330: break;
331: }
332: /* Handle this via the gdb */
333: gdb_handlesig (env, SIGSEGV);
334: break;
335: case EXCP_PRIV:
336: fprintf(stderr, "Privilege violation\n");
337: if (loglevel)
338: fprintf(logfile, "Privilege violation\n");
339: info.si_signo = SIGILL;
340: info.si_errno = 0;
341: switch (env->error_code & 0xF) {
342: case EXCP_PRIV_OPC:
343: info.si_code = ILL_PRVOPC;
344: break;
345: case EXCP_PRIV_REG:
346: info.si_code = ILL_PRVREG;
347: break;
348: default:
349: fprintf(stderr, "Unknown privilege violation (%02x)\n",
350: env->error_code & 0xF);
351: info.si_code = ILL_PRVOPC;
352: break;
353: }
354: break;
355: case EXCP_TRAP:
356: fprintf(stderr, "Tried to call a TRAP\n");
357: if (loglevel)
358: fprintf(logfile, "Tried to call a TRAP\n");
359: abort();
360: default:
361: /* Should not happen ! */
362: fprintf(stderr, "Unknown program exception (%02x)\n",
363: env->error_code);
364: if (loglevel) {
365: fprintf(logfile, "Unknwon program exception (%02x)\n",
366: env->error_code);
367: }
368: abort();
369: }
370: info.si_addr = (void*)(env->nip - 4);
371: queue_signal(info.si_signo, &info);
372: break;
373: case EXCP_NO_FP:
374: fprintf(stderr, "No floating point allowed\n");
375: if (loglevel)
376: fprintf(logfile, "No floating point allowed\n");
377: info.si_signo = SIGILL;
378: info.si_errno = 0;
379: info.si_code = ILL_COPROC;
380: info.si_addr = (void*)(env->nip - 4);
381: queue_signal(info.si_signo, &info);
382: break;
383: case EXCP_DECR:
384: /* Should not happen ! */
385: fprintf(stderr, "Decrementer exception\n");
386: if (loglevel)
387: fprintf(logfile, "Decrementer exception\n");
388: abort();
389: case EXCP_TRACE:
390: /* Pass to gdb: we use this to trace execution */
391: gdb_handlesig (env, SIGTRAP);
392: break;
393: case EXCP_FP_ASSIST:
394: /* Should not happen ! */
395: fprintf(stderr, "Floating point assist exception\n");
396: if (loglevel)
397: fprintf(logfile, "Floating point assist exception\n");
398: abort();
399: case EXCP_MTMSR:
400: /* We reloaded the msr, just go on */
401: if (msr_pr == 0) {
402: fprintf(stderr, "Tried to go into supervisor mode !\n");
403: if (loglevel)
404: fprintf(logfile, "Tried to go into supervisor mode !\n");
405: abort();
406: }
407: break;
408: case EXCP_BRANCH:
409: /* We stopped because of a jump... */
410: break;
411: case EXCP_INTERRUPT:
412: /* Don't know why this should ever happen... */
413: fprintf(stderr, "EXCP_INTERRUPT\n");
414: break;
415: case EXCP_DEBUG:
416: gdb_handlesig (env, SIGTRAP);
417: break;
418: default:
419: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
420: trapnr);
421: if (loglevel) {
422: fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
423: "0x%02x - aborting\n", trapnr, env->error_code);
424: }
425: abort();
426: }
427: process_pending_signals(env);
428: }
429: }
430: #endif
431:
432:
433: #ifdef TARGET_I386
434:
435: /***********************************************************/
436: /* CPUX86 core interface */
437:
438: uint64_t cpu_get_tsc(CPUX86State *env)
439: {
440: return cpu_get_real_ticks();
441: }
442:
443: void
444: write_dt(void *ptr, unsigned long addr, unsigned long limit,
445: int flags)
446: {
447: unsigned int e1, e2;
448: e1 = (addr << 16) | (limit & 0xffff);
449: e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
450: e2 |= flags;
451: stl((uint8_t *)ptr, e1);
452: stl((uint8_t *)ptr + 4, e2);
453: }
454:
455: static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
456: unsigned long addr, unsigned int sel)
457: {
458: unsigned int e1, e2;
459: e1 = (addr & 0xffff) | (sel << 16);
460: e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
461: stl((uint8_t *)ptr, e1);
462: stl((uint8_t *)ptr + 4, e2);
463: }
464:
465: #define GDT_TABLE_SIZE 14
466: #define LDT_TABLE_SIZE 15
467: #define IDT_TABLE_SIZE 256
468: #define TSS_SIZE 104
469: uint64_t gdt_table[GDT_TABLE_SIZE];
470: uint64_t ldt_table[LDT_TABLE_SIZE];
471: uint64_t idt_table[IDT_TABLE_SIZE];
472: uint32_t tss[TSS_SIZE];
473:
474: /* only dpl matters as we do only user space emulation */
475: static void set_idt(int n, unsigned int dpl)
476: {
477: set_gate(idt_table + n, 0, dpl, 0, 0);
478: }
479:
480: /* ABI convention: after a syscall if there was an error the CF flag is set */
481: static inline void set_error(CPUX86State *env, int ret)
482: {
483: if(ret<0)
484: env->eflags = env->eflags | 0x1;
485: else
486: env->eflags &= ~0x1;
487: env->regs[R_EAX] = ret;
488: }
489:
490: void cpu_loop(CPUX86State *env)
491: {
492: int trapnr;
493: int ret;
494: uint8_t *pc;
495: target_siginfo_t info;
496:
497: for(;;) {
498: trapnr = cpu_x86_exec(env);
499: uint32_t *params = (uint32_t *)env->regs[R_ESP];
500: switch(trapnr) {
501: case 0x79: /* Our commpage hack back door exit is here */
502: do_commpage(env, env->eip, *(params + 1), *(params + 2),
503: *(params + 3), *(params + 4),
504: *(params + 5), *(params + 6),
505: *(params + 7), *(params + 8));
506: break;
507: case 0x81: /* mach syscall */
508: {
509: ret = do_mach_syscall(env, env->regs[R_EAX],
510: *(params + 1), *(params + 2),
511: *(params + 3), *(params + 4),
512: *(params + 5), *(params + 6),
513: *(params + 7), *(params + 8));
514: set_error(env, ret);
515: break;
516: }
517: case 0x90: /* unix backdoor */
518: {
519: /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
520: int saved_stack = env->regs[R_ESP];
521: env->regs[R_ESP] = env->regs[R_ECX];
522:
523: ret = do_unix_syscall(env, env->regs[R_EAX]);
524:
525: env->regs[R_ECX] = env->regs[R_ESP];
526: env->regs[R_ESP] = saved_stack;
527:
528: set_error(env, ret);
529: break;
530: }
531: case 0x80: /* unix syscall */
532: {
533: ret = do_unix_syscall(env, env->regs[R_EAX]/*,
534: *(params + 1), *(params + 2),
535: *(params + 3), *(params + 4),
536: *(params + 5), *(params + 6),
537: *(params + 7), *(params + 8)*/);
538: set_error(env, ret);
539: break;
540: }
541: case 0x82: /* thread syscall */
542: {
543: ret = do_thread_syscall(env, env->regs[R_EAX],
544: *(params + 1), *(params + 2),
545: *(params + 3), *(params + 4),
546: *(params + 5), *(params + 6),
547: *(params + 7), *(params + 8));
548: set_error(env, ret);
549: break;
550: }
551: case EXCP0B_NOSEG:
552: case EXCP0C_STACK:
553: info.si_signo = SIGBUS;
554: info.si_errno = 0;
555: info.si_code = BUS_NOOP;
556: info.si_addr = 0;
557: gdb_handlesig (env, SIGBUS);
558: queue_signal(info.si_signo, &info);
559: break;
560: case EXCP0D_GPF:
561: info.si_signo = SIGSEGV;
562: info.si_errno = 0;
563: info.si_code = SEGV_NOOP;
564: info.si_addr = 0;
565: gdb_handlesig (env, SIGSEGV);
566: queue_signal(info.si_signo, &info);
567: break;
568: case EXCP0E_PAGE:
569: info.si_signo = SIGSEGV;
570: info.si_errno = 0;
571: if (!(env->error_code & 1))
572: info.si_code = SEGV_MAPERR;
573: else
574: info.si_code = SEGV_ACCERR;
575: info.si_addr = (void*)env->cr[2];
576: gdb_handlesig (env, SIGSEGV);
577: queue_signal(info.si_signo, &info);
578: break;
579: case EXCP00_DIVZ:
580: /* division by zero */
581: info.si_signo = SIGFPE;
582: info.si_errno = 0;
583: info.si_code = FPE_INTDIV;
584: info.si_addr = (void*)env->eip;
585: gdb_handlesig (env, SIGFPE);
586: queue_signal(info.si_signo, &info);
587: break;
588: case EXCP01_SSTP:
589: case EXCP03_INT3:
590: info.si_signo = SIGTRAP;
591: info.si_errno = 0;
592: info.si_code = TRAP_BRKPT;
593: info.si_addr = (void*)env->eip;
594: gdb_handlesig (env, SIGTRAP);
595: queue_signal(info.si_signo, &info);
596: break;
597: case EXCP04_INTO:
598: case EXCP05_BOUND:
599: info.si_signo = SIGSEGV;
600: info.si_errno = 0;
601: info.si_code = SEGV_NOOP;
602: info.si_addr = 0;
603: gdb_handlesig (env, SIGSEGV);
604: queue_signal(info.si_signo, &info);
605: break;
606: case EXCP06_ILLOP:
607: info.si_signo = SIGILL;
608: info.si_errno = 0;
609: info.si_code = ILL_ILLOPN;
610: info.si_addr = (void*)env->eip;
611: gdb_handlesig (env, SIGILL);
612: queue_signal(info.si_signo, &info);
613: break;
614: case EXCP_INTERRUPT:
615: /* just indicate that signals should be handled asap */
616: break;
617: case EXCP_DEBUG:
618: {
619: int sig;
620:
621: sig = gdb_handlesig (env, SIGTRAP);
622: if (sig)
623: {
624: info.si_signo = sig;
625: info.si_errno = 0;
626: info.si_code = TRAP_BRKPT;
627: queue_signal(info.si_signo, &info);
628: }
629: }
630: break;
631: default:
632: pc = (void*)(env->segs[R_CS].base + env->eip);
633: fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
634: (long)pc, trapnr);
635: abort();
636: }
637: process_pending_signals(env);
638: }
639: }
640: #endif
641:
642: void usage(void)
643: {
644: printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
645: "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
646: "Darwin CPU emulator (compiled for %s emulation)\n"
647: "\n"
648: "-h print this help\n"
649: "-L path set the %s library path (default='%s')\n"
650: "-s size set the stack size in bytes (default=%ld)\n"
651: "\n"
652: "debug options:\n"
653: #ifdef USE_CODE_COPY
654: "-no-code-copy disable code copy acceleration\n"
655: #endif
656: "-d options activate log (logfile='%s')\n"
657: "-g wait for gdb on port 1234\n"
658: "-p pagesize set the host page size to 'pagesize'\n",
659: TARGET_ARCH,
660: TARGET_ARCH,
661: interp_prefix,
662: stack_size,
663: DEBUG_LOGFILE);
664: _exit(1);
665: }
666:
667: /* XXX: currently only used for async signals (see signal.c) */
668: CPUState *global_env;
669: /* used only if single thread */
670: CPUState *cpu_single_env = NULL;
671:
672: /* used to free thread contexts */
673: TaskState *first_task_state;
674:
675: int main(int argc, char **argv)
676: {
677: const char *filename;
678: struct target_pt_regs regs1, *regs = ®s1;
679: TaskState ts1, *ts = &ts1;
680: CPUState *env;
681: int optind;
682: short use_gdbstub = 0;
683: const char *r;
684:
685: if (argc <= 1)
686: usage();
687:
688: /* init debug */
689: cpu_set_log_filename(DEBUG_LOGFILE);
690:
691: optind = 1;
692: for(;;) {
693: if (optind >= argc)
694: break;
695: r = argv[optind];
696: if (r[0] != '-')
697: break;
698: optind++;
699: r++;
700: if (!strcmp(r, "-")) {
701: break;
702: } else if (!strcmp(r, "d")) {
703: int mask;
704: CPULogItem *item;
705:
706: if (optind >= argc)
707: break;
708:
709: r = argv[optind++];
710: mask = cpu_str_to_log_mask(r);
711: if (!mask) {
712: printf("Log items (comma separated):\n");
713: for(item = cpu_log_items; item->mask != 0; item++) {
714: printf("%-10s %s\n", item->name, item->help);
715: }
716: exit(1);
717: }
718: cpu_set_log(mask);
719: } else if (!strcmp(r, "s")) {
720: r = argv[optind++];
721: stack_size = strtol(r, (char **)&r, 0);
722: if (stack_size <= 0)
723: usage();
724: if (*r == 'M')
725: stack_size *= 1024 * 1024;
726: else if (*r == 'k' || *r == 'K')
727: stack_size *= 1024;
728: } else if (!strcmp(r, "L")) {
729: interp_prefix = argv[optind++];
730: } else if (!strcmp(r, "p")) {
731: qemu_host_page_size = atoi(argv[optind++]);
732: if (qemu_host_page_size == 0 ||
733: (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
734: fprintf(stderr, "page size must be a power of two\n");
735: exit(1);
736: }
737: } else
738: if (!strcmp(r, "g")) {
739: use_gdbstub = 1;
740: } else
741: #ifdef USE_CODE_COPY
742: if (!strcmp(r, "no-code-copy")) {
743: code_copy_enabled = 0;
744: } else
745: #endif
746: {
747: usage();
748: }
749: }
750: if (optind >= argc)
751: usage();
752: filename = argv[optind];
753:
754: /* Zero out regs */
755: memset(regs, 0, sizeof(struct target_pt_regs));
756:
757: /* NOTE: we need to init the CPU at this stage to get
758: qemu_host_page_size */
759: env = cpu_init();
760:
761: printf("Starting %s with qemu\n----------------\n", filename);
762:
763: commpage_init();
764:
765: if (mach_exec(filename, argv+optind, environ, regs) != 0) {
766: printf("Error loading %s\n", filename);
767: _exit(1);
768: }
769:
770: syscall_init();
771: signal_init();
772: global_env = env;
773:
774: /* build Task State */
775: memset(ts, 0, sizeof(TaskState));
776: env->opaque = ts;
777: ts->used = 1;
778: env->user_mode_only = 1;
779:
780: #if defined(TARGET_I386)
781: cpu_x86_set_cpl(env, 3);
782:
783: env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
784: env->hflags |= HF_PE_MASK;
785:
786: if (env->cpuid_features & CPUID_SSE) {
787: env->cr[4] |= CR4_OSFXSR_MASK;
788: env->hflags |= HF_OSFXSR_MASK;
789: }
790:
791: /* flags setup : we activate the IRQs by default as in user mode */
792: env->eflags |= IF_MASK;
793:
794: /* darwin register setup */
795: env->regs[R_EAX] = regs->eax;
796: env->regs[R_EBX] = regs->ebx;
797: env->regs[R_ECX] = regs->ecx;
798: env->regs[R_EDX] = regs->edx;
799: env->regs[R_ESI] = regs->esi;
800: env->regs[R_EDI] = regs->edi;
801: env->regs[R_EBP] = regs->ebp;
802: env->regs[R_ESP] = regs->esp;
803: env->eip = regs->eip;
804:
805: /* Darwin LDT setup */
806: /* 2 - User code segment
807: 3 - User data segment
808: 4 - User cthread */
809: bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
810: env->ldt.base = (uint32_t) ldt_table;
811: env->ldt.limit = sizeof(ldt_table) - 1;
812:
813: write_dt(ldt_table + 2, 0, 0xfffff,
814: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
815: (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
816: write_dt(ldt_table + 3, 0, 0xfffff,
817: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
818: (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
819: write_dt(ldt_table + 4, 0, 0xfffff,
820: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
821: (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
822:
823: /* Darwin GDT setup.
824: * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
825: now everything is done via int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
826: bzero(gdt_table, sizeof(gdt_table));
827: env->gdt.base = (uint32_t)gdt_table;
828: env->gdt.limit = sizeof(gdt_table) - 1;
829:
830: /* Set up a back door to handle sysenter syscalls (unix) */
831: char * syscallbackdoor = malloc(64);
832: page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
833:
834: int i = 0;
835: syscallbackdoor[i++] = 0xcd;
836: syscallbackdoor[i++] = 0x90; /* int 0x90 */
837: syscallbackdoor[i++] = 0x0F;
838: syscallbackdoor[i++] = 0x35; /* sysexit */
839:
840: /* Darwin sysenter/sysexit setup */
841: env->sysenter_cs = 0x1; //XXX
842: env->sysenter_eip = (int)syscallbackdoor;
843: env->sysenter_esp = (int)malloc(64);
844:
845: /* Darwin TSS setup
846: This must match up with GDT[4] */
847: env->tr.base = (uint32_t) tss;
848: env->tr.limit = sizeof(tss) - 1;
849: env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
850: stw(tss + 2, 0x10); // ss0 = 0x10 = GDT[2] = Kernel Data Segment
851:
852: /* Darwin interrupt setup */
853: bzero(idt_table, sizeof(idt_table));
854: env->idt.base = (uint32_t) idt_table;
855: env->idt.limit = sizeof(idt_table) - 1;
856: set_idt(0, 0);
857: set_idt(1, 0);
858: set_idt(2, 0);
859: set_idt(3, 3);
860: set_idt(4, 3);
861: set_idt(5, 3);
862: set_idt(6, 0);
863: set_idt(7, 0);
864: set_idt(8, 0);
865: set_idt(9, 0);
866: set_idt(10, 0);
867: set_idt(11, 0);
868: set_idt(12, 0);
869: set_idt(13, 0);
870: set_idt(14, 0);
871: set_idt(15, 0);
872: set_idt(16, 0);
873: set_idt(17, 0);
874: set_idt(18, 0);
875: set_idt(19, 0);
876: /* Syscalls are done via
877: int 0x80 (unix) (rarely used)
878: int 0x81 (mach)
879: int 0x82 (thread)
880: int 0x83 (diag) (not handled here)
881: sysenter/sysexit (unix) -> we redirect that to int 0x90 */
882: set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
883: set_idt(0x80, 3); /* Unix Syscall */
884: set_idt(0x81, 3); /* Mach Syscalls */
885: set_idt(0x82, 3); /* thread Syscalls */
886:
887: set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
888:
889:
890: cpu_x86_load_seg(env, R_CS, __USER_CS);
891: cpu_x86_load_seg(env, R_DS, __USER_DS);
892: cpu_x86_load_seg(env, R_ES, __USER_DS);
893: cpu_x86_load_seg(env, R_SS, __USER_DS);
894: cpu_x86_load_seg(env, R_FS, __USER_DS);
895: cpu_x86_load_seg(env, R_GS, __USER_DS);
896:
897: #elif defined(TARGET_PPC)
898: {
899: int i;
900: env->nip = regs->nip;
901: for(i = 0; i < 32; i++) {
902: env->gpr[i] = regs->gpr[i];
903: }
904: }
905: #else
906: #error unsupported target CPU
907: #endif
908:
909: if (use_gdbstub) {
910: printf("Waiting for gdb Connection on port 1234...\n");
911: gdbserver_start (1234);
912: gdb_handlesig(env, 0);
913: }
914:
915: cpu_loop(env);
916: /* never exits */
917: return 0;
918: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.