X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=cpu-exec.c;h=142a5862fc31ec74a1b7127e669b690da48c0c14;hb=0aeebc73b7976bae5cb7e9768e3d9a0fd9d634e8;hp=9400732137da85de5c146afc29f2058dec595f9e;hpb=5929d7e8a0e1f43333bc3528b50397ae8dd0fd6b;p=mirror_qemu.git diff --git a/cpu-exec.c b/cpu-exec.c index 9400732137..142a5862fc 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -18,7 +18,7 @@ */ #include "qemu/osdep.h" #include "cpu.h" -#include "trace.h" +#include "trace-root.h" #include "disas/disas.h" #include "exec/exec-all.h" #include "tcg.h" @@ -143,17 +143,20 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb) uint8_t *tb_ptr = itb->tc_ptr; qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc, - "Trace %p [" TARGET_FMT_lx "] %s\n", - itb->tc_ptr, itb->pc, lookup_symbol(itb->pc)); + "Trace %p [%d: " TARGET_FMT_lx "] %s\n", + itb->tc_ptr, cpu->cpu_index, itb->pc, + lookup_symbol(itb->pc)); #if defined(DEBUG_DISAS) if (qemu_loglevel_mask(CPU_LOG_TB_CPU) && qemu_log_in_addr_range(itb->pc)) { + qemu_log_lock(); #if defined(TARGET_I386) log_cpu_state(cpu, CPU_DUMP_CCOP); #else log_cpu_state(cpu, 0); #endif + qemu_log_unlock(); } #endif /* DEBUG_DISAS */ @@ -204,15 +207,21 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles, if (max_cycles > CF_COUNT_MASK) max_cycles = CF_COUNT_MASK; + tb_lock(); tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags, max_cycles | CF_NOCACHE | (ignore_icount ? CF_IGNORE_ICOUNT : 0)); tb->orig_tb = orig_tb; + tb_unlock(); + /* execute the generated code */ trace_exec_tb_nocache(tb, tb->pc); cpu_tb_exec(cpu, tb); + + tb_lock(); tb_phys_invalidate(tb, -1); tb_free(tb); + tb_unlock(); } #endif @@ -452,7 +461,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret) return false; } -static inline void cpu_handle_interrupt(CPUState *cpu, +static inline bool cpu_handle_interrupt(CPUState *cpu, TranslationBlock **last_tb) { CPUClass *cc = CPU_GET_CLASS(cpu); @@ -466,7 +475,7 @@ static inline void cpu_handle_interrupt(CPUState *cpu, if (interrupt_request & CPU_INTERRUPT_DEBUG) { cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG; cpu->exception_index = EXCP_DEBUG; - cpu_loop_exit(cpu); + return true; } if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) { /* Do nothing */ @@ -475,23 +484,23 @@ static inline void cpu_handle_interrupt(CPUState *cpu, cpu->interrupt_request &= ~CPU_INTERRUPT_HALT; cpu->halted = 1; cpu->exception_index = EXCP_HLT; - cpu_loop_exit(cpu); + return true; } #if defined(TARGET_I386) else if (interrupt_request & CPU_INTERRUPT_INIT) { X86CPU *x86_cpu = X86_CPU(cpu); CPUArchState *env = &x86_cpu->env; replay_interrupt(); - cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0); + cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0, 0); do_cpu_init(x86_cpu); cpu->exception_index = EXCP_HALTED; - cpu_loop_exit(cpu); + return true; } #else else if (interrupt_request & CPU_INTERRUPT_RESET) { replay_interrupt(); cpu_reset(cpu); - cpu_loop_exit(cpu); + return true; } #endif /* The target hook has 3 exit conditions: @@ -499,8 +508,8 @@ static inline void cpu_handle_interrupt(CPUState *cpu, True when it is, and we should restart on a new TB, and via longjmp via cpu_loop_exit. */ else { - replay_interrupt(); if (cc->cpu_exec_interrupt(cpu, interrupt_request)) { + replay_interrupt(); *last_tb = NULL; } /* The target hook may have updated the 'cpu->interrupt_request'; @@ -517,8 +526,10 @@ static inline void cpu_handle_interrupt(CPUState *cpu, if (unlikely(atomic_read(&cpu->exit_request) || replay_has_interrupt())) { atomic_set(&cpu->exit_request, 0); cpu->exception_index = EXCP_INTERRUPT; - cpu_loop_exit(cpu); + return true; } + + return false; } static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, @@ -533,7 +544,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, trace_exec_tb(tb, tb->pc); ret = cpu_tb_exec(cpu, tb); - *last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK); + tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK); *tb_exit = ret & TB_EXIT_MASK; switch (*tb_exit) { case TB_EXIT_REQUESTED: @@ -543,11 +554,11 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, * have set something else (eg exit_request or * interrupt_request) which we will handle * next time around the loop. But we need to - * ensure the tcg_exit_req read in generated code + * ensure the zeroing of tcg_exit_req (see cpu_tb_exec) * comes before the next read of cpu->exit_request * or cpu->interrupt_request. */ - smp_rmb(); + smp_mb(); *last_tb = NULL; break; case TB_EXIT_ICOUNT_EXPIRED: @@ -557,6 +568,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, abort(); #else int insns_left = cpu->icount_decr.u32; + *last_tb = NULL; if (cpu->icount_extra && insns_left >= 0) { /* Refill decrementer and continue execution. */ cpu->icount_extra += insns_left; @@ -566,17 +578,17 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, } else { if (insns_left > 0) { /* Execute remaining instructions. */ - cpu_exec_nocache(cpu, insns_left, *last_tb, false); + cpu_exec_nocache(cpu, insns_left, tb, false); align_clocks(sc, cpu); } cpu->exception_index = EXCP_INTERRUPT; - *last_tb = NULL; cpu_loop_exit(cpu); } break; #endif } default: + *last_tb = tb; break; } } @@ -612,42 +624,37 @@ int cpu_exec(CPUState *cpu) */ init_delay_params(&sc, cpu); - for(;;) { - /* prepare setjmp context for exception handling */ - if (sigsetjmp(cpu->jmp_env, 0) == 0) { - TranslationBlock *tb, *last_tb = NULL; - int tb_exit = 0; - - /* if an exception is pending, we execute it here */ - if (cpu_handle_exception(cpu, &ret)) { - break; - } - - for(;;) { - cpu_handle_interrupt(cpu, &last_tb); - tb = tb_find(cpu, last_tb, tb_exit); - cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit, &sc); - /* Try to align the host and virtual clocks - if the guest is in advance */ - align_clocks(&sc, cpu); - } /* for(;;) */ - } else { + /* prepare setjmp context for exception handling */ + if (sigsetjmp(cpu->jmp_env, 0) != 0) { #if defined(__clang__) || !QEMU_GNUC_PREREQ(4, 6) - /* Some compilers wrongly smash all local variables after - * siglongjmp. There were bug reports for gcc 4.5.0 and clang. - * Reload essential local variables here for those compilers. - * Newer versions of gcc would complain about this code (-Wclobbered). */ - cpu = current_cpu; - cc = CPU_GET_CLASS(cpu); + /* Some compilers wrongly smash all local variables after + * siglongjmp. There were bug reports for gcc 4.5.0 and clang. + * Reload essential local variables here for those compilers. + * Newer versions of gcc would complain about this code (-Wclobbered). */ + cpu = current_cpu; + cc = CPU_GET_CLASS(cpu); #else /* buggy compiler */ - /* Assert that the compiler does not smash local variables. */ - g_assert(cpu == current_cpu); - g_assert(cc == CPU_GET_CLASS(cpu)); + /* Assert that the compiler does not smash local variables. */ + g_assert(cpu == current_cpu); + g_assert(cc == CPU_GET_CLASS(cpu)); #endif /* buggy compiler */ - cpu->can_do_io = 1; - tb_lock_reset(); + cpu->can_do_io = 1; + tb_lock_reset(); + } + + /* if an exception is pending, we execute it here */ + while (!cpu_handle_exception(cpu, &ret)) { + TranslationBlock *last_tb = NULL; + int tb_exit = 0; + + while (!cpu_handle_interrupt(cpu, &last_tb)) { + TranslationBlock *tb = tb_find(cpu, last_tb, tb_exit); + cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit, &sc); + /* Try to align the host and virtual clocks + if the guest is in advance */ + align_clocks(&sc, cpu); } - } /* for(;;) */ + } cc->cpu_exec_exit(cpu); rcu_read_unlock();