hw/intc/riscv_aplic.c | 4 ++++ hw/intc/riscv_imsic.c | 4 ++++ 2 files changed, 8 insertions(+)
The emulated APLIC and IMSIC state arrays are only allocated when QEMU
handles the interrupt controller state itself. With KVM AIA/APLIC-IMSIC,
the interrupt controller state is owned by the KVM in-kernel irqchip, so
these emulated state arrays are not allocated.
The reset handlers added for APLIC and IMSIC still clear those arrays
unconditionally. This makes qemu_system_reset(), which runs during machine
creation, dereference NULL pointers with -machine virt,aia=aplic-imsic and
KVM.
Skip the emulated APLIC and IMSIC reset paths when the interrupt controller
is handled by KVM. The emulated paths are unchanged for TCG and for
configurations that use QEMU emulation.
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: Qingwei Hu <qingwei.hu@bytedance.com>
---
hw/intc/riscv_aplic.c | 4 ++++
hw/intc/riscv_imsic.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index c2c67c29e6..84606e9f3d 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -910,6 +910,10 @@ static void riscv_aplic_reset_enter(Object *obj, ResetType type)
RISCVAPLICState *aplic = RISCV_APLIC(obj);
int i;
+ if (!riscv_use_emulated_aplic(aplic->msimode)) {
+ return;
+ }
+
aplic->domaincfg = 0;
memset(aplic->sourcecfg, 0, sizeof(uint32_t) * aplic->num_irqs);
memset(aplic->target, 0, sizeof(uint32_t) * aplic->num_irqs);
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index ac59496c22..f1f23c3a3e 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -347,6 +347,10 @@ static void riscv_imsic_reset_enter(Object *obj, ResetType type)
RISCVIMSICState *imsic = RISCV_IMSIC(obj);
int i;
+ if (kvm_irqchip_in_kernel()) {
+ return;
+ }
+
memset(imsic->eidelivery, 0, sizeof(uint32_t) * imsic->num_pages);
memset(imsic->eithreshold, 0, sizeof(uint32_t) * imsic->num_pages);
--
2.47.3
On 6/5/2026 7:06 PM, Qingwei Hu wrote:
> The emulated APLIC and IMSIC state arrays are only allocated when QEMU
> handles the interrupt controller state itself. With KVM AIA/APLIC-IMSIC,
> the interrupt controller state is owned by the KVM in-kernel irqchip, so
> these emulated state arrays are not allocated.
>
> The reset handlers added for APLIC and IMSIC still clear those arrays
> unconditionally. This makes qemu_system_reset(), which runs during machine
> creation, dereference NULL pointers with -machine virt,aia=aplic-imsic and
> KVM.
>
> Skip the emulated APLIC and IMSIC reset paths when the interrupt controller
> is handled by KVM. The emulated paths are unchanged for TCG and for
> configurations that use QEMU emulation.
>
> 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: Qingwei Hu <qingwei.hu@bytedance.com>
It would be better to split it into two fix patches.
Otherwise,
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
> ---
> hw/intc/riscv_aplic.c | 4 ++++
> hw/intc/riscv_imsic.c | 4 ++++
> 2 files changed, 8 insertions(+)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index c2c67c29e6..84606e9f3d 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -910,6 +910,10 @@ static void riscv_aplic_reset_enter(Object *obj, ResetType type)
> RISCVAPLICState *aplic = RISCV_APLIC(obj);
> int i;
>
> + if (!riscv_use_emulated_aplic(aplic->msimode)) {
> + return;
> + }
> +
> aplic->domaincfg = 0;
> memset(aplic->sourcecfg, 0, sizeof(uint32_t) * aplic->num_irqs);
> memset(aplic->target, 0, sizeof(uint32_t) * aplic->num_irqs);
> diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
> index ac59496c22..f1f23c3a3e 100644
> --- a/hw/intc/riscv_imsic.c
> +++ b/hw/intc/riscv_imsic.c
> @@ -347,6 +347,10 @@ static void riscv_imsic_reset_enter(Object *obj, ResetType type)
> RISCVIMSICState *imsic = RISCV_IMSIC(obj);
> int i;
>
> + if (kvm_irqchip_in_kernel()) {
> + return;
> + }
> +
> memset(imsic->eidelivery, 0, sizeof(uint32_t) * imsic->num_pages);
> memset(imsic->eithreshold, 0, sizeof(uint32_t) * imsic->num_pages);
>
> On Jun 11, 2026, at 18:06, Nutty.Liu <nutty.liu@hotmail.com> wrote:
>
>
> On 6/5/2026 7:06 PM, Qingwei Hu wrote:
>> The emulated APLIC and IMSIC state arrays are only allocated when QEMU
>> handles the interrupt controller state itself. With KVM AIA/APLIC-IMSIC,
>> the interrupt controller state is owned by the KVM in-kernel irqchip, so
>> these emulated state arrays are not allocated.
>>
>> The reset handlers added for APLIC and IMSIC still clear those arrays
>> unconditionally. This makes qemu_system_reset(), which runs during machine
>> creation, dereference NULL pointers with -machine virt,aia=aplic-imsic and
>> KVM.
>>
>> Skip the emulated APLIC and IMSIC reset paths when the interrupt controller
>> is handled by KVM. The emulated paths are unchanged for TCG and for
>> configurations that use QEMU emulation.
>>
>> 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: Qingwei Hu <qingwei.hu@bytedance.com>
> It would be better to split it into two fix patches.
> Otherwise,
> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
>
> Thanks,
> Nutty
Hi Nutty,
Thanks for the review. I will split this into two patches and send a v2.
Best regards,
Qingwei
>> ---
>> hw/intc/riscv_aplic.c | 4 ++++
>> hw/intc/riscv_imsic.c | 4 ++++
>> 2 files changed, 8 insertions(+)
>>
>> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
>> index c2c67c29e6..84606e9f3d 100644
>> --- a/hw/intc/riscv_aplic.c
>> +++ b/hw/intc/riscv_aplic.c
>> @@ -910,6 +910,10 @@ static void riscv_aplic_reset_enter(Object *obj, ResetType type)
>> RISCVAPLICState *aplic = RISCV_APLIC(obj);
>> int i;
>> + if (!riscv_use_emulated_aplic(aplic->msimode)) {
>> + return;
>> + }
>> +
>> aplic->domaincfg = 0;
>> memset(aplic->sourcecfg, 0, sizeof(uint32_t) * aplic->num_irqs);
>> memset(aplic->target, 0, sizeof(uint32_t) * aplic->num_irqs);
>> diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
>> index ac59496c22..f1f23c3a3e 100644
>> --- a/hw/intc/riscv_imsic.c
>> +++ b/hw/intc/riscv_imsic.c
>> @@ -347,6 +347,10 @@ static void riscv_imsic_reset_enter(Object *obj, ResetType type)
>> RISCVIMSICState *imsic = RISCV_IMSIC(obj);
>> int i;
>> + if (kvm_irqchip_in_kernel()) {
>> + return;
>> + }
>> +
>> memset(imsic->eidelivery, 0, sizeof(uint32_t) * imsic->num_pages);
>> memset(imsic->eithreshold, 0, sizeof(uint32_t) * imsic->num_pages);
© 2016 - 2026 Red Hat, Inc.