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

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
1.1.1.9   root       17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       18:  */
                     19: #include "config.h"
                     20: #include "exec.h"
                     21: #include "disas.h"
1.1.1.7   root       22: #include "tcg.h"
                     23: #include "kvm.h"
1.1.1.12! root       24: #include "qemu-barrier.h"
1.1       root       25: 
                     26: #if !defined(CONFIG_SOFTMMU)
                     27: #undef EAX
                     28: #undef ECX
                     29: #undef EDX
                     30: #undef EBX
                     31: #undef ESP
                     32: #undef EBP
                     33: #undef ESI
                     34: #undef EDI
                     35: #undef EIP
                     36: #include <signal.h>
1.1.1.7   root       37: #ifdef __linux__
1.1       root       38: #include <sys/ucontext.h>
                     39: #endif
1.1.1.7   root       40: #endif
1.1.1.6   root       41: 
1.1.1.10  root       42: #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
1.1.1.6   root       43: // Work around ugly bugs in glibc that mangle global register contents
1.1.1.7   root       44: #undef env
                     45: #define env cpu_single_env
                     46: #endif
1.1.1.6   root       47: 
1.1.1.7   root       48: int tb_invalidated_flag;
1.1.1.6   root       49: 
1.1.1.10  root       50: //#define CONFIG_DEBUG_EXEC
1.1.1.7   root       51: //#define DEBUG_SIGNAL
1.1.1.6   root       52: 
1.1.1.9   root       53: int qemu_cpu_has_work(CPUState *env)
                     54: {
                     55:     return cpu_has_work(env);
                     56: }
                     57: 
1.1       root       58: void cpu_loop_exit(void)
                     59: {
1.1.1.12! root       60:     env->current_tb = NULL;
1.1       root       61:     longjmp(env->jmp_env, 1);
                     62: }
1.1.1.6   root       63: 
1.1       root       64: /* exit the current TB from a signal handler. The host registers are
                     65:    restored in a state compatible with the CPU emulator
                     66:  */
1.1.1.6   root       67: void cpu_resume_from_signal(CPUState *env1, void *puc)
1.1       root       68: {
                     69: #if !defined(CONFIG_SOFTMMU)
1.1.1.7   root       70: #ifdef __linux__
1.1       root       71:     struct ucontext *uc = puc;
1.1.1.7   root       72: #elif defined(__OpenBSD__)
                     73:     struct sigcontext *uc = puc;
                     74: #endif
1.1       root       75: #endif
                     76: 
                     77:     env = env1;
                     78: 
                     79:     /* XXX: restore cpu registers saved in host registers */
                     80: 
                     81: #if !defined(CONFIG_SOFTMMU)
                     82:     if (puc) {
                     83:         /* XXX: use siglongjmp ? */
1.1.1.7   root       84: #ifdef __linux__
1.1.1.12! root       85: #ifdef __ia64
        !            86:         sigprocmask(SIG_SETMASK, (sigset_t *)&uc->uc_sigmask, NULL);
        !            87: #else
1.1       root       88:         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
1.1.1.12! root       89: #endif
1.1.1.7   root       90: #elif defined(__OpenBSD__)
                     91:         sigprocmask(SIG_SETMASK, &uc->sc_mask, NULL);
                     92: #endif
1.1       root       93:     }
                     94: #endif
1.1.1.7   root       95:     env->exception_index = -1;
1.1       root       96:     longjmp(env->jmp_env, 1);
                     97: }
                     98: 
1.1.1.7   root       99: /* Execute the code without caching the generated code. An interpreter
                    100:    could be used if available. */
                    101: static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
                    102: {
                    103:     unsigned long next_tb;
                    104:     TranslationBlock *tb;
                    105: 
                    106:     /* Should never happen.
                    107:        We only end up here when an existing TB is too long.  */
                    108:     if (max_cycles > CF_COUNT_MASK)
                    109:         max_cycles = CF_COUNT_MASK;
                    110: 
                    111:     tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
                    112:                      max_cycles);
                    113:     env->current_tb = tb;
                    114:     /* execute the generated code */
                    115:     next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
1.1.1.12! root      116:     env->current_tb = NULL;
1.1.1.7   root      117: 
                    118:     if ((next_tb & 3) == 2) {
                    119:         /* Restore PC.  This may happen if async event occurs before
                    120:            the TB starts executing.  */
                    121:         cpu_pc_from_tb(env, tb);
                    122:     }
                    123:     tb_phys_invalidate(tb, -1);
                    124:     tb_free(tb);
                    125: }
1.1.1.2   root      126: 
                    127: static TranslationBlock *tb_find_slow(target_ulong pc,
                    128:                                       target_ulong cs_base,
1.1.1.6   root      129:                                       uint64_t flags)
1.1.1.2   root      130: {
                    131:     TranslationBlock *tb, **ptb1;
                    132:     unsigned int h;
1.1.1.12! root      133:     tb_page_addr_t phys_pc, phys_page1, phys_page2;
        !           134:     target_ulong virt_page2;
1.1.1.2   root      135: 
                    136:     tb_invalidated_flag = 0;
1.1.1.6   root      137: 
1.1.1.2   root      138:     /* find translated block using physical mappings */
1.1.1.12! root      139:     phys_pc = get_page_addr_code(env, pc);
1.1.1.2   root      140:     phys_page1 = phys_pc & TARGET_PAGE_MASK;
                    141:     phys_page2 = -1;
                    142:     h = tb_phys_hash_func(phys_pc);
                    143:     ptb1 = &tb_phys_hash[h];
                    144:     for(;;) {
                    145:         tb = *ptb1;
                    146:         if (!tb)
                    147:             goto not_found;
1.1.1.6   root      148:         if (tb->pc == pc &&
1.1.1.2   root      149:             tb->page_addr[0] == phys_page1 &&
1.1.1.6   root      150:             tb->cs_base == cs_base &&
1.1.1.2   root      151:             tb->flags == flags) {
                    152:             /* check next page if needed */
                    153:             if (tb->page_addr[1] != -1) {
1.1.1.6   root      154:                 virt_page2 = (pc & TARGET_PAGE_MASK) +
1.1.1.2   root      155:                     TARGET_PAGE_SIZE;
1.1.1.12! root      156:                 phys_page2 = get_page_addr_code(env, virt_page2);
1.1.1.2   root      157:                 if (tb->page_addr[1] == phys_page2)
                    158:                     goto found;
                    159:             } else {
                    160:                 goto found;
                    161:             }
                    162:         }
                    163:         ptb1 = &tb->phys_hash_next;
                    164:     }
                    165:  not_found:
1.1.1.7   root      166:    /* if no translated code available, then translate it now */
                    167:     tb = tb_gen_code(env, pc, cs_base, flags, 0);
1.1.1.6   root      168: 
1.1.1.2   root      169:  found:
                    170:     /* we add the TB in the virtual pc hash table */
                    171:     env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
                    172:     return tb;
                    173: }
                    174: 
                    175: static inline TranslationBlock *tb_find_fast(void)
                    176: {
                    177:     TranslationBlock *tb;
                    178:     target_ulong cs_base, pc;
1.1.1.7   root      179:     int flags;
1.1.1.2   root      180: 
                    181:     /* we record a subset of the CPU state. It will
                    182:        always be the same before a given translated block
                    183:        is executed. */
1.1.1.7   root      184:     cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
1.1.1.2   root      185:     tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
1.1.1.7   root      186:     if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                    187:                  tb->flags != flags)) {
1.1.1.2   root      188:         tb = tb_find_slow(pc, cs_base, flags);
                    189:     }
                    190:     return tb;
                    191: }
                    192: 
1.1.1.7   root      193: static CPUDebugExcpHandler *debug_excp_handler;
                    194: 
                    195: CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
                    196: {
                    197:     CPUDebugExcpHandler *old_handler = debug_excp_handler;
                    198: 
                    199:     debug_excp_handler = handler;
                    200:     return old_handler;
                    201: }
                    202: 
                    203: static void cpu_handle_debug_exception(CPUState *env)
                    204: {
                    205:     CPUWatchpoint *wp;
                    206: 
                    207:     if (!env->watchpoint_hit)
1.1.1.10  root      208:         QTAILQ_FOREACH(wp, &env->watchpoints, entry)
1.1.1.7   root      209:             wp->flags &= ~BP_WATCHPOINT_HIT;
                    210: 
                    211:     if (debug_excp_handler)
                    212:         debug_excp_handler(env);
                    213: }
1.1.1.2   root      214: 
1.1       root      215: /* main execution loop */
                    216: 
1.1.1.12! root      217: volatile sig_atomic_t exit_request;
        !           218: 
1.1       root      219: int cpu_exec(CPUState *env1)
                    220: {
1.1.1.12! root      221:     volatile host_reg_t saved_env_reg;
1.1.1.2   root      222:     int ret, interrupt_request;
                    223:     TranslationBlock *tb;
1.1       root      224:     uint8_t *tc_ptr;
1.1.1.7   root      225:     unsigned long next_tb;
1.1.1.2   root      226: 
1.1.1.6   root      227:     if (cpu_halted(env1) == EXCP_HALTED)
                    228:         return EXCP_HALTED;
1.1.1.2   root      229: 
1.1.1.6   root      230:     cpu_single_env = env1;
1.1       root      231: 
1.1.1.12! root      232:     /* the access to env below is actually saving the global register's
        !           233:        value, so that files not including target-xyz/exec.h are free to
        !           234:        use it.  */
        !           235:     QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
        !           236:     saved_env_reg = (host_reg_t) env;
        !           237:     barrier();
1.1       root      238:     env = env1;
                    239: 
1.1.1.12! root      240:     if (unlikely(exit_request)) {
        !           241:         env->exit_request = 1;
        !           242:     }
        !           243: 
1.1.1.6   root      244: #if defined(TARGET_I386)
1.1.1.11  root      245:     if (!kvm_enabled()) {
                    246:         /* put eflags in CPU temporary format */
                    247:         CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    248:         DF = 1 - (2 * ((env->eflags >> 10) & 1));
                    249:         CC_OP = CC_OP_EFLAGS;
                    250:         env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    251:     }
1.1       root      252: #elif defined(TARGET_SPARC)
1.1.1.5   root      253: #elif defined(TARGET_M68K)
                    254:     env->cc_op = CC_OP_FLAGS;
                    255:     env->cc_dest = env->sr & 0xf;
                    256:     env->cc_x = (env->sr >> 4) & 1;
1.1.1.6   root      257: #elif defined(TARGET_ALPHA)
                    258: #elif defined(TARGET_ARM)
                    259: #elif defined(TARGET_PPC)
1.1.1.9   root      260: #elif defined(TARGET_MICROBLAZE)
1.1       root      261: #elif defined(TARGET_MIPS)
1.1.1.3   root      262: #elif defined(TARGET_SH4)
1.1.1.6   root      263: #elif defined(TARGET_CRIS)
1.1.1.10  root      264: #elif defined(TARGET_S390X)
1.1.1.3   root      265:     /* XXXXX */
1.1       root      266: #else
                    267: #error unsupported target CPU
                    268: #endif
                    269:     env->exception_index = -1;
                    270: 
                    271:     /* prepare setjmp context for exception handling */
                    272:     for(;;) {
                    273:         if (setjmp(env->jmp_env) == 0) {
1.1.1.10  root      274: #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
1.1.1.9   root      275: #undef env
                    276:                     env = cpu_single_env;
                    277: #define env cpu_single_env
                    278: #endif
1.1       root      279:             /* if an exception is pending, we execute it here */
                    280:             if (env->exception_index >= 0) {
                    281:                 if (env->exception_index >= EXCP_INTERRUPT) {
                    282:                     /* exit request from the cpu execution loop */
                    283:                     ret = env->exception_index;
1.1.1.7   root      284:                     if (ret == EXCP_DEBUG)
                    285:                         cpu_handle_debug_exception(env);
1.1       root      286:                     break;
1.1.1.7   root      287:                 } else {
                    288: #if defined(CONFIG_USER_ONLY)
1.1       root      289:                     /* if user mode only, we simulate a fake exception
1.1.1.5   root      290:                        which will be handled outside the cpu execution
1.1       root      291:                        loop */
                    292: #if defined(TARGET_I386)
1.1.1.6   root      293:                     do_interrupt_user(env->exception_index,
                    294:                                       env->exception_is_int,
                    295:                                       env->error_code,
1.1       root      296:                                       env->exception_next_eip);
1.1.1.7   root      297:                     /* successfully delivered */
                    298:                     env->old_exception = -1;
1.1       root      299: #endif
                    300:                     ret = env->exception_index;
                    301:                     break;
1.1.1.7   root      302: #else
1.1       root      303: #if defined(TARGET_I386)
                    304:                     /* simulate a real cpu exception. On i386, it can
                    305:                        trigger new exceptions, but we do not handle
                    306:                        double or triple faults yet. */
1.1.1.6   root      307:                     do_interrupt(env->exception_index,
                    308:                                  env->exception_is_int,
                    309:                                  env->error_code,
1.1       root      310:                                  env->exception_next_eip, 0);
1.1.1.6   root      311:                     /* successfully delivered */
                    312:                     env->old_exception = -1;
1.1       root      313: #elif defined(TARGET_PPC)
                    314:                     do_interrupt(env);
1.1.1.9   root      315: #elif defined(TARGET_MICROBLAZE)
                    316:                     do_interrupt(env);
1.1       root      317: #elif defined(TARGET_MIPS)
                    318:                     do_interrupt(env);
                    319: #elif defined(TARGET_SPARC)
1.1.1.7   root      320:                     do_interrupt(env);
1.1.1.2   root      321: #elif defined(TARGET_ARM)
                    322:                     do_interrupt(env);
1.1.1.3   root      323: #elif defined(TARGET_SH4)
                    324:                    do_interrupt(env);
1.1.1.6   root      325: #elif defined(TARGET_ALPHA)
                    326:                     do_interrupt(env);
                    327: #elif defined(TARGET_CRIS)
                    328:                     do_interrupt(env);
                    329: #elif defined(TARGET_M68K)
                    330:                     do_interrupt(0);
1.1       root      331: #endif
1.1.1.12! root      332:                     env->exception_index = -1;
1.1.1.7   root      333: #endif
1.1       root      334:                 }
1.1.1.6   root      335:             }
1.1       root      336: 
1.1.1.7   root      337:             if (kvm_enabled()) {
                    338:                 kvm_cpu_exec(env);
                    339:                 longjmp(env->jmp_env, 1);
                    340:             }
                    341: 
                    342:             next_tb = 0; /* force lookup of first TB */
1.1       root      343:             for(;;) {
                    344:                 interrupt_request = env->interrupt_request;
1.1.1.7   root      345:                 if (unlikely(interrupt_request)) {
                    346:                     if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
                    347:                         /* Mask out external interrupts for this step. */
                    348:                         interrupt_request &= ~(CPU_INTERRUPT_HARD |
                    349:                                                CPU_INTERRUPT_FIQ |
                    350:                                                CPU_INTERRUPT_SMI |
                    351:                                                CPU_INTERRUPT_NMI);
                    352:                     }
1.1.1.6   root      353:                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
                    354:                         env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                    355:                         env->exception_index = EXCP_DEBUG;
                    356:                         cpu_loop_exit();
                    357:                     }
                    358: #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
1.1.1.9   root      359:     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
                    360:     defined(TARGET_MICROBLAZE)
1.1.1.6   root      361:                     if (interrupt_request & CPU_INTERRUPT_HALT) {
                    362:                         env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                    363:                         env->halted = 1;
                    364:                         env->exception_index = EXCP_HLT;
                    365:                         cpu_loop_exit();
                    366:                     }
                    367: #endif
1.1       root      368: #if defined(TARGET_I386)
1.1.1.9   root      369:                     if (interrupt_request & CPU_INTERRUPT_INIT) {
                    370:                             svm_check_intercept(SVM_EXIT_INIT);
                    371:                             do_cpu_init(env);
                    372:                             env->exception_index = EXCP_HALTED;
                    373:                             cpu_loop_exit();
                    374:                     } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
                    375:                             do_cpu_sipi(env);
                    376:                     } else if (env->hflags2 & HF2_GIF_MASK) {
1.1.1.7   root      377:                         if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                    378:                             !(env->hflags & HF_SMM_MASK)) {
                    379:                             svm_check_intercept(SVM_EXIT_SMI);
                    380:                             env->interrupt_request &= ~CPU_INTERRUPT_SMI;
                    381:                             do_smm_enter();
                    382:                             next_tb = 0;
                    383:                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                    384:                                    !(env->hflags2 & HF2_NMI_MASK)) {
                    385:                             env->interrupt_request &= ~CPU_INTERRUPT_NMI;
                    386:                             env->hflags2 |= HF2_NMI_MASK;
                    387:                             do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
                    388:                             next_tb = 0;
1.1.1.9   root      389:                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {
                    390:                             env->interrupt_request &= ~CPU_INTERRUPT_MCE;
                    391:                             do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
                    392:                             next_tb = 0;
1.1.1.7   root      393:                         } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                    394:                                    (((env->hflags2 & HF2_VINTR_MASK) && 
                    395:                                      (env->hflags2 & HF2_HIF_MASK)) ||
                    396:                                     (!(env->hflags2 & HF2_VINTR_MASK) && 
                    397:                                      (env->eflags & IF_MASK && 
                    398:                                       !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
                    399:                             int intno;
                    400:                             svm_check_intercept(SVM_EXIT_INTR);
                    401:                             env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
                    402:                             intno = cpu_get_pic_interrupt(env);
                    403:                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
1.1.1.10  root      404: #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
1.1.1.9   root      405: #undef env
                    406:                     env = cpu_single_env;
                    407: #define env cpu_single_env
                    408: #endif
1.1.1.7   root      409:                             do_interrupt(intno, 0, 0, 0, 1);
                    410:                             /* ensure that no TB jump will be modified as
                    411:                                the program flow was changed */
                    412:                             next_tb = 0;
1.1.1.6   root      413: #if !defined(CONFIG_USER_ONLY)
1.1.1.7   root      414:                         } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
                    415:                                    (env->eflags & IF_MASK) && 
                    416:                                    !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                    417:                             int intno;
                    418:                             /* FIXME: this should respect TPR */
                    419:                             svm_check_intercept(SVM_EXIT_VINTR);
                    420:                             intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
                    421:                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
                    422:                             do_interrupt(intno, 0, 0, 0, 1);
                    423:                             env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
                    424:                             next_tb = 0;
1.1       root      425: #endif
1.1.1.7   root      426:                         }
1.1       root      427:                     }
                    428: #elif defined(TARGET_PPC)
                    429: #if 0
                    430:                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
1.1.1.10  root      431:                         cpu_reset(env);
1.1       root      432:                     }
                    433: #endif
1.1.1.6   root      434:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                    435:                         ppc_hw_interrupt(env);
                    436:                         if (env->pending_interrupts == 0)
1.1.1.2   root      437:                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1.1.1.7   root      438:                         next_tb = 0;
1.1       root      439:                     }
1.1.1.9   root      440: #elif defined(TARGET_MICROBLAZE)
                    441:                     if ((interrupt_request & CPU_INTERRUPT_HARD)
                    442:                         && (env->sregs[SR_MSR] & MSR_IE)
                    443:                         && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
                    444:                         && !(env->iflags & (D_FLAG | IMM_FLAG))) {
                    445:                         env->exception_index = EXCP_IRQ;
                    446:                         do_interrupt(env);
                    447:                         next_tb = 0;
                    448:                     }
1.1       root      449: #elif defined(TARGET_MIPS)
                    450:                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
1.1.1.6   root      451:                         (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
1.1       root      452:                         (env->CP0_Status & (1 << CP0St_IE)) &&
1.1.1.6   root      453:                         !(env->CP0_Status & (1 << CP0St_EXL)) &&
                    454:                         !(env->CP0_Status & (1 << CP0St_ERL)) &&
1.1       root      455:                         !(env->hflags & MIPS_HFLAG_DM)) {
                    456:                         /* Raise it */
                    457:                         env->exception_index = EXCP_EXT_INTERRUPT;
                    458:                         env->error_code = 0;
                    459:                         do_interrupt(env);
1.1.1.7   root      460:                         next_tb = 0;
1.1       root      461:                     }
                    462: #elif defined(TARGET_SPARC)
1.1.1.12! root      463:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
        !           464:                         if (cpu_interrupts_enabled(env) &&
        !           465:                             env->interrupt_index > 0) {
        !           466:                             int pil = env->interrupt_index & 0xf;
        !           467:                             int type = env->interrupt_index & 0xf0;
        !           468: 
        !           469:                             if (((type == TT_EXTINT) &&
        !           470:                                   cpu_pil_allowed(env, pil)) ||
        !           471:                                   type != TT_EXTINT) {
        !           472:                                 env->exception_index = env->interrupt_index;
        !           473:                                 do_interrupt(env);
        !           474:                                 next_tb = 0;
        !           475:                             }
        !           476:                         }
1.1       root      477:                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
                    478:                        //do_interrupt(0, 0, 0, 0, 0);
                    479:                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
1.1.1.6   root      480:                    }
1.1.1.2   root      481: #elif defined(TARGET_ARM)
                    482:                     if (interrupt_request & CPU_INTERRUPT_FIQ
                    483:                         && !(env->uncached_cpsr & CPSR_F)) {
                    484:                         env->exception_index = EXCP_FIQ;
                    485:                         do_interrupt(env);
1.1.1.7   root      486:                         next_tb = 0;
1.1.1.2   root      487:                     }
1.1.1.6   root      488:                     /* ARMv7-M interrupt return works by loading a magic value
                    489:                        into the PC.  On real hardware the load causes the
                    490:                        return to occur.  The qemu implementation performs the
                    491:                        jump normally, then does the exception return when the
                    492:                        CPU tries to execute code at the magic address.
                    493:                        This will cause the magic PC value to be pushed to
                    494:                        the stack if an interrupt occured at the wrong time.
                    495:                        We avoid this by disabling interrupts when
                    496:                        pc contains a magic address.  */
1.1.1.2   root      497:                     if (interrupt_request & CPU_INTERRUPT_HARD
1.1.1.6   root      498:                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
                    499:                             || !(env->uncached_cpsr & CPSR_I))) {
1.1.1.2   root      500:                         env->exception_index = EXCP_IRQ;
                    501:                         do_interrupt(env);
1.1.1.7   root      502:                         next_tb = 0;
1.1.1.2   root      503:                     }
1.1.1.3   root      504: #elif defined(TARGET_SH4)
1.1.1.6   root      505:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                    506:                         do_interrupt(env);
1.1.1.7   root      507:                         next_tb = 0;
1.1.1.6   root      508:                     }
                    509: #elif defined(TARGET_ALPHA)
                    510:                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                    511:                         do_interrupt(env);
1.1.1.7   root      512:                         next_tb = 0;
1.1.1.6   root      513:                     }
                    514: #elif defined(TARGET_CRIS)
1.1.1.7   root      515:                     if (interrupt_request & CPU_INTERRUPT_HARD
1.1.1.12! root      516:                         && (env->pregs[PR_CCS] & I_FLAG)
        !           517:                         && !env->locked_irq) {
1.1.1.7   root      518:                         env->exception_index = EXCP_IRQ;
1.1.1.6   root      519:                         do_interrupt(env);
1.1.1.7   root      520:                         next_tb = 0;
                    521:                     }
                    522:                     if (interrupt_request & CPU_INTERRUPT_NMI
                    523:                         && (env->pregs[PR_CCS] & M_FLAG)) {
                    524:                         env->exception_index = EXCP_NMI;
                    525:                         do_interrupt(env);
                    526:                         next_tb = 0;
1.1.1.6   root      527:                     }
                    528: #elif defined(TARGET_M68K)
                    529:                     if (interrupt_request & CPU_INTERRUPT_HARD
                    530:                         && ((env->sr & SR_I) >> SR_I_SHIFT)
                    531:                             < env->pending_level) {
                    532:                         /* Real hardware gets the interrupt vector via an
                    533:                            IACK cycle at this point.  Current emulated
                    534:                            hardware doesn't rely on this, so we
                    535:                            provide/save the vector when the interrupt is
                    536:                            first signalled.  */
                    537:                         env->exception_index = env->pending_vector;
                    538:                         do_interrupt(1);
1.1.1.7   root      539:                         next_tb = 0;
1.1.1.6   root      540:                     }
1.1       root      541: #endif
1.1.1.4   root      542:                    /* Don't use the cached interupt_request value,
                    543:                       do_interrupt may have updated the EXITTB flag. */
1.1.1.2   root      544:                     if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
1.1       root      545:                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                    546:                         /* ensure that no TB jump will be modified as
                    547:                            the program flow was changed */
1.1.1.7   root      548:                         next_tb = 0;
1.1       root      549:                     }
1.1.1.8   root      550:                 }
                    551:                 if (unlikely(env->exit_request)) {
                    552:                     env->exit_request = 0;
                    553:                     env->exception_index = EXCP_INTERRUPT;
                    554:                     cpu_loop_exit();
1.1       root      555:                 }
1.1.1.12! root      556: #if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
1.1.1.7   root      557:                 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
1.1       root      558:                     /* restore flags in standard format */
1.1.1.6   root      559: #if defined(TARGET_I386)
1.1.1.7   root      560:                     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
                    561:                     log_cpu_state(env, X86_DUMP_CCOP);
1.1       root      562:                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1.1.1.5   root      563: #elif defined(TARGET_M68K)
                    564:                     cpu_m68k_flush_flags(env, env->cc_op);
                    565:                     env->cc_op = CC_OP_FLAGS;
                    566:                     env->sr = (env->sr & 0xffe0)
                    567:                               | env->cc_dest | (env->cc_x << 4);
1.1.1.7   root      568:                     log_cpu_state(env, 0);
1.1       root      569: #else
1.1.1.12! root      570:                     log_cpu_state(env, 0);
1.1       root      571: #endif
                    572:                 }
1.1.1.12! root      573: #endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
1.1.1.7   root      574:                 spin_lock(&tb_lock);
1.1.1.2   root      575:                 tb = tb_find_fast();
1.1.1.7   root      576:                 /* Note: we do it here to avoid a gcc bug on Mac OS X when
                    577:                    doing it in tb_find_slow */
                    578:                 if (tb_invalidated_flag) {
                    579:                     /* as some TB could have been invalidated because
                    580:                        of memory exceptions while generating the code, we
                    581:                        must recompute the hash index here */
                    582:                     next_tb = 0;
                    583:                     tb_invalidated_flag = 0;
1.1       root      584:                 }
1.1.1.10  root      585: #ifdef CONFIG_DEBUG_EXEC
1.1.1.7   root      586:                 qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
                    587:                              (long)tb->tc_ptr, tb->pc,
                    588:                              lookup_symbol(tb->pc));
1.1       root      589: #endif
1.1.1.2   root      590:                 /* see if we can patch the calling TB. When the TB
                    591:                    spans two pages, we cannot safely do a direct
                    592:                    jump. */
1.1.1.12! root      593:                 if (next_tb != 0 && tb->page_addr[1] == -1) {
1.1.1.7   root      594:                     tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
1.1       root      595:                 }
1.1.1.7   root      596:                 spin_unlock(&tb_lock);
                    597: 
                    598:                 /* cpu_interrupt might be called while translating the
                    599:                    TB, but before it is linked into a potentially
                    600:                    infinite loop and becomes env->current_tb. Avoid
                    601:                    starting execution if there is a pending interrupt. */
1.1.1.12! root      602:                 env->current_tb = tb;
        !           603:                 barrier();
        !           604:                 if (likely(!env->exit_request)) {
1.1.1.7   root      605:                     tc_ptr = tb->tc_ptr;
1.1       root      606:                 /* execute the generated code */
1.1.1.10  root      607: #if defined(__sparc__) && !defined(CONFIG_SOLARIS)
1.1.1.7   root      608: #undef env
                    609:                     env = cpu_single_env;
                    610: #define env cpu_single_env
                    611: #endif
                    612:                     next_tb = tcg_qemu_tb_exec(tc_ptr);
                    613:                     if ((next_tb & 3) == 2) {
                    614:                         /* Instruction counter expired.  */
                    615:                         int insns_left;
                    616:                         tb = (TranslationBlock *)(long)(next_tb & ~3);
                    617:                         /* Restore PC.  */
                    618:                         cpu_pc_from_tb(env, tb);
                    619:                         insns_left = env->icount_decr.u32;
                    620:                         if (env->icount_extra && insns_left >= 0) {
                    621:                             /* Refill decrementer and continue execution.  */
                    622:                             env->icount_extra += insns_left;
                    623:                             if (env->icount_extra > 0xffff) {
                    624:                                 insns_left = 0xffff;
                    625:                             } else {
                    626:                                 insns_left = env->icount_extra;
                    627:                             }
                    628:                             env->icount_extra -= insns_left;
                    629:                             env->icount_decr.u16.low = insns_left;
                    630:                         } else {
                    631:                             if (insns_left > 0) {
                    632:                                 /* Execute remaining instructions.  */
                    633:                                 cpu_exec_nocache(insns_left, tb);
                    634:                             }
                    635:                             env->exception_index = EXCP_INTERRUPT;
                    636:                             next_tb = 0;
                    637:                             cpu_loop_exit();
                    638:                         }
                    639:                     }
                    640:                 }
1.1.1.12! root      641:                 env->current_tb = NULL;
1.1       root      642:                 /* reset soft MMU for next block (it can currently
                    643:                    only be set by a memory fault) */
1.1.1.6   root      644:             } /* for(;;) */
1.1       root      645:         }
                    646:     } /* for(;;) */
                    647: 
                    648: 
                    649: #if defined(TARGET_I386)
                    650:     /* restore flags in standard format */
1.1.1.7   root      651:     env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
1.1       root      652: #elif defined(TARGET_ARM)
                    653:     /* XXX: Save/restore host fpu exception state?.  */
                    654: #elif defined(TARGET_SPARC)
                    655: #elif defined(TARGET_PPC)
1.1.1.5   root      656: #elif defined(TARGET_M68K)
                    657:     cpu_m68k_flush_flags(env, env->cc_op);
                    658:     env->cc_op = CC_OP_FLAGS;
                    659:     env->sr = (env->sr & 0xffe0)
                    660:               | env->cc_dest | (env->cc_x << 4);
1.1.1.9   root      661: #elif defined(TARGET_MICROBLAZE)
1.1       root      662: #elif defined(TARGET_MIPS)
1.1.1.3   root      663: #elif defined(TARGET_SH4)
1.1.1.6   root      664: #elif defined(TARGET_ALPHA)
                    665: #elif defined(TARGET_CRIS)
1.1.1.10  root      666: #elif defined(TARGET_S390X)
1.1.1.3   root      667:     /* XXXXX */
1.1       root      668: #else
                    669: #error unsupported target CPU
                    670: #endif
1.1.1.5   root      671: 
                    672:     /* restore global registers */
1.1.1.12! root      673:     barrier();
        !           674:     env = (void *) saved_env_reg;
1.1.1.5   root      675: 
1.1.1.2   root      676:     /* fail safe : never use cpu_single_env outside cpu_exec() */
1.1.1.6   root      677:     cpu_single_env = NULL;
1.1       root      678:     return ret;
                    679: }
                    680: 
                    681: /* must only be called from the generated code as an exception can be
                    682:    generated */
                    683: void tb_invalidate_page_range(target_ulong start, target_ulong end)
                    684: {
                    685:     /* XXX: cannot enable it yet because it yields to MMU exception
                    686:        where NIP != read address on PowerPC */
                    687: #if 0
                    688:     target_ulong phys_addr;
                    689:     phys_addr = get_phys_addr_code(env, start);
                    690:     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
                    691: #endif
                    692: }
                    693: 
                    694: #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
                    695: 
                    696: void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
                    697: {
                    698:     CPUX86State *saved_env;
                    699: 
                    700:     saved_env = env;
                    701:     env = s;
                    702:     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
                    703:         selector &= 0xffff;
1.1.1.6   root      704:         cpu_x86_load_seg_cache(env, seg_reg, selector,
1.1       root      705:                                (selector << 4), 0xffff, 0);
                    706:     } else {
1.1.1.7   root      707:         helper_load_seg(seg_reg, selector);
1.1       root      708:     }
                    709:     env = saved_env;
                    710: }
                    711: 
1.1.1.6   root      712: void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
1.1       root      713: {
                    714:     CPUX86State *saved_env;
                    715: 
                    716:     saved_env = env;
                    717:     env = s;
1.1.1.6   root      718: 
                    719:     helper_fsave(ptr, data32);
1.1       root      720: 
                    721:     env = saved_env;
                    722: }
                    723: 
1.1.1.6   root      724: void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
1.1       root      725: {
                    726:     CPUX86State *saved_env;
                    727: 
                    728:     saved_env = env;
                    729:     env = s;
1.1.1.6   root      730: 
                    731:     helper_frstor(ptr, data32);
1.1       root      732: 
                    733:     env = saved_env;
                    734: }
                    735: 
                    736: #endif /* TARGET_I386 */
                    737: 
                    738: #if !defined(CONFIG_SOFTMMU)
                    739: 
                    740: #if defined(TARGET_I386)
1.1.1.10  root      741: #define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
                    742: #else
                    743: #define EXCEPTION_ACTION cpu_loop_exit()
                    744: #endif
1.1       root      745: 
                    746: /* 'pc' is the host PC at which the exception was raised. 'address' is
                    747:    the effective address of the memory exception. 'is_write' is 1 if a
                    748:    write caused the exception and otherwise 0'. 'old_set' is the
                    749:    signal set which should be restored */
                    750: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1.1.1.6   root      751:                                     int is_write, sigset_t *old_set,
1.1       root      752:                                     void *puc)
                    753: {
                    754:     TranslationBlock *tb;
                    755:     int ret;
                    756: 
                    757:     if (cpu_single_env)
                    758:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    759: #if defined(DEBUG_SIGNAL)
1.1.1.6   root      760:     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1.1       root      761:                 pc, address, is_write, *(unsigned long *)old_set);
                    762: #endif
                    763:     /* XXX: locking issue */
1.1.1.3   root      764:     if (is_write && page_unprotect(h2g(address), pc, puc)) {
1.1       root      765:         return 1;
                    766:     }
                    767: 
                    768:     /* see if it is an MMU fault */
1.1.1.10  root      769:     ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1.1       root      770:     if (ret < 0)
                    771:         return 0; /* not an MMU fault */
                    772:     if (ret == 0)
                    773:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    774:     /* now we have a real cpu fault */
                    775:     tb = tb_find_pc(pc);
                    776:     if (tb) {
                    777:         /* the PC is inside the translated code. It means that we have
                    778:            a virtual CPU fault */
                    779:         cpu_restore_state(tb, env, pc, puc);
                    780:     }
                    781: 
                    782:     /* we restore the process signal mask as the sigreturn should
                    783:        do it (XXX: use sigsetjmp) */
                    784:     sigprocmask(SIG_SETMASK, old_set, NULL);
1.1.1.10  root      785:     EXCEPTION_ACTION;
1.1       root      786: 
                    787:     /* never comes here */
                    788:     return 1;
                    789: }
                    790: 
1.1.1.6   root      791: #if defined(__i386__)
                    792: 
                    793: #if defined(__APPLE__)
                    794: # include <sys/ucontext.h>
                    795: 
                    796: # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
                    797: # define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
                    798: # define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1.1.1.9   root      799: # define MASK_sig(context)    ((context)->uc_sigmask)
1.1.1.10  root      800: #elif defined (__NetBSD__)
                    801: # include <ucontext.h>
                    802: 
                    803: # define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
                    804: # define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
                    805: # define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
                    806: # define MASK_sig(context)    ((context)->uc_sigmask)
                    807: #elif defined (__FreeBSD__) || defined(__DragonFly__)
                    808: # include <ucontext.h>
                    809: 
                    810: # define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
                    811: # define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
                    812: # define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
                    813: # define MASK_sig(context)    ((context)->uc_sigmask)
1.1.1.9   root      814: #elif defined(__OpenBSD__)
                    815: # define EIP_sig(context)     ((context)->sc_eip)
                    816: # define TRAP_sig(context)    ((context)->sc_trapno)
                    817: # define ERROR_sig(context)   ((context)->sc_err)
                    818: # define MASK_sig(context)    ((context)->sc_mask)
1.1.1.6   root      819: #else
                    820: # define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
                    821: # define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
                    822: # define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1.1.1.9   root      823: # define MASK_sig(context)    ((context)->uc_sigmask)
1.1.1.6   root      824: #endif
                    825: 
                    826: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root      827:                        void *puc)
                    828: {
1.1.1.5   root      829:     siginfo_t *info = pinfo;
1.1.1.10  root      830: #if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
                    831:     ucontext_t *uc = puc;
                    832: #elif defined(__OpenBSD__)
1.1.1.9   root      833:     struct sigcontext *uc = puc;
                    834: #else
1.1       root      835:     struct ucontext *uc = puc;
1.1.1.9   root      836: #endif
1.1       root      837:     unsigned long pc;
                    838:     int trapno;
                    839: 
                    840: #ifndef REG_EIP
                    841: /* for glibc 2.1 */
                    842: #define REG_EIP    EIP
                    843: #define REG_ERR    ERR
                    844: #define REG_TRAPNO TRAPNO
                    845: #endif
1.1.1.5   root      846:     pc = EIP_sig(uc);
                    847:     trapno = TRAP_sig(uc);
1.1.1.6   root      848:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                    849:                              trapno == 0xe ?
                    850:                              (ERROR_sig(uc) >> 1) & 1 : 0,
1.1.1.9   root      851:                              &MASK_sig(uc), puc);
1.1       root      852: }
                    853: 
                    854: #elif defined(__x86_64__)
                    855: 
1.1.1.7   root      856: #ifdef __NetBSD__
1.1.1.9   root      857: #define PC_sig(context)       _UC_MACHINE_PC(context)
                    858: #define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
                    859: #define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
                    860: #define MASK_sig(context)     ((context)->uc_sigmask)
                    861: #elif defined(__OpenBSD__)
                    862: #define PC_sig(context)       ((context)->sc_rip)
                    863: #define TRAP_sig(context)     ((context)->sc_trapno)
                    864: #define ERROR_sig(context)    ((context)->sc_err)
                    865: #define MASK_sig(context)     ((context)->sc_mask)
1.1.1.10  root      866: #elif defined (__FreeBSD__) || defined(__DragonFly__)
                    867: #include <ucontext.h>
                    868: 
                    869: #define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
                    870: #define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
                    871: #define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
                    872: #define MASK_sig(context)     ((context)->uc_sigmask)
1.1.1.7   root      873: #else
1.1.1.9   root      874: #define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
                    875: #define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
                    876: #define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
                    877: #define MASK_sig(context)     ((context)->uc_sigmask)
1.1.1.7   root      878: #endif
                    879: 
1.1.1.5   root      880: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root      881:                        void *puc)
                    882: {
1.1.1.5   root      883:     siginfo_t *info = pinfo;
1.1       root      884:     unsigned long pc;
1.1.1.10  root      885: #if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
1.1.1.7   root      886:     ucontext_t *uc = puc;
1.1.1.9   root      887: #elif defined(__OpenBSD__)
                    888:     struct sigcontext *uc = puc;
1.1.1.7   root      889: #else
                    890:     struct ucontext *uc = puc;
                    891: #endif
1.1       root      892: 
1.1.1.9   root      893:     pc = PC_sig(uc);
1.1.1.6   root      894:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1.1.9   root      895:                              TRAP_sig(uc) == 0xe ?
                    896:                              (ERROR_sig(uc) >> 1) & 1 : 0,
                    897:                              &MASK_sig(uc), puc);
1.1       root      898: }
                    899: 
1.1.1.7   root      900: #elif defined(_ARCH_PPC)
1.1       root      901: 
                    902: /***********************************************************************
                    903:  * signal context platform-specific definitions
                    904:  * From Wine
                    905:  */
                    906: #ifdef linux
                    907: /* All Registers access - only for local access */
                    908: # define REG_sig(reg_name, context)            ((context)->uc_mcontext.regs->reg_name)
                    909: /* Gpr Registers access  */
                    910: # define GPR_sig(reg_num, context)             REG_sig(gpr[reg_num], context)
                    911: # define IAR_sig(context)                      REG_sig(nip, context)   /* Program counter */
                    912: # define MSR_sig(context)                      REG_sig(msr, context)   /* Machine State Register (Supervisor) */
                    913: # define CTR_sig(context)                      REG_sig(ctr, context)   /* Count register */
                    914: # define XER_sig(context)                      REG_sig(xer, context) /* User's integer exception register */
                    915: # define LR_sig(context)                       REG_sig(link, context) /* Link register */
                    916: # define CR_sig(context)                       REG_sig(ccr, context) /* Condition register */
                    917: /* Float Registers access  */
                    918: # define FLOAT_sig(reg_num, context)           (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
                    919: # define FPSCR_sig(context)                    (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
                    920: /* Exception Registers access */
                    921: # define DAR_sig(context)                      REG_sig(dar, context)
                    922: # define DSISR_sig(context)                    REG_sig(dsisr, context)
                    923: # define TRAP_sig(context)                     REG_sig(trap, context)
                    924: #endif /* linux */
                    925: 
1.1.1.12! root      926: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
        !           927: #include <ucontext.h>
        !           928: # define IAR_sig(context)              ((context)->uc_mcontext.mc_srr0)
        !           929: # define MSR_sig(context)              ((context)->uc_mcontext.mc_srr1)
        !           930: # define CTR_sig(context)              ((context)->uc_mcontext.mc_ctr)
        !           931: # define XER_sig(context)              ((context)->uc_mcontext.mc_xer)
        !           932: # define LR_sig(context)               ((context)->uc_mcontext.mc_lr)
        !           933: # define CR_sig(context)               ((context)->uc_mcontext.mc_cr)
        !           934: /* Exception Registers access */
        !           935: # define DAR_sig(context)              ((context)->uc_mcontext.mc_dar)
        !           936: # define DSISR_sig(context)            ((context)->uc_mcontext.mc_dsisr)
        !           937: # define TRAP_sig(context)             ((context)->uc_mcontext.mc_exc)
        !           938: #endif /* __FreeBSD__|| __FreeBSD_kernel__ */
        !           939: 
1.1       root      940: #ifdef __APPLE__
                    941: # include <sys/ucontext.h>
                    942: typedef struct ucontext SIGCONTEXT;
                    943: /* All Registers access - only for local access */
                    944: # define REG_sig(reg_name, context)            ((context)->uc_mcontext->ss.reg_name)
                    945: # define FLOATREG_sig(reg_name, context)       ((context)->uc_mcontext->fs.reg_name)
                    946: # define EXCEPREG_sig(reg_name, context)       ((context)->uc_mcontext->es.reg_name)
                    947: # define VECREG_sig(reg_name, context)         ((context)->uc_mcontext->vs.reg_name)
                    948: /* Gpr Registers access */
                    949: # define GPR_sig(reg_num, context)             REG_sig(r##reg_num, context)
                    950: # define IAR_sig(context)                      REG_sig(srr0, context)  /* Program counter */
                    951: # define MSR_sig(context)                      REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
                    952: # define CTR_sig(context)                      REG_sig(ctr, context)
                    953: # define XER_sig(context)                      REG_sig(xer, context) /* Link register */
                    954: # define LR_sig(context)                       REG_sig(lr, context)  /* User's integer exception register */
                    955: # define CR_sig(context)                       REG_sig(cr, context)  /* Condition register */
                    956: /* Float Registers access */
                    957: # define FLOAT_sig(reg_num, context)           FLOATREG_sig(fpregs[reg_num], context)
                    958: # define FPSCR_sig(context)                    ((double)FLOATREG_sig(fpscr, context))
                    959: /* Exception Registers access */
                    960: # define DAR_sig(context)                      EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
                    961: # define DSISR_sig(context)                    EXCEPREG_sig(dsisr, context)
                    962: # define TRAP_sig(context)                     EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
                    963: #endif /* __APPLE__ */
                    964: 
1.1.1.6   root      965: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root      966:                        void *puc)
                    967: {
1.1.1.5   root      968:     siginfo_t *info = pinfo;
1.1.1.12! root      969: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
        !           970:     ucontext_t *uc = puc;
        !           971: #else
1.1       root      972:     struct ucontext *uc = puc;
1.1.1.12! root      973: #endif
1.1       root      974:     unsigned long pc;
                    975:     int is_write;
                    976: 
                    977:     pc = IAR_sig(uc);
                    978:     is_write = 0;
                    979: #if 0
                    980:     /* ppc 4xx case */
                    981:     if (DSISR_sig(uc) & 0x00800000)
                    982:         is_write = 1;
                    983: #else
                    984:     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
                    985:         is_write = 1;
                    986: #endif
1.1.1.6   root      987:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root      988:                              is_write, &uc->uc_sigmask, puc);
                    989: }
                    990: 
                    991: #elif defined(__alpha__)
                    992: 
1.1.1.6   root      993: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root      994:                            void *puc)
                    995: {
1.1.1.5   root      996:     siginfo_t *info = pinfo;
1.1       root      997:     struct ucontext *uc = puc;
                    998:     uint32_t *pc = uc->uc_mcontext.sc_pc;
                    999:     uint32_t insn = *pc;
                   1000:     int is_write = 0;
                   1001: 
                   1002:     /* XXX: need kernel patch to get write flag faster */
                   1003:     switch (insn >> 26) {
                   1004:     case 0x0d: // stw
                   1005:     case 0x0e: // stb
                   1006:     case 0x0f: // stq_u
                   1007:     case 0x24: // stf
                   1008:     case 0x25: // stg
                   1009:     case 0x26: // sts
                   1010:     case 0x27: // stt
                   1011:     case 0x2c: // stl
                   1012:     case 0x2d: // stq
                   1013:     case 0x2e: // stl_c
                   1014:     case 0x2f: // stq_c
                   1015:        is_write = 1;
                   1016:     }
                   1017: 
1.1.1.6   root     1018:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1019:                              is_write, &uc->uc_sigmask, puc);
                   1020: }
                   1021: #elif defined(__sparc__)
                   1022: 
1.1.1.6   root     1023: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1024:                        void *puc)
                   1025: {
1.1.1.5   root     1026:     siginfo_t *info = pinfo;
1.1       root     1027:     int is_write;
                   1028:     uint32_t insn;
1.1.1.10  root     1029: #if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1.1.1.7   root     1030:     uint32_t *regs = (uint32_t *)(info + 1);
                   1031:     void *sigmask = (regs + 20);
1.1       root     1032:     /* XXX: is there a standard glibc define ? */
1.1.1.7   root     1033:     unsigned long pc = regs[1];
                   1034: #else
                   1035: #ifdef __linux__
                   1036:     struct sigcontext *sc = puc;
                   1037:     unsigned long pc = sc->sigc_regs.tpc;
                   1038:     void *sigmask = (void *)sc->sigc_mask;
                   1039: #elif defined(__OpenBSD__)
                   1040:     struct sigcontext *uc = puc;
                   1041:     unsigned long pc = uc->sc_pc;
                   1042:     void *sigmask = (void *)(long)uc->sc_mask;
                   1043: #endif
                   1044: #endif
                   1045: 
1.1       root     1046:     /* XXX: need kernel patch to get write flag faster */
                   1047:     is_write = 0;
                   1048:     insn = *(uint32_t *)pc;
                   1049:     if ((insn >> 30) == 3) {
                   1050:       switch((insn >> 19) & 0x3f) {
                   1051:       case 0x05: // stb
1.1.1.9   root     1052:       case 0x15: // stba
1.1       root     1053:       case 0x06: // sth
1.1.1.9   root     1054:       case 0x16: // stha
1.1       root     1055:       case 0x04: // st
1.1.1.9   root     1056:       case 0x14: // sta
1.1       root     1057:       case 0x07: // std
1.1.1.9   root     1058:       case 0x17: // stda
                   1059:       case 0x0e: // stx
                   1060:       case 0x1e: // stxa
1.1       root     1061:       case 0x24: // stf
1.1.1.9   root     1062:       case 0x34: // stfa
1.1       root     1063:       case 0x27: // stdf
1.1.1.9   root     1064:       case 0x37: // stdfa
                   1065:       case 0x26: // stqf
                   1066:       case 0x36: // stqfa
1.1       root     1067:       case 0x25: // stfsr
1.1.1.9   root     1068:       case 0x3c: // casa
                   1069:       case 0x3e: // casxa
1.1       root     1070:        is_write = 1;
                   1071:        break;
                   1072:       }
                   1073:     }
1.1.1.6   root     1074:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1075:                              is_write, sigmask, NULL);
                   1076: }
                   1077: 
                   1078: #elif defined(__arm__)
                   1079: 
1.1.1.6   root     1080: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1081:                        void *puc)
                   1082: {
1.1.1.5   root     1083:     siginfo_t *info = pinfo;
1.1       root     1084:     struct ucontext *uc = puc;
                   1085:     unsigned long pc;
                   1086:     int is_write;
1.1.1.6   root     1087: 
1.1.1.7   root     1088: #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1.1       root     1089:     pc = uc->uc_mcontext.gregs[R15];
1.1.1.7   root     1090: #else
                   1091:     pc = uc->uc_mcontext.arm_pc;
                   1092: #endif
1.1       root     1093:     /* XXX: compute is_write */
                   1094:     is_write = 0;
1.1.1.6   root     1095:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1096:                              is_write,
1.1.1.5   root     1097:                              &uc->uc_sigmask, puc);
1.1       root     1098: }
                   1099: 
                   1100: #elif defined(__mc68000)
                   1101: 
1.1.1.6   root     1102: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1103:                        void *puc)
                   1104: {
1.1.1.5   root     1105:     siginfo_t *info = pinfo;
1.1       root     1106:     struct ucontext *uc = puc;
                   1107:     unsigned long pc;
                   1108:     int is_write;
1.1.1.6   root     1109: 
1.1       root     1110:     pc = uc->uc_mcontext.gregs[16];
                   1111:     /* XXX: compute is_write */
                   1112:     is_write = 0;
1.1.1.6   root     1113:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1.1       root     1114:                              is_write,
                   1115:                              &uc->uc_sigmask, puc);
                   1116: }
                   1117: 
                   1118: #elif defined(__ia64)
                   1119: 
                   1120: #ifndef __ISR_VALID
                   1121:   /* This ought to be in <bits/siginfo.h>... */
                   1122: # define __ISR_VALID   1
                   1123: #endif
                   1124: 
1.1.1.5   root     1125: int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1.1       root     1126: {
1.1.1.5   root     1127:     siginfo_t *info = pinfo;
1.1       root     1128:     struct ucontext *uc = puc;
                   1129:     unsigned long ip;
                   1130:     int is_write = 0;
                   1131: 
                   1132:     ip = uc->uc_mcontext.sc_ip;
                   1133:     switch (host_signum) {
                   1134:       case SIGILL:
                   1135:       case SIGFPE:
                   1136:       case SIGSEGV:
                   1137:       case SIGBUS:
                   1138:       case SIGTRAP:
1.1.1.3   root     1139:          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1.1       root     1140:              /* ISR.W (write-access) is bit 33:  */
                   1141:              is_write = (info->si_isr >> 33) & 1;
                   1142:          break;
                   1143: 
                   1144:       default:
                   1145:          break;
                   1146:     }
                   1147:     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
                   1148:                              is_write,
1.1.1.12! root     1149:                              (sigset_t *)&uc->uc_sigmask, puc);
1.1       root     1150: }
                   1151: 
                   1152: #elif defined(__s390__)
                   1153: 
1.1.1.6   root     1154: int cpu_signal_handler(int host_signum, void *pinfo,
1.1       root     1155:                        void *puc)
                   1156: {
1.1.1.5   root     1157:     siginfo_t *info = pinfo;
1.1       root     1158:     struct ucontext *uc = puc;
                   1159:     unsigned long pc;
1.1.1.12! root     1160:     uint16_t *pinsn;
        !          1161:     int is_write = 0;
1.1.1.6   root     1162: 
1.1       root     1163:     pc = uc->uc_mcontext.psw.addr;
1.1.1.12! root     1164: 
        !          1165:     /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
        !          1166:        of the normal 2 arguments.  The 3rd argument contains the "int_code"
        !          1167:        from the hardware which does in fact contain the is_write value.
        !          1168:        The rt signal handler, as far as I can tell, does not give this value
        !          1169:        at all.  Not that we could get to it from here even if it were.  */
        !          1170:     /* ??? This is not even close to complete, since it ignores all
        !          1171:        of the read-modify-write instructions.  */
        !          1172:     pinsn = (uint16_t *)pc;
        !          1173:     switch (pinsn[0] >> 8) {
        !          1174:     case 0x50: /* ST */
        !          1175:     case 0x42: /* STC */
        !          1176:     case 0x40: /* STH */
        !          1177:         is_write = 1;
        !          1178:         break;
        !          1179:     case 0xc4: /* RIL format insns */
        !          1180:         switch (pinsn[0] & 0xf) {
        !          1181:         case 0xf: /* STRL */
        !          1182:         case 0xb: /* STGRL */
        !          1183:         case 0x7: /* STHRL */
        !          1184:             is_write = 1;
        !          1185:         }
        !          1186:         break;
        !          1187:     case 0xe3: /* RXY format insns */
        !          1188:         switch (pinsn[2] & 0xff) {
        !          1189:         case 0x50: /* STY */
        !          1190:         case 0x24: /* STG */
        !          1191:         case 0x72: /* STCY */
        !          1192:         case 0x70: /* STHY */
        !          1193:         case 0x8e: /* STPQ */
        !          1194:         case 0x3f: /* STRVH */
        !          1195:         case 0x3e: /* STRV */
        !          1196:         case 0x2f: /* STRVG */
        !          1197:             is_write = 1;
        !          1198:         }
        !          1199:         break;
        !          1200:     }
1.1.1.6   root     1201:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                   1202:                              is_write, &uc->uc_sigmask, puc);
                   1203: }
                   1204: 
                   1205: #elif defined(__mips__)
                   1206: 
                   1207: int cpu_signal_handler(int host_signum, void *pinfo,
                   1208:                        void *puc)
                   1209: {
                   1210:     siginfo_t *info = pinfo;
                   1211:     struct ucontext *uc = puc;
                   1212:     greg_t pc = uc->uc_mcontext.pc;
                   1213:     int is_write;
                   1214: 
                   1215:     /* XXX: compute is_write */
                   1216:     is_write = 0;
                   1217:     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                   1218:                              is_write, &uc->uc_sigmask, puc);
1.1       root     1219: }
                   1220: 
1.1.1.7   root     1221: #elif defined(__hppa__)
                   1222: 
                   1223: int cpu_signal_handler(int host_signum, void *pinfo,
                   1224:                        void *puc)
                   1225: {
                   1226:     struct siginfo *info = pinfo;
                   1227:     struct ucontext *uc = puc;
1.1.1.12! root     1228:     unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
        !          1229:     uint32_t insn = *(uint32_t *)pc;
        !          1230:     int is_write = 0;
        !          1231: 
        !          1232:     /* XXX: need kernel patch to get write flag faster.  */
        !          1233:     switch (insn >> 26) {
        !          1234:     case 0x1a: /* STW */
        !          1235:     case 0x19: /* STH */
        !          1236:     case 0x18: /* STB */
        !          1237:     case 0x1b: /* STWM */
        !          1238:         is_write = 1;
        !          1239:         break;
        !          1240: 
        !          1241:     case 0x09: /* CSTWX, FSTWX, FSTWS */
        !          1242:     case 0x0b: /* CSTDX, FSTDX, FSTDS */
        !          1243:         /* Distinguish from coprocessor load ... */
        !          1244:         is_write = (insn >> 9) & 1;
        !          1245:         break;
        !          1246: 
        !          1247:     case 0x03:
        !          1248:         switch ((insn >> 6) & 15) {
        !          1249:         case 0xa: /* STWS */
        !          1250:         case 0x9: /* STHS */
        !          1251:         case 0x8: /* STBS */
        !          1252:         case 0xe: /* STWAS */
        !          1253:         case 0xc: /* STBYS */
        !          1254:             is_write = 1;
        !          1255:         }
        !          1256:         break;
        !          1257:     }
1.1.1.7   root     1258: 
                   1259:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1.1.1.12! root     1260:                              is_write, &uc->uc_sigmask, puc);
1.1.1.7   root     1261: }
                   1262: 
1.1       root     1263: #else
                   1264: 
                   1265: #error host CPU specific signal handler needed
                   1266: 
                   1267: #endif
                   1268: 
                   1269: #endif /* !defined(CONFIG_SOFTMMU) */

unix.superglobalmegacorp.com