diff mbox series

[v3,07/11] accel/tcg: Add do_interrupt() wrapper for targets to manage BQL

Message ID 20260902152044.31291-8-philmd@oss.qualcomm.com
State New
Headers show
Series accel/tcg: Push BQL down into per-target do_interrupt handlers | expand

Commit Message

Philippe Mathieu-Daudé Sept. 2, 2026, 3:20 p.m. UTC
Add TCGCPUOps::do_interrupt() as a wrapper that targets can
implement to control BQL locking independently. The existing
do_interrupt_locked() callback remains for BQL-held contexts.
This allows each target to decide when to acquire the BQL.

Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
 include/accel/tcg/cpu-ops.h | 14 ++++++++++++++
 accel/tcg/cpu-exec.c        | 12 ++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

Comments

Richard Henderson Sept. 13, 2026, 3:50 a.m. UTC | #1
On 9/2/26 05:20, Philippe Mathieu-Daudé wrote:
> Add TCGCPUOps::do_interrupt() as a wrapper that targets can
> implement to control BQL locking independently. The existing
> do_interrupt_locked() callback remains for BQL-held contexts.
> This allows each target to decide when to acquire the BQL.
> 
> Signed-off-by: Philippe Mathieu-Daudé<philmd@oss.qualcomm.com>
> ---
>   include/accel/tcg/cpu-ops.h | 14 ++++++++++++++
>   accel/tcg/cpu-exec.c        | 12 ++++++++----
>   2 files changed, 22 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~
diff mbox series

Patch

diff --git a/include/accel/tcg/cpu-ops.h b/include/accel/tcg/cpu-ops.h
index 2e97f79a373..e2e67f796f6 100644
--- a/include/accel/tcg/cpu-ops.h
+++ b/include/accel/tcg/cpu-ops.h
@@ -169,6 +169,20 @@  struct TCGCPUOps {
      */
     vaddr (*untagged_addr)(CPUState *cs, vaddr addr);
 #else
+    /**
+     * @do_interrupt: Deliver a pending exception/interrupt to the CPU
+     *
+     * Called when cs->exception_index contains the exception code to deliver.
+     * Updates CPU architectural state (usually before executing a guest
+     * exception handler).
+     *
+     * Called from cpu_handle_exception(). Implementations must acquire the
+     * BQL before modifying CPU state and hold it for the duration of the
+     * handler (this ensures safe access to shared CPU and device state during
+     * exception delivery, which may be cross-vCPU).
+     */
+    void (*do_interrupt)(CPUState *cpu);
+
     /**
      * @do_interrupt_locked: Deliver a pending exception/interrupt to the CPU
      * @cpu: cpu context
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 8d9c203f222..4deb7e00571 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -727,9 +727,13 @@  static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
     if (replay_exception()) {
         const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops;
 
-        bql_lock();
-        tcg_ops->do_interrupt_locked(cpu);
-        bql_unlock();
+        if (tcg_ops->do_interrupt) {
+            tcg_ops->do_interrupt(cpu);
+        } else {
+            bql_lock();
+            tcg_ops->do_interrupt_locked(cpu);
+            bql_unlock();
+        }
         cpu->exception_index = -1;
 
         if (unlikely(cpu_single_stepping(cpu))) {
@@ -1059,7 +1063,7 @@  bool tcg_exec_realizefn(CPUState *cpu, Error **errp)
         assert(tcg_ops->cpu_exec_halt);
         assert(tcg_ops->cpu_exec_interrupt);
         assert(tcg_ops->cpu_exec_reset);
-        assert(tcg_ops->do_interrupt_locked);
+        assert(tcg_ops->do_interrupt || tcg_ops->do_interrupt_locked);
         assert(tcg_ops->pointer_wrap);
 #endif /* !CONFIG_USER_ONLY */
         assert(tcg_ops->translate_code);