Annotation of qemu/user-exec.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com