File:  [Qemu by Fabrice Bellard] / qemu / user-exec.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:56:20 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, HEAD
qemu 0.15.1

    1: /*
    2:  *  User emulator execution
    3:  *
    4:  *  Copyright (c) 2003-2005 Fabrice Bellard
    5:  *
    6:  * This library is free software; you can redistribute it and/or
    7:  * modify it under the terms of the GNU Lesser General Public
    8:  * License as published by the Free Software Foundation; either
    9:  * version 2 of the License, or (at your option) any later version.
   10:  *
   11:  * This library 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 GNU
   14:  * Lesser General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU Lesser General Public
   17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
   18:  */
   19: #include "config.h"
   20: #include "exec.h"
   21: #include "disas.h"
   22: #include "tcg.h"
   23: 
   24: #undef EAX
   25: #undef ECX
   26: #undef EDX
   27: #undef EBX
   28: #undef ESP
   29: #undef EBP
   30: #undef ESI
   31: #undef EDI
   32: #undef EIP
   33: #include <signal.h>
   34: #ifdef __linux__
   35: #include <sys/ucontext.h>
   36: #endif
   37: 
   38: //#define DEBUG_SIGNAL
   39: 
   40: static void exception_action(CPUState *env1)
   41: {
   42: #if defined(TARGET_I386)
   43:     raise_exception_err(env1->exception_index, env1->error_code);
   44: #else
   45:     cpu_loop_exit(env1);
   46: #endif
   47: }
   48: 
   49: /* exit the current TB from a signal handler. The host registers are
   50:    restored in a state compatible with the CPU emulator
   51:  */
   52: void cpu_resume_from_signal(CPUState *env1, void *puc)
   53: {
   54: #ifdef __linux__
   55:     struct ucontext *uc = puc;
   56: #elif defined(__OpenBSD__)
   57:     struct sigcontext *uc = puc;
   58: #endif
   59: 
   60:     env = env1;
   61: 
   62:     /* XXX: restore cpu registers saved in host registers */
   63: 
   64:     if (puc) {
   65:         /* XXX: use siglongjmp ? */
   66: #ifdef __linux__
   67: #ifdef __ia64
   68:         sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
   69: #else
   70:         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
   71: #endif
   72: #elif defined(__OpenBSD__)
   73:         sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
   74: #endif
   75:     }
   76:     env->exception_index = -1;
   77:     longjmp(env->jmp_env, 1);
   78: }
   79: 
   80: /* 'pc' is the host PC at which the exception was raised. 'address' is
   81:    the effective address of the memory exception. 'is_write' is 1 if a
   82:    write caused the exception and otherwise 0'. 'old_set' is the
   83:    signal set which should be restored */
   84: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
   85:                                     int is_write, sigset_t *old_set,
   86:                                     void *puc)
   87: {
   88:     TranslationBlock *tb;
   89:     int ret;
   90: 
   91:     if (cpu_single_env) {
   92:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
   93:     }
   94: #if defined(DEBUG_SIGNAL)
   95:     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
   96:                 pc, address, is_write, *(unsigned long *)old_set);
   97: #endif
   98:     /* XXX: locking issue */
   99:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
  100:         return 1;
  101:     }
  102: 
  103:     /* see if it is an MMU fault */
  104:     ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
  105:     if (ret < 0) {
  106:         return 0; /* not an MMU fault */
  107:     }
  108:     if (ret == 0) {
  109:         return 1; /* the MMU fault was handled without causing real CPU fault */
  110:     }
  111:     /* now we have a real cpu fault */
  112:     tb = tb_find_pc(pc);
  113:     if (tb) {
  114:         /* the PC is inside the translated code. It means that we have
  115:            a virtual CPU fault */
  116:         cpu_restore_state(tb, env, pc);
  117:     }
  118: 
  119:     /* we restore the process signal mask as the sigreturn should
  120:        do it (XXX: use sigsetjmp) */
  121:     sigprocmask(SIG_SETMASK, old_set, NULL);
  122:     exception_action(env);
  123: 
  124:     /* never comes here */
  125:     return 1;
  126: }
  127: 
  128: #if defined(__i386__)
  129: 
  130: #if defined(__APPLE__)
  131: #include <sys/ucontext.h>
  132: 
  133: #define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext->ss.eip))
  134: #define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
  135: #define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
  136: #define MASK_sig(context)    ((context)->uc_sigmask)
  137: #elif defined(__NetBSD__)
  138: #include <ucontext.h>
  139: 
  140: #define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
  141: #define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
  142: #define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
  143: #define MASK_sig(context)    ((context)->uc_sigmask)
  144: #elif defined(__FreeBSD__) || defined(__DragonFly__)
  145: #include <ucontext.h>
  146: 
  147: #define EIP_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_eip))
  148: #define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
  149: #define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
  150: #define MASK_sig(context)    ((context)->uc_sigmask)
  151: #elif defined(__OpenBSD__)
  152: #define EIP_sig(context)     ((context)->sc_eip)
  153: #define TRAP_sig(context)    ((context)->sc_trapno)
  154: #define ERROR_sig(context)   ((context)->sc_err)
  155: #define MASK_sig(context)    ((context)->sc_mask)
  156: #else
  157: #define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
  158: #define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
  159: #define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
  160: #define MASK_sig(context)    ((context)->uc_sigmask)
  161: #endif
  162: 
  163: int cpu_signal_handler(int host_signum, void *pinfo,
  164:                        void *puc)
  165: {
  166:     siginfo_t *info = pinfo;
  167: #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
  168:     ucontext_t *uc = puc;
  169: #elif defined(__OpenBSD__)
  170:     struct sigcontext *uc = puc;
  171: #else
  172:     struct ucontext *uc = puc;
  173: #endif
  174:     unsigned long pc;
  175:     int trapno;
  176: 
  177: #ifndef REG_EIP
  178: /* for glibc 2.1 */
  179: #define REG_EIP    EIP
  180: #define REG_ERR    ERR
  181: #define REG_TRAPNO TRAPNO
  182: #endif
  183:     pc = EIP_sig(uc);
  184:     trapno = TRAP_sig(uc);
  185:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  186:                              trapno == 0xe ?
  187:                              (ERROR_sig(uc) >> 1) & 1 : 0,
  188:                              &MASK_sig(uc), puc);
  189: }
  190: 
  191: #elif defined(__x86_64__)
  192: 
  193: #ifdef __NetBSD__
  194: #define PC_sig(context)       _UC_MACHINE_PC(context)
  195: #define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
  196: #define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
  197: #define MASK_sig(context)     ((context)->uc_sigmask)
  198: #elif defined(__OpenBSD__)
  199: #define PC_sig(context)       ((context)->sc_rip)
  200: #define TRAP_sig(context)     ((context)->sc_trapno)
  201: #define ERROR_sig(context)    ((context)->sc_err)
  202: #define MASK_sig(context)     ((context)->sc_mask)
  203: #elif defined(__FreeBSD__) || defined(__DragonFly__)
  204: #include <ucontext.h>
  205: 
  206: #define PC_sig(context)  (*((unsigned long *)&(context)->uc_mcontext.mc_rip))
  207: #define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
  208: #define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
  209: #define MASK_sig(context)     ((context)->uc_sigmask)
  210: #else
  211: #define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
  212: #define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
  213: #define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
  214: #define MASK_sig(context)     ((context)->uc_sigmask)
  215: #endif
  216: 
  217: int cpu_signal_handler(int host_signum, void *pinfo,
  218:                        void *puc)
  219: {
  220:     siginfo_t *info = pinfo;
  221:     unsigned long pc;
  222: #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
  223:     ucontext_t *uc = puc;
  224: #elif defined(__OpenBSD__)
  225:     struct sigcontext *uc = puc;
  226: #else
  227:     struct ucontext *uc = puc;
  228: #endif
  229: 
  230:     pc = PC_sig(uc);
  231:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  232:                              TRAP_sig(uc) == 0xe ?
  233:                              (ERROR_sig(uc) >> 1) & 1 : 0,
  234:                              &MASK_sig(uc), puc);
  235: }
  236: 
  237: #elif defined(_ARCH_PPC)
  238: 
  239: /***********************************************************************
  240:  * signal context platform-specific definitions
  241:  * From Wine
  242:  */
  243: #ifdef linux
  244: /* All Registers access - only for local access */
  245: #define REG_sig(reg_name, context)              \
  246:     ((context)->uc_mcontext.regs->reg_name)
  247: /* Gpr Registers access  */
  248: #define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
  249: /* Program counter */
  250: #define IAR_sig(context)                       REG_sig(nip, context)
  251: /* Machine State Register (Supervisor) */
  252: #define MSR_sig(context)                       REG_sig(msr, context)
  253: /* Count register */
  254: #define CTR_sig(context)                       REG_sig(ctr, context)
  255: /* User's integer exception register */
  256: #define XER_sig(context)                       REG_sig(xer, context)
  257: /* Link register */
  258: #define LR_sig(context)                        REG_sig(link, context)
  259: /* Condition register */
  260: #define CR_sig(context)                        REG_sig(ccr, context)
  261: 
  262: /* Float Registers access  */
  263: #define FLOAT_sig(reg_num, context)                                     \
  264:     (((double *)((char *)((context)->uc_mcontext.regs + 48 * 4)))[reg_num])
  265: #define FPSCR_sig(context) \
  266:     (*(int *)((char *)((context)->uc_mcontext.regs + (48 + 32 * 2) * 4)))
  267: /* Exception Registers access */
  268: #define DAR_sig(context)                       REG_sig(dar, context)
  269: #define DSISR_sig(context)                     REG_sig(dsisr, context)
  270: #define TRAP_sig(context)                      REG_sig(trap, context)
  271: #endif /* linux */
  272: 
  273: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  274: #include <ucontext.h>
  275: #define IAR_sig(context)               ((context)->uc_mcontext.mc_srr0)
  276: #define MSR_sig(context)               ((context)->uc_mcontext.mc_srr1)
  277: #define CTR_sig(context)               ((context)->uc_mcontext.mc_ctr)
  278: #define XER_sig(context)               ((context)->uc_mcontext.mc_xer)
  279: #define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
  280: #define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
  281: /* Exception Registers access */
  282: #define DAR_sig(context)               ((context)->uc_mcontext.mc_dar)
  283: #define DSISR_sig(context)             ((context)->uc_mcontext.mc_dsisr)
  284: #define TRAP_sig(context)              ((context)->uc_mcontext.mc_exc)
  285: #endif /* __FreeBSD__|| __FreeBSD_kernel__ */
  286: 
  287: #ifdef __APPLE__
  288: #include <sys/ucontext.h>
  289: typedef struct ucontext SIGCONTEXT;
  290: /* All Registers access - only for local access */
  291: #define REG_sig(reg_name, context)              \
  292:     ((context)->uc_mcontext->ss.reg_name)
  293: #define FLOATREG_sig(reg_name, context)         \
  294:     ((context)->uc_mcontext->fs.reg_name)
  295: #define EXCEPREG_sig(reg_name, context)         \
  296:     ((context)->uc_mcontext->es.reg_name)
  297: #define VECREG_sig(reg_name, context)           \
  298:     ((context)->uc_mcontext->vs.reg_name)
  299: /* Gpr Registers access */
  300: #define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
  301: /* Program counter */
  302: #define IAR_sig(context)                       REG_sig(srr0, context)
  303: /* Machine State Register (Supervisor) */
  304: #define MSR_sig(context)                       REG_sig(srr1, context)
  305: #define CTR_sig(context)                       REG_sig(ctr, context)
  306: /* Link register */
  307: #define XER_sig(context)                       REG_sig(xer, context)
  308: /* User's integer exception register */
  309: #define LR_sig(context)                        REG_sig(lr, context)
  310: /* Condition register */
  311: #define CR_sig(context)                        REG_sig(cr, context)
  312: /* Float Registers access */
  313: #define FLOAT_sig(reg_num, context)             \
  314:     FLOATREG_sig(fpregs[reg_num], context)
  315: #define FPSCR_sig(context)                      \
  316:     ((double)FLOATREG_sig(fpscr, context))
  317: /* Exception Registers access */
  318: /* Fault registers for coredump */
  319: #define DAR_sig(context)                       EXCEPREG_sig(dar, context)
  320: #define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
  321: /* number of powerpc exception taken */
  322: #define TRAP_sig(context)                      EXCEPREG_sig(exception, context)
  323: #endif /* __APPLE__ */
  324: 
  325: int cpu_signal_handler(int host_signum, void *pinfo,
  326:                        void *puc)
  327: {
  328:     siginfo_t *info = pinfo;
  329: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  330:     ucontext_t *uc = puc;
  331: #else
  332:     struct ucontext *uc = puc;
  333: #endif
  334:     unsigned long pc;
  335:     int is_write;
  336: 
  337:     pc = IAR_sig(uc);
  338:     is_write = 0;
  339: #if 0
  340:     /* ppc 4xx case */
  341:     if (DSISR_sig(uc) & 0x00800000) {
  342:         is_write = 1;
  343:     }
  344: #else
  345:     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) {
  346:         is_write = 1;
  347:     }
  348: #endif
  349:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  350:                              is_write, &uc->uc_sigmask, puc);
  351: }
  352: 
  353: #elif defined(__alpha__)
  354: 
  355: int cpu_signal_handler(int host_signum, void *pinfo,
  356:                            void *puc)
  357: {
  358:     siginfo_t *info = pinfo;
  359:     struct ucontext *uc = puc;
  360:     uint32_t *pc = uc->uc_mcontext.sc_pc;
  361:     uint32_t insn = *pc;
  362:     int is_write = 0;
  363: 
  364:     /* XXX: need kernel patch to get write flag faster */
  365:     switch (insn >> 26) {
  366:     case 0x0d: /* stw */
  367:     case 0x0e: /* stb */
  368:     case 0x0f: /* stq_u */
  369:     case 0x24: /* stf */
  370:     case 0x25: /* stg */
  371:     case 0x26: /* sts */
  372:     case 0x27: /* stt */
  373:     case 0x2c: /* stl */
  374:     case 0x2d: /* stq */
  375:     case 0x2e: /* stl_c */
  376:     case 0x2f: /* stq_c */
  377:         is_write = 1;
  378:     }
  379: 
  380:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  381:                              is_write, &uc->uc_sigmask, puc);
  382: }
  383: #elif defined(__sparc__)
  384: 
  385: int cpu_signal_handler(int host_signum, void *pinfo,
  386:                        void *puc)
  387: {
  388:     siginfo_t *info = pinfo;
  389:     int is_write;
  390:     uint32_t insn;
  391: #if !defined(__arch64__) || defined(CONFIG_SOLARIS)
  392:     uint32_t *regs = (uint32_t *)(info + 1);
  393:     void *sigmask = (regs + 20);
  394:     /* XXX: is there a standard glibc define ? */
  395:     unsigned long pc = regs[1];
  396: #else
  397: #ifdef __linux__
  398:     struct sigcontext *sc = puc;
  399:     unsigned long pc = sc->sigc_regs.tpc;
  400:     void *sigmask = (void *)sc->sigc_mask;
  401: #elif defined(__OpenBSD__)
  402:     struct sigcontext *uc = puc;
  403:     unsigned long pc = uc->sc_pc;
  404:     void *sigmask = (void *)(long)uc->sc_mask;
  405: #endif
  406: #endif
  407: 
  408:     /* XXX: need kernel patch to get write flag faster */
  409:     is_write = 0;
  410:     insn = *(uint32_t *)pc;
  411:     if ((insn >> 30) == 3) {
  412:         switch ((insn >> 19) & 0x3f) {
  413:         case 0x05: /* stb */
  414:         case 0x15: /* stba */
  415:         case 0x06: /* sth */
  416:         case 0x16: /* stha */
  417:         case 0x04: /* st */
  418:         case 0x14: /* sta */
  419:         case 0x07: /* std */
  420:         case 0x17: /* stda */
  421:         case 0x0e: /* stx */
  422:         case 0x1e: /* stxa */
  423:         case 0x24: /* stf */
  424:         case 0x34: /* stfa */
  425:         case 0x27: /* stdf */
  426:         case 0x37: /* stdfa */
  427:         case 0x26: /* stqf */
  428:         case 0x36: /* stqfa */
  429:         case 0x25: /* stfsr */
  430:         case 0x3c: /* casa */
  431:         case 0x3e: /* casxa */
  432:             is_write = 1;
  433:             break;
  434:         }
  435:     }
  436:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  437:                              is_write, sigmask, NULL);
  438: }
  439: 
  440: #elif defined(__arm__)
  441: 
  442: int cpu_signal_handler(int host_signum, void *pinfo,
  443:                        void *puc)
  444: {
  445:     siginfo_t *info = pinfo;
  446:     struct ucontext *uc = puc;
  447:     unsigned long pc;
  448:     int is_write;
  449: 
  450: #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
  451:     pc = uc->uc_mcontext.gregs[R15];
  452: #else
  453:     pc = uc->uc_mcontext.arm_pc;
  454: #endif
  455:     /* XXX: compute is_write */
  456:     is_write = 0;
  457:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  458:                              is_write,
  459:                              &uc->uc_sigmask, puc);
  460: }
  461: 
  462: #elif defined(__mc68000)
  463: 
  464: int cpu_signal_handler(int host_signum, void *pinfo,
  465:                        void *puc)
  466: {
  467:     siginfo_t *info = pinfo;
  468:     struct ucontext *uc = puc;
  469:     unsigned long pc;
  470:     int is_write;
  471: 
  472:     pc = uc->uc_mcontext.gregs[16];
  473:     /* XXX: compute is_write */
  474:     is_write = 0;
  475:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  476:                              is_write,
  477:                              &uc->uc_sigmask, puc);
  478: }
  479: 
  480: #elif defined(__ia64)
  481: 
  482: #ifndef __ISR_VALID
  483:   /* This ought to be in <bits/siginfo.h>... */
  484: # define __ISR_VALID    1
  485: #endif
  486: 
  487: int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
  488: {
  489:     siginfo_t *info = pinfo;
  490:     struct ucontext *uc = puc;
  491:     unsigned long ip;
  492:     int is_write = 0;
  493: 
  494:     ip = uc->uc_mcontext.sc_ip;
  495:     switch (host_signum) {
  496:     case SIGILL:
  497:     case SIGFPE:
  498:     case SIGSEGV:
  499:     case SIGBUS:
  500:     case SIGTRAP:
  501:         if (info->si_code && (info->si_segvflags & __ISR_VALID)) {
  502:             /* ISR.W (write-access) is bit 33:  */
  503:             is_write = (info->si_isr >> 33) & 1;
  504:         }
  505:         break;
  506: 
  507:     default:
  508:         break;
  509:     }
  510:     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
  511:                              is_write,
  512:                              (sigset_t *)&uc->uc_sigmask, puc);
  513: }
  514: 
  515: #elif defined(__s390__)
  516: 
  517: int cpu_signal_handler(int host_signum, void *pinfo,
  518:                        void *puc)
  519: {
  520:     siginfo_t *info = pinfo;
  521:     struct ucontext *uc = puc;
  522:     unsigned long pc;
  523:     uint16_t *pinsn;
  524:     int is_write = 0;
  525: 
  526:     pc = uc->uc_mcontext.psw.addr;
  527: 
  528:     /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
  529:        of the normal 2 arguments.  The 3rd argument contains the "int_code"
  530:        from the hardware which does in fact contain the is_write value.
  531:        The rt signal handler, as far as I can tell, does not give this value
  532:        at all.  Not that we could get to it from here even if it were.  */
  533:     /* ??? This is not even close to complete, since it ignores all
  534:        of the read-modify-write instructions.  */
  535:     pinsn = (uint16_t *)pc;
  536:     switch (pinsn[0] >> 8) {
  537:     case 0x50: /* ST */
  538:     case 0x42: /* STC */
  539:     case 0x40: /* STH */
  540:         is_write = 1;
  541:         break;
  542:     case 0xc4: /* RIL format insns */
  543:         switch (pinsn[0] & 0xf) {
  544:         case 0xf: /* STRL */
  545:         case 0xb: /* STGRL */
  546:         case 0x7: /* STHRL */
  547:             is_write = 1;
  548:         }
  549:         break;
  550:     case 0xe3: /* RXY format insns */
  551:         switch (pinsn[2] & 0xff) {
  552:         case 0x50: /* STY */
  553:         case 0x24: /* STG */
  554:         case 0x72: /* STCY */
  555:         case 0x70: /* STHY */
  556:         case 0x8e: /* STPQ */
  557:         case 0x3f: /* STRVH */
  558:         case 0x3e: /* STRV */
  559:         case 0x2f: /* STRVG */
  560:             is_write = 1;
  561:         }
  562:         break;
  563:     }
  564:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  565:                              is_write, &uc->uc_sigmask, puc);
  566: }
  567: 
  568: #elif defined(__mips__)
  569: 
  570: int cpu_signal_handler(int host_signum, void *pinfo,
  571:                        void *puc)
  572: {
  573:     siginfo_t *info = pinfo;
  574:     struct ucontext *uc = puc;
  575:     greg_t pc = uc->uc_mcontext.pc;
  576:     int is_write;
  577: 
  578:     /* XXX: compute is_write */
  579:     is_write = 0;
  580:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  581:                              is_write, &uc->uc_sigmask, puc);
  582: }
  583: 
  584: #elif defined(__hppa__)
  585: 
  586: int cpu_signal_handler(int host_signum, void *pinfo,
  587:                        void *puc)
  588: {
  589:     struct siginfo *info = pinfo;
  590:     struct ucontext *uc = puc;
  591:     unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
  592:     uint32_t insn = *(uint32_t *)pc;
  593:     int is_write = 0;
  594: 
  595:     /* XXX: need kernel patch to get write flag faster.  */
  596:     switch (insn >> 26) {
  597:     case 0x1a: /* STW */
  598:     case 0x19: /* STH */
  599:     case 0x18: /* STB */
  600:     case 0x1b: /* STWM */
  601:         is_write = 1;
  602:         break;
  603: 
  604:     case 0x09: /* CSTWX, FSTWX, FSTWS */
  605:     case 0x0b: /* CSTDX, FSTDX, FSTDS */
  606:         /* Distinguish from coprocessor load ... */
  607:         is_write = (insn >> 9) & 1;
  608:         break;
  609: 
  610:     case 0x03:
  611:         switch ((insn >> 6) & 15) {
  612:         case 0xa: /* STWS */
  613:         case 0x9: /* STHS */
  614:         case 0x8: /* STBS */
  615:         case 0xe: /* STWAS */
  616:         case 0xc: /* STBYS */
  617:             is_write = 1;
  618:         }
  619:         break;
  620:     }
  621: 
  622:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
  623:                              is_write, &uc->uc_sigmask, puc);
  624: }
  625: 
  626: #else
  627: 
  628: #error host CPU specific signal handler needed
  629: 
  630: #endif
  631: 
  632: #if defined(TARGET_I386)
  633: 
  634: void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
  635: {
  636:     CPUX86State *saved_env;
  637: 
  638:     saved_env = env;
  639:     env = s;
  640:     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
  641:         selector &= 0xffff;
  642:         cpu_x86_load_seg_cache(env, seg_reg, selector,
  643:                                (selector << 4), 0xffff, 0);
  644:     } else {
  645:         helper_load_seg(seg_reg, selector);
  646:     }
  647:     env = saved_env;
  648: }
  649: 
  650: void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
  651: {
  652:     CPUX86State *saved_env;
  653: 
  654:     saved_env = env;
  655:     env = s;
  656: 
  657:     helper_fsave(ptr, data32);
  658: 
  659:     env = saved_env;
  660: }
  661: 
  662: void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
  663: {
  664:     CPUX86State *saved_env;
  665: 
  666:     saved_env = env;
  667:     env = s;
  668: 
  669:     helper_frstor(ptr, data32);
  670: 
  671:     env = saved_env;
  672: }
  673: 
  674: #endif /* TARGET_I386 */

unix.superglobalmegacorp.com