Annotation of qemu/cpu-exec.c, revision 1.1.1.6

1.1       root        1: /*
                      2:  *  i386 emulator main execution loop
1.1.1.6 ! root        3:  *
1.1       root        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, write to the Free Software
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: #include "config.h"
                     21: #include "exec.h"
                     22: #include "disas.h"
                     23: 
                     24: #if !defined(CONFIG_SOFTMMU)
                     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: #include <sys/ucontext.h>
                     36: #endif
                     37: 
                     38: int tb_invalidated_flag;
                     39: 
                     40: //#define DEBUG_EXEC
                     41: //#define DEBUG_SIGNAL
                     42: 
1.1.1.6 ! root       43: #define SAVE_GLOBALS()
        !            44: #define RESTORE_GLOBALS()
        !            45: 
        !            46: #if defined(__sparc__) && !defined(HOST_SOLARIS)
        !            47: #include <features.h>
        !            48: #if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
        !            49:                            ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
        !            50: // Work around ugly bugs in glibc that mangle global register contents
        !            51: 
        !            52: static volatile void *saved_env;
        !            53: static volatile unsigned long saved_t0, saved_i7;
        !            54: #undef SAVE_GLOBALS
        !            55: #define SAVE_GLOBALS() do {                                     \
        !            56:         saved_env = env;                                        \
        !            57:         saved_t0 = T0;                                          \
        !            58:         asm volatile ("st %%i7, [%0]" : : "r" (&saved_i7));     \
        !            59:     } while(0)
        !            60: 
        !            61: #undef RESTORE_GLOBALS
        !            62: #define RESTORE_GLOBALS() do {                                  \
        !            63:         env = (void *)saved_env;                                \
        !            64:         T0 = saved_t0;                                          \
        !            65:         asm volatile ("ld [%0], %%i7" : : "r" (&saved_i7));     \
        !            66:     } while(0)
        !            67: 
        !            68: static int sparc_setjmp(jmp_buf buf)
        !            69: {
        !            70:     int ret;
        !            71: 
        !            72:     SAVE_GLOBALS();
        !            73:     ret = setjmp(buf);
        !            74:     RESTORE_GLOBALS();
        !            75:     return ret;
        !            76: }
        !            77: #undef setjmp
        !            78: #define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
        !            79: 
        !            80: static void sparc_longjmp(jmp_buf buf, int val)
        !            81: {
        !            82:     SAVE_GLOBALS();
        !            83:     longjmp(buf, val);
        !            84: }
        !            85: #define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
        !            86: #endif
        !            87: #endif
        !            88: 
1.1       root       89: void cpu_loop_exit(void)
                     90: {
1.1.1.6 ! root       91:     /* NOTE: the register at this point must be saved by hand because
        !            92:        longjmp restore them */
        !            93:     regs_to_env();
1.1       root       94:     longjmp(env->jmp_env, 1);
                     95: }
1.1.1.6 ! root       96: 
1.1.1.5   root       97: #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
1.1       root       98: #define reg_T2
                     99: #endif
                    100: 
                    101: /* exit the current TB from a signal handler. The host registers are
                    102:    restored in a state compatible with the CPU emulator
                    103:  */
1.1.1.6 ! root      104: void cpu_resume_from_signal(CPUState *env1, void *puc)
1.1       root      105: {
                    106: #if !defined(CONFIG_SOFTMMU)
                    107:     struct ucontext *uc = puc;
                    108: #endif
                    109: 
                    110:     env = env1;
                    111: 
                    112:     /* XXX: restore cpu registers saved in host registers */
                    113: 
                    114: #if !defined(CONFIG_SOFTMMU)
                    115:     if (puc) {
                    116:         /* XXX: use siglongjmp ? */
                    117:         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
                    118:     }
                    119: #endif
                    120:     longjmp(env->jmp_env, 1);
                    121: }
                    122: 
1.1.1.2   root      123: 
                    124: static TranslationBlock *tb_find_slow(target_ulong pc,
                    125:                                       target_ulong cs_base,
1.1.1.6 ! root      126:                                       uint64_t flags)
1.1.1.2   root      127: {
                    128:     TranslationBlock *tb, **ptb1;
                    129:     int code_gen_size;
                    130:     unsigned int h;
                    131:     target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
                    132:     uint8_t *tc_ptr;
1.1.1.6 ! root      133: 
1.1.1.2   root      134:     spin_lock(&tb_lock);
                    135: 
                    136:     tb_invalidated_flag = 0;
1.1.1.6 ! root      137: 
1.1.1.2   root      138:     regs_to_env(); /* XXX: do it just before cpu_gen_code() */
1.1.1.6 ! root      139: 
1.1.1.2   root      140:     /* find translated block using physical mappings */
                    141:     phys_pc = get_phys_addr_code(env, pc);
                    142:     phys_page1 = phys_pc & TARGET_PAGE_MASK;
                    143:     phys_page2 = -1;
                    144:     h = tb_phys_hash_func(phys_pc);
                    145:     ptb1 = &tb_phys_hash[h];
                    146:     for(;;) {
                    147:         tb = *ptb1;
                    148:         if (!tb)
                    149:             goto not_found;
1.1.1.6 ! root      150:         if (tb->pc == pc &&
1.1.1.2   root      151:             tb->page_addr[0] == phys_page1 &&
1.1.1.6 ! root      152:             tb->cs_base == cs_base &&
1.1.1.2   root      153:             tb->flags == flags) {
                    154:             /* check next page if needed */
                    155:             if (tb->page_addr[1] != -1) {
1.1.1.6 ! root      156:                 virt_page2 = (pc & TARGET_PAGE_MASK) +
1.1.1.2   root      157:                     TARGET_PAGE_SIZE;
                    158:                 phys_page2 = get_phys_addr_code(env, virt_page2);
                    159:                 if (tb->page_addr[1] == phys_page2)
                    160:                     goto found;
                    161:             } else {
                    162:                 goto found;
                    163:             }
                    164:         }
                    165:         ptb1 = &tb->phys_hash_next;
                    166:     }
                    167:  not_found:
                    168:     /* if no translated code available, then translate it now */
                    169:     tb = tb_alloc(pc);
                    170:     if (!tb) {
                    171:         /* flush must be done */
                    172:         tb_flush(env);
                    173:         /* cannot fail at this point */
                    174:         tb = tb_alloc(pc);
                    175:         /* don't forget to invalidate previous TB info */
                    176:         tb_invalidated_flag = 1;
                    177:     }
                    178:     tc_ptr = code_gen_ptr;
                    179:     tb->tc_ptr = tc_ptr;
                    180:     tb->cs_base = cs_base;
                    181:     tb->flags = flags;
1.1.1.6 ! root      182:     SAVE_GLOBALS();
        !           183:     cpu_gen_code(env, tb, &code_gen_size);
        !           184:     RESTORE_GLOBALS();
1.1.1.2   root      185:     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
1.1.1.6 ! root      186: 
1.1.1.2   root      187:     /* check next page if needed */
                    188:     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
                    189:     phys_page2 = -1;
                    190:     if ((pc & TARGET_PAGE_MASK) != virt_page2) {
                    191:         phys_page2 = get_phys_addr_code(env, virt_page2);
                    192:     }
                    193:     tb_link_phys(tb, phys_pc, phys_page2);
1.1.1.6 ! root      194: 
1.1.1.2   root      195:  found:
                    196:     /* we add the TB in the virtual pc hash table */
                    197:     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
                    198:     spin_unlock(&tb_lock);
                    199:     return tb;
                    200: }
                    201: 
                    202: static inline TranslationBlock *tb_find_fast(void)
                    203: {
                    204:     TranslationBlock *tb;
                    205:     target_ulong cs_base, pc;
1.1.1.6 ! root      206:     uint64_t flags;
1.1.1.2   root      207: 
                    208:     /* we record a subset of the CPU state. It will
                    209:        always be the same before a given translated block
                    210:        is executed. */
                    211: #if defined(TARGET_I386)
                    212:     flags = env->hflags;
                    213:     flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
1.1.1.6 ! root      214:     flags |= env->intercept;
1.1.1.2   root      215:     cs_base = env->segs[R_CS].base;
                    216:     pc = cs_base + env->eip;
                    217: #elif defined(TARGET_ARM)
                    218:     flags = env->thumb | (env->vfp.vec_len << 1)
                    219:             | (env->vfp.vec_stride << 4);
                    220:     if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
                    221:         flags |= (1 << 6);
1.1.1.3   root      222:     if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
                    223:         flags |= (1 << 7);
1.1.1.6 ! root      224:     flags |= (env->condexec_bits << 8);
1.1.1.2   root      225:     cs_base = 0;
                    226:     pc = env->regs[15];
                    227: #elif defined(TARGET_SPARC)
                    228: #ifdef TARGET_SPARC64
1.1.1.4   root      229:     // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
                    230:     flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
                    231:         | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
1.1.1.2   root      232: #else
1.1.1.6 ! root      233:     // FPU enable . Supervisor
        !           234:     flags = (env->psref << 4) | env->psrs;
1.1.1.2   root      235: #endif
                    236:     cs_base = env->npc;
                    237:     pc = env->pc;
                    238: #elif defined(TARGET_PPC)
1.1.1.6 ! root      239:     flags = env->hflags;
1.1.1.2   root      240:     cs_base = 0;
                    241:     pc = env->nip;
                    242: #elif defined(TARGET_MIPS)
1.1.1.3   root      243:     flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
1.1.1.2   root      244:     cs_base = 0;
1.1.1.6 ! root      245:     pc = env->PC[env->current_tc];
1.1.1.5   root      246: #elif defined(TARGET_M68K)
1.1.1.6 ! root      247:     flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
        !           248:             | (env->sr & SR_S)            /* Bit  13 */
        !           249:             | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
1.1.1.5   root      250:     cs_base = 0;
                    251:     pc = env->pc;
1.1.1.3   root      252: #elif defined(TARGET_SH4)
1.1.1.6 ! root      253:     flags = env->flags;
        !           254:     cs_base = 0;
        !           255:     pc = env->pc;
        !           256: #elif defined(TARGET_ALPHA)
        !           257:     flags = env->ps;
        !           258:     cs_base = 0;
        !           259:     pc = env->pc;
        !           260: #elif defined(TARGET_CRIS)
        !           261:     flags = 0;
        !           262:     cs_base = 0;
1.1.1.3   root      263:     pc = env->pc;
1.1.1.2   root      264: #else
                    265: #error unsupported CPU
                    266: #endif
                    267:     tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
                    268:     if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                    269:                          tb->flags != flags, 0)) {
                    270:         tb = tb_find_slow(pc, cs_base, flags);
                    271:         /* Note: we do it here to avoid a gcc bug on Mac OS X when
                    272:            doing it in tb_find_slow */
                    273:         if (tb_invalidated_flag) {
                    274:             /* as some TB could have been invalidated because
                    275:                of memory exceptions while generating the code, we
                    276:                must recompute the hash index here */
                    277:             T0 = 0;
                    278:         }
                    279:     }
                    280:     return tb;
                    281: }
                    282: 
1.1.1.6 ! root      283: #define BREAK_CHAIN T0 = 0
1.1.1.2   root      284: 
1.1       root      285: /* main execution loop */
                    286: 
                    287: int cpu_exec(CPUState *env1)
                    288: {
1.1.1.5   root      289: #define DECLARE_HOST_REGS 1
                    290: #include "hostregs_helper.h"
                    291: #if defined(TARGET_SPARC)
1.1       root      292: #if defined(reg_REGWPTR)
                    293:     uint32_t *saved_regwptr;
                    294: #endif
                    295: #endif
1.1.1.2   root      296:     int ret, interrupt_request;
1.1       root      297:     void (*gen_func)(void);
1.1.1.2   root      298:     TranslationBlock *tb;
1.1       root      299:     uint8_t *tc_ptr;
1.1.1.2   root      300: 
1.1.1.6 ! root      301:     if (cpu_halted(env1) == EXCP_HALTED)
        !           302:         return EXCP_HALTED;
1.1.1.2   root      303: 
1.1.1.6 ! root      304:     cpu_single_env = env1;
1.1       root      305: 
                    306:     /* first we save global registers */
1.1.1.5   root      307: #define SAVE_HOST_REGS 1
                    308: #include "hostregs_helper.h"
1.1       root      309:     env = env1;
1.1.1.6 ! root      310:     SAVE_GLOBALS();
1.1       root      311: 
                    312:     env_to_regs();
1.1.1.6 ! root      313: #if defined(TARGET_I386)
1.1       root      314:     /* put eflags in CPU temporary format */
                    315:     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    316:     DF = 1 - (2 * ((env->eflags >> 10) & 1));
                    317:     CC_OP = CC_OP_EFLAGS;
                    318:     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    319: #elif defined(TARGET_SPARC)
                    320: #if defined(reg_REGWPTR)
                    321:     saved_regwptr = REGWPTR;
                    322: #endif
1.1.1.5   root      323: #elif defined(TARGET_M68K)
                    324:     env->cc_op = CC_OP_FLAGS;
                    325:     env->cc_dest = env->sr & 0xf;
                    326:     env->cc_x = (env->sr >> 4) & 1;
1.1.1.6 ! root      327: #elif defined(TARGET_ALPHA)
        !           328: #elif defined(TARGET_ARM)
        !           329: #elif defined(TARGET_PPC)
1.1       root      330: #elif defined(TARGET_MIPS)
1.1.1.3   root      331: #elif defined(TARGET_SH4)
1.1.1.6 ! root      332: #elif defined(TARGET_CRIS)
1.1.1.3   root      333:     /* XXXXX */
1.1       root      334: #else
                    335: #error unsupported target CPU
                    336: #endif
                    337:     env->exception_index = -1;
                    338: 
                    339:     /* prepare setjmp context for exception handling */
                    340:     for(;;) {
                    341:         if (setjmp(env->jmp_env) == 0) {
                    342:             env->current_tb = NULL;
                    343:             /* if an exception is pending, we execute it here */
                    344:             if (env->exception_index >= 0) {
                    345:                 if (env->exception_index >= EXCP_INTERRUPT) {
                    346:                     /* exit request from the cpu execution loop */
                    347:                     ret = env->exception_index;
                    348:                     break;
                    349:                 } else if (env->user_mode_only) {
                    350:                     /* if user mode only, we simulate a fake exception
1.1.1.5   root      351:                        which will be handled outside the cpu execution
1.1       root      352:                        loop */
                    353: #if defined(TARGET_I386)
1.1.1.6 ! root      354:                     do_interrupt_user(env->exception_index,
        !           355:                                       env->exception_is_int,
        !           356:                                       env->error_code,
1.1       root      357:                                       env->exception_next_eip);
                    358: #endif
                    359:                     ret = env->exception_index;
                    360:                     break;
                    361:                 } else {
                    362: #if defined(TARGET_I386)
                    363:                     /* simulate a real cpu exception. On i386, it can
                    364:                        trigger new exceptions, but we do not handle
                    365:                        double or triple faults yet. */
1.1.1.6 ! root      366:                     do_interrupt(env->exception_index,
        !           367:                                  env->exception_is_int,
        !           368:                                  env->error_code,
1.1       root      369:                                  env->exception_next_eip, 0);
1.1.1.6 ! root      370:                     /* successfully delivered */
        !           371:                     env->old_exception = -1;
1.1       root      372: #elif defined(TARGET_PPC)
                    373:                     do_interrupt(env);
                    374: #elif defined(TARGET_MIPS)
                    375:                     do_interrupt(env);
                    376: #elif defined(TARGET_SPARC)
                    377:                     do_interrupt(env->exception_index);
1.1.1.2   root      378: #elif defined(TARGET_ARM)
                    379:                     do_interrupt(env);
1.1.1.3   root      380: #elif defined(TARGET_SH4)
                    381:                    do_interrupt(env);
1.1.1.6 ! root      382: #elif defined(TARGET_ALPHA)
        !           383:                     do_interrupt(env);
        !           384: #elif defined(TARGET_CRIS)
        !           385:                     do_interrupt(env);
        !           386: #elif defined(TARGET_M68K)
        !           387:                     do_interrupt(0);
1.1       root      388: #endif
                    389:                 }
                    390:                 env->exception_index = -1;
1.1.1.6 ! root      391:             }
1.1       root      392: #ifdef USE_KQEMU
                    393:             if (kqemu_is_ok(env) && env->interrupt_request == 0) {
                    394:                 int ret;
                    395:                 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                    396:                 ret = kqemu_cpu_exec(env);
                    397:                 /* put eflags in CPU temporary format */
                    398:                 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    399:                 DF = 1 - (2 * ((env->eflags >> 10) & 1));
                    400:                 CC_OP = CC_OP_EFLAGS;
                    401:                 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    402:                 if (ret == 1) {
                    403:                     /* exception */
                    404:                     longjmp(env->jmp_env, 1);
                    405:                 } else if (ret == 2) {
                    406:                     /* softmmu execution needed */
                    407:                 } else {
                    408:                     if (env->interrupt_request != 0) {
                    409:                         /* hardware interrupt will be executed just after */
                    410:                     } else {
                    411:                         /* otherwise, we restart */
                    412:                         longjmp(env->jmp_env, 1);
                    413:                     }
                    414:                 }
                    415:             }
                    416: #endif
                    417: 
                    418:             T0 = 0; /* force lookup of first TB */
                    419:             for(;;) {
1.1.1.6 ! root      420:                 SAVE_GLOBALS();
1.1       root      421:                 interrupt_request = env->interrupt_request;
1.1.1.6 ! root      422:                 if (__builtin_expect(interrupt_request, 0)
        !           423: #if defined(TARGET_I386)
        !           424:                        && env->hflags & HF_GIF_MASK
        !           425: #endif
        !           426:                                ) {
        !           427:                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
        !           428:                         env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
        !           429:                         env->exception_index = EXCP_DEBUG;
        !           430:                         cpu_loop_exit();
        !           431:                     }
        !           432: #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
        !           433:     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
        !           434:                     if (interrupt_request & CPU_INTERRUPT_HALT) {
        !           435:                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
        !           436:                         env->halted = 1;
        !           437:                         env->exception_index = EXCP_HLT;
        !           438:                         cpu_loop_exit();
        !           439:                     }
        !           440: #endif
1.1       root      441: #if defined(TARGET_I386)
1.1.1.5   root      442:                     if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                    443:                         !(env->hflags & HF_SMM_MASK)) {
1.1.1.6 ! root      444:                         svm_check_intercept(SVM_EXIT_SMI);
1.1.1.5   root      445:                         env->interrupt_request &= ~CPU_INTERRUPT_SMI;
                    446:                         do_smm_enter();
1.1.1.6 ! root      447:                         BREAK_CHAIN;
1.1.1.5   root      448:                     } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
1.1.1.6 ! root      449:                         (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
1.1       root      450:                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                    451:                         int intno;
1.1.1.6 ! root      452:                         svm_check_intercept(SVM_EXIT_INTR);
        !           453:                         env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
1.1       root      454:                         intno = cpu_get_pic_interrupt(env);
                    455:                         if (loglevel & CPU_LOG_TB_IN_ASM) {
                    456:                             fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
                    457:                         }
                    458:                         do_interrupt(intno, 0, 0, 0, 1);
                    459:                         /* ensure that no TB jump will be modified as
                    460:                            the program flow was changed */
1.1.1.6 ! root      461:                         BREAK_CHAIN;
        !           462: #if !defined(CONFIG_USER_ONLY)
        !           463:                     } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
        !           464:                         (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
        !           465:                          int intno;
        !           466:                          /* FIXME: this should respect TPR */
        !           467:                          env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
        !           468:                          svm_check_intercept(SVM_EXIT_VINTR);
        !           469:                          intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
        !           470:                          if (loglevel & CPU_LOG_TB_IN_ASM)
        !           471:                              fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
        !           472:                         do_interrupt(intno, 0, 0, -1, 1);
        !           473:                          stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
        !           474:                                   ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
        !           475:                         BREAK_CHAIN;
1.1       root      476: #endif
                    477:                     }
                    478: #elif defined(TARGET_PPC)
                    479: #if 0
                    480:                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
                    481:                         cpu_ppc_reset(env);
                    482:                     }
                    483: #endif
1.1.1.6 ! root      484:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
        !           485:                         ppc_hw_interrupt(env);
        !           486:                         if (env->pending_interrupts == 0)
1.1.1.2   root      487:                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1.1.1.6 ! root      488:                         BREAK_CHAIN;
1.1       root      489:                     }
                    490: #elif defined(TARGET_MIPS)
                    491:                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
1.1.1.6 ! root      492:                         (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
1.1       root      493:                         (env->CP0_Status & (1 << CP0St_IE)) &&
1.1.1.6 ! root      494:                         !(env->CP0_Status & (1 << CP0St_EXL)) &&
        !           495:                         !(env->CP0_Status & (1 << CP0St_ERL)) &&
1.1       root      496:                         !(env->hflags & MIPS_HFLAG_DM)) {
                    497:                         /* Raise it */
                    498:                         env->exception_index = EXCP_EXT_INTERRUPT;
                    499:                         env->error_code = 0;
                    500:                         do_interrupt(env);
1.1.1.6 ! root      501:                         BREAK_CHAIN;
1.1       root      502:                     }
                    503: #elif defined(TARGET_SPARC)
                    504:                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                    505:                        (env->psret != 0)) {
                    506:                        int pil = env->interrupt_index & 15;
                    507:                        int type = env->interrupt_index & 0xf0;
                    508: 
                    509:                        if (((type == TT_EXTINT) &&
                    510:                             (pil == 15 || pil > env->psrpil)) ||
                    511:                            type != TT_EXTINT) {
                    512:                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                    513:                            do_interrupt(env->interrupt_index);
                    514:                            env->interrupt_index = 0;
1.1.1.6 ! root      515: #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
        !           516:                             cpu_check_irqs(env);
1.1.1.2   root      517: #endif
1.1.1.6 ! root      518:                         BREAK_CHAIN;
1.1       root      519:                        }
                    520:                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
                    521:                        //do_interrupt(0, 0, 0, 0, 0);
                    522:                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
1.1.1.6 ! root      523:                    }
1.1.1.2   root      524: #elif defined(TARGET_ARM)
                    525:                     if (interrupt_request & CPU_INTERRUPT_FIQ
                    526:                         && !(env->uncached_cpsr & CPSR_F)) {
                    527:                         env->exception_index = EXCP_FIQ;
                    528:                         do_interrupt(env);
1.1.1.6 ! root      529:                         BREAK_CHAIN;
1.1.1.2   root      530:                     }
1.1.1.6 ! root      531:                     /* ARMv7-M interrupt return works by loading a magic value
        !           532:                        into the PC.  On real hardware the load causes the
        !           533:                        return to occur.  The qemu implementation performs the
        !           534:                        jump normally, then does the exception return when the
        !           535:                        CPU tries to execute code at the magic address.
        !           536:                        This will cause the magic PC value to be pushed to
        !           537:                        the stack if an interrupt occured at the wrong time.
        !           538:                        We avoid this by disabling interrupts when
        !           539:                        pc contains a magic address.  */
1.1.1.2   root      540:                     if (interrupt_request & CPU_INTERRUPT_HARD
1.1.1.6 ! root      541:                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
        !           542:                             || !(env->uncached_cpsr & CPSR_I))) {
1.1.1.2   root      543:                         env->exception_index = EXCP_IRQ;
                    544:                         do_interrupt(env);
1.1.1.6 ! root      545:                         BREAK_CHAIN;
1.1.1.2   root      546:                     }
1.1.1.3   root      547: #elif defined(TARGET_SH4)
1.1.1.6 ! root      548:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
        !           549:                         do_interrupt(env);
        !           550:                         BREAK_CHAIN;
        !           551:                     }
        !           552: #elif defined(TARGET_ALPHA)
        !           553:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
        !           554:                         do_interrupt(env);
        !           555:                         BREAK_CHAIN;
        !           556:                     }
        !           557: #elif defined(TARGET_CRIS)
        !           558:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
        !           559:                         do_interrupt(env);
        !           560:                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
        !           561:                         BREAK_CHAIN;
        !           562:                     }
        !           563: #elif defined(TARGET_M68K)
        !           564:                     if (interrupt_request & CPU_INTERRUPT_HARD
        !           565:                         && ((env->sr & SR_I) >> SR_I_SHIFT)
        !           566:                             < env->pending_level) {
        !           567:                         /* Real hardware gets the interrupt vector via an
        !           568:                            IACK cycle at this point.  Current emulated
        !           569:                            hardware doesn't rely on this, so we
        !           570:                            provide/save the vector when the interrupt is
        !           571:                            first signalled.  */
        !           572:                         env->exception_index = env->pending_vector;
        !           573:                         do_interrupt(1);
        !           574:                         BREAK_CHAIN;
        !           575:                     }
1.1       root      576: #endif
1.1.1.4   root      577:                    /* Don't use the cached interupt_request value,
                    578:                       do_interrupt may have updated the EXITTB flag. */
1.1.1.2   root      579:                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
1.1       root      580:                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                    581:                         /* ensure that no TB jump will be modified as
                    582:                            the program flow was changed */
1.1.1.6 ! root      583:                         BREAK_CHAIN;
1.1       root      584:                     }
                    585:                     if (interrupt_request & CPU_INTERRUPT_EXIT) {
                    586:                         env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
                    587:                         env->exception_index = EXCP_INTERRUPT;
                    588:                         cpu_loop_exit();
                    589:                     }
                    590:                 }
                    591: #ifdef DEBUG_EXEC
1.1.1.2   root      592:                 if ((loglevel & CPU_LOG_TB_CPU)) {
1.1       root      593:                     /* restore flags in standard format */
1.1.1.6 ! root      594:                     regs_to_env();
        !           595: #if defined(TARGET_I386)
1.1       root      596:                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                    597:                     cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                    598:                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    599: #elif defined(TARGET_ARM)
                    600:                     cpu_dump_state(env, logfile, fprintf, 0);
                    601: #elif defined(TARGET_SPARC)
                    602:                    REGWPTR = env->regbase + (env->cwp * 16);
                    603:                    env->regwptr = REGWPTR;
                    604:                     cpu_dump_state(env, logfile, fprintf, 0);
                    605: #elif defined(TARGET_PPC)
                    606:                     cpu_dump_state(env, logfile, fprintf, 0);
1.1.1.5   root      607: #elif defined(TARGET_M68K)
                    608:                     cpu_m68k_flush_flags(env, env->cc_op);
                    609:                     env->cc_op = CC_OP_FLAGS;
                    610:                     env->sr = (env->sr & 0xffe0)
                    611:                               | env->cc_dest | (env->cc_x << 4);
                    612:                     cpu_dump_state(env, logfile, fprintf, 0);
1.1       root      613: #elif defined(TARGET_MIPS)
                    614:                     cpu_dump_state(env, logfile, fprintf, 0);
1.1.1.3   root      615: #elif defined(TARGET_SH4)
                    616:                    cpu_dump_state(env, logfile, fprintf, 0);
1.1.1.6 ! root      617: #elif defined(TARGET_ALPHA)
        !           618:                     cpu_dump_state(env, logfile, fprintf, 0);
        !           619: #elif defined(TARGET_CRIS)
        !           620:                     cpu_dump_state(env, logfile, fprintf, 0);
1.1       root      621: #else
1.1.1.6 ! root      622: #error unsupported target CPU
1.1       root      623: #endif
                    624:                 }
                    625: #endif
1.1.1.2   root      626:                 tb = tb_find_fast();
1.1       root      627: #ifdef DEBUG_EXEC
                    628:                 if ((loglevel & CPU_LOG_EXEC)) {
                    629:                     fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
                    630:                             (long)tb->tc_ptr, tb->pc,
                    631:                             lookup_symbol(tb->pc));
                    632:                 }
                    633: #endif
1.1.1.6 ! root      634:                 RESTORE_GLOBALS();
1.1.1.2   root      635:                 /* see if we can patch the calling TB. When the TB
                    636:                    spans two pages, we cannot safely do a direct
                    637:                    jump. */
1.1       root      638:                 {
1.1.1.2   root      639:                     if (T0 != 0 &&
1.1.1.3   root      640: #if USE_KQEMU
                    641:                         (env->kqemu_enabled != 2) &&
                    642: #endif
1.1.1.6 ! root      643:                         tb->page_addr[1] == -1) {
1.1       root      644:                     spin_lock(&tb_lock);
                    645:                     tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
                    646:                     spin_unlock(&tb_lock);
                    647:                 }
                    648:                 }
                    649:                 tc_ptr = tb->tc_ptr;
                    650:                 env->current_tb = tb;
                    651:                 /* execute the generated code */
                    652:                 gen_func = (void *)tc_ptr;
                    653: #if defined(__sparc__)
                    654:                 __asm__ __volatile__("call     %0\n\t"
                    655:                                      "mov      %%o7,%%i0"
                    656:                                      : /* no outputs */
1.1.1.6 ! root      657:                                      : "r" (gen_func)
1.1.1.4   root      658:                                      : "i0", "i1", "i2", "i3", "i4", "i5",
1.1.1.6 ! root      659:                                        "o0", "o1", "o2", "o3", "o4", "o5",
1.1.1.4   root      660:                                        "l0", "l1", "l2", "l3", "l4", "l5",
                    661:                                        "l6", "l7");
1.1       root      662: #elif defined(__arm__)
                    663:                 asm volatile ("mov pc, %0\n\t"
                    664:                               ".global exec_loop\n\t"
                    665:                               "exec_loop:\n\t"
                    666:                               : /* no outputs */
                    667:                               : "r" (gen_func)
                    668:                               : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
                    669: #elif defined(__ia64)
                    670:                struct fptr {
                    671:                        void *ip;
                    672:                        void *gp;
                    673:                } fp;
                    674: 
                    675:                fp.ip = tc_ptr;
                    676:                fp.gp = code_gen_buffer + 2 * (1 << 20);
                    677:                (*(void (*)(void)) &fp)();
                    678: #else
                    679:                 gen_func();
                    680: #endif
                    681:                 env->current_tb = NULL;
                    682:                 /* reset soft MMU for next block (it can currently
                    683:                    only be set by a memory fault) */
                    684: #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
                    685:                 if (env->hflags & HF_SOFTMMU_MASK) {
                    686:                     env->hflags &= ~HF_SOFTMMU_MASK;
                    687:                     /* do not allow linking to another block */
                    688:                     T0 = 0;
                    689:                 }
                    690: #endif
1.1.1.3   root      691: #if defined(USE_KQEMU)
                    692: #define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
                    693:                 if (kqemu_is_ok(env) &&
                    694:                     (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
                    695:                     cpu_loop_exit();
                    696:                 }
                    697: #endif
1.1.1.6 ! root      698:             } /* for(;;) */
1.1       root      699:         } else {
                    700:             env_to_regs();
                    701:         }
                    702:     } /* for(;;) */
                    703: 
                    704: 
                    705: #if defined(TARGET_I386)
                    706:     /* restore flags in standard format */
                    707:     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                    708: #elif defined(TARGET_ARM)
                    709:     /* XXX: Save/restore host fpu exception state?.  */
                    710: #elif defined(TARGET_SPARC)
                    711: #if defined(reg_REGWPTR)
                    712:     REGWPTR = saved_regwptr;
                    713: #endif
                    714: #elif defined(TARGET_PPC)
1.1.1.5   root      715: #elif defined(TARGET_M68K)
                    716:     cpu_m68k_flush_flags(env, env->cc_op);
                    717:     env->cc_op = CC_OP_FLAGS;
                    718:     env->sr = (env->sr & 0xffe0)
                    719:               | env->cc_dest | (env->cc_x << 4);
1.1       root      720: #elif defined(TARGET_MIPS)
1.1.1.3   root      721: #elif defined(TARGET_SH4)
1.1.1.6 ! root      722: #elif defined(TARGET_ALPHA)
        !           723: #elif defined(TARGET_CRIS)
1.1.1.3   root      724:     /* XXXXX */
1.1       root      725: #else
                    726: #error unsupported target CPU
                    727: #endif
1.1.1.5   root      728: 
                    729:     /* restore global registers */
1.1.1.6 ! root      730:     RESTORE_GLOBALS();
1.1.1.5   root      731: #include "hostregs_helper.h"
                    732: 
1.1.1.2   root      733:     /* fail safe : never use cpu_single_env outside cpu_exec() */
1.1.1.6 ! root      734:     cpu_single_env = NULL;
1.1       root      735:     return ret;
                    736: }
                    737: 
                    738: /* must only be called from the generated code as an exception can be
                    739:    generated */
                    740: void tb_invalidate_page_range(target_ulong start, target_ulong end)
                    741: {
                    742:     /* XXX: cannot enable it yet because it yields to MMU exception
                    743:        where NIP != read address on PowerPC */
                    744: #if 0
                    745:     target_ulong phys_addr;
                    746:     phys_addr = get_phys_addr_code(env, start);
                    747:     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
                    748: #endif
                    749: }
                    750: 
                    751: #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
                    752: 
                    753: void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
                    754: {
                    755:     CPUX86State *saved_env;
                    756: 
                    757:     saved_env = env;
                    758:     env = s;
                    759:     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
                    760:         selector &= 0xffff;
1.1.1.6 ! root      761:         cpu_x86_load_seg_cache(env, seg_reg, selector,
1.1       root      762:                                (selector << 4), 0xffff, 0);
                    763:     } else {
                    764:         load_seg(seg_reg, selector);
                    765:     }
                    766:     env = saved_env;
                    767: }
                    768: 
1.1.1.6 ! root      769: void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
1.1       root      770: {
                    771:     CPUX86State *saved_env;
                    772: 
                    773:     saved_env = env;
                    774:     env = s;
1.1.1.6 ! root      775: 
        !           776:     helper_fsave(ptr, data32);
1.1       root      777: 
                    778:     env = saved_env;
                    779: }
                    780: 
1.1.1.6 ! root      781: void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
1.1       root      782: {
                    783:     CPUX86State *saved_env;
                    784: 
                    785:     saved_env = env;
                    786:     env = s;
1.1.1.6 ! root      787: 
        !           788:     helper_frstor(ptr, data32);
1.1       root      789: 
                    790:     env = saved_env;
                    791: }
                    792: 
                    793: #endif /* TARGET_I386 */
                    794: 
                    795: #if !defined(CONFIG_SOFTMMU)
                    796: 
                    797: #if defined(TARGET_I386)
                    798: 
                    799: /* 'pc' is the host PC at which the exception was raised. 'address' is
                    800:    the effective address of the memory exception. 'is_write' is 1 if a
                    801:    write caused the exception and otherwise 0'. 'old_set' is the
                    802:    signal set which should be restored */
                    803: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1.1.1.6 ! root      804:                                     int is_write, sigset_t *old_set,
1.1       root      805:                                     void *puc)
                    806: {
                    807:     TranslationBlock *tb;
                    808:     int ret;
                    809: 
                    810:     if (cpu_single_env)
                    811:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    812: #if defined(DEBUG_SIGNAL)
1.1.1.6 ! root      813:     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1       root      814:                 pc, address, is_write, *(unsigned long *)old_set);
                    815: #endif
                    816:     /* XXX: locking issue */
1.1.1.3   root      817:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1.1       root      818:         return 1;
                    819:     }
                    820: 
                    821:     /* see if it is an MMU fault */
1.1.1.6 ! root      822:     ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1       root      823:     if (ret < 0)
                    824:         return 0; /* not an MMU fault */
                    825:     if (ret == 0)
                    826:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    827:     /* now we have a real cpu fault */
                    828:     tb = tb_find_pc(pc);
                    829:     if (tb) {
                    830:         /* the PC is inside the translated code. It means that we have
                    831:            a virtual CPU fault */
                    832:         cpu_restore_state(tb, env, pc, puc);
                    833:     }
                    834:     if (ret == 1) {
                    835: #if 0
1.1.1.6 ! root      836:         printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
1.1       root      837:                env->eip, env->cr[2], env->error_code);
                    838: #endif
                    839:         /* we restore the process signal mask as the sigreturn should
                    840:            do it (XXX: use sigsetjmp) */
                    841:         sigprocmask(SIG_SETMASK, old_set, NULL);
1.1.1.2   root      842:         raise_exception_err(env->exception_index, env->error_code);
1.1       root      843:     } else {
                    844:         /* activate soft MMU for this block */
                    845:         env->hflags |= HF_SOFTMMU_MASK;
                    846:         cpu_resume_from_signal(env, puc);
                    847:     }
                    848:     /* never comes here */
                    849:     return 1;
                    850: }
                    851: 
                    852: #elif defined(TARGET_ARM)
                    853: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    854:                                     int is_write, sigset_t *old_set,
                    855:                                     void *puc)
                    856: {
                    857:     TranslationBlock *tb;
                    858:     int ret;
                    859: 
                    860:     if (cpu_single_env)
                    861:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    862: #if defined(DEBUG_SIGNAL)
1.1.1.6 ! root      863:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1       root      864:            pc, address, is_write, *(unsigned long *)old_set);
                    865: #endif
                    866:     /* XXX: locking issue */
1.1.1.3   root      867:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1.1       root      868:         return 1;
                    869:     }
                    870:     /* see if it is an MMU fault */
1.1.1.6 ! root      871:     ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1       root      872:     if (ret < 0)
                    873:         return 0; /* not an MMU fault */
                    874:     if (ret == 0)
                    875:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    876:     /* now we have a real cpu fault */
                    877:     tb = tb_find_pc(pc);
                    878:     if (tb) {
                    879:         /* the PC is inside the translated code. It means that we have
                    880:            a virtual CPU fault */
                    881:         cpu_restore_state(tb, env, pc, puc);
                    882:     }
                    883:     /* we restore the process signal mask as the sigreturn should
                    884:        do it (XXX: use sigsetjmp) */
                    885:     sigprocmask(SIG_SETMASK, old_set, NULL);
                    886:     cpu_loop_exit();
                    887: }
                    888: #elif defined(TARGET_SPARC)
                    889: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    890:                                     int is_write, sigset_t *old_set,
                    891:                                     void *puc)
                    892: {
                    893:     TranslationBlock *tb;
                    894:     int ret;
                    895: 
                    896:     if (cpu_single_env)
                    897:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    898: #if defined(DEBUG_SIGNAL)
1.1.1.6 ! root      899:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1       root      900:            pc, address, is_write, *(unsigned long *)old_set);
                    901: #endif
                    902:     /* XXX: locking issue */
1.1.1.3   root      903:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1.1       root      904:         return 1;
                    905:     }
                    906:     /* see if it is an MMU fault */
1.1.1.6 ! root      907:     ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1       root      908:     if (ret < 0)
                    909:         return 0; /* not an MMU fault */
                    910:     if (ret == 0)
                    911:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    912:     /* now we have a real cpu fault */
                    913:     tb = tb_find_pc(pc);
                    914:     if (tb) {
                    915:         /* the PC is inside the translated code. It means that we have
                    916:            a virtual CPU fault */
                    917:         cpu_restore_state(tb, env, pc, puc);
                    918:     }
                    919:     /* we restore the process signal mask as the sigreturn should
                    920:        do it (XXX: use sigsetjmp) */
                    921:     sigprocmask(SIG_SETMASK, old_set, NULL);
                    922:     cpu_loop_exit();
                    923: }
                    924: #elif defined (TARGET_PPC)
                    925: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    926:                                     int is_write, sigset_t *old_set,
                    927:                                     void *puc)
                    928: {
                    929:     TranslationBlock *tb;
                    930:     int ret;
1.1.1.6 ! root      931: 
1.1       root      932:     if (cpu_single_env)
                    933:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    934: #if defined(DEBUG_SIGNAL)
1.1.1.6 ! root      935:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1       root      936:            pc, address, is_write, *(unsigned long *)old_set);
                    937: #endif
                    938:     /* XXX: locking issue */
1.1.1.3   root      939:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1.1       root      940:         return 1;
                    941:     }
                    942: 
                    943:     /* see if it is an MMU fault */
1.1.1.6 ! root      944:     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1       root      945:     if (ret < 0)
                    946:         return 0; /* not an MMU fault */
                    947:     if (ret == 0)
                    948:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    949: 
                    950:     /* now we have a real cpu fault */
                    951:     tb = tb_find_pc(pc);
                    952:     if (tb) {
                    953:         /* the PC is inside the translated code. It means that we have
                    954:            a virtual CPU fault */
                    955:         cpu_restore_state(tb, env, pc, puc);
                    956:     }
                    957:     if (ret == 1) {
                    958: #if 0
1.1.1.6 ! root      959:         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1.1       root      960:                env->nip, env->error_code, tb);
                    961: #endif
                    962:     /* we restore the process signal mask as the sigreturn should
                    963:        do it (XXX: use sigsetjmp) */
                    964:         sigprocmask(SIG_SETMASK, old_set, NULL);
                    965:         do_raise_exception_err(env->exception_index, env->error_code);
                    966:     } else {
                    967:         /* activate soft MMU for this block */
                    968:         cpu_resume_from_signal(env, puc);
                    969:     }
                    970:     /* never comes here */
                    971:     return 1;
                    972: }
                    973: 
1.1.1.5   root      974: #elif defined(TARGET_M68K)
                    975: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    976:                                     int is_write, sigset_t *old_set,
                    977:                                     void *puc)
                    978: {
                    979:     TranslationBlock *tb;
                    980:     int ret;
                    981: 
                    982:     if (cpu_single_env)
                    983:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    984: #if defined(DEBUG_SIGNAL)
1.1.1.6 ! root      985:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1.1.5   root      986:            pc, address, is_write, *(unsigned long *)old_set);
                    987: #endif
                    988:     /* XXX: locking issue */
                    989:     if (is_write && page_unprotect(address, pc, puc)) {
                    990:         return 1;
                    991:     }
                    992:     /* see if it is an MMU fault */
1.1.1.6 ! root      993:     ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1.1.5   root      994:     if (ret < 0)
                    995:         return 0; /* not an MMU fault */
                    996:     if (ret == 0)
                    997:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    998:     /* now we have a real cpu fault */
                    999:     tb = tb_find_pc(pc);
                   1000:     if (tb) {
                   1001:         /* the PC is inside the translated code. It means that we have
                   1002:            a virtual CPU fault */
                   1003:         cpu_restore_state(tb, env, pc, puc);
                   1004:     }
                   1005:     /* we restore the process signal mask as the sigreturn should
                   1006:        do it (XXX: use sigsetjmp) */
                   1007:     sigprocmask(SIG_SETMASK, old_set, NULL);
                   1008:     cpu_loop_exit();
                   1009:     /* never comes here */
                   1010:     return 1;
                   1011: }
                   1012: 
1.1       root     1013: #elif defined (TARGET_MIPS)
                   1014: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                   1015:                                     int is_write, sigset_t *old_set,
                   1016:                                     void *puc)
                   1017: {
                   1018:     TranslationBlock *tb;
                   1019:     int ret;
1.1.1.6 ! root     1020: 
1.1       root     1021:     if (cpu_single_env)
                   1022:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                   1023: #if defined(DEBUG_SIGNAL)
1.1.1.6 ! root     1024:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1       root     1025:            pc, address, is_write, *(unsigned long *)old_set);
                   1026: #endif
                   1027:     /* XXX: locking issue */
1.1.1.3   root     1028:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1.1       root     1029:         return 1;
                   1030:     }
                   1031: 
                   1032:     /* see if it is an MMU fault */
1.1.1.6 ! root     1033:     ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1       root     1034:     if (ret < 0)
                   1035:         return 0; /* not an MMU fault */
                   1036:     if (ret == 0)
                   1037:         return 1; /* the MMU fault was handled without causing real CPU fault */
                   1038: 
                   1039:     /* now we have a real cpu fault */
                   1040:     tb = tb_find_pc(pc);
                   1041:     if (tb) {
                   1042:         /* the PC is inside the translated code. It means that we have
                   1043:            a virtual CPU fault */
                   1044:         cpu_restore_state(tb, env, pc, puc);
                   1045:     }
                   1046:     if (ret == 1) {
                   1047: #if 0
1.1.1.6 ! root     1048:         printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
        !          1049:                env->PC, env->error_code, tb);
1.1       root     1050: #endif
                   1051:     /* we restore the process signal mask as the sigreturn should
                   1052:        do it (XXX: use sigsetjmp) */
                   1053:         sigprocmask(SIG_SETMASK, old_set, NULL);
                   1054:         do_raise_exception_err(env->exception_index, env->error_code);
                   1055:     } else {
                   1056:         /* activate soft MMU for this block */
                   1057:         cpu_resume_from_signal(env, puc);
                   1058:     }
                   1059:     /* never comes here */
                   1060:     return 1;
                   1061: }
                   1062: 
1.1.1.3   root     1063: #elif defined (TARGET_SH4)
                   1064: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                   1065:                                     int is_write, sigset_t *old_set,
                   1066:                                     void *puc)
                   1067: {
                   1068:     TranslationBlock *tb;
                   1069:     int ret;
1.1.1.6 ! root     1070: 
1.1.1.3   root     1071:     if (cpu_single_env)
                   1072:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                   1073: #if defined(DEBUG_SIGNAL)
1.1.1.6 ! root     1074:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1.1.3   root     1075:            pc, address, is_write, *(unsigned long *)old_set);
                   1076: #endif
                   1077:     /* XXX: locking issue */
                   1078:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
                   1079:         return 1;
                   1080:     }
                   1081: 
                   1082:     /* see if it is an MMU fault */
1.1.1.6 ! root     1083:     ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1.1.3   root     1084:     if (ret < 0)
                   1085:         return 0; /* not an MMU fault */
                   1086:     if (ret == 0)
                   1087:         return 1; /* the MMU fault was handled without causing real CPU fault */
                   1088: 
                   1089:     /* now we have a real cpu fault */
                   1090:     tb = tb_find_pc(pc);
                   1091:     if (tb) {
                   1092:         /* the PC is inside the translated code. It means that we have
                   1093:            a virtual CPU fault */
                   1094:         cpu_restore_state(tb, env, pc, puc);
                   1095:     }
                   1096: #if 0
1.1.1.6 ! root     1097:         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1.1.1.3   root     1098:                env->nip, env->error_code, tb);
                   1099: #endif
                   1100:     /* we restore the process signal mask as the sigreturn should
                   1101:        do it (XXX: use sigsetjmp) */
1.1.1.4   root     1102:     sigprocmask(SIG_SETMASK, old_set, NULL);
                   1103:     cpu_loop_exit();
1.1.1.3   root     1104:     /* never comes here */
                   1105:     return 1;
                   1106: }
1.1       root     1107: 
1.1.1.6 ! root     1108: #elif defined (TARGET_ALPHA)
        !          1109: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
        !          1110:                                     int is_write, sigset_t *old_set,
        !          1111:                                     void *puc)
        !          1112: {
        !          1113:     TranslationBlock *tb;
        !          1114:     int ret;
1.1.1.5   root     1115: 
1.1.1.6 ! root     1116:     if (cpu_single_env)
        !          1117:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
        !          1118: #if defined(DEBUG_SIGNAL)
        !          1119:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
        !          1120:            pc, address, is_write, *(unsigned long *)old_set);
1.1.1.5   root     1121: #endif
1.1.1.6 ! root     1122:     /* XXX: locking issue */
        !          1123:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
        !          1124:         return 1;
        !          1125:     }
1.1.1.5   root     1126: 
1.1.1.6 ! root     1127:     /* see if it is an MMU fault */
        !          1128:     ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
        !          1129:     if (ret < 0)
        !          1130:         return 0; /* not an MMU fault */
        !          1131:     if (ret == 0)
        !          1132:         return 1; /* the MMU fault was handled without causing real CPU fault */
        !          1133: 
        !          1134:     /* now we have a real cpu fault */
        !          1135:     tb = tb_find_pc(pc);
        !          1136:     if (tb) {
        !          1137:         /* the PC is inside the translated code. It means that we have
        !          1138:            a virtual CPU fault */
        !          1139:         cpu_restore_state(tb, env, pc, puc);
        !          1140:     }
        !          1141: #if 0
        !          1142:         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
        !          1143:                env->nip, env->error_code, tb);
        !          1144: #endif
        !          1145:     /* we restore the process signal mask as the sigreturn should
        !          1146:        do it (XXX: use sigsetjmp) */
        !          1147:     sigprocmask(SIG_SETMASK, old_set, NULL);
        !          1148:     cpu_loop_exit();
        !          1149:     /* never comes here */
        !          1150:     return 1;
        !          1151: }
        !          1152: #elif defined (TARGET_CRIS)
        !          1153: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
        !          1154:                                     int is_write, sigset_t *old_set,
        !          1155:                                     void *puc)
1.1       root     1156: {
                   1157:     TranslationBlock *tb;
1.1.1.6 ! root     1158:     int ret;
1.1       root     1159: 
                   1160:     if (cpu_single_env)
                   1161:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
1.1.1.6 ! root     1162: #if defined(DEBUG_SIGNAL)
        !          1163:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
        !          1164:            pc, address, is_write, *(unsigned long *)old_set);
        !          1165: #endif
        !          1166:     /* XXX: locking issue */
        !          1167:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
        !          1168:         return 1;
        !          1169:     }
        !          1170: 
        !          1171:     /* see if it is an MMU fault */
        !          1172:     ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
        !          1173:     if (ret < 0)
        !          1174:         return 0; /* not an MMU fault */
        !          1175:     if (ret == 0)
        !          1176:         return 1; /* the MMU fault was handled without causing real CPU fault */
        !          1177: 
1.1       root     1178:     /* now we have a real cpu fault */
                   1179:     tb = tb_find_pc(pc);
                   1180:     if (tb) {
                   1181:         /* the PC is inside the translated code. It means that we have
                   1182:            a virtual CPU fault */
1.1.1.6 ! root     1183:         cpu_restore_state(tb, env, pc, puc);
1.1       root     1184:     }
1.1.1.6 ! root     1185: #if 0
        !          1186:         printf("PF exception: NIP=0x%08x error=0x%x %p\n",
        !          1187:                env->nip, env->error_code, tb);
        !          1188: #endif
        !          1189:     /* we restore the process signal mask as the sigreturn should
        !          1190:        do it (XXX: use sigsetjmp) */
        !          1191:     sigprocmask(SIG_SETMASK, old_set, NULL);
        !          1192:     cpu_loop_exit();
        !          1193:     /* never comes here */
        !          1194:     return 1;
1.1       root     1195: }
1.1.1.6 ! root     1196: 
        !          1197: #else
        !          1198: #error unsupported target CPU
1.1       root     1199: #endif
                   1200: 
1.1.1.6 ! root     1201: #if defined(__i386__)
        !          1202: 
        !          1203: #if defined(__APPLE__)
        !          1204: # include <sys/ucontext.h>
        !          1205: 
        !          1206: # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
        !          1207: # define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
        !          1208: # define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
        !          1209: #else
        !          1210: # define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
        !          1211: # define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
        !          1212: # define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
        !          1213: #endif
        !          1214: 
        !          1215: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1216:                        void *puc)
                   1217: {
1.1.1.5   root     1218:     siginfo_t *info = pinfo;
1.1       root     1219:     struct ucontext *uc = puc;
                   1220:     unsigned long pc;
                   1221:     int trapno;
                   1222: 
                   1223: #ifndef REG_EIP
                   1224: /* for glibc 2.1 */
                   1225: #define REG_EIP    EIP
                   1226: #define REG_ERR    ERR
                   1227: #define REG_TRAPNO TRAPNO
                   1228: #endif
1.1.1.5   root     1229:     pc = EIP_sig(uc);
                   1230:     trapno = TRAP_sig(uc);
1.1.1.6 ! root     1231:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
        !          1232:                              trapno == 0xe ?
        !          1233:                              (ERROR_sig(uc) >> 1) & 1 : 0,
        !          1234:                              &uc->uc_sigmask, puc);
1.1       root     1235: }
                   1236: 
                   1237: #elif defined(__x86_64__)
                   1238: 
1.1.1.5   root     1239: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1240:                        void *puc)
                   1241: {
1.1.1.5   root     1242:     siginfo_t *info = pinfo;
1.1       root     1243:     struct ucontext *uc = puc;
                   1244:     unsigned long pc;
                   1245: 
                   1246:     pc = uc->uc_mcontext.gregs[REG_RIP];
1.1.1.6 ! root     1247:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
        !          1248:                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1.1       root     1249:                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
                   1250:                              &uc->uc_sigmask, puc);
                   1251: }
                   1252: 
                   1253: #elif defined(__powerpc__)
                   1254: 
                   1255: /***********************************************************************
                   1256:  * signal context platform-specific definitions
                   1257:  * From Wine
                   1258:  */
                   1259: #ifdef linux
                   1260: /* All Registers access - only for local access */
                   1261: # define REG_sig(reg_name, context)            ((context)->uc_mcontext.regs->reg_name)
                   1262: /* Gpr Registers access  */
                   1263: # define GPR_sig(reg_num, context)             REG_sig(gpr[reg_num], context)
                   1264: # define IAR_sig(context)                      REG_sig(nip, context)   /* Program counter */
                   1265: # define MSR_sig(context)                      REG_sig(msr, context)   /* Machine State Register (Supervisor) */
                   1266: # define CTR_sig(context)                      REG_sig(ctr, context)   /* Count register */
                   1267: # define XER_sig(context)                      REG_sig(xer, context) /* User's integer exception register */
                   1268: # define LR_sig(context)                       REG_sig(link, context) /* Link register */
                   1269: # define CR_sig(context)                       REG_sig(ccr, context) /* Condition register */
                   1270: /* Float Registers access  */
                   1271: # define FLOAT_sig(reg_num, context)           (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
                   1272: # define FPSCR_sig(context)                    (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
                   1273: /* Exception Registers access */
                   1274: # define DAR_sig(context)                      REG_sig(dar, context)
                   1275: # define DSISR_sig(context)                    REG_sig(dsisr, context)
                   1276: # define TRAP_sig(context)                     REG_sig(trap, context)
                   1277: #endif /* linux */
                   1278: 
                   1279: #ifdef __APPLE__
                   1280: # include <sys/ucontext.h>
                   1281: typedef struct ucontext SIGCONTEXT;
                   1282: /* All Registers access - only for local access */
                   1283: # define REG_sig(reg_name, context)            ((context)->uc_mcontext->ss.reg_name)
                   1284: # define FLOATREG_sig(reg_name, context)       ((context)->uc_mcontext->fs.reg_name)
                   1285: # define EXCEPREG_sig(reg_name, context)       ((context)->uc_mcontext->es.reg_name)
                   1286: # define VECREG_sig(reg_name, context)         ((context)->uc_mcontext->vs.reg_name)
                   1287: /* Gpr Registers access */
                   1288: # define GPR_sig(reg_num, context)             REG_sig(r##reg_num, context)
                   1289: # define IAR_sig(context)                      REG_sig(srr0, context)  /* Program counter */
                   1290: # define MSR_sig(context)                      REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
                   1291: # define CTR_sig(context)                      REG_sig(ctr, context)
                   1292: # define XER_sig(context)                      REG_sig(xer, context) /* Link register */
                   1293: # define LR_sig(context)                       REG_sig(lr, context)  /* User's integer exception register */
                   1294: # define CR_sig(context)                       REG_sig(cr, context)  /* Condition register */
                   1295: /* Float Registers access */
                   1296: # define FLOAT_sig(reg_num, context)           FLOATREG_sig(fpregs[reg_num], context)
                   1297: # define FPSCR_sig(context)                    ((double)FLOATREG_sig(fpscr, context))
                   1298: /* Exception Registers access */
                   1299: # define DAR_sig(context)                      EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
                   1300: # define DSISR_sig(context)                    EXCEPREG_sig(dsisr, context)
                   1301: # define TRAP_sig(context)                     EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
                   1302: #endif /* __APPLE__ */
                   1303: 
1.1.1.6 ! root     1304: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1305:                        void *puc)
                   1306: {
1.1.1.5   root     1307:     siginfo_t *info = pinfo;
1.1       root     1308:     struct ucontext *uc = puc;
                   1309:     unsigned long pc;
                   1310:     int is_write;
                   1311: 
                   1312:     pc = IAR_sig(uc);
                   1313:     is_write = 0;
                   1314: #if 0
                   1315:     /* ppc 4xx case */
                   1316:     if (DSISR_sig(uc) & 0x00800000)
                   1317:         is_write = 1;
                   1318: #else
                   1319:     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
                   1320:         is_write = 1;
                   1321: #endif
1.1.1.6 ! root     1322:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1323:                              is_write, &uc->uc_sigmask, puc);
                   1324: }
                   1325: 
                   1326: #elif defined(__alpha__)
                   1327: 
1.1.1.6 ! root     1328: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1329:                            void *puc)
                   1330: {
1.1.1.5   root     1331:     siginfo_t *info = pinfo;
1.1       root     1332:     struct ucontext *uc = puc;
                   1333:     uint32_t *pc = uc->uc_mcontext.sc_pc;
                   1334:     uint32_t insn = *pc;
                   1335:     int is_write = 0;
                   1336: 
                   1337:     /* XXX: need kernel patch to get write flag faster */
                   1338:     switch (insn >> 26) {
                   1339:     case 0x0d: // stw
                   1340:     case 0x0e: // stb
                   1341:     case 0x0f: // stq_u
                   1342:     case 0x24: // stf
                   1343:     case 0x25: // stg
                   1344:     case 0x26: // sts
                   1345:     case 0x27: // stt
                   1346:     case 0x2c: // stl
                   1347:     case 0x2d: // stq
                   1348:     case 0x2e: // stl_c
                   1349:     case 0x2f: // stq_c
                   1350:        is_write = 1;
                   1351:     }
                   1352: 
1.1.1.6 ! root     1353:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1354:                              is_write, &uc->uc_sigmask, puc);
                   1355: }
                   1356: #elif defined(__sparc__)
                   1357: 
1.1.1.6 ! root     1358: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1359:                        void *puc)
                   1360: {
1.1.1.5   root     1361:     siginfo_t *info = pinfo;
1.1       root     1362:     uint32_t *regs = (uint32_t *)(info + 1);
                   1363:     void *sigmask = (regs + 20);
                   1364:     unsigned long pc;
                   1365:     int is_write;
                   1366:     uint32_t insn;
1.1.1.6 ! root     1367: 
1.1       root     1368:     /* XXX: is there a standard glibc define ? */
                   1369:     pc = regs[1];
                   1370:     /* XXX: need kernel patch to get write flag faster */
                   1371:     is_write = 0;
                   1372:     insn = *(uint32_t *)pc;
                   1373:     if ((insn >> 30) == 3) {
                   1374:       switch((insn >> 19) & 0x3f) {
                   1375:       case 0x05: // stb
                   1376:       case 0x06: // sth
                   1377:       case 0x04: // st
                   1378:       case 0x07: // std
                   1379:       case 0x24: // stf
                   1380:       case 0x27: // stdf
                   1381:       case 0x25: // stfsr
                   1382:        is_write = 1;
                   1383:        break;
                   1384:       }
                   1385:     }
1.1.1.6 ! root     1386:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1387:                              is_write, sigmask, NULL);
                   1388: }
                   1389: 
                   1390: #elif defined(__arm__)
                   1391: 
1.1.1.6 ! root     1392: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1393:                        void *puc)
                   1394: {
1.1.1.5   root     1395:     siginfo_t *info = pinfo;
1.1       root     1396:     struct ucontext *uc = puc;
                   1397:     unsigned long pc;
                   1398:     int is_write;
1.1.1.6 ! root     1399: 
1.1       root     1400:     pc = uc->uc_mcontext.gregs[R15];
                   1401:     /* XXX: compute is_write */
                   1402:     is_write = 0;
1.1.1.6 ! root     1403:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1404:                              is_write,
1.1.1.5   root     1405:                              &uc->uc_sigmask, puc);
1.1       root     1406: }
                   1407: 
                   1408: #elif defined(__mc68000)
                   1409: 
1.1.1.6 ! root     1410: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1411:                        void *puc)
                   1412: {
1.1.1.5   root     1413:     siginfo_t *info = pinfo;
1.1       root     1414:     struct ucontext *uc = puc;
                   1415:     unsigned long pc;
                   1416:     int is_write;
1.1.1.6 ! root     1417: 
1.1       root     1418:     pc = uc->uc_mcontext.gregs[16];
                   1419:     /* XXX: compute is_write */
                   1420:     is_write = 0;
1.1.1.6 ! root     1421:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1422:                              is_write,
                   1423:                              &uc->uc_sigmask, puc);
                   1424: }
                   1425: 
                   1426: #elif defined(__ia64)
                   1427: 
                   1428: #ifndef __ISR_VALID
                   1429:   /* This ought to be in <bits/siginfo.h>... */
                   1430: # define __ISR_VALID   1
                   1431: #endif
                   1432: 
1.1.1.5   root     1433: int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1.1       root     1434: {
1.1.1.5   root     1435:     siginfo_t *info = pinfo;
1.1       root     1436:     struct ucontext *uc = puc;
                   1437:     unsigned long ip;
                   1438:     int is_write = 0;
                   1439: 
                   1440:     ip = uc->uc_mcontext.sc_ip;
                   1441:     switch (host_signum) {
                   1442:       case SIGILL:
                   1443:       case SIGFPE:
                   1444:       case SIGSEGV:
                   1445:       case SIGBUS:
                   1446:       case SIGTRAP:
1.1.1.3   root     1447:          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1.1       root     1448:              /* ISR.W (write-access) is bit 33:  */
                   1449:              is_write = (info->si_isr >> 33) & 1;
                   1450:          break;
                   1451: 
                   1452:       default:
                   1453:          break;
                   1454:     }
                   1455:     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
                   1456:                              is_write,
                   1457:                              &uc->uc_sigmask, puc);
                   1458: }
                   1459: 
                   1460: #elif defined(__s390__)
                   1461: 
1.1.1.6 ! root     1462: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1463:                        void *puc)
                   1464: {
1.1.1.5   root     1465:     siginfo_t *info = pinfo;
1.1       root     1466:     struct ucontext *uc = puc;
                   1467:     unsigned long pc;
                   1468:     int is_write;
1.1.1.6 ! root     1469: 
1.1       root     1470:     pc = uc->uc_mcontext.psw.addr;
                   1471:     /* XXX: compute is_write */
                   1472:     is_write = 0;
1.1.1.6 ! root     1473:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
        !          1474:                              is_write, &uc->uc_sigmask, puc);
        !          1475: }
        !          1476: 
        !          1477: #elif defined(__mips__)
        !          1478: 
        !          1479: int cpu_signal_handler(int host_signum, void *pinfo,
        !          1480:                        void *puc)
        !          1481: {
        !          1482:     siginfo_t *info = pinfo;
        !          1483:     struct ucontext *uc = puc;
        !          1484:     greg_t pc = uc->uc_mcontext.pc;
        !          1485:     int is_write;
        !          1486: 
        !          1487:     /* XXX: compute is_write */
        !          1488:     is_write = 0;
        !          1489:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
        !          1490:                              is_write, &uc->uc_sigmask, puc);
1.1       root     1491: }
                   1492: 
                   1493: #else
                   1494: 
                   1495: #error host CPU specific signal handler needed
                   1496: 
                   1497: #endif
                   1498: 
                   1499: #endif /* !defined(CONFIG_SOFTMMU) */

unix.superglobalmegacorp.com