[PATCH v6 27/39] accel: Pass old/new interrupt mask to handle_interrupt() handler

Philippe Mathieu-Daudé posted 39 patches 5 months, 2 weeks ago
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Cameron Esfahani <dirty@apple.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, Mads Ynddal <mads@ynddal.dk>, Fabiano Rosas <farosas@suse.de>, Laurent Vivier <lvivier@redhat.com>, Stefano Stabellini <sstabellini@kernel.org>, Anthony PERARD <anthony@xenproject.org>, Paul Durrant <paul@xen.org>, "Edgar E. Iglesias" <edgar.iglesias@gmail.com>, Warner Losh <imp@bsdimp.com>, Kyle Evans <kevans@freebsd.org>, "Alex Bennée" <alex.bennee@linaro.org>, "Dr. David Alan Gilbert" <dave@treblig.org>, Eduardo Habkost <eduardo@habkost.net>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, Reinoud Zandijk <reinoud@netbsd.org>, Sunil Muthuswamy <sunilmut@microsoft.com>, Eric Blake <eblake@redhat.com>, Markus Armbruster <armbru@redhat.com>, Peter Xu <peterx@redhat.com>, David Hildenbrand <david@redhat.com>, Alexander Graf <agraf@csgraf.de>, Peter Maydell <peter.maydell@linaro.org>
[PATCH v6 27/39] accel: Pass old/new interrupt mask to handle_interrupt() handler
Posted by Philippe Mathieu-Daudé 5 months, 2 weeks ago
Update CPUState::interrupt_request once in cpu_interrupt().
Pass the old and new masks along.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/tcg-accel-ops-icount.h |  2 +-
 accel/tcg/tcg-accel-ops.h        |  2 +-
 include/system/accel-ops.h       |  2 +-
 accel/tcg/tcg-accel-ops-icount.c |  8 +++-----
 accel/tcg/tcg-accel-ops.c        |  4 +---
 system/cpus.c                    | 12 +++++++-----
 6 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/accel/tcg/tcg-accel-ops-icount.h b/accel/tcg/tcg-accel-ops-icount.h
index 16a301b6dc0..1d9d66f0707 100644
--- a/accel/tcg/tcg-accel-ops-icount.h
+++ b/accel/tcg/tcg-accel-ops-icount.h
@@ -15,6 +15,6 @@ void icount_prepare_for_run(CPUState *cpu, int64_t cpu_budget);
 int64_t icount_percpu_budget(int cpu_count);
 void icount_process_data(CPUState *cpu);
 
-void icount_handle_interrupt(CPUState *cpu, int mask);
+void icount_handle_interrupt(CPUState *cpu, int old_mask, int new_mask);
 
 #endif /* TCG_ACCEL_OPS_ICOUNT_H */
diff --git a/accel/tcg/tcg-accel-ops.h b/accel/tcg/tcg-accel-ops.h
index 6feeb3f3e9b..6e7c2aae5a8 100644
--- a/accel/tcg/tcg-accel-ops.h
+++ b/accel/tcg/tcg-accel-ops.h
@@ -16,7 +16,7 @@
 
 void tcg_cpu_destroy(CPUState *cpu);
 int tcg_cpu_exec(CPUState *cpu);
-void tcg_handle_interrupt(CPUState *cpu, int mask);
+void tcg_handle_interrupt(CPUState *cpu, int old_mask, int new_mask);
 void tcg_cpu_init_cflags(CPUState *cpu, bool parallel);
 
 #endif /* TCG_ACCEL_OPS_H */
diff --git a/include/system/accel-ops.h b/include/system/accel-ops.h
index 2075691331c..d84eaa376c2 100644
--- a/include/system/accel-ops.h
+++ b/include/system/accel-ops.h
@@ -61,7 +61,7 @@ struct AccelOpsClass {
     void (*synchronize_pre_loadvm)(CPUState *cpu);
     void (*synchronize_pre_resume)(bool step_pending);
 
-    void (*handle_interrupt)(CPUState *cpu, int mask);
+    void (*handle_interrupt)(CPUState *cpu, int old_mask, int new_mask);
 
     /**
      * @get_virtual_clock: fetch virtual clock
diff --git a/accel/tcg/tcg-accel-ops-icount.c b/accel/tcg/tcg-accel-ops-icount.c
index d0f7b410fab..500b5dd4942 100644
--- a/accel/tcg/tcg-accel-ops-icount.c
+++ b/accel/tcg/tcg-accel-ops-icount.c
@@ -147,14 +147,12 @@ void icount_process_data(CPUState *cpu)
     replay_mutex_unlock();
 }
 
-void icount_handle_interrupt(CPUState *cpu, int mask)
+void icount_handle_interrupt(CPUState *cpu, int old_mask, int new_mask)
 {
-    int old_mask = cpu->interrupt_request;
-
-    tcg_handle_interrupt(cpu, mask);
+    tcg_handle_interrupt(cpu, old_mask, new_mask);
     if (qemu_cpu_is_self(cpu) &&
         !cpu->neg.can_do_io
-        && (mask & ~old_mask) != 0) {
+        && (new_mask & ~old_mask) != 0) {
         cpu_abort(cpu, "Raised interrupt while not in I/O function");
     }
 }
diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c
index f579685a611..eb16a6bf6db 100644
--- a/accel/tcg/tcg-accel-ops.c
+++ b/accel/tcg/tcg-accel-ops.c
@@ -91,10 +91,8 @@ static void tcg_cpu_reset_hold(CPUState *cpu)
 }
 
 /* mask must never be zero, except for A20 change call */
-void tcg_handle_interrupt(CPUState *cpu, int mask)
+void tcg_handle_interrupt(CPUState *cpu, int old_mask, int new_mask)
 {
-    cpu->interrupt_request |= mask;
-
     /*
      * If called from iothread context, wake the target cpu in
      * case its halted.
diff --git a/system/cpus.c b/system/cpus.c
index 4fb764ac880..13535a74e6f 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -246,10 +246,8 @@ int64_t cpus_get_elapsed_ticks(void)
     return cpu_get_ticks();
 }
 
-static void generic_handle_interrupt(CPUState *cpu, int mask)
+static void generic_handle_interrupt(CPUState *cpu, int old_mask, int new_mask)
 {
-    cpu->interrupt_request |= mask;
-
     if (!qemu_cpu_is_self(cpu)) {
         qemu_cpu_kick(cpu);
     }
@@ -257,12 +255,16 @@ static void generic_handle_interrupt(CPUState *cpu, int mask)
 
 void cpu_interrupt(CPUState *cpu, int mask)
 {
+    int old_mask = cpu->interrupt_request;
+
     g_assert(bql_locked());
 
+    cpu->interrupt_request |= mask;
+
     if (cpus_accel->handle_interrupt) {
-        cpus_accel->handle_interrupt(cpu, mask);
+        cpus_accel->handle_interrupt(cpu, old_mask, cpu->interrupt_request);
     } else {
-        generic_handle_interrupt(cpu, mask);
+        generic_handle_interrupt(cpu, old_mask, cpu->interrupt_request);
     }
 }
 
-- 
2.49.0


Re: [PATCH v6 27/39] accel: Pass old/new interrupt mask to handle_interrupt() handler
Posted by Zhao Liu 5 months, 2 weeks ago
On Thu, Jul 03, 2025 at 07:32:33PM +0200, Philippe Mathieu-Daudé wrote:
> Date: Thu,  3 Jul 2025 19:32:33 +0200
> From: Philippe Mathieu-Daudé <philmd@linaro.org>
> Subject: [PATCH v6 27/39] accel: Pass old/new interrupt mask to
>  handle_interrupt() handler
> X-Mailer: git-send-email 2.49.0
> 
> Update CPUState::interrupt_request once in cpu_interrupt().
> Pass the old and new masks along.
> 
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  accel/tcg/tcg-accel-ops-icount.h |  2 +-
>  accel/tcg/tcg-accel-ops.h        |  2 +-
>  include/system/accel-ops.h       |  2 +-
>  accel/tcg/tcg-accel-ops-icount.c |  8 +++-----
>  accel/tcg/tcg-accel-ops.c        |  4 +---
>  system/cpus.c                    | 12 +++++++-----
>  6 files changed, 14 insertions(+), 16 deletions(-)

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Re: [PATCH v6 27/39] accel: Pass old/new interrupt mask to handle_interrupt() handler
Posted by Xiaoyao Li 5 months, 2 weeks ago
On 7/4/2025 1:32 AM, Philippe Mathieu-Daudé wrote:
> Update CPUState::interrupt_request once in cpu_interrupt().
> Pass the old and new masks along.
> 
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   accel/tcg/tcg-accel-ops-icount.h |  2 +-
>   accel/tcg/tcg-accel-ops.h        |  2 +-
>   include/system/accel-ops.h       |  2 +-
>   accel/tcg/tcg-accel-ops-icount.c |  8 +++-----
>   accel/tcg/tcg-accel-ops.c        |  4 +---
>   system/cpus.c                    | 12 +++++++-----
>   6 files changed, 14 insertions(+), 16 deletions(-)
> 
> diff --git a/accel/tcg/tcg-accel-ops-icount.h b/accel/tcg/tcg-accel-ops-icount.h
> index 16a301b6dc0..1d9d66f0707 100644
> --- a/accel/tcg/tcg-accel-ops-icount.h
> +++ b/accel/tcg/tcg-accel-ops-icount.h
> @@ -15,6 +15,6 @@ void icount_prepare_for_run(CPUState *cpu, int64_t cpu_budget);
>   int64_t icount_percpu_budget(int cpu_count);
>   void icount_process_data(CPUState *cpu);
>   
> -void icount_handle_interrupt(CPUState *cpu, int mask);
> +void icount_handle_interrupt(CPUState *cpu, int old_mask, int new_mask);
>   
>   #endif /* TCG_ACCEL_OPS_ICOUNT_H */
> diff --git a/accel/tcg/tcg-accel-ops.h b/accel/tcg/tcg-accel-ops.h
> index 6feeb3f3e9b..6e7c2aae5a8 100644
> --- a/accel/tcg/tcg-accel-ops.h
> +++ b/accel/tcg/tcg-accel-ops.h
> @@ -16,7 +16,7 @@
>   
>   void tcg_cpu_destroy(CPUState *cpu);
>   int tcg_cpu_exec(CPUState *cpu);
> -void tcg_handle_interrupt(CPUState *cpu, int mask);
> +void tcg_handle_interrupt(CPUState *cpu, int old_mask, int new_mask);
>   void tcg_cpu_init_cflags(CPUState *cpu, bool parallel);
>   
>   #endif /* TCG_ACCEL_OPS_H */
> diff --git a/include/system/accel-ops.h b/include/system/accel-ops.h
> index 2075691331c..d84eaa376c2 100644
> --- a/include/system/accel-ops.h
> +++ b/include/system/accel-ops.h
> @@ -61,7 +61,7 @@ struct AccelOpsClass {
>       void (*synchronize_pre_loadvm)(CPUState *cpu);
>       void (*synchronize_pre_resume)(bool step_pending);
>   
> -    void (*handle_interrupt)(CPUState *cpu, int mask);
> +    void (*handle_interrupt)(CPUState *cpu, int old_mask, int new_mask);
>   
>       /**
>        * @get_virtual_clock: fetch virtual clock
> diff --git a/accel/tcg/tcg-accel-ops-icount.c b/accel/tcg/tcg-accel-ops-icount.c
> index d0f7b410fab..500b5dd4942 100644
> --- a/accel/tcg/tcg-accel-ops-icount.c
> +++ b/accel/tcg/tcg-accel-ops-icount.c
> @@ -147,14 +147,12 @@ void icount_process_data(CPUState *cpu)
>       replay_mutex_unlock();
>   }
>   
> -void icount_handle_interrupt(CPUState *cpu, int mask)
> +void icount_handle_interrupt(CPUState *cpu, int old_mask, int new_mask)
>   {
> -    int old_mask = cpu->interrupt_request;
> -
> -    tcg_handle_interrupt(cpu, mask);
> +    tcg_handle_interrupt(cpu, old_mask, new_mask);
>       if (qemu_cpu_is_self(cpu) &&
>           !cpu->neg.can_do_io
> -        && (mask & ~old_mask) != 0) {
> +        && (new_mask & ~old_mask) != 0) {

This patch changes the behavior,

Assume the @mask is the value passed to cpu_interrupt()

- before this patch:

	(mask & ~old_mask) is

	(@mask & ~cpu->interrupt_request)

- after this patch:

	(new_mask & ~old_mask) is

	((@mask | cpu->interrupt_request) & ~cpu->interrupt_request)