File:  [Qemu by Fabrice Bellard] / qemu / cpu-exec.c
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:56:15 2018 UTC (2 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, HEAD
qemu 0.10.1

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

unix.superglobalmegacorp.com