📄 cpu-exec.c
字号:
"m" (*(uint8_t *)offsetof(CPUState, regs[6])), "m" (*(uint8_t *)offsetof(CPUState, regs[7])), "m" (*(uint8_t *)offsetof(CPUState, cc_src)), "m" (*(uint8_t *)offsetof(CPUState, tmp0)), "a" (gen_func), "m" (*(uint8_t *)offsetof(CPUState, df)), "m" (*(uint8_t *)offsetof(CPUState, saved_esp)) : "%ecx", "%edx" ); }}#elif defined(__ia64) struct fptr { void *ip; void *gp; } fp; fp.ip = tc_ptr; fp.gp = code_gen_buffer + 2 * (1 << 20); (*(void (*)(void)) &fp)();#else gen_func();#endif env->current_tb = NULL; /* reset soft MMU for next block (it can currently only be set by a memory fault) */#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU) if (env->hflags & HF_SOFTMMU_MASK) { env->hflags &= ~HF_SOFTMMU_MASK; /* do not allow linking to another block */ T0 = 0; }#endif#if defined(USE_KQEMU)#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000) if (kqemu_is_ok(env) && (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) { cpu_loop_exit(); }#endif } } else { env_to_regs(); } } /* for(;;) */#if defined(TARGET_I386)#if defined(USE_CODE_COPY) if (env->native_fp_regs) { save_native_fp_state(env); }#endif /* restore flags in standard format */ env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); /* restore global registers */#ifdef reg_EAX EAX = saved_EAX;#endif#ifdef reg_ECX ECX = saved_ECX;#endif#ifdef reg_EDX EDX = saved_EDX;#endif#ifdef reg_EBX EBX = saved_EBX;#endif#ifdef reg_ESP ESP = saved_ESP;#endif#ifdef reg_EBP EBP = saved_EBP;#endif#ifdef reg_ESI ESI = saved_ESI;#endif#ifdef reg_EDI EDI = saved_EDI;#endif#elif defined(TARGET_ARM) /* XXX: Save/restore host fpu exception state?. */#elif defined(TARGET_SPARC)#if defined(reg_REGWPTR) REGWPTR = saved_regwptr;#endif#elif defined(TARGET_PPC)#elif defined(TARGET_MIPS)#elif defined(TARGET_SH4) /* XXXXX */#else#error unsupported target CPU#endif#ifdef __sparc__ asm volatile ("mov %0, %%i7" : : "r" (saved_i7));#endif T0 = saved_T0; T1 = saved_T1;#if defined(reg_T2) T2 = saved_T2;#endif env = saved_env; /* fail safe : never use cpu_single_env outside cpu_exec() */ cpu_single_env = NULL; return ret;}/* must only be called from the generated code as an exception can be generated */void tb_invalidate_page_range(target_ulong start, target_ulong end){ /* XXX: cannot enable it yet because it yields to MMU exception where NIP != read address on PowerPC */#if 0 target_ulong phys_addr; phys_addr = get_phys_addr_code(env, start); tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);#endif}#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector){ CPUX86State *saved_env; saved_env = env; env = s; if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) { selector &= 0xffff; cpu_x86_load_seg_cache(env, seg_reg, selector, (selector << 4), 0xffff, 0); } else { load_seg(seg_reg, selector); } env = saved_env;}void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32){ CPUX86State *saved_env; saved_env = env; env = s; helper_fsave((target_ulong)ptr, data32); env = saved_env;}void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32){ CPUX86State *saved_env; saved_env = env; env = s; helper_frstor((target_ulong)ptr, data32); env = saved_env;}#endif /* TARGET_I386 */#if !defined(CONFIG_SOFTMMU)#if defined(TARGET_I386)/* 'pc' is the host PC at which the exception was raised. 'address' is the effective address of the memory exception. 'is_write' is 1 if a write caused the exception and otherwise 0'. 'old_set' is the signal set which should be restored */static inline int handle_cpu_signal(unsigned long pc, unsigned long address, int is_write, sigset_t *old_set, void *puc){ TranslationBlock *tb; int ret; if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */#if defined(DEBUG_SIGNAL) qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set);#endif /* XXX: locking issue */ if (is_write && page_unprotect(h2g(address), pc, puc)) { return 1; } /* see if it is an MMU fault */ ret = cpu_x86_handle_mmu_fault(env, address, is_write, ((env->hflags & HF_CPL_MASK) == 3), 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) return 1; /* the MMU fault was handled without causing real CPU fault */ /* now we have a real cpu fault */ tb = tb_find_pc(pc); if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ cpu_restore_state(tb, env, pc, puc); } if (ret == 1) {#if 0 printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", env->eip, env->cr[2], env->error_code);#endif /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); raise_exception_err(env->exception_index, env->error_code); } else { /* activate soft MMU for this block */ env->hflags |= HF_SOFTMMU_MASK; cpu_resume_from_signal(env, puc); } /* never comes here */ return 1;}#elif defined(TARGET_ARM)static inline int handle_cpu_signal(unsigned long pc, unsigned long address, int is_write, sigset_t *old_set, void *puc){ TranslationBlock *tb; int ret; if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */#if defined(DEBUG_SIGNAL) printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set);#endif /* XXX: locking issue */ if (is_write && page_unprotect(h2g(address), pc, puc)) { return 1; } /* see if it is an MMU fault */ ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) return 1; /* the MMU fault was handled without causing real CPU fault */ /* now we have a real cpu fault */ tb = tb_find_pc(pc); if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ cpu_restore_state(tb, env, pc, puc); } /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); cpu_loop_exit();}#elif defined(TARGET_SPARC)static inline int handle_cpu_signal(unsigned long pc, unsigned long address, int is_write, sigset_t *old_set, void *puc){ TranslationBlock *tb; int ret; if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */#if defined(DEBUG_SIGNAL) printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set);#endif /* XXX: locking issue */ if (is_write && page_unprotect(h2g(address), pc, puc)) { return 1; } /* see if it is an MMU fault */ ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) return 1; /* the MMU fault was handled without causing real CPU fault */ /* now we have a real cpu fault */ tb = tb_find_pc(pc); if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ cpu_restore_state(tb, env, pc, puc); } /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); cpu_loop_exit();}#elif defined (TARGET_PPC)static inline int handle_cpu_signal(unsigned long pc, unsigned long address, int is_write, sigset_t *old_set, void *puc){ TranslationBlock *tb; int ret; if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */#if defined(DEBUG_SIGNAL) printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set);#endif /* XXX: locking issue */ if (is_write && page_unprotect(h2g(address), pc, puc)) { return 1; } /* see if it is an MMU fault */ ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) return 1; /* the MMU fault was handled without causing real CPU fault */ /* now we have a real cpu fault */ tb = tb_find_pc(pc); if (tb) { /* the PC is inside the translated code. It means that we have a virtual CPU fault */ cpu_restore_state(tb, env, pc, puc); } if (ret == 1) {#if 0 printf("PF exception: NIP=0x%08x error=0x%x %p\n", env->nip, env->error_code, tb);#endif /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); do_raise_exception_err(env->exception_index, env->error_code); } else { /* activate soft MMU for this block */ cpu_resume_from_signal(env, puc); } /* never comes here */ return 1;}#elif defined (TARGET_MIPS)static inline int handle_cpu_signal(unsigned long pc, unsigned long address, int is_write, sigset_t *old_set, void *puc){ TranslationBlock *tb; int ret; if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */#if defined(DEBUG_SIGNAL) printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set);#endif /* XXX: locking issue */ if (is_write && page_unprotect(h2g(address), pc, puc)) { return 1; } /* see if it is an MMU fault */ ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0); if (ret < 0) return 0; /* not an MMU fault */ if (ret == 0) return 1; /* the MMU fault was handled without causing real CPU fault */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -