On 2026-08-19 23:40, Peter Maydell wrote:
On Wed, 19 Aug 2026 at 21:14, Richard Henderson
<[email protected]> wrote:
On 8/19/26 07:56, Philippe Mathieu-Daudé wrote:
Refactor the target-specific halt-to-execution transition
logic (disable WFE/WFI timers, clear the halt_reason flag)
into a separate arm_cpu_transition_halt_to_exec() function.
Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
---
target/arm/cpu.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 77aa78f00e2..8e9b584559d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -870,18 +870,26 @@ static bool arm_cpu_internal_is_big_endian(CPUState *cs)
}
#ifdef CONFIG_TCG
+static void arm_cpu_transition_halt_to_exec(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ assert(cpu_has_work(cs));
In reply to patch 11 you suggest removing this.
I wonder why you added it in the first place.
Does the accel loop enforce that we hold the BQL when
arm_cpu_exec_halt() is called?
For MTTCG:
mttcg_cpu_thread_fn()
{
bql_lock();
while (1)
qemu_process_cpu_events(cpu);
if (cpu_can_run(cpu)) {
bql_unlock();
tcg_cpu_exec(cpu);
cpu_exec(cpu);
if (cpu->halted) {
cpu_has_work_after_processing_async_events(cpu);
process_async_events(cpu);
x86_cpu_process_async_events(); // APIC takes BQL
cpu_has_work(cpu);
transition_halt_to_exec(cpu);
arm_cpu_transition_halt_to_exec(); // timer_lock
x86_cpu_transition_halt_to_exec();
...
bql_lock();
...
}
void x86_cpu_process_async_events()
{
/* (BQL not held) */
if (cpu_test_interrupt()) {
bql_lock();
apic_poll_irq();
apic_sync_vapic();
apic_update_irq();
cpu_interrupt();
cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
bql_unlock();
}
}
void arm_cpu_transition_halt_to_exec()
{
/* (BQL not held) */
timer_del();
qemu_mutex_lock();
timer_del_locked();
qemu_mutex_unlock();
}
void x86_cpu_transition_halt_to_exec()
{
/* (BQL not held) */
do_interrupt_all();
handle_even_inj();
x86_ldl_phys(VMCB);
address_space_ldl_le(VMCB);
device MMIO?
x86_stl_phys(VMCB);
address_space_stl_le(VMCB);
device MMIO?
}
VMCB address is guest-controlled, it comes from the guest %EAX
register passed to the VMRUN instruction (see helper_vmrun).
(I'm not looking further at the SVM specification).
If not then the assertion
is racy, because something might get in and e.g. lower
an IRQ line so that cpu_has_work() is no longer true
(which would be fine -- it just means we made the decision
to wake up and that won vs the incoming interrupt).
On the one hand, if we don't have the BQL in has_work and
exec_halt then we should be a lot more careful about how
we code them (e.g. use of the right kind of atomics, and
there's no way the call to do_interrupt_all() in the x86
exec_halt can be safe without the BQL, surely).
On the other hand, if we do have the BQL in exec_halt
then why is the x86 implementation explicitly taking
the BQL when it calls apic_poll_irq()?
This analysis is similar before this series applied.
I don't have any idea how to proceed, I suppose from
here you expect Paolo / Richard to provide their feedback.