Commit 761eb76a3b for qemu.org

commit 761eb76a3bc7493e2425f3ea659b018b099a409b
Author: Bibo Mao <maobibo@loongson.cn>
Date:   Thu Aug 27 15:53:08 2026 +0800

    hw/intc/loongarch_ipi: Add ipi interrupt status display

    When irqchip in kernel is enabled, the register status of ipi irqchip is
    in KVM kernel. Here add interrupt status display in user side in order to
    debug irqchip driver.

    Signed-off-by: Bibo Mao <maobibo@loongson.cn>
    Reviewed-by: Xianglai Li <lixianglai@loongson.cn>

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 5d8b8c96df..28d816e3f5 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -9,6 +9,7 @@
 #include "qemu/error-report.h"
 #include "hw/core/boards.h"
 #include "qapi/error.h"
+#include "hw/intc/intc.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/core/qdev-properties.h"
 #include "system/kvm.h"
@@ -193,8 +194,47 @@ static int loongarch_ipi_post_load(void *opaque, int version_id)
     return 0;
 }

+static void loongarch_ipi_print_info(InterruptStatsProvider *obj, GString *buf)
+{
+    LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(obj);
+    int i, j;
+    IPICore *core;
+    uint64_t mbx;
+    unsigned long pos;
+
+    loongarch_ipi_pre_save(lics);
+
+    g_string_append_printf(buf, "%s:\n", object_get_typename(OBJECT(obj)));
+    for (i = 0; i < lics->num_cpu; i++) {
+        core = lics->cpu + i;
+        /* IPI with targeted CPU available however not present */
+        if (!core->cpu) {
+            continue;
+        }
+
+        g_string_append_printf(buf, "  CPU %-3u status=0x%x en=0x%x\n",
+                                    i, core->status, core->en);
+
+        pos = find_first_bit((unsigned long *)core->buf, IPI_MBX_NUM * 64);
+        /* All zero in mailbox */
+        if (pos == (IPI_MBX_NUM * 64)) {
+            continue;
+        }
+
+        for (j = 0; j < IPI_MBX_NUM; j++) {
+            mbx = *(uint64_t *)&core->buf[2 * j];
+            if (mbx) {
+                g_string_append_printf(buf, "  MBX[%-1u] 0x%016"PRIx64, j, mbx);
+            }
+        }
+
+        g_string_append_c(buf, '\n');
+    }
+}
+
 static void loongarch_ipi_class_init(ObjectClass *klass, const void *data)
 {
+    InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
     LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass);
     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
     LoongarchIPIClass *lic = LOONGARCH_IPI_CLASS(klass);
@@ -211,6 +251,7 @@ static void loongarch_ipi_class_init(ObjectClass *klass, const void *data)
     hc->unplug = loongarch_ipi_cpu_unplug;
     licc->pre_save = loongarch_ipi_pre_save;
     licc->post_load = loongarch_ipi_post_load;
+    ic->print_info = loongarch_ipi_print_info;
 }

 static const TypeInfo loongarch_ipi_types[] = {
@@ -222,6 +263,7 @@ static const TypeInfo loongarch_ipi_types[] = {
         .class_init         = loongarch_ipi_class_init,
         .interfaces         = (const InterfaceInfo[]) {
             { TYPE_HOTPLUG_HANDLER },
+            { TYPE_INTERRUPT_STATS_PROVIDER },
             { }
         },
     }