#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
static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
{
CPUArchState *env = cpu->env_ptr;
- uintptr_t next_tb = tcg_qemu_tb_exec(env, tb_ptr);
+ uintptr_t next_tb;
+
+#if defined(DEBUG_DISAS)
+ if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
+#if defined(TARGET_I386)
+ log_cpu_state(cpu, CPU_DUMP_CCOP);
+#elif defined(TARGET_M68K)
+ /* ??? Should not modify env state for dumping. */
+ cpu_m68k_flush_flags(env, env->cc_op);
+ env->cc_op = CC_OP_FLAGS;
+ env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4);
+ log_cpu_state(cpu, 0);
+#else
+ log_cpu_state(cpu, 0);
+#endif
+ }
+#endif /* DEBUG_DISAS */
+
+ next_tb = tcg_qemu_tb_exec(env, tb_ptr);
if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
/* We didn't start executing this TB (eg because the instruction
* counter hit zero); we must restore the guest PC to the address
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 */
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;
}
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 */
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;
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);
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;
}
}
#if !(defined(CONFIG_USER_ONLY) && \
(defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
CPUClass *cc = CPU_GET_CLASS(cpu);
+#endif
+#ifdef TARGET_I386
+ X86CPU *x86_cpu = X86_CPU(cpu);
#endif
int ret, interrupt_request;
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)) {
#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);
}
#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
}
}
}
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) || \
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)
+ if (interrupt_request & CPU_INTERRUPT_INIT) {
+ cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
+ do_cpu_init(x86_cpu);
+ cpu->exception_index = EXCP_HALTED;
+ cpu_loop_exit(cpu);
+ }
+#else
+ if (interrupt_request & CPU_INTERRUPT_RESET) {
+ cpu_reset(cpu);
}
#endif
#if defined(TARGET_I386)
#if !defined(CONFIG_USER_ONLY)
if (interrupt_request & CPU_INTERRUPT_POLL) {
cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
- apic_poll_irq(env->apic_state);
+ apic_poll_irq(x86_cpu->apic_state);
}
#endif
- if (interrupt_request & CPU_INTERRUPT_INIT) {
- cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
- 0);
- do_cpu_init(x86_env_get_cpu(env));
- env->exception_index = EXCP_HALTED;
- cpu_loop_exit(env);
- } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
- do_cpu_sipi(x86_env_get_cpu(env));
+ if (interrupt_request & CPU_INTERRUPT_SIPI) {
+ do_cpu_sipi(x86_cpu);
} else if (env->hflags2 & HF2_GIF_MASK) {
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
0);
cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
- do_smm_enter(x86_env_get_cpu(env));
+ do_smm_enter(x86_cpu);
next_tb = 0;
} else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
!(env->hflags2 & HF2_NMI_MASK)) {
/* FIXME: this should respect TPR */
cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
0);
- intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
+ intno = ldl_phys(cpu->as,
+ env->vm_vmcb
+ + offsetof(struct vmcb,
+ control.int_vector));
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
do_interrupt_x86_hardirq(env, intno, 1);
cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
}
}
#elif defined(TARGET_PPC)
- if ((interrupt_request & CPU_INTERRUPT_RESET)) {
- cpu_reset(cpu);
- }
if (interrupt_request & CPU_INTERRUPT_HARD) {
ppc_hw_interrupt(env);
if (env->pending_interrupts == 0) {
#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;
}
&& (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;
}
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;
idx = EXCP_TICK;
}
if (idx >= 0) {
- env->exception_index = idx;
+ cpu->exception_index = idx;
cc->do_interrupt(cpu);
next_tb = 0;
}
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;
}
}
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
- && !(env->uncached_cpsr & CPSR_F)) {
- env->exception_index = EXCP_FIQ;
+ && !(env->daif & PSTATE_F)) {
+ cpu->exception_index = EXCP_FIQ;
cc->do_interrupt(cpu);
next_tb = 0;
}
pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD
&& ((IS_M(env) && env->regs[15] < 0xfffffff0)
- || !(env->uncached_cpsr & CPSR_I))) {
- env->exception_index = EXCP_IRQ;
+ || !(env->daif & PSTATE_I))) {
+ 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;
}
}
}
if (idx >= 0) {
- env->exception_index = idx;
+ cpu->exception_index = idx;
env->error_code = 0;
cc->do_interrupt(cpu);
next_tb = 0;
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;
}
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;
}
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;
}
}
#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;
}
}
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);
}
-#if defined(DEBUG_DISAS)
- if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
- /* restore flags in standard format */
-#if defined(TARGET_I386)
- log_cpu_state(cpu, CPU_DUMP_CCOP);
-#elif defined(TARGET_M68K)
- cpu_m68k_flush_flags(env, env->cc_op);
- env->cc_op = CC_OP_FLAGS;
- env->sr = (env->sr & 0xffe0)
- | env->cc_dest | (env->cc_x << 4);
- log_cpu_state(cpu, 0);
-#else
- log_cpu_state(cpu, 0);
-#endif
- }
-#endif /* DEBUG_DISAS */
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 */
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
/* 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;
}
* local variables as longjmp is marked 'noreturn'. */
cpu = current_cpu;
env = cpu->env_ptr;
+#if !(defined(CONFIG_USER_ONLY) && \
+ (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
+ cc = CPU_GET_CLASS(cpu);
+#endif
+#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(;;) */