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

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

unix.superglobalmegacorp.com