On 6/1/2026 11:16 AM, [email protected] wrote:
From: Xuemei Liu <[email protected]>
Since commits 99bfcd329a ("hw/intc: riscv_aplic: Add reset API to APLIC")
and 766391483b ("hw/intc: riscv_imsic: Add reset API to IMSIC"), when KVM
acceleration is used and AIA is configured as aplic-imsic, the APLIC and
IMSIC devices are not emulated (they are handled in-kernel). In such
cases, the realize functions do not allocate memory for their internal
register state, leaving the corresponding pointers NULL.
The reset functions riscv_aplic_reset_enter() and riscv_imsic_reset_enter()
subsequently attempt to access these NULL pointers (e.g., via memset),
causing a segmentation fault and VM start failure.
Fix this by guarding the reset operations with condition checks that
skip the emulated‑specific logic when the in‑kernel mode is active:
- For APLIC, check riscv_use_emulated_aplic(aplic->msimode).
- For IMSIC, check !kvm_irqchip_in_kernel().
Fixes: 99bfcd329a ("hw/intc: riscv_aplic: Add reset API to APLIC")
Fixes: 766391483b ("hw/intc: riscv_imsic: Add reset API to IMSIC")
Signed-off-by: Xuemei Liu <[email protected]>
It would be better to split this patch into two fix patches.
Otherwise,
Reviewed-by: Nutty Liu <[email protected]>
Thanks,
Nutty
---
hw/intc/riscv_aplic.c | 52 ++++++++++++++++++++++---------------------
hw/intc/riscv_imsic.c | 16 +++++++------
2 files changed, 36 insertions(+), 32 deletions(-)
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index c2c67c29e6..0f61b67fc5 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -910,35 +910,37 @@ static void riscv_aplic_reset_enter(Object *obj,
ResetType type)
RISCVAPLICState *aplic = RISCV_APLIC(obj);
int i;
- aplic->domaincfg = 0;
- memset(aplic->sourcecfg, 0, sizeof(uint32_t) * aplic->num_irqs);
- memset(aplic->target, 0, sizeof(uint32_t) * aplic->num_irqs);
- if (!aplic->msimode) {
- for (i = 0; i < aplic->num_irqs; i++) {
- aplic->target[i] = 1;
+ if (riscv_use_emulated_aplic(aplic->msimode)) {
+ aplic->domaincfg = 0;
+ memset(aplic->sourcecfg, 0, sizeof(uint32_t) * aplic->num_irqs);
+ memset(aplic->target, 0, sizeof(uint32_t) * aplic->num_irqs);
+ if (!aplic->msimode) {
+ for (i = 0; i < aplic->num_irqs; i++) {
+ aplic->target[i] = 1;
+ }
}
- }
- for (i = 0; i < aplic->num_irqs ; i++) {
- riscv_aplic_set_enabled_raw(aplic, i, false);
- }
-
- /* Need to unlock [ms]msicfgaddrh.L */
- aplic->mmsicfgaddr = 0;
- aplic->mmsicfgaddrH = 0;
- aplic->smsicfgaddr = 0;
- aplic->smsicfgaddrH = 0;
-
- if (!aplic->msimode) {
- /* Reset IDC registers only in non-MSI mode */
- for (i = 0; i < aplic->num_harts; i++) {
- aplic->idelivery[i] = 0;
- aplic->iforce[i] = 0;
- aplic->ithreshold[i] = 0;
+ for (i = 0; i < aplic->num_irqs ; i++) {
+ riscv_aplic_set_enabled_raw(aplic, i, false);
}
- for (i = 0; i < aplic->num_harts; i++) {
- qemu_irq_lower(aplic->external_irqs[i]);
+ /* Need to unlock [ms]msicfgaddrh.L */
+ aplic->mmsicfgaddr = 0;
+ aplic->mmsicfgaddrH = 0;
+ aplic->smsicfgaddr = 0;
+ aplic->smsicfgaddrH = 0;
+
+ if (!aplic->msimode) {
+ /* Reset IDC registers only in non-MSI mode */
+ for (i = 0; i < aplic->num_harts; i++) {
+ aplic->idelivery[i] = 0;
+ aplic->iforce[i] = 0;
+ aplic->ithreshold[i] = 0;
+ }
+
+ for (i = 0; i < aplic->num_harts; i++) {
+ qemu_irq_lower(aplic->external_irqs[i]);
+ }
}
}
}
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index ac59496c22..6dbbc152a2 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -347,15 +347,17 @@ static void riscv_imsic_reset_enter(Object *obj,
ResetType type)
RISCVIMSICState *imsic = RISCV_IMSIC(obj);
int i;
- memset(imsic->eidelivery, 0, sizeof(uint32_t) * imsic->num_pages);
- memset(imsic->eithreshold, 0, sizeof(uint32_t) * imsic->num_pages);
+ if (!kvm_irqchip_in_kernel()) {
+ memset(imsic->eidelivery, 0, sizeof(uint32_t) * imsic->num_pages);
+ memset(imsic->eithreshold, 0, sizeof(uint32_t) * imsic->num_pages);
- for (i = 0; i < imsic->num_eistate; i++) {
- imsic->eistate[i] &= ~IMSIC_EISTATE_ENABLED;
- }
+ for (i = 0; i < imsic->num_eistate; i++) {
+ imsic->eistate[i] &= ~IMSIC_EISTATE_ENABLED;
+ }
- for (i = 0; i < imsic->num_pages; i++) {
- qemu_irq_lower(imsic->external_irqs[i]);
+ for (i = 0; i < imsic->num_pages; i++) {
+ qemu_irq_lower(imsic->external_irqs[i]);
+ }
}
}