1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
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:
48:
49:
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:
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: uint32_t cpu_ppc_load_atbl (CPUState *env)
128: {
129: return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
130: }
131:
132: uint32_t cpu_ppc_load_atbu (CPUState *env)
133: {
134: return cpu_ppc_get_tb(env) >> 32;
135: }
136:
137: uint32_t cpu_ppc601_load_rtcu (CPUState *env)
138: {
139: cpu_ppc_load_tbu(env);
140: }
141:
142: uint32_t cpu_ppc601_load_rtcl (CPUState *env)
143: {
144: return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
145: }
146:
147:
148: int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
149: {
150: return -1;
151: }
152:
153: int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
154: {
155: return -1;
156: }
157:
158: #define EXCP_DUMP(env, fmt, args...) \
159: do { \
160: fprintf(stderr, fmt , ##args); \
161: cpu_dump_state(env, stderr, fprintf, 0); \
162: if (loglevel != 0) { \
163: fprintf(logfile, fmt , ##args); \
164: cpu_dump_state(env, logfile, fprintf, 0); \
165: } \
166: } while (0)
167:
168: void cpu_loop(CPUPPCState *env)
169: {
170: int trapnr;
171: uint32_t ret;
172: target_siginfo_t info;
173:
174: for(;;) {
175: trapnr = cpu_ppc_exec(env);
176: switch(trapnr) {
177: case POWERPC_EXCP_NONE:
178:
179: break;
180: case POWERPC_EXCP_CRITICAL:
181: cpu_abort(env, "Critical interrupt while in user mode. "
182: "Aborting\n");
183: break;
184: case POWERPC_EXCP_MCHECK:
185: cpu_abort(env, "Machine check exception while in user mode. "
186: "Aborting\n");
187: break;
188: case POWERPC_EXCP_DSI:
189: #ifndef DAR
190:
191: # define DAR SPR_DAR
192: #endif
193: EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
194: env->spr[SPR_DAR]);
195:
196: gdb_handlesig (env, SIGSEGV);
197:
198: info.si_addr = (void*)env->nip;
199: queue_signal(info.si_signo, &info);
200: break;
201: case POWERPC_EXCP_ISI:
202: EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
203: env->spr[SPR_DAR]);
204:
205: gdb_handlesig (env, SIGSEGV);
206:
207: info.si_addr = (void*)(env->nip - 4);
208: queue_signal(info.si_signo, &info);
209: break;
210: case POWERPC_EXCP_EXTERNAL:
211: cpu_abort(env, "External interrupt while in user mode. "
212: "Aborting\n");
213: break;
214: case POWERPC_EXCP_ALIGN:
215: EXCP_DUMP(env, "Unaligned memory access\n");
216: info.si_errno = 0;
217: info.si_code = BUS_ADRALN;
218: info.si_addr = (void*)(env->nip - 4);
219: queue_signal(info.si_signo, &info);
220: break;
221: case POWERPC_EXCP_PROGRAM:
222:
223: switch (env->error_code & ~0xF) {
224: case POWERPC_EXCP_FP:
225: EXCP_DUMP(env, "Floating point program exception\n");
226:
227: info.si_signo = SIGFPE;
228: info.si_errno = 0;
229: switch (env->error_code & 0xF) {
230: case POWERPC_EXCP_FP_OX:
231: info.si_code = FPE_FLTOVF;
232: break;
233: case POWERPC_EXCP_FP_UX:
234: info.si_code = FPE_FLTUND;
235: break;
236: case POWERPC_EXCP_FP_ZX:
237: case POWERPC_EXCP_FP_VXZDZ:
238: info.si_code = FPE_FLTDIV;
239: break;
240: case POWERPC_EXCP_FP_XX:
241: info.si_code = FPE_FLTRES;
242: break;
243: case POWERPC_EXCP_FP_VXSOFT:
244: info.si_code = FPE_FLTINV;
245: break;
246: case POWERPC_EXCP_FP_VXSNAN:
247: case POWERPC_EXCP_FP_VXISI:
248: case POWERPC_EXCP_FP_VXIDI:
249: case POWERPC_EXCP_FP_VXIMZ:
250: case POWERPC_EXCP_FP_VXVC:
251: case POWERPC_EXCP_FP_VXSQRT:
252: case POWERPC_EXCP_FP_VXCVI:
253: info.si_code = FPE_FLTSUB;
254: break;
255: default:
256: EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
257: env->error_code);
258: break;
259: }
260: break;
261: case POWERPC_EXCP_INVAL:
262: EXCP_DUMP(env, "Invalid instruction\n");
263: info.si_signo = SIGILL;
264: info.si_errno = 0;
265: switch (env->error_code & 0xF) {
266: case POWERPC_EXCP_INVAL_INVAL:
267: info.si_code = ILL_ILLOPC;
268: break;
269: case POWERPC_EXCP_INVAL_LSWX:
270: info.si_code = ILL_ILLOPN;
271: break;
272: case POWERPC_EXCP_INVAL_SPR:
273: info.si_code = ILL_PRVREG;
274: break;
275: case POWERPC_EXCP_INVAL_FP:
276: info.si_code = ILL_COPROC;
277: break;
278: default:
279: EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
280: env->error_code & 0xF);
281: info.si_code = ILL_ILLADR;
282: break;
283: }
284:
285: gdb_handlesig (env, SIGSEGV);
286: break;
287: case POWERPC_EXCP_PRIV:
288: EXCP_DUMP(env, "Privilege violation\n");
289: info.si_signo = SIGILL;
290: info.si_errno = 0;
291: switch (env->error_code & 0xF) {
292: case POWERPC_EXCP_PRIV_OPC:
293: info.si_code = ILL_PRVOPC;
294: break;
295: case POWERPC_EXCP_PRIV_REG:
296: info.si_code = ILL_PRVREG;
297: break;
298: default:
299: EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
300: env->error_code & 0xF);
301: info.si_code = ILL_PRVOPC;
302: break;
303: }
304: break;
305: case POWERPC_EXCP_TRAP:
306: cpu_abort(env, "Tried to call a TRAP\n");
307: break;
308: default:
309:
310: cpu_abort(env, "Unknown program exception (%02x)\n",
311: env->error_code);
312: break;
313: }
314: info.si_addr = (void*)(env->nip - 4);
315: queue_signal(info.si_signo, &info);
316: break;
317: case POWERPC_EXCP_FPU:
318: EXCP_DUMP(env, "No floating point allowed\n");
319: info.si_signo = SIGILL;
320: info.si_errno = 0;
321: info.si_code = ILL_COPROC;
322: info.si_addr = (void*)(env->nip - 4);
323: queue_signal(info.si_signo, &info);
324: break;
325: case POWERPC_EXCP_SYSCALL:
326: cpu_abort(env, "Syscall exception while in user mode. "
327: "Aborting\n");
328: break;
329: case POWERPC_EXCP_APU:
330: EXCP_DUMP(env, "No APU instruction allowed\n");
331: info.si_signo = SIGILL;
332: info.si_errno = 0;
333: info.si_code = ILL_COPROC;
334: info.si_addr = (void*)(env->nip - 4);
335: queue_signal(info.si_signo, &info);
336: break;
337: case POWERPC_EXCP_DECR:
338: cpu_abort(env, "Decrementer interrupt while in user mode. "
339: "Aborting\n");
340: break;
341: case POWERPC_EXCP_FIT:
342: cpu_abort(env, "Fix interval timer interrupt while in user mode. "
343: "Aborting\n");
344: break;
345: case POWERPC_EXCP_WDT:
346: cpu_abort(env, "Watchdog timer interrupt while in user mode. "
347: "Aborting\n");
348: break;
349: case POWERPC_EXCP_DTLB:
350: cpu_abort(env, "Data TLB exception while in user mode. "
351: "Aborting\n");
352: break;
353: case POWERPC_EXCP_ITLB:
354: cpu_abort(env, "Instruction TLB exception while in user mode. "
355: "Aborting\n");
356: break;
357: case POWERPC_EXCP_DEBUG:
358: gdb_handlesig (env, SIGTRAP);
359: break;
360: case POWERPC_EXCP_SPEU:
361: EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
362: info.si_signo = SIGILL;
363: info.si_errno = 0;
364: info.si_code = ILL_COPROC;
365: info.si_addr = (void*)(env->nip - 4);
366: queue_signal(info.si_signo, &info);
367: break;
368: case POWERPC_EXCP_EFPDI:
369: cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
370: break;
371: case POWERPC_EXCP_EFPRI:
372: cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
373: break;
374: case POWERPC_EXCP_EPERFM:
375: cpu_abort(env, "Performance monitor exception not handled\n");
376: break;
377: case POWERPC_EXCP_DOORI:
378: cpu_abort(env, "Doorbell interrupt while in user mode. "
379: "Aborting\n");
380: break;
381: case POWERPC_EXCP_DOORCI:
382: cpu_abort(env, "Doorbell critical interrupt while in user mode. "
383: "Aborting\n");
384: break;
385: case POWERPC_EXCP_RESET:
386: cpu_abort(env, "Reset interrupt while in user mode. "
387: "Aborting\n");
388: break;
389: case POWERPC_EXCP_DSEG:
390: cpu_abort(env, "Data segment exception while in user mode. "
391: "Aborting\n");
392: break;
393: case POWERPC_EXCP_ISEG:
394: cpu_abort(env, "Instruction segment exception "
395: "while in user mode. Aborting\n");
396: break;
397: case POWERPC_EXCP_HDECR:
398: cpu_abort(env, "Hypervisor decrementer interrupt "
399: "while in user mode. Aborting\n");
400: break;
401: case POWERPC_EXCP_TRACE:
402:
403:
404:
405: break;
406: case POWERPC_EXCP_HDSI:
407: cpu_abort(env, "Hypervisor data storage exception "
408: "while in user mode. Aborting\n");
409: break;
410: case POWERPC_EXCP_HISI:
411: cpu_abort(env, "Hypervisor instruction storage exception "
412: "while in user mode. Aborting\n");
413: break;
414: case POWERPC_EXCP_HDSEG:
415: cpu_abort(env, "Hypervisor data segment exception "
416: "while in user mode. Aborting\n");
417: break;
418: case POWERPC_EXCP_HISEG:
419: cpu_abort(env, "Hypervisor instruction segment exception "
420: "while in user mode. Aborting\n");
421: break;
422: case POWERPC_EXCP_VPU:
423: EXCP_DUMP(env, "No Altivec instructions allowed\n");
424: info.si_signo = SIGILL;
425: info.si_errno = 0;
426: info.si_code = ILL_COPROC;
427: info.si_addr = (void*)(env->nip - 4);
428: queue_signal(info.si_signo, &info);
429: break;
430: case POWERPC_EXCP_PIT:
431: cpu_abort(env, "Programable interval timer interrupt "
432: "while in user mode. Aborting\n");
433: break;
434: case POWERPC_EXCP_IO:
435: cpu_abort(env, "IO error exception while in user mode. "
436: "Aborting\n");
437: break;
438: case POWERPC_EXCP_RUNM:
439: cpu_abort(env, "Run mode exception while in user mode. "
440: "Aborting\n");
441: break;
442: case POWERPC_EXCP_EMUL:
443: cpu_abort(env, "Emulation trap exception not handled\n");
444: break;
445: case POWERPC_EXCP_IFTLB:
446: cpu_abort(env, "Instruction fetch TLB exception "
447: "while in user-mode. Aborting");
448: break;
449: case POWERPC_EXCP_DLTLB:
450: cpu_abort(env, "Data load TLB exception while in user-mode. "
451: "Aborting");
452: break;
453: case POWERPC_EXCP_DSTLB:
454: cpu_abort(env, "Data store TLB exception while in user-mode. "
455: "Aborting");
456: break;
457: case POWERPC_EXCP_FPA:
458: cpu_abort(env, "Floating-point assist exception not handled\n");
459: break;
460: case POWERPC_EXCP_IABR:
461: cpu_abort(env, "Instruction address breakpoint exception "
462: "not handled\n");
463: break;
464: case POWERPC_EXCP_SMI:
465: cpu_abort(env, "System management interrupt while in user mode. "
466: "Aborting\n");
467: break;
468: case POWERPC_EXCP_THERM:
469: cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
470: "Aborting\n");
471: break;
472: case POWERPC_EXCP_PERFM:
473: cpu_abort(env, "Performance monitor exception not handled\n");
474: break;
475: case POWERPC_EXCP_VPUA:
476: cpu_abort(env, "Vector assist exception not handled\n");
477: break;
478: case POWERPC_EXCP_SOFTP:
479: cpu_abort(env, "Soft patch exception not handled\n");
480: break;
481: case POWERPC_EXCP_MAINT:
482: cpu_abort(env, "Maintenance exception while in user mode. "
483: "Aborting\n");
484: break;
485: case POWERPC_EXCP_STOP:
486:
487: break;
488: case POWERPC_EXCP_BRANCH:
489:
490: break;
491: case POWERPC_EXCP_SYSCALL_USER:
492:
493:
494: if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
495: ret = do_unix_syscall(env, env->gpr[0]
496:
497: );
498: else if(((int)env->gpr[0])<0)
499: ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
500: env->gpr[5], env->gpr[6], env->gpr[7],
501: env->gpr[8], env->gpr[9], env->gpr[10]);
502: else
503: ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
504: env->gpr[5], env->gpr[6], env->gpr[7],
505: env->gpr[8], env->gpr[9], env->gpr[10]);
506:
507:
508: if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
509: {
510: if( (int)ret < 0 )
511: env->nip += 0;
512: else
513: env->nip += 4;
514: }
515:
516:
517: env->gpr[3] = ret;
518: break;
519: case EXCP_INTERRUPT:
520:
521: break;
522: default:
523: cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
524: break;
525: }
526: process_pending_signals(env);
527: }
528: }
529: #endif
530:
531:
532: #ifdef TARGET_I386
533:
534:
535:
536:
537: uint64_t cpu_get_tsc(CPUX86State *env)
538: {
539: return cpu_get_real_ticks();
540: }
541:
542: void
543: write_dt(void *ptr, unsigned long addr, unsigned long limit,
544: int flags)
545: {
546: unsigned int e1, e2;
547: e1 = (addr <<