diff options
Diffstat (limited to 'cpu-exec.c')
-rw-r--r-- | cpu-exec.c | 114 |
1 files changed, 59 insertions, 55 deletions
diff --git a/cpu-exec.c b/cpu-exec.c index 1b0f617c19..2f54054d8c 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -23,29 +23,22 @@ #include "qemu/atomic.h" #include "sysemu/qtest.h" -bool qemu_cpu_has_work(CPUState *cpu) +void cpu_loop_exit(CPUState *cpu) { - return cpu_has_work(cpu); -} - -void cpu_loop_exit(CPUArchState *env) -{ - CPUState *cpu = ENV_GET_CPU(env); - cpu->current_tb = NULL; - siglongjmp(env->jmp_env, 1); + siglongjmp(cpu->jmp_env, 1); } /* exit the current TB from a signal handler. The host registers are restored in a state compatible with the CPU emulator */ #if defined(CONFIG_SOFTMMU) -void cpu_resume_from_signal(CPUArchState *env, void *puc) +void cpu_resume_from_signal(CPUState *cpu, void *puc) { /* XXX: restore cpu registers saved in host registers */ - env->exception_index = -1; - siglongjmp(env->jmp_env, 1); + cpu->exception_index = -1; + siglongjmp(cpu->jmp_env, 1); } #endif @@ -108,7 +101,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles, if (max_cycles > CF_COUNT_MASK) max_cycles = CF_COUNT_MASK; - tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, + tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, max_cycles); cpu->current_tb = tb; /* execute the generated code */ @@ -123,6 +116,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong cs_base, uint64_t flags) { + CPUState *cpu = ENV_GET_CPU(env); TranslationBlock *tb, **ptb1; unsigned int h; tb_page_addr_t phys_pc, phys_page1; @@ -160,7 +154,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, } not_found: /* if no translated code available, then translate it now */ - tb = tb_gen_code(env, pc, cs_base, flags, 0); + tb = tb_gen_code(cpu, pc, cs_base, flags, 0); found: /* Move the last found TB to the head of the list */ @@ -170,12 +164,13 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, tcg_ctx.tb_ctx.tb_phys_hash[h] = tb; } /* we add the TB in the virtual pc hash table */ - env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; + cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; return tb; } static inline TranslationBlock *tb_find_fast(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); TranslationBlock *tb; target_ulong cs_base, pc; int flags; @@ -184,7 +179,7 @@ static inline TranslationBlock *tb_find_fast(CPUArchState *env) always be the same before a given translated block is executed. */ cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); - tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; + tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || tb->flags != flags)) { tb = tb_find_slow(env, pc, cs_base, flags); @@ -201,10 +196,11 @@ void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler) static void cpu_handle_debug_exception(CPUArchState *env) { + CPUState *cpu = ENV_GET_CPU(env); CPUWatchpoint *wp; - if (!env->watchpoint_hit) { - QTAILQ_FOREACH(wp, &env->watchpoints, entry) { + if (!cpu->watchpoint_hit) { + QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { wp->flags &= ~BP_WATCHPOINT_HIT; } } @@ -231,6 +227,8 @@ int cpu_exec(CPUArchState *env) TranslationBlock *tb; uint8_t *tc_ptr; uintptr_t next_tb; + /* This must be volatile so it is not trashed by longjmp() */ + volatile bool have_tb_lock = false; if (cpu->halted) { if (!cpu_has_work(cpu)) { @@ -283,16 +281,16 @@ int cpu_exec(CPUArchState *env) #else #error unsupported target CPU #endif - env->exception_index = -1; + cpu->exception_index = -1; /* prepare setjmp context for exception handling */ for(;;) { - if (sigsetjmp(env->jmp_env, 0) == 0) { + if (sigsetjmp(cpu->jmp_env, 0) == 0) { /* if an exception is pending, we execute it here */ - if (env->exception_index >= 0) { - if (env->exception_index >= EXCP_INTERRUPT) { + if (cpu->exception_index >= 0) { + if (cpu->exception_index >= EXCP_INTERRUPT) { /* exit request from the cpu execution loop */ - ret = env->exception_index; + ret = cpu->exception_index; if (ret == EXCP_DEBUG) { cpu_handle_debug_exception(env); } @@ -305,11 +303,11 @@ int cpu_exec(CPUArchState *env) #if defined(TARGET_I386) cc->do_interrupt(cpu); #endif - ret = env->exception_index; + ret = cpu->exception_index; break; #else cc->do_interrupt(cpu); - env->exception_index = -1; + cpu->exception_index = -1; #endif } } @@ -324,8 +322,8 @@ int cpu_exec(CPUArchState *env) } if (interrupt_request & CPU_INTERRUPT_DEBUG) { cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG; - env->exception_index = EXCP_DEBUG; - cpu_loop_exit(env); + cpu->exception_index = EXCP_DEBUG; + cpu_loop_exit(cpu); } #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \ defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \ @@ -333,8 +331,8 @@ int cpu_exec(CPUArchState *env) if (interrupt_request & CPU_INTERRUPT_HALT) { cpu->interrupt_request &= ~CPU_INTERRUPT_HALT; cpu->halted = 1; - env->exception_index = EXCP_HLT; - cpu_loop_exit(env); + cpu->exception_index = EXCP_HLT; + cpu_loop_exit(cpu); } #endif #if defined(TARGET_I386) @@ -348,8 +346,8 @@ int cpu_exec(CPUArchState *env) cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0); do_cpu_init(x86_cpu); - env->exception_index = EXCP_HALTED; - cpu_loop_exit(env); + cpu->exception_index = EXCP_HALTED; + cpu_loop_exit(cpu); } else if (interrupt_request & CPU_INTERRUPT_SIPI) { do_cpu_sipi(x86_cpu); } else if (env->hflags2 & HF2_GIF_MASK) { @@ -420,7 +418,7 @@ int cpu_exec(CPUArchState *env) #elif defined(TARGET_LM32) if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->ie & IE_IE)) { - env->exception_index = EXCP_IRQ; + cpu->exception_index = EXCP_IRQ; cc->do_interrupt(cpu); next_tb = 0; } @@ -429,7 +427,7 @@ int cpu_exec(CPUArchState *env) && (env->sregs[SR_MSR] & MSR_IE) && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP)) && !(env->iflags & (D_FLAG | IMM_FLAG))) { - env->exception_index = EXCP_IRQ; + cpu->exception_index = EXCP_IRQ; cc->do_interrupt(cpu); next_tb = 0; } @@ -437,7 +435,7 @@ int cpu_exec(CPUArchState *env) if ((interrupt_request & CPU_INTERRUPT_HARD) && cpu_mips_hw_interrupts_pending(env)) { /* Raise it */ - env->exception_index = EXCP_EXT_INTERRUPT; + cpu->exception_index = EXCP_EXT_INTERRUPT; env->error_code = 0; cc->do_interrupt(cpu); next_tb = 0; @@ -454,7 +452,7 @@ int cpu_exec(CPUArchState *env) idx = EXCP_TICK; } if (idx >= 0) { - env->exception_index = idx; + cpu->exception_index = idx; cc->do_interrupt(cpu); next_tb = 0; } @@ -469,7 +467,7 @@ int cpu_exec(CPUArchState *env) if (((type == TT_EXTINT) && cpu_pil_allowed(env, pil)) || type != TT_EXTINT) { - env->exception_index = env->interrupt_index; + cpu->exception_index = env->interrupt_index; cc->do_interrupt(cpu); next_tb = 0; } @@ -478,7 +476,7 @@ int cpu_exec(CPUArchState *env) #elif defined(TARGET_ARM) if (interrupt_request & CPU_INTERRUPT_FIQ && !(env->daif & PSTATE_F)) { - env->exception_index = EXCP_FIQ; + cpu->exception_index = EXCP_FIQ; cc->do_interrupt(cpu); next_tb = 0; } @@ -494,14 +492,14 @@ int cpu_exec(CPUArchState *env) if (interrupt_request & CPU_INTERRUPT_HARD && ((IS_M(env) && env->regs[15] < 0xfffffff0) || !(env->daif & PSTATE_I))) { - env->exception_index = EXCP_IRQ; + cpu->exception_index = EXCP_IRQ; cc->do_interrupt(cpu); next_tb = 0; } #elif defined(TARGET_UNICORE32) if (interrupt_request & CPU_INTERRUPT_HARD && !(env->uncached_asr & ASR_I)) { - env->exception_index = UC32_EXCP_INTR; + cpu->exception_index = UC32_EXCP_INTR; cc->do_interrupt(cpu); next_tb = 0; } @@ -536,7 +534,7 @@ int cpu_exec(CPUArchState *env) } } if (idx >= 0) { - env->exception_index = idx; + cpu->exception_index = idx; env->error_code = 0; cc->do_interrupt(cpu); next_tb = 0; @@ -546,7 +544,7 @@ int cpu_exec(CPUArchState *env) if (interrupt_request & CPU_INTERRUPT_HARD && (env->pregs[PR_CCS] & I_FLAG) && !env->locked_irq) { - env->exception_index = EXCP_IRQ; + cpu->exception_index = EXCP_IRQ; cc->do_interrupt(cpu); next_tb = 0; } @@ -558,7 +556,7 @@ int cpu_exec(CPUArchState *env) m_flag_archval = M_FLAG_V32; } if ((env->pregs[PR_CCS] & m_flag_archval)) { - env->exception_index = EXCP_NMI; + cpu->exception_index = EXCP_NMI; cc->do_interrupt(cpu); next_tb = 0; } @@ -572,7 +570,7 @@ int cpu_exec(CPUArchState *env) hardware doesn't rely on this, so we provide/save the vector when the interrupt is first signalled. */ - env->exception_index = env->pending_vector; + cpu->exception_index = env->pending_vector; do_interrupt_m68k_hardirq(env); next_tb = 0; } @@ -584,7 +582,7 @@ int cpu_exec(CPUArchState *env) } #elif defined(TARGET_XTENSA) if (interrupt_request & CPU_INTERRUPT_HARD) { - env->exception_index = EXC_IRQ; + cpu->exception_index = EXC_IRQ; cc->do_interrupt(cpu); next_tb = 0; } @@ -600,10 +598,11 @@ int cpu_exec(CPUArchState *env) } if (unlikely(cpu->exit_request)) { cpu->exit_request = 0; - env->exception_index = EXCP_INTERRUPT; - cpu_loop_exit(env); + cpu->exception_index = EXCP_INTERRUPT; + cpu_loop_exit(cpu); } spin_lock(&tcg_ctx.tb_ctx.tb_lock); + have_tb_lock = true; tb = tb_find_fast(env); /* Note: we do it here to avoid a gcc bug on Mac OS X when doing it in tb_find_slow */ @@ -625,6 +624,7 @@ int cpu_exec(CPUArchState *env) tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK), next_tb & TB_EXIT_MASK, tb); } + have_tb_lock = false; spin_unlock(&tcg_ctx.tb_ctx.tb_lock); /* cpu_interrupt might be called while translating the @@ -654,25 +654,25 @@ int cpu_exec(CPUArchState *env) /* Instruction counter expired. */ int insns_left; tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK); - insns_left = env->icount_decr.u32; - if (env->icount_extra && insns_left >= 0) { + insns_left = cpu->icount_decr.u32; + if (cpu->icount_extra && insns_left >= 0) { /* Refill decrementer and continue execution. */ - env->icount_extra += insns_left; - if (env->icount_extra > 0xffff) { + cpu->icount_extra += insns_left; + if (cpu->icount_extra > 0xffff) { insns_left = 0xffff; } else { - insns_left = env->icount_extra; + insns_left = cpu->icount_extra; } - env->icount_extra -= insns_left; - env->icount_decr.u16.low = insns_left; + cpu->icount_extra -= insns_left; + cpu->icount_decr.u16.low = insns_left; } else { if (insns_left > 0) { /* Execute remaining instructions. */ cpu_exec_nocache(env, insns_left, tb); } - env->exception_index = EXCP_INTERRUPT; + cpu->exception_index = EXCP_INTERRUPT; next_tb = 0; - cpu_loop_exit(env); + cpu_loop_exit(cpu); } break; } @@ -696,6 +696,10 @@ int cpu_exec(CPUArchState *env) #ifdef TARGET_I386 x86_cpu = X86_CPU(cpu); #endif + if (have_tb_lock) { + spin_unlock(&tcg_ctx.tb_ctx.tb_lock); + have_tb_lock = false; + } } } /* for(;;) */ |