* [PATCH 0/2] hw/riscv/riscv-iommu: Bug fixes and IPSR.PMIP support
@ 2026-03-04 4:09 Jay Chang
2026-03-04 4:09 ` [PATCH 1/2] hw/riscv/riscv-iommu-hpm: Fix irq_overflow_left residual value bug Jay Chang
2026-03-04 4:09 ` [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support Jay Chang
0 siblings, 2 replies; 6+ messages in thread
From: Jay Chang @ 2026-03-04 4:09 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Jay Chang
This series contains two fixes for the RISC-V IOMMU implementation:
1. Fix a bug in the HPM (Hardware Performance Monitor) timer setup where
irq_overflow_left was not properly reset, causing stale values from
previous timer setups to affect new timer behavior.
2. Add proper RW1C (Read/Write 1 to Clear) support for the IPSR.PMIP
(Performance Monitor Interrupt Pending) bit, which was missing from
the IPSR register implementation.
Jay Chang (2):
hw/riscv/riscv-iommu-hpm: Fix irq_overflow_left residual value bug
hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support
hw/riscv/riscv-iommu-bits.h | 1 +
hw/riscv/riscv-iommu-hpm.c | 1 +
hw/riscv/riscv-iommu.c | 4 ++++
3 files changed, 6 insertions(+)
--
2.48.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] hw/riscv/riscv-iommu-hpm: Fix irq_overflow_left residual value bug
2026-03-04 4:09 [PATCH 0/2] hw/riscv/riscv-iommu: Bug fixes and IPSR.PMIP support Jay Chang
@ 2026-03-04 4:09 ` Jay Chang
2026-03-04 13:20 ` Chao Liu
2026-03-04 4:09 ` [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support Jay Chang
1 sibling, 1 reply; 6+ messages in thread
From: Jay Chang @ 2026-03-04 4:09 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Jay Chang,
Frank Chang
Reset irq_overflow_left to 0 before setting up a new timer. Without
this fix, a stale irq_overflow_left value from a previous timer setup
could cause incorrect timer behavior.
Signed-off-by: Jay Chang <jay.chang@sifive.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
---
hw/riscv/riscv-iommu-hpm.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/riscv/riscv-iommu-hpm.c b/hw/riscv/riscv-iommu-hpm.c
index c5034bff79..e8d284ac8b 100644
--- a/hw/riscv/riscv-iommu-hpm.c
+++ b/hw/riscv/riscv-iommu-hpm.c
@@ -228,6 +228,7 @@ static void hpm_setup_timer(RISCVIOMMUState *s, uint64_t value)
}
overflow_at = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + overflow_ns;
+ s->irq_overflow_left = 0;
if (overflow_at > INT64_MAX) {
s->irq_overflow_left = overflow_at - INT64_MAX;
--
2.48.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support
2026-03-04 4:09 [PATCH 0/2] hw/riscv/riscv-iommu: Bug fixes and IPSR.PMIP support Jay Chang
2026-03-04 4:09 ` [PATCH 1/2] hw/riscv/riscv-iommu-hpm: Fix irq_overflow_left residual value bug Jay Chang
@ 2026-03-04 4:09 ` Jay Chang
2026-03-04 10:13 ` Nutty.Liu
2026-03-04 13:29 ` Chao Liu
1 sibling, 2 replies; 6+ messages in thread
From: Jay Chang @ 2026-03-04 4:09 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Jay Chang,
Frank Chang
Signed-off-by: Jay Chang <jay.chang@sifive.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
---
hw/riscv/riscv-iommu-bits.h | 1 +
hw/riscv/riscv-iommu.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
index 47fe01bee5..a938fd3eb4 100644
--- a/hw/riscv/riscv-iommu-bits.h
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -189,6 +189,7 @@ enum riscv_iommu_ddtp_modes {
#define RISCV_IOMMU_REG_IPSR 0x0054
#define RISCV_IOMMU_IPSR_CIP BIT(0)
#define RISCV_IOMMU_IPSR_FIP BIT(1)
+#define RISCV_IOMMU_IPSR_PMIP BIT(2)
#define RISCV_IOMMU_IPSR_PIP BIT(3)
enum {
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 98345b1280..610cdebac2 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -2153,6 +2153,10 @@ static void riscv_iommu_update_ipsr(RISCVIOMMUState *s, uint64_t data)
ipsr_clr |= RISCV_IOMMU_IPSR_FIP;
}
+ if (!(data & RISCV_IOMMU_IPSR_PMIP)) {
+ ipsr_clr |= RISCV_IOMMU_IPSR_PMIP;
+ }
+
if (data & RISCV_IOMMU_IPSR_PIP) {
pqcsr = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQCSR);
--
2.48.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support
2026-03-04 4:09 ` [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support Jay Chang
@ 2026-03-04 10:13 ` Nutty.Liu
2026-03-04 13:29 ` Chao Liu
1 sibling, 0 replies; 6+ messages in thread
From: Nutty.Liu @ 2026-03-04 10:13 UTC (permalink / raw)
To: Jay Chang, qemu-devel, qemu-riscv
Cc: Palmer Dabbelt, Alistair Francis, Weiwei Li,
Daniel Henrique Barboza, Liu Zhiwei, Chao Liu, Frank Chang
On 3/4/2026 12:09 PM, Jay Chang wrote:
> Signed-off-by: Jay Chang <jay.chang@sifive.com>
> Reviewed-by: Frank Chang <frank.chang@sifive.com>
> ---
> hw/riscv/riscv-iommu-bits.h | 1 +
> hw/riscv/riscv-iommu.c | 4 ++++
> 2 files changed, 5 insertions(+)
>
> diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
> index 47fe01bee5..a938fd3eb4 100644
> --- a/hw/riscv/riscv-iommu-bits.h
> +++ b/hw/riscv/riscv-iommu-bits.h
> @@ -189,6 +189,7 @@ enum riscv_iommu_ddtp_modes {
> #define RISCV_IOMMU_REG_IPSR 0x0054
> #define RISCV_IOMMU_IPSR_CIP BIT(0)
> #define RISCV_IOMMU_IPSR_FIP BIT(1)
> +#define RISCV_IOMMU_IPSR_PMIP BIT(2)
> #define RISCV_IOMMU_IPSR_PIP BIT(3)
>
> enum {
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index 98345b1280..610cdebac2 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -2153,6 +2153,10 @@ static void riscv_iommu_update_ipsr(RISCVIOMMUState *s, uint64_t data)
> ipsr_clr |= RISCV_IOMMU_IPSR_FIP;
> }
>
> + if (!(data & RISCV_IOMMU_IPSR_PMIP)) {
> + ipsr_clr |= RISCV_IOMMU_IPSR_PMIP;
> + }
> +
According to the following description of 'pmip' in the specification:
"The performance-monitoring-interrupt-pending is set to 1 when OF bit
iniohpmcycles or in any of the iohpmctr1-31 registers transitions
from 0 to 1."
Would it be better to handle like the following ?
if (data & RISCV_IOMMU_IPSR_PMIP) {
ipsr_set ...
} else {
ipsr_clr ...
}
Otherwise,
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
> if (data & RISCV_IOMMU_IPSR_PIP) {
> pqcsr = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQCSR);
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] hw/riscv/riscv-iommu-hpm: Fix irq_overflow_left residual value bug
2026-03-04 4:09 ` [PATCH 1/2] hw/riscv/riscv-iommu-hpm: Fix irq_overflow_left residual value bug Jay Chang
@ 2026-03-04 13:20 ` Chao Liu
0 siblings, 0 replies; 6+ messages in thread
From: Chao Liu @ 2026-03-04 13:20 UTC (permalink / raw)
To: Jay Chang
Cc: qemu-devel, qemu-riscv, Palmer Dabbelt, Alistair Francis,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, Frank Chang
On Wed, Mar 04, 2026 at 12:09:58PM +0800, Jay Chang wrote:
> Reset irq_overflow_left to 0 before setting up a new timer. Without
> this fix, a stale irq_overflow_left value from a previous timer setup
> could cause incorrect timer behavior.
>
> Signed-off-by: Jay Chang <jay.chang@sifive.com>
> Reviewed-by: Frank Chang <frank.chang@sifive.com>
> ---
> hw/riscv/riscv-iommu-hpm.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/hw/riscv/riscv-iommu-hpm.c b/hw/riscv/riscv-iommu-hpm.c
> index c5034bff79..e8d284ac8b 100644
> --- a/hw/riscv/riscv-iommu-hpm.c
> +++ b/hw/riscv/riscv-iommu-hpm.c
> @@ -228,6 +228,7 @@ static void hpm_setup_timer(RISCVIOMMUState *s, uint64_t value)
> }
>
> overflow_at = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + overflow_ns;
> + s->irq_overflow_left = 0;
>
Looks good. Without this reset, if a previous call set
irq_overflow_left (overflow_at > INT64_MAX) and the current
call does NOT overflow, the stale value persists and the
two-phase timer fires incorrectly.
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Best regards,
Chao Liu
> if (overflow_at > INT64_MAX) {
> s->irq_overflow_left = overflow_at - INT64_MAX;
> --
> 2.48.1
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support
2026-03-04 4:09 ` [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support Jay Chang
2026-03-04 10:13 ` Nutty.Liu
@ 2026-03-04 13:29 ` Chao Liu
1 sibling, 0 replies; 6+ messages in thread
From: Chao Liu @ 2026-03-04 13:29 UTC (permalink / raw)
To: Jay Chang
Cc: qemu-devel, qemu-riscv, Palmer Dabbelt, Alistair Francis,
Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei, Frank Chang
On Wed, Mar 04, 2026 at 12:09:59PM +0800, Jay Chang wrote:
> Signed-off-by: Jay Chang <jay.chang@sifive.com>
> Reviewed-by: Frank Chang <frank.chang@sifive.com>
The commit message has no body text. Please add a short
description of what PMIP is and why RW1C support is needed,
similar to patch 1's commit message style.
You can copy the second point of the cover letter too:
2. Add proper RW1C (Read/Write 1 to Clear) support for the IPSR.PMIP
(Performance Monitor Interrupt Pending) bit, which was missing from
the IPSR register implementation.
> ---
> hw/riscv/riscv-iommu-bits.h | 1 +
> hw/riscv/riscv-iommu.c | 4 ++++
> 2 files changed, 5 insertions(+)
>
> diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
> index 47fe01bee5..a938fd3eb4 100644
> --- a/hw/riscv/riscv-iommu-bits.h
> +++ b/hw/riscv/riscv-iommu-bits.h
> @@ -189,6 +189,7 @@ enum riscv_iommu_ddtp_modes {
> #define RISCV_IOMMU_REG_IPSR 0x0054
> #define RISCV_IOMMU_IPSR_CIP BIT(0)
> #define RISCV_IOMMU_IPSR_FIP BIT(1)
> +#define RISCV_IOMMU_IPSR_PMIP BIT(2)
> #define RISCV_IOMMU_IPSR_PIP BIT(3)
>
Good, BIT(2) matches the IOMMU spec for PMIP.
> enum {
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index 98345b1280..610cdebac2 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -2153,6 +2153,10 @@ static void riscv_iommu_update_ipsr(RISCVIOMMUState *s, uint64_t data)
> ipsr_clr |= RISCV_IOMMU_IPSR_FIP;
> }
>
> + if (!(data & RISCV_IOMMU_IPSR_PMIP)) {
This works correctly in practice because `data` (the val
computed by riscv_iommu_write_reg_val) is always 0 for
IPSR writes — regs_wc is ~0 and regs_ro is 0, so the
formula yields data & ~data = 0. The condition
`!(0 & PMIP)` is always true, so PMIP is always cleared.
That said, since `data` is always 0 here, you could
simplify this to just:
ipsr_clr |= RISCV_IOMMU_IPSR_PMIP;
without the conditional. This would also be more
consistent with the effective behavior of the CIP/FIP/PIP
branches (which always take the "else" / clear path for
the same reason).
Not a blocker — the current code is correct. Just a
suggestion for clarity.
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Best regards,
Chao Liu
> + ipsr_clr |= RISCV_IOMMU_IPSR_PMIP;
> + }
> +
> if (data & RISCV_IOMMU_IPSR_PIP) {
> pqcsr = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQCSR);
>
> --
> 2.48.1
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-03-04 13:30 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-04 4:09 [PATCH 0/2] hw/riscv/riscv-iommu: Bug fixes and IPSR.PMIP support Jay Chang
2026-03-04 4:09 ` [PATCH 1/2] hw/riscv/riscv-iommu-hpm: Fix irq_overflow_left residual value bug Jay Chang
2026-03-04 13:20 ` Chao Liu
2026-03-04 4:09 ` [PATCH 2/2] hw/riscv/riscv-iommu: Add IPSR.PMIP RW1C support Jay Chang
2026-03-04 10:13 ` Nutty.Liu
2026-03-04 13:29 ` Chao Liu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.