Commit 970657e490 for qemu.org
commit 970657e490c05b0d2dd8ffbd68466d22685083d1
Author: Bibo Mao <maobibo@loongson.cn>
Date: Thu Aug 27 15:53:10 2026 +0800
hw/intc/loongarch_extioi: Add extioi interrupt status display
When irqchip in kernel is enabled, the register status of extioi irqchip
is in KVM kernel. Here add interrupt status display in user side in order
to debug extioi irqchip driver.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Reviewed-by: Xianglai Li <lixianglai@loongson.cn>
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
index 2999740269..06f2aa7b14 100644
--- a/hw/intc/loongarch_extioi.c
+++ b/hw/intc/loongarch_extioi.c
@@ -10,6 +10,7 @@
#include "qemu/log.h"
#include "qapi/error.h"
#include "hw/core/irq.h"
+#include "hw/intc/intc.h"
#include "hw/loongarch/virt.h"
#include "system/address-spaces.h"
#include "system/kvm.h"
@@ -420,11 +421,63 @@ static int vmstate_extioi_post_load(void *opaque, int version_id)
return 0;
}
+static void loongarch_extioi_print_info(InterruptStatsProvider *obj,
+ GString *buf)
+{
+ LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(obj);
+ uint64_t *val;
+ unsigned long irq;
+ ExtIOICore *core;
+ int i;
+
+ vmstate_extioi_pre_save(s);
+ g_string_append_printf(buf, "%s:\n", object_get_typename(OBJECT(obj)));
+
+ val = (uint64_t *)s->isr;
+ g_string_append_printf(buf, " ISR 0x%016"PRIx64" 0x%016"PRIx64
+ " 0x%016"PRIx64" 0x%016"PRIx64"\n",
+ *val, *(val + 1), *(val + 2), *(val + 3));
+ val = (uint64_t *)s->enable;
+ g_string_append_printf(buf, " ENABLE 0x%016"PRIx64" 0x%016"PRIx64
+ " 0x%016"PRIx64" 0x%016"PRIx64"\n",
+ *val, *(val + 1), *(val + 2), *(val + 3));
+ val = (uint64_t *)s->ipmap;
+ g_string_append_printf(buf, " IPMAP 0x%016"PRIx64"\n", *val);
+
+ val = (uint64_t *)s->coremap;
+ for (i = 0; i < EXTIOI_IRQS; i += 32) {
+ g_string_append_printf(buf, " COREMAP 0x%016"PRIx64" 0x%016"PRIx64
+ " 0x%016"PRIx64" 0x%016"PRIx64"\n",
+ *val, *(val + 1), *(val + 2), *(val + 3));
+ val += 4;
+ }
+
+ core = s->cpu;
+ for (i = 0; i < s->num_cpu; i++, core++) {
+ if (!core->cpu) {
+ continue;
+ }
+
+ irq = find_first_bit((unsigned long *)core->coreisr, EXTIOI_IRQS);
+ /* No pending IRQ */
+ if (irq == EXTIOI_IRQS) {
+ continue;
+ }
+
+ val = (uint64_t *)core->coreisr;
+ g_string_append_printf(buf, " CPU[%d] ISR 0x%016"PRIx64" 0x%016"PRIx64
+ " 0x%016"PRIx64" 0x%016"PRIx64"\n",
+ i, *val, *(val + 1), *(val + 2),
+ *(val + 3));
+ }
+}
+
static void loongarch_extioi_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_CLASS(klass);
LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass);
+ InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
device_class_set_parent_realize(dc, loongarch_extioi_realize,
@@ -433,6 +486,7 @@ static void loongarch_extioi_class_init(ObjectClass *klass, const void *data)
NULL, &lec->parent_phases);
lecc->pre_save = vmstate_extioi_pre_save;
lecc->post_load = vmstate_extioi_post_load;
+ ic->print_info = loongarch_extioi_print_info;
}
static const TypeInfo loongarch_extioi_types[] = {
@@ -442,6 +496,10 @@ static const TypeInfo loongarch_extioi_types[] = {
.instance_size = sizeof(LoongArchExtIOIState),
.class_size = sizeof(LoongArchExtIOIClass),
.class_init = loongarch_extioi_class_init,
+ .interfaces = (const InterfaceInfo[]) {
+ { TYPE_INTERRUPT_STATS_PROVIDER },
+ { }
+ },
}
};