From 632b853761d5b930c94dd8a45548af489e1e0f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 2 Mar 2018 09:36:41 -0500 Subject: [PATCH] tcg: remove global exit_request There are now only two uses of the global exit_request left. The first ensures we exit the run_loop when we first start to process pending work and in the kick handler. This is just as easily done by setting the first_cpu->exit_request flag. The second use is in the round robin kick routine. The global exit_request ensured every vCPU would set its local exit_request and cause a full exit of the loop. Now the iothread isn't being held while running we can just rely on the kick handler to push us out as intended. We lightly re-factor the main vCPU thread to ensure cpu->exit_requests cause us to exit the main loop and process any IO requests that might come along. As an cpu->exit_request may legitimately get squashed while processing the EXCP_INTERRUPT exception we also check cpu->queued_work_first to ensure queued work is expedited as soon as possible. Backports commit e5143e30fb87fbf179029387f83f98a5a9b27f19 from qemu --- include/uc_priv.h | 1 - qemu/cpu-exec.c | 20 +++++++------------- qemu/cpus.c | 13 ++++++------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index a3036ada..3b8d85a6 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -193,7 +193,6 @@ struct uc_struct { // qemu/cpu-exec.c BounceBuffer bounce; - volatile sig_atomic_t exit_request; CPUState *tcg_current_rr_cpu; // qemu/memory.c diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index 9419e48e..3a35e843 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -400,15 +400,13 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, *tb_exit = ret & TB_EXIT_MASK; switch (*tb_exit) { case TB_EXIT_REQUESTED: - /* Something asked us to stop executing - * chained TBs; just continue round the main - * loop. Whatever requested the exit will also - * 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 zeroing of tcg_exit_req (see cpu_tb_exec) - * comes before the next read of cpu->exit_request - * or cpu->interrupt_request. + /* Something asked us to stop executing chained TBs; just + * continue round the main loop. Whatever requested the exit + * will also have set something else (eg interrupt_request) + * which we will handle next time around the loop. But we + * need to ensure the tcg_exit_req read in generated code + * comes before the next read of cpu->exit_request or + * cpu->interrupt_request. */ smp_mb(); *last_tb = NULL; @@ -494,10 +492,6 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu) atomic_mb_set(&uc->current_cpu, cpu); atomic_mb_set(&uc->tcg_current_rr_cpu, cpu); - if (unlikely(atomic_mb_read(&uc->exit_request))) { - cpu->exit_request = 1; - } - cc->cpu_exec_enter(cpu); cpu->exception_index = -1; env->invalid_error = UC_ERR_OK; diff --git a/qemu/cpus.c b/qemu/cpus.c index c9f2ea67..a4841a2a 100644 --- a/qemu/cpus.c +++ b/qemu/cpus.c @@ -150,7 +150,7 @@ static bool tcg_exec_all(struct uc_struct* uc) { int r; bool finish = false; - while (!uc->exit_request) { + while (!uc->cpu->exit_request) { CPUState *cpu = uc->cpu; CPUArchState *env = cpu->env_ptr; @@ -165,38 +165,37 @@ static bool tcg_exec_all(struct uc_struct* uc) // reset stop_request uc->stop_request = false; } else if (uc->stop_request) { - //printf(">>> got STOP request!!!\n"); finish = true; break; } // save invalid memory access error & quit if (env->invalid_error) { - // printf(">>> invalid memory accessed, STOP = %u!!!\n", env->invalid_error); uc->invalid_addr = env->invalid_addr; uc->invalid_error = env->invalid_error; finish = true; break; } - // printf(">>> stop with r = %x, HLT=%x\n", r, EXCP_HLT); if (r == EXCP_DEBUG) { cpu_handle_guest_debug(cpu); break; } if (r == EXCP_HLT) { - //printf(">>> got HLT!!!\n"); finish = true; break; } else if (r == EXCP_ATOMIC) { cpu_exec_step_atomic(uc, cpu); } } else if (cpu->stop || cpu->stopped) { - printf(">>> got stopped!!!\n"); + printf(">>> got stopped!!!\n"); break; } } - uc->exit_request = 0; + + if (uc->cpu && uc->cpu->exit_request) { + atomic_mb_set(&uc->cpu->exit_request, 0); + } return finish; }