1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
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: static const char *interp_prefix = CONFIG_QEMU_PREFIX;
32: const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
33:
34: #if defined(__i386__) && !defined(CONFIG_STATIC)
35:
36:
37: const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
38: #endif
39:
40:
41:
42: #if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
43: asm(".globl __preinit_array_start\n"
44: ".globl __preinit_array_end\n"
45: ".globl __init_array_start\n"
46: ".globl __init_array_end\n"
47: ".globl __fini_array_start\n"
48: ".globl __fini_array_end\n"
49: ".section \".rodata\"\n"
50: "__preinit_array_start:\n"
51: "__preinit_array_end:\n"
52: "__init_array_start:\n"
53: "__init_array_end:\n"
54: "__fini_array_start:\n"
55: "__fini_array_end:\n"
56: ".long 0\n");
57: #endif
58:
59:
60:
61:
62: unsigned long x86_stack_size = 512 * 1024;
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: void cpu_outb(CPUState *env, int addr, int val)
74: {
75: fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
76: }
77:
78: void cpu_outw(CPUState *env, int addr, int val)
79: {
80: fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
81: }
82:
83: void cpu_outl(CPUState *env, int addr, int val)
84: {
85: fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
86: }
87:
88: int cpu_inb(CPUState *env, int addr)
89: {
90: fprintf(stderr, "inb: port=0x%04x\n", addr);
91: return 0;
92: }
93:
94: int cpu_inw(CPUState *env, int addr)
95: {
96: fprintf(stderr, "inw: port=0x%04x\n", addr);
97: return 0;
98: }
99:
100: int cpu_inl(CPUState *env, int addr)
101: {
102: fprintf(stderr, "inl: port=0x%04x\n", addr);
103: return 0;
104: }
105:
106: int cpu_get_pic_interrupt(CPUState *env)
107: {
108: return -1;
109: }
110:
111:
112:
113: #if 0
114:
115: static uint64_t emu_time;
116:
117: int64_t cpu_get_real_ticks(void)
118: {
119: return emu_time++;
120: }
121:
122: #endif
123:
124: #ifdef TARGET_I386
125:
126:
127:
128: void cpu_smm_update(CPUState *env)
129: {
130: }
131:
132: uint64_t cpu_get_tsc(CPUX86State *env)
133: {
134: return cpu_get_real_ticks();
135: }
136:
137: static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
138: int flags)
139: {
140: unsigned int e1, e2;
141: uint32_t *p;
142: e1 = (addr << 16) | (limit & 0xffff);
143: e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
144: e2 |= flags;
145: p = ptr;
146: p[0] = tswapl(e1);
147: p[1] = tswapl(e2);
148: }
149:
150: #if TARGET_X86_64
151: uint64_t idt_table[512];
152:
153: static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
154: uint64_t addr, unsigned int sel)
155: {
156: uint32_t *p, e1, e2;
157: e1 = (addr & 0xffff) | (sel << 16);
158: e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
159: p = ptr;
160: p[0] = tswap32(e1);
161: p[1] = tswap32(e2);
162: p[2] = tswap32(addr >> 32);
163: p[3] = 0;
164: }
165:
166: static void set_idt(int n, unsigned int dpl)
167: {
168: set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
169: }
170: #else
171: uint64_t idt_table[256];
172:
173: static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
174: uint32_t addr, unsigned int sel)
175: {
176: uint32_t *p, e1, e2;
177: e1 = (addr & 0xffff) | (sel << 16);
178: e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
179: p = ptr;
180: p[0] = tswap32(e1);
181: p[1] = tswap32(e2);
182: }
183:
184:
185: static void set_idt(int n, unsigned int dpl)
186: {
187: set_gate(idt_table + n, 0, dpl, 0, 0);
188: }
189: #endif
190:
191: void cpu_loop(CPUX86State *env)
192: {
193: int trapnr;
194: abi_ulong pc;
195: target_siginfo_t info;
196:
197: for(;;) {
198: trapnr = cpu_x86_exec(env);
199: switch(trapnr) {
200: case 0x80:
201:
202: env->regs[R_EAX] = do_syscall(env,
203: env->regs[R_EAX],
204: env->regs[R_EBX],
205: env->regs[R_ECX],
206: env->regs[R_EDX],
207: env->regs[R_ESI],
208: env->regs[R_EDI],
209: env->regs[R_EBP]);
210: break;
211: #ifndef TARGET_ABI32
212: case EXCP_SYSCALL:
213:
214: env->regs[R_EAX] = do_syscall(env,
215: env->regs[R_EAX],
216: env->regs[R_EDI],
217: env->regs[R_ESI],
218: env->regs[R_EDX],
219: env->regs[10],
220: env->regs[8],
221: env->regs[9]);
222: env->eip = env->exception_next_eip;
223: break;
224: #endif
225: case EXCP0B_NOSEG:
226: case EXCP0C_STACK:
227: info.si_signo = SIGBUS;
228: info.si_errno = 0;
229: info.si_code = TARGET_SI_KERNEL;
230: info._sifields._sigfault._addr = 0;
231: queue_signal(info.si_signo, &info);
232: break;
233: case EXCP0D_GPF:
234:
235: #ifndef TARGET_X86_64
236: if (env->eflags & VM_MASK) {
237: handle_vm86_fault(env);
238: } else
239: #endif
240: {
241: info.si_signo = SIGSEGV;
242: info.si_errno = 0;
243: info.si_code = TARGET_SI_KERNEL;
244: info._sifields._sigfault._addr = 0;
245: queue_signal(info.si_signo, &info);
246: }
247: break;
248: case EXCP0E_PAGE:
249: info.si_signo = SIGSEGV;
250: info.si_errno = 0;
251: if (!(env->error_code & 1))
252: info.si_code = TARGET_SEGV_MAPERR;
253: else
254: info.si_code = TARGET_SEGV_ACCERR;
255: info._sifields._sigfault._addr = env->cr[2];
256: queue_signal(info.si_signo, &info);
257: break;
258: case EXCP00_DIVZ:
259: #ifndef TARGET_X86_64
260: if (env->eflags & VM_MASK) {
261: handle_vm86_trap(env, trapnr);
262: } else
263: #endif
264: {
265:
266: info.si_signo = SIGFPE;
267: info.si_errno = 0;
268: info.si_code = TARGET_FPE_INTDIV;
269: info._sifields._sigfault._addr = env->eip;
270: queue_signal(info.si_signo, &info);
271: }
272: break;
273: case EXCP01_SSTP:
274: case EXCP03_INT3:
275: #ifndef TARGET_X86_64
276: if (env->eflags & VM_MASK) {
277: handle_vm86_trap(env, trapnr);
278: } else
279: #endif
280: {
281: info.si_signo = SIGTRAP;
282: info.si_errno = 0;
283: if (trapnr == EXCP01_SSTP) {
284: info.si_code = TARGET_TRAP_BRKPT;
285: info._sifields._sigfault._addr = env->eip;
286: } else {
287: info.si_code = TARGET_SI_KERNEL;
288: info._sifields._sigfault._addr = 0;
289: }
290: queue_signal(info.si_signo, &info);
291: }
292: break;
293: case EXCP04_INTO:
294: case EXCP05_BOUND:
295: #ifndef TARGET_X86_64
296: if (env->eflags & VM_MASK) {
297: handle_vm86_trap(env, trapnr);
298: } else
299: #endif
300: {
301: info.si_signo = SIGSEGV;
302: info.si_errno = 0;
303: info.si_code = TARGET_SI_KERNEL;
304: info._sifields._sigfault._addr = 0;
305: queue_signal(info.si_signo, &info);
306: }
307: break;
308: case EXCP06_ILLOP:
309: info.si_signo = SIGILL;
310: info.si_errno = 0;
311: info.si_code = TARGET_ILL_ILLOPN;
312: info._sifields._sigfault._addr = env->eip;
313: queue_signal(info.si_signo, &info);
314: break;
315: case EXCP_INTERRUPT:
316:
317: break;
318: case EXCP_DEBUG:
319: {
320: int sig;
321:
322: sig = gdb_handlesig (env, TARGET_SIGTRAP);
323: if (sig)
324: {
325: info.si_signo = sig;
326: info.si_errno = 0;
327: info.si_code = TARGET_TRAP_BRKPT;
328: queue_signal(info.si_signo, &info);
329: }
330: }
331: break;
332: default:
333: pc = env->segs[R_CS].base + env->eip;
334: fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
335: (long)pc, trapnr);
336: abort();
337: }
338: process_pending_signals(env);
339: }
340: }
341: #endif
342:
343: #ifdef TARGET_ARM
344:
345:
346: extern void tb_invalidate_page_range(abi_ulong start, abi_ulong end);
347:
348: static void arm_cache_flush(abi_ulong start, abi_ulong last)
349: {
350: abi_ulong addr, last1;
351:
352: if (last < start)
353: return;
354: addr = start;
355: for(;;) {
356: last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;
357: if (last1 > last)
358: last1 = last;
359: tb_invalidate_page_range(addr, last1 + 1);
360: if (last1 == last)
361: break;
362: addr = last1 + 1;
363: }
364: }
365:
366: void cpu_loop(CPUARMState *env)
367: {
368: int trapnr;
369: unsigned int n, insn;
370: target_siginfo_t info;
371: uint32_t addr;
372:
373: for(;;) {
374: trapnr = cpu_arm_exec(env);
375: switch(trapnr) {
376: case EXCP_UDEF:
377: {
378: TaskState *ts = env->opaque;
379: uint32_t opcode;
380:
381:
382:
383:
384: get_user_u32(opcode, env->regs[15]);
385:
386: if (EmulateAll(opcode, &ts->fpa, env) == 0) {
387: info.si_signo = SIGILL;
388: info.si_errno = 0;
389: info.si_code = TARGET_ILL_ILLOPN;
390: info._sifields._sigfault._addr = env->regs[15];
391: queue_signal(info.si_signo, &info);
392: } else {
393:
394: env->regs[15] += 4;
395: }
396: }
397: break;
398: case EXCP_SWI:
399: case EXCP_BKPT:
400: {
401: env->eabi = 1;
402:
403: if (trapnr == EXCP_BKPT) {
404: if (env->thumb) {
405:
406: get_user_u16(insn, env->regs[15]);
407: n = insn & 0xff;
408: env->regs[15] += 2;
409: } else {
410:
411: get_user_u32(insn, env->regs[15]);
412: n = (insn & 0xf) | ((insn >> 4) & 0xff0);
413: env->regs[15] += 4;
414: }
415: } else {
416: if (env->thumb) {
417:
418: get_user_u16(insn, env->regs[15] - 2);
419: n = insn & 0xff;
420: } else {
421:
422: get_user_u32(insn, env->regs[15] - 4);
423: n = insn & 0xffffff;
424: }
425: }
426:
427: if (n == ARM_NR_cacheflush) {
428: arm_cache_flush(env->regs[0], env->regs[1]);
429: } else if (n == ARM_NR_semihosting
430: || n == ARM_NR_thumb_semihosting) {
431: env->regs[0] = do_arm_semihosting (env);
432: } else if (n == 0 || n >= ARM_SYSCALL_BASE
433: || (env->thumb && n == ARM_THUMB_SYSCALL)) {
434:
435: if (env->thumb || n == 0) {
436: n = env->regs[7];
437: } else {
438: n -= ARM_SYSCALL_BASE;
439: env->eabi = 0;
440: }
441: env->regs[0] = do_syscall(env,
442: n,
443: env->regs[0],
444: env->regs[1],
445: env->regs[2],
446: env->regs[3],
447: env->regs[4],
448: env->regs[5]);
449: } else {
450: goto error;
451: }
452: }
453: break;
454: case EXCP_INTERRUPT:
455:
456: break;
457: case EXCP_PREFETCH_ABORT:
458: addr = env->cp15.c6_data;
459: goto do_segv;
460: case EXCP_DATA_ABORT:
461: addr = env->cp15.c6_insn;
462: goto do_segv;
463: do_segv:
464: {
465: info.si_signo = SIGSEGV;
466: info.si_errno = 0;
467:
468: info.si_code = TARGET_SEGV_MAPERR;
469: info._sifields._sigfault._addr = addr;
470: queue_signal(info.si_signo, &info);
471: }
472: break;
473: case EXCP_DEBUG:
474: {
475: int sig;
476:
477: sig = gdb_handlesig (env, TARGET_SIGTRAP);
478: if (sig)
479: {
480: info.si_signo = sig;
481: info.si_errno = 0;
482: info.si_code = TARGET_TRAP_BRKPT;
483: queue_signal(info.si_signo, &info);
484: }
485: }
486: break;
487: default:
488: error:
489: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
490: trapnr);
491: cpu_dump_state(env, stderr, fprintf, 0);
492: abort();
493: }
494: process_pending_signals(env);
495: }
496: }
497:
498: #endif
499:
500: #ifdef TARGET_SPARC
501:
502:
503:
504:
505:
506: static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
507: {
508: index = (index + cwp * 16) & (16 * NWINDOWS - 1);
509:
510:
511: if (index < 8 && env->cwp == (NWINDOWS - 1))
512: index += (16 * NWINDOWS);
513: return index;
514: }
515:
516:
517: static inline void save_window_offset(CPUSPARCState *env, int cwp1)
518: {
519: unsigned int i;
520: abi_ulong sp_ptr;
521:
522: sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
523: #if defined(DEBUG_WIN)
524: printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n",
525: (int)sp_ptr, cwp1);
526: #endif
527: for(i = 0; i < 16; i++) {
528:
529: put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
530: sp_ptr += sizeof(abi_ulong);
531: }
532: }
533:
534: static void save_window(CPUSPARCState *env)
535: {
536: #ifndef TARGET_SPARC64
537: unsigned int new_wim;
538: new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
539: ((1LL << NWINDOWS) - 1);
540: save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
541: env->wim = new_wim;
542: #else
543: save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
544: env->cansave++;
545: env->canrestore--;
546: #endif
547: }
548:
549: static void restore_window(CPUSPARCState *env)
550: {
551: unsigned int new_wim, i, cwp1;
552: abi_ulong sp_ptr;
553:
554: new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
555: ((1LL << NWINDOWS) - 1);
556:
557:
558: cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
559: sp_ptr = env->regbase[get_reg