|
|
1.1 root 1: /*
2: * qemu user main
1.1.1.6 ! root 3: *
! 4: * Copyright (c) 2003-2008 Fabrice Bellard
1.1 root 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: static const char *interp_prefix = CONFIG_QEMU_PREFIX;
1.1.1.4 root 32: const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
1.1 root 33:
34: #if defined(__i386__) && !defined(CONFIG_STATIC)
35: /* Force usage of an ELF interpreter even if it is an ELF shared
36: object ! */
37: const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
38: #endif
39:
40: /* for recent libc, we add these dummy symbols which are not declared
41: when generating a linked object (bug in ld ?) */
42: #if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
1.1.1.6 ! root 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");
1.1 root 57: #endif
58:
59: /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
60: we allocate a bigger stack. Need a better solution, for example
61: by remapping the process stack directly at the right place */
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: /* timers for rdtsc */
112:
1.1.1.4 root 113: #if 0
1.1 root 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: /* CPUX86 core interface */
127:
1.1.1.5 root 128: void cpu_smm_update(CPUState *env)
129: {
130: }
131:
1.1 root 132: uint64_t cpu_get_tsc(CPUX86State *env)
133: {
134: return cpu_get_real_ticks();
135: }
136:
1.1.1.6 ! root 137: static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
1.1 root 138: int flags)
139: {
140: unsigned int e1, e2;
1.1.1.3 root 141: uint32_t *p;
1.1 root 142: e1 = (addr << 16) | (limit & 0xffff);
143: e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
144: e2 |= flags;
1.1.1.3 root 145: p = ptr;
146: p[0] = tswapl(e1);
147: p[1] = tswapl(e2);
1.1 root 148: }
149:
1.1.1.6 ! root 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)
1.1 root 155: {
1.1.1.6 ! root 156: uint32_t *p, e1, e2;
1.1 root 157: e1 = (addr & 0xffff) | (sel << 16);
158: e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
1.1.1.3 root 159: p = ptr;
1.1.1.6 ! root 160: p[0] = tswap32(e1);
! 161: p[1] = tswap32(e2);
! 162: p[2] = tswap32(addr >> 32);
! 163: p[3] = 0;
1.1 root 164: }
1.1.1.6 ! root 165: /* only dpl matters as we do only user space emulation */
! 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
1.1 root 171: uint64_t idt_table[256];
172:
1.1.1.6 ! root 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:
1.1 root 184: /* only dpl matters as we do only user space emulation */
185: static void set_idt(int n, unsigned int dpl)
186: {
187: set_gate(idt_table + n, 0, dpl, 0, 0);
188: }
1.1.1.6 ! root 189: #endif
1.1 root 190:
191: void cpu_loop(CPUX86State *env)
192: {
193: int trapnr;
1.1.1.6 ! root 194: abi_ulong pc;
1.1 root 195: target_siginfo_t info;
196:
197: for(;;) {
198: trapnr = cpu_x86_exec(env);
199: switch(trapnr) {
200: case 0x80:
1.1.1.6 ! root 201: /* linux syscall from int $0x80 */
! 202: env->regs[R_EAX] = do_syscall(env,
! 203: env->regs[R_EAX],
1.1 root 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;
1.1.1.6 ! root 211: #ifndef TARGET_ABI32
! 212: case EXCP_SYSCALL:
! 213: /* linux syscall from syscall intruction */
! 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
1.1 root 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:
1.1.1.6 ! root 234: /* XXX: potential problem if ABI32 */
! 235: #ifndef TARGET_X86_64
1.1 root 236: if (env->eflags & VM_MASK) {
237: handle_vm86_fault(env);
1.1.1.6 ! root 238: } else
! 239: #endif
! 240: {
1.1 root 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:
1.1.1.6 ! root 259: #ifndef TARGET_X86_64
1.1 root 260: if (env->eflags & VM_MASK) {
261: handle_vm86_trap(env, trapnr);
1.1.1.6 ! root 262: } else
! 263: #endif
! 264: {
1.1 root 265: /* division by zero */
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:
1.1.1.6 ! root 275: #ifndef TARGET_X86_64
1.1 root 276: if (env->eflags & VM_MASK) {
277: handle_vm86_trap(env, trapnr);
1.1.1.6 ! root 278: } else
! 279: #endif
! 280: {
1.1 root 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:
1.1.1.6 ! root 295: #ifndef TARGET_X86_64
1.1 root 296: if (env->eflags & VM_MASK) {
297: handle_vm86_trap(env, trapnr);
1.1.1.6 ! root 298: } else
! 299: #endif
! 300: {
1.1 root 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: /* just indicate that signals should be handled asap */
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;
1.1.1.6 ! root 334: fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
1.1 root 335: (long)pc, trapnr);
336: abort();
337: }
338: process_pending_signals(env);
339: }
340: }
341: #endif
342:
343: #ifdef TARGET_ARM
344:
345: /* XXX: find a better solution */
1.1.1.6 ! root 346: extern void tb_invalidate_page_range(abi_ulong start, abi_ulong end);
1.1 root 347:
1.1.1.6 ! root 348: static void arm_cache_flush(abi_ulong start, abi_ulong last)
1.1 root 349: {
1.1.1.6 ! root 350: abi_ulong addr, last1;
1.1 root 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;
1.1.1.2 root 371: uint32_t addr;
1.1.1.6 ! root 372:
1.1 root 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: /* we handle the FPU emulation here, as Linux */
382: /* we get the opcode */
1.1.1.6 ! root 383: /* FIXME - what to do if get_user() fails? */
! 384: get_user_u32(opcode, env->regs[15]);
! 385:
1.1.1.3 root 386: if (EmulateAll(opcode, &ts->fpa, env) == 0) {
1.1 root 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: /* increment PC */
394: env->regs[15] += 4;
395: }
396: }
397: break;
398: case EXCP_SWI:
1.1.1.3 root 399: case EXCP_BKPT:
1.1 root 400: {
1.1.1.3 root 401: env->eabi = 1;
1.1 root 402: /* system call */
1.1.1.3 root 403: if (trapnr == EXCP_BKPT) {
404: if (env->thumb) {
1.1.1.6 ! root 405: /* FIXME - what to do if get_user() fails? */
! 406: get_user_u16(insn, env->regs[15]);
1.1.1.3 root 407: n = insn & 0xff;
408: env->regs[15] += 2;
409: } else {
1.1.1.6 ! root 410: /* FIXME - what to do if get_user() fails? */
! 411: get_user_u32(insn, env->regs[15]);
1.1.1.3 root 412: n = (insn & 0xf) | ((insn >> 4) & 0xff0);
413: env->regs[15] += 4;
414: }
1.1 root 415: } else {
1.1.1.3 root 416: if (env->thumb) {
1.1.1.6 ! root 417: /* FIXME - what to do if get_user() fails? */
! 418: get_user_u16(insn, env->regs[15] - 2);
1.1.1.3 root 419: n = insn & 0xff;
420: } else {
1.1.1.6 ! root 421: /* FIXME - what to do if get_user() fails? */
! 422: get_user_u32(insn, env->regs[15] - 4);
1.1.1.3 root 423: n = insn & 0xffffff;
424: }
1.1 root 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);
1.1.1.3 root 432: } else if (n == 0 || n >= ARM_SYSCALL_BASE
1.1 root 433: || (env->thumb && n == ARM_THUMB_SYSCALL)) {
434: /* linux syscall */
1.1.1.3 root 435: if (env->thumb || n == 0) {
1.1 root 436: n = env->regs[7];
437: } else {
438: n -= ARM_SYSCALL_BASE;
1.1.1.3 root 439: env->eabi = 0;
1.1 root 440: }
1.1.1.6 ! root 441: env->regs[0] = do_syscall(env,
! 442: n,
1.1 root 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: /* just indicate that signals should be handled asap */
456: break;
457: case EXCP_PREFETCH_ABORT:
1.1.1.2 root 458: addr = env->cp15.c6_data;
459: goto do_segv;
1.1 root 460: case EXCP_DATA_ABORT:
1.1.1.2 root 461: addr = env->cp15.c6_insn;
462: goto do_segv;
463: do_segv:
1.1 root 464: {
465: info.si_signo = SIGSEGV;
466: info.si_errno = 0;
467: /* XXX: check env->error_code */
468: info.si_code = TARGET_SEGV_MAPERR;
1.1.1.2 root 469: info._sifields._sigfault._addr = addr;
1.1 root 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:
1.1.1.6 ! root 489: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
1.1 root 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: //#define DEBUG_WIN
503:
504: /* WARNING: dealing with register windows _is_ complicated. More info
505: can be found at http://www.sics.se/~psm/sparcstack.html */
506: static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
507: {
508: index = (index + cwp * 16) & (16 * NWINDOWS - 1);
509: /* wrap handling : if cwp is on the last window, then we use the
510: registers 'after' the end */
511: if (index < 8 && env->cwp == (NWINDOWS - 1))
512: index += (16 * NWINDOWS);
513: return index;
514: }
515:
516: /* save the register window 'cwp1' */
517: static inline void save_window_offset(CPUSPARCState *env, int cwp1)
518: {
519: unsigned int i;
1.1.1.6 ! root 520: abi_ulong sp_ptr;
! 521:
1.1.1.3 root 522: sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
1.1 root 523: #if defined(DEBUG_WIN)
1.1.1.6 ! root 524: printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n",
1.1 root 525: (int)sp_ptr, cwp1);
526: #endif
527: for(i = 0; i < 16; i++) {
1.1.1.6 ! root 528: /* FIXME - what to do if put_user() fails? */
! 529: put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
! 530: sp_ptr += sizeof(abi_ulong);
1.1 root 531: }
532: }
533:
534: static void save_window(CPUSPARCState *env)
535: {
1.1.1.4 root 536: #ifndef TARGET_SPARC64
1.1 root 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;
1.1.1.4 root 542: #else
543: save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
544: env->cansave++;
545: env->canrestore--;
546: #endif
1.1 root 547: }
548:
549: static void restore_window(CPUSPARCState *env)
550: {
551: unsigned int new_wim, i, cwp1;
1.1.1.6 ! root 552: abi_ulong sp_ptr;
! 553:
1.1 root 554: new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
555: ((1LL << NWINDOWS) - 1);
1.1.1.6 ! root 556:
1.1 root 557: /* restore the invalid window */
558: cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
1.1.1.3 root 559: sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
1.1 root 560: #if defined(DEBUG_WIN)
1.1.1.6 ! root 561: printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n",
1.1 root 562: (int)sp_ptr, cwp1);
563: #endif
564: for(i = 0; i < 16; i++) {
1.1.1.6 ! root 565: /* FIXME - what to do if get_user() fails? */
! 566: get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
! 567: sp_ptr += sizeof(abi_ulong);
1.1 root 568: }
569: env->wim = new_wim;
1.1.1.4 root 570: #ifdef TARGET_SPARC64
571: env->canrestore++;
572: if (env->cleanwin < NWINDOWS - 1)
573: env->cleanwin++;
574: env->cansave--;
575: #endif
1.1 root 576: }
577:
578: static void flush_windows(CPUSPARCState *env)
579: {
580: int offset, cwp1;
581:
582: offset = 1;
583: for(;;) {
584: /* if restore would invoke restore_window(), then we can stop */
585: cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
586: if (env->wim & (1 << cwp1))
587: break;
588: save_window_offset(env, cwp1);
589: offset++;
590: }
591: /* set wim so that restore will reload the registers */
592: cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
593: env->wim = 1 << cwp1;
594: #if defined(DEBUG_WIN)
595: printf("flush_windows: nb=%d\n", offset - 1);
596: #endif
597: }
598:
599: void cpu_loop (CPUSPARCState *env)
600: {
601: int trapnr, ret;
602: target_siginfo_t info;
1.1.1.6 ! root 603:
1.1 root 604: while (1) {
605: trapnr = cpu_sparc_exec (env);
1.1.1.6 ! root 606:
1.1 root 607: switch (trapnr) {
1.1.1.4 root 608: #ifndef TARGET_SPARC64
1.1.1.6 ! root 609: case 0x88:
1.1 root 610: case 0x90:
1.1.1.4 root 611: #else
1.1.1.6 ! root 612: case 0x110:
1.1.1.4 root 613: case 0x16d:
614: #endif
1.1 root 615: ret = do_syscall (env, env->gregs[1],
1.1.1.6 ! root 616: env->regwptr[0], env->regwptr[1],
! 617: env->regwptr[2], env->regwptr[3],
1.1 root 618: env->regwptr[4], env->regwptr[5]);
619: if ((unsigned int)ret >= (unsigned int)(-515)) {
1.1.1.6 ! root 620: #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
1.1.1.5 root 621: env->xcc |= PSR_CARRY;
622: #else
1.1 root 623: env->psr |= PSR_CARRY;
1.1.1.5 root 624: #endif
1.1 root 625: ret = -ret;
626: } else {
1.1.1.6 ! root 627: #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
1.1.1.5 root 628: env->xcc &= ~PSR_CARRY;
629: #else
1.1 root 630: env->psr &= ~PSR_CARRY;
1.1.1.5 root 631: #endif
1.1 root 632: }
633: env->regwptr[0] = ret;
634: /* next instruction */
635: env->pc = env->npc;
636: env->npc = env->npc + 4;
637: break;
638: case 0x83: /* flush windows */
1.1.1.6 ! root 639: #ifdef TARGET_ABI32
! 640: case 0x103:
! 641: #endif
1.1 root 642: flush_windows(env);
643: /* next instruction */
644: env->pc = env->npc;
645: env->npc = env->npc + 4;
646: break;
647: #ifndef TARGET_SPARC64
648: case TT_WIN_OVF: /* window overflow */
649: save_window(env);
650: break;
651: case TT_WIN_UNF: /* window underflow */
652: restore_window(env);
653: break;
654: case TT_TFAULT:
655: case TT_DFAULT:
656: {
657: info.si_signo = SIGSEGV;
658: info.si_errno = 0;
659: /* XXX: check env->error_code */
660: info.si_code = TARGET_SEGV_MAPERR;
661: info._sifields._sigfault._addr = env->mmuregs[4];
662: queue_signal(info.si_signo, &info);
663: }
664: break;
665: #else
1.1.1.4 root 666: case TT_SPILL: /* window overflow */
667: save_window(env);
668: break;
669: case TT_FILL: /* window underflow */
670: restore_window(env);
671: break;
1.1.1.6 ! root 672: case TT_TFAULT:
! 673: case TT_DFAULT:
! 674: {
! 675: info.si_signo = SIGSEGV;
! 676: info.si_errno = 0;
! 677: /* XXX: check env->error_code */
! 678: info.si_code = TARGET_SEGV_MAPERR;
! 679: if (trapnr == TT_DFAULT)
! 680: info._sifields._sigfault._addr = env->dmmuregs[4];
! 681: else
! 682: info._sifields._sigfault._addr = env->tpc[env->tl];
! 683: queue_signal(info.si_signo, &info);
! 684: }
! 685: break;
! 686: #ifndef TARGET_ABI32
! 687: case 0x16e:
! 688: flush_windows(env);
! 689: sparc64_get_context(env);
! 690: break;
! 691: case 0x16f:
! 692: flush_windows(env);
! 693: sparc64_set_context(env);
! 694: break;
! 695: #endif
1.1 root 696: #endif
1.1.1.4 root 697: case EXCP_INTERRUPT:
698: /* just indicate that signals should be handled asap */
699: break;
1.1 root 700: case EXCP_DEBUG:
701: {
702: int sig;
703:
704: sig = gdb_handlesig (env, TARGET_SIGTRAP);
705: if (sig)
706: {
707: info.si_signo = sig;
708: info.si_errno = 0;
709: info.si_code = TARGET_TRAP_BRKPT;
710: queue_signal(info.si_signo, &info);
711: }
712: }
713: break;
714: default:
715: printf ("Unhandled trap: 0x%x\n", trapnr);
716: cpu_dump_state(env, stderr, fprintf, 0);
717: exit (1);
718: }
719: process_pending_signals (env);
720: }
721: }
722:
723: #endif
724:
725: #ifdef TARGET_PPC
726: static inline uint64_t cpu_ppc_get_tb (CPUState *env)
727: {
728: /* TO FIX */
729: return 0;
730: }
1.1.1.6 ! root 731:
1.1 root 732: uint32_t cpu_ppc_load_tbl (CPUState *env)
733: {
734: return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
735: }
1.1.1.6 ! root 736:
1.1 root 737: uint32_t cpu_ppc_load_tbu (CPUState *env)
738: {
739: return cpu_ppc_get_tb(env) >> 32;
740: }
1.1.1.6 ! root 741:
! 742: uint32_t cpu_ppc_load_atbl (CPUState *env)
1.1 root 743: {
1.1.1.6 ! root 744: return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
1.1 root 745: }
746:
1.1.1.6 ! root 747: uint32_t cpu_ppc_load_atbu (CPUState *env)
1.1 root 748: {
1.1.1.6 ! root 749: return cpu_ppc_get_tb(env) >> 32;
1.1 root 750: }
1.1.1.6 ! root 751:
! 752: uint32_t cpu_ppc601_load_rtcu (CPUState *env)
! 753: __attribute__ (( alias ("cpu_ppc_load_tbu") ));
! 754:
! 755: uint32_t cpu_ppc601_load_rtcl (CPUState *env)
1.1 root 756: {
1.1.1.6 ! root 757: return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
1.1 root 758: }
1.1.1.6 ! root 759:
! 760: /* XXX: to be fixed */
! 761: int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1.1 root 762: {
763: return -1;
764: }
1.1.1.6 ! root 765:
! 766: int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1.1 root 767: {
1.1.1.6 ! root 768: return -1;
1.1 root 769: }
1.1.1.6 ! root 770:
! 771: #define EXCP_DUMP(env, fmt, args...) \
! 772: do { \
! 773: fprintf(stderr, fmt , ##args); \
! 774: cpu_dump_state(env, stderr, fprintf, 0); \
! 775: if (loglevel != 0) { \
! 776: fprintf(logfile, fmt , ##args); \
! 777: cpu_dump_state(env, logfile, fprintf, 0); \
! 778: } \
! 779: } while (0)
! 780:
1.1 root 781: void cpu_loop(CPUPPCState *env)
782: {
783: target_siginfo_t info;
784: int trapnr;
785: uint32_t ret;
1.1.1.6 ! root 786:
1.1 root 787: for(;;) {
788: trapnr = cpu_ppc_exec(env);
789: switch(trapnr) {
1.1.1.6 ! root 790: case POWERPC_EXCP_NONE:
! 791: /* Just go on */
1.1 root 792: break;
1.1.1.6 ! root 793: case POWERPC_EXCP_CRITICAL: /* Critical input */
! 794: cpu_abort(env, "Critical interrupt while in user mode. "
! 795: "Aborting\n");
! 796: break;
! 797: case POWERPC_EXCP_MCHECK: /* Machine check exception */
! 798: cpu_abort(env, "Machine check exception while in user mode. "
! 799: "Aborting\n");
! 800: break;
! 801: case POWERPC_EXCP_DSI: /* Data storage exception */
! 802: EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
! 803: env->spr[SPR_DAR]);
! 804: /* XXX: check this. Seems bugged */
1.1 root 805: switch (env->error_code & 0xFF000000) {
806: case 0x40000000:
807: info.si_signo = TARGET_SIGSEGV;
808: info.si_errno = 0;
809: info.si_code = TARGET_SEGV_MAPERR;
810: break;
811: case 0x04000000:
812: info.si_signo = TARGET_SIGILL;
813: info.si_errno = 0;
814: info.si_code = TARGET_ILL_ILLADR;
815: break;
816: case 0x08000000:
817: info.si_signo = TARGET_SIGSEGV;
818: info.si_errno = 0;
819: info.si_code = TARGET_SEGV_ACCERR;
820: break;
821: default:
822: /* Let's send a regular segfault... */
1.1.1.6 ! root 823: EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
! 824: env->error_code);
1.1 root 825: info.si_signo = TARGET_SIGSEGV;
826: info.si_errno = 0;
827: info.si_code = TARGET_SEGV_MAPERR;
828: break;
829: }
830: info._sifields._sigfault._addr = env->nip;
831: queue_signal(info.si_signo, &info);
832: break;
1.1.1.6 ! root 833: case POWERPC_EXCP_ISI: /* Instruction storage exception */
! 834: EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
! 835: env->spr[SPR_SRR0]);
! 836: /* XXX: check this */
1.1 root 837: switch (env->error_code & 0xFF000000) {
838: case 0x40000000:
839: info.si_signo = TARGET_SIGSEGV;
840: info.si_errno = 0;
841: info.si_code = TARGET_SEGV_MAPERR;
842: break;
843: case 0x10000000:
844: case 0x08000000:
845: info.si_signo = TARGET_SIGSEGV;
846: info.si_errno = 0;
847: info.si_code = TARGET_SEGV_ACCERR;
848: break;
849: default:
850: /* Let's send a regular segfault... */
1.1.1.6 ! root 851: EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
! 852: env->error_code);
1.1 root 853: info.si_signo = TARGET_SIGSEGV;
854: info.si_errno = 0;
855: info.si_code = TARGET_SEGV_MAPERR;
856: break;
857: }
858: info._sifields._sigfault._addr = env->nip - 4;
859: queue_signal(info.si_signo, &info);
860: break;
1.1.1.6 ! root 861: case POWERPC_EXCP_EXTERNAL: /* External input */
! 862: cpu_abort(env, "External interrupt while in user mode. "
! 863: "Aborting\n");
! 864: break;
! 865: case POWERPC_EXCP_ALIGN: /* Alignment exception */
! 866: EXCP_DUMP(env, "Unaligned memory access\n");
! 867: /* XXX: check this */
1.1 root 868: info.si_signo = TARGET_SIGBUS;
869: info.si_errno = 0;
870: info.si_code = TARGET_BUS_ADRALN;
871: info._sifields._sigfault._addr = env->nip - 4;
872: queue_signal(info.si_signo, &info);
873: break;
1.1.1.6 ! root 874: case POWERPC_EXCP_PROGRAM: /* Program exception */
! 875: /* XXX: check this */
1.1 root 876: switch (env->error_code & ~0xF) {
1.1.1.6 ! root 877: case POWERPC_EXCP_FP:
! 878: EXCP_DUMP(env, "Floating point program exception\n");
1.1 root 879: info.si_signo = TARGET_SIGFPE;
880: info.si_errno = 0;
881: switch (env->error_code & 0xF) {
1.1.1.6 ! root 882: case POWERPC_EXCP_FP_OX:
1.1 root 883: info.si_code = TARGET_FPE_FLTOVF;
884: break;
1.1.1.6 ! root 885: case POWERPC_EXCP_FP_UX:
1.1 root 886: info.si_code = TARGET_FPE_FLTUND;
887: break;
1.1.1.6 ! root 888: case POWERPC_EXCP_FP_ZX:
! 889: case POWERPC_EXCP_FP_VXZDZ:
1.1 root 890: info.si_code = TARGET_FPE_FLTDIV;
891: break;
1.1.1.6 ! root 892: case POWERPC_EXCP_FP_XX:
1.1 root 893: info.si_code = TARGET_FPE_FLTRES;
894: break;
1.1.1.6 ! root 895: case POWERPC_EXCP_FP_VXSOFT:
1.1 root 896: info.si_code = TARGET_FPE_FLTINV;
897: break;
1.1.1.6 ! root 898: case POWERPC_EXCP_FP_VXSNAN:
! 899: case POWERPC_EXCP_FP_VXISI:
! 900: case POWERPC_EXCP_FP_VXIDI:
! 901: case POWERPC_EXCP_FP_VXIMZ:
! 902: case POWERPC_EXCP_FP_VXVC:
! 903: case POWERPC_EXCP_FP_VXSQRT:
! 904: case POWERPC_EXCP_FP_VXCVI:
1.1 root 905: info.si_code = TARGET_FPE_FLTSUB;
906: break;
907: default:
1.1.1.6 ! root 908: EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
! 909: env->error_code);
! 910: break;
1.1 root 911: }
1.1.1.6 ! root 912: break;
! 913: case POWERPC_EXCP_INVAL:
! 914: EXCP_DUMP(env, "Invalid instruction\n");
1.1 root 915: info.si_signo = TARGET_SIGILL;
916: info.si_errno = 0;
917: switch (env->error_code & 0xF) {
1.1.1.6 ! root 918: case POWERPC_EXCP_INVAL_INVAL:
1.1 root 919: info.si_code = TARGET_ILL_ILLOPC;
920: break;
1.1.1.6 ! root 921: case POWERPC_EXCP_INVAL_LSWX:
! 922: info.si_code = TARGET_ILL_ILLOPN;
1.1 root 923: break;
1.1.1.6 ! root 924: case POWERPC_EXCP_INVAL_SPR:
1.1 root 925: info.si_code = TARGET_ILL_PRVREG;
926: break;
1.1.1.6 ! root 927: case POWERPC_EXCP_INVAL_FP:
1.1 root 928: info.si_code = TARGET_ILL_COPROC;
929: break;
930: default:
1.1.1.6 ! root 931: EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
! 932: env->error_code & 0xF);
1.1 root 933: info.si_code = TARGET_ILL_ILLADR;
934: break;
935: }
936: break;
1.1.1.6 ! root 937: case POWERPC_EXCP_PRIV:
! 938: EXCP_DUMP(env, "Privilege violation\n");
1.1 root 939: info.si_signo = TARGET_SIGILL;
940: info.si_errno = 0;
941: switch (env->error_code & 0xF) {
1.1.1.6 ! root 942: case POWERPC_EXCP_PRIV_OPC:
1.1 root 943: info.si_code = TARGET_ILL_PRVOPC;
944: break;
1.1.1.6 ! root 945: case POWERPC_EXCP_PRIV_REG:
1.1 root 946: info.si_code = TARGET_ILL_PRVREG;
1.1.1.6 ! root 947: break;
1.1 root 948: default:
1.1.1.6 ! root 949: EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
! 950: env->error_code & 0xF);
1.1 root 951: info.si_code = TARGET_ILL_PRVOPC;
952: break;
953: }
954: break;
1.1.1.6 ! root 955: case POWERPC_EXCP_TRAP:
! 956: cpu_abort(env, "Tried to call a TRAP\n");
! 957: break;
1.1 root 958: default:
959: /* Should not happen ! */
1.1.1.6 ! root 960: cpu_abort(env, "Unknown program exception (%02x)\n",
! 961: env->error_code);
! 962: break;
1.1 root 963: }
964: info._sifields._sigfault._addr = env->nip - 4;
965: queue_signal(info.si_signo, &info);
966: break;
1.1.1.6 ! root 967: case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
! 968: EXCP_DUMP(env, "No floating point allowed\n");
1.1 root 969: info.si_signo = TARGET_SIGILL;
970: info.si_errno = 0;
971: info.si_code = TARGET_ILL_COPROC;
972: info._sifields._sigfault._addr = env->nip - 4;
973: queue_signal(info.si_signo, &info);
974: break;
1.1.1.6 ! root 975: case POWERPC_EXCP_SYSCALL: /* System call exception */
! 976: cpu_abort(env, "Syscall exception while in user mode. "
! 977: "Aborting\n");
1.1 root 978: break;
1.1.1.6 ! root 979: case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
! 980: EXCP_DUMP(env, "No APU instruction allowed\n");
! 981: info.si_signo = TARGET_SIGILL;
! 982: info.si_errno = 0;
! 983: info.si_code = TARGET_ILL_COPROC;
! 984: info._sifields._sigfault._addr = env->nip - 4;
! 985: queue_signal(info.si_signo, &info);
1.1 root 986: break;
1.1.1.6 ! root 987: case POWERPC_EXCP_DECR: /* Decrementer exception */
! 988: cpu_abort(env, "Decrementer interrupt while in user mode. "
! 989: "Aborting\n");
! 990: break;
! 991: case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
! 992: cpu_abort(env, "Fix interval timer interrupt while in user mode. "
! 993: "Aborting\n");
! 994: break;
! 995: case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
! 996: cpu_abort(env, "Watchdog timer interrupt while in user mode. "
! 997: "Aborting\n");
! 998: break;
! 999: case POWERPC_EXCP_DTLB: /* Data TLB error */
! 1000: cpu_abort(env, "Data TLB exception while in user mode. "
! 1001: "Aborting\n");
! 1002: break;
! 1003: case POWERPC_EXCP_ITLB: /* Instruction TLB error */
! 1004: cpu_abort(env, "Instruction TLB exception while in user mode. "
! 1005: "Aborting\n");
1.1 root 1006: break;
1.1.1.6 ! root 1007: case POWERPC_EXCP_DEBUG: /* Debug interrupt */
! 1008: /* XXX: check this */
1.1 root 1009: {
1010: int sig;
1011:
1.1.1.6 ! root 1012: sig = gdb_handlesig(env, TARGET_SIGTRAP);
! 1013: if (sig) {
1.1 root 1014: info.si_signo = sig;
1015: info.si_errno = 0;
1016: info.si_code = TARGET_TRAP_BRKPT;
1017: queue_signal(info.si_signo, &info);
1018: }
1019: }
1020: break;
1.1.1.6 ! root 1021: case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
! 1022: EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
! 1023: info.si_signo = TARGET_SIGILL;
! 1024: info.si_errno = 0;
! 1025: info.si_code = TARGET_ILL_COPROC;
! 1026: info._sifields._sigfault._addr = env->nip - 4;
! 1027: queue_signal(info.si_signo, &info);
! 1028: break;
! 1029: case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
! 1030: cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
! 1031: break;
! 1032: case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
! 1033: cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
! 1034: break;
! 1035: case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
! 1036: cpu_abort(env, "Performance monitor exception not handled\n");
! 1037: break;
! 1038: case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
! 1039: cpu_abort(env, "Doorbell interrupt while in user mode. "
! 1040: "Aborting\n");
! 1041: break;
! 1042: case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
! 1043: cpu_abort(env, "Doorbell critical interrupt while in user mode. "
! 1044: "Aborting\n");
! 1045: break;
! 1046: case POWERPC_EXCP_RESET: /* System reset exception */
! 1047: cpu_abort(env, "Reset interrupt while in user mode. "
! 1048: "Aborting\n");
! 1049: break;
! 1050: case POWERPC_EXCP_DSEG: /* Data segment exception */
! 1051: cpu_abort(env, "Data segment exception while in user mode. "
! 1052: "Aborting\n");
! 1053: break;
! 1054: case POWERPC_EXCP_ISEG: /* Instruction segment exception */
! 1055: cpu_abort(env, "Instruction segment exception "
! 1056: "while in user mode. Aborting\n");
! 1057: break;
! 1058: /* PowerPC 64 with hypervisor mode support */
! 1059: case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
! 1060: cpu_abort(env, "Hypervisor decrementer interrupt "
! 1061: "while in user mode. Aborting\n");
! 1062: break;
! 1063: case POWERPC_EXCP_TRACE: /* Trace exception */
! 1064: /* Nothing to do:
! 1065: * we use this exception to emulate step-by-step execution mode.
! 1066: */
! 1067: break;
! 1068: /* PowerPC 64 with hypervisor mode support */
! 1069: case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
! 1070: cpu_abort(env, "Hypervisor data storage exception "
! 1071: "while in user mode. Aborting\n");
! 1072: break;
! 1073: case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
! 1074: cpu_abort(env, "Hypervisor instruction storage exception "
! 1075: "while in user mode. Aborting\n");
! 1076: break;
! 1077: case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
! 1078: cpu_abort(env, "Hypervisor data segment exception "
! 1079: "while in user mode. Aborting\n");
! 1080: break;
! 1081: case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
! 1082: cpu_abort(env, "Hypervisor instruction segment exception "
! 1083: "while in user mode. Aborting\n");
! 1084: break;
! 1085: case POWERPC_EXCP_VPU: /* Vector unavailable exception */
! 1086: EXCP_DUMP(env, "No Altivec instructions allowed\n");
! 1087: info.si_signo = TARGET_SIGILL;
! 1088: info.si_errno = 0;
! 1089: info.si_code = TARGET_ILL_COPROC;
! 1090: info._sifields._sigfault._addr = env->nip - 4;
! 1091: queue_signal(info.si_signo, &info);
! 1092: break;
! 1093: case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
! 1094: cpu_abort(env, "Programable interval timer interrupt "
! 1095: "while in user mode. Aborting\n");
! 1096: break;
! 1097: case POWERPC_EXCP_IO: /* IO error exception */
! 1098: cpu_abort(env, "IO error exception while in user mode. "
! 1099: "Aborting\n");
! 1100: break;
! 1101: case POWERPC_EXCP_RUNM: /* Run mode exception */
! 1102: cpu_abort(env, "Run mode exception while in user mode. "
! 1103: "Aborting\n");
! 1104: break;
! 1105: case POWERPC_EXCP_EMUL: /* Emulation trap exception */
! 1106: cpu_abort(env, "Emulation trap exception not handled\n");
! 1107: break;
! 1108: case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
! 1109: cpu_abort(env, "Instruction fetch TLB exception "
! 1110: "while in user-mode. Aborting");
! 1111: break;
! 1112: case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
! 1113: cpu_abort(env, "Data load TLB exception while in user-mode. "
! 1114: "Aborting");
! 1115: break;
! 1116: case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
! 1117: cpu_abort(env, "Data store TLB exception while in user-mode. "
! 1118: "Aborting");
! 1119: break;
! 1120: case POWERPC_EXCP_FPA: /* Floating-point assist exception */
! 1121: cpu_abort(env, "Floating-point assist exception not handled\n");
! 1122: break;
! 1123: case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
! 1124: cpu_abort(env, "Instruction address breakpoint exception "
! 1125: "not handled\n");
! 1126: break;
! 1127: case POWERPC_EXCP_SMI: /* System management interrupt */
! 1128: cpu_abort(env, "System management interrupt while in user mode. "
! 1129: "Aborting\n");
! 1130: break;
! 1131: case POWERPC_EXCP_THERM: /* Thermal interrupt */
! 1132: cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
! 1133: "Aborting\n");
! 1134: break;
! 1135: case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
! 1136: cpu_abort(env, "Performance monitor exception not handled\n");
! 1137: break;
! 1138: case POWERPC_EXCP_VPUA: /* Vector assist exception */
! 1139: cpu_abort(env, "Vector assist exception not handled\n");
! 1140: break;
! 1141: case POWERPC_EXCP_SOFTP: /* Soft patch exception */
! 1142: cpu_abort(env, "Soft patch exception not handled\n");
! 1143: break;
! 1144: case POWERPC_EXCP_MAINT: /* Maintenance exception */
! 1145: cpu_abort(env, "Maintenance exception while in user mode. "
! 1146: "Aborting\n");
! 1147: break;
! 1148: case POWERPC_EXCP_STOP: /* stop translation */
! 1149: /* We did invalidate the instruction cache. Go on */
! 1150: break;
! 1151: case POWERPC_EXCP_BRANCH: /* branch instruction: */
! 1152: /* We just stopped because of a branch. Go on */
! 1153: break;
! 1154: case POWERPC_EXCP_SYSCALL_USER:
! 1155: /* system call in user-mode emulation */
! 1156: /* WARNING:
! 1157: * PPC ABI uses overflow flag in cr0 to signal an error
! 1158: * in syscalls.
! 1159: */
! 1160: #if 0
! 1161: printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
! 1162: env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
! 1163: #endif
! 1164: env->crf[0] &= ~0x1;
! 1165: ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
! 1166: env->gpr[5], env->gpr[6], env->gpr[7],
! 1167: env->gpr[8]);
! 1168: if (ret > (uint32_t)(-515)) {
! 1169: env->crf[0] |= 0x1;
! 1170: ret = -ret;
1.1 root 1171: }
1.1.1.6 ! root 1172: env->gpr[3] = ret;
! 1173: #if 0
! 1174: printf("syscall returned 0x%08x (%d)\n", ret, ret);
! 1175: #endif
! 1176: break;
! 1177: case EXCP_INTERRUPT:
! 1178: /* just indicate that signals should be handled asap */
! 1179: break;
! 1180: default:
! 1181: cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
! 1182: break;
1.1 root 1183: }
1184: process_pending_signals(env);
1185: }
1186: }
1187: #endif
1188:
1.1.1.2 root 1189: #ifdef TARGET_MIPS
1190:
1191: #define MIPS_SYS(name, args) args,
1192:
1193: static const uint8_t mips_syscall_args[] = {
1194: MIPS_SYS(sys_syscall , 0) /* 4000 */
1195: MIPS_SYS(sys_exit , 1)
1196: MIPS_SYS(sys_fork , 0)
1197: MIPS_SYS(sys_read , 3)
1198: MIPS_SYS(sys_write , 3)
1199: MIPS_SYS(sys_open , 3) /* 4005 */
1200: MIPS_SYS(sys_close , 1)
1201: MIPS_SYS(sys_waitpid , 3)
1202: MIPS_SYS(sys_creat , 2)
1203: MIPS_SYS(sys_link , 2)
1204: MIPS_SYS(sys_unlink , 1) /* 4010 */
1205: MIPS_SYS(sys_execve , 0)
1206: MIPS_SYS(sys_chdir , 1)
1207: MIPS_SYS(sys_time , 1)
1208: MIPS_SYS(sys_mknod , 3)
1209: MIPS_SYS(sys_chmod , 2) /* 4015 */
1210: MIPS_SYS(sys_lchown , 3)
1211: MIPS_SYS(sys_ni_syscall , 0)
1212: MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */
1213: MIPS_SYS(sys_lseek , 3)
1214: MIPS_SYS(sys_getpid , 0) /* 4020 */
1215: MIPS_SYS(sys_mount , 5)
1216: MIPS_SYS(sys_oldumount , 1)
1217: MIPS_SYS(sys_setuid , 1)
1218: MIPS_SYS(sys_getuid , 0)
1219: MIPS_SYS(sys_stime , 1) /* 4025 */
1220: MIPS_SYS(sys_ptrace , 4)
1221: MIPS_SYS(sys_alarm , 1)
1222: MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */
1223: MIPS_SYS(sys_pause , 0)
1224: MIPS_SYS(sys_utime , 2) /* 4030 */
1225: MIPS_SYS(sys_ni_syscall , 0)
1226: MIPS_SYS(sys_ni_syscall , 0)
1227: MIPS_SYS(sys_access , 2)
1228: MIPS_SYS(sys_nice , 1)
1229: MIPS_SYS(sys_ni_syscall , 0) /* 4035 */
1230: MIPS_SYS(sys_sync , 0)
1231: MIPS_SYS(sys_kill , 2)
1232: MIPS_SYS(sys_rename , 2)
1233: MIPS_SYS(sys_mkdir , 2)
1234: MIPS_SYS(sys_rmdir , 1) /* 4040 */
1235: MIPS_SYS(sys_dup , 1)
1236: MIPS_SYS(sys_pipe , 0)
1237: MIPS_SYS(sys_times , 1)
1238: MIPS_SYS(sys_ni_syscall , 0)
1239: MIPS_SYS(sys_brk , 1) /* 4045 */
1240: MIPS_SYS(sys_setgid , 1)
1241: MIPS_SYS(sys_getgid , 0)
1242: MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */
1243: MIPS_SYS(sys_geteuid , 0)
1244: MIPS_SYS(sys_getegid , 0) /* 4050 */
1245: MIPS_SYS(sys_acct , 0)
1246: MIPS_SYS(sys_umount , 2)
1247: MIPS_SYS(sys_ni_syscall , 0)
1248: MIPS_SYS(sys_ioctl , 3)
1249: MIPS_SYS(sys_fcntl , 3) /* 4055 */
1250: MIPS_SYS(sys_ni_syscall , 2)
1251: MIPS_SYS(sys_setpgid , 2)
1252: MIPS_SYS(sys_ni_syscall , 0)
1253: MIPS_SYS(sys_olduname , 1)
1254: MIPS_SYS(sys_umask , 1) /* 4060 */
1255: MIPS_SYS(sys_chroot , 1)
1256: MIPS_SYS(sys_ustat , 2)
1257: MIPS_SYS(sys_dup2 , 2)
1258: MIPS_SYS(sys_getppid , 0)
1259: MIPS_SYS(sys_getpgrp , 0) /* 4065 */
1260: MIPS_SYS(sys_setsid , 0)
1261: MIPS_SYS(sys_sigaction , 3)
1262: MIPS_SYS(sys_sgetmask , 0)
1263: MIPS_SYS(sys_ssetmask , 1)
1264: MIPS_SYS(sys_setreuid , 2) /* 4070 */
1265: MIPS_SYS(sys_setregid , 2)
1266: MIPS_SYS(sys_sigsuspend , 0)
1267: MIPS_SYS(sys_sigpending , 1)
1268: MIPS_SYS(sys_sethostname , 2)
1269: MIPS_SYS(sys_setrlimit , 2) /* 4075 */
1270: MIPS_SYS(sys_getrlimit , 2)
1271: MIPS_SYS(sys_getrusage , 2)
1272: MIPS_SYS(sys_gettimeofday, 2)
1273: MIPS_SYS(sys_settimeofday, 2)
1274: MIPS_SYS(sys_getgroups , 2) /* 4080 */
1275: MIPS_SYS(sys_setgroups , 2)
1276: MIPS_SYS(sys_ni_syscall , 0) /* old_select */
1277: MIPS_SYS(sys_symlink , 2)
1278: MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */
1279: MIPS_SYS(sys_readlink , 3) /* 4085 */
1280: MIPS_SYS(sys_uselib , 1)
1281: MIPS_SYS(sys_swapon , 2)
1282: MIPS_SYS(sys_reboot , 3)
1283: MIPS_SYS(old_readdir , 3)
1284: MIPS_SYS(old_mmap , 6) /* 4090 */
1285: MIPS_SYS(sys_munmap , 2)
1286: MIPS_SYS(sys_truncate , 2)
1287: MIPS_SYS(sys_ftruncate , 2)
1288: MIPS_SYS(sys_fchmod , 2)
1289: MIPS_SYS(sys_fchown , 3) /* 4095 */
1290: MIPS_SYS(sys_getpriority , 2)
1291: MIPS_SYS(sys_setpriority , 3)
1292: MIPS_SYS(sys_ni_syscall , 0)
1293: MIPS_SYS(sys_statfs , 2)
1294: MIPS_SYS(sys_fstatfs , 2) /* 4100 */
1295: MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */
1296: MIPS_SYS(sys_socketcall , 2)
1297: MIPS_SYS(sys_syslog , 3)
1298: MIPS_SYS(sys_setitimer , 3)
1299: MIPS_SYS(sys_getitimer , 2) /* 4105 */
1300: MIPS_SYS(sys_newstat , 2)
1301: MIPS_SYS(sys_newlstat , 2)
1302: MIPS_SYS(sys_newfstat , 2)
1303: MIPS_SYS(sys_uname , 1)
1304: MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */
1305: MIPS_SYS(sys_vhangup , 0)
1306: MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */
1307: MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */
1308: MIPS_SYS(sys_wait4 , 4)
1309: MIPS_SYS(sys_swapoff , 1) /* 4115 */
1310: MIPS_SYS(sys_sysinfo , 1)
1311: MIPS_SYS(sys_ipc , 6)
1312: MIPS_SYS(sys_fsync , 1)
1313: MIPS_SYS(sys_sigreturn , 0)
1314: MIPS_SYS(sys_clone , 0) /* 4120 */
1315: MIPS_SYS(sys_setdomainname, 2)
1316: MIPS_SYS(sys_newuname , 1)
1317: MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */
1318: MIPS_SYS(sys_adjtimex , 1)
1319: MIPS_SYS(sys_mprotect , 3) /* 4125 */
1320: MIPS_SYS(sys_sigprocmask , 3)
1321: MIPS_SYS(sys_ni_syscall , 0) /* was create_module */
1322: MIPS_SYS(sys_init_module , 5)
1323: MIPS_SYS(sys_delete_module, 1)
1324: MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */
1325: MIPS_SYS(sys_quotactl , 0)
1326: MIPS_SYS(sys_getpgid , 1)
1327: MIPS_SYS(sys_fchdir , 1)
1328: MIPS_SYS(sys_bdflush , 2)
1329: MIPS_SYS(sys_sysfs , 3) /* 4135 */
1330: MIPS_SYS(sys_personality , 1)
1331: MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */
1332: MIPS_SYS(sys_setfsuid , 1)
1333: MIPS_SYS(sys_setfsgid , 1)
1334: MIPS_SYS(sys_llseek , 5) /* 4140 */
1335: MIPS_SYS(sys_getdents , 3)
1336: MIPS_SYS(sys_select , 5)
1337: MIPS_SYS(sys_flock , 2)
1338: MIPS_SYS(sys_msync , 3)
1339: MIPS_SYS(sys_readv , 3) /* 4145 */
1340: MIPS_SYS(sys_writev , 3)
1341: MIPS_SYS(sys_cacheflush , 3)
1342: MIPS_SYS(sys_cachectl , 3)
1343: MIPS_SYS(sys_sysmips , 4)
1344: MIPS_SYS(sys_ni_syscall , 0) /* 4150 */
1345: MIPS_SYS(sys_getsid , 1)
1346: MIPS_SYS(sys_fdatasync , 0)
1347: MIPS_SYS(sys_sysctl , 1)
1348: MIPS_SYS(sys_mlock , 2)
1349: MIPS_SYS(sys_munlock , 2) /* 4155 */
1350: MIPS_SYS(sys_mlockall , 1)
1351: MIPS_SYS(sys_munlockall , 0)
1352: MIPS_SYS(sys_sched_setparam, 2)
1353: MIPS_SYS(sys_sched_getparam, 2)
1354: MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */
1355: MIPS_SYS(sys_sched_getscheduler, 1)
1356: MIPS_SYS(sys_sched_yield , 0)
1357: MIPS_SYS(sys_sched_get_priority_max, 1)
1358: MIPS_SYS(sys_sched_get_priority_min, 1)
1359: MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
1360: MIPS_SYS(sys_nanosleep, 2)
1361: MIPS_SYS(sys_mremap , 4)
1362: MIPS_SYS(sys_accept , 3)
1363: MIPS_SYS(sys_bind , 3)
1364: MIPS_SYS(sys_connect , 3) /* 4170 */
1365: MIPS_SYS(sys_getpeername , 3)
1366: MIPS_SYS(sys_getsockname , 3)
1367: MIPS_SYS(sys_getsockopt , 5)
1368: MIPS_SYS(sys_listen , 2)
1369: MIPS_SYS(sys_recv , 4) /* 4175 */
1370: MIPS_SYS(sys_recvfrom , 6)
1371: MIPS_SYS(sys_recvmsg , 3)
1372: MIPS_SYS(sys_send , 4)
1373: MIPS_SYS(sys_sendmsg , 3)
1374: MIPS_SYS(sys_sendto , 6) /* 4180 */
1375: MIPS_SYS(sys_setsockopt , 5)
1376: MIPS_SYS(sys_shutdown , 2)
1377: MIPS_SYS(sys_socket , 3)
1378: MIPS_SYS(sys_socketpair , 4)
1379: MIPS_SYS(sys_setresuid , 3) /* 4185 */
1380: MIPS_SYS(sys_getresuid , 3)
1381: MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */
1382: MIPS_SYS(sys_poll , 3)
1383: MIPS_SYS(sys_nfsservctl , 3)
1384: MIPS_SYS(sys_setresgid , 3) /* 4190 */
1385: MIPS_SYS(sys_getresgid , 3)
1386: MIPS_SYS(sys_prctl , 5)
1387: MIPS_SYS(sys_rt_sigreturn, 0)
1388: MIPS_SYS(sys_rt_sigaction, 4)
1389: MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */
1390: MIPS_SYS(sys_rt_sigpending, 2)
1391: MIPS_SYS(sys_rt_sigtimedwait, 4)
1392: MIPS_SYS(sys_rt_sigqueueinfo, 3)
1393: MIPS_SYS(sys_rt_sigsuspend, 0)
1394: MIPS_SYS(sys_pread64 , 6) /* 4200 */
1395: MIPS_SYS(sys_pwrite64 , 6)
1396: MIPS_SYS(sys_chown , 3)
1397: MIPS_SYS(sys_getcwd , 2)
1398: MIPS_SYS(sys_capget , 2)
1399: MIPS_SYS(sys_capset , 2) /* 4205 */
1400: MIPS_SYS(sys_sigaltstack , 0)
1401: MIPS_SYS(sys_sendfile , 4)
1402: MIPS_SYS(sys_ni_syscall , 0)
1403: MIPS_SYS(sys_ni_syscall , 0)
1404: MIPS_SYS(sys_mmap2 , 6) /* 4210 */
1405: MIPS_SYS(sys_truncate64 , 4)
1406: MIPS_SYS(sys_ftruncate64 , 4)
1407: MIPS_SYS(sys_stat64 , 2)
1408: MIPS_SYS(sys_lstat64 , 2)
1409: MIPS_SYS(sys_fstat64 , 2) /* 4215 */
1410: MIPS_SYS(sys_pivot_root , 2)
1411: MIPS_SYS(sys_mincore , 3)
1412: MIPS_SYS(sys_madvise , 3)
1413: MIPS_SYS(sys_getdents64 , 3)
1414: MIPS_SYS(sys_fcntl64 , 3) /* 4220 */
1415: MIPS_SYS(sys_ni_syscall , 0)
1416: MIPS_SYS(sys_gettid , 0)
1417: MIPS_SYS(sys_readahead , 5)
1418: MIPS_SYS(sys_setxattr , 5)
1419: MIPS_SYS(sys_lsetxattr , 5) /* 4225 */
1420: MIPS_SYS(sys_fsetxattr , 5)
1421: MIPS_SYS(sys_getxattr , 4)
1422: MIPS_SYS(sys_lgetxattr , 4)
1423: MIPS_SYS(sys_fgetxattr , 4)
1424: MIPS_SYS(sys_listxattr , 3) /* 4230 */
1425: MIPS_SYS(sys_llistxattr , 3)
1426: MIPS_SYS(sys_flistxattr , 3)
1427: MIPS_SYS(sys_removexattr , 2)
1428: MIPS_SYS(sys_lremovexattr, 2)
1429: MIPS_SYS(sys_fremovexattr, 2) /* 4235 */
1430: MIPS_SYS(sys_tkill , 2)
1431: MIPS_SYS(sys_sendfile64 , 5)
1432: MIPS_SYS(sys_futex , 2)
1433: MIPS_SYS(sys_sched_setaffinity, 3)
1434: MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */
1435: MIPS_SYS(sys_io_setup , 2)
1436: MIPS_SYS(sys_io_destroy , 1)
1437: MIPS_SYS(sys_io_getevents, 5)
1438: MIPS_SYS(sys_io_submit , 3)
1439: MIPS_SYS(sys_io_cancel , 3) /* 4245 */
1440: MIPS_SYS(sys_exit_group , 1)
1441: MIPS_SYS(sys_lookup_dcookie, 3)
1442: MIPS_SYS(sys_epoll_create, 1)
1443: MIPS_SYS(sys_epoll_ctl , 4)
1444: MIPS_SYS(sys_epoll_wait , 3) /* 4250 */
1445: MIPS_SYS(sys_remap_file_pages, 5)
1446: MIPS_SYS(sys_set_tid_address, 1)
1447: MIPS_SYS(sys_restart_syscall, 0)
1448: MIPS_SYS(sys_fadvise64_64, 7)
1449: MIPS_SYS(sys_statfs64 , 3) /* 4255 */
1450: MIPS_SYS(sys_fstatfs64 , 2)
1451: MIPS_SYS(sys_timer_create, 3)
1452: MIPS_SYS(sys_timer_settime, 4)
1453: MIPS_SYS(sys_timer_gettime, 2)
1454: MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */
1455: MIPS_SYS(sys_timer_delete, 1)
1456: MIPS_SYS(sys_clock_settime, 2)
1457: MIPS_SYS(sys_clock_gettime, 2)
1458: MIPS_SYS(sys_clock_getres, 2)
1459: MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */
1460: MIPS_SYS(sys_tgkill , 3)
1461: MIPS_SYS(sys_utimes , 2)
1462: MIPS_SYS(sys_mbind , 4)
1463: MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */
1464: MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */
1465: MIPS_SYS(sys_mq_open , 4)
1466: MIPS_SYS(sys_mq_unlink , 1)
1467: MIPS_SYS(sys_mq_timedsend, 5)
1468: MIPS_SYS(sys_mq_timedreceive, 5)
1469: MIPS_SYS(sys_mq_notify , 2) /* 4275 */
1470: MIPS_SYS(sys_mq_getsetattr, 3)
1471: MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */
1472: MIPS_SYS(sys_waitid , 4)
1473: MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */
1474: MIPS_SYS(sys_add_key , 5)
1.1.1.6 ! root 1475: MIPS_SYS(sys_request_key, 4)
1.1.1.2 root 1476: MIPS_SYS(sys_keyctl , 5)
1.1.1.6 ! root 1477: MIPS_SYS(sys_set_thread_area, 1)
! 1478: MIPS_SYS(sys_inotify_init, 0)
! 1479: MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */
! 1480: MIPS_SYS(sys_inotify_rm_watch, 2)
! 1481: MIPS_SYS(sys_migrate_pages, 4)
! 1482: MIPS_SYS(sys_openat, 4)
! 1483: MIPS_SYS(sys_mkdirat, 3)
! 1484: MIPS_SYS(sys_mknodat, 4) /* 4290 */
! 1485: MIPS_SYS(sys_fchownat, 5)
! 1486: MIPS_SYS(sys_futimesat, 3)
! 1487: MIPS_SYS(sys_fstatat64, 4)
! 1488: MIPS_SYS(sys_unlinkat, 3)
! 1489: MIPS_SYS(sys_renameat, 4) /* 4295 */
! 1490: MIPS_SYS(sys_linkat, 5)
! 1491: MIPS_SYS(sys_symlinkat, 3)
! 1492: MIPS_SYS(sys_readlinkat, 4)
! 1493: MIPS_SYS(sys_fchmodat, 3)
! 1494: MIPS_SYS(sys_faccessat, 3) /* 4300 */
! 1495: MIPS_SYS(sys_pselect6, 6)
! 1496: MIPS_SYS(sys_ppoll, 5)
! 1497: MIPS_SYS(sys_unshare, 1)
! 1498: MIPS_SYS(sys_splice, 4)
! 1499: MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
! 1500: MIPS_SYS(sys_tee, 4)
! 1501: MIPS_SYS(sys_vmsplice, 4)
! 1502: MIPS_SYS(sys_move_pages, 6)
! 1503: MIPS_SYS(sys_set_robust_list, 2)
! 1504: MIPS_SYS(sys_get_robust_list, 3) /* 4310 */
! 1505: MIPS_SYS(sys_kexec_load, 4)
! 1506: MIPS_SYS(sys_getcpu, 3)
! 1507: MIPS_SYS(sys_epoll_pwait, 6)
! 1508: MIPS_SYS(sys_ioprio_set, 3)
! 1509: MIPS_SYS(sys_ioprio_get, 2)
1.1.1.2 root 1510: };
1511:
1512: #undef MIPS_SYS
1513:
1514: void cpu_loop(CPUMIPSState *env)
1515: {
1516: target_siginfo_t info;
1.1.1.6 ! root 1517: int trapnr, ret;
1.1.1.2 root 1518: unsigned int syscall_num;
1519:
1520: for(;;) {
1521: trapnr = cpu_mips_exec(env);
1522: switch(trapnr) {
1523: case EXCP_SYSCALL:
1.1.1.6 ! root 1524: syscall_num = env->gpr[2][env->current_tc] - 4000;
! 1525: env->PC[env->current_tc] += 4;
! 1526: if (syscall_num >= sizeof(mips_syscall_args)) {
! 1527: ret = -ENOSYS;
! 1528: } else {
! 1529: int nb_args;
! 1530: abi_ulong sp_reg;
! 1531: abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
! 1532:
! 1533: nb_args = mips_syscall_args[syscall_num];
! 1534: sp_reg = env->gpr[29][env->current_tc];
! 1535: switch (nb_args) {
! 1536: /* these arguments are taken from the stack */
! 1537: /* FIXME - what to do if get_user() fails? */
! 1538: case 8: get_user_ual(arg8, sp_reg + 28);
! 1539: case 7: get_user_ual(arg7, sp_reg + 24);
! 1540: case 6: get_user_ual(arg6, sp_reg + 20);
! 1541: case 5: get_user_ual(arg5, sp_reg + 16);
! 1542: default:
! 1543: break;
1.1.1.2 root 1544: }
1.1.1.6 ! root 1545: ret = do_syscall(env, env->gpr[2][env->current_tc],
! 1546: env->gpr[4][env->current_tc],
! 1547: env->gpr[5][env->current_tc],
! 1548: env->gpr[6][env->current_tc],
! 1549: env->gpr[7][env->current_tc],
! 1550: arg5, arg6/*, arg7, arg8*/);
! 1551: }
! 1552: if ((unsigned int)ret >= (unsigned int)(-1133)) {
! 1553: env->gpr[7][env->current_tc] = 1; /* error flag */
! 1554: ret = -ret;
! 1555: } else {
! 1556: env->gpr[7][env->current_tc] = 0; /* error flag */
1.1.1.2 root 1557: }
1.1.1.6 ! root 1558: env->gpr[2][env->current_tc] = ret;
1.1.1.2 root 1559: break;
1.1.1.5 root 1560: case EXCP_TLBL:
1561: case EXCP_TLBS:
1.1.1.2 root 1562: case EXCP_CpU:
1563: case EXCP_RI:
1.1.1.4 root 1564: info.si_signo = TARGET_SIGILL;
1565: info.si_errno = 0;
1566: info.si_code = 0;
1567: queue_signal(info.si_signo, &info);
1568: break;
1569: case EXCP_INTERRUPT:
1570: /* just indicate that signals should be handled asap */
1.1.1.2 root 1571: break;
1.1.1.5 root 1572: case EXCP_DEBUG:
1573: {
1574: int sig;
1575:
1576: sig = gdb_handlesig (env, TARGET_SIGTRAP);
1577: if (sig)
1578: {
1579: info.si_signo = sig;
1580: info.si_errno = 0;
1581: info.si_code = TARGET_TRAP_BRKPT;
1582: queue_signal(info.si_signo, &info);
1583: }
1584: }
1585: break;
1.1.1.2 root 1586: default:
1587: // error:
1.1.1.6 ! root 1588: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
1.1.1.2 root 1589: trapnr);
1590: cpu_dump_state(env, stderr, fprintf, 0);
1591: abort();
1592: }
1593: process_pending_signals(env);
1594: }
1595: }
1596: #endif
1597:
1.1.1.3 root 1598: #ifdef TARGET_SH4
1599: void cpu_loop (CPUState *env)
1600: {
1601: int trapnr, ret;
1.1.1.4 root 1602: target_siginfo_t info;
1.1.1.6 ! root 1603:
1.1.1.3 root 1604: while (1) {
1605: trapnr = cpu_sh4_exec (env);
1.1.1.6 ! root 1606:
1.1.1.3 root 1607: switch (trapnr) {
1608: case 0x160:
1.1.1.6 ! root 1609: ret = do_syscall(env,
! 1610: env->gregs[3],
! 1611: env->gregs[4],
! 1612: env->gregs[5],
! 1613: env->gregs[6],
! 1614: env->gregs[7],
! 1615: env->gregs[0],
! 1616: env->gregs[1]);
1.1.1.4 root 1617: env->gregs[0] = ret;
1.1.1.3 root 1618: env->pc += 2;
1619: break;
1.1.1.6 ! root 1620: case EXCP_INTERRUPT:
! 1621: /* just indicate that signals should be handled asap */
! 1622: break;
! 1623: case EXCP_DEBUG:
! 1624: {
! 1625: int sig;
! 1626:
! 1627: sig = gdb_handlesig (env, TARGET_SIGTRAP);
! 1628: if (sig)
! 1629: {
! 1630: info.si_signo = sig;
! 1631: info.si_errno = 0;
! 1632: info.si_code = TARGET_TRAP_BRKPT;
! 1633: queue_signal(info.si_signo, &info);
! 1634: }
! 1635: }
! 1636: break;
! 1637: case 0xa0:
! 1638: case 0xc0:
! 1639: info.si_signo = SIGSEGV;
! 1640: info.si_errno = 0;
! 1641: info.si_code = TARGET_SEGV_MAPERR;
! 1642: info._sifields._sigfault._addr = env->tea;
! 1643: queue_signal(info.si_signo, &info);
! 1644: break;
! 1645:
! 1646: default:
! 1647: printf ("Unhandled trap: 0x%x\n", trapnr);
! 1648: cpu_dump_state(env, stderr, fprintf, 0);
! 1649: exit (1);
! 1650: }
! 1651: process_pending_signals (env);
! 1652: }
! 1653: }
! 1654: #endif
! 1655:
! 1656: #ifdef TARGET_CRIS
! 1657: void cpu_loop (CPUState *env)
! 1658: {
! 1659: int trapnr, ret;
! 1660: target_siginfo_t info;
! 1661:
! 1662: while (1) {
! 1663: trapnr = cpu_cris_exec (env);
! 1664: switch (trapnr) {
! 1665: case 0xaa:
! 1666: {
! 1667: info.si_signo = SIGSEGV;
! 1668: info.si_errno = 0;
! 1669: /* XXX: check env->error_code */
! 1670: info.si_code = TARGET_SEGV_MAPERR;
! 1671: info._sifields._sigfault._addr = env->debug1;
! 1672: queue_signal(info.si_signo, &info);
! 1673: }
! 1674: break;
! 1675: case EXCP_BREAK:
! 1676: ret = do_syscall(env,
! 1677: env->regs[9],
! 1678: env->regs[10],
! 1679: env->regs[11],
! 1680: env->regs[12],
! 1681: env->regs[13],
! 1682: env->pregs[7],
! 1683: env->pregs[11]);
! 1684: env->regs[10] = ret;
! 1685: env->pc += 2;
! 1686: break;
1.1.1.4 root 1687: case EXCP_DEBUG:
1688: {
1689: int sig;
1690:
1691: sig = gdb_handlesig (env, TARGET_SIGTRAP);
1692: if (sig)
1693: {
1694: info.si_signo = sig;
1695: info.si_errno = 0;
1696: info.si_code = TARGET_TRAP_BRKPT;
1697: queue_signal(info.si_signo, &info);
1698: }
1699: }
1700: break;
1.1.1.3 root 1701: default:
1702: printf ("Unhandled trap: 0x%x\n", trapnr);
1703: cpu_dump_state(env, stderr, fprintf, 0);
1704: exit (1);
1705: }
1706: process_pending_signals (env);
1707: }
1708: }
1709: #endif
1710:
1.1.1.5 root 1711: #ifdef TARGET_M68K
1712:
1713: void cpu_loop(CPUM68KState *env)
1714: {
1715: int trapnr;
1716: unsigned int n;
1717: target_siginfo_t info;
1718: TaskState *ts = env->opaque;
1.1.1.6 ! root 1719:
1.1.1.5 root 1720: for(;;) {
1721: trapnr = cpu_m68k_exec(env);
1722: switch(trapnr) {
1723: case EXCP_ILLEGAL:
1724: {
1725: if (ts->sim_syscalls) {
1726: uint16_t nr;
1727: nr = lduw(env->pc + 2);
1728: env->pc += 4;
1729: do_m68k_simcall(env, nr);
1730: } else {
1731: goto do_sigill;
1732: }
1733: }
1734: break;
1.1.1.6 ! root 1735: case EXCP_HALT_INSN:
1.1.1.5 root 1736: /* Semihosing syscall. */
1.1.1.6 ! root 1737: env->pc += 4;
1.1.1.5 root 1738: do_m68k_semihosting(env, env->dregs[0]);
1739: break;
1740: case EXCP_LINEA:
1741: case EXCP_LINEF:
1742: case EXCP_UNSUPPORTED:
1743: do_sigill:
1744: info.si_signo = SIGILL;
1745: info.si_errno = 0;
1746: info.si_code = TARGET_ILL_ILLOPN;
1747: info._sifields._sigfault._addr = env->pc;
1748: queue_signal(info.si_signo, &info);
1749: break;
1750: case EXCP_TRAP0:
1751: {
1752: ts->sim_syscalls = 0;
1753: n = env->dregs[0];
1754: env->pc += 2;
1.1.1.6 ! root 1755: env->dregs[0] = do_syscall(env,
! 1756: n,
1.1.1.5 root 1757: env->dregs[1],
1758: env->dregs[2],
1759: env->dregs[3],
1760: env->dregs[4],
1761: env->dregs[5],
1762: env->dregs[6]);
1763: }
1764: break;
1765: case EXCP_INTERRUPT:
1766: /* just indicate that signals should be handled asap */
1767: break;
1768: case EXCP_ACCESS:
1769: {
1770: info.si_signo = SIGSEGV;
1771: info.si_errno = 0;
1772: /* XXX: check env->error_code */
1773: info.si_code = TARGET_SEGV_MAPERR;
1774: info._sifields._sigfault._addr = env->mmu.ar;
1775: queue_signal(info.si_signo, &info);
1776: }
1777: break;
1778: case EXCP_DEBUG:
1779: {
1780: int sig;
1781:
1782: sig = gdb_handlesig (env, TARGET_SIGTRAP);
1783: if (sig)
1784: {
1785: info.si_signo = sig;
1786: info.si_errno = 0;
1787: info.si_code = TARGET_TRAP_BRKPT;
1788: queue_signal(info.si_signo, &info);
1789: }
1790: }
1791: break;
1792: default:
1.1.1.6 ! root 1793: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
1.1.1.5 root 1794: trapnr);
1795: cpu_dump_state(env, stderr, fprintf, 0);
1796: abort();
1797: }
1798: process_pending_signals(env);
1799: }
1800: }
1801: #endif /* TARGET_M68K */
1802:
1.1.1.6 ! root 1803: #ifdef TARGET_ALPHA
! 1804: void cpu_loop (CPUState *env)
! 1805: {
! 1806: int trapnr;
! 1807: target_siginfo_t info;
! 1808:
! 1809: while (1) {
! 1810: trapnr = cpu_alpha_exec (env);
! 1811:
! 1812: switch (trapnr) {
! 1813: case EXCP_RESET:
! 1814: fprintf(stderr, "Reset requested. Exit\n");
! 1815: exit(1);
! 1816: break;
! 1817: case EXCP_MCHK:
! 1818: fprintf(stderr, "Machine check exception. Exit\n");
! 1819: exit(1);
! 1820: break;
! 1821: case EXCP_ARITH:
! 1822: fprintf(stderr, "Arithmetic trap.\n");
! 1823: exit(1);
! 1824: break;
! 1825: case EXCP_HW_INTERRUPT:
! 1826: fprintf(stderr, "External interrupt. Exit\n");
! 1827: exit(1);
! 1828: break;
! 1829: case EXCP_DFAULT:
! 1830: fprintf(stderr, "MMU data fault\n");
! 1831: exit(1);
! 1832: break;
! 1833: case EXCP_DTB_MISS_PAL:
! 1834: fprintf(stderr, "MMU data TLB miss in PALcode\n");
! 1835: exit(1);
! 1836: break;
! 1837: case EXCP_ITB_MISS:
! 1838: fprintf(stderr, "MMU instruction TLB miss\n");
! 1839: exit(1);
! 1840: break;
! 1841: case EXCP_ITB_ACV:
! 1842: fprintf(stderr, "MMU instruction access violation\n");
! 1843: exit(1);
! 1844: break;
! 1845: case EXCP_DTB_MISS_NATIVE:
! 1846: fprintf(stderr, "MMU data TLB miss\n");
! 1847: exit(1);
! 1848: break;
! 1849: case EXCP_UNALIGN:
! 1850: fprintf(stderr, "Unaligned access\n");
! 1851: exit(1);
! 1852: break;
! 1853: case EXCP_OPCDEC:
! 1854: fprintf(stderr, "Invalid instruction\n");
! 1855: exit(1);
! 1856: break;
! 1857: case EXCP_FEN:
! 1858: fprintf(stderr, "Floating-point not allowed\n");
! 1859: exit(1);
! 1860: break;
! 1861: case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
! 1862: fprintf(stderr, "Call to PALcode\n");
! 1863: call_pal(env, (trapnr >> 6) | 0x80);
! 1864: break;
! 1865: case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1):
! 1866: fprintf(stderr, "Privileged call to PALcode\n");
! 1867: exit(1);
! 1868: break;
! 1869: case EXCP_DEBUG:
! 1870: {
! 1871: int sig;
! 1872:
! 1873: sig = gdb_handlesig (env, TARGET_SIGTRAP);
! 1874: if (sig)
! 1875: {
! 1876: info.si_signo = sig;
! 1877: info.si_errno = 0;
! 1878: info.si_code = TARGET_TRAP_BRKPT;
! 1879: queue_signal(info.si_signo, &info);
! 1880: }
! 1881: }
! 1882: break;
! 1883: default:
! 1884: printf ("Unhandled trap: 0x%x\n", trapnr);
! 1885: cpu_dump_state(env, stderr, fprintf, 0);
! 1886: exit (1);
! 1887: }
! 1888: process_pending_signals (env);
! 1889: }
! 1890: }
! 1891: #endif /* TARGET_ALPHA */
! 1892:
1.1 root 1893: void usage(void)
1894: {
1.1.1.6 ! root 1895: printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
! 1896: "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
1.1 root 1897: "Linux CPU emulator (compiled for %s emulation)\n"
1898: "\n"
1.1.1.6 ! root 1899: "Standard options:\n"
! 1900: "-h print this help\n"
! 1901: "-g port wait gdb connection to port\n"
! 1902: "-L path set the elf interpreter prefix (default=%s)\n"
! 1903: "-s size set the stack size in bytes (default=%ld)\n"
! 1904: "-cpu model select CPU (-cpu ? for list)\n"
! 1905: "-drop-ld-preload drop LD_PRELOAD for target process\n"
1.1 root 1906: "\n"
1.1.1.6 ! root 1907: "Debug options:\n"
1.1 root 1908: "-d options activate log (logfile=%s)\n"
1.1.1.6 ! root 1909: "-p pagesize set the host page size to 'pagesize'\n"
! 1910: "-strace log system calls\n"
! 1911: "\n"
! 1912: "Environment variables:\n"
! 1913: "QEMU_STRACE Print system calls and arguments similar to the\n"
! 1914: " 'strace' program. Enable by setting to any value.\n"
! 1915: ,
1.1 root 1916: TARGET_ARCH,
1.1.1.6 ! root 1917: interp_prefix,
1.1 root 1918: x86_stack_size,
1919: DEBUG_LOGFILE);
1920: _exit(1);
1921: }
1922:
1923: /* XXX: currently only used for async signals (see signal.c) */
1924: CPUState *global_env;
1925:
1926: /* used to free thread contexts */
1927: TaskState *first_task_state;
1928:
1929: int main(int argc, char **argv)
1930: {
1931: const char *filename;
1.1.1.6 ! root 1932: const char *cpu_model;
1.1 root 1933: struct target_pt_regs regs1, *regs = ®s1;
1934: struct image_info info1, *info = &info1;
1935: TaskState ts1, *ts = &ts1;
1936: CPUState *env;
1937: int optind;
1938: const char *r;
1.1.1.2 root 1939: int gdbstub_port = 0;
1.1.1.6 ! root 1940: int drop_ld_preload = 0, environ_count = 0;
! 1941: char **target_environ, **wrk, **dst;
! 1942:
1.1 root 1943: if (argc <= 1)
1944: usage();
1945:
1946: /* init debug */
1947: cpu_set_log_filename(DEBUG_LOGFILE);
1948:
1.1.1.6 ! root 1949: cpu_model = NULL;
1.1 root 1950: optind = 1;
1951: for(;;) {
1952: if (optind >= argc)
1953: break;
1954: r = argv[optind];
1955: if (r[0] != '-')
1956: break;
1957: optind++;
1958: r++;
1959: if (!strcmp(r, "-")) {
1960: break;
1961: } else if (!strcmp(r, "d")) {
1962: int mask;
1963: CPULogItem *item;
1964:
1965: if (optind >= argc)
1966: break;
1.1.1.6 ! root 1967:
1.1 root 1968: r = argv[optind++];
1969: mask = cpu_str_to_log_mask(r);
1970: if (!mask) {
1971: printf("Log items (comma separated):\n");
1972: for(item = cpu_log_items; item->mask != 0; item++) {
1973: printf("%-10s %s\n", item->name, item->help);
1974: }
1975: exit(1);
1976: }
1977: cpu_set_log(mask);
1978: } else if (!strcmp(r, "s")) {
1979: r = argv[optind++];
1980: x86_stack_size = strtol(r, (char **)&r, 0);
1981: if (x86_stack_size <= 0)
1982: usage();
1983: if (*r == 'M')
1984: x86_stack_size *= 1024 * 1024;
1985: else if (*r == 'k' || *r == 'K')
1986: x86_stack_size *= 1024;
1987: } else if (!strcmp(r, "L")) {
1988: interp_prefix = argv[optind++];
1989: } else if (!strcmp(r, "p")) {
1990: qemu_host_page_size = atoi(argv[optind++]);
1991: if (qemu_host_page_size == 0 ||
1992: (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
1993: fprintf(stderr, "page size must be a power of two\n");
1994: exit(1);
1995: }
1996: } else if (!strcmp(r, "g")) {
1.1.1.2 root 1997: gdbstub_port = atoi(argv[optind++]);
1.1.1.4 root 1998: } else if (!strcmp(r, "r")) {
1999: qemu_uname_release = argv[optind++];
1.1.1.6 ! root 2000: } else if (!strcmp(r, "cpu")) {
! 2001: cpu_model = argv[optind++];
! 2002: if (strcmp(cpu_model, "?") == 0) {
! 2003: /* XXX: implement xxx_cpu_list for targets that still miss it */
! 2004: #if defined(cpu_list)
! 2005: cpu_list(stdout, &fprintf);
! 2006: #endif
! 2007: _exit(1);
! 2008: }
! 2009: } else if (!strcmp(r, "drop-ld-preload")) {
! 2010: drop_ld_preload = 1;
! 2011: } else if (!strcmp(r, "strace")) {
! 2012: do_strace = 1;
! 2013: } else
1.1 root 2014: {
2015: usage();
2016: }
2017: }
2018: if (optind >= argc)
2019: usage();
2020: filename = argv[optind];
2021:
2022: /* Zero out regs */
2023: memset(regs, 0, sizeof(struct target_pt_regs));
2024:
2025: /* Zero out image_info */
2026: memset(info, 0, sizeof(struct image_info));
2027:
2028: /* Scan interp_prefix dir for replacement files. */
2029: init_paths(interp_prefix);
2030:
1.1.1.6 ! root 2031: if (cpu_model == NULL) {
! 2032: #if defined(TARGET_I386)
! 2033: #ifdef TARGET_X86_64
! 2034: cpu_model = "qemu64";
! 2035: #else
! 2036: cpu_model = "qemu32";
! 2037: #endif
! 2038: #elif defined(TARGET_ARM)
! 2039: cpu_model = "arm926";
! 2040: #elif defined(TARGET_M68K)
! 2041: cpu_model = "any";
! 2042: #elif defined(TARGET_SPARC)
! 2043: #ifdef TARGET_SPARC64
! 2044: cpu_model = "TI UltraSparc II";
! 2045: #else
! 2046: cpu_model = "Fujitsu MB86904";
! 2047: #endif
! 2048: #elif defined(TARGET_MIPS)
! 2049: #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
! 2050: cpu_model = "20Kc";
! 2051: #else
! 2052: cpu_model = "24Kf";
! 2053: #endif
! 2054: #elif defined(TARGET_PPC)
! 2055: #ifdef TARGET_PPC64
! 2056: cpu_model = "970";
! 2057: #else
! 2058: cpu_model = "750";
! 2059: #endif
! 2060: #else
! 2061: cpu_model = "any";
! 2062: #endif
! 2063: }
1.1 root 2064: /* NOTE: we need to init the CPU at this stage to get
2065: qemu_host_page_size */
1.1.1.6 ! root 2066: env = cpu_init(cpu_model);
! 2067: if (!env) {
! 2068: fprintf(stderr, "Unable to find CPU definition\n");
! 2069: exit(1);
! 2070: }
1.1.1.2 root 2071: global_env = env;
1.1.1.6 ! root 2072:
! 2073: if (getenv("QEMU_STRACE")) {
! 2074: do_strace = 1;
1.1 root 2075: }
1.1.1.6 ! root 2076:
! 2077: wrk = environ;
! 2078: while (*(wrk++))
! 2079: environ_count++;
! 2080:
! 2081: target_environ = malloc((environ_count + 1) * sizeof(char *));
! 2082: if (!target_environ)
! 2083: abort();
! 2084: for (wrk = environ, dst = target_environ; *wrk; wrk++) {
! 2085: if (drop_ld_preload && !strncmp(*wrk, "LD_PRELOAD=", 11))
! 2086: continue;
! 2087: *(dst++) = strdup(*wrk);
! 2088: }
! 2089: *dst = NULL; /* NULL terminate target_environ */
! 2090:
! 2091: if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
! 2092: printf("Error loading %s\n", filename);
! 2093: _exit(1);
! 2094: }
! 2095:
! 2096: for (wrk = target_environ; *wrk; wrk++) {
! 2097: free(*wrk);
! 2098: }
! 2099:
! 2100: free(target_environ);
! 2101:
1.1 root 2102: if (loglevel) {
2103: page_dump(logfile);
1.1.1.6 ! root 2104:
! 2105: fprintf(logfile, "start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
! 2106: fprintf(logfile, "end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
! 2107: fprintf(logfile, "start_code 0x" TARGET_ABI_FMT_lx "\n",
! 2108: info->start_code);
! 2109: fprintf(logfile, "start_data 0x" TARGET_ABI_FMT_lx "\n",
! 2110: info->start_data);
! 2111: fprintf(logfile, "end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data);
! 2112: fprintf(logfile, "start_stack 0x" TARGET_ABI_FMT_lx "\n",
! 2113: info->start_stack);
! 2114: fprintf(logfile, "brk 0x" TARGET_ABI_FMT_lx "\n", info->brk);
! 2115: fprintf(logfile, "entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
1.1 root 2116: }
2117:
1.1.1.3 root 2118: target_set_brk(info->brk);
1.1 root 2119: syscall_init();
2120: signal_init();
2121:
2122: /* build Task State */
2123: memset(ts, 0, sizeof(TaskState));
2124: env->opaque = ts;
2125: ts->used = 1;
1.1.1.4 root 2126: ts->info = info;
1.1 root 2127: env->user_mode_only = 1;
1.1.1.6 ! root 2128:
1.1 root 2129: #if defined(TARGET_I386)
2130: cpu_x86_set_cpl(env, 3);
2131:
2132: env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
2133: env->hflags |= HF_PE_MASK;
2134: if (env->cpuid_features & CPUID_SSE) {
2135: env->cr[4] |= CR4_OSFXSR_MASK;
2136: env->hflags |= HF_OSFXSR_MASK;
2137: }
1.1.1.6 ! root 2138: #ifndef TARGET_ABI32
! 2139: /* enable 64 bit mode if possible */
! 2140: if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
! 2141: fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
! 2142: exit(1);
! 2143: }
! 2144: env->cr[4] |= CR4_PAE_MASK;
! 2145: env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
! 2146: env->hflags |= HF_LMA_MASK;
! 2147: #endif
1.1 root 2148:
2149: /* flags setup : we activate the IRQs by default as in user mode */
2150: env->eflags |= IF_MASK;
1.1.1.6 ! root 2151:
1.1 root 2152: /* linux register setup */
1.1.1.6 ! root 2153: #ifndef TARGET_ABI32
! 2154: env->regs[R_EAX] = regs->rax;
! 2155: env->regs[R_EBX] = regs->rbx;
! 2156: env->regs[R_ECX] = regs->rcx;
! 2157: env->regs[R_EDX] = regs->rdx;
! 2158: env->regs[R_ESI] = regs->rsi;
! 2159: env->regs[R_EDI] = regs->rdi;
! 2160: env->regs[R_EBP] = regs->rbp;
! 2161: env->regs[R_ESP] = regs->rsp;
! 2162: env->eip = regs->rip;
! 2163: #else
1.1 root 2164: env->regs[R_EAX] = regs->eax;
2165: env->regs[R_EBX] = regs->ebx;
2166: env->regs[R_ECX] = regs->ecx;
2167: env->regs[R_EDX] = regs->edx;
2168: env->regs[R_ESI] = regs->esi;
2169: env->regs[R_EDI] = regs->edi;
2170: env->regs[R_EBP] = regs->ebp;
2171: env->regs[R_ESP] = regs->esp;
2172: env->eip = regs->eip;
1.1.1.6 ! root 2173: #endif
1.1 root 2174:
2175: /* linux interrupt setup */
1.1.1.3 root 2176: env->idt.base = h2g(idt_table);
1.1 root 2177: env->idt.limit = sizeof(idt_table) - 1;
2178: set_idt(0, 0);
2179: set_idt(1, 0);
2180: set_idt(2, 0);
2181: set_idt(3, 3);
2182: set_idt(4, 3);
2183: set_idt(5, 3);
2184: set_idt(6, 0);
2185: set_idt(7, 0);
2186: set_idt(8, 0);
2187: set_idt(9, 0);
2188: set_idt(10, 0);
2189: set_idt(11, 0);
2190: set_idt(12, 0);
2191: set_idt(13, 0);
2192: set_idt(14, 0);
2193: set_idt(15, 0);
2194: set_idt(16, 0);
2195: set_idt(17, 0);
2196: set_idt(18, 0);
2197: set_idt(19, 0);
2198: set_idt(0x80, 3);
2199:
2200: /* linux segment setup */
1.1.1.6 ! root 2201: {
! 2202: uint64_t *gdt_table;
! 2203: gdt_table = qemu_mallocz(sizeof(uint64_t) * TARGET_GDT_ENTRIES);
! 2204: env->gdt.base = h2g((unsigned long)gdt_table);
! 2205: env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
! 2206: #ifdef TARGET_ABI32
! 2207: write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
! 2208: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
! 2209: (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
! 2210: #else
! 2211: /* 64 bit code segment */
! 2212: write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
! 2213: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
! 2214: DESC_L_MASK |
! 2215: (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
! 2216: #endif
! 2217: write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
! 2218: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
! 2219: (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
! 2220: }
1.1 root 2221: cpu_x86_load_seg(env, R_CS, __USER_CS);
1.1.1.6 ! root 2222: cpu_x86_load_seg(env, R_SS, __USER_DS);
! 2223: #ifdef TARGET_ABI32
1.1 root 2224: cpu_x86_load_seg(env, R_DS, __USER_DS);
2225: cpu_x86_load_seg(env, R_ES, __USER_DS);
2226: cpu_x86_load_seg(env, R_FS, __USER_DS);
2227: cpu_x86_load_seg(env, R_GS, __USER_DS);
1.1.1.6 ! root 2228: /* This hack makes Wine work... */
! 2229: env->segs[R_FS].selector = 0;
! 2230: #else
! 2231: cpu_x86_load_seg(env, R_DS, 0);
! 2232: cpu_x86_load_seg(env, R_ES, 0);
! 2233: cpu_x86_load_seg(env, R_FS, 0);
! 2234: cpu_x86_load_seg(env, R_GS, 0);
! 2235: #endif
1.1 root 2236: #elif defined(TARGET_ARM)
2237: {
2238: int i;
1.1.1.2 root 2239: cpsr_write(env, regs->uregs[16], 0xffffffff);
1.1 root 2240: for(i = 0; i < 16; i++) {
2241: env->regs[i] = regs->uregs[i];
2242: }
2243: }
2244: #elif defined(TARGET_SPARC)
2245: {
2246: int i;
2247: env->pc = regs->pc;
2248: env->npc = regs->npc;
2249: env->y = regs->y;
2250: for(i = 0; i < 8; i++)
2251: env->gregs[i] = regs->u_regs[i];
2252: for(i = 0; i < 8; i++)
2253: env->regwptr[i] = regs->u_regs[i + 8];
2254: }
2255: #elif defined(TARGET_PPC)
2256: {
2257: int i;
2258:
1.1.1.6 ! root 2259: #if defined(TARGET_PPC64)
! 2260: #if defined(TARGET_ABI32)
! 2261: env->msr &= ~((target_ulong)1 << MSR_SF);
! 2262: #else
! 2263: env->msr |= (target_ulong)1 << MSR_SF;
! 2264: #endif
! 2265: #endif
1.1 root 2266: env->nip = regs->nip;
2267: for(i = 0; i < 32; i++) {
2268: env->gpr[i] = regs->gpr[i];
2269: }
2270: }
1.1.1.5 root 2271: #elif defined(TARGET_M68K)
2272: {
2273: env->pc = regs->pc;
2274: env->dregs[0] = regs->d0;
2275: env->dregs[1] = regs->d1;
2276: env->dregs[2] = regs->d2;
2277: env->dregs[3] = regs->d3;
2278: env->dregs[4] = regs->d4;
2279: env->dregs[5] = regs->d5;
2280: env->dregs[6] = regs->d6;
2281: env->dregs[7] = regs->d7;
2282: env->aregs[0] = regs->a0;
2283: env->aregs[1] = regs->a1;
2284: env->aregs[2] = regs->a2;
2285: env->aregs[3] = regs->a3;
2286: env->aregs[4] = regs->a4;
2287: env->aregs[5] = regs->a5;
2288: env->aregs[6] = regs->a6;
2289: env->aregs[7] = regs->usp;
2290: env->sr = regs->sr;
2291: ts->sim_syscalls = 1;
2292: }
1.1.1.2 root 2293: #elif defined(TARGET_MIPS)
2294: {
2295: int i;
2296:
2297: for(i = 0; i < 32; i++) {
1.1.1.6 ! root 2298: env->gpr[i][env->current_tc] = regs->regs[i];
1.1.1.2 root 2299: }
1.1.1.6 ! root 2300: env->PC[env->current_tc] = regs->cp0_epc;
1.1.1.2 root 2301: }
1.1.1.3 root 2302: #elif defined(TARGET_SH4)
2303: {
2304: int i;
2305:
2306: for(i = 0; i < 16; i++) {
2307: env->gregs[i] = regs->regs[i];
2308: }
2309: env->pc = regs->pc;
2310: }
1.1.1.6 ! root 2311: #elif defined(TARGET_ALPHA)
! 2312: {
! 2313: int i;
! 2314:
! 2315: for(i = 0; i < 28; i++) {
! 2316: env->ir[i] = ((abi_ulong *)regs)[i];
! 2317: }
! 2318: env->ipr[IPR_USP] = regs->usp;
! 2319: env->ir[30] = regs->usp;
! 2320: env->pc = regs->pc;
! 2321: env->unique = regs->unique;
! 2322: }
! 2323: #elif defined(TARGET_CRIS)
! 2324: {
! 2325: env->regs[0] = regs->r0;
! 2326: env->regs[1] = regs->r1;
! 2327: env->regs[2] = regs->r2;
! 2328: env->regs[3] = regs->r3;
! 2329: env->regs[4] = regs->r4;
! 2330: env->regs[5] = regs->r5;
! 2331: env->regs[6] = regs->r6;
! 2332: env->regs[7] = regs->r7;
! 2333: env->regs[8] = regs->r8;
! 2334: env->regs[9] = regs->r9;
! 2335: env->regs[10] = regs->r10;
! 2336: env->regs[11] = regs->r11;
! 2337: env->regs[12] = regs->r12;
! 2338: env->regs[13] = regs->r13;
! 2339: env->regs[14] = info->start_stack;
! 2340: env->regs[15] = regs->acr;
! 2341: env->pc = regs->erp;
! 2342: }
1.1 root 2343: #else
2344: #error unsupported target CPU
2345: #endif
2346:
1.1.1.6 ! root 2347: #if defined(TARGET_ARM) || defined(TARGET_M68K)
! 2348: ts->stack_base = info->start_stack;
! 2349: ts->heap_base = info->brk;
! 2350: /* This will be filled in on the first SYS_HEAPINFO call. */
! 2351: ts->heap_limit = 0;
! 2352: #endif
! 2353:
1.1.1.2 root 2354: if (gdbstub_port) {
2355: gdbserver_start (gdbstub_port);
1.1 root 2356: gdb_handlesig(env, 0);
2357: }
2358: cpu_loop(env);
2359: /* never exits */
2360: return 0;
2361: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.