|
|
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
1.1.1.4 root 18: * along with this program; if not, see <http://www.gnu.org/licenses/>.
1.1 root 19: */
20: #include <stdlib.h>
21: #include <stdio.h>
22: #include <stdarg.h>
23: #include <string.h>
24: #include <errno.h>
25: #include <unistd.h>
26:
27: #include <sys/syscall.h>
28: #include <sys/mman.h>
29:
30: #include "qemu.h"
31:
32: #define DEBUG_LOGFILE "/tmp/qemu.log"
33:
34: #ifdef __APPLE__
35: #include <crt_externs.h>
36: # define environ (*_NSGetEnviron())
37: #endif
38:
39: #include <mach/mach_init.h>
40: #include <mach/vm_map.h>
41:
1.1.1.4 root 42: int singlestep;
43:
1.1 root 44: const char *interp_prefix = "";
45:
46: asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
47:
48: /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
49: we allocate a bigger stack. Need a better solution, for example
50: by remapping the process stack directly at the right place */
51: unsigned long stack_size = 512 * 1024;
52:
53: void qerror(const char *fmt, ...)
54: {
55: va_list ap;
56:
57: va_start(ap, fmt);
58: vfprintf(stderr, fmt, ap);
59: va_end(ap);
60: fprintf(stderr, "\n");
61: exit(1);
62: }
63:
64: void gemu_log(const char *fmt, ...)
65: {
66: va_list ap;
67:
68: va_start(ap, fmt);
69: vfprintf(stderr, fmt, ap);
70: va_end(ap);
71: }
72:
73: int cpu_get_pic_interrupt(CPUState *env)
74: {
75: return -1;
76: }
77: #ifdef TARGET_PPC
78:
79: static inline uint64_t cpu_ppc_get_tb (CPUState *env)
80: {
81: /* TO FIX */
82: return 0;
83: }
84:
1.1.1.6 root 85: uint64_t cpu_ppc_load_tbl (CPUState *env)
1.1 root 86: {
1.1.1.6 root 87: return cpu_ppc_get_tb(env);
1.1 root 88: }
89:
90: uint32_t cpu_ppc_load_tbu (CPUState *env)
91: {
92: return cpu_ppc_get_tb(env) >> 32;
93: }
94:
1.1.1.6 root 95: uint64_t cpu_ppc_load_atbl (CPUState *env)
1.1 root 96: {
1.1.1.6 root 97: return cpu_ppc_get_tb(env);
1.1 root 98: }
99:
1.1.1.2 root 100: uint32_t cpu_ppc_load_atbu (CPUState *env)
1.1 root 101: {
1.1.1.2 root 102: return cpu_ppc_get_tb(env) >> 32;
1.1 root 103: }
104:
1.1.1.2 root 105: uint32_t cpu_ppc601_load_rtcu (CPUState *env)
1.1 root 106: {
1.1.1.2 root 107: cpu_ppc_load_tbu(env);
1.1 root 108: }
109:
1.1.1.2 root 110: uint32_t cpu_ppc601_load_rtcl (CPUState *env)
111: {
112: return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
113: }
114:
115: /* XXX: to be fixed */
1.1.1.6 root 116: int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
1.1 root 117: {
118: return -1;
119: }
120:
1.1.1.6 root 121: int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
1.1 root 122: {
1.1.1.2 root 123: return -1;
1.1 root 124: }
125:
1.1.1.4 root 126: #define EXCP_DUMP(env, fmt, ...) \
127: do { \
128: fprintf(stderr, fmt , ## __VA_ARGS__); \
129: cpu_dump_state(env, stderr, fprintf, 0); \
130: qemu_log(fmt, ## __VA_ARGS__); \
131: log_cpu_state(env, 0); \
1.1.1.2 root 132: } while (0)
133:
1.1 root 134: void cpu_loop(CPUPPCState *env)
135: {
136: int trapnr;
137: uint32_t ret;
138: target_siginfo_t info;
139:
140: for(;;) {
141: trapnr = cpu_ppc_exec(env);
142: switch(trapnr) {
1.1.1.2 root 143: case POWERPC_EXCP_NONE:
144: /* Just go on */
1.1 root 145: break;
1.1.1.2 root 146: case POWERPC_EXCP_CRITICAL: /* Critical input */
147: cpu_abort(env, "Critical interrupt while in user mode. "
148: "Aborting\n");
149: break;
150: case POWERPC_EXCP_MCHECK: /* Machine check exception */
151: cpu_abort(env, "Machine check exception while in user mode. "
152: "Aborting\n");
1.1 root 153: break;
1.1.1.2 root 154: case POWERPC_EXCP_DSI: /* Data storage exception */
1.1 root 155: #ifndef DAR
156: /* To deal with multiple qemu header version as host for the darwin-user code */
157: # define DAR SPR_DAR
158: #endif
1.1.1.5 root 159: EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n",
1.1.1.2 root 160: env->spr[SPR_DAR]);
1.1 root 161: /* Handle this via the gdb */
162: gdb_handlesig (env, SIGSEGV);
163:
164: info.si_addr = (void*)env->nip;
165: queue_signal(info.si_signo, &info);
166: break;
1.1.1.2 root 167: case POWERPC_EXCP_ISI: /* Instruction storage exception */
1.1.1.5 root 168: EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx "\n",
1.1.1.2 root 169: env->spr[SPR_DAR]);
1.1 root 170: /* Handle this via the gdb */
171: gdb_handlesig (env, SIGSEGV);
172:
173: info.si_addr = (void*)(env->nip - 4);
174: queue_signal(info.si_signo, &info);
175: break;
1.1.1.2 root 176: case POWERPC_EXCP_EXTERNAL: /* External input */
177: cpu_abort(env, "External interrupt while in user mode. "
178: "Aborting\n");
179: break;
180: case POWERPC_EXCP_ALIGN: /* Alignment exception */
181: EXCP_DUMP(env, "Unaligned memory access\n");
1.1 root 182: info.si_errno = 0;
183: info.si_code = BUS_ADRALN;
184: info.si_addr = (void*)(env->nip - 4);
185: queue_signal(info.si_signo, &info);
186: break;
1.1.1.2 root 187: case POWERPC_EXCP_PROGRAM: /* Program exception */
188: /* XXX: check this */
1.1 root 189: switch (env->error_code & ~0xF) {
1.1.1.2 root 190: case POWERPC_EXCP_FP:
191: EXCP_DUMP(env, "Floating point program exception\n");
192: /* Set FX */
193: info.si_signo = SIGFPE;
194: info.si_errno = 0;
195: switch (env->error_code & 0xF) {
196: case POWERPC_EXCP_FP_OX:
197: info.si_code = FPE_FLTOVF;
198: break;
199: case POWERPC_EXCP_FP_UX:
200: info.si_code = FPE_FLTUND;
201: break;
202: case POWERPC_EXCP_FP_ZX:
203: case POWERPC_EXCP_FP_VXZDZ:
204: info.si_code = FPE_FLTDIV;
205: break;
206: case POWERPC_EXCP_FP_XX:
207: info.si_code = FPE_FLTRES;
208: break;
209: case POWERPC_EXCP_FP_VXSOFT:
210: info.si_code = FPE_FLTINV;
211: break;
212: case POWERPC_EXCP_FP_VXSNAN:
213: case POWERPC_EXCP_FP_VXISI:
214: case POWERPC_EXCP_FP_VXIDI:
215: case POWERPC_EXCP_FP_VXIMZ:
216: case POWERPC_EXCP_FP_VXVC:
217: case POWERPC_EXCP_FP_VXSQRT:
218: case POWERPC_EXCP_FP_VXCVI:
219: info.si_code = FPE_FLTSUB;
220: break;
221: default:
222: EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
223: env->error_code);
224: break;
225: }
226: break;
227: case POWERPC_EXCP_INVAL:
228: EXCP_DUMP(env, "Invalid instruction\n");
229: info.si_signo = SIGILL;
230: info.si_errno = 0;
231: switch (env->error_code & 0xF) {
232: case POWERPC_EXCP_INVAL_INVAL:
233: info.si_code = ILL_ILLOPC;
234: break;
235: case POWERPC_EXCP_INVAL_LSWX:
236: info.si_code = ILL_ILLOPN;
237: break;
238: case POWERPC_EXCP_INVAL_SPR:
239: info.si_code = ILL_PRVREG;
240: break;
241: case POWERPC_EXCP_INVAL_FP:
242: info.si_code = ILL_COPROC;
243: break;
1.1 root 244: default:
1.1.1.2 root 245: EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
246: env->error_code & 0xF);
247: info.si_code = ILL_ILLADR;
248: break;
249: }
250: /* Handle this via the gdb */
251: gdb_handlesig (env, SIGSEGV);
252: break;
253: case POWERPC_EXCP_PRIV:
254: EXCP_DUMP(env, "Privilege violation\n");
255: info.si_signo = SIGILL;
256: info.si_errno = 0;
257: switch (env->error_code & 0xF) {
258: case POWERPC_EXCP_PRIV_OPC:
259: info.si_code = ILL_PRVOPC;
260: break;
261: case POWERPC_EXCP_PRIV_REG:
262: info.si_code = ILL_PRVREG;
263: break;
264: default:
265: EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
266: env->error_code & 0xF);
267: info.si_code = ILL_PRVOPC;
268: break;
269: }
270: break;
271: case POWERPC_EXCP_TRAP:
272: cpu_abort(env, "Tried to call a TRAP\n");
273: break;
274: default:
275: /* Should not happen ! */
276: cpu_abort(env, "Unknown program exception (%02x)\n",
277: env->error_code);
278: break;
1.1 root 279: }
280: info.si_addr = (void*)(env->nip - 4);
281: queue_signal(info.si_signo, &info);
282: break;
1.1.1.2 root 283: case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
284: EXCP_DUMP(env, "No floating point allowed\n");
285: info.si_signo = SIGILL;
1.1 root 286: info.si_errno = 0;
287: info.si_code = ILL_COPROC;
288: info.si_addr = (void*)(env->nip - 4);
289: queue_signal(info.si_signo, &info);
290: break;
1.1.1.2 root 291: case POWERPC_EXCP_SYSCALL: /* System call exception */
292: cpu_abort(env, "Syscall exception while in user mode. "
293: "Aborting\n");
294: break;
295: case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
296: EXCP_DUMP(env, "No APU instruction allowed\n");
297: info.si_signo = SIGILL;
298: info.si_errno = 0;
299: info.si_code = ILL_COPROC;
300: info.si_addr = (void*)(env->nip - 4);
301: queue_signal(info.si_signo, &info);
302: break;
303: case POWERPC_EXCP_DECR: /* Decrementer exception */
304: cpu_abort(env, "Decrementer interrupt while in user mode. "
305: "Aborting\n");
306: break;
307: case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
308: cpu_abort(env, "Fix interval timer interrupt while in user mode. "
309: "Aborting\n");
310: break;
311: case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
312: cpu_abort(env, "Watchdog timer interrupt while in user mode. "
313: "Aborting\n");
314: break;
315: case POWERPC_EXCP_DTLB: /* Data TLB error */
316: cpu_abort(env, "Data TLB exception while in user mode. "
317: "Aborting\n");
318: break;
319: case POWERPC_EXCP_ITLB: /* Instruction TLB error */
320: cpu_abort(env, "Instruction TLB exception while in user mode. "
321: "Aborting\n");
322: break;
323: case POWERPC_EXCP_DEBUG: /* Debug interrupt */
1.1 root 324: gdb_handlesig (env, SIGTRAP);
325: break;
1.1.1.2 root 326: case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
327: EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
328: info.si_signo = SIGILL;
329: info.si_errno = 0;
330: info.si_code = ILL_COPROC;
331: info.si_addr = (void*)(env->nip - 4);
332: queue_signal(info.si_signo, &info);
1.1 root 333: break;
1.1.1.2 root 334: case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
335: cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
1.1 root 336: break;
1.1.1.2 root 337: case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
338: cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
1.1 root 339: break;
1.1.1.2 root 340: case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
341: cpu_abort(env, "Performance monitor exception not handled\n");
1.1 root 342: break;
1.1.1.2 root 343: case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
344: cpu_abort(env, "Doorbell interrupt while in user mode. "
345: "Aborting\n");
346: break;
347: case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
348: cpu_abort(env, "Doorbell critical interrupt while in user mode. "
349: "Aborting\n");
350: break;
351: case POWERPC_EXCP_RESET: /* System reset exception */
352: cpu_abort(env, "Reset interrupt while in user mode. "
353: "Aborting\n");
354: break;
355: case POWERPC_EXCP_DSEG: /* Data segment exception */
356: cpu_abort(env, "Data segment exception while in user mode. "
357: "Aborting\n");
358: break;
359: case POWERPC_EXCP_ISEG: /* Instruction segment exception */
360: cpu_abort(env, "Instruction segment exception "
361: "while in user mode. Aborting\n");
362: break;
363: case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
364: cpu_abort(env, "Hypervisor decrementer interrupt "
365: "while in user mode. Aborting\n");
366: break;
367: case POWERPC_EXCP_TRACE: /* Trace exception */
368: /* Nothing to do:
369: * we use this exception to emulate step-by-step execution mode.
370: */
371: break;
372: case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
373: cpu_abort(env, "Hypervisor data storage exception "
374: "while in user mode. Aborting\n");
375: break;
376: case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
377: cpu_abort(env, "Hypervisor instruction storage exception "
378: "while in user mode. Aborting\n");
379: break;
380: case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
381: cpu_abort(env, "Hypervisor data segment exception "
382: "while in user mode. Aborting\n");
383: break;
384: case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
385: cpu_abort(env, "Hypervisor instruction segment exception "
386: "while in user mode. Aborting\n");
387: break;
388: case POWERPC_EXCP_VPU: /* Vector unavailable exception */
389: EXCP_DUMP(env, "No Altivec instructions allowed\n");
390: info.si_signo = SIGILL;
391: info.si_errno = 0;
392: info.si_code = ILL_COPROC;
393: info.si_addr = (void*)(env->nip - 4);
394: queue_signal(info.si_signo, &info);
395: break;
396: case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
397: cpu_abort(env, "Programable interval timer interrupt "
398: "while in user mode. Aborting\n");
399: break;
400: case POWERPC_EXCP_IO: /* IO error exception */
401: cpu_abort(env, "IO error exception while in user mode. "
402: "Aborting\n");
403: break;
404: case POWERPC_EXCP_RUNM: /* Run mode exception */
405: cpu_abort(env, "Run mode exception while in user mode. "
406: "Aborting\n");
407: break;
408: case POWERPC_EXCP_EMUL: /* Emulation trap exception */
409: cpu_abort(env, "Emulation trap exception not handled\n");
410: break;
411: case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
412: cpu_abort(env, "Instruction fetch TLB exception "
413: "while in user-mode. Aborting");
414: break;
415: case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
416: cpu_abort(env, "Data load TLB exception while in user-mode. "
417: "Aborting");
418: break;
419: case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
420: cpu_abort(env, "Data store TLB exception while in user-mode. "
421: "Aborting");
422: break;
423: case POWERPC_EXCP_FPA: /* Floating-point assist exception */
424: cpu_abort(env, "Floating-point assist exception not handled\n");
425: break;
426: case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
427: cpu_abort(env, "Instruction address breakpoint exception "
428: "not handled\n");
429: break;
430: case POWERPC_EXCP_SMI: /* System management interrupt */
431: cpu_abort(env, "System management interrupt while in user mode. "
432: "Aborting\n");
433: break;
434: case POWERPC_EXCP_THERM: /* Thermal interrupt */
435: cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
436: "Aborting\n");
437: break;
438: case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
439: cpu_abort(env, "Performance monitor exception not handled\n");
440: break;
441: case POWERPC_EXCP_VPUA: /* Vector assist exception */
442: cpu_abort(env, "Vector assist exception not handled\n");
443: break;
444: case POWERPC_EXCP_SOFTP: /* Soft patch exception */
445: cpu_abort(env, "Soft patch exception not handled\n");
446: break;
447: case POWERPC_EXCP_MAINT: /* Maintenance exception */
448: cpu_abort(env, "Maintenance exception while in user mode. "
449: "Aborting\n");
450: break;
451: case POWERPC_EXCP_STOP: /* stop translation */
452: /* We did invalidate the instruction cache. Go on */
453: break;
454: case POWERPC_EXCP_BRANCH: /* branch instruction: */
455: /* We just stopped because of a branch. Go on */
456: break;
457: case POWERPC_EXCP_SYSCALL_USER:
458: /* system call in user-mode emulation */
459: /* system call */
460: if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
461: ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
462: env->gpr[5], env->gpr[6], env->gpr[7],
463: env->gpr[8], env->gpr[9], env->gpr[10]*/);
464: else if(((int)env->gpr[0])<0)
465: ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
466: env->gpr[5], env->gpr[6], env->gpr[7],
467: env->gpr[8], env->gpr[9], env->gpr[10]);
468: else
469: ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
470: env->gpr[5], env->gpr[6], env->gpr[7],
471: env->gpr[8], env->gpr[9], env->gpr[10]);
472:
473: /* Unix syscall error signaling */
474: if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
475: {
476: if( (int)ret < 0 )
477: env->nip += 0;
478: else
479: env->nip += 4;
1.1 root 480: }
1.1.1.2 root 481:
482: /* Return value */
483: env->gpr[3] = ret;
484: break;
485: case EXCP_INTERRUPT:
486: /* just indicate that signals should be handled asap */
487: break;
488: default:
489: cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
490: break;
1.1 root 491: }
492: process_pending_signals(env);
493: }
494: }
495: #endif
496:
497:
498: #ifdef TARGET_I386
499:
500: /***********************************************************/
501: /* CPUX86 core interface */
502:
503: uint64_t cpu_get_tsc(CPUX86State *env)
504: {
505: return cpu_get_real_ticks();
506: }
507:
508: void
509: write_dt(void *ptr, unsigned long addr, unsigned long limit,
510: int flags)
511: {
512: unsigned int e1, e2;
513: e1 = (addr << 16) | (limit & 0xffff);
514: e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
515: e2 |= flags;
516: stl((uint8_t *)ptr, e1);
517: stl((uint8_t *)ptr + 4, e2);
518: }
519:
520: static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
521: unsigned long addr, unsigned int sel)
522: {
523: unsigned int e1, e2;
524: e1 = (addr & 0xffff) | (sel << 16);
525: e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
526: stl((uint8_t *)ptr, e1);
527: stl((uint8_t *)ptr + 4, e2);
528: }
529:
530: #define GDT_TABLE_SIZE 14
531: #define LDT_TABLE_SIZE 15
532: #define IDT_TABLE_SIZE 256
533: #define TSS_SIZE 104
534: uint64_t gdt_table[GDT_TABLE_SIZE];
535: uint64_t ldt_table[LDT_TABLE_SIZE];
536: uint64_t idt_table[IDT_TABLE_SIZE];
537: uint32_t tss[TSS_SIZE];
538:
539: /* only dpl matters as we do only user space emulation */
540: static void set_idt(int n, unsigned int dpl)
541: {
542: set_gate(idt_table + n, 0, dpl, 0, 0);
543: }
544:
545: /* ABI convention: after a syscall if there was an error the CF flag is set */
546: static inline void set_error(CPUX86State *env, int ret)
547: {
548: if(ret<0)
549: env->eflags = env->eflags | 0x1;
550: else
551: env->eflags &= ~0x1;
552: env->regs[R_EAX] = ret;
553: }
554:
555: void cpu_loop(CPUX86State *env)
556: {
557: int trapnr;
558: int ret;
559: uint8_t *pc;
560: target_siginfo_t info;
561:
562: for(;;) {
563: trapnr = cpu_x86_exec(env);
564: uint32_t *params = (uint32_t *)env->regs[R_ESP];
565: switch(trapnr) {
566: case 0x79: /* Our commpage hack back door exit is here */
567: do_commpage(env, env->eip, *(params + 1), *(params + 2),
568: *(params + 3), *(params + 4),
569: *(params + 5), *(params + 6),
570: *(params + 7), *(params + 8));
571: break;
572: case 0x81: /* mach syscall */
573: {
574: ret = do_mach_syscall(env, env->regs[R_EAX],
575: *(params + 1), *(params + 2),
576: *(params + 3), *(params + 4),
577: *(params + 5), *(params + 6),
578: *(params + 7), *(params + 8));
579: set_error(env, ret);
580: break;
581: }
582: case 0x90: /* unix backdoor */
583: {
584: /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
585: int saved_stack = env->regs[R_ESP];
586: env->regs[R_ESP] = env->regs[R_ECX];
587:
588: ret = do_unix_syscall(env, env->regs[R_EAX]);
589:
590: env->regs[R_ECX] = env->regs[R_ESP];
591: env->regs[R_ESP] = saved_stack;
592:
593: set_error(env, ret);
594: break;
595: }
596: case 0x80: /* unix syscall */
597: {
598: ret = do_unix_syscall(env, env->regs[R_EAX]/*,
599: *(params + 1), *(params + 2),
600: *(params + 3), *(params + 4),
601: *(params + 5), *(params + 6),
602: *(params + 7), *(params + 8)*/);
603: set_error(env, ret);
604: break;
605: }
606: case 0x82: /* thread syscall */
607: {
608: ret = do_thread_syscall(env, env->regs[R_EAX],
609: *(params + 1), *(params + 2),
610: *(params + 3), *(params + 4),
611: *(params + 5), *(params + 6),
612: *(params + 7), *(params + 8));
613: set_error(env, ret);
614: break;
615: }
616: case EXCP0B_NOSEG:
617: case EXCP0C_STACK:
618: info.si_signo = SIGBUS;
619: info.si_errno = 0;
620: info.si_code = BUS_NOOP;
621: info.si_addr = 0;
622: gdb_handlesig (env, SIGBUS);
623: queue_signal(info.si_signo, &info);
624: break;
625: case EXCP0D_GPF:
626: info.si_signo = SIGSEGV;
627: info.si_errno = 0;
628: info.si_code = SEGV_NOOP;
629: info.si_addr = 0;
630: gdb_handlesig (env, SIGSEGV);
631: queue_signal(info.si_signo, &info);
632: break;
633: case EXCP0E_PAGE:
634: info.si_signo = SIGSEGV;
635: info.si_errno = 0;
636: if (!(env->error_code & 1))
637: info.si_code = SEGV_MAPERR;
638: else
639: info.si_code = SEGV_ACCERR;
640: info.si_addr = (void*)env->cr[2];
641: gdb_handlesig (env, SIGSEGV);
642: queue_signal(info.si_signo, &info);
643: break;
644: case EXCP00_DIVZ:
645: /* division by zero */
646: info.si_signo = SIGFPE;
647: info.si_errno = 0;
648: info.si_code = FPE_INTDIV;
649: info.si_addr = (void*)env->eip;
650: gdb_handlesig (env, SIGFPE);
651: queue_signal(info.si_signo, &info);
652: break;
653: case EXCP01_SSTP:
654: case EXCP03_INT3:
655: info.si_signo = SIGTRAP;
656: info.si_errno = 0;
657: info.si_code = TRAP_BRKPT;
658: info.si_addr = (void*)env->eip;
659: gdb_handlesig (env, SIGTRAP);
660: queue_signal(info.si_signo, &info);
661: break;
662: case EXCP04_INTO:
663: case EXCP05_BOUND:
664: info.si_signo = SIGSEGV;
665: info.si_errno = 0;
666: info.si_code = SEGV_NOOP;
667: info.si_addr = 0;
668: gdb_handlesig (env, SIGSEGV);
669: queue_signal(info.si_signo, &info);
670: break;
671: case EXCP06_ILLOP:
672: info.si_signo = SIGILL;
673: info.si_errno = 0;
674: info.si_code = ILL_ILLOPN;
675: info.si_addr = (void*)env->eip;
676: gdb_handlesig (env, SIGILL);
677: queue_signal(info.si_signo, &info);
678: break;
679: case EXCP_INTERRUPT:
680: /* just indicate that signals should be handled asap */
681: break;
682: case EXCP_DEBUG:
683: {
684: int sig;
685:
686: sig = gdb_handlesig (env, SIGTRAP);
687: if (sig)
688: {
689: info.si_signo = sig;
690: info.si_errno = 0;
691: info.si_code = TRAP_BRKPT;
692: queue_signal(info.si_signo, &info);
693: }
694: }
695: break;
696: default:
697: pc = (void*)(env->segs[R_CS].base + env->eip);
698: fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
699: (long)pc, trapnr);
700: abort();
701: }
702: process_pending_signals(env);
703: }
704: }
705: #endif
706:
1.1.1.6 root 707: static void usage(void)
1.1 root 708: {
709: printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
710: "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
711: "Darwin CPU emulator (compiled for %s emulation)\n"
712: "\n"
713: "-h print this help\n"
714: "-L path set the %s library path (default='%s')\n"
715: "-s size set the stack size in bytes (default=%ld)\n"
716: "\n"
717: "debug options:\n"
718: "-d options activate log (logfile='%s')\n"
719: "-g wait for gdb on port 1234\n"
720: "-p pagesize set the host page size to 'pagesize'\n",
1.1.1.4 root 721: "-singlestep always run in singlestep mode\n"
1.1 root 722: TARGET_ARCH,
723: TARGET_ARCH,
724: interp_prefix,
725: stack_size,
726: DEBUG_LOGFILE);
1.1.1.3 root 727: exit(1);
1.1 root 728: }
729:
730: /* XXX: currently only used for async signals (see signal.c) */
731: CPUState *global_env;
732: /* used only if single thread */
733: CPUState *cpu_single_env = NULL;
734:
735: /* used to free thread contexts */
736: TaskState *first_task_state;
737:
738: int main(int argc, char **argv)
739: {
740: const char *filename;
1.1.1.7 ! root 741: const char *log_file = DEBUG_LOGFILE;
! 742: const char *log_mask = NULL;
1.1 root 743: struct target_pt_regs regs1, *regs = ®s1;
744: TaskState ts1, *ts = &ts1;
745: CPUState *env;
746: int optind;
747: short use_gdbstub = 0;
748: const char *r;
1.1.1.2 root 749: const char *cpu_model;
1.1 root 750:
751: if (argc <= 1)
752: usage();
753:
754: optind = 1;
755: for(;;) {
756: if (optind >= argc)
757: break;
758: r = argv[optind];
759: if (r[0] != '-')
760: break;
761: optind++;
762: r++;
763: if (!strcmp(r, "-")) {
764: break;
765: } else if (!strcmp(r, "d")) {
1.1.1.7 ! root 766: if (optind >= argc) {
! 767: break;
! 768: }
! 769: log_mask = argv[optind++];
! 770: } else if (!strcmp(r, "D")) {
! 771: if (optind >= argc) {
! 772: break;
1.1 root 773: }
1.1.1.7 ! root 774: log_file = argv[optind++];
1.1 root 775: } else if (!strcmp(r, "s")) {
776: r = argv[optind++];
777: stack_size = strtol(r, (char **)&r, 0);
778: if (stack_size <= 0)
779: usage();
780: if (*r == 'M')
781: stack_size *= 1024 * 1024;
782: else if (*r == 'k' || *r == 'K')
783: stack_size *= 1024;
784: } else if (!strcmp(r, "L")) {
785: interp_prefix = argv[optind++];
786: } else if (!strcmp(r, "p")) {
787: qemu_host_page_size = atoi(argv[optind++]);
788: if (qemu_host_page_size == 0 ||
789: (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
790: fprintf(stderr, "page size must be a power of two\n");
791: exit(1);
792: }
793: } else
794: if (!strcmp(r, "g")) {
795: use_gdbstub = 1;
1.1.1.2 root 796: } else if (!strcmp(r, "cpu")) {
797: cpu_model = argv[optind++];
798: if (strcmp(cpu_model, "?") == 0) {
799: /* XXX: implement xxx_cpu_list for targets that still miss it */
800: #if defined(cpu_list)
801: cpu_list(stdout, &fprintf);
1.1 root 802: #endif
1.1.1.3 root 803: exit(1);
1.1.1.2 root 804: }
1.1.1.4 root 805: } else if (!strcmp(r, "singlestep")) {
806: singlestep = 1;
1.1.1.2 root 807: } else
1.1 root 808: {
809: usage();
810: }
811: }
1.1.1.7 ! root 812:
! 813: /* init debug */
! 814: cpu_set_log_filename(log_file);
! 815: if (log_mask) {
! 816: int mask;
! 817: CPULogItem *item;
! 818:
! 819: mask = cpu_str_to_log_mask(log_mask);
! 820: if (!mask) {
! 821: printf("Log items (comma separated):\n");
! 822: for (item = cpu_log_items; item->mask != 0; item++) {
! 823: printf("%-10s %s\n", item->name, item->help);
! 824: }
! 825: exit(1);
! 826: }
! 827: cpu_set_log(mask);
! 828: }
! 829:
! 830: if (optind >= argc) {
1.1 root 831: usage();
1.1.1.7 ! root 832: }
1.1 root 833: filename = argv[optind];
834:
835: /* Zero out regs */
836: memset(regs, 0, sizeof(struct target_pt_regs));
837:
1.1.1.2 root 838: if (cpu_model == NULL) {
839: #if defined(TARGET_I386)
840: #ifdef TARGET_X86_64
841: cpu_model = "qemu64";
842: #else
843: cpu_model = "qemu32";
844: #endif
845: #elif defined(TARGET_PPC)
846: #ifdef TARGET_PPC64
847: cpu_model = "970";
848: #else
849: cpu_model = "750";
850: #endif
851: #else
852: #error unsupported CPU
853: #endif
854: }
855:
1.1.1.3 root 856: cpu_exec_init_all(0);
1.1 root 857: /* NOTE: we need to init the CPU at this stage to get
858: qemu_host_page_size */
1.1.1.2 root 859: env = cpu_init(cpu_model);
1.1.1.5 root 860: cpu_reset(env);
1.1 root 861:
862: printf("Starting %s with qemu\n----------------\n", filename);
863:
864: commpage_init();
865:
866: if (mach_exec(filename, argv+optind, environ, regs) != 0) {
867: printf("Error loading %s\n", filename);
868: _exit(1);
869: }
870:
871: syscall_init();
872: signal_init();
873: global_env = env;
874:
875: /* build Task State */
876: memset(ts, 0, sizeof(TaskState));
877: env->opaque = ts;
878: ts->used = 1;
879:
880: #if defined(TARGET_I386)
881: cpu_x86_set_cpl(env, 3);
882:
883: env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
884: env->hflags |= HF_PE_MASK;
885:
886: if (env->cpuid_features & CPUID_SSE) {
887: env->cr[4] |= CR4_OSFXSR_MASK;
888: env->hflags |= HF_OSFXSR_MASK;
889: }
890:
891: /* flags setup : we activate the IRQs by default as in user mode */
892: env->eflags |= IF_MASK;
893:
894: /* darwin register setup */
895: env->regs[R_EAX] = regs->eax;
896: env->regs[R_EBX] = regs->ebx;
897: env->regs[R_ECX] = regs->ecx;
898: env->regs[R_EDX] = regs->edx;
899: env->regs[R_ESI] = regs->esi;
900: env->regs[R_EDI] = regs->edi;
901: env->regs[R_EBP] = regs->ebp;
902: env->regs[R_ESP] = regs->esp;
903: env->eip = regs->eip;
904:
905: /* Darwin LDT setup */
906: /* 2 - User code segment
907: 3 - User data segment
908: 4 - User cthread */
909: bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
910: env->ldt.base = (uint32_t) ldt_table;
911: env->ldt.limit = sizeof(ldt_table) - 1;
912:
913: write_dt(ldt_table + 2, 0, 0xfffff,
914: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
915: (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
916: write_dt(ldt_table + 3, 0, 0xfffff,
917: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
918: (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
919: write_dt(ldt_table + 4, 0, 0xfffff,
920: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
921: (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
922:
923: /* Darwin GDT setup.
924: * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
925: now everything is done via int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
926: bzero(gdt_table, sizeof(gdt_table));
927: env->gdt.base = (uint32_t)gdt_table;
928: env->gdt.limit = sizeof(gdt_table) - 1;
929:
930: /* Set up a back door to handle sysenter syscalls (unix) */
931: char * syscallbackdoor = malloc(64);
932: page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
933:
934: int i = 0;
935: syscallbackdoor[i++] = 0xcd;
936: syscallbackdoor[i++] = 0x90; /* int 0x90 */
937: syscallbackdoor[i++] = 0x0F;
938: syscallbackdoor[i++] = 0x35; /* sysexit */
939:
940: /* Darwin sysenter/sysexit setup */
941: env->sysenter_cs = 0x1; //XXX
942: env->sysenter_eip = (int)syscallbackdoor;
943: env->sysenter_esp = (int)malloc(64);
944:
945: /* Darwin TSS setup
946: This must match up with GDT[4] */
947: env->tr.base = (uint32_t) tss;
948: env->tr.limit = sizeof(tss) - 1;
949: env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
950: stw(tss + 2, 0x10); // ss0 = 0x10 = GDT[2] = Kernel Data Segment
951:
952: /* Darwin interrupt setup */
953: bzero(idt_table, sizeof(idt_table));
954: env->idt.base = (uint32_t) idt_table;
955: env->idt.limit = sizeof(idt_table) - 1;
956: set_idt(0, 0);
957: set_idt(1, 0);
958: set_idt(2, 0);
959: set_idt(3, 3);
960: set_idt(4, 3);
961: set_idt(5, 3);
962: set_idt(6, 0);
963: set_idt(7, 0);
964: set_idt(8, 0);
965: set_idt(9, 0);
966: set_idt(10, 0);
967: set_idt(11, 0);
968: set_idt(12, 0);
969: set_idt(13, 0);
970: set_idt(14, 0);
971: set_idt(15, 0);
972: set_idt(16, 0);
973: set_idt(17, 0);
974: set_idt(18, 0);
975: set_idt(19, 0);
976: /* Syscalls are done via
977: int 0x80 (unix) (rarely used)
978: int 0x81 (mach)
979: int 0x82 (thread)
980: int 0x83 (diag) (not handled here)
981: sysenter/sysexit (unix) -> we redirect that to int 0x90 */
982: set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
983: set_idt(0x80, 3); /* Unix Syscall */
984: set_idt(0x81, 3); /* Mach Syscalls */
985: set_idt(0x82, 3); /* thread Syscalls */
986:
987: set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
988:
989:
990: cpu_x86_load_seg(env, R_CS, __USER_CS);
991: cpu_x86_load_seg(env, R_DS, __USER_DS);
992: cpu_x86_load_seg(env, R_ES, __USER_DS);
993: cpu_x86_load_seg(env, R_SS, __USER_DS);
994: cpu_x86_load_seg(env, R_FS, __USER_DS);
995: cpu_x86_load_seg(env, R_GS, __USER_DS);
996:
997: #elif defined(TARGET_PPC)
998: {
999: int i;
1.1.1.2 root 1000:
1001: #if defined(TARGET_PPC64)
1002: #if defined(TARGET_ABI32)
1003: env->msr &= ~((target_ulong)1 << MSR_SF);
1004: #else
1005: env->msr |= (target_ulong)1 << MSR_SF;
1006: #endif
1007: #endif
1.1 root 1008: env->nip = regs->nip;
1009: for(i = 0; i < 32; i++) {
1010: env->gpr[i] = regs->gpr[i];
1011: }
1012: }
1013: #else
1014: #error unsupported target CPU
1015: #endif
1016:
1017: if (use_gdbstub) {
1018: printf("Waiting for gdb Connection on port 1234...\n");
1019: gdbserver_start (1234);
1020: gdb_handlesig(env, 0);
1021: }
1022:
1023: cpu_loop(env);
1024: /* never exits */
1025: return 0;
1026: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.