All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 1/3] iommu/riscv: Add iommu perf driver
@ 2025-09-15  2:09 ` Yaxing Guo
  0 siblings, 0 replies; 21+ messages in thread
From: Yaxing Guo @ 2025-09-15  2:09 UTC (permalink / raw)
  To: linux-riscv
  Cc: iommu, tjeznach, joro, will, robin.murphy, paul.walmsley, palmer,
	aou, alex, anxu, wangran, Yaxing Guo

This patch introduces a performance monitor driver for RISC-V IOMMU
iohpm implementions that support hardware performance counters.
The driver expose RISC-V-IOMMU-specific performance events (eg. cycles,
tlb miss ...)through the Linux perf subsystem, enabling developers
to profile and optimize I/O translation performance.

Key features:
- Implements a perf PMU driver for RISC-V IOMMU.

- Exposes IOMMU perf events, such as 'cycles', 'tlb_miss'... via
  /sys/devices/riscv-iommu-pmu/events/, allowing use with perf
  tools:
    perf stat -C 0 -e riscv-iommu-pmu/cycles/ ...
    perf stat -C 0 -e riscv-iommu-pmu/tlb_miss/ ...
    ...
- Supports event filtering through configureable attributes exposed
  in /sys/devices/riscv-iommu-pmu/format/, including:
  dv_gscv, pv_pscv,did_gscid,pid_pscid,idt (riscv iommu spec 5-23).

- Implements overflow interrupt handling.

- Adds device tree binding support via optional 'pmu-name' property
  allowing platform-specific IOMMU implementations to specify a custom
  defined event ID list. If not provided, the driver defaults to only
  supporting 'cycles'. When set to 'dummy', it enables all 9 standard
  event IDs as defined in riscv iommu spec(5-23).

Signed-off-by: Yaxing Guo <guoyaxing@bosc.ac.cn>
---
 drivers/iommu/riscv/iommu-perf.c | 535 +++++++++++++++++++++++++++++++
 drivers/iommu/riscv/iommu-perf.h |  88 +++++
 drivers/iommu/riscv/iommu.h      |   8 +
 3 files changed, 631 insertions(+)
 create mode 100644 drivers/iommu/riscv/iommu-perf.c
 create mode 100644 drivers/iommu/riscv/iommu-perf.h

diff --git a/drivers/iommu/riscv/iommu-perf.c b/drivers/iommu/riscv/iommu-perf.c
new file mode 100644
index 000000000000..a9a8788a5776
--- /dev/null
+++ b/drivers/iommu/riscv/iommu-perf.c
@@ -0,0 +1,535 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IOMMU hpm implementations
+ * Copyright(c) 2025 Beijing Institute of Open Source Chip (BOSC)
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/perf_event.h>
+#include <linux/iommu.h>
+#include "iommu.h"
+#include "iommu-perf.h"
+
+#define EVENT_CYCLES              0
+#define EVENT_UNTRANSLATED_REQ    1
+#define EVENT_TRANSLATED_REQUESTS 2
+#define EVENT_ATS_TRANSLATION_REQ 3
+#define EVENT_TLB_MISS            4
+#define EVENT_DDT_WALK            5
+#define EVENT_PDT_WALK            6
+#define EVENT_STAGE1_PT_WALK      7
+#define EVENT_STAGE2_PT_WALK      8
+
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(translated_req,      "config=0x001")
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(untranslated_req,    "config=0x002")
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(ats_translation_req, "config=0x003")
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(tlb_miss,            "config=0x004")
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(ddt_walk,            "config=0x005")
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(pdt_walk,            "config=0x006")
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(stage1_pt_walk,      "config=0x007")
+RISCV_IOMMU_PMU_EXT_EVENT_ATTR(stage2_pt_walk,      "config=0x008")
+
+static const struct attribute_group *riscv_iommu_pmu_attr_update_dummy[] = {
+	&translated_req,
+	&untranslated_req,
+	&ats_translation_req,
+	&tlb_miss,
+	&ddt_walk,
+	&pdt_walk,
+	&stage1_pt_walk,
+	&stage2_pt_walk,
+	NULL
+};
+
+static struct riscv_iommu_pmu_event_map event_map[] = {
+	{ "dummy", riscv_iommu_pmu_attr_update_dummy },
+	{ NULL,    NULL}
+};
+
+PMU_EVENT_ATTR_STRING(pv_pscv,   format_pv_pscv_attr,   "config1:0");
+PMU_EVENT_ATTR_STRING(dv_gscv,   format_dv_gscv_attr,   "config1:1");
+PMU_EVENT_ATTR_STRING(idt,       format_idt_attr,       "config1:2");
+PMU_EVENT_ATTR_STRING(pid_pscid, format_pid_pscid_attr, "config1:20-39");
+PMU_EVENT_ATTR_STRING(did_gscid, format_did_gscid_attr, "config1:40-63");
+
+static struct attribute *formats_attrs[] = {
+	&format_pv_pscv_attr.attr.attr,
+	&format_dv_gscv_attr.attr.attr,
+	&format_idt_attr.attr.attr,
+	&format_pid_pscid_attr.attr.attr,
+	&format_did_gscid_attr.attr.attr,
+	NULL
+};
+
+static struct attribute_group riscv_iommu_pmu_format_attr_group = {
+	.name = "format",
+	.attrs = formats_attrs,
+};
+
+PMU_EVENT_ATTR_STRING(cycles, event_cycles_attr, "config=0x0");
+
+static struct attribute *events_attrs[] = {
+	&event_cycles_attr.attr.attr,
+	NULL
+};
+
+static struct attribute_group riscv_iommu_pmu_events_attr_group = {
+	.name = "events",
+	.attrs = events_attrs,
+};
+
+static const struct attribute_group *riscv_iommu_pmu_attr_groups[] = {
+	&riscv_iommu_pmu_format_attr_group,
+	&riscv_iommu_pmu_events_attr_group,
+	NULL,
+};
+
+static void __riscv_iommu_pmu_unregister(struct riscv_iommu_pmu *iommu_pmu);
+static void riscv_iommu_pmu_read(struct perf_event *event);
+
+static void riscv_iommu_pmu_hpmevt_set(iohpmevt_t *hpmevt, unsigned long event_id,
+				       int pv_pscv, int dv_gscv, int idt,
+				       int pid_pscid, int did_gscid, int of)
+{
+	hpmevt->val = 0;
+	hpmevt->eventID = event_id;
+	hpmevt->IDT = idt;
+	hpmevt->OF = of;
+	hpmevt->PID_PSCID = pid_pscid;
+	hpmevt->DID_GSCID = did_gscid;
+	hpmevt->PV_PSCV = pv_pscv;
+	hpmevt->DV_GSCV = dv_gscv;
+}
+
+static struct riscv_iommu_perf_event *
+get_riscv_iommu_perf_event(struct riscv_iommu_pmu *iommu_pmu,
+			   struct perf_event *event,
+			   int pv_pscv, int dv_gscv, int idt,
+			   int pid_pscid, int did_gscid,
+			   int *idx)
+{
+	int i, nr;
+	struct riscv_iommu_device *iommu = iommu_pmu->iommu;
+	struct riscv_iommu_perf_event *iommu_event;
+
+	for (i = 0; i < RISCV_IOMMU_IOHPMCTR_CNT; i++) {
+		iommu_event = iommu->events[i];
+		if (iommu_event == NULL)
+			continue;
+
+		if (iommu_event->perf_event == event) {
+			nr = i;
+			goto update;
+		}
+	}
+
+	nr = find_first_zero_bit(&iommu->iohpmctr_bitmap,
+				 RISCV_IOMMU_IOHPMCTR_CNT);
+	if (nr >= RISCV_IOMMU_IOHPMCTR_CNT)
+		return NULL;
+again:
+	if (test_and_set_bit(nr, &iommu_pmu->iommu->iohpmctr_bitmap))
+		goto again;
+
+	iommu_event = kzalloc(sizeof(struct riscv_iommu_perf_event), GFP_KERNEL);
+	if (!iommu_event)
+		return NULL;
+update:
+	iommu_event->perf_event = event;
+	iommu_event->pv_pscv = pv_pscv;
+	iommu_event->dv_gscv = dv_gscv;
+	iommu_event->idt = idt;
+	iommu_event->pid_pscid = pid_pscid;
+	iommu_event->did_gscid = did_gscid;
+	iommu->events[nr] = iommu_event;
+
+	*idx = nr;
+
+	return iommu_event;
+}
+
+static int riscv_iommu_pmu_event_add(struct riscv_iommu_pmu *iommu_pmu,
+				     struct perf_event *event)
+{
+	int nr = -1, of;
+	unsigned long event_id = event->attr.config;
+	riscv_iommu_pmu_cfg1_t config1;
+	struct hw_perf_event *hwc = &event->hw;
+	struct riscv_iommu_device *iommu = iommu_pmu->iommu;
+
+	config1.val = event->attr.config1;
+
+	if (event_id >= RISCV_IOMMU_IOHPMCTR_CNT)
+		return -EINVAL;
+
+	if (iommu->hpm_irq)
+		of = 0;
+	else
+		of = 1;
+
+	if (event_id == EVENT_CYCLES) {
+		unsigned long val;
+
+		val = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCYCLES);
+		if (of)
+			val &= ~RISCV_IOMMU_IOHPMCYCLES_OF;
+		else
+			val |= RISCV_IOMMU_IOHPMCYCLES_OF;
+		riscv_iommu_writeq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCYCLES, val);
+
+		hwc->idx = 0;
+		iommu->events[0]->perf_event = event;
+	} else {
+		struct riscv_iommu_perf_event *iommu_perf_event;
+
+		iommu_perf_event = get_riscv_iommu_perf_event(iommu_pmu, event,
+							      config1.pv_pscv, config1.dv_gscv,
+							      config1.idt, config1.pid_pscid,
+							      config1.did_gscid, &nr);
+		if (!iommu_perf_event)
+			return -ENOSPC;
+
+		riscv_iommu_pmu_hpmevt_set(&iommu_pmu->iommu->iohpmevt[nr], event_id,
+					   iommu_perf_event->pv_pscv, iommu_perf_event->dv_gscv,
+					   iommu_perf_event->idt, iommu_perf_event->pid_pscid,
+					   iommu_perf_event->did_gscid, of);
+		riscv_iommu_writeq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMEVT(nr),
+				   iommu_pmu->iommu->iohpmevt[nr].val);
+
+		hwc->idx = nr;
+	}
+
+	return 0;
+}
+
+static int riscv_iommu_pmu_hpmevt_idx_get(struct riscv_iommu_pmu *iommu_pmu, int event_id)
+{
+	int i;
+	iohpmevt_t *iohpmevt;
+
+	for (i = 0; i < RISCV_IOMMU_IOHPMCTR_CNT; i++) {
+		iohpmevt = &iommu_pmu->iommu->iohpmevt[i];
+		if (iohpmevt->eventID == event_id)
+			return iohpmevt - iommu_pmu->iommu->iohpmevt;
+	}
+
+	return -1;
+}
+
+static int riscv_iommu_event_del(struct riscv_iommu_pmu *iommu_pmu,
+				 struct perf_event *event)
+{
+	unsigned long config = event->attr.config;
+	struct riscv_iommu_device *iommu = iommu_pmu->iommu;
+
+	if (config >= RISCV_IOMMU_IOHPMCTR_CNT)
+		return -EINVAL;
+
+	if (config == EVENT_CYCLES) {
+		iommu->events[0] = NULL;
+	} else {
+		int nr;
+
+		nr = riscv_iommu_pmu_hpmevt_idx_get(iommu_pmu, config);
+		if (-1 == nr)
+			return -1;
+		riscv_iommu_pmu_hpmevt_set(&iommu_pmu->iommu->iohpmevt[nr], 0,
+					   0, 0, 0, 0, 0, 0);
+		clear_bit(nr, &iommu_pmu->iommu->iohpmctr_bitmap);
+		riscv_iommu_writeq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMEVT(nr),
+				   0);
+		kfree(iommu->events[nr]);
+		iommu->events[nr] = NULL;
+	}
+
+	return 0;
+}
+
+static int riscv_iommu_pmu_event_init(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (event->attr.sample_period)
+		return -EINVAL;
+
+	if (event->cpu < 0)
+		return -EINVAL;
+
+	hwc->config = event->attr.config;
+
+	return 0;
+}
+
+static void riscv_iommu_pmu_enable(struct pmu *pmu)
+{
+}
+
+static void riscv_iommu_pmu_disable(struct pmu *pmu)
+{
+}
+
+static void riscv_iommu_pmu_start(struct perf_event *event, int flags)
+{
+	struct riscv_iommu_pmu *iommu_pmu = riscv_iommu_event_to_pmu(event);
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned long count;
+
+	hwc->state = 0;
+
+	if (hwc->idx == EVENT_CYCLES)
+		count = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCYCLES);
+	else
+		count = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCTR(hwc->idx));
+
+	local64_set((&hwc->prev_count), count);
+
+	perf_event_update_userpage(event);
+}
+
+static void riscv_iommu_pmu_stop(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		riscv_iommu_pmu_read(event);
+		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	}
+}
+
+static int riscv_iommu_pmu_add(struct perf_event *event, int flags)
+{
+	struct riscv_iommu_pmu *iommu_pmu = riscv_iommu_event_to_pmu(event);
+	struct hw_perf_event *hwc = &event->hw;
+
+	riscv_iommu_pmu_event_add(iommu_pmu, event);
+
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+	if (flags & PERF_EF_START)
+		riscv_iommu_pmu_start(event, 0);
+
+	return 0;
+}
+
+static void riscv_iommu_pmu_del(struct perf_event *event, int flags)
+{
+	struct riscv_iommu_pmu *iommu_pmu = riscv_iommu_event_to_pmu(event);
+
+	riscv_iommu_pmu_stop(event, PERF_EF_UPDATE);
+
+	riscv_iommu_event_del(iommu_pmu, event);
+	event->hw.idx = -1;
+
+	perf_event_update_userpage(event);
+}
+
+static void riscv_iommu_pmu_read(struct perf_event *event)
+{
+	struct riscv_iommu_pmu *iommu_pmu = riscv_iommu_event_to_pmu(event);
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned long prev_count, new_count, delta;
+
+again:
+	prev_count = local64_read(&hwc->prev_count);
+	if (hwc->idx == EVENT_CYCLES)
+		new_count = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCYCLES);
+	else
+		new_count = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCTR(hwc->idx));
+
+	if (local64_xchg(&hwc->prev_count, new_count) != prev_count)
+		goto again;
+	delta = new_count - prev_count;
+
+	local64_add(delta, &event->count);
+}
+
+int riscv_iommu_pmu_alloc(struct riscv_iommu_device *iommu)
+{
+	struct riscv_iommu_pmu *iommu_pmu;
+	struct riscv_iommu_perf_event *iommu_event;
+	int ret = 0;
+
+	if (iommu->pmu)
+		return -EEXIST;
+
+	iommu_pmu = kzalloc(sizeof(struct riscv_iommu_pmu), GFP_KERNEL);
+	if (!iommu_pmu)
+		return -ENOMEM;
+
+	iommu_pmu->iommu = iommu;
+	iommu->pmu = iommu_pmu;
+
+	set_bit(0, &iommu_pmu->iommu->iohpmctr_bitmap);
+	iommu_event = kzalloc(sizeof(struct riscv_iommu_perf_event), GFP_KERNEL);
+	if (!iommu_event) {
+		ret = -ENOMEM;
+		goto free_pmu;
+	}
+	iommu->events[0] = iommu_event;
+
+	return 0;
+
+free_pmu:
+	kfree(iommu_pmu);
+	return ret;
+}
+
+static void riscv_iommu_pmu_do_overflow(struct riscv_iommu_device *iommu)
+{
+	int idx;
+	struct riscv_iommu_perf_event *iommu_event;
+
+	for_each_set_bit(idx, &iommu->iohpmctr_bitmap,
+			 RISCV_IOMMU_IOHPMCTR_CNT) {
+		iohpmevt_t hpmevt;
+		unsigned int val;
+
+		if (idx == 0)
+			continue;
+		iommu_event = iommu->events[idx];
+		if (!iommu_event)
+			continue;
+		hpmevt.val = riscv_iommu_readq(iommu, RISCV_IOMMU_REG_IOHPMEVT(idx));
+		if (hpmevt.OF) {
+			riscv_iommu_pmu_read(iommu_event->perf_event);
+
+			hpmevt.OF = 0;
+			riscv_iommu_writeq(iommu, RISCV_IOMMU_REG_IOHPMEVT(idx), hpmevt.val);
+
+			val = riscv_iommu_readl(iommu, RISCV_IOMMU_REG_IPSR);
+			val &= ~RISCV_IOMMU_IPSR_PMIP;
+			riscv_iommu_writel(iommu, RISCV_IOMMU_REG_IPSR, val);
+		}
+	}
+}
+
+static irqreturn_t riscv_iommu_pmu_irq_handler(int irq, void *data)
+{
+	struct riscv_iommu_device *iommu = (struct riscv_iommu_device *)data;
+
+	riscv_iommu_pmu_do_overflow(iommu);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t riscv_iommu_pmu_ipsr(int irq, void *data)
+{
+	struct riscv_iommu_device *iommu = (struct riscv_iommu_device *)data;
+
+	if (riscv_iommu_readl(iommu, RISCV_IOMMU_REG_IPSR) & RISCV_IOMMU_IPSR_PMIP)
+		return IRQ_WAKE_THREAD;
+
+	return IRQ_NONE;
+}
+
+static int riscv_iommu_pmu_vec(struct riscv_iommu_device *iommu)
+{
+	return FIELD_GET(RISCV_IOMMU_ICVEC_PMIV, iommu->icvec);
+}
+
+static int riscv_iommu_pmu_set_irq(struct riscv_iommu_device *iommu)
+{
+	int irq, ret;
+
+	if (!iommu)
+		return -EINVAL;
+	irq = iommu->irqs[riscv_iommu_pmu_vec(iommu)];
+	if (!irq)
+		return -EEXIST;
+	iommu->hpm_irq = irq;
+
+	ret = request_threaded_irq(irq, riscv_iommu_pmu_ipsr,
+				   riscv_iommu_pmu_irq_handler,
+				   IRQF_ONESHOT, "rv-iommu-pmu-irq", iommu);
+	if (ret) {
+		iommu->hpm_irq = 0;
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct attribute_group **
+riscv_iommu_get_ext_attr(struct riscv_iommu_pmu *iommu_pmu)
+{
+	struct riscv_iommu_pmu_event_map *map = event_map;
+	const char *str;
+	struct device *dev = iommu_pmu->iommu->dev;
+
+	if (of_property_read_string(dev->of_node, "pmu-name", &str))
+		return NULL;
+
+	while (map->compatible) {
+		if (!strcmp(map->compatible, str))
+			return map->attr_group;
+	}
+
+	return NULL;
+}
+
+static int __riscv_iommu_pmu_register(struct riscv_iommu_pmu *iommu_pmu,
+				      const char *name)
+{
+	int ret;
+
+	if (!iommu_pmu)
+		return -EINVAL;
+
+	iommu_pmu->pmu.attr_groups = riscv_iommu_pmu_attr_groups;
+	iommu_pmu->pmu.attr_update = riscv_iommu_get_ext_attr(iommu_pmu);
+	iommu_pmu->pmu.task_ctx_nr = perf_invalid_context;
+	iommu_pmu->pmu.event_init  = riscv_iommu_pmu_event_init;
+	iommu_pmu->pmu.pmu_enable  = riscv_iommu_pmu_enable;
+	iommu_pmu->pmu.pmu_disable = riscv_iommu_pmu_disable;
+	iommu_pmu->pmu.add         = riscv_iommu_pmu_add;
+	iommu_pmu->pmu.del         = riscv_iommu_pmu_del;
+	iommu_pmu->pmu.start       = riscv_iommu_pmu_start;
+	iommu_pmu->pmu.stop        = riscv_iommu_pmu_stop;
+	iommu_pmu->pmu.read        = riscv_iommu_pmu_read;
+
+	ret = perf_pmu_register(&iommu_pmu->pmu, name, -1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void __riscv_iommu_pmu_unregister(struct riscv_iommu_pmu *iommu_pmu)
+{
+	if (!iommu_pmu)
+		return;
+
+	perf_pmu_unregister(&iommu_pmu->pmu);
+
+	kfree(iommu_pmu->iommu->events[0]);
+	kfree(iommu_pmu);
+}
+
+int riscv_iommu_pmu_register(struct riscv_iommu_device *iommu)
+{
+	int ret;
+
+	ret = __riscv_iommu_pmu_register(iommu->pmu, "riscv-iommu-pmu");
+	if (ret)
+		goto err;
+
+	ret = riscv_iommu_pmu_set_irq(iommu);
+	if (ret)
+		goto unregister;
+
+	return 0;
+
+unregister:
+	riscv_iommu_pmu_unregister(iommu);
+err:
+	return ret;
+}
+
+void riscv_iommu_pmu_unregister(struct riscv_iommu_device *iommu)
+{
+	__riscv_iommu_pmu_unregister(iommu->pmu);
+
+	iommu->pmu = NULL;
+}
diff --git a/drivers/iommu/riscv/iommu-perf.h b/drivers/iommu/riscv/iommu-perf.h
new file mode 100644
index 000000000000..5c4cc7b9a978
--- /dev/null
+++ b/drivers/iommu/riscv/iommu-perf.h
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IOMMU hpm implementations
+ * Copyright(c) 2025 Beijing Institute of Open Source Chip (BOSC)
+ */
+
+#ifndef __IOMMU_PERF_H__
+#define __IOMMU_PERF_H__
+
+#include <linux/sysfs.h>
+#include <linux/perf_event.h>
+#include <linux/bitops.h>
+
+typedef union {
+	struct {
+		unsigned long eventID:15;
+		unsigned long DMASK:1;
+		unsigned long PID_PSCID:20;
+		unsigned long DID_GSCID:24;
+		unsigned long PV_PSCV:1;
+		unsigned long DV_GSCV:1;
+		unsigned long IDT:1;
+		unsigned long OF:1;
+	};
+	unsigned long val;
+} iohpmevt_t;
+
+typedef union {
+	struct {
+		unsigned long pv_pscv:1;
+		unsigned long dv_gscv:1;
+		unsigned long idt:1;
+		unsigned long reserved:17;
+		unsigned long pid_pscid:20;
+		unsigned long did_gscid:24;
+	};
+	unsigned long val;
+} riscv_iommu_pmu_cfg1_t;
+
+struct riscv_iommu_pmu_event_map {
+	const char *compatible;
+	const struct attribute_group **attr_group;
+};
+
+#define RISCV_IOMMU_IOHPMCTR_CNT 32
+
+struct riscv_iommu_perf_event {
+	int pv_pscv;
+	int dv_gscv;
+	int idt;
+	int pid_pscid;
+	int did_gscid;
+	struct perf_event *perf_event;
+};
+
+struct riscv_iommu_pmu {
+	struct riscv_iommu_device *iommu;
+	struct pmu pmu;
+};
+
+static inline struct riscv_iommu_pmu *dev_to_riscv_iommu_pmu(struct device *dev)
+{
+	return container_of(dev_get_drvdata(dev), struct riscv_iommu_pmu, pmu);
+}
+
+static inline struct riscv_iommu_pmu *riscv_iommu_event_to_pmu(struct perf_event *event)
+{
+	return container_of(event->pmu, struct riscv_iommu_pmu, pmu);
+}
+
+#define RISCV_IOMMU_PMU_EXT_EVENT_ATTR(_name, _string)			\
+	PMU_EVENT_ATTR_STRING(_name, event_attr_##_name, _string)	\
+									\
+static struct attribute *_name##_attr[] = {				\
+	&event_attr_##_name.attr.attr,					\
+	NULL								\
+};									\
+									\
+static struct attribute_group _name = {					\
+	.name		= "events",					\
+	.attrs		= _name##_attr,					\
+};
+
+int riscv_iommu_pmu_alloc(struct riscv_iommu_device *iommu);
+int riscv_iommu_pmu_register(struct riscv_iommu_device *iommu);
+void riscv_iommu_pmu_unregister(struct riscv_iommu_device *iommu);
+
+#endif
diff --git a/drivers/iommu/riscv/iommu.h b/drivers/iommu/riscv/iommu.h
index 46df79dd5495..1eabe04dbbc1 100644
--- a/drivers/iommu/riscv/iommu.h
+++ b/drivers/iommu/riscv/iommu.h
@@ -14,8 +14,10 @@
 #include <linux/iommu.h>
 #include <linux/types.h>
 #include <linux/iopoll.h>
+#include <linux/perf_event.h>
 
 #include "iommu-bits.h"
+#include "iommu-perf.h"
 
 struct riscv_iommu_device;
 
@@ -60,6 +62,12 @@ struct riscv_iommu_device {
 	unsigned int ddt_mode;
 	dma_addr_t ddt_phys;
 	u64 *ddt_root;
+
+	iohpmevt_t iohpmevt[RISCV_IOMMU_IOHPMCTR_CNT];
+	unsigned long iohpmctr_bitmap;
+	struct riscv_iommu_pmu *pmu;
+	int hpm_irq;
+	struct riscv_iommu_perf_event *events[RISCV_IOMMU_IOHPMCTR_CNT];
 };
 
 int riscv_iommu_init(struct riscv_iommu_device *iommu);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread
* Re: [PATCH v1 2/3] iommu/riscv: Add Makefile support for RISC-V IOMMU perf driver
@ 2025-09-16  3:30 kernel test robot
  0 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2025-09-16  3:30 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp

:::::: 
:::::: Manual check reason: "only suspicious fbc files changed"
:::::: 

BCC: lkp@intel.com
CC: llvm@lists.linux.dev
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20250915020911.1313-2-guoyaxing@bosc.ac.cn>
References: <20250915020911.1313-2-guoyaxing@bosc.ac.cn>
TO: Yaxing Guo <guoyaxing@bosc.ac.cn>
TO: linux-riscv@lists.infradead.org
CC: iommu@lists.linux.dev
CC: tjeznach@rivosinc.com
CC: joro@8bytes.org
CC: will@kernel.org
CC: robin.murphy@arm.com
CC: paul.walmsley@sifive.com
CC: palmer@dabbelt.com
CC: aou@eecs.berkeley.edu
CC: alex@ghiti.fr
CC: anxu@bosc.ac.cn
CC: wangran@bosc.ac.cn
CC: Yaxing Guo <guoyaxing@bosc.ac.cn>

Hi Yaxing,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.17-rc6 next-20250915]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yaxing-Guo/iommu-riscv-Add-Makefile-support-for-RISC-V-IOMMU-perf-driver/20250915-101640
base:   linus/master
patch link:    https://lore.kernel.org/r/20250915020911.1313-2-guoyaxing%40bosc.ac.cn
patch subject: [PATCH v1 2/3] iommu/riscv: Add Makefile support for RISC-V IOMMU perf driver
:::::: branch date: 25 hours ago
:::::: commit date: 25 hours ago
config: riscv-randconfig-001-20250916 (https://download.01.org/0day-ci/archive/20250916/202509161121.SHWsStQM-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 65ad21d730d25789454d18e811f8ff5db79cb5d4)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250916/202509161121.SHWsStQM-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/r/202509161121.SHWsStQM-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from drivers/iommu/riscv/iommu-perf.c:12:
   In file included from drivers/iommu/riscv/iommu.h:20:
   drivers/iommu/riscv/iommu-perf.h:68:29: error: no member named 'pmu' in 'struct perf_event'
      68 |         return container_of(event->pmu, struct riscv_iommu_pmu, pmu);
         |                             ~~~~~  ^
   drivers/iommu/riscv/iommu-perf.h:68:29: error: no member named 'pmu' in 'struct perf_event'
      68 |         return container_of(event->pmu, struct riscv_iommu_pmu, pmu);
         |                             ~~~~~  ^
   drivers/iommu/riscv/iommu-perf.h:68:29: error: no member named 'pmu' in 'struct perf_event'
      68 |         return container_of(event->pmu, struct riscv_iommu_pmu, pmu);
         |                             ~~~~~  ^
>> drivers/iommu/riscv/iommu-perf.c:157:34: error: no member named 'attr' in 'struct perf_event'
     157 |         unsigned long event_id = event->attr.config;
         |                                  ~~~~~  ^
>> drivers/iommu/riscv/iommu-perf.c:159:38: error: no member named 'hw' in 'struct perf_event'
     159 |         struct hw_perf_event *hwc = &event->hw;
         |                                      ~~~~~  ^
   drivers/iommu/riscv/iommu-perf.c:162:23: error: no member named 'attr' in 'struct perf_event'
     162 |         config1.val = event->attr.config1;
         |                       ~~~~~  ^
>> drivers/iommu/riscv/iommu-perf.c:182:8: error: no member named 'idx' in 'struct hw_perf_event'
     182 |                 hwc->idx = 0;
         |                 ~~~  ^
   drivers/iommu/riscv/iommu-perf.c:201:8: error: no member named 'idx' in 'struct hw_perf_event'
     201 |                 hwc->idx = nr;
         |                 ~~~  ^
   drivers/iommu/riscv/iommu-perf.c:224:32: error: no member named 'attr' in 'struct perf_event'
     224 |         unsigned long config = event->attr.config;
         |                                ~~~~~  ^
   drivers/iommu/riscv/iommu-perf.c:252:38: error: no member named 'hw' in 'struct perf_event'
     252 |         struct hw_perf_event *hwc = &event->hw;
         |                                      ~~~~~  ^
   drivers/iommu/riscv/iommu-perf.c:254:13: error: no member named 'attr' in 'struct perf_event'
     254 |         if (event->attr.sample_period)
         |             ~~~~~  ^
>> drivers/iommu/riscv/iommu-perf.c:257:13: error: no member named 'cpu' in 'struct perf_event'
     257 |         if (event->cpu < 0)
         |             ~~~~~  ^
>> drivers/iommu/riscv/iommu-perf.c:260:7: error: no member named 'config' in 'struct hw_perf_event'
     260 |         hwc->config = event->attr.config;
         |         ~~~  ^
   drivers/iommu/riscv/iommu-perf.c:260:23: error: no member named 'attr' in 'struct perf_event'
     260 |         hwc->config = event->attr.config;
         |                       ~~~~~  ^
   drivers/iommu/riscv/iommu-perf.c:276:38: error: no member named 'hw' in 'struct perf_event'
     276 |         struct hw_perf_event *hwc = &event->hw;
         |                                      ~~~~~  ^
>> drivers/iommu/riscv/iommu-perf.c:279:7: error: no member named 'state' in 'struct hw_perf_event'
     279 |         hwc->state = 0;
         |         ~~~  ^
   drivers/iommu/riscv/iommu-perf.c:281:11: error: no member named 'idx' in 'struct hw_perf_event'
     281 |         if (hwc->idx == EVENT_CYCLES)
         |             ~~~  ^
   drivers/iommu/riscv/iommu-perf.c:284:77: error: no member named 'idx' in 'struct hw_perf_event'
     284 |                 count = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCTR(hwc->idx));
         |                                                                                      ~~~  ^
>> drivers/iommu/riscv/iommu-perf.c:286:21: error: no member named 'prev_count' in 'struct hw_perf_event'
     286 |         local64_set((&hwc->prev_count), count);
         |                       ~~~  ^
   fatal error: too many errors emitted, stopping now [-ferror-limit=]
   20 errors generated.


vim +157 drivers/iommu/riscv/iommu-perf.c

8cf5fb280f5fc0 Yaxing Guo 2025-09-15  152  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  153  static int riscv_iommu_pmu_event_add(struct riscv_iommu_pmu *iommu_pmu,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  154  				     struct perf_event *event)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  155  {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  156  	int nr = -1, of;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @157  	unsigned long event_id = event->attr.config;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  158  	riscv_iommu_pmu_cfg1_t config1;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @159  	struct hw_perf_event *hwc = &event->hw;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  160  	struct riscv_iommu_device *iommu = iommu_pmu->iommu;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  161  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  162  	config1.val = event->attr.config1;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  163  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  164  	if (event_id >= RISCV_IOMMU_IOHPMCTR_CNT)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  165  		return -EINVAL;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  166  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  167  	if (iommu->hpm_irq)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  168  		of = 0;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  169  	else
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  170  		of = 1;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  171  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  172  	if (event_id == EVENT_CYCLES) {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  173  		unsigned long val;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  174  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  175  		val = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCYCLES);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  176  		if (of)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  177  			val &= ~RISCV_IOMMU_IOHPMCYCLES_OF;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  178  		else
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  179  			val |= RISCV_IOMMU_IOHPMCYCLES_OF;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  180  		riscv_iommu_writeq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCYCLES, val);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  181  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @182  		hwc->idx = 0;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  183  		iommu->events[0]->perf_event = event;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  184  	} else {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  185  		struct riscv_iommu_perf_event *iommu_perf_event;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  186  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  187  		iommu_perf_event = get_riscv_iommu_perf_event(iommu_pmu, event,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  188  							      config1.pv_pscv, config1.dv_gscv,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  189  							      config1.idt, config1.pid_pscid,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  190  							      config1.did_gscid, &nr);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  191  		if (!iommu_perf_event)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  192  			return -ENOSPC;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  193  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  194  		riscv_iommu_pmu_hpmevt_set(&iommu_pmu->iommu->iohpmevt[nr], event_id,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  195  					   iommu_perf_event->pv_pscv, iommu_perf_event->dv_gscv,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  196  					   iommu_perf_event->idt, iommu_perf_event->pid_pscid,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  197  					   iommu_perf_event->did_gscid, of);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  198  		riscv_iommu_writeq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMEVT(nr),
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  199  				   iommu_pmu->iommu->iohpmevt[nr].val);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  200  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  201  		hwc->idx = nr;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  202  	}
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  203  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  204  	return 0;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  205  }
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  206  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  207  static int riscv_iommu_pmu_hpmevt_idx_get(struct riscv_iommu_pmu *iommu_pmu, int event_id)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  208  {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  209  	int i;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  210  	iohpmevt_t *iohpmevt;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  211  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  212  	for (i = 0; i < RISCV_IOMMU_IOHPMCTR_CNT; i++) {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  213  		iohpmevt = &iommu_pmu->iommu->iohpmevt[i];
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  214  		if (iohpmevt->eventID == event_id)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  215  			return iohpmevt - iommu_pmu->iommu->iohpmevt;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  216  	}
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  217  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  218  	return -1;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  219  }
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  220  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  221  static int riscv_iommu_event_del(struct riscv_iommu_pmu *iommu_pmu,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  222  				 struct perf_event *event)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  223  {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @224  	unsigned long config = event->attr.config;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  225  	struct riscv_iommu_device *iommu = iommu_pmu->iommu;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  226  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  227  	if (config >= RISCV_IOMMU_IOHPMCTR_CNT)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  228  		return -EINVAL;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  229  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  230  	if (config == EVENT_CYCLES) {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  231  		iommu->events[0] = NULL;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  232  	} else {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  233  		int nr;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  234  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  235  		nr = riscv_iommu_pmu_hpmevt_idx_get(iommu_pmu, config);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  236  		if (-1 == nr)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  237  			return -1;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  238  		riscv_iommu_pmu_hpmevt_set(&iommu_pmu->iommu->iohpmevt[nr], 0,
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  239  					   0, 0, 0, 0, 0, 0);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  240  		clear_bit(nr, &iommu_pmu->iommu->iohpmctr_bitmap);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  241  		riscv_iommu_writeq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMEVT(nr),
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  242  				   0);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  243  		kfree(iommu->events[nr]);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  244  		iommu->events[nr] = NULL;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  245  	}
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  246  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  247  	return 0;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  248  }
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  249  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  250  static int riscv_iommu_pmu_event_init(struct perf_event *event)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  251  {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @252  	struct hw_perf_event *hwc = &event->hw;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  253  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  254  	if (event->attr.sample_period)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  255  		return -EINVAL;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  256  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @257  	if (event->cpu < 0)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  258  		return -EINVAL;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  259  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @260  	hwc->config = event->attr.config;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  261  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  262  	return 0;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  263  }
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  264  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  265  static void riscv_iommu_pmu_enable(struct pmu *pmu)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  266  {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  267  }
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  268  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  269  static void riscv_iommu_pmu_disable(struct pmu *pmu)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  270  {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  271  }
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  272  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  273  static void riscv_iommu_pmu_start(struct perf_event *event, int flags)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  274  {
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  275  	struct riscv_iommu_pmu *iommu_pmu = riscv_iommu_event_to_pmu(event);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  276  	struct hw_perf_event *hwc = &event->hw;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  277  	unsigned long count;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  278  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @279  	hwc->state = 0;
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  280  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  281  	if (hwc->idx == EVENT_CYCLES)
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  282  		count = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCYCLES);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  283  	else
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  284  		count = riscv_iommu_readq(iommu_pmu->iommu, RISCV_IOMMU_REG_IOHPMCTR(hwc->idx));
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  285  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15 @286  	local64_set((&hwc->prev_count), count);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  287  
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  288  	perf_event_update_userpage(event);
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  289  }
8cf5fb280f5fc0 Yaxing Guo 2025-09-15  290  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2025-09-18 14:20 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-15  2:09 [PATCH v1 1/3] iommu/riscv: Add iommu perf driver Yaxing Guo
2025-09-15  2:09 ` Yaxing Guo
2025-09-15  2:09 ` [PATCH v1 2/3] iommu/riscv: Add Makefile support for RISC-V IOMMU " Yaxing Guo
2025-09-15  2:09   ` Yaxing Guo
2025-09-16  3:40   ` kernel test robot
2025-09-16  3:40     ` kernel test robot
2025-09-15  2:09 ` [PATCH v1 3/3] iommu/riscv: Register RISC-V IOMMU PMU at init time Yaxing Guo
2025-09-15  2:09   ` Yaxing Guo
2025-09-15 10:38 ` [PATCH v1 1/3] iommu/riscv: Add iommu perf driver Will Deacon
2025-09-15 10:38   ` Will Deacon
2025-09-16 10:27   ` guoyaxing
2025-09-16 10:27     ` guoyaxing
2025-09-17 12:10     ` Will Deacon
2025-09-17 12:10       ` Will Deacon
2025-09-18  3:20       ` 郭亚星
2025-09-18  3:20         ` 郭亚星
2025-09-18 14:20         ` Will Deacon
2025-09-18 14:20           ` Will Deacon
2025-09-16  1:47 ` kernel test robot
2025-09-16  1:47   ` kernel test robot
  -- strict thread matches above, loose matches on Subject: below --
2025-09-16  3:30 [PATCH v1 2/3] iommu/riscv: Add Makefile support for RISC-V IOMMU " kernel test robot

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.