File:  [Qemu by Fabrice Bellard] / qemu / cpu-exec.c
Revision 1.1.1.13 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:33:32 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

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

unix.superglobalmegacorp.com