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

1.1       root        1: /*
                      2:  *  i386 emulator main execution loop
                      3:  * 
                      4:  *  Copyright (c) 2003-2005 Fabrice Bellard
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, write to the Free Software
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: #include "config.h"
                     21: #include "exec.h"
                     22: #include "disas.h"
                     23: 
                     24: #if !defined(CONFIG_SOFTMMU)
                     25: #undef EAX
                     26: #undef ECX
                     27: #undef EDX
                     28: #undef EBX
                     29: #undef ESP
                     30: #undef EBP
                     31: #undef ESI
                     32: #undef EDI
                     33: #undef EIP
                     34: #include <signal.h>
                     35: #include <sys/ucontext.h>
                     36: #endif
                     37: 
                     38: int tb_invalidated_flag;
                     39: 
                     40: //#define DEBUG_EXEC
                     41: //#define DEBUG_SIGNAL
                     42: 
                     43: #if defined(TARGET_ARM) || defined(TARGET_SPARC)
                     44: /* XXX: unify with i386 target */
                     45: void cpu_loop_exit(void)
                     46: {
                     47:     longjmp(env->jmp_env, 1);
                     48: }
                     49: #endif
                     50: #ifndef TARGET_SPARC
                     51: #define reg_T2
                     52: #endif
                     53: 
                     54: /* exit the current TB from a signal handler. The host registers are
                     55:    restored in a state compatible with the CPU emulator
                     56:  */
                     57: void cpu_resume_from_signal(CPUState *env1, void *puc) 
                     58: {
                     59: #if !defined(CONFIG_SOFTMMU)
                     60:     struct ucontext *uc = puc;
                     61: #endif
                     62: 
                     63:     env = env1;
                     64: 
                     65:     /* XXX: restore cpu registers saved in host registers */
                     66: 
                     67: #if !defined(CONFIG_SOFTMMU)
                     68:     if (puc) {
                     69:         /* XXX: use siglongjmp ? */
                     70:         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
                     71:     }
                     72: #endif
                     73:     longjmp(env->jmp_env, 1);
                     74: }
                     75: 
                     76: /* main execution loop */
                     77: 
                     78: int cpu_exec(CPUState *env1)
                     79: {
                     80:     int saved_T0, saved_T1;
                     81: #if defined(reg_T2)
                     82:     int saved_T2;
                     83: #endif
                     84:     CPUState *saved_env;
                     85: #if defined(TARGET_I386)
                     86: #ifdef reg_EAX
                     87:     int saved_EAX;
                     88: #endif
                     89: #ifdef reg_ECX
                     90:     int saved_ECX;
                     91: #endif
                     92: #ifdef reg_EDX
                     93:     int saved_EDX;
                     94: #endif
                     95: #ifdef reg_EBX
                     96:     int saved_EBX;
                     97: #endif
                     98: #ifdef reg_ESP
                     99:     int saved_ESP;
                    100: #endif
                    101: #ifdef reg_EBP
                    102:     int saved_EBP;
                    103: #endif
                    104: #ifdef reg_ESI
                    105:     int saved_ESI;
                    106: #endif
                    107: #ifdef reg_EDI
                    108:     int saved_EDI;
                    109: #endif
                    110: #elif defined(TARGET_SPARC)
                    111: #if defined(reg_REGWPTR)
                    112:     uint32_t *saved_regwptr;
                    113: #endif
                    114: #endif
                    115: #ifdef __sparc__
                    116:     int saved_i7, tmp_T0;
                    117: #endif
                    118:     int code_gen_size, ret, interrupt_request;
                    119:     void (*gen_func)(void);
                    120:     TranslationBlock *tb, **ptb;
                    121:     target_ulong cs_base, pc;
                    122:     uint8_t *tc_ptr;
                    123:     unsigned int flags;
                    124: 
                    125:     /* first we save global registers */
                    126:     saved_env = env;
                    127:     env = env1;
                    128:     saved_T0 = T0;
                    129:     saved_T1 = T1;
                    130: #if defined(reg_T2)
                    131:     saved_T2 = T2;
                    132: #endif
                    133: #ifdef __sparc__
                    134:     /* we also save i7 because longjmp may not restore it */
                    135:     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
                    136: #endif
                    137: 
                    138: #if defined(TARGET_I386)
                    139: #ifdef reg_EAX
                    140:     saved_EAX = EAX;
                    141: #endif
                    142: #ifdef reg_ECX
                    143:     saved_ECX = ECX;
                    144: #endif
                    145: #ifdef reg_EDX
                    146:     saved_EDX = EDX;
                    147: #endif
                    148: #ifdef reg_EBX
                    149:     saved_EBX = EBX;
                    150: #endif
                    151: #ifdef reg_ESP
                    152:     saved_ESP = ESP;
                    153: #endif
                    154: #ifdef reg_EBP
                    155:     saved_EBP = EBP;
                    156: #endif
                    157: #ifdef reg_ESI
                    158:     saved_ESI = ESI;
                    159: #endif
                    160: #ifdef reg_EDI
                    161:     saved_EDI = EDI;
                    162: #endif
                    163: 
                    164:     env_to_regs();
                    165:     /* put eflags in CPU temporary format */
                    166:     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    167:     DF = 1 - (2 * ((env->eflags >> 10) & 1));
                    168:     CC_OP = CC_OP_EFLAGS;
                    169:     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    170: #elif defined(TARGET_ARM)
                    171:     {
                    172:         unsigned int psr;
                    173:         psr = env->cpsr;
                    174:         env->CF = (psr >> 29) & 1;
                    175:         env->NZF = (psr & 0xc0000000) ^ 0x40000000;
                    176:         env->VF = (psr << 3) & 0x80000000;
                    177:         env->QF = (psr >> 27) & 1;
                    178:         env->cpsr = psr & ~CACHED_CPSR_BITS;
                    179:     }
                    180: #elif defined(TARGET_SPARC)
                    181: #if defined(reg_REGWPTR)
                    182:     saved_regwptr = REGWPTR;
                    183: #endif
                    184: #elif defined(TARGET_PPC)
                    185: #elif defined(TARGET_MIPS)
                    186: #else
                    187: #error unsupported target CPU
                    188: #endif
                    189:     env->exception_index = -1;
                    190: 
                    191:     /* prepare setjmp context for exception handling */
                    192:     for(;;) {
                    193:         if (setjmp(env->jmp_env) == 0) {
                    194:             env->current_tb = NULL;
                    195:             /* if an exception is pending, we execute it here */
                    196:             if (env->exception_index >= 0) {
                    197:                 if (env->exception_index >= EXCP_INTERRUPT) {
                    198:                     /* exit request from the cpu execution loop */
                    199:                     ret = env->exception_index;
                    200:                     break;
                    201:                 } else if (env->user_mode_only) {
                    202:                     /* if user mode only, we simulate a fake exception
                    203:                        which will be hanlded outside the cpu execution
                    204:                        loop */
                    205: #if defined(TARGET_I386)
                    206:                     do_interrupt_user(env->exception_index, 
                    207:                                       env->exception_is_int, 
                    208:                                       env->error_code, 
                    209:                                       env->exception_next_eip);
                    210: #endif
                    211:                     ret = env->exception_index;
                    212:                     break;
                    213:                 } else {
                    214: #if defined(TARGET_I386)
                    215:                     /* simulate a real cpu exception. On i386, it can
                    216:                        trigger new exceptions, but we do not handle
                    217:                        double or triple faults yet. */
                    218:                     do_interrupt(env->exception_index, 
                    219:                                  env->exception_is_int, 
                    220:                                  env->error_code, 
                    221:                                  env->exception_next_eip, 0);
                    222: #elif defined(TARGET_PPC)
                    223:                     do_interrupt(env);
                    224: #elif defined(TARGET_MIPS)
                    225:                     do_interrupt(env);
                    226: #elif defined(TARGET_SPARC)
                    227:                     do_interrupt(env->exception_index);
                    228: #endif
                    229:                 }
                    230:                 env->exception_index = -1;
                    231:             } 
                    232: #ifdef USE_KQEMU
                    233:             if (kqemu_is_ok(env) && env->interrupt_request == 0) {
                    234:                 int ret;
                    235:                 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                    236:                 ret = kqemu_cpu_exec(env);
                    237:                 /* put eflags in CPU temporary format */
                    238:                 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    239:                 DF = 1 - (2 * ((env->eflags >> 10) & 1));
                    240:                 CC_OP = CC_OP_EFLAGS;
                    241:                 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    242:                 if (ret == 1) {
                    243:                     /* exception */
                    244:                     longjmp(env->jmp_env, 1);
                    245:                 } else if (ret == 2) {
                    246:                     /* softmmu execution needed */
                    247:                 } else {
                    248:                     if (env->interrupt_request != 0) {
                    249:                         /* hardware interrupt will be executed just after */
                    250:                     } else {
                    251:                         /* otherwise, we restart */
                    252:                         longjmp(env->jmp_env, 1);
                    253:                     }
                    254:                 }
                    255:             }
                    256: #endif
                    257: 
                    258:             T0 = 0; /* force lookup of first TB */
                    259:             for(;;) {
                    260: #ifdef __sparc__
                    261:                 /* g1 can be modified by some libc? functions */ 
                    262:                 tmp_T0 = T0;
                    263: #endif     
                    264:                 interrupt_request = env->interrupt_request;
                    265:                 if (__builtin_expect(interrupt_request, 0)) {
                    266: #if defined(TARGET_I386)
                    267:                     /* if hardware interrupt pending, we execute it */
                    268:                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                    269:                         (env->eflags & IF_MASK) && 
                    270:                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                    271:                         int intno;
                    272:                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                    273:                         intno = cpu_get_pic_interrupt(env);
                    274:                         if (loglevel & CPU_LOG_TB_IN_ASM) {
                    275:                             fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
                    276:                         }
                    277:                         do_interrupt(intno, 0, 0, 0, 1);
                    278:                         /* ensure that no TB jump will be modified as
                    279:                            the program flow was changed */
                    280: #ifdef __sparc__
                    281:                         tmp_T0 = 0;
                    282: #else
                    283:                         T0 = 0;
                    284: #endif
                    285:                     }
                    286: #elif defined(TARGET_PPC)
                    287: #if 0
                    288:                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
                    289:                         cpu_ppc_reset(env);
                    290:                     }
                    291: #endif
                    292:                     if (msr_ee != 0) {
                    293:                     if ((interrupt_request & CPU_INTERRUPT_HARD)) {
                    294:                            /* Raise it */
                    295:                            env->exception_index = EXCP_EXTERNAL;
                    296:                            env->error_code = 0;
                    297:                             do_interrupt(env);
                    298:                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                    299:                        } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
                    300:                            /* Raise it */
                    301:                            env->exception_index = EXCP_DECR;
                    302:                            env->error_code = 0;
                    303:                            do_interrupt(env);
                    304:                             env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
                    305:                        }
                    306:                     }
                    307: #elif defined(TARGET_MIPS)
                    308:                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                    309:                         (env->CP0_Status & (1 << CP0St_IE)) &&
                    310:                         (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
                    311:                         !(env->hflags & MIPS_HFLAG_EXL) &&
                    312:                         !(env->hflags & MIPS_HFLAG_ERL) &&
                    313:                         !(env->hflags & MIPS_HFLAG_DM)) {
                    314:                         /* Raise it */
                    315:                         env->exception_index = EXCP_EXT_INTERRUPT;
                    316:                         env->error_code = 0;
                    317:                         do_interrupt(env);
                    318:                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                    319:                     }
                    320: #elif defined(TARGET_SPARC)
                    321:                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                    322:                        (env->psret != 0)) {
                    323:                        int pil = env->interrupt_index & 15;
                    324:                        int type = env->interrupt_index & 0xf0;
                    325: 
                    326:                        if (((type == TT_EXTINT) &&
                    327:                             (pil == 15 || pil > env->psrpil)) ||
                    328:                            type != TT_EXTINT) {
                    329:                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                    330:                            do_interrupt(env->interrupt_index);
                    331:                            env->interrupt_index = 0;
                    332:                        }
                    333:                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
                    334:                        //do_interrupt(0, 0, 0, 0, 0);
                    335:                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
                    336:                    }
                    337: #endif
                    338:                     if (interrupt_request & CPU_INTERRUPT_EXITTB) {
                    339:                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                    340:                         /* ensure that no TB jump will be modified as
                    341:                            the program flow was changed */
                    342: #ifdef __sparc__
                    343:                         tmp_T0 = 0;
                    344: #else
                    345:                         T0 = 0;
                    346: #endif
                    347:                     }
                    348:                     if (interrupt_request & CPU_INTERRUPT_EXIT) {
                    349:                         env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
                    350:                         env->exception_index = EXCP_INTERRUPT;
                    351:                         cpu_loop_exit();
                    352:                     }
                    353:                 }
                    354: #ifdef DEBUG_EXEC
                    355:                 if ((loglevel & CPU_LOG_EXEC)) {
                    356: #if defined(TARGET_I386)
                    357:                     /* restore flags in standard format */
                    358: #ifdef reg_EAX
                    359:                     env->regs[R_EAX] = EAX;
                    360: #endif
                    361: #ifdef reg_EBX
                    362:                     env->regs[R_EBX] = EBX;
                    363: #endif
                    364: #ifdef reg_ECX
                    365:                     env->regs[R_ECX] = ECX;
                    366: #endif
                    367: #ifdef reg_EDX
                    368:                     env->regs[R_EDX] = EDX;
                    369: #endif
                    370: #ifdef reg_ESI
                    371:                     env->regs[R_ESI] = ESI;
                    372: #endif
                    373: #ifdef reg_EDI
                    374:                     env->regs[R_EDI] = EDI;
                    375: #endif
                    376: #ifdef reg_EBP
                    377:                     env->regs[R_EBP] = EBP;
                    378: #endif
                    379: #ifdef reg_ESP
                    380:                     env->regs[R_ESP] = ESP;
                    381: #endif
                    382:                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                    383:                     cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                    384:                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
                    385: #elif defined(TARGET_ARM)
                    386:                     env->cpsr = compute_cpsr();
                    387:                     cpu_dump_state(env, logfile, fprintf, 0);
                    388:                     env->cpsr &= ~CACHED_CPSR_BITS;
                    389: #elif defined(TARGET_SPARC)
                    390:                    REGWPTR = env->regbase + (env->cwp * 16);
                    391:                    env->regwptr = REGWPTR;
                    392:                     cpu_dump_state(env, logfile, fprintf, 0);
                    393: #elif defined(TARGET_PPC)
                    394:                     cpu_dump_state(env, logfile, fprintf, 0);
                    395: #elif defined(TARGET_MIPS)
                    396:                     cpu_dump_state(env, logfile, fprintf, 0);
                    397: #else
                    398: #error unsupported target CPU 
                    399: #endif
                    400:                 }
                    401: #endif
                    402:                 /* we record a subset of the CPU state. It will
                    403:                    always be the same before a given translated block
                    404:                    is executed. */
                    405: #if defined(TARGET_I386)
                    406:                 flags = env->hflags;
                    407:                 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
                    408:                 cs_base = env->segs[R_CS].base;
                    409:                 pc = cs_base + env->eip;
                    410: #elif defined(TARGET_ARM)
                    411:                 flags = env->thumb | (env->vfp.vec_len << 1)
                    412:                         | (env->vfp.vec_stride << 4);
                    413:                 cs_base = 0;
                    414:                 pc = env->regs[15];
                    415: #elif defined(TARGET_SPARC)
                    416: #ifdef TARGET_SPARC64
                    417:                 flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
                    418: #else
                    419:                 flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);
                    420: #endif
                    421:                 cs_base = env->npc;
                    422:                 pc = env->pc;
                    423: #elif defined(TARGET_PPC)
                    424:                 flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
                    425:                     (msr_se << MSR_SE) | (msr_le << MSR_LE);
                    426:                 cs_base = 0;
                    427:                 pc = env->nip;
                    428: #elif defined(TARGET_MIPS)
                    429:                 flags = env->hflags & MIPS_HFLAGS_TMASK;
                    430:                 cs_base = NULL;
                    431:                 pc = env->PC;
                    432: #else
                    433: #error unsupported CPU
                    434: #endif
                    435:                 tb = tb_find(&ptb, pc, cs_base, 
                    436:                              flags);
                    437:                 if (!tb) {
                    438:                     TranslationBlock **ptb1;
                    439:                     unsigned int h;
                    440:                     target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
                    441:                     
                    442:                     
                    443:                     spin_lock(&tb_lock);
                    444: 
                    445:                     tb_invalidated_flag = 0;
                    446:                     
                    447:                     regs_to_env(); /* XXX: do it just before cpu_gen_code() */
                    448: 
                    449:                     /* find translated block using physical mappings */
                    450:                     phys_pc = get_phys_addr_code(env, pc);
                    451:                     phys_page1 = phys_pc & TARGET_PAGE_MASK;
                    452:                     phys_page2 = -1;
                    453:                     h = tb_phys_hash_func(phys_pc);
                    454:                     ptb1 = &tb_phys_hash[h];
                    455:                     for(;;) {
                    456:                         tb = *ptb1;
                    457:                         if (!tb)
                    458:                             goto not_found;
                    459:                         if (tb->pc == pc && 
                    460:                             tb->page_addr[0] == phys_page1 &&
                    461:                             tb->cs_base == cs_base && 
                    462:                             tb->flags == flags) {
                    463:                             /* check next page if needed */
                    464:                             if (tb->page_addr[1] != -1) {
                    465:                                 virt_page2 = (pc & TARGET_PAGE_MASK) + 
                    466:                                     TARGET_PAGE_SIZE;
                    467:                                 phys_page2 = get_phys_addr_code(env, virt_page2);
                    468:                                 if (tb->page_addr[1] == phys_page2)
                    469:                                     goto found;
                    470:                             } else {
                    471:                                 goto found;
                    472:                             }
                    473:                         }
                    474:                         ptb1 = &tb->phys_hash_next;
                    475:                     }
                    476:                 not_found:
                    477:                     /* if no translated code available, then translate it now */
                    478:                     tb = tb_alloc(pc);
                    479:                     if (!tb) {
                    480:                         /* flush must be done */
                    481:                         tb_flush(env);
                    482:                         /* cannot fail at this point */
                    483:                         tb = tb_alloc(pc);
                    484:                         /* don't forget to invalidate previous TB info */
                    485:                         ptb = &tb_hash[tb_hash_func(pc)];
                    486:                         T0 = 0;
                    487:                     }
                    488:                     tc_ptr = code_gen_ptr;
                    489:                     tb->tc_ptr = tc_ptr;
                    490:                     tb->cs_base = cs_base;
                    491:                     tb->flags = flags;
                    492:                     cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
                    493:                     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
                    494:                     
                    495:                     /* check next page if needed */
                    496:                     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
                    497:                     phys_page2 = -1;
                    498:                     if ((pc & TARGET_PAGE_MASK) != virt_page2) {
                    499:                         phys_page2 = get_phys_addr_code(env, virt_page2);
                    500:                     }
                    501:                     tb_link_phys(tb, phys_pc, phys_page2);
                    502: 
                    503:                 found:
                    504:                     if (tb_invalidated_flag) {
                    505:                         /* as some TB could have been invalidated because
                    506:                            of memory exceptions while generating the code, we
                    507:                            must recompute the hash index here */
                    508:                         ptb = &tb_hash[tb_hash_func(pc)];
                    509:                         while (*ptb != NULL)
                    510:                             ptb = &(*ptb)->hash_next;
                    511:                         T0 = 0;
                    512:                     }
                    513:                     /* we add the TB in the virtual pc hash table */
                    514:                     *ptb = tb;
                    515:                     tb->hash_next = NULL;
                    516:                     tb_link(tb);
                    517:                     spin_unlock(&tb_lock);
                    518:                 }
                    519: #ifdef DEBUG_EXEC
                    520:                 if ((loglevel & CPU_LOG_EXEC)) {
                    521:                     fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
                    522:                             (long)tb->tc_ptr, tb->pc,
                    523:                             lookup_symbol(tb->pc));
                    524:                 }
                    525: #endif
                    526: #ifdef __sparc__
                    527:                 T0 = tmp_T0;
                    528: #endif     
                    529:                 /* see if we can patch the calling TB. */
                    530:                 {
                    531:                     if (T0 != 0
                    532: #if defined(TARGET_I386) && defined(USE_CODE_COPY)
                    533:                     && (tb->cflags & CF_CODE_COPY) == 
                    534:                     (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
                    535: #endif
                    536:                     ) {
                    537:                     spin_lock(&tb_lock);
                    538:                     tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
                    539: #if defined(USE_CODE_COPY)
                    540:                     /* propagates the FP use info */
                    541:                     ((TranslationBlock *)(T0 & ~3))->cflags |= 
                    542:                         (tb->cflags & CF_FP_USED);
                    543: #endif
                    544:                     spin_unlock(&tb_lock);
                    545:                 }
                    546:                 }
                    547:                 tc_ptr = tb->tc_ptr;
                    548:                 env->current_tb = tb;
                    549:                 /* execute the generated code */
                    550:                 gen_func = (void *)tc_ptr;
                    551: #if defined(__sparc__)
                    552:                 __asm__ __volatile__("call     %0\n\t"
                    553:                                      "mov      %%o7,%%i0"
                    554:                                      : /* no outputs */
                    555:                                      : "r" (gen_func) 
                    556:                                      : "i0", "i1", "i2", "i3", "i4", "i5");
                    557: #elif defined(__arm__)
                    558:                 asm volatile ("mov pc, %0\n\t"
                    559:                               ".global exec_loop\n\t"
                    560:                               "exec_loop:\n\t"
                    561:                               : /* no outputs */
                    562:                               : "r" (gen_func)
                    563:                               : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
                    564: #elif defined(TARGET_I386) && defined(USE_CODE_COPY)
                    565: {
                    566:     if (!(tb->cflags & CF_CODE_COPY)) {
                    567:         if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
                    568:             save_native_fp_state(env);
                    569:         }
                    570:         gen_func();
                    571:     } else {
                    572:         if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
                    573:             restore_native_fp_state(env);
                    574:         }
                    575:         /* we work with native eflags */
                    576:         CC_SRC = cc_table[CC_OP].compute_all();
                    577:         CC_OP = CC_OP_EFLAGS;
                    578:         asm(".globl exec_loop\n"
                    579:             "\n"
                    580:             "debug1:\n"
                    581:             "    pushl %%ebp\n"
                    582:             "    fs movl %10, %9\n"
                    583:             "    fs movl %11, %%eax\n"
                    584:             "    andl $0x400, %%eax\n"
                    585:             "    fs orl %8, %%eax\n"
                    586:             "    pushl %%eax\n"
                    587:             "    popf\n"
                    588:             "    fs movl %%esp, %12\n"
                    589:             "    fs movl %0, %%eax\n"
                    590:             "    fs movl %1, %%ecx\n"
                    591:             "    fs movl %2, %%edx\n"
                    592:             "    fs movl %3, %%ebx\n"
                    593:             "    fs movl %4, %%esp\n"
                    594:             "    fs movl %5, %%ebp\n"
                    595:             "    fs movl %6, %%esi\n"
                    596:             "    fs movl %7, %%edi\n"
                    597:             "    fs jmp *%9\n"
                    598:             "exec_loop:\n"
                    599:             "    fs movl %%esp, %4\n"
                    600:             "    fs movl %12, %%esp\n"
                    601:             "    fs movl %%eax, %0\n"
                    602:             "    fs movl %%ecx, %1\n"
                    603:             "    fs movl %%edx, %2\n"
                    604:             "    fs movl %%ebx, %3\n"
                    605:             "    fs movl %%ebp, %5\n"
                    606:             "    fs movl %%esi, %6\n"
                    607:             "    fs movl %%edi, %7\n"
                    608:             "    pushf\n"
                    609:             "    popl %%eax\n"
                    610:             "    movl %%eax, %%ecx\n"
                    611:             "    andl $0x400, %%ecx\n"
                    612:             "    shrl $9, %%ecx\n"
                    613:             "    andl $0x8d5, %%eax\n"
                    614:             "    fs movl %%eax, %8\n"
                    615:             "    movl $1, %%eax\n"
                    616:             "    subl %%ecx, %%eax\n"
                    617:             "    fs movl %%eax, %11\n"
                    618:             "    fs movl %9, %%ebx\n" /* get T0 value */
                    619:             "    popl %%ebp\n"
                    620:             :
                    621:             : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
                    622:             "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
                    623:             "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
                    624:             "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
                    625:             "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
                    626:             "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
                    627:             "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
                    628:             "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
                    629:             "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
                    630:             "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
                    631:             "a" (gen_func),
                    632:             "m" (*(uint8_t *)offsetof(CPUState, df)),
                    633:             "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
                    634:             : "%ecx", "%edx"
                    635:             );
                    636:     }
                    637: }
                    638: #elif defined(__ia64)
                    639:                struct fptr {
                    640:                        void *ip;
                    641:                        void *gp;
                    642:                } fp;
                    643: 
                    644:                fp.ip = tc_ptr;
                    645:                fp.gp = code_gen_buffer + 2 * (1 << 20);
                    646:                (*(void (*)(void)) &fp)();
                    647: #else
                    648:                 gen_func();
                    649: #endif
                    650:                 env->current_tb = NULL;
                    651:                 /* reset soft MMU for next block (it can currently
                    652:                    only be set by a memory fault) */
                    653: #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
                    654:                 if (env->hflags & HF_SOFTMMU_MASK) {
                    655:                     env->hflags &= ~HF_SOFTMMU_MASK;
                    656:                     /* do not allow linking to another block */
                    657:                     T0 = 0;
                    658:                 }
                    659: #endif
                    660:             }
                    661:         } else {
                    662:             env_to_regs();
                    663:         }
                    664:     } /* for(;;) */
                    665: 
                    666: 
                    667: #if defined(TARGET_I386)
                    668: #if defined(USE_CODE_COPY)
                    669:     if (env->native_fp_regs) {
                    670:         save_native_fp_state(env);
                    671:     }
                    672: #endif
                    673:     /* restore flags in standard format */
                    674:     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
                    675: 
                    676:     /* restore global registers */
                    677: #ifdef reg_EAX
                    678:     EAX = saved_EAX;
                    679: #endif
                    680: #ifdef reg_ECX
                    681:     ECX = saved_ECX;
                    682: #endif
                    683: #ifdef reg_EDX
                    684:     EDX = saved_EDX;
                    685: #endif
                    686: #ifdef reg_EBX
                    687:     EBX = saved_EBX;
                    688: #endif
                    689: #ifdef reg_ESP
                    690:     ESP = saved_ESP;
                    691: #endif
                    692: #ifdef reg_EBP
                    693:     EBP = saved_EBP;
                    694: #endif
                    695: #ifdef reg_ESI
                    696:     ESI = saved_ESI;
                    697: #endif
                    698: #ifdef reg_EDI
                    699:     EDI = saved_EDI;
                    700: #endif
                    701: #elif defined(TARGET_ARM)
                    702:     env->cpsr = compute_cpsr();
                    703:     /* XXX: Save/restore host fpu exception state?.  */
                    704: #elif defined(TARGET_SPARC)
                    705: #if defined(reg_REGWPTR)
                    706:     REGWPTR = saved_regwptr;
                    707: #endif
                    708: #elif defined(TARGET_PPC)
                    709: #elif defined(TARGET_MIPS)
                    710: #else
                    711: #error unsupported target CPU
                    712: #endif
                    713: #ifdef __sparc__
                    714:     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
                    715: #endif
                    716:     T0 = saved_T0;
                    717:     T1 = saved_T1;
                    718: #if defined(reg_T2)
                    719:     T2 = saved_T2;
                    720: #endif
                    721:     env = saved_env;
                    722:     return ret;
                    723: }
                    724: 
                    725: /* must only be called from the generated code as an exception can be
                    726:    generated */
                    727: void tb_invalidate_page_range(target_ulong start, target_ulong end)
                    728: {
                    729:     /* XXX: cannot enable it yet because it yields to MMU exception
                    730:        where NIP != read address on PowerPC */
                    731: #if 0
                    732:     target_ulong phys_addr;
                    733:     phys_addr = get_phys_addr_code(env, start);
                    734:     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
                    735: #endif
                    736: }
                    737: 
                    738: #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
                    739: 
                    740: void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
                    741: {
                    742:     CPUX86State *saved_env;
                    743: 
                    744:     saved_env = env;
                    745:     env = s;
                    746:     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
                    747:         selector &= 0xffff;
                    748:         cpu_x86_load_seg_cache(env, seg_reg, selector, 
                    749:                                (selector << 4), 0xffff, 0);
                    750:     } else {
                    751:         load_seg(seg_reg, selector);
                    752:     }
                    753:     env = saved_env;
                    754: }
                    755: 
                    756: void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
                    757: {
                    758:     CPUX86State *saved_env;
                    759: 
                    760:     saved_env = env;
                    761:     env = s;
                    762:     
                    763:     helper_fsave((target_ulong)ptr, data32);
                    764: 
                    765:     env = saved_env;
                    766: }
                    767: 
                    768: void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
                    769: {
                    770:     CPUX86State *saved_env;
                    771: 
                    772:     saved_env = env;
                    773:     env = s;
                    774:     
                    775:     helper_frstor((target_ulong)ptr, data32);
                    776: 
                    777:     env = saved_env;
                    778: }
                    779: 
                    780: #endif /* TARGET_I386 */
                    781: 
                    782: #if !defined(CONFIG_SOFTMMU)
                    783: 
                    784: #if defined(TARGET_I386)
                    785: 
                    786: /* 'pc' is the host PC at which the exception was raised. 'address' is
                    787:    the effective address of the memory exception. 'is_write' is 1 if a
                    788:    write caused the exception and otherwise 0'. 'old_set' is the
                    789:    signal set which should be restored */
                    790: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    791:                                     int is_write, sigset_t *old_set, 
                    792:                                     void *puc)
                    793: {
                    794:     TranslationBlock *tb;
                    795:     int ret;
                    796: 
                    797:     if (cpu_single_env)
                    798:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    799: #if defined(DEBUG_SIGNAL)
                    800:     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
                    801:                 pc, address, is_write, *(unsigned long *)old_set);
                    802: #endif
                    803:     /* XXX: locking issue */
                    804:     if (is_write && page_unprotect(address, pc, puc)) {
                    805:         return 1;
                    806:     }
                    807: 
                    808:     /* see if it is an MMU fault */
                    809:     ret = cpu_x86_handle_mmu_fault(env, address, is_write, 
                    810:                                    ((env->hflags & HF_CPL_MASK) == 3), 0);
                    811:     if (ret < 0)
                    812:         return 0; /* not an MMU fault */
                    813:     if (ret == 0)
                    814:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    815:     /* now we have a real cpu fault */
                    816:     tb = tb_find_pc(pc);
                    817:     if (tb) {
                    818:         /* the PC is inside the translated code. It means that we have
                    819:            a virtual CPU fault */
                    820:         cpu_restore_state(tb, env, pc, puc);
                    821:     }
                    822:     if (ret == 1) {
                    823: #if 0
                    824:         printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", 
                    825:                env->eip, env->cr[2], env->error_code);
                    826: #endif
                    827:         /* we restore the process signal mask as the sigreturn should
                    828:            do it (XXX: use sigsetjmp) */
                    829:         sigprocmask(SIG_SETMASK, old_set, NULL);
                    830:         raise_exception_err(EXCP0E_PAGE, env->error_code);
                    831:     } else {
                    832:         /* activate soft MMU for this block */
                    833:         env->hflags |= HF_SOFTMMU_MASK;
                    834:         cpu_resume_from_signal(env, puc);
                    835:     }
                    836:     /* never comes here */
                    837:     return 1;
                    838: }
                    839: 
                    840: #elif defined(TARGET_ARM)
                    841: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    842:                                     int is_write, sigset_t *old_set,
                    843:                                     void *puc)
                    844: {
                    845:     TranslationBlock *tb;
                    846:     int ret;
                    847: 
                    848:     if (cpu_single_env)
                    849:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    850: #if defined(DEBUG_SIGNAL)
                    851:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
                    852:            pc, address, is_write, *(unsigned long *)old_set);
                    853: #endif
                    854:     /* XXX: locking issue */
                    855:     if (is_write && page_unprotect(address, pc, puc)) {
                    856:         return 1;
                    857:     }
                    858:     /* see if it is an MMU fault */
                    859:     ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
                    860:     if (ret < 0)
                    861:         return 0; /* not an MMU fault */
                    862:     if (ret == 0)
                    863:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    864:     /* now we have a real cpu fault */
                    865:     tb = tb_find_pc(pc);
                    866:     if (tb) {
                    867:         /* the PC is inside the translated code. It means that we have
                    868:            a virtual CPU fault */
                    869:         cpu_restore_state(tb, env, pc, puc);
                    870:     }
                    871:     /* we restore the process signal mask as the sigreturn should
                    872:        do it (XXX: use sigsetjmp) */
                    873:     sigprocmask(SIG_SETMASK, old_set, NULL);
                    874:     cpu_loop_exit();
                    875: }
                    876: #elif defined(TARGET_SPARC)
                    877: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    878:                                     int is_write, sigset_t *old_set,
                    879:                                     void *puc)
                    880: {
                    881:     TranslationBlock *tb;
                    882:     int ret;
                    883: 
                    884:     if (cpu_single_env)
                    885:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    886: #if defined(DEBUG_SIGNAL)
                    887:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
                    888:            pc, address, is_write, *(unsigned long *)old_set);
                    889: #endif
                    890:     /* XXX: locking issue */
                    891:     if (is_write && page_unprotect(address, pc, puc)) {
                    892:         return 1;
                    893:     }
                    894:     /* see if it is an MMU fault */
                    895:     ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
                    896:     if (ret < 0)
                    897:         return 0; /* not an MMU fault */
                    898:     if (ret == 0)
                    899:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    900:     /* now we have a real cpu fault */
                    901:     tb = tb_find_pc(pc);
                    902:     if (tb) {
                    903:         /* the PC is inside the translated code. It means that we have
                    904:            a virtual CPU fault */
                    905:         cpu_restore_state(tb, env, pc, puc);
                    906:     }
                    907:     /* we restore the process signal mask as the sigreturn should
                    908:        do it (XXX: use sigsetjmp) */
                    909:     sigprocmask(SIG_SETMASK, old_set, NULL);
                    910:     cpu_loop_exit();
                    911: }
                    912: #elif defined (TARGET_PPC)
                    913: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    914:                                     int is_write, sigset_t *old_set,
                    915:                                     void *puc)
                    916: {
                    917:     TranslationBlock *tb;
                    918:     int ret;
                    919:     
                    920:     if (cpu_single_env)
                    921:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    922: #if defined(DEBUG_SIGNAL)
                    923:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
                    924:            pc, address, is_write, *(unsigned long *)old_set);
                    925: #endif
                    926:     /* XXX: locking issue */
                    927:     if (is_write && page_unprotect(address, pc, puc)) {
                    928:         return 1;
                    929:     }
                    930: 
                    931:     /* see if it is an MMU fault */
                    932:     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
                    933:     if (ret < 0)
                    934:         return 0; /* not an MMU fault */
                    935:     if (ret == 0)
                    936:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    937: 
                    938:     /* now we have a real cpu fault */
                    939:     tb = tb_find_pc(pc);
                    940:     if (tb) {
                    941:         /* the PC is inside the translated code. It means that we have
                    942:            a virtual CPU fault */
                    943:         cpu_restore_state(tb, env, pc, puc);
                    944:     }
                    945:     if (ret == 1) {
                    946: #if 0
                    947:         printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
                    948:                env->nip, env->error_code, tb);
                    949: #endif
                    950:     /* we restore the process signal mask as the sigreturn should
                    951:        do it (XXX: use sigsetjmp) */
                    952:         sigprocmask(SIG_SETMASK, old_set, NULL);
                    953:         do_raise_exception_err(env->exception_index, env->error_code);
                    954:     } else {
                    955:         /* activate soft MMU for this block */
                    956:         cpu_resume_from_signal(env, puc);
                    957:     }
                    958:     /* never comes here */
                    959:     return 1;
                    960: }
                    961: 
                    962: #elif defined (TARGET_MIPS)
                    963: static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
                    964:                                     int is_write, sigset_t *old_set,
                    965:                                     void *puc)
                    966: {
                    967:     TranslationBlock *tb;
                    968:     int ret;
                    969:     
                    970:     if (cpu_single_env)
                    971:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                    972: #if defined(DEBUG_SIGNAL)
                    973:     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
                    974:            pc, address, is_write, *(unsigned long *)old_set);
                    975: #endif
                    976:     /* XXX: locking issue */
                    977:     if (is_write && page_unprotect(address, pc, puc)) {
                    978:         return 1;
                    979:     }
                    980: 
                    981:     /* see if it is an MMU fault */
                    982:     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
                    983:     if (ret < 0)
                    984:         return 0; /* not an MMU fault */
                    985:     if (ret == 0)
                    986:         return 1; /* the MMU fault was handled without causing real CPU fault */
                    987: 
                    988:     /* now we have a real cpu fault */
                    989:     tb = tb_find_pc(pc);
                    990:     if (tb) {
                    991:         /* the PC is inside the translated code. It means that we have
                    992:            a virtual CPU fault */
                    993:         cpu_restore_state(tb, env, pc, puc);
                    994:     }
                    995:     if (ret == 1) {
                    996: #if 0
                    997:         printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
                    998:                env->nip, env->error_code, tb);
                    999: #endif
                   1000:     /* we restore the process signal mask as the sigreturn should
                   1001:        do it (XXX: use sigsetjmp) */
                   1002:         sigprocmask(SIG_SETMASK, old_set, NULL);
                   1003:         do_raise_exception_err(env->exception_index, env->error_code);
                   1004:     } else {
                   1005:         /* activate soft MMU for this block */
                   1006:         cpu_resume_from_signal(env, puc);
                   1007:     }
                   1008:     /* never comes here */
                   1009:     return 1;
                   1010: }
                   1011: 
                   1012: #else
                   1013: #error unsupported target CPU
                   1014: #endif
                   1015: 
                   1016: #if defined(__i386__)
                   1017: 
                   1018: #if defined(USE_CODE_COPY)
                   1019: static void cpu_send_trap(unsigned long pc, int trap, 
                   1020:                           struct ucontext *uc)
                   1021: {
                   1022:     TranslationBlock *tb;
                   1023: 
                   1024:     if (cpu_single_env)
                   1025:         env = cpu_single_env; /* XXX: find a correct solution for multithread */
                   1026:     /* now we have a real cpu fault */
                   1027:     tb = tb_find_pc(pc);
                   1028:     if (tb) {
                   1029:         /* the PC is inside the translated code. It means that we have
                   1030:            a virtual CPU fault */
                   1031:         cpu_restore_state(tb, env, pc, uc);
                   1032:     }
                   1033:     sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
                   1034:     raise_exception_err(trap, env->error_code);
                   1035: }
                   1036: #endif
                   1037: 
                   1038: int cpu_signal_handler(int host_signum, struct siginfo *info, 
                   1039:                        void *puc)
                   1040: {
                   1041:     struct ucontext *uc = puc;
                   1042:     unsigned long pc;
                   1043:     int trapno;
                   1044: 
                   1045: #ifndef REG_EIP
                   1046: /* for glibc 2.1 */
                   1047: #define REG_EIP    EIP
                   1048: #define REG_ERR    ERR
                   1049: #define REG_TRAPNO TRAPNO
                   1050: #endif
                   1051:     pc = uc->uc_mcontext.gregs[REG_EIP];
                   1052:     trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
                   1053: #if defined(TARGET_I386) && defined(USE_CODE_COPY)
                   1054:     if (trapno == 0x00 || trapno == 0x05) {
                   1055:         /* send division by zero or bound exception */
                   1056:         cpu_send_trap(pc, trapno, uc);
                   1057:         return 1;
                   1058:     } else
                   1059: #endif
                   1060:         return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1061:                                  trapno == 0xe ? 
                   1062:                                  (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
                   1063:                                  &uc->uc_sigmask, puc);
                   1064: }
                   1065: 
                   1066: #elif defined(__x86_64__)
                   1067: 
                   1068: int cpu_signal_handler(int host_signum, struct siginfo *info,
                   1069:                        void *puc)
                   1070: {
                   1071:     struct ucontext *uc = puc;
                   1072:     unsigned long pc;
                   1073: 
                   1074:     pc = uc->uc_mcontext.gregs[REG_RIP];
                   1075:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1076:                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? 
                   1077:                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
                   1078:                              &uc->uc_sigmask, puc);
                   1079: }
                   1080: 
                   1081: #elif defined(__powerpc__)
                   1082: 
                   1083: /***********************************************************************
                   1084:  * signal context platform-specific definitions
                   1085:  * From Wine
                   1086:  */
                   1087: #ifdef linux
                   1088: /* All Registers access - only for local access */
                   1089: # define REG_sig(reg_name, context)            ((context)->uc_mcontext.regs->reg_name)
                   1090: /* Gpr Registers access  */
                   1091: # define GPR_sig(reg_num, context)             REG_sig(gpr[reg_num], context)
                   1092: # define IAR_sig(context)                      REG_sig(nip, context)   /* Program counter */
                   1093: # define MSR_sig(context)                      REG_sig(msr, context)   /* Machine State Register (Supervisor) */
                   1094: # define CTR_sig(context)                      REG_sig(ctr, context)   /* Count register */
                   1095: # define XER_sig(context)                      REG_sig(xer, context) /* User's integer exception register */
                   1096: # define LR_sig(context)                       REG_sig(link, context) /* Link register */
                   1097: # define CR_sig(context)                       REG_sig(ccr, context) /* Condition register */
                   1098: /* Float Registers access  */
                   1099: # define FLOAT_sig(reg_num, context)           (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
                   1100: # define FPSCR_sig(context)                    (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
                   1101: /* Exception Registers access */
                   1102: # define DAR_sig(context)                      REG_sig(dar, context)
                   1103: # define DSISR_sig(context)                    REG_sig(dsisr, context)
                   1104: # define TRAP_sig(context)                     REG_sig(trap, context)
                   1105: #endif /* linux */
                   1106: 
                   1107: #ifdef __APPLE__
                   1108: # include <sys/ucontext.h>
                   1109: typedef struct ucontext SIGCONTEXT;
                   1110: /* All Registers access - only for local access */
                   1111: # define REG_sig(reg_name, context)            ((context)->uc_mcontext->ss.reg_name)
                   1112: # define FLOATREG_sig(reg_name, context)       ((context)->uc_mcontext->fs.reg_name)
                   1113: # define EXCEPREG_sig(reg_name, context)       ((context)->uc_mcontext->es.reg_name)
                   1114: # define VECREG_sig(reg_name, context)         ((context)->uc_mcontext->vs.reg_name)
                   1115: /* Gpr Registers access */
                   1116: # define GPR_sig(reg_num, context)             REG_sig(r##reg_num, context)
                   1117: # define IAR_sig(context)                      REG_sig(srr0, context)  /* Program counter */
                   1118: # define MSR_sig(context)                      REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
                   1119: # define CTR_sig(context)                      REG_sig(ctr, context)
                   1120: # define XER_sig(context)                      REG_sig(xer, context) /* Link register */
                   1121: # define LR_sig(context)                       REG_sig(lr, context)  /* User's integer exception register */
                   1122: # define CR_sig(context)                       REG_sig(cr, context)  /* Condition register */
                   1123: /* Float Registers access */
                   1124: # define FLOAT_sig(reg_num, context)           FLOATREG_sig(fpregs[reg_num], context)
                   1125: # define FPSCR_sig(context)                    ((double)FLOATREG_sig(fpscr, context))
                   1126: /* Exception Registers access */
                   1127: # define DAR_sig(context)                      EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
                   1128: # define DSISR_sig(context)                    EXCEPREG_sig(dsisr, context)
                   1129: # define TRAP_sig(context)                     EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
                   1130: #endif /* __APPLE__ */
                   1131: 
                   1132: int cpu_signal_handler(int host_signum, struct siginfo *info, 
                   1133:                        void *puc)
                   1134: {
                   1135:     struct ucontext *uc = puc;
                   1136:     unsigned long pc;
                   1137:     int is_write;
                   1138: 
                   1139:     pc = IAR_sig(uc);
                   1140:     is_write = 0;
                   1141: #if 0
                   1142:     /* ppc 4xx case */
                   1143:     if (DSISR_sig(uc) & 0x00800000)
                   1144:         is_write = 1;
                   1145: #else
                   1146:     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
                   1147:         is_write = 1;
                   1148: #endif
                   1149:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1150:                              is_write, &uc->uc_sigmask, puc);
                   1151: }
                   1152: 
                   1153: #elif defined(__alpha__)
                   1154: 
                   1155: int cpu_signal_handler(int host_signum, struct siginfo *info, 
                   1156:                            void *puc)
                   1157: {
                   1158:     struct ucontext *uc = puc;
                   1159:     uint32_t *pc = uc->uc_mcontext.sc_pc;
                   1160:     uint32_t insn = *pc;
                   1161:     int is_write = 0;
                   1162: 
                   1163:     /* XXX: need kernel patch to get write flag faster */
                   1164:     switch (insn >> 26) {
                   1165:     case 0x0d: // stw
                   1166:     case 0x0e: // stb
                   1167:     case 0x0f: // stq_u
                   1168:     case 0x24: // stf
                   1169:     case 0x25: // stg
                   1170:     case 0x26: // sts
                   1171:     case 0x27: // stt
                   1172:     case 0x2c: // stl
                   1173:     case 0x2d: // stq
                   1174:     case 0x2e: // stl_c
                   1175:     case 0x2f: // stq_c
                   1176:        is_write = 1;
                   1177:     }
                   1178: 
                   1179:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1180:                              is_write, &uc->uc_sigmask, puc);
                   1181: }
                   1182: #elif defined(__sparc__)
                   1183: 
                   1184: int cpu_signal_handler(int host_signum, struct siginfo *info, 
                   1185:                        void *puc)
                   1186: {
                   1187:     uint32_t *regs = (uint32_t *)(info + 1);
                   1188:     void *sigmask = (regs + 20);
                   1189:     unsigned long pc;
                   1190:     int is_write;
                   1191:     uint32_t insn;
                   1192:     
                   1193:     /* XXX: is there a standard glibc define ? */
                   1194:     pc = regs[1];
                   1195:     /* XXX: need kernel patch to get write flag faster */
                   1196:     is_write = 0;
                   1197:     insn = *(uint32_t *)pc;
                   1198:     if ((insn >> 30) == 3) {
                   1199:       switch((insn >> 19) & 0x3f) {
                   1200:       case 0x05: // stb
                   1201:       case 0x06: // sth
                   1202:       case 0x04: // st
                   1203:       case 0x07: // std
                   1204:       case 0x24: // stf
                   1205:       case 0x27: // stdf
                   1206:       case 0x25: // stfsr
                   1207:        is_write = 1;
                   1208:        break;
                   1209:       }
                   1210:     }
                   1211:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1212:                              is_write, sigmask, NULL);
                   1213: }
                   1214: 
                   1215: #elif defined(__arm__)
                   1216: 
                   1217: int cpu_signal_handler(int host_signum, struct siginfo *info, 
                   1218:                        void *puc)
                   1219: {
                   1220:     struct ucontext *uc = puc;
                   1221:     unsigned long pc;
                   1222:     int is_write;
                   1223:     
                   1224:     pc = uc->uc_mcontext.gregs[R15];
                   1225:     /* XXX: compute is_write */
                   1226:     is_write = 0;
                   1227:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1228:                              is_write,
                   1229:                              &uc->uc_sigmask);
                   1230: }
                   1231: 
                   1232: #elif defined(__mc68000)
                   1233: 
                   1234: int cpu_signal_handler(int host_signum, struct siginfo *info, 
                   1235:                        void *puc)
                   1236: {
                   1237:     struct ucontext *uc = puc;
                   1238:     unsigned long pc;
                   1239:     int is_write;
                   1240:     
                   1241:     pc = uc->uc_mcontext.gregs[16];
                   1242:     /* XXX: compute is_write */
                   1243:     is_write = 0;
                   1244:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1245:                              is_write,
                   1246:                              &uc->uc_sigmask, puc);
                   1247: }
                   1248: 
                   1249: #elif defined(__ia64)
                   1250: 
                   1251: #ifndef __ISR_VALID
                   1252:   /* This ought to be in <bits/siginfo.h>... */
                   1253: # define __ISR_VALID   1
                   1254: # define si_flags      _sifields._sigfault._si_pad0
                   1255: #endif
                   1256: 
                   1257: int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
                   1258: {
                   1259:     struct ucontext *uc = puc;
                   1260:     unsigned long ip;
                   1261:     int is_write = 0;
                   1262: 
                   1263:     ip = uc->uc_mcontext.sc_ip;
                   1264:     switch (host_signum) {
                   1265:       case SIGILL:
                   1266:       case SIGFPE:
                   1267:       case SIGSEGV:
                   1268:       case SIGBUS:
                   1269:       case SIGTRAP:
                   1270:          if (info->si_code && (info->si_flags & __ISR_VALID))
                   1271:              /* ISR.W (write-access) is bit 33:  */
                   1272:              is_write = (info->si_isr >> 33) & 1;
                   1273:          break;
                   1274: 
                   1275:       default:
                   1276:          break;
                   1277:     }
                   1278:     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
                   1279:                              is_write,
                   1280:                              &uc->uc_sigmask, puc);
                   1281: }
                   1282: 
                   1283: #elif defined(__s390__)
                   1284: 
                   1285: int cpu_signal_handler(int host_signum, struct siginfo *info, 
                   1286:                        void *puc)
                   1287: {
                   1288:     struct ucontext *uc = puc;
                   1289:     unsigned long pc;
                   1290:     int is_write;
                   1291:     
                   1292:     pc = uc->uc_mcontext.psw.addr;
                   1293:     /* XXX: compute is_write */
                   1294:     is_write = 0;
                   1295:     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                   1296:                              is_write,
                   1297:                              &uc->uc_sigmask, puc);
                   1298: }
                   1299: 
                   1300: #else
                   1301: 
                   1302: #error host CPU specific signal handler needed
                   1303: 
                   1304: #endif
                   1305: 
                   1306: #endif /* !defined(CONFIG_SOFTMMU) */

unix.superglobalmegacorp.com