Annotation of qemu/cpu-exec.c, revision 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