|
|
1.1 root 1: /*
2: * qemu user main
3: *
4: * Copyright (c) 2003 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
17: * along with this program; if not, write to the Free Software
18: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 "qemu.h"
28:
29: #define DEBUG_LOGFILE "/tmp/qemu.log"
30:
31: #ifdef __APPLE__
32: #include <crt_externs.h>
33: # define environ (*_NSGetEnviron())
34: #endif
35:
36: static const char *interp_prefix = CONFIG_QEMU_PREFIX;
37:
38: #if defined(__i386__) && !defined(CONFIG_STATIC)
39: /* Force usage of an ELF interpreter even if it is an ELF shared
40: object ! */
41: const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
42: #endif
43:
44: /* for recent libc, we add these dummy symbols which are not declared
45: when generating a linked object (bug in ld ?) */
46: #if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
47: long __preinit_array_start[0];
48: long __preinit_array_end[0];
49: long __init_array_start[0];
50: long __init_array_end[0];
51: long __fini_array_start[0];
52: long __fini_array_end[0];
53: #endif
54:
55: /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
56: we allocate a bigger stack. Need a better solution, for example
57: by remapping the process stack directly at the right place */
58: unsigned long x86_stack_size = 512 * 1024;
59:
60: void gemu_log(const char *fmt, ...)
61: {
62: va_list ap;
63:
64: va_start(ap, fmt);
65: vfprintf(stderr, fmt, ap);
66: va_end(ap);
67: }
68:
69: void cpu_outb(CPUState *env, int addr, int val)
70: {
71: fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
72: }
73:
74: void cpu_outw(CPUState *env, int addr, int val)
75: {
76: fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
77: }
78:
79: void cpu_outl(CPUState *env, int addr, int val)
80: {
81: fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
82: }
83:
84: int cpu_inb(CPUState *env, int addr)
85: {
86: fprintf(stderr, "inb: port=0x%04x\n", addr);
87: return 0;
88: }
89:
90: int cpu_inw(CPUState *env, int addr)
91: {
92: fprintf(stderr, "inw: port=0x%04x\n", addr);
93: return 0;
94: }
95:
96: int cpu_inl(CPUState *env, int addr)
97: {
98: fprintf(stderr, "inl: port=0x%04x\n", addr);
99: return 0;
100: }
101:
102: int cpu_get_pic_interrupt(CPUState *env)
103: {
104: return -1;
105: }
106:
107: /* timers for rdtsc */
108:
109: #if defined(__i386__)
110:
111: int64_t cpu_get_real_ticks(void)
112: {
113: int64_t val;
114: asm volatile ("rdtsc" : "=A" (val));
115: return val;
116: }
117:
118: #elif defined(__x86_64__)
119:
120: int64_t cpu_get_real_ticks(void)
121: {
122: uint32_t low,high;
123: int64_t val;
124: asm volatile("rdtsc" : "=a" (low), "=d" (high));
125: val = high;
126: val <<= 32;
127: val |= low;
128: return val;
129: }
130:
131: #else
132:
133: static uint64_t emu_time;
134:
135: int64_t cpu_get_real_ticks(void)
136: {
137: return emu_time++;
138: }
139:
140: #endif
141:
142: #ifdef TARGET_I386
143: /***********************************************************/
144: /* CPUX86 core interface */
145:
146: uint64_t cpu_get_tsc(CPUX86State *env)
147: {
148: return cpu_get_real_ticks();
149: }
150:
151: static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
152: int flags)
153: {
154: unsigned int e1, e2;
155: e1 = (addr << 16) | (limit & 0xffff);
156: e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
157: e2 |= flags;
158: stl((uint8_t *)ptr, e1);
159: stl((uint8_t *)ptr + 4, e2);
160: }
161:
162: static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
163: unsigned long addr, unsigned int sel)
164: {
165: unsigned int e1, e2;
166: e1 = (addr & 0xffff) | (sel << 16);
167: e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
168: stl((uint8_t *)ptr, e1);
169: stl((uint8_t *)ptr + 4, e2);
170: }
171:
172: uint64_t gdt_table[6];
173: uint64_t idt_table[256];
174:
175: /* only dpl matters as we do only user space emulation */
176: static void set_idt(int n, unsigned int dpl)
177: {
178: set_gate(idt_table + n, 0, dpl, 0, 0);
179: }
180:
181: void cpu_loop(CPUX86State *env)
182: {
183: int trapnr;
184: target_ulong pc;
185: target_siginfo_t info;
186:
187: for(;;) {
188: trapnr = cpu_x86_exec(env);
189: switch(trapnr) {
190: case 0x80:
191: /* linux syscall */
192: env->regs[R_EAX] = do_syscall(env,
193: env->regs[R_EAX],
194: env->regs[R_EBX],
195: env->regs[R_ECX],
196: env->regs[R_EDX],
197: env->regs[R_ESI],
198: env->regs[R_EDI],
199: env->regs[R_EBP]);
200: break;
201: case EXCP0B_NOSEG:
202: case EXCP0C_STACK:
203: info.si_signo = SIGBUS;
204: info.si_errno = 0;
205: info.si_code = TARGET_SI_KERNEL;
206: info._sifields._sigfault._addr = 0;
207: queue_signal(info.si_signo, &info);
208: break;
209: case EXCP0D_GPF:
210: if (env->eflags & VM_MASK) {
211: handle_vm86_fault(env);
212: } else {
213: info.si_signo = SIGSEGV;
214: info.si_errno = 0;
215: info.si_code = TARGET_SI_KERNEL;
216: info._sifields._sigfault._addr = 0;
217: queue_signal(info.si_signo, &info);
218: }
219: break;
220: case EXCP0E_PAGE:
221: info.si_signo = SIGSEGV;
222: info.si_errno = 0;
223: if (!(env->error_code & 1))
224: info.si_code = TARGET_SEGV_MAPERR;
225: else
226: info.si_code = TARGET_SEGV_ACCERR;
227: info._sifields._sigfault._addr = env->cr[2];
228: queue_signal(info.si_signo, &info);
229: break;
230: case EXCP00_DIVZ:
231: if (env->eflags & VM_MASK) {
232: handle_vm86_trap(env, trapnr);
233: } else {
234: /* division by zero */
235: info.si_signo = SIGFPE;
236: info.si_errno = 0;
237: info.si_code = TARGET_FPE_INTDIV;
238: info._sifields._sigfault._addr = env->eip;
239: queue_signal(info.si_signo, &info);
240: }
241: break;
242: case EXCP01_SSTP:
243: case EXCP03_INT3:
244: if (env->eflags & VM_MASK) {
245: handle_vm86_trap(env, trapnr);
246: } else {
247: info.si_signo = SIGTRAP;
248: info.si_errno = 0;
249: if (trapnr == EXCP01_SSTP) {
250: info.si_code = TARGET_TRAP_BRKPT;
251: info._sifields._sigfault._addr = env->eip;
252: } else {
253: info.si_code = TARGET_SI_KERNEL;
254: info._sifields._sigfault._addr = 0;
255: }
256: queue_signal(info.si_signo, &info);
257: }
258: break;
259: case EXCP04_INTO:
260: case EXCP05_BOUND:
261: if (env->eflags & VM_MASK) {
262: handle_vm86_trap(env, trapnr);
263: } else {
264: info.si_signo = SIGSEGV;
265: info.si_errno = 0;
266: info.si_code = TARGET_SI_KERNEL;
267: info._sifields._sigfault._addr = 0;
268: queue_signal(info.si_signo, &info);
269: }
270: break;
271: case EXCP06_ILLOP:
272: info.si_signo = SIGILL;
273: info.si_errno = 0;
274: info.si_code = TARGET_ILL_ILLOPN;
275: info._sifields._sigfault._addr = env->eip;
276: queue_signal(info.si_signo, &info);
277: break;
278: case EXCP_INTERRUPT:
279: /* just indicate that signals should be handled asap */
280: break;
281: case EXCP_DEBUG:
282: {
283: int sig;
284:
285: sig = gdb_handlesig (env, TARGET_SIGTRAP);
286: if (sig)
287: {
288: info.si_signo = sig;
289: info.si_errno = 0;
290: info.si_code = TARGET_TRAP_BRKPT;
291: queue_signal(info.si_signo, &info);
292: }
293: }
294: break;
295: default:
296: pc = env->segs[R_CS].base + env->eip;
297: fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
298: (long)pc, trapnr);
299: abort();
300: }
301: process_pending_signals(env);
302: }
303: }
304: #endif
305:
306: #ifdef TARGET_ARM
307:
308: /* XXX: find a better solution */
309: extern void tb_invalidate_page_range(target_ulong start, target_ulong end);
310:
311: static void arm_cache_flush(target_ulong start, target_ulong last)
312: {
313: target_ulong addr, last1;
314:
315: if (last < start)
316: return;
317: addr = start;
318: for(;;) {
319: last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;
320: if (last1 > last)
321: last1 = last;
322: tb_invalidate_page_range(addr, last1 + 1);
323: if (last1 == last)
324: break;
325: addr = last1 + 1;
326: }
327: }
328:
329: void cpu_loop(CPUARMState *env)
330: {
331: int trapnr;
332: unsigned int n, insn;
333: target_siginfo_t info;
334:
335: for(;;) {
336: trapnr = cpu_arm_exec(env);
337: switch(trapnr) {
338: case EXCP_UDEF:
339: {
340: TaskState *ts = env->opaque;
341: uint32_t opcode;
342:
343: /* we handle the FPU emulation here, as Linux */
344: /* we get the opcode */
345: opcode = ldl_raw((uint8_t *)env->regs[15]);
346:
347: if (EmulateAll(opcode, &ts->fpa, env->regs) == 0) {
348: info.si_signo = SIGILL;
349: info.si_errno = 0;
350: info.si_code = TARGET_ILL_ILLOPN;
351: info._sifields._sigfault._addr = env->regs[15];
352: queue_signal(info.si_signo, &info);
353: } else {
354: /* increment PC */
355: env->regs[15] += 4;
356: }
357: }
358: break;
359: case EXCP_SWI:
360: {
361: /* system call */
362: if (env->thumb) {
363: insn = lduw((void *)(env->regs[15] - 2));
364: n = insn & 0xff;
365: } else {
366: insn = ldl((void *)(env->regs[15] - 4));
367: n = insn & 0xffffff;
368: }
369:
370: if (n == ARM_NR_cacheflush) {
371: arm_cache_flush(env->regs[0], env->regs[1]);
372: } else if (n == ARM_NR_semihosting
373: || n == ARM_NR_thumb_semihosting) {
374: env->regs[0] = do_arm_semihosting (env);
375: } else if (n >= ARM_SYSCALL_BASE
376: || (env->thumb && n == ARM_THUMB_SYSCALL)) {
377: /* linux syscall */
378: if (env->thumb) {
379: n = env->regs[7];
380: } else {
381: n -= ARM_SYSCALL_BASE;
382: }
383: env->regs[0] = do_syscall(env,
384: n,
385: env->regs[0],
386: env->regs[1],
387: env->regs[2],
388: env->regs[3],
389: env->regs[4],
390: env->regs[5]);
391: } else {
392: goto error;
393: }
394: }
395: break;
396: case EXCP_INTERRUPT:
397: /* just indicate that signals should be handled asap */
398: break;
399: case EXCP_PREFETCH_ABORT:
400: case EXCP_DATA_ABORT:
401: {
402: info.si_signo = SIGSEGV;
403: info.si_errno = 0;
404: /* XXX: check env->error_code */
405: info.si_code = TARGET_SEGV_MAPERR;
406: info._sifields._sigfault._addr = env->cp15_6;
407: queue_signal(info.si_signo, &info);
408: }
409: break;
410: case EXCP_DEBUG:
411: {
412: int sig;
413:
414: sig = gdb_handlesig (env, TARGET_SIGTRAP);
415: if (sig)
416: {
417: info.si_signo = sig;
418: info.si_errno = 0;
419: info.si_code = TARGET_TRAP_BRKPT;
420: queue_signal(info.si_signo, &info);
421: }
422: }
423: break;
424: default:
425: error:
426: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
427: trapnr);
428: cpu_dump_state(env, stderr, fprintf, 0);
429: abort();
430: }
431: process_pending_signals(env);
432: }
433: }
434:
435: #endif
436:
437: #ifdef TARGET_SPARC
438:
439: //#define DEBUG_WIN
440:
441: /* WARNING: dealing with register windows _is_ complicated. More info
442: can be found at http://www.sics.se/~psm/sparcstack.html */
443: static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
444: {
445: index = (index + cwp * 16) & (16 * NWINDOWS - 1);
446: /* wrap handling : if cwp is on the last window, then we use the
447: registers 'after' the end */
448: if (index < 8 && env->cwp == (NWINDOWS - 1))
449: index += (16 * NWINDOWS);
450: return index;
451: }
452:
453: /* save the register window 'cwp1' */
454: static inline void save_window_offset(CPUSPARCState *env, int cwp1)
455: {
456: unsigned int i;
457: uint32_t *sp_ptr;
458:
459: sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
460: #if defined(DEBUG_WIN)
461: printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n",
462: (int)sp_ptr, cwp1);
463: #endif
464: for(i = 0; i < 16; i++) {
465: put_user(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
466: sp_ptr++;
467: }
468: }
469:
470: static void save_window(CPUSPARCState *env)
471: {
472: unsigned int new_wim;
473: new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
474: ((1LL << NWINDOWS) - 1);
475: save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
476: env->wim = new_wim;
477: }
478:
479: static void restore_window(CPUSPARCState *env)
480: {
481: unsigned int new_wim, i, cwp1;
482: uint32_t *sp_ptr, reg;
483:
484: new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
485: ((1LL << NWINDOWS) - 1);
486:
487: /* restore the invalid window */
488: cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
489: sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
490: #if defined(DEBUG_WIN)
491: printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n",
492: (int)sp_ptr, cwp1);
493: #endif
494: for(i = 0; i < 16; i++) {
495: get_user(reg, sp_ptr);
496: env->regbase[get_reg_index(env, cwp1, 8 + i)] = reg;
497: sp_ptr++;
498: }
499: env->wim = new_wim;
500: }
501:
502: static void flush_windows(CPUSPARCState *env)
503: {
504: int offset, cwp1;
505:
506: offset = 1;
507: for(;;) {
508: /* if restore would invoke restore_window(), then we can stop */
509: cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
510: if (env->wim & (1 << cwp1))
511: break;
512: save_window_offset(env, cwp1);
513: offset++;
514: }
515: /* set wim so that restore will reload the registers */
516: cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
517: env->wim = 1 << cwp1;
518: #if defined(DEBUG_WIN)
519: printf("flush_windows: nb=%d\n", offset - 1);
520: #endif
521: }
522:
523: void cpu_loop (CPUSPARCState *env)
524: {
525: int trapnr, ret;
526: target_siginfo_t info;
527:
528: while (1) {
529: trapnr = cpu_sparc_exec (env);
530:
531: switch (trapnr) {
532: case 0x88:
533: case 0x90:
534: ret = do_syscall (env, env->gregs[1],
535: env->regwptr[0], env->regwptr[1],
536: env->regwptr[2], env->regwptr[3],
537: env->regwptr[4], env->regwptr[5]);
538: if ((unsigned int)ret >= (unsigned int)(-515)) {
539: env->psr |= PSR_CARRY;
540: ret = -ret;
541: } else {
542: env->psr &= ~PSR_CARRY;
543: }
544: env->regwptr[0] = ret;
545: /* next instruction */
546: env->pc = env->npc;
547: env->npc = env->npc + 4;
548: break;
549: case 0x83: /* flush windows */
550: flush_windows(env);
551: /* next instruction */
552: env->pc = env->npc;
553: env->npc = env->npc + 4;
554: break;
555: #ifndef TARGET_SPARC64
556: case TT_WIN_OVF: /* window overflow */
557: save_window(env);
558: break;
559: case TT_WIN_UNF: /* window underflow */
560: restore_window(env);
561: break;
562: case TT_TFAULT:
563: case TT_DFAULT:
564: {
565: info.si_signo = SIGSEGV;
566: info.si_errno = 0;
567: /* XXX: check env->error_code */
568: info.si_code = TARGET_SEGV_MAPERR;
569: info._sifields._sigfault._addr = env->mmuregs[4];
570: queue_signal(info.si_signo, &info);
571: }
572: break;
573: #else
574: // XXX
575: #endif
576: case 0x100: // XXX, why do we get these?
577: break;
578: case EXCP_DEBUG:
579: {
580: int sig;
581:
582: sig = gdb_handlesig (env, TARGET_SIGTRAP);
583: if (sig)
584: {
585: info.si_signo = sig;
586: info.si_errno = 0;
587: info.si_code = TARGET_TRAP_BRKPT;
588: queue_signal(info.si_signo, &info);
589: }
590: }
591: break;
592: default:
593: printf ("Unhandled trap: 0x%x\n", trapnr);
594: cpu_dump_state(env, stderr, fprintf, 0);
595: exit (1);
596: }
597: process_pending_signals (env);
598: }
599: }
600:
601: #endif
602:
603: #ifdef TARGET_PPC
604:
605: static inline uint64_t cpu_ppc_get_tb (CPUState *env)
606: {
607: /* TO FIX */
608: return 0;
609: }
610:
611: uint32_t cpu_ppc_load_tbl (CPUState *env)
612: {
613: return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
614: }
615:
616: uint32_t cpu_ppc_load_tbu (CPUState *env)
617: {
618: return cpu_ppc_get_tb(env) >> 32;
619: }
620:
621: static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
622: {
623: /* TO FIX */
624: }
625:
626: void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
627: {
628: cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
629: }
630:
631: void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
632: {
633: cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
634: }
635:
636: uint32_t cpu_ppc_load_decr (CPUState *env)
637: {
638: /* TO FIX */
639: return -1;
640: }
641:
642: void cpu_ppc_store_decr (CPUState *env, uint32_t value)
643: {
644: /* TO FIX */
645: }
646:
647: void cpu_loop(CPUPPCState *env)
648: {
649: target_siginfo_t info;
650: int trapnr;
651: uint32_t ret;
652:
653: for(;;) {
654: trapnr = cpu_ppc_exec(env);
655: if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
656: trapnr != EXCP_TRACE) {
657: if (loglevel > 0) {
658: cpu_dump_state(env, logfile, fprintf, 0);
659: }
660: }
661: switch(trapnr) {
662: case EXCP_NONE:
663: break;
664: case EXCP_SYSCALL_USER:
665: /* system call */
666: /* WARNING:
667: * PPC ABI uses overflow flag in cr0 to signal an error
668: * in syscalls.
669: */
670: #if 0
671: printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
672: env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
673: #endif
674: env->crf[0] &= ~0x1;
675: ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
676: env->gpr[5], env->gpr[6], env->gpr[7],
677: env->gpr[8]);
678: if (ret > (uint32_t)(-515)) {
679: env->crf[0] |= 0x1;
680: ret = -ret;
681: }
682: env->gpr[3] = ret;
683: #if 0
684: printf("syscall returned 0x%08x (%d)\n", ret, ret);
685: #endif
686: break;
687: case EXCP_RESET:
688: /* Should not happen ! */
689: fprintf(stderr, "RESET asked... Stop emulation\n");
690: if (loglevel)
691: fprintf(logfile, "RESET asked... Stop emulation\n");
692: abort();
693: case EXCP_MACHINE_CHECK:
694: fprintf(stderr, "Machine check exeption... Stop emulation\n");
695: if (loglevel)
696: fprintf(logfile, "RESET asked... Stop emulation\n");
697: info.si_signo = TARGET_SIGBUS;
698: info.si_errno = 0;
699: info.si_code = TARGET_BUS_OBJERR;
700: info._sifields._sigfault._addr = env->nip - 4;
701: queue_signal(info.si_signo, &info);
702: case EXCP_DSI:
703: fprintf(stderr, "Invalid data memory access: 0x%08x\n",
704: env->spr[SPR_DAR]);
705: if (loglevel) {
706: fprintf(logfile, "Invalid data memory access: 0x%08x\n",
707: env->spr[SPR_DAR]);
708: }
709: switch (env->error_code & 0xFF000000) {
710: case 0x40000000:
711: info.si_signo = TARGET_SIGSEGV;
712: info.si_errno = 0;
713: info.si_code = TARGET_SEGV_MAPERR;
714: break;
715: case 0x04000000:
716: info.si_signo = TARGET_SIGILL;
717: info.si_errno = 0;
718: info.si_code = TARGET_ILL_ILLADR;
719: break;
720: case 0x08000000:
721: info.si_signo = TARGET_SIGSEGV;
722: info.si_errno = 0;
723: info.si_code = TARGET_SEGV_ACCERR;
724: break;
725: default:
726: /* Let's send a regular segfault... */
727: fprintf(stderr, "Invalid segfault errno (%02x)\n",
728: env->error_code);
729: if (loglevel) {
730: fprintf(logfile, "Invalid segfault errno (%02x)\n",
731: env->error_code);
732: }
733: info.si_signo = TARGET_SIGSEGV;
734: info.si_errno = 0;
735: info.si_code = TARGET_SEGV_MAPERR;
736: break;
737: }
738: info._sifields._sigfault._addr = env->nip;
739: queue_signal(info.si_signo, &info);
740: break;
741: case EXCP_ISI:
742: fprintf(stderr, "Invalid instruction fetch\n");
743: if (loglevel)
744: fprintf(logfile, "Invalid instruction fetch\n");
745: switch (env->error_code & 0xFF000000) {
746: case 0x40000000:
747: info.si_signo = TARGET_SIGSEGV;
748: info.si_errno = 0;
749: info.si_code = TARGET_SEGV_MAPERR;
750: break;
751: case 0x10000000:
752: case 0x08000000:
753: info.si_signo = TARGET_SIGSEGV;
754: info.si_errno = 0;
755: info.si_code = TARGET_SEGV_ACCERR;
756: break;
757: default:
758: /* Let's send a regular segfault... */
759: fprintf(stderr, "Invalid segfault errno (%02x)\n",
760: env->error_code);
761: if (loglevel) {
762: fprintf(logfile, "Invalid segfault errno (%02x)\n",
763: env->error_code);
764: }
765: info.si_signo = TARGET_SIGSEGV;
766: info.si_errno = 0;
767: info.si_code = TARGET_SEGV_MAPERR;
768: break;
769: }
770: info._sifields._sigfault._addr = env->nip - 4;
771: queue_signal(info.si_signo, &info);
772: break;
773: case EXCP_EXTERNAL:
774: /* Should not happen ! */
775: fprintf(stderr, "External interruption... Stop emulation\n");
776: if (loglevel)
777: fprintf(logfile, "External interruption... Stop emulation\n");
778: abort();
779: case EXCP_ALIGN:
780: fprintf(stderr, "Invalid unaligned memory access\n");
781: if (loglevel)
782: fprintf(logfile, "Invalid unaligned memory access\n");
783: info.si_signo = TARGET_SIGBUS;
784: info.si_errno = 0;
785: info.si_code = TARGET_BUS_ADRALN;
786: info._sifields._sigfault._addr = env->nip - 4;
787: queue_signal(info.si_signo, &info);
788: break;
789: case EXCP_PROGRAM:
790: switch (env->error_code & ~0xF) {
791: case EXCP_FP:
792: fprintf(stderr, "Program exception\n");
793: if (loglevel)
794: fprintf(logfile, "Program exception\n");
795: /* Set FX */
796: env->fpscr[7] |= 0x8;
797: /* Finally, update FEX */
798: if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
799: ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
800: env->fpscr[7] |= 0x4;
801: info.si_signo = TARGET_SIGFPE;
802: info.si_errno = 0;
803: switch (env->error_code & 0xF) {
804: case EXCP_FP_OX:
805: info.si_code = TARGET_FPE_FLTOVF;
806: break;
807: case EXCP_FP_UX:
808: info.si_code = TARGET_FPE_FLTUND;
809: break;
810: case EXCP_FP_ZX:
811: case EXCP_FP_VXZDZ:
812: info.si_code = TARGET_FPE_FLTDIV;
813: break;
814: case EXCP_FP_XX:
815: info.si_code = TARGET_FPE_FLTRES;
816: break;
817: case EXCP_FP_VXSOFT:
818: info.si_code = TARGET_FPE_FLTINV;
819: break;
820: case EXCP_FP_VXNAN:
821: case EXCP_FP_VXISI:
822: case EXCP_FP_VXIDI:
823: case EXCP_FP_VXIMZ:
824: case EXCP_FP_VXVC:
825: case EXCP_FP_VXSQRT:
826: case EXCP_FP_VXCVI:
827: info.si_code = TARGET_FPE_FLTSUB;
828: break;
829: default:
830: fprintf(stderr, "Unknown floating point exception "
831: "(%02x)\n", env->error_code);
832: if (loglevel) {
833: fprintf(logfile, "Unknown floating point exception "
834: "(%02x)\n", env->error_code & 0xF);
835: }
836: }
837: break;
838: case EXCP_INVAL:
839: fprintf(stderr, "Invalid instruction\n");
840: if (loglevel)
841: fprintf(logfile, "Invalid instruction\n");
842: info.si_signo = TARGET_SIGILL;
843: info.si_errno = 0;
844: switch (env->error_code & 0xF) {
845: case EXCP_INVAL_INVAL:
846: info.si_code = TARGET_ILL_ILLOPC;
847: break;
848: case EXCP_INVAL_LSWX:
849: info.si_code = TARGET_ILL_ILLOPN;
850: break;
851: case EXCP_INVAL_SPR:
852: info.si_code = TARGET_ILL_PRVREG;
853: break;
854: case EXCP_INVAL_FP:
855: info.si_code = TARGET_ILL_COPROC;
856: break;
857: default:
858: fprintf(stderr, "Unknown invalid operation (%02x)\n",
859: env->error_code & 0xF);
860: if (loglevel) {
861: fprintf(logfile, "Unknown invalid operation (%02x)\n",
862: env->error_code & 0xF);
863: }
864: info.si_code = TARGET_ILL_ILLADR;
865: break;
866: }
867: break;
868: case EXCP_PRIV:
869: fprintf(stderr, "Privilege violation\n");
870: if (loglevel)
871: fprintf(logfile, "Privilege violation\n");
872: info.si_signo = TARGET_SIGILL;
873: info.si_errno = 0;
874: switch (env->error_code & 0xF) {
875: case EXCP_PRIV_OPC:
876: info.si_code = TARGET_ILL_PRVOPC;
877: break;
878: case EXCP_PRIV_REG:
879: info.si_code = TARGET_ILL_PRVREG;
880: break;
881: default:
882: fprintf(stderr, "Unknown privilege violation (%02x)\n",
883: env->error_code & 0xF);
884: info.si_code = TARGET_ILL_PRVOPC;
885: break;
886: }
887: break;
888: case EXCP_TRAP:
889: fprintf(stderr, "Tried to call a TRAP\n");
890: if (loglevel)
891: fprintf(logfile, "Tried to call a TRAP\n");
892: abort();
893: default:
894: /* Should not happen ! */
895: fprintf(stderr, "Unknown program exception (%02x)\n",
896: env->error_code);
897: if (loglevel) {
898: fprintf(logfile, "Unknwon program exception (%02x)\n",
899: env->error_code);
900: }
901: abort();
902: }
903: info._sifields._sigfault._addr = env->nip - 4;
904: queue_signal(info.si_signo, &info);
905: break;
906: case EXCP_NO_FP:
907: fprintf(stderr, "No floating point allowed\n");
908: if (loglevel)
909: fprintf(logfile, "No floating point allowed\n");
910: info.si_signo = TARGET_SIGILL;
911: info.si_errno = 0;
912: info.si_code = TARGET_ILL_COPROC;
913: info._sifields._sigfault._addr = env->nip - 4;
914: queue_signal(info.si_signo, &info);
915: break;
916: case EXCP_DECR:
917: /* Should not happen ! */
918: fprintf(stderr, "Decrementer exception\n");
919: if (loglevel)
920: fprintf(logfile, "Decrementer exception\n");
921: abort();
922: case EXCP_TRACE:
923: /* Do nothing: we use this to trace execution */
924: break;
925: case EXCP_FP_ASSIST:
926: /* Should not happen ! */
927: fprintf(stderr, "Floating point assist exception\n");
928: if (loglevel)
929: fprintf(logfile, "Floating point assist exception\n");
930: abort();
931: case EXCP_MTMSR:
932: /* We reloaded the msr, just go on */
933: if (msr_pr == 0) {
934: fprintf(stderr, "Tried to go into supervisor mode !\n");
935: if (loglevel)
936: fprintf(logfile, "Tried to go into supervisor mode !\n");
937: abort();
938: }
939: break;
940: case EXCP_BRANCH:
941: /* We stopped because of a jump... */
942: break;
943: case EXCP_INTERRUPT:
944: /* Don't know why this should ever happen... */
945: break;
946: case EXCP_DEBUG:
947: {
948: int sig;
949:
950: sig = gdb_handlesig (env, TARGET_SIGTRAP);
951: if (sig)
952: {
953: info.si_signo = sig;
954: info.si_errno = 0;
955: info.si_code = TARGET_TRAP_BRKPT;
956: queue_signal(info.si_signo, &info);
957: }
958: }
959: break;
960: default:
961: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
962: trapnr);
963: if (loglevel) {
964: fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
965: "0x%02x - aborting\n", trapnr, env->error_code);
966: }
967: abort();
968: }
969: process_pending_signals(env);
970: }
971: }
972: #endif
973:
974: void usage(void)
975: {
976: printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2005 Fabrice Bellard\n"
977: "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] program [arguments...]\n"
978: "Linux CPU emulator (compiled for %s emulation)\n"
979: "\n"
980: "-h print this help\n"
981: "-g wait gdb connection to port %d\n"
982: "-L path set the elf interpreter prefix (default=%s)\n"
983: "-s size set the stack size in bytes (default=%ld)\n"
984: "\n"
985: "debug options:\n"
986: #ifdef USE_CODE_COPY
987: "-no-code-copy disable code copy acceleration\n"
988: #endif
989: "-d options activate log (logfile=%s)\n"
990: "-p pagesize set the host page size to 'pagesize'\n",
991: TARGET_ARCH,
992: DEFAULT_GDBSTUB_PORT,
993: interp_prefix,
994: x86_stack_size,
995: DEBUG_LOGFILE);
996: _exit(1);
997: }
998:
999: /* XXX: currently only used for async signals (see signal.c) */
1000: CPUState *global_env;
1001: /* used only if single thread */
1002: CPUState *cpu_single_env = NULL;
1003:
1004: /* used to free thread contexts */
1005: TaskState *first_task_state;
1006:
1007: int main(int argc, char **argv)
1008: {
1009: const char *filename;
1010: struct target_pt_regs regs1, *regs = ®s1;
1011: struct image_info info1, *info = &info1;
1012: TaskState ts1, *ts = &ts1;
1013: CPUState *env;
1014: int optind;
1015: const char *r;
1016: int use_gdbstub = 0;
1017:
1018: if (argc <= 1)
1019: usage();
1020:
1021: /* init debug */
1022: cpu_set_log_filename(DEBUG_LOGFILE);
1023:
1024: optind = 1;
1025: for(;;) {
1026: if (optind >= argc)
1027: break;
1028: r = argv[optind];
1029: if (r[0] != '-')
1030: break;
1031: optind++;
1032: r++;
1033: if (!strcmp(r, "-")) {
1034: break;
1035: } else if (!strcmp(r, "d")) {
1036: int mask;
1037: CPULogItem *item;
1038:
1039: if (optind >= argc)
1040: break;
1041:
1042: r = argv[optind++];
1043: mask = cpu_str_to_log_mask(r);
1044: if (!mask) {
1045: printf("Log items (comma separated):\n");
1046: for(item = cpu_log_items; item->mask != 0; item++) {
1047: printf("%-10s %s\n", item->name, item->help);
1048: }
1049: exit(1);
1050: }
1051: cpu_set_log(mask);
1052: } else if (!strcmp(r, "s")) {
1053: r = argv[optind++];
1054: x86_stack_size = strtol(r, (char **)&r, 0);
1055: if (x86_stack_size <= 0)
1056: usage();
1057: if (*r == 'M')
1058: x86_stack_size *= 1024 * 1024;
1059: else if (*r == 'k' || *r == 'K')
1060: x86_stack_size *= 1024;
1061: } else if (!strcmp(r, "L")) {
1062: interp_prefix = argv[optind++];
1063: } else if (!strcmp(r, "p")) {
1064: qemu_host_page_size = atoi(argv[optind++]);
1065: if (qemu_host_page_size == 0 ||
1066: (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
1067: fprintf(stderr, "page size must be a power of two\n");
1068: exit(1);
1069: }
1070: } else if (!strcmp(r, "g")) {
1071: use_gdbstub = 1;
1072: } else
1073: #ifdef USE_CODE_COPY
1074: if (!strcmp(r, "no-code-copy")) {
1075: code_copy_enabled = 0;
1076: } else
1077: #endif
1078: {
1079: usage();
1080: }
1081: }
1082: if (optind >= argc)
1083: usage();
1084: filename = argv[optind];
1085:
1086: /* Zero out regs */
1087: memset(regs, 0, sizeof(struct target_pt_regs));
1088:
1089: /* Zero out image_info */
1090: memset(info, 0, sizeof(struct image_info));
1091:
1092: /* Scan interp_prefix dir for replacement files. */
1093: init_paths(interp_prefix);
1094:
1095: /* NOTE: we need to init the CPU at this stage to get
1096: qemu_host_page_size */
1097: env = cpu_init();
1098:
1099: if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
1100: printf("Error loading %s\n", filename);
1101: _exit(1);
1102: }
1103:
1104: if (loglevel) {
1105: page_dump(logfile);
1106:
1107: fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk);
1108: fprintf(logfile, "end_code 0x%08lx\n" , info->end_code);
1109: fprintf(logfile, "start_code 0x%08lx\n" , info->start_code);
1110: fprintf(logfile, "end_data 0x%08lx\n" , info->end_data);
1111: fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
1112: fprintf(logfile, "brk 0x%08lx\n" , info->brk);
1113: fprintf(logfile, "entry 0x%08lx\n" , info->entry);
1114: }
1115:
1116: target_set_brk((char *)info->brk);
1117: syscall_init();
1118: signal_init();
1119:
1120: global_env = env;
1121:
1122: /* build Task State */
1123: memset(ts, 0, sizeof(TaskState));
1124: env->opaque = ts;
1125: ts->used = 1;
1126: env->user_mode_only = 1;
1127:
1128: #if defined(TARGET_I386)
1129: cpu_x86_set_cpl(env, 3);
1130:
1131: env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
1132: env->hflags |= HF_PE_MASK;
1133: if (env->cpuid_features & CPUID_SSE) {
1134: env->cr[4] |= CR4_OSFXSR_MASK;
1135: env->hflags |= HF_OSFXSR_MASK;
1136: }
1137:
1138: /* flags setup : we activate the IRQs by default as in user mode */
1139: env->eflags |= IF_MASK;
1140:
1141: /* linux register setup */
1142: env->regs[R_EAX] = regs->eax;
1143: env->regs[R_EBX] = regs->ebx;
1144: env->regs[R_ECX] = regs->ecx;
1145: env->regs[R_EDX] = regs->edx;
1146: env->regs[R_ESI] = regs->esi;
1147: env->regs[R_EDI] = regs->edi;
1148: env->regs[R_EBP] = regs->ebp;
1149: env->regs[R_ESP] = regs->esp;
1150: env->eip = regs->eip;
1151:
1152: /* linux interrupt setup */
1153: env->idt.base = (long)idt_table;
1154: env->idt.limit = sizeof(idt_table) - 1;
1155: set_idt(0, 0);
1156: set_idt(1, 0);
1157: set_idt(2, 0);
1158: set_idt(3, 3);
1159: set_idt(4, 3);
1160: set_idt(5, 3);
1161: set_idt(6, 0);
1162: set_idt(7, 0);
1163: set_idt(8, 0);
1164: set_idt(9, 0);
1165: set_idt(10, 0);
1166: set_idt(11, 0);
1167: set_idt(12, 0);
1168: set_idt(13, 0);
1169: set_idt(14, 0);
1170: set_idt(15, 0);
1171: set_idt(16, 0);
1172: set_idt(17, 0);
1173: set_idt(18, 0);
1174: set_idt(19, 0);
1175: set_idt(0x80, 3);
1176:
1177: /* linux segment setup */
1178: env->gdt.base = (long)gdt_table;
1179: env->gdt.limit = sizeof(gdt_table) - 1;
1180: write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
1181: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
1182: (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
1183: write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
1184: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
1185: (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
1186: cpu_x86_load_seg(env, R_CS, __USER_CS);
1187: cpu_x86_load_seg(env, R_DS, __USER_DS);
1188: cpu_x86_load_seg(env, R_ES, __USER_DS);
1189: cpu_x86_load_seg(env, R_SS, __USER_DS);
1190: cpu_x86_load_seg(env, R_FS, __USER_DS);
1191: cpu_x86_load_seg(env, R_GS, __USER_DS);
1192:
1193: #elif defined(TARGET_ARM)
1194: {
1195: int i;
1196: for(i = 0; i < 16; i++) {
1197: env->regs[i] = regs->uregs[i];
1198: }
1199: env->cpsr = regs->uregs[16];
1200: ts->stack_base = info->start_stack;
1201: ts->heap_base = info->brk;
1202: /* This will be filled in on the first SYS_HEAPINFO call. */
1203: ts->heap_limit = 0;
1204: }
1205: #elif defined(TARGET_SPARC)
1206: {
1207: int i;
1208: env->pc = regs->pc;
1209: env->npc = regs->npc;
1210: env->y = regs->y;
1211: for(i = 0; i < 8; i++)
1212: env->gregs[i] = regs->u_regs[i];
1213: for(i = 0; i < 8; i++)
1214: env->regwptr[i] = regs->u_regs[i + 8];
1215: }
1216: #elif defined(TARGET_PPC)
1217: {
1218: ppc_def_t *def;
1219: int i;
1220:
1221: /* Choose and initialise CPU */
1222: /* XXX: CPU model (or PVR) should be provided on command line */
1223: // ppc_find_by_name("750gx", &def);
1224: // ppc_find_by_name("750fx", &def);
1225: // ppc_find_by_name("750p", &def);
1226: ppc_find_by_name("750", &def);
1227: // ppc_find_by_name("G3", &def);
1228: // ppc_find_by_name("604r", &def);
1229: // ppc_find_by_name("604e", &def);
1230: // ppc_find_by_name("604", &def);
1231: if (def == NULL) {
1232: cpu_abort(cpu_single_env,
1233: "Unable to find PowerPC CPU definition\n");
1234: }
1235: cpu_ppc_register(cpu_single_env, def);
1236:
1237: for (i = 0; i < 32; i++) {
1238: if (i != 12 && i != 6 && i != 13)
1239: env->msr[i] = (regs->msr >> i) & 1;
1240: }
1241: env->nip = regs->nip;
1242: for(i = 0; i < 32; i++) {
1243: env->gpr[i] = regs->gpr[i];
1244: }
1245: }
1246: #else
1247: #error unsupported target CPU
1248: #endif
1249:
1250: if (use_gdbstub) {
1251: gdbserver_start (DEFAULT_GDBSTUB_PORT);
1252: gdb_handlesig(env, 0);
1253: }
1254: cpu_loop(env);
1255: /* never exits */
1256: return 0;
1257: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.