X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=cpu-exec.c;h=38e5f02a307523d99134f4e2e6c51683bb10b45b;hb=7d2a35cc921ea4832083a7e8598461868bb538ce;hp=301be28bf74015ee24d9c1d923d89e561b3112a1;hpb=874ec3c5b3821bb964f9f37b2f930f2a9ce51652;p=mirror_qemu.git diff --git a/cpu-exec.c b/cpu-exec.c index 301be28bf7..38e5f02a30 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 @@ -53,7 +46,25 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc) static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr) { CPUArchState *env = cpu->env_ptr; - tcg_target_ulong 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 @@ -90,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 */ @@ -105,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; @@ -142,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 */ @@ -152,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; @@ -166,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); @@ -183,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; } } @@ -205,11 +219,16 @@ int cpu_exec(CPUArchState *env) #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; - tcg_target_ulong next_tb; + 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)) { @@ -262,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); } @@ -284,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 } } @@ -303,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) || \ @@ -312,32 +331,38 @@ 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) + 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)) { @@ -374,7 +399,10 @@ int cpu_exec(CPUArchState *env) /* 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; @@ -383,9 +411,6 @@ int cpu_exec(CPUArchState *env) } } #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) { @@ -396,7 +421,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; } @@ -405,7 +430,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; } @@ -413,7 +438,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; @@ -430,7 +455,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; } @@ -445,7 +470,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; } @@ -453,8 +478,8 @@ int cpu_exec(CPUArchState *env) } #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; } @@ -469,15 +494,15 @@ int cpu_exec(CPUArchState *env) 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; } @@ -512,7 +537,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; @@ -522,7 +547,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; } @@ -534,7 +559,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; } @@ -548,7 +573,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; } @@ -560,7 +585,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; } @@ -576,26 +601,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); } -#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 */ @@ -617,6 +627,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 @@ -646,25 +657,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; } @@ -681,6 +692,17 @@ int cpu_exec(CPUArchState *env) * 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(;;) */