Message ID | 20210210221053.18050-18-alex.bennee@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | plugins/next pre-PR (hwprofile, regression fixes, icount count fix) | expand |
On 2/10/21 2:10 PM, Alex Bennée wrote: > Again there is no reason to jump through the nocache hoops to execute > a single instruction block. We do have to add an additional wrinkle to > the cpu_handle_interrupt case to ensure we let through a TB where we > have specifically disabled icount for the block. Can you say more about this? Because... > if (unlikely(qatomic_read(&cpu->exit_request)) > || (icount_enabled() > + && (cpu->cflags_next_tb == -1 || cpu->cflags_next_tb & CF_USE_ICOUNT) > && cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0)) { ... this does not appear to match. You're checking that icount has been explicitly *enabled*? Or am I reading the logic backward and only if icount is enabled will we take EXCP_INTERRUPT? r~
Richard Henderson <richard.henderson@linaro.org> writes: > On 2/10/21 2:10 PM, Alex Bennée wrote: >> Again there is no reason to jump through the nocache hoops to execute >> a single instruction block. We do have to add an additional wrinkle to >> the cpu_handle_interrupt case to ensure we let through a TB where we >> have specifically disabled icount for the block. > > Can you say more about this? Because... > >> if (unlikely(qatomic_read(&cpu->exit_request)) >> || (icount_enabled() >> + && (cpu->cflags_next_tb == -1 || cpu->cflags_next_tb & CF_USE_ICOUNT) >> && cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0)) { > > ... this does not appear to match. You're checking that icount has been > explicitly *enabled*? If icount has been enabled and we are using the default cflags or enabled and we have the explicit CF_ICOUNT. The replay exception leg explicitly disables icount because otherwise we'd never actually execute the block because we have a budget of 0 cycles left. Previously we ran that block at the exception handling point - now we fall through and have to make sure we don't trigger an IRQ. > Or am I reading the logic backward and only if icount is > enabled will we take EXCP_INTERRUPT? Or I guess we have an exit_request which hasn't been handled yet but there is no EXCP_ pending. > > > r~ -- Alex Bennée
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 5b6a4fe84b..438fece73b 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -224,40 +224,6 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) return last_tb; } -#ifndef CONFIG_USER_ONLY -/* Execute the code without caching the generated code. An interpreter - could be used if available. */ -static void cpu_exec_nocache(CPUState *cpu, int max_cycles, - TranslationBlock *orig_tb, bool ignore_icount) -{ - TranslationBlock *tb; - uint32_t cflags = curr_cflags() | CF_NOCACHE; - int tb_exit; - - if (ignore_icount) { - cflags &= ~CF_USE_ICOUNT; - } - - /* Should never happen. - We only end up here when an existing TB is too long. */ - cflags |= MIN(max_cycles, CF_COUNT_MASK); - - mmap_lock(); - tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, - orig_tb->flags, cflags); - tb->orig_tb = orig_tb; - mmap_unlock(); - - /* execute the generated code */ - trace_exec_tb_nocache(tb, tb->pc); - cpu_tb_exec(cpu, tb, &tb_exit); - - mmap_lock(); - tb_phys_invalidate(tb, -1); - mmap_unlock(); - tcg_tb_remove(tb); -} -#endif static void cpu_exec_enter(CPUState *cpu) { @@ -524,15 +490,12 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret) #ifndef CONFIG_USER_ONLY if (replay_has_exception() && cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) { - /* try to cause an exception pending in the log */ - cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0, curr_cflags()), true); + /* Execute just one insn to trigger exception pending in the log */ + cpu->cflags_next_tb = (curr_cflags() & ~CF_USE_ICOUNT) | 1; } #endif - if (cpu->exception_index < 0) { - return false; - } + return false; } - if (cpu->exception_index >= EXCP_INTERRUPT) { /* exit request from the cpu execution loop */ *ret = cpu->exception_index; @@ -688,6 +651,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, /* Finally, check if we need to exit to the main loop. */ if (unlikely(qatomic_read(&cpu->exit_request)) || (icount_enabled() + && (cpu->cflags_next_tb == -1 || cpu->cflags_next_tb & CF_USE_ICOUNT) && cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0)) { qatomic_set(&cpu->exit_request, 0); if (cpu->exception_index == -1) {
Again there is no reason to jump through the nocache hoops to execute a single instruction block. We do have to add an additional wrinkle to the cpu_handle_interrupt case to ensure we let through a TB where we have specifically disabled icount for the block. As the last user of cpu_exec_nocache we can now remove the function. Further clean-up will follow in subsequent patches. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20210209182749.31323-9-alex.bennee@linaro.org> --- accel/tcg/cpu-exec.c | 44 ++++---------------------------------------- 1 file changed, 4 insertions(+), 40 deletions(-) -- 2.20.1