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

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

unix.superglobalmegacorp.com