* [PATCH v7 0/2] RISC-V IOMMU HPM support
@ 2026-08-28 7:07 Zong Li
2026-08-28 7:07 ` [PATCH v7 1/2] iommu/riscv: create a auxiliary device for HPM Zong Li
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Zong Li @ 2026-08-28 7:07 UTC (permalink / raw)
To: tomasz.jeznach, joro, will, robin.murphy, pjw, palmer, aou, alex,
mark.rutland, andrew.jones, guoren, david.laight.linux,
zhangzhanpeng.jasper, yang.yicong, iommu, linux-riscv,
linux-kernel, linux-perf-users
Cc: Zong Li
This series implements support for the RISC-V IOMMU hardware performance
monitor.
The RISC-V IOMMU PMU driver is implemented as an auxiliary device driver
created by the parent RISC-V IOMMU driver. Therefore, the child driver
can obtain resources and information from the parent device, such as
the MMIO base address and IRQ number.
The thrid commit adds raw spinlock for race condition when PCI MSI/MSI-X
on IMSIC. As the commit message mentioned:
Events are bound to one CPU and the interrupt is affine to it, so the
perf callbacks running with interrupts disabled would be enough to
exclude the handler. But PCI MSI/MSI-X on IMSIC breaks that:
The irqchip sets IRQCHIP_MOVE_DEFERRED, so irq_set_affinity() reports
success while only recording the request, and the move is applied in
interrupt context upon the next device interrupt. Until then the
interrupt is still routed to the CPU IMSIC picked initially, so the
first overflow interrupt can run concurrently with the perf callbacks
on the CPU the events are bound to.
I noticed that xgene_pmu and arm-cci have similar implementation, so add
it in riscv_iommu_pmu should be accepted.
Changed in v6:
- Rebased onto the latest v7.3-rc
- Use sysfs_emit instead of cpumap_print_to_pagebuf
- Set up on_cpu and irq affinity by cpuhp callbacks
- Change type of on_cpu from unsigned int to int
- Reject filter operands of cycle event in event_init
- Check return value of counter number and masks in probe
- Add raw spinlock for race condition (third commit)
Changed in v5:
- Pick up suggestions from sashiko-bot as follows
- Fix event group validation for sw event
- Bind IRQ to aux PMU dev instead of parent IOMMU dev
- Clear OF bit when event is NULL
- Improve hi-lo-hi patten
- Add back IRQF_SHARED flag due to mismatch
- Manage cpuhp and pmu register by devre
Changed in v4:
- Rebased onto v7.3-rc
- Use is_sampling_event() instead of accessing vairable directly
- Rename the matching name from "iommu.pmu" to "riscv-iommu.pmu"
- Change the naming of PMU device for avoid ":" in PCIe case
- Add suppress_bind_attrs attribute
- Remove IRQF_SHARED flag
- Set irq affinity to local CPU of IOMMU
- Allocate ID by IDA for auxiliary device
- Pick up suggestions from sashiko-bot
Changed in v3:
- Rebased onto v7.2-rc3
- Use hi_lo_writeq/readq to access register
- Pick comments from sashiko-bot as follows
- Set IRQ CPU affinity
- Remove IRQF_ONESHOT flag when request irq
- Adjust cycle event check by checking event_id field only
- Fix bug for group events verificaiton
- Fix KASAN issue about casting 32-bit variable to unsigned long pointer
- Clear IPSR pending bit before starting counter
- Clear OF bit in event selector register in irq handler
- Release irq by devm instead of explicit free_irq
Changed in v2:
- Rebased onto v7.2-rc1
- Use hi-lo-hi mechanism to read counter.
Suggested by Guo Ren and David Laight
Changed in v1:
- Rebased onto v6.19-rc8
- Pick all suggestions and feedbacks from v1 series
- Add cpu hotplug implementation to avoid race enablement
- Move PMU-related definition from header to c file
- Change PMU driver to auxiliary device driver
Changed in RFC:
- Rebase onto v6.13-rc7
- Clear interrupt pending before handling interrupt
- Fix the counter value issue caused by OF bit in the cycle counter.
- Invoke riscv_iommu_hpm_disable() instead of riscv_iommu_pmu_uninit()
in riscv_iommu_remove()
Zong Li (2):
iommu/riscv: create a auxiliary device for HPM
drivers/perf: riscv-iommu: protect shared state with a raw spinlock
drivers/iommu/riscv/Kconfig | 1 +
drivers/iommu/riscv/iommu.c | 37 +++++++++++++++++++
drivers/perf/riscv_iommu_pmu.c | 66 ++++++++++++++++++++++++++++++----
3 files changed, 98 insertions(+), 6 deletions(-)
--
2.43.7
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v7 1/2] iommu/riscv: create a auxiliary device for HPM
2026-08-28 7:07 [PATCH v7 0/2] RISC-V IOMMU HPM support Zong Li
@ 2026-08-28 7:07 ` Zong Li
2026-08-28 7:07 ` [PATCH v7 2/2] drivers/perf: riscv-iommu: protect shared state with a raw spinlock Zong Li
2026-08-28 8:49 ` [PATCH v7 0/2] RISC-V IOMMU HPM support Guo Ren
2 siblings, 0 replies; 5+ messages in thread
From: Zong Li @ 2026-08-28 7:07 UTC (permalink / raw)
To: tomasz.jeznach, joro, will, robin.murphy, pjw, palmer, aou, alex,
mark.rutland, andrew.jones, guoren, david.laight.linux,
zhangzhanpeng.jasper, yang.yicong, iommu, linux-riscv,
linux-kernel, linux-perf-users
Cc: Zong Li, Chen Pei, Fangyu Yu, Samuel Holland
Create an auxiliary device for HPM when the IOMMU supports a
hardware performance monitor.
Tested-by: Chen Pei <cp0613@linux.alibaba.com>
Tested-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>
Reviewed-by: Guo Ren <guoren@kernel.org>
Reviewed-by: Yicong Yang <yang.yicong@picoheart.com>
Suggested-by: Samuel Holland <samuel.holland@sifive.com>
Signed-off-by: Zong Li <zong.li@sifive.com>
---
drivers/iommu/riscv/Kconfig | 1 +
drivers/iommu/riscv/iommu.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/drivers/iommu/riscv/Kconfig b/drivers/iommu/riscv/Kconfig
index b86e5ab94183..8025bf0fb67f 100644
--- a/drivers/iommu/riscv/Kconfig
+++ b/drivers/iommu/riscv/Kconfig
@@ -10,6 +10,7 @@ config RISCV_IOMMU
select GENERIC_PT
select IOMMU_PT
select IOMMU_PT_RISCV64
+ select AUXILIARY_BUS
help
Support for implementations of the RISC-V IOMMU architecture that
complements the RISC-V MMU capabilities, providing similar address
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index cec3ddd7ab10..7f619971bb70 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -14,6 +14,7 @@
#include <linux/acpi.h>
#include <linux/acpi_rimt.h>
+#include <linux/auxiliary_bus.h>
#include <linux/compiler.h>
#include <linux/crash_dump.h>
#include <linux/init.h>
@@ -48,6 +49,9 @@
static DEFINE_IDA(riscv_iommu_pscids);
#define RISCV_IOMMU_MAX_PSCID (BIT(20) - 1)
+/* IOMMU PMU auxiliary device id allocation namespace. */
+static DEFINE_IDA(riscv_iommu_pmu_ida);
+
/* Device resource-managed allocations */
struct riscv_iommu_devres {
void *addr;
@@ -565,6 +569,36 @@ static irqreturn_t riscv_iommu_fltq_process(int irq, void *data)
return IRQ_HANDLED;
}
+/*
+ * IOMMU Hardware performance monitor
+ */
+static void riscv_iommu_pmu_id_free(void *data)
+{
+ ida_free(&riscv_iommu_pmu_ida, (unsigned long)data);
+}
+
+static int riscv_iommu_hpm_enable(struct riscv_iommu_device *iommu)
+{
+ struct auxiliary_device *auxdev;
+ int id, ret;
+
+ id = ida_alloc(&riscv_iommu_pmu_ida, GFP_KERNEL);
+ if (id < 0)
+ return id;
+
+ ret = devm_add_action_or_reset(iommu->dev, riscv_iommu_pmu_id_free,
+ (void *)(unsigned long)id);
+ if (ret)
+ return ret;
+
+ auxdev = __devm_auxiliary_device_create(iommu->dev, "riscv-iommu",
+ "pmu", iommu, id);
+ if (!auxdev)
+ return -ENODEV;
+
+ return 0;
+}
+
/* Lookup and initialize device context info structure. */
static struct riscv_iommu_dc *riscv_iommu_get_dc(struct riscv_iommu_device *iommu,
unsigned int devid)
@@ -1613,6 +1647,9 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
goto err_remove_sysfs;
}
+ if (iommu->caps & RISCV_IOMMU_CAPABILITIES_HPM)
+ riscv_iommu_hpm_enable(iommu);
+
return 0;
err_remove_sysfs:
--
2.43.7
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v7 2/2] drivers/perf: riscv-iommu: protect shared state with a raw spinlock
2026-08-28 7:07 [PATCH v7 0/2] RISC-V IOMMU HPM support Zong Li
2026-08-28 7:07 ` [PATCH v7 1/2] iommu/riscv: create a auxiliary device for HPM Zong Li
@ 2026-08-28 7:07 ` Zong Li
2026-08-28 8:49 ` [PATCH v7 0/2] RISC-V IOMMU HPM support Guo Ren
2 siblings, 0 replies; 5+ messages in thread
From: Zong Li @ 2026-08-28 7:07 UTC (permalink / raw)
To: tomasz.jeznach, joro, will, robin.murphy, pjw, palmer, aou, alex,
mark.rutland, andrew.jones, guoren, david.laight.linux,
zhangzhanpeng.jasper, yang.yicong, iommu, linux-riscv,
linux-kernel, linux-perf-users
Cc: Zong Li
Events are bound to one CPU and the interrupt is affine to it, so the
perf callbacks running with interrupts disabled would be enough to
exclude the handler.
PCI MSI/MSI-X on IMSIC breaks that: the irqchip sets
IRQCHIP_MOVE_DEFERRED, so irq_set_affinity() reports success while only
recording the request, and the move is applied in interrupt context upon
the next device interrupt. Until then the interrupt is still routed to
the CPU IMSIC picked initially, so the first overflow interrupt can run
concurrently with the perf callbacks on the CPU the events are bound to.
Take a raw spinlock, with interrupts disabled so that the handler can
never interrupt a holder on the same CPU, rather than depending on that
irqchip behaviour. It covers the state which is reachable from both
sides:
- IOCOUNTINH is read-modify-written by ->start()/->stop() and is saved
and restored around the whole handler.
- pmu->events[] is written by ->del() and read by the handler.
- hw_perf_event::prev_count is updated by both.
->add() and ->del() call the unlocked __riscv_iommu_pmu_start() and
__riscv_iommu_pmu_stop() so the lock is taken once per callback.
Signed-off-by: Zong Li <zong.li@sifive.com>
---
drivers/perf/riscv_iommu_pmu.c | 66 ++++++++++++++++++++++++++++++----
1 file changed, 60 insertions(+), 6 deletions(-)
diff --git a/drivers/perf/riscv_iommu_pmu.c b/drivers/perf/riscv_iommu_pmu.c
index f6acd56f2f61..ee2f6d1fbece 100644
--- a/drivers/perf/riscv_iommu_pmu.c
+++ b/drivers/perf/riscv_iommu_pmu.c
@@ -101,6 +101,7 @@ struct riscv_iommu_pmu {
u64 event_cntr_mask;
struct perf_event *events[RISCV_IOMMU_HPM_COUNTER_NUM];
DECLARE_BITMAP(used_counters, RISCV_IOMMU_HPM_COUNTER_NUM);
+ raw_spinlock_t lock;
};
#define to_riscv_iommu_pmu(p) (container_of(p, struct riscv_iommu_pmu, pmu))
@@ -485,7 +486,8 @@ static void riscv_iommu_pmu_update(struct perf_event *event)
local64_add(delta, &event->count);
}
-static void riscv_iommu_pmu_start(struct perf_event *event, int flags)
+/* Called with pmu->lock held */
+static void __riscv_iommu_pmu_start(struct perf_event *event, int flags)
{
struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
@@ -500,11 +502,22 @@ static void riscv_iommu_pmu_start(struct perf_event *event, int flags)
riscv_iommu_pmu_set_period(event);
riscv_iommu_pmu_set_event(pmu, hwc->idx, hwc->config);
riscv_iommu_pmu_enable_counter(pmu, hwc->idx);
+}
+
+static void riscv_iommu_pmu_start(struct perf_event *event, int flags)
+{
+ struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu);
+ unsigned long irqflags;
+
+ raw_spin_lock_irqsave(&pmu->lock, irqflags);
+ __riscv_iommu_pmu_start(event, flags);
+ raw_spin_unlock_irqrestore(&pmu->lock, irqflags);
perf_event_update_userpage(event);
}
-static void riscv_iommu_pmu_stop(struct perf_event *event, int flags)
+/* Called with pmu->lock held */
+static void __riscv_iommu_pmu_stop(struct perf_event *event, int flags)
{
struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
@@ -521,13 +534,26 @@ static void riscv_iommu_pmu_stop(struct perf_event *event, int flags)
hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
}
+static void riscv_iommu_pmu_stop(struct perf_event *event, int flags)
+{
+ struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu);
+ unsigned long irqflags;
+
+ raw_spin_lock_irqsave(&pmu->lock, irqflags);
+ __riscv_iommu_pmu_stop(event, flags);
+ raw_spin_unlock_irqrestore(&pmu->lock, irqflags);
+}
+
static int riscv_iommu_pmu_add(struct perf_event *event, int flags)
{
struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
unsigned int num_counters = pmu->num_counters;
+ unsigned long irqflags;
unsigned int idx;
+ raw_spin_lock_irqsave(&pmu->lock, irqflags);
+
/* Reserve index zero for iohpmcycles */
if (is_cycle_event(event->attr.config))
idx = RISCV_IOMMU_HPM_CYCLE_IDX;
@@ -535,8 +561,10 @@ static int riscv_iommu_pmu_add(struct perf_event *event, int flags)
idx = find_next_zero_bit(pmu->used_counters, num_counters, 1);
/* All event counters or cycle counter are in use */
- if (idx == num_counters || pmu->events[idx])
+ if (idx == num_counters || pmu->events[idx]) {
+ raw_spin_unlock_irqrestore(&pmu->lock, irqflags);
return -EAGAIN;
+ }
set_bit(idx, pmu->used_counters);
@@ -546,7 +574,9 @@ static int riscv_iommu_pmu_add(struct perf_event *event, int flags)
local64_set(&hwc->prev_count, 0);
if (flags & PERF_EF_START)
- riscv_iommu_pmu_start(event, flags);
+ __riscv_iommu_pmu_start(event, flags);
+
+ raw_spin_unlock_irqrestore(&pmu->lock, irqflags);
/* Propagate changes to the userspace mapping. */
perf_event_update_userpage(event);
@@ -556,18 +586,26 @@ static int riscv_iommu_pmu_add(struct perf_event *event, int flags)
static void riscv_iommu_pmu_read(struct perf_event *event)
{
+ struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu);
+ unsigned long irqflags;
+
+ raw_spin_lock_irqsave(&pmu->lock, irqflags);
riscv_iommu_pmu_update(event);
+ raw_spin_unlock_irqrestore(&pmu->lock, irqflags);
}
static void riscv_iommu_pmu_del(struct perf_event *event, int flags)
{
struct riscv_iommu_pmu *pmu = to_riscv_iommu_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
+ unsigned long irqflags;
int idx = hwc->idx;
- riscv_iommu_pmu_stop(event, PERF_EF_UPDATE);
+ raw_spin_lock_irqsave(&pmu->lock, irqflags);
+ __riscv_iommu_pmu_stop(event, PERF_EF_UPDATE);
pmu->events[idx] = NULL;
clear_bit(idx, pmu->used_counters);
+ raw_spin_unlock_irqrestore(&pmu->lock, irqflags);
perf_event_update_userpage(event);
}
@@ -635,12 +673,24 @@ static irqreturn_t riscv_iommu_pmu_irq_handler(int irq, void *dev_id)
{
struct riscv_iommu_pmu *pmu = (struct riscv_iommu_pmu *)dev_id;
DECLARE_BITMAP(ovf_bitmap, BITS_PER_TYPE(u64));
+ unsigned long irqflags;
u32 ovf, idx, inhibit;
- /* Check whether this interrupt is for PMU */
+ /*
+ * Check whether this interrupt is for PMU. Done outside the lock so
+ * that a shared interrupt line is left alone as cheaply as possible.
+ */
if (!(readl_relaxed(pmu->reg + RISCV_IOMMU_REG_IPSR) & RISCV_IOMMU_IPSR_PMIP))
return IRQ_NONE;
+ /*
+ * Hold the lock across the whole sequence below. Stopping the
+ * counters, processing them and restoring the previous inhibit state
+ * has to be atomic against ->start()/->stop(), otherwise a counter
+ * enabled in between would be inhibited again by the restore.
+ */
+ raw_spin_lock_irqsave(&pmu->lock, irqflags);
+
/* Process PMU IRQ */
inhibit = riscv_iommu_pmu_stop_all(pmu);
@@ -672,6 +722,8 @@ static irqreturn_t riscv_iommu_pmu_irq_handler(int irq, void *dev_id)
riscv_iommu_pmu_start_all(pmu, inhibit);
+ raw_spin_unlock_irqrestore(&pmu->lock, irqflags);
+
return IRQ_HANDLED;
}
@@ -735,6 +787,8 @@ static int riscv_iommu_pmu_probe(struct auxiliary_device *auxdev,
iommu_pmu->reg = iommu_dev->reg;
+ raw_spin_lock_init(&iommu_pmu->lock);
+
/*
* Counter number and width are hardware-implemented, detect them by
* writing 1s and reading back which bits stuck.
--
2.43.7
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v7 0/2] RISC-V IOMMU HPM support
2026-08-28 7:07 [PATCH v7 0/2] RISC-V IOMMU HPM support Zong Li
2026-08-28 7:07 ` [PATCH v7 1/2] iommu/riscv: create a auxiliary device for HPM Zong Li
2026-08-28 7:07 ` [PATCH v7 2/2] drivers/perf: riscv-iommu: protect shared state with a raw spinlock Zong Li
@ 2026-08-28 8:49 ` Guo Ren
2026-08-28 8:56 ` Zong Li
2 siblings, 1 reply; 5+ messages in thread
From: Guo Ren @ 2026-08-28 8:49 UTC (permalink / raw)
To: Zong Li
Cc: tomasz.jeznach, joro, will, robin.murphy, pjw, palmer, aou, alex,
mark.rutland, andrew.jones, david.laight.linux,
zhangzhanpeng.jasper, yang.yicong, iommu, linux-riscv,
linux-kernel, linux-perf-users
Hi Li Zong,
Just two patches? Where did the riscv-iommu PMU driver patch go?
--
Best Regards
GUO Ren
On Fri, Aug 28, 2026 at 3:07 PM Zong Li <zong.li@sifive.com> wrote:
>
> This series implements support for the RISC-V IOMMU hardware performance
> monitor.
>
> The RISC-V IOMMU PMU driver is implemented as an auxiliary device driver
> created by the parent RISC-V IOMMU driver. Therefore, the child driver
> can obtain resources and information from the parent device, such as
> the MMIO base address and IRQ number.
>
> The thrid commit adds raw spinlock for race condition when PCI MSI/MSI-X
> on IMSIC. As the commit message mentioned:
> Events are bound to one CPU and the interrupt is affine to it, so the
> perf callbacks running with interrupts disabled would be enough to
> exclude the handler. But PCI MSI/MSI-X on IMSIC breaks that:
> The irqchip sets IRQCHIP_MOVE_DEFERRED, so irq_set_affinity() reports
> success while only recording the request, and the move is applied in
> interrupt context upon the next device interrupt. Until then the
> interrupt is still routed to the CPU IMSIC picked initially, so the
> first overflow interrupt can run concurrently with the perf callbacks
> on the CPU the events are bound to.
>
> I noticed that xgene_pmu and arm-cci have similar implementation, so add
> it in riscv_iommu_pmu should be accepted.
>
> Changed in v6:
> - Rebased onto the latest v7.3-rc
> - Use sysfs_emit instead of cpumap_print_to_pagebuf
> - Set up on_cpu and irq affinity by cpuhp callbacks
> - Change type of on_cpu from unsigned int to int
> - Reject filter operands of cycle event in event_init
> - Check return value of counter number and masks in probe
> - Add raw spinlock for race condition (third commit)
>
> Changed in v5:
> - Pick up suggestions from sashiko-bot as follows
> - Fix event group validation for sw event
> - Bind IRQ to aux PMU dev instead of parent IOMMU dev
> - Clear OF bit when event is NULL
> - Improve hi-lo-hi patten
> - Add back IRQF_SHARED flag due to mismatch
> - Manage cpuhp and pmu register by devre
>
> Changed in v4:
> - Rebased onto v7.3-rc
> - Use is_sampling_event() instead of accessing vairable directly
> - Rename the matching name from "iommu.pmu" to "riscv-iommu.pmu"
> - Change the naming of PMU device for avoid ":" in PCIe case
> - Add suppress_bind_attrs attribute
> - Remove IRQF_SHARED flag
> - Set irq affinity to local CPU of IOMMU
> - Allocate ID by IDA for auxiliary device
> - Pick up suggestions from sashiko-bot
>
> Changed in v3:
> - Rebased onto v7.2-rc3
> - Use hi_lo_writeq/readq to access register
> - Pick comments from sashiko-bot as follows
> - Set IRQ CPU affinity
> - Remove IRQF_ONESHOT flag when request irq
> - Adjust cycle event check by checking event_id field only
> - Fix bug for group events verificaiton
> - Fix KASAN issue about casting 32-bit variable to unsigned long pointer
> - Clear IPSR pending bit before starting counter
> - Clear OF bit in event selector register in irq handler
> - Release irq by devm instead of explicit free_irq
>
> Changed in v2:
> - Rebased onto v7.2-rc1
> - Use hi-lo-hi mechanism to read counter.
> Suggested by Guo Ren and David Laight
>
> Changed in v1:
> - Rebased onto v6.19-rc8
> - Pick all suggestions and feedbacks from v1 series
> - Add cpu hotplug implementation to avoid race enablement
> - Move PMU-related definition from header to c file
> - Change PMU driver to auxiliary device driver
>
> Changed in RFC:
> - Rebase onto v6.13-rc7
> - Clear interrupt pending before handling interrupt
> - Fix the counter value issue caused by OF bit in the cycle counter.
> - Invoke riscv_iommu_hpm_disable() instead of riscv_iommu_pmu_uninit()
> in riscv_iommu_remove()
>
> Zong Li (2):
> iommu/riscv: create a auxiliary device for HPM
> drivers/perf: riscv-iommu: protect shared state with a raw spinlock
>
> drivers/iommu/riscv/Kconfig | 1 +
> drivers/iommu/riscv/iommu.c | 37 +++++++++++++++++++
> drivers/perf/riscv_iommu_pmu.c | 66 ++++++++++++++++++++++++++++++----
> 3 files changed, 98 insertions(+), 6 deletions(-)
>
> --
> 2.43.7
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v7 0/2] RISC-V IOMMU HPM support
2026-08-28 8:49 ` [PATCH v7 0/2] RISC-V IOMMU HPM support Guo Ren
@ 2026-08-28 8:56 ` Zong Li
0 siblings, 0 replies; 5+ messages in thread
From: Zong Li @ 2026-08-28 8:56 UTC (permalink / raw)
To: Guo Ren
Cc: tomasz.jeznach, joro, will, robin.murphy, pjw, palmer, aou, alex,
mark.rutland, andrew.jones, david.laight.linux,
zhangzhanpeng.jasper, yang.yicong, iommu, linux-riscv,
linux-kernel, linux-perf-users
On Fri, Aug 28, 2026 at 4:49 PM Guo Ren <guoren@kernel.org> wrote:
>
> Hi Li Zong,
>
> Just two patches? Where did the riscv-iommu PMU driver patch go?
>
I apologize for missing the first commit. I will resend it as PATCH
RESEND v7. Thank you very much for pointing this out!
> --
> Best Regards
> GUO Ren
>
> On Fri, Aug 28, 2026 at 3:07 PM Zong Li <zong.li@sifive.com> wrote:
> >
> > This series implements support for the RISC-V IOMMU hardware performance
> > monitor.
> >
> > The RISC-V IOMMU PMU driver is implemented as an auxiliary device driver
> > created by the parent RISC-V IOMMU driver. Therefore, the child driver
> > can obtain resources and information from the parent device, such as
> > the MMIO base address and IRQ number.
> >
> > The thrid commit adds raw spinlock for race condition when PCI MSI/MSI-X
> > on IMSIC. As the commit message mentioned:
> > Events are bound to one CPU and the interrupt is affine to it, so the
> > perf callbacks running with interrupts disabled would be enough to
> > exclude the handler. But PCI MSI/MSI-X on IMSIC breaks that:
> > The irqchip sets IRQCHIP_MOVE_DEFERRED, so irq_set_affinity() reports
> > success while only recording the request, and the move is applied in
> > interrupt context upon the next device interrupt. Until then the
> > interrupt is still routed to the CPU IMSIC picked initially, so the
> > first overflow interrupt can run concurrently with the perf callbacks
> > on the CPU the events are bound to.
> >
> > I noticed that xgene_pmu and arm-cci have similar implementation, so add
> > it in riscv_iommu_pmu should be accepted.
> >
> > Changed in v6:
> > - Rebased onto the latest v7.3-rc
> > - Use sysfs_emit instead of cpumap_print_to_pagebuf
> > - Set up on_cpu and irq affinity by cpuhp callbacks
> > - Change type of on_cpu from unsigned int to int
> > - Reject filter operands of cycle event in event_init
> > - Check return value of counter number and masks in probe
> > - Add raw spinlock for race condition (third commit)
> >
> > Changed in v5:
> > - Pick up suggestions from sashiko-bot as follows
> > - Fix event group validation for sw event
> > - Bind IRQ to aux PMU dev instead of parent IOMMU dev
> > - Clear OF bit when event is NULL
> > - Improve hi-lo-hi patten
> > - Add back IRQF_SHARED flag due to mismatch
> > - Manage cpuhp and pmu register by devre
> >
> > Changed in v4:
> > - Rebased onto v7.3-rc
> > - Use is_sampling_event() instead of accessing vairable directly
> > - Rename the matching name from "iommu.pmu" to "riscv-iommu.pmu"
> > - Change the naming of PMU device for avoid ":" in PCIe case
> > - Add suppress_bind_attrs attribute
> > - Remove IRQF_SHARED flag
> > - Set irq affinity to local CPU of IOMMU
> > - Allocate ID by IDA for auxiliary device
> > - Pick up suggestions from sashiko-bot
> >
> > Changed in v3:
> > - Rebased onto v7.2-rc3
> > - Use hi_lo_writeq/readq to access register
> > - Pick comments from sashiko-bot as follows
> > - Set IRQ CPU affinity
> > - Remove IRQF_ONESHOT flag when request irq
> > - Adjust cycle event check by checking event_id field only
> > - Fix bug for group events verificaiton
> > - Fix KASAN issue about casting 32-bit variable to unsigned long pointer
> > - Clear IPSR pending bit before starting counter
> > - Clear OF bit in event selector register in irq handler
> > - Release irq by devm instead of explicit free_irq
> >
> > Changed in v2:
> > - Rebased onto v7.2-rc1
> > - Use hi-lo-hi mechanism to read counter.
> > Suggested by Guo Ren and David Laight
> >
> > Changed in v1:
> > - Rebased onto v6.19-rc8
> > - Pick all suggestions and feedbacks from v1 series
> > - Add cpu hotplug implementation to avoid race enablement
> > - Move PMU-related definition from header to c file
> > - Change PMU driver to auxiliary device driver
> >
> > Changed in RFC:
> > - Rebase onto v6.13-rc7
> > - Clear interrupt pending before handling interrupt
> > - Fix the counter value issue caused by OF bit in the cycle counter.
> > - Invoke riscv_iommu_hpm_disable() instead of riscv_iommu_pmu_uninit()
> > in riscv_iommu_remove()
> >
> > Zong Li (2):
> > iommu/riscv: create a auxiliary device for HPM
> > drivers/perf: riscv-iommu: protect shared state with a raw spinlock
> >
> > drivers/iommu/riscv/Kconfig | 1 +
> > drivers/iommu/riscv/iommu.c | 37 +++++++++++++++++++
> > drivers/perf/riscv_iommu_pmu.c | 66 ++++++++++++++++++++++++++++++----
> > 3 files changed, 98 insertions(+), 6 deletions(-)
> >
> > --
> > 2.43.7
> >
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-28 8:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28 7:07 [PATCH v7 0/2] RISC-V IOMMU HPM support Zong Li
2026-08-28 7:07 ` [PATCH v7 1/2] iommu/riscv: create a auxiliary device for HPM Zong Li
2026-08-28 7:07 ` [PATCH v7 2/2] drivers/perf: riscv-iommu: protect shared state with a raw spinlock Zong Li
2026-08-28 8:49 ` [PATCH v7 0/2] RISC-V IOMMU HPM support Guo Ren
2026-08-28 8:56 ` Zong Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox