* [PATCH 1/4] hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode
2026-04-28 16:00 [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices Jim Shu
@ 2026-04-28 16:01 ` Jim Shu
2026-05-18 12:20 ` Daniel Henrique Barboza
2026-05-18 21:56 ` Chao Liu
2026-04-28 16:01 ` [PATCH 2/4] hw/intc: riscv_aplic: Add reset API to APLIC Jim Shu
` (3 subsequent siblings)
4 siblings, 2 replies; 11+ messages in thread
From: Jim Shu @ 2026-04-28 16:01 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Jim Shu
According to the AIA spec ch4.7 ("Precise effects on interrupt-pending
bits"), pending bit of APLIC should be set/cleared whenever the
rectified input value is high/low in the both level-trigger mode
and direct delivery mode.
Currently, QEMU APLIC only clears the pending bit when interrupt is
claimed in APLIC, but not clears it when the rectified input value is
low. (e.g. IRQ source signal is low in the LEVEL_HIGH/Level1 mode).
The software may receive an additional IRQ if the peripheral
triggers one after the software clears the APLIC IRQ but before it
clears the peripheral's IRQ.
Thus, we also clear the pending bit via the rectified input value in the
level-trigger mode.
This change doesn't affect MSI delivery mode. Calling
riscv_aplic_msi_irq_update() when IRQ pending is low will do nothing.
Signed-off-by: Jim Shu <jim.shu@sifive.com>
---
hw/intc/riscv_aplic.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index 8f700431114..791e0b01b96 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -591,14 +591,14 @@ static void riscv_aplic_request(void *opaque, int irq, int level)
}
break;
case APLIC_SOURCECFG_SM_LEVEL_HIGH:
- if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) {
- riscv_aplic_set_pending_raw(aplic, irq, true);
+ if ((level > 0) != !!(state & APLIC_ISTATE_PENDING)) {
+ riscv_aplic_set_pending_raw(aplic, irq, level > 0);
update = true;
}
break;
case APLIC_SOURCECFG_SM_LEVEL_LOW:
- if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) {
- riscv_aplic_set_pending_raw(aplic, irq, true);
+ if ((level <= 0) != !!(state & APLIC_ISTATE_PENDING)) {
+ riscv_aplic_set_pending_raw(aplic, irq, level <= 0);
update = true;
}
break;
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 1/4] hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode
2026-04-28 16:01 ` [PATCH 1/4] hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode Jim Shu
@ 2026-05-18 12:20 ` Daniel Henrique Barboza
2026-05-18 21:56 ` Chao Liu
1 sibling, 0 replies; 11+ messages in thread
From: Daniel Henrique Barboza @ 2026-05-18 12:20 UTC (permalink / raw)
To: Jim Shu, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li, Liu Zhiwei, Chao Liu
On 4/28/2026 1:01 PM, Jim Shu wrote:
> According to the AIA spec ch4.7 ("Precise effects on interrupt-pending
> bits"), pending bit of APLIC should be set/cleared whenever the
> rectified input value is high/low in the both level-trigger mode
> and direct delivery mode.
>
> Currently, QEMU APLIC only clears the pending bit when interrupt is
> claimed in APLIC, but not clears it when the rectified input value is
> low. (e.g. IRQ source signal is low in the LEVEL_HIGH/Level1 mode).
> The software may receive an additional IRQ if the peripheral
> triggers one after the software clears the APLIC IRQ but before it
> clears the peripheral's IRQ.
>
> Thus, we also clear the pending bit via the rectified input value in the
> level-trigger mode.
>
> This change doesn't affect MSI delivery mode. Calling
> riscv_aplic_msi_irq_update() when IRQ pending is low will do nothing.
>
> Signed-off-by: Jim Shu <jim.shu@sifive.com>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> hw/intc/riscv_aplic.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index 8f700431114..791e0b01b96 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -591,14 +591,14 @@ static void riscv_aplic_request(void *opaque, int irq, int level)
> }
> break;
> case APLIC_SOURCECFG_SM_LEVEL_HIGH:
> - if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) {
> - riscv_aplic_set_pending_raw(aplic, irq, true);
> + if ((level > 0) != !!(state & APLIC_ISTATE_PENDING)) {
> + riscv_aplic_set_pending_raw(aplic, irq, level > 0);
> update = true;
> }
> break;
> case APLIC_SOURCECFG_SM_LEVEL_LOW:
> - if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) {
> - riscv_aplic_set_pending_raw(aplic, irq, true);
> + if ((level <= 0) != !!(state & APLIC_ISTATE_PENDING)) {
> + riscv_aplic_set_pending_raw(aplic, irq, level <= 0);
> update = true;
> }
> break;
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH 1/4] hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode
2026-04-28 16:01 ` [PATCH 1/4] hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode Jim Shu
2026-05-18 12:20 ` Daniel Henrique Barboza
@ 2026-05-18 21:56 ` Chao Liu
1 sibling, 0 replies; 11+ messages in thread
From: Chao Liu @ 2026-05-18 21:56 UTC (permalink / raw)
To: Jim Shu
Cc: qemu-devel, qemu-riscv, Palmer Dabbelt, Alistair Francis,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei
On Wed, Apr 29, 2026 at 12:01:00AM +0800, Jim Shu wrote:
> According to the AIA spec ch4.7 ("Precise effects on interrupt-pending
> bits"), pending bit of APLIC should be set/cleared whenever the
> rectified input value is high/low in the both level-trigger mode
> and direct delivery mode.
>
> Currently, QEMU APLIC only clears the pending bit when interrupt is
> claimed in APLIC, but not clears it when the rectified input value is
> low. (e.g. IRQ source signal is low in the LEVEL_HIGH/Level1 mode).
> The software may receive an additional IRQ if the peripheral
> triggers one after the software clears the APLIC IRQ but before it
> clears the peripheral's IRQ.
>
> Thus, we also clear the pending bit via the rectified input value in the
> level-trigger mode.
>
> This change doesn't affect MSI delivery mode. Calling
> riscv_aplic_msi_irq_update() when IRQ pending is low will do nothing.
>
> Signed-off-by: Jim Shu <jim.shu@sifive.com>
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Thanks,
Chao
> ---
> hw/intc/riscv_aplic.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index 8f700431114..791e0b01b96 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -591,14 +591,14 @@ static void riscv_aplic_request(void *opaque, int irq, int level)
> }
> break;
> case APLIC_SOURCECFG_SM_LEVEL_HIGH:
> - if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) {
> - riscv_aplic_set_pending_raw(aplic, irq, true);
> + if ((level > 0) != !!(state & APLIC_ISTATE_PENDING)) {
> + riscv_aplic_set_pending_raw(aplic, irq, level > 0);
> update = true;
> }
> break;
> case APLIC_SOURCECFG_SM_LEVEL_LOW:
> - if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) {
> - riscv_aplic_set_pending_raw(aplic, irq, true);
> + if ((level <= 0) != !!(state & APLIC_ISTATE_PENDING)) {
> + riscv_aplic_set_pending_raw(aplic, irq, level <= 0);
> update = true;
> }
> break;
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/4] hw/intc: riscv_aplic: Add reset API to APLIC
2026-04-28 16:00 [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices Jim Shu
2026-04-28 16:01 ` [PATCH 1/4] hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode Jim Shu
@ 2026-04-28 16:01 ` Jim Shu
2026-05-18 12:20 ` Daniel Henrique Barboza
2026-04-28 16:01 ` [PATCH 3/4] hw/intc: riscv_imsic: Add reset API to IMSIC Jim Shu
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Jim Shu @ 2026-04-28 16:01 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Jim Shu,
Fea . Wang
Clearing APLIC registers and qemu_irq in the reset function
Signed-off-by: Jim Shu <jim.shu@sifive.com>
Signed-off-by: Fea.Wang <fea.wang@sifive.com>
---
hw/intc/riscv_aplic.c | 45 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index 791e0b01b96..a04e0e1a898 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -892,6 +892,44 @@ static const MemoryRegionOps riscv_aplic_ops = {
}
};
+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;
+ }
+ }
+
+ 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_harts; i++) {
+ qemu_irq_lower(aplic->external_irqs[i]);
+ }
+ }
+}
+
static void riscv_aplic_realize(DeviceState *dev, Error **errp)
{
uint32_t i;
@@ -925,11 +963,6 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
aplic->state = g_new0(uint32_t, aplic->num_irqs);
aplic->target = g_new0(uint32_t, aplic->num_irqs);
- if (!aplic->msimode) {
- for (i = 0; i < aplic->num_irqs; i++) {
- aplic->target[i] = 1;
- }
- }
aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
aplic->iforce = g_new0(uint32_t, aplic->num_harts);
aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
@@ -1014,9 +1047,11 @@ static const VMStateDescription vmstate_riscv_aplic = {
static void riscv_aplic_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
device_class_set_props(dc, riscv_aplic_properties);
dc->realize = riscv_aplic_realize;
+ rc->phases.enter = riscv_aplic_reset_enter;
dc->vmsd = &vmstate_riscv_aplic;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 2/4] hw/intc: riscv_aplic: Add reset API to APLIC
2026-04-28 16:01 ` [PATCH 2/4] hw/intc: riscv_aplic: Add reset API to APLIC Jim Shu
@ 2026-05-18 12:20 ` Daniel Henrique Barboza
0 siblings, 0 replies; 11+ messages in thread
From: Daniel Henrique Barboza @ 2026-05-18 12:20 UTC (permalink / raw)
To: Jim Shu, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li, Liu Zhiwei, Chao Liu,
Fea . Wang
On 4/28/2026 1:01 PM, Jim Shu wrote:
> Clearing APLIC registers and qemu_irq in the reset function
>
> Signed-off-by: Jim Shu <jim.shu@sifive.com>
> Signed-off-by: Fea.Wang <fea.wang@sifive.com>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> hw/intc/riscv_aplic.c | 45 ++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 40 insertions(+), 5 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index 791e0b01b96..a04e0e1a898 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -892,6 +892,44 @@ static const MemoryRegionOps riscv_aplic_ops = {
> }
> };
>
> +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;
> + }
> + }
> +
> + 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_harts; i++) {
> + qemu_irq_lower(aplic->external_irqs[i]);
> + }
> + }
> +}
> +
> static void riscv_aplic_realize(DeviceState *dev, Error **errp)
> {
> uint32_t i;
> @@ -925,11 +963,6 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
> aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
> aplic->state = g_new0(uint32_t, aplic->num_irqs);
> aplic->target = g_new0(uint32_t, aplic->num_irqs);
> - if (!aplic->msimode) {
> - for (i = 0; i < aplic->num_irqs; i++) {
> - aplic->target[i] = 1;
> - }
> - }
> aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
> aplic->iforce = g_new0(uint32_t, aplic->num_harts);
> aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
> @@ -1014,9 +1047,11 @@ static const VMStateDescription vmstate_riscv_aplic = {
> static void riscv_aplic_class_init(ObjectClass *klass, const void *data)
> {
> DeviceClass *dc = DEVICE_CLASS(klass);
> + ResettableClass *rc = RESETTABLE_CLASS(klass);
>
> device_class_set_props(dc, riscv_aplic_properties);
> dc->realize = riscv_aplic_realize;
> + rc->phases.enter = riscv_aplic_reset_enter;
> dc->vmsd = &vmstate_riscv_aplic;
> }
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/4] hw/intc: riscv_imsic: Add reset API to IMSIC
2026-04-28 16:00 [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices Jim Shu
2026-04-28 16:01 ` [PATCH 1/4] hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode Jim Shu
2026-04-28 16:01 ` [PATCH 2/4] hw/intc: riscv_aplic: Add reset API to APLIC Jim Shu
@ 2026-04-28 16:01 ` Jim Shu
2026-05-18 12:20 ` Daniel Henrique Barboza
2026-04-28 16:01 ` [PATCH 4/4] hw/intc: riscv_aplic: add trace events of APLIC read/write function Jim Shu
2026-05-19 4:46 ` [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices Alistair Francis
4 siblings, 1 reply; 11+ messages in thread
From: Jim Shu @ 2026-04-28 16:01 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Jim Shu
Clearing IMSIC registers and qemu_irq in the reset function
Signed-off-by: Jim Shu <jim.shu@sifive.com>
---
hw/intc/riscv_imsic.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index 7c9a0120335..ac59496c22b 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -342,6 +342,23 @@ static const MemoryRegionOps riscv_imsic_ops = {
}
};
+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);
+
+ 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]);
+ }
+}
+
static void riscv_imsic_realize(DeviceState *dev, Error **errp)
{
RISCVIMSICState *imsic = RISCV_IMSIC(dev);
@@ -425,9 +442,11 @@ static const VMStateDescription vmstate_riscv_imsic = {
static void riscv_imsic_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
device_class_set_props(dc, riscv_imsic_properties);
dc->realize = riscv_imsic_realize;
+ rc->phases.enter = riscv_imsic_reset_enter;
dc->vmsd = &vmstate_riscv_imsic;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 3/4] hw/intc: riscv_imsic: Add reset API to IMSIC
2026-04-28 16:01 ` [PATCH 3/4] hw/intc: riscv_imsic: Add reset API to IMSIC Jim Shu
@ 2026-05-18 12:20 ` Daniel Henrique Barboza
0 siblings, 0 replies; 11+ messages in thread
From: Daniel Henrique Barboza @ 2026-05-18 12:20 UTC (permalink / raw)
To: Jim Shu, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li, Liu Zhiwei, Chao Liu
On 4/28/2026 1:01 PM, Jim Shu wrote:
> Clearing IMSIC registers and qemu_irq in the reset function
>
> Signed-off-by: Jim Shu <jim.shu@sifive.com>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> hw/intc/riscv_imsic.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
> index 7c9a0120335..ac59496c22b 100644
> --- a/hw/intc/riscv_imsic.c
> +++ b/hw/intc/riscv_imsic.c
> @@ -342,6 +342,23 @@ static const MemoryRegionOps riscv_imsic_ops = {
> }
> };
>
> +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);
> +
> + 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]);
> + }
> +}
> +
> static void riscv_imsic_realize(DeviceState *dev, Error **errp)
> {
> RISCVIMSICState *imsic = RISCV_IMSIC(dev);
> @@ -425,9 +442,11 @@ static const VMStateDescription vmstate_riscv_imsic = {
> static void riscv_imsic_class_init(ObjectClass *klass, const void *data)
> {
> DeviceClass *dc = DEVICE_CLASS(klass);
> + ResettableClass *rc = RESETTABLE_CLASS(klass);
>
> device_class_set_props(dc, riscv_imsic_properties);
> dc->realize = riscv_imsic_realize;
> + rc->phases.enter = riscv_imsic_reset_enter;
> dc->vmsd = &vmstate_riscv_imsic;
> }
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/4] hw/intc: riscv_aplic: add trace events of APLIC read/write function
2026-04-28 16:00 [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices Jim Shu
` (2 preceding siblings ...)
2026-04-28 16:01 ` [PATCH 3/4] hw/intc: riscv_imsic: Add reset API to IMSIC Jim Shu
@ 2026-04-28 16:01 ` Jim Shu
2026-05-18 12:20 ` Daniel Henrique Barboza
2026-05-19 4:46 ` [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices Alistair Francis
4 siblings, 1 reply; 11+ messages in thread
From: Jim Shu @ 2026-04-28 16:01 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Jim Shu
Add the trace events for APLIC read/write functions.
Signed-off-by: Jim Shu <jim.shu@sifive.com>
---
hw/intc/riscv_aplic.c | 63 ++++++++++++++++++++++++++-----------------
hw/intc/trace-events | 4 +++
2 files changed, 42 insertions(+), 25 deletions(-)
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index a04e0e1a898..55515d1a085 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -35,6 +35,7 @@
#include "system/tcg.h"
#include "kvm/kvm_riscv.h"
#include "migration/vmstate.h"
+#include "trace.h"
#define APLIC_MAX_IDC (1UL << 14)
#define APLIC_MAX_SOURCE 1024
@@ -626,6 +627,7 @@ static void riscv_aplic_request(void *opaque, int irq, int level)
static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
{
uint32_t irq, word, idc;
+ uint64_t val;
RISCVAPLICState *aplic = opaque;
/* Reads must be 4 byte words */
@@ -634,18 +636,18 @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
}
if (addr == APLIC_DOMAINCFG) {
- return APLIC_DOMAINCFG_RDONLY | aplic->domaincfg |
- (aplic->msimode ? APLIC_DOMAINCFG_DM : 0);
+ val = APLIC_DOMAINCFG_RDONLY | aplic->domaincfg |
+ (aplic->msimode ? APLIC_DOMAINCFG_DM : 0);
} else if ((APLIC_SOURCECFG_BASE <= addr) &&
(addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) {
irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1;
- return aplic->sourcecfg[irq];
+ val = aplic->sourcecfg[irq];
} else if (aplic->mmode && aplic->msimode &&
(addr == APLIC_MMSICFGADDR)) {
- return aplic->mmsicfgaddr;
+ val = aplic->mmsicfgaddr;
} else if (aplic->mmode && aplic->msimode &&
(addr == APLIC_MMSICFGADDRH)) {
- return aplic->mmsicfgaddrH;
+ val = aplic->mmsicfgaddrH;
} else if (aplic->mmode && aplic->msimode &&
(addr == APLIC_SMSICFGADDR)) {
/*
@@ -657,65 +659,74 @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
* only zero in at least one of the supervisor-level child
* domains).
*/
- return (aplic->num_children) ? aplic->smsicfgaddr : 0;
+ val = (aplic->num_children) ? aplic->smsicfgaddr : 0;
} else if (aplic->mmode && aplic->msimode &&
(addr == APLIC_SMSICFGADDRH)) {
- return (aplic->num_children) ? aplic->smsicfgaddrH : 0;
+ val = (aplic->num_children) ? aplic->smsicfgaddrH : 0;
} else if ((APLIC_SETIP_BASE <= addr) &&
(addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) {
word = (addr - APLIC_SETIP_BASE) >> 2;
- return riscv_aplic_read_pending_word(aplic, word);
+ val = riscv_aplic_read_pending_word(aplic, word);
} else if (addr == APLIC_SETIPNUM) {
- return 0;
+ val = 0;
} else if ((APLIC_CLRIP_BASE <= addr) &&
(addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) {
word = (addr - APLIC_CLRIP_BASE) >> 2;
- return riscv_aplic_read_input_word(aplic, word);
+ val = riscv_aplic_read_input_word(aplic, word);
} else if (addr == APLIC_CLRIPNUM) {
- return 0;
+ val = 0;
} else if ((APLIC_SETIE_BASE <= addr) &&
(addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) {
word = (addr - APLIC_SETIE_BASE) >> 2;
- return riscv_aplic_read_enabled_word(aplic, word);
+ val = riscv_aplic_read_enabled_word(aplic, word);
} else if (addr == APLIC_SETIENUM) {
- return 0;
+ val = 0;
} else if ((APLIC_CLRIE_BASE <= addr) &&
(addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) {
- return 0;
+ val = 0;
} else if (addr == APLIC_CLRIENUM) {
- return 0;
+ val = 0;
} else if (addr == APLIC_SETIPNUM_LE) {
- return 0;
+ val = 0;
} else if (addr == APLIC_SETIPNUM_BE) {
- return 0;
+ val = 0;
} else if (addr == APLIC_GENMSI) {
- return (aplic->msimode) ? aplic->genmsi : 0;
+ val = (aplic->msimode) ? aplic->genmsi : 0;
} else if ((APLIC_TARGET_BASE <= addr) &&
(addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) {
irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1;
if (!riscv_aplic_source_active(aplic, irq)) {
- return 0;
+ val = 0;
+ } else {
+ val = aplic->target[irq];
}
- return aplic->target[irq];
} else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) &&
(addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) {
idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE;
switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) {
case APLIC_IDC_IDELIVERY:
- return aplic->idelivery[idc];
+ val = aplic->idelivery[idc];
+ break;
case APLIC_IDC_IFORCE:
- return aplic->iforce[idc];
+ val = aplic->iforce[idc];
+ break;
case APLIC_IDC_ITHRESHOLD:
- return aplic->ithreshold[idc];
+ val = aplic->ithreshold[idc];
+ break;
case APLIC_IDC_TOPI:
- return riscv_aplic_idc_topi(aplic, idc);
+ val = riscv_aplic_idc_topi(aplic, idc);
+ break;
case APLIC_IDC_CLAIMI:
- return riscv_aplic_idc_claimi(aplic, idc);
+ val = riscv_aplic_idc_claimi(aplic, idc);
+ break;
default:
goto err;
};
}
+ trace_riscv_aplic_read(addr, size, val);
+ return val;
+
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register read 0x%" HWADDR_PRIx "\n",
@@ -734,6 +745,8 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value,
goto err;
}
+ trace_riscv_aplic_write(addr, size, value);
+
if (addr == APLIC_DOMAINCFG) {
/* Only IE bit writable at the moment */
value &= APLIC_DOMAINCFG_IE;
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 018c609ca5e..36ea75049ab 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -330,3 +330,7 @@ loongarch_msi_set_irq(int irq_num) "set msi irq %d"
loongarch_extioi_setirq(int irq, int level) "set extirq irq %d level %d"
loongarch_extioi_readw(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64
loongarch_extioi_writew(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64
+
+# riscv_aplic.c
+riscv_aplic_read(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64
+riscv_aplic_write(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64
--
2.43.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 4/4] hw/intc: riscv_aplic: add trace events of APLIC read/write function
2026-04-28 16:01 ` [PATCH 4/4] hw/intc: riscv_aplic: add trace events of APLIC read/write function Jim Shu
@ 2026-05-18 12:20 ` Daniel Henrique Barboza
0 siblings, 0 replies; 11+ messages in thread
From: Daniel Henrique Barboza @ 2026-05-18 12:20 UTC (permalink / raw)
To: Jim Shu, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li, Liu Zhiwei, Chao Liu
On 4/28/2026 1:01 PM, Jim Shu wrote:
> Add the trace events for APLIC read/write functions.
>
> Signed-off-by: Jim Shu <jim.shu@sifive.com>
> ---
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
> hw/intc/riscv_aplic.c | 63 ++++++++++++++++++++++++++-----------------
> hw/intc/trace-events | 4 +++
> 2 files changed, 42 insertions(+), 25 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index a04e0e1a898..55515d1a085 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -35,6 +35,7 @@
> #include "system/tcg.h"
> #include "kvm/kvm_riscv.h"
> #include "migration/vmstate.h"
> +#include "trace.h"
>
> #define APLIC_MAX_IDC (1UL << 14)
> #define APLIC_MAX_SOURCE 1024
> @@ -626,6 +627,7 @@ static void riscv_aplic_request(void *opaque, int irq, int level)
> static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
> {
> uint32_t irq, word, idc;
> + uint64_t val;
> RISCVAPLICState *aplic = opaque;
>
> /* Reads must be 4 byte words */
> @@ -634,18 +636,18 @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
> }
>
> if (addr == APLIC_DOMAINCFG) {
> - return APLIC_DOMAINCFG_RDONLY | aplic->domaincfg |
> - (aplic->msimode ? APLIC_DOMAINCFG_DM : 0);
> + val = APLIC_DOMAINCFG_RDONLY | aplic->domaincfg |
> + (aplic->msimode ? APLIC_DOMAINCFG_DM : 0);
> } else if ((APLIC_SOURCECFG_BASE <= addr) &&
> (addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) {
> irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1;
> - return aplic->sourcecfg[irq];
> + val = aplic->sourcecfg[irq];
> } else if (aplic->mmode && aplic->msimode &&
> (addr == APLIC_MMSICFGADDR)) {
> - return aplic->mmsicfgaddr;
> + val = aplic->mmsicfgaddr;
> } else if (aplic->mmode && aplic->msimode &&
> (addr == APLIC_MMSICFGADDRH)) {
> - return aplic->mmsicfgaddrH;
> + val = aplic->mmsicfgaddrH;
> } else if (aplic->mmode && aplic->msimode &&
> (addr == APLIC_SMSICFGADDR)) {
> /*
> @@ -657,65 +659,74 @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size)
> * only zero in at least one of the supervisor-level child
> * domains).
> */
> - return (aplic->num_children) ? aplic->smsicfgaddr : 0;
> + val = (aplic->num_children) ? aplic->smsicfgaddr : 0;
> } else if (aplic->mmode && aplic->msimode &&
> (addr == APLIC_SMSICFGADDRH)) {
> - return (aplic->num_children) ? aplic->smsicfgaddrH : 0;
> + val = (aplic->num_children) ? aplic->smsicfgaddrH : 0;
> } else if ((APLIC_SETIP_BASE <= addr) &&
> (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) {
> word = (addr - APLIC_SETIP_BASE) >> 2;
> - return riscv_aplic_read_pending_word(aplic, word);
> + val = riscv_aplic_read_pending_word(aplic, word);
> } else if (addr == APLIC_SETIPNUM) {
> - return 0;
> + val = 0;
> } else if ((APLIC_CLRIP_BASE <= addr) &&
> (addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) {
> word = (addr - APLIC_CLRIP_BASE) >> 2;
> - return riscv_aplic_read_input_word(aplic, word);
> + val = riscv_aplic_read_input_word(aplic, word);
> } else if (addr == APLIC_CLRIPNUM) {
> - return 0;
> + val = 0;
> } else if ((APLIC_SETIE_BASE <= addr) &&
> (addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) {
> word = (addr - APLIC_SETIE_BASE) >> 2;
> - return riscv_aplic_read_enabled_word(aplic, word);
> + val = riscv_aplic_read_enabled_word(aplic, word);
> } else if (addr == APLIC_SETIENUM) {
> - return 0;
> + val = 0;
> } else if ((APLIC_CLRIE_BASE <= addr) &&
> (addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) {
> - return 0;
> + val = 0;
> } else if (addr == APLIC_CLRIENUM) {
> - return 0;
> + val = 0;
> } else if (addr == APLIC_SETIPNUM_LE) {
> - return 0;
> + val = 0;
> } else if (addr == APLIC_SETIPNUM_BE) {
> - return 0;
> + val = 0;
> } else if (addr == APLIC_GENMSI) {
> - return (aplic->msimode) ? aplic->genmsi : 0;
> + val = (aplic->msimode) ? aplic->genmsi : 0;
> } else if ((APLIC_TARGET_BASE <= addr) &&
> (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) {
> irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1;
> if (!riscv_aplic_source_active(aplic, irq)) {
> - return 0;
> + val = 0;
> + } else {
> + val = aplic->target[irq];
> }
> - return aplic->target[irq];
> } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) &&
> (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) {
> idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE;
> switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) {
> case APLIC_IDC_IDELIVERY:
> - return aplic->idelivery[idc];
> + val = aplic->idelivery[idc];
> + break;
> case APLIC_IDC_IFORCE:
> - return aplic->iforce[idc];
> + val = aplic->iforce[idc];
> + break;
> case APLIC_IDC_ITHRESHOLD:
> - return aplic->ithreshold[idc];
> + val = aplic->ithreshold[idc];
> + break;
> case APLIC_IDC_TOPI:
> - return riscv_aplic_idc_topi(aplic, idc);
> + val = riscv_aplic_idc_topi(aplic, idc);
> + break;
> case APLIC_IDC_CLAIMI:
> - return riscv_aplic_idc_claimi(aplic, idc);
> + val = riscv_aplic_idc_claimi(aplic, idc);
> + break;
> default:
> goto err;
> };
> }
>
> + trace_riscv_aplic_read(addr, size, val);
> + return val;
> +
> err:
> qemu_log_mask(LOG_GUEST_ERROR,
> "%s: Invalid register read 0x%" HWADDR_PRIx "\n",
> @@ -734,6 +745,8 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value,
> goto err;
> }
>
> + trace_riscv_aplic_write(addr, size, value);
> +
> if (addr == APLIC_DOMAINCFG) {
> /* Only IE bit writable at the moment */
> value &= APLIC_DOMAINCFG_IE;
> diff --git a/hw/intc/trace-events b/hw/intc/trace-events
> index 018c609ca5e..36ea75049ab 100644
> --- a/hw/intc/trace-events
> +++ b/hw/intc/trace-events
> @@ -330,3 +330,7 @@ loongarch_msi_set_irq(int irq_num) "set msi irq %d"
> loongarch_extioi_setirq(int irq, int level) "set extirq irq %d level %d"
> loongarch_extioi_readw(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64
> loongarch_extioi_writew(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64
> +
> +# riscv_aplic.c
> +riscv_aplic_read(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64
> +riscv_aplic_write(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices
2026-04-28 16:00 [PATCH 0/4] Minor fixes and enhancements of RISC-V AIA devices Jim Shu
` (3 preceding siblings ...)
2026-04-28 16:01 ` [PATCH 4/4] hw/intc: riscv_aplic: add trace events of APLIC read/write function Jim Shu
@ 2026-05-19 4:46 ` Alistair Francis
4 siblings, 0 replies; 11+ messages in thread
From: Alistair Francis @ 2026-05-19 4:46 UTC (permalink / raw)
To: Jim Shu
Cc: qemu-devel, qemu-riscv, Palmer Dabbelt, Alistair Francis,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, Chao Liu
On Wed, Apr 29, 2026 at 2:04 AM Jim Shu <jim.shu@sifive.com> wrote:
>
> Bugfix:
> - APLIC should also clear pending bit from rectified value when it is
> in the both level-trigger mode and direct delivery mode.
>
> Enhancements:
> - Add reset API to APLIC and IMSIC device
> - Add trace events of APLIC read/write function
>
> Jim Shu (4):
> hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode
> hw/intc: riscv_aplic: Add reset API to APLIC
> hw/intc: riscv_imsic: Add reset API to IMSIC
> hw/intc: riscv_aplic: add trace events of APLIC read/write function
Thanks!
Applied to riscv-to-apply.next
Alistair
>
> hw/intc/riscv_aplic.c | 116 +++++++++++++++++++++++++++++-------------
> hw/intc/riscv_imsic.c | 19 +++++++
> hw/intc/trace-events | 4 ++
> 3 files changed, 105 insertions(+), 34 deletions(-)
>
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread