diff mbox series

[RFC,RESEND,34/42] accel/split: Implement get_[vcpu]_stats()

Message ID 20250620172751.94231-35-philmd@linaro.org
State New
Headers show
Series accel/split/arm: Run EL2 using TCG and EL1/EL0 in hardware with HVF | expand

Commit Message

Philippe Mathieu-Daudé June 20, 2025, 5:27 p.m. UTC
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 accel/split/split-accel.h     |  5 +++++
 accel/split/split-accel-ops.c | 24 +++++++++++++++++++++++-
 accel/split/split-all.c       | 16 +++++++++++++++-
 3 files changed, 43 insertions(+), 2 deletions(-)

Comments

Richard Henderson June 22, 2025, 3:19 a.m. UTC | #1
On 6/20/25 10:27, Philippe Mathieu-Daudé wrote:
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
>   accel/split/split-accel.h     |  5 +++++
>   accel/split/split-accel-ops.c | 24 +++++++++++++++++++++++-
>   accel/split/split-all.c       | 16 +++++++++++++++-
>   3 files changed, 43 insertions(+), 2 deletions(-)
> 
> diff --git a/accel/split/split-accel.h b/accel/split/split-accel.h
> index 8a2888507f3..80a19bbb1e5 100644
> --- a/accel/split/split-accel.h
> +++ b/accel/split/split-accel.h
> @@ -36,6 +36,11 @@ struct SplitAccelState {
>   
>       char *hw_name;
>       char *sw_name;
> +
> +    struct {
> +        unsigned transitions; /* number of HW <-> SW transitions */
> +        uint64_t exec_count[2]; /* SW:0 HW:1 */
> +    } stats;
>   };
>   
>   struct AccelCPUState {
> diff --git a/accel/split/split-accel-ops.c b/accel/split/split-accel-ops.c
> index d59e70e0d9b..615faf1d96b 100644
> --- a/accel/split/split-accel-ops.c
> +++ b/accel/split/split-accel-ops.c
> @@ -9,6 +9,7 @@
>   #include "qemu/osdep.h"
>   #include "qemu/main-loop.h"
>   #include "qemu/guest-random.h"
> +#include "qapi/type-helpers.h"
>   #include "exec/cpu-common.h"
>   #include "exec/cpu-interrupt.h"
>   #include "hw/core/cpu.h"
> @@ -16,6 +17,7 @@
>   #include "system/cpus.h"
>   #include "system/hw_accel.h"
>   #include "system/tcg.h"
> +#include "monitor/monitor.h"
>   #include "split-accel.h"
>   #include "trace.h"
>   
> @@ -70,6 +72,7 @@ static void *split_cpu_thread_routine(void *arg)
>                   r = swops->exec_vcpu_thread(cpu);
>                   trace_accel_split_exec_vcpu_thread_sw(r);
>               }
> +            sas->stats.exec_count[acs->use_hw]++;
>               switch (r) {
>               case 0:
>                   if (acs->use_hw) {
> @@ -103,6 +106,7 @@ static void *split_cpu_thread_routine(void *arg)
>                   assert(!acs->use_hw);
>                   trace_accel_split_hw_accelerate();
>                   acs->use_hw = true;
> +                sas->stats.transitions++;

There's also the transitions in case 0.
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>



r~
diff mbox series

Patch

diff --git a/accel/split/split-accel.h b/accel/split/split-accel.h
index 8a2888507f3..80a19bbb1e5 100644
--- a/accel/split/split-accel.h
+++ b/accel/split/split-accel.h
@@ -36,6 +36,11 @@  struct SplitAccelState {
 
     char *hw_name;
     char *sw_name;
+
+    struct {
+        unsigned transitions; /* number of HW <-> SW transitions */
+        uint64_t exec_count[2]; /* SW:0 HW:1 */
+    } stats;
 };
 
 struct AccelCPUState {
diff --git a/accel/split/split-accel-ops.c b/accel/split/split-accel-ops.c
index d59e70e0d9b..615faf1d96b 100644
--- a/accel/split/split-accel-ops.c
+++ b/accel/split/split-accel-ops.c
@@ -9,6 +9,7 @@ 
 #include "qemu/osdep.h"
 #include "qemu/main-loop.h"
 #include "qemu/guest-random.h"
+#include "qapi/type-helpers.h"
 #include "exec/cpu-common.h"
 #include "exec/cpu-interrupt.h"
 #include "hw/core/cpu.h"
@@ -16,6 +17,7 @@ 
 #include "system/cpus.h"
 #include "system/hw_accel.h"
 #include "system/tcg.h"
+#include "monitor/monitor.h"
 #include "split-accel.h"
 #include "trace.h"
 
@@ -70,6 +72,7 @@  static void *split_cpu_thread_routine(void *arg)
                 r = swops->exec_vcpu_thread(cpu);
                 trace_accel_split_exec_vcpu_thread_sw(r);
             }
+            sas->stats.exec_count[acs->use_hw]++;
             switch (r) {
             case 0:
                 if (acs->use_hw) {
@@ -103,6 +106,7 @@  static void *split_cpu_thread_routine(void *arg)
                 assert(!acs->use_hw);
                 trace_accel_split_hw_accelerate();
                 acs->use_hw = true;
+                sas->stats.transitions++;
                 break;
             default:
                 /* Ignore everything else? */
@@ -314,7 +318,25 @@  static void split_remove_all_breakpoints(CPUState *cpu)
 
 static void split_get_vcpu_stats(CPUState *cpu, GString *buf)
 {
-    g_assert_not_reached();
+    SplitAccelState *sas = SPLIT_ACCEL(cpu->accel->accel);
+    AccelClass *hwc = ACCEL_GET_CLASS(sas->hw);
+    AccelClass *swc = ACCEL_GET_CLASS(sas->sw);
+    g_autofree char *cpu_model =
+        cpu_model_from_type(object_get_typename(OBJECT(cpu)));
+
+    if (cpu->cluster_index != -1) {
+        g_string_append_printf(buf, "CPU#%d@%d: %s\n",
+                               cpu->cpu_index, cpu->cluster_index, cpu_model);
+    } else {
+        g_string_append_printf(buf, "CPU#%d: %s\n",
+                               cpu->cpu_index, cpu_model);
+    }
+    if (hwc->ops->get_vcpu_stats) {
+        hwc->ops->get_vcpu_stats(cpu, buf);
+    }
+    if (swc->ops->get_vcpu_stats) {
+        swc->ops->get_vcpu_stats(cpu, buf);
+    }
 }
 
 static void split_accel_ops_class_init(ObjectClass *oc, const void *data)
diff --git a/accel/split/split-all.c b/accel/split/split-all.c
index 413954af96c..9e0848db971 100644
--- a/accel/split/split-all.c
+++ b/accel/split/split-all.c
@@ -94,7 +94,21 @@  static int split_gdbstub_supported_sstep_flags(AccelState *as)
 
 static void split_get_stats(AccelState *as, GString *buf)
 {
-    g_assert_not_reached();
+    SplitAccelState *sas = SPLIT_ACCEL(as);
+    AccelClass *hwc = ACCEL_GET_CLASS(sas->hw);
+    AccelClass *swc = ACCEL_GET_CLASS(sas->sw);
+
+    g_string_append_printf(buf,
+                           "%u transitions, %llu SW and %llu HW executions\n",
+                           sas->stats.transitions,
+                           sas->stats.exec_count[0],
+                           sas->stats.exec_count[1]);
+    if (hwc->get_stats) {
+        hwc->get_stats(as, buf);
+    }
+    if (swc->get_stats) {
+        swc->get_stats(as, buf);
+    }
 }
 
 static char *split_get_hw(Object *obj, Error **errp)