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 <[email protected]>
---
 hw/intc/loongarch_ipi.c | 42 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

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 },
             { }
         },
     }
-- 
2.54.0


Reply via email to