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