(linenum→info "unix/slp.c:2238")

qemu/0.9.1/linux-user/main.c

    1: /*
    2:  *  qemu user main
    3:  *
    4:  *  Copyright (c) 2003-2008 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: 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: /* 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)
   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: /* 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: 
  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: /* CPUX86 core interface */
  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: /* 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
  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: /* 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: }
  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:             /* linux syscall from int $0x80 */
  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:             /* 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
  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:             /* XXX: potential problem if ABI32 */
  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:                 /* 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:
  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:             /* 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;
  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: /* XXX: find a better solution */
  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:                 /* we handle the FPU emulation here, as Linux */
  382:                 /* we get the opcode */
  383:                 /* FIXME - what to do if get_user() fails? */
  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:                     /* increment PC */
  394:                     env->regs[15] += 4;
  395:                 }
  396:             }
  397:             break;
  398:         case EXCP_SWI:
  399:         case EXCP_BKPT:
  400:             {
  401:                 env->eabi = 1;
  402:                 /* system call */
  403:                 if (trapnr == EXCP_BKPT) {
  404:                     if (env->thumb) {
  405:                         /* FIXME - what to do if get_user() fails? */
  406:                         get_user_u16(insn, env->regs[15]);
  407:                         n = insn & 0xff;
  408:                         env->regs[15] += 2;
  409:                     } else {
  410:                         /* FIXME - what to do if get_user() fails? */
  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:                         /* FIXME - what to do if get_user() fails? */
  418:                         get_user_u16(insn, env->regs[15] - 2);
  419:                         n = insn & 0xff;
  420:                     } else {
  421:                         /* FIXME - what to do if get_user() fails? */
  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:                     /* linux syscall */
  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:             /* just indicate that signals should be handled asap */
  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:                 /* XXX: check env->error_code */
  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: //#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;
  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:         /* 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);
  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:     /* restore the invalid window */
  558:     cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
  559:     sp_ptr = env->regbase[get_reg