Devicetree
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/4] RISC-V Sspesa: Linux perf precise sample attribution
@ 2026-10-29 13:09 Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 1/4] dt-bindings: riscv: Add Sspesa and Ssplcofi extensions Mayuresh Chitale
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Mayuresh Chitale @ 2026-10-29 13:09 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Peter Zijlstra,
	Ingo Molnar, Arnaldo Carvalho de Melo, Mark Rutland
  Cc: Mayuresh Chitale, devicetree, linux-kernel, linux-riscv

This Linux series adds kernel support for the RISC-V Performance Event
Sampling extensions Sspesa (Precise Event Sample Attribution) and
Ssplcofi (Precise Local Counter Overflow Interrupt).

The first two patches add the DT binding and ISA-extension detection.
Sspesa depends on Sscofpmf, while Ssplcofi depends on Sspesa. The third
patch implements perf_arch_misc_flags callback for RISC-V. The last
patch uses Sspesa in the SBI PMU driver to build synthetic regs for the
perf framework and report exact-IP samples when Ssplcofi is available.

Note:

QEMU does not currently identify any event as supporting precise
attribution. The QEMU setup is intended to validate the end-to-end
Sspesa plumbing only. Similarly, the `pesa=1` raw-event format bit in
Linux is used to simulate an event that supports precise attribution.
Such events are expected to be defined in vendor/platform specific
JSON event files, but this series does not add such an event file
for the 'Virt' machine.

Reproducing the full setup:

Sspesa support requires Linux, QEMU and OpenSBI. The matching v2
branches are:

  Linux:   https://github.com/mdchitale/linux/tree/riscv_sspesa_rfc_v2
  QEMU:    https://github.com/mdchitale/qemu/tree/riscv_sspesa_rfc_v2

OpenSBI must be built with the following fix so that PMU overflow
interrupts work correctly:

  https://lists.infradead.org/pipermail/opensbi/2026-October/010957.html

Build Linux and QEMU from the branches above, and build OpenSBI with
this fix applied. By default QEMU doesn't define a raw event that can be
mapped to programmable counters and hence a special test DTB is required
which includes the raw-event-to-counter mapping.

Build the test DTB:
  - qemu-system-riscv64 -machine virt,dumpdtb=/tmp/virt-sspesa.dtb \
    -cpu rv64,sspesa=true,ssplcofi=true,ssccfg=true,sscofpmf=true
  - dtc -I dtb -O dts -o /tmp/virt-sspesa.dts /tmp/virt-sspesa.dtb
  - Edit `/tmp/virt-sspesa.dts` and add the following property to the
    `/pmu` node:
    riscv,raw-event-to-mhpmcounters = <0x0 0x2 0x0 0xffffffffffff 0x7fff8>;
  - dtc -I dts -O dtb -o /tmp/virt-sspesa-test.dtb /tmp/virt-sspesa.dts

Boot Linux with the test DTB:
  - qemu-system-riscv64 -nographic -machine virt \
    -cpu rv64,sspesa=true,ssplcofi=true,ssccfg=true,sscofpmf=true \
    -bios /path/to/fw_dynamic.bin -kernel /path/to/Image \
    -drive file=/path/to/rootfs.img,id=hd0,format=raw,if=none \
    -device virtio-blk-device,drive=hd0 \
    -append "root=/dev/vda rw console=ttyS0 earlycon=sbi" \
    -dtb /tmp/virt-sspesa-test.dtb

Once Linux boots, use the PESA event modifier with a precise request:

  - perf record -o /tmp/sspesa-perf.data -e 'cpu/event=2,pesa=1/ppp' <workload>
  - perf record -o /tmp/non-sspesa-perf.data -e 'cpu/event=2/' <workload>

Check the resulting data with:

  - perf report -D -i /tmp/sspesa-perf.data \
      | grep 'PERF_RECORD_SAMPLE' | head
  - perf report -D -i /tmp/non-sspesa-perf.data \
      | grep 'PERF_RECORD_SAMPLE' | head

Samples in sspesa-perf.data should have the PERF_RECORD_MISC_EXACT_IP
bit (0x4000) set in the misc field, while samples in non-sspesa-perf.data
should not have that bit set. This verifies plumbing only regardless of
whether QEMU supports precise attribution.

Changes since v1:
 - Use the new shpmsdata.PRIV field defined in the updated spec
   to reconstruct the regs for perf:
   https://github.com/riscv/riscv-performance-event-sampling/commit/3eff81a6161ffc7a74a57436132d0c15ab549e74
   Fallback to interrupted registers if precise attribution is not
   available.
 - Add the required extension dependencies: Sspesa requires Sscofpmf,
   and Ssplcofi requires Sspesa.
 - Add the perf_arch_misc_flags callback to update the EXACT_IP and mode
   in perf misc record.
 - Add the `pesa` raw-event format bit and validate precise_ip requests
   against the precision supported by each event.
 - Clear shpmsdata before clearing the pending overflow interrupt.
 - Use Sspesa in the SBI PMU driver only when Smcdeleg is available.

Mayuresh Chitale (4):
  dt-bindings: riscv: Add Sspesa and Ssplcofi extensions
  riscv: Add detection for Sspesa and Ssplcofi extensions
  riscv: Add perf_arch_misc_flags callback
  perf/riscv: Use Sspesa for precise sample attribution

 .../devicetree/bindings/riscv/extensions.yaml |  26 +++
 arch/riscv/include/asm/csr.h                  |  12 ++
 arch/riscv/include/asm/hwcap.h                |   2 +
 arch/riscv/include/asm/perf_event.h           |   8 +
 arch/riscv/kernel/cpufeature.c                |  21 +++
 arch/riscv/kernel/perf_callchain.c            |  15 ++
 drivers/perf/riscv_pmu_sbi.c                  | 150 +++++++++++++++++-
 7 files changed, 233 insertions(+), 1 deletion(-)

-- 
2.43.0


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

* [RFC PATCH v2 1/4] dt-bindings: riscv: Add Sspesa and Ssplcofi extensions
  2026-10-29 13:09 [RFC PATCH v2 0/4] RISC-V Sspesa: Linux perf precise sample attribution Mayuresh Chitale
@ 2026-10-29 13:09 ` Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 2/4] riscv: Add detection for " Mayuresh Chitale
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Mayuresh Chitale @ 2026-10-29 13:09 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: Mayuresh Chitale, devicetree, linux-kernel, linux-riscv

Document the RISC-V Performance Event Sampling extensions Sspesa
(Precise Event Sample Attribution) and Ssplcofi (Precise Local Counter
Overflow Interrupt) in the ISA extensions binding.

Add a dependency rule requiring Sspesa to be present whenever Ssplcofi
is present.

Signed-off-by: Mayuresh Chitale <mayuresh.chitale@oss.qualcomm.com>

diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index 577d7ae5576b..5c1c0d308615 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -269,6 +269,18 @@ properties:
             ratified at commit d70011dde6c2 ("Update to ratified state")
             of riscv-j-extension.
 
+        - const: sspesa
+          description: |
+            The standard Sspesa supervisor-level extension for precise event
+            sample attribution, as defined in the RISC-V Performance Event
+            Sampling specification.
+
+        - const: ssplcofi
+          description: |
+            The standard Ssplcofi supervisor-level extension for precise local
+            counter overflow interrupts, as defined in the RISC-V Performance
+            Event Sampling specification. Ssplcofi depends on Sspesa.
+
         - const: ssqosid
           description: |
             The standard Ssqosid extension for Quality of Service ID is
@@ -977,6 +989,20 @@ properties:
                 const: smnpm
             - contains:
                 const: ssnpm
+      # Sspesa depends on Sscofpmf
+      - if:
+          contains:
+            const: sspesa
+        then:
+          contains:
+            const: sscofpmf
+      # Ssplcofi depends on Sspesa
+      - if:
+          contains:
+            const: ssplcofi
+        then:
+          contains:
+            const: sspesa
       # Za64rs and Ziccrse depend on Zalrsc or A
       - if:
           contains:

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

* [RFC PATCH v2 2/4] riscv: Add detection for Sspesa and Ssplcofi extensions
  2026-10-29 13:09 [RFC PATCH v2 0/4] RISC-V Sspesa: Linux perf precise sample attribution Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 1/4] dt-bindings: riscv: Add Sspesa and Ssplcofi extensions Mayuresh Chitale
@ 2026-10-29 13:09 ` Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 3/4] riscv: Add perf_arch_misc_flags callback Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 4/4] perf/riscv: Use Sspesa for precise sample attribution Mayuresh Chitale
  3 siblings, 0 replies; 6+ messages in thread
From: Mayuresh Chitale @ 2026-10-29 13:09 UTC (permalink / raw)
  To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	Anup Patel, Charlie Jenkins, Deepak Gupta,
	Clément Léger, Andrew Jones, Atish Patra, Xu Lu,
	Hui Wang, Pincheng Wang, Sergey Matyukevich
  Cc: Mayuresh Chitale, devicetree, linux-kernel, linux-riscv

Add ISA extension detection for the RISC-V Performance Event Sampling
extensions Sspesa (Precise Event Sample Attribution) and Ssplcofi
(Precise Local Counter Overflow Interrupt).

Ssplcofi requires Sspesa, so validate that Sspesa is present before
enabling Ssplcofi.

Signed-off-by: Mayuresh Chitale <mayuresh.chitale@oss.qualcomm.com>

diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 621f84d1898f..220d1dfab89e 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -350,6 +350,18 @@
 
 #define CSR_SCOUNTOVF		0xda0
 
+/* Temporary addresses for Sspesa (Precise Event Sample Attribution) CSRs. */
+#define CSR_SHPMSPC		0x5d0
+#define CSR_SHPMSDATA		0x5d1
+
+/* shpmsdata fields */
+#define SHPMSDATA_CNTRID	GENMASK(4, 0)
+#define SHPMSDATA_MODE		GENMASK(6, 5)
+#define SHPMSDATA_V		BIT(7)
+#define SHPMSDATA_METADATA_SHIFT	8
+#define SHPMSDATA_MODE_U	0
+#define SHPMSDATA_MODE_S	1
+
 #define CSR_SSTATUS		0x100
 #define CSR_SIE			0x104
 #define CSR_STVEC		0x105
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index f8db798b2654..030a946c73ef 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -122,6 +122,8 @@
 #define RISCV_ISA_EXT_ZICCAMOA		113
 #define RISCV_ISA_EXT_ZICCIF		114
 #define RISCV_ISA_EXT_ZA64RS		115
+#define RISCV_ISA_EXT_SSPESA		116
+#define RISCV_ISA_EXT_SSPLCOFI		117
 
 #define RISCV_ISA_EXT_XLINUXENVCFG	127
 
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 7329792978cc..46405bf2dfea 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -287,6 +287,24 @@ static int riscv_ext_zvfbfwma_validate(const struct riscv_isa_ext_data *data,
 	return -EPROBE_DEFER;
 }
 
+static int riscv_ext_sspesa_validate(const struct riscv_isa_ext_data *data,
+				     const unsigned long *isa_bitmap)
+{
+	if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_SSCOFPMF))
+		return 0;
+
+	return -EPROBE_DEFER;
+}
+
+static int riscv_ext_ssplcofi_validate(const struct riscv_isa_ext_data *data,
+				       const unsigned long *isa_bitmap)
+{
+	if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_SSPESA))
+		return 0;
+
+	return -EPROBE_DEFER;
+}
+
 static int riscv_ext_svadu_validate(const struct riscv_isa_ext_data *data,
 				    const unsigned long *isa_bitmap)
 {
@@ -631,6 +649,9 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
 	__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
 	__RISCV_ISA_EXT_DATA(sscsrind, RISCV_ISA_EXT_SSCSRIND),
 	__RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts),
+	__RISCV_ISA_EXT_DATA_VALIDATE(sspesa, RISCV_ISA_EXT_SSPESA, riscv_ext_sspesa_validate),
+	__RISCV_ISA_EXT_DATA_VALIDATE(ssplcofi, RISCV_ISA_EXT_SSPLCOFI,
+				      riscv_ext_ssplcofi_validate),
 	__RISCV_ISA_EXT_DATA(ssqosid, RISCV_ISA_EXT_SSQOSID),
 	__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
 	__RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE),

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

* [RFC PATCH v2 3/4] riscv: Add perf_arch_misc_flags callback
  2026-10-29 13:09 [RFC PATCH v2 0/4] RISC-V Sspesa: Linux perf precise sample attribution Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 1/4] dt-bindings: riscv: Add Sspesa and Ssplcofi extensions Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 2/4] riscv: Add detection for " Mayuresh Chitale
@ 2026-10-29 13:09 ` Mayuresh Chitale
  2026-10-29 13:09 ` [RFC PATCH v2 4/4] perf/riscv: Use Sspesa for precise sample attribution Mayuresh Chitale
  3 siblings, 0 replies; 6+ messages in thread
From: Mayuresh Chitale @ 2026-10-29 13:09 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: Mayuresh Chitale, devicetree, linux-kernel, linux-riscv

Similar to X86, add perf_arch_misc_flags callback so that
PERF_RECORD_MISC flags may be set based on the regs provided by the
SBI PMU perf driver.

Signed-off-by: Mayuresh Chitale <mayuresh.chitale@oss.qualcomm.com>

diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h
index bcc928fd3785..cf13702b185f 100644
--- a/arch/riscv/include/asm/perf_event.h
+++ b/arch/riscv/include/asm/perf_event.h
@@ -9,6 +9,14 @@
 #define _ASM_RISCV_PERF_EVENT_H
 
 #ifdef CONFIG_PERF_EVENTS
+/* Use sstatus bit 2 to convey whether an epc in the sample is precise or not */
+#define PERF_SR_PRECISE	_AC(0x00000004, UL)
+
+struct pt_regs;
+extern unsigned long perf_arch_misc_flags(struct pt_regs *regs);
+#define perf_arch_misc_flags(regs)	perf_arch_misc_flags(regs)
+#define perf_arch_instruction_pointer(regs)	instruction_pointer(regs)
+
 #include <linux/perf_event.h>
 #define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs
 
diff --git a/arch/riscv/kernel/perf_callchain.c b/arch/riscv/kernel/perf_callchain.c
index b465bc9eb870..9b68d21b3a51 100644
--- a/arch/riscv/kernel/perf_callchain.c
+++ b/arch/riscv/kernel/perf_callchain.c
@@ -6,6 +6,21 @@
 
 #include <asm/stacktrace.h>
 
+unsigned long perf_arch_misc_flags(struct pt_regs *regs)
+{
+	unsigned long misc;
+
+	if (user_mode(regs))
+		misc = PERF_RECORD_MISC_USER;
+	else
+		misc = PERF_RECORD_MISC_KERNEL;
+
+	if (regs->status & PERF_SR_PRECISE)
+		misc |= PERF_RECORD_MISC_EXACT_IP;
+
+	return misc;
+}
+
 static bool fill_callchain(void *entry, unsigned long pc)
 {
 	return perf_callchain_store(entry, pc) == 0;

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

* [RFC PATCH v2 4/4] perf/riscv: Use Sspesa for precise sample attribution
  2026-10-29 13:09 [RFC PATCH v2 0/4] RISC-V Sspesa: Linux perf precise sample attribution Mayuresh Chitale
                   ` (2 preceding siblings ...)
  2026-10-29 13:09 ` [RFC PATCH v2 3/4] riscv: Add perf_arch_misc_flags callback Mayuresh Chitale
@ 2026-10-29 13:09 ` Mayuresh Chitale
  2026-10-29 13:33   ` sashiko-bot
  3 siblings, 1 reply; 6+ messages in thread
From: Mayuresh Chitale @ 2026-10-29 13:09 UTC (permalink / raw)
  To: Atish Patra, Anup Patel, Will Deacon, Mark Rutland, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: Mayuresh Chitale, devicetree, linux-kernel, linux-riscv

When the Sspesa (Precise Event Sample Attribution) extension is
available and a counter overflows, the hardware records a sample PC in
shpmspc register and the counter ID and additional implementation-defined
data in shpmsdata register.

In the SBI PMU overflow handler, build the perf_regs for the perf
backend. The regs->epc should be derived from the shpmspc and shpmsdata
values. Along with the regs->epc, PERF_SR_PRECISE is also set if
ssplcofi is present and the event supports pesa. If sspesa is not
available or for counters that don't match shpmsdata.CNTRID, fallback
to epc for PERF_SAMPLE_IP.

Signed-off-by: Mayuresh Chitale <mayuresh.chitale@oss.qualcomm.com>

diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index 2991dd92def2..c42122f0e676 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) "riscv-pmu-sbi: " fmt
 
+#include <linux/bitfield.h>
 #include <linux/perf/riscv_pmu.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
@@ -60,9 +61,16 @@ asm volatile(ALTERNATIVE(						\
 
 PMU_FORMAT_ATTR(event, "config:0-55");
 PMU_FORMAT_ATTR(firmware, "config:62-63");
+PMU_FORMAT_ATTR(pesa, "config:56");
+
+#define RISCV_PMU_PESA_EVENT	BIT_ULL(56)
 
 static bool sbi_v2_available;
 static bool sbi_v3_available;
+static bool sspesa_available;
+static bool ssplcofi_available;
+static bool (*pmu_sbi_sspesa_derive_pc)(unsigned long *pc, unsigned long sdata);
+
 static DEFINE_STATIC_KEY_FALSE(sbi_pmu_snapshot_available);
 #define sbi_pmu_snapshot_available() \
 	static_branch_unlikely(&sbi_pmu_snapshot_available)
@@ -70,6 +78,7 @@ static DEFINE_STATIC_KEY_FALSE(sbi_pmu_snapshot_available);
 static struct attribute *riscv_arch_formats_attr[] = {
 	&format_attr_event.attr,
 	&format_attr_firmware.attr,
+	&format_attr_pesa.attr,
 	NULL,
 };
 
@@ -667,6 +676,29 @@ static bool pmu_sbi_is_fw_event(struct perf_event *event)
 		return false;
 }
 
+/*
+ * Check if this event can claim precise attribution on this platform. Only hardware raw
+ * events can claim precise attribution support.
+ */
+static bool pmu_sbi_is_pesa_event(struct perf_event *event)
+{
+	u64 config = event->attr.config;
+
+	if (!sspesa_available || event->attr.type != PERF_TYPE_RAW || config >> 62)
+		return false;
+
+	return config & RISCV_PMU_PESA_EVENT;
+}
+
+/* Check if this event can fulfill the precise_ip level requested by the user */
+static int pmu_sbi_precise_max(struct perf_event *event)
+{
+	if (!pmu_sbi_is_pesa_event(event) || !pmu_sbi_sspesa_derive_pc)
+		return 0;
+
+	return ssplcofi_available ? 3 : 2;
+}
+
 static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
 {
 	u32 type = event->attr.type;
@@ -678,6 +710,12 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
 	 */
 	flush_work(&check_std_events_work);
 
+	if (event->attr.precise_ip > pmu_sbi_precise_max(event))
+		return -EOPNOTSUPP;
+
+	if (type == PERF_TYPE_RAW && !(config >> 62))
+		config &= ~RISCV_PMU_PESA_EVENT;
+
 	return riscv_pmu_get_event_info(type, config, econfig);
 }
 
@@ -1073,6 +1111,77 @@ static void pmu_sbi_start_overflow_mask(struct riscv_pmu *pmu,
 		pmu_sbi_start_ovf_ctrs_sbi(cpu_hw_evt, ctr_ovf_mask);
 }
 
+/*
+ * Build regs for the perf backend as follows:
+ * 'U' mode samples - task_pt_regs
+ * 'S' mode samples - irq regs
+ * 'V' bit set - fallback to irq regs for now
+ */
+
+static bool pmu_sbi_sspesa_regs(struct pt_regs *perf_regs, struct pt_regs *regs,
+				unsigned long pc, unsigned long sdata)
+{
+	int mode = FIELD_GET(SHPMSDATA_MODE, sdata);
+
+	/* Virtualization not supported yet */
+	if (sdata & SHPMSDATA_V)
+		return false;
+
+	switch (mode) {
+	case SHPMSDATA_MODE_U:
+		/*
+		 * Hardware indicates 'U' mode but current task is not a userspace task,
+		 * so perf_regs should be left untouched.
+		 */
+		if (!is_user_task(current))
+			return false;
+		*perf_regs = *task_pt_regs(current);
+		break;
+	case SHPMSDATA_MODE_S:
+		*perf_regs = *regs;
+		perf_regs->status |= SR_PP;
+		if (user_mode(regs)) {
+			/*
+			 * shpmspc was recorded in 'S' mode but interrupt was delivered in 'U'
+			 * mode due to which perf_regs can't retain 'U' mode stack frame.
+			 */
+			perf_regs->s0 = 0;
+			perf_regs->sp = 0;
+		}
+		break;
+	default:
+		return false;
+	}
+
+	/* Update the epc to the more precise PC derived from shpmspc */
+	perf_regs->epc = pc;
+	return true;
+}
+
+/* QEMU hardwires shpmsdata[63:8] to 0 by default and so shpmspc needs no adjustment. */
+static bool pmu_sbi_sspesa_pc(unsigned long *pc, unsigned long sdata)
+{
+	return !(sdata >> SHPMSDATA_METADATA_SHIFT);
+}
+
+/*
+ * Following is a tentative guideline in the spec that if shpmsdata is not hardwired to 0 and no
+ * custom algorithm is reported then software shouldn't report support for precise attribution.
+ * The pmu_sbi_sspesa_derive_pc is responsible for implementing the custom algorithm and must be
+ * set per vendor and implementation during probe. If it isn't set then precise attribution is
+ * not supported for that vendor and implementation.
+ */
+static void pmu_sbi_sspesa_setup(void)
+{
+	switch (riscv_cached_mvendorid(0)) {
+	case 0:
+		pmu_sbi_sspesa_derive_pc = pmu_sbi_sspesa_pc;
+		break;
+	default:
+		break;
+	}
+}
+
 static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
 {
 	struct perf_sample_data data;
@@ -1087,6 +1196,11 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
 	struct cpu_hw_events *cpu_hw_evt = dev;
 	u64 start_clock = sched_clock();
 	struct riscv_pmu_snapshot_data *sdata;
+	unsigned long sample_pc = 0;
+	unsigned long sample_data = 0;
+	int sample_cntrid, cur_cntrid;
+	bool sample_pc_valid = false;
+	struct pt_regs perf_regs, *sample_regs;
 
 	if (WARN_ON_ONCE(!cpu_hw_evt))
 		return IRQ_NONE;
@@ -1115,6 +1229,21 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
 	else
 		ALT_SBI_PMU_OVERFLOW(overflow);
 
+	/*
+	 * Sspesa records the PC and metadata of the overflowing counter in
+	 * hardware. The PC is precise only for events that support precise
+	 * attribution; otherwise it is best-effort.
+	 */
+	if (overflow && sspesa_available) {
+		sample_pc = csr_read(CSR_SHPMSPC);
+		sample_data = csr_read(CSR_SHPMSDATA);
+		csr_write(CSR_SHPMSDATA, 0);
+		sample_cntrid = sample_data & SHPMSDATA_CNTRID;
+		if (pmu_sbi_sspesa_derive_pc)
+			sample_pc_valid = pmu_sbi_sspesa_derive_pc(&sample_pc,
+								sample_data);
+	}
+
 	/*
 	 * Overflow interrupt pending bit should only be cleared after stopping
 	 * all the counters to avoid any race condition.
@@ -1161,6 +1290,16 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
 		riscv_pmu_event_update(event);
 		hw_evt->state |= PERF_HES_UPTODATE;
 		perf_sample_data_init(&data, 0, hw_evt->last_period);
+		sample_regs = regs;
+		cur_cntrid = pmu_sbi_csr_index(event);
+		/* Update the regs if the current event caused the overflow */
+		if (sample_pc_valid && cur_cntrid == sample_cntrid) {
+			if (pmu_sbi_sspesa_regs(&perf_regs, regs, sample_pc, sample_data)) {
+				sample_regs = &perf_regs;
+				if (ssplcofi_available && pmu_sbi_is_pesa_event(event))
+					sample_regs->status |= PERF_SR_PRECISE;
+			}
+		}
 		if (riscv_pmu_event_set_period(event)) {
 			/*
 			 * Unlike other ISAs, RISC-V don't have to disable interrupts
@@ -1170,7 +1309,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
 			 * TODO: We will need to stop the guest counters once
 			 * virtualization support is added.
 			 */
-			perf_event_overflow(event, &data, regs);
+			perf_event_overflow(event, &data, sample_regs);
 		}
 		/* Reset the state as we are going to start the counter after the loop */
 		hw_evt->state = 0;
@@ -1500,6 +1639,15 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
 	}
 	irq_requested = (ret == 0);
 
+	if (riscv_isa_extension_available(NULL, SSPESA) &&
+	    riscv_isa_extension_available(NULL, SMCDELEG)) {
+		sspesa_available = true;
+		pmu_sbi_sspesa_setup();
+	}
+
+	if (riscv_isa_extension_available(NULL, SSPLCOFI))
+		ssplcofi_available = true;
+
 	pmu->pmu.attr_groups = riscv_pmu_attr_groups;
 	pmu->pmu.parent = &pdev->dev;
 	bitmap_copy(pmu->cmask, cmask, RISCV_MAX_COUNTERS);

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

* Re: [RFC PATCH v2 4/4] perf/riscv: Use Sspesa for precise sample attribution
  2026-10-29 13:09 ` [RFC PATCH v2 4/4] perf/riscv: Use Sspesa for precise sample attribution Mayuresh Chitale
@ 2026-10-29 13:33   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-10-29 13:33 UTC (permalink / raw)
  To: Mayuresh Chitale; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] perf/riscv: stale CSR_SHPMSDATA not cleared in pmu_sbi_ovf_handler()
--

commit 097e5fbeec62109e46a3171d644ba9f822fd792f
Author: Mayuresh Chitale <mayuresh.chitale@oss.qualcomm.com>

perf/riscv: Use Sspesa for precise sample attribution

This commit adds support for the RISC-V Sspesa extension in the SBI PMU
driver to record precise sample PCs from CSR_SHPMSPC and CSR_SHPMSDATA
during counter overflow handling.

> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index 2991dd92def28..c42122f0e6760 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c

[ ... ]

> @@ -1115,6 +1229,21 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
>  	else
>  		ALT_SBI_PMU_OVERFLOW(overflow);
>  
> +	/*
> +	 * Sspesa records the PC and metadata of the overflowing counter in
> +	 * hardware. The PC is precise only for events that support precise
> +	 * attribution; otherwise it is best-effort.
> +	 */
> +	if (overflow && sspesa_available) {
> +		sample_pc = csr_read(CSR_SHPMSPC);
> +		sample_data = csr_read(CSR_SHPMSDATA);
> +		csr_write(CSR_SHPMSDATA, 0);
> +		sample_cntrid = sample_data & SHPMSDATA_CNTRID;
> +		if (pmu_sbi_sspesa_derive_pc)
> +			sample_pc_valid = pmu_sbi_sspesa_derive_pc(&sample_pc,
> +								sample_data);
> +	}

[Severity: Medium]
Can CSR_SHPMSDATA remain latched with a stale counter ID and sample PC if a
counter overflows while local interrupts are disabled during a context switch
or event teardown?

When a hardware counter overflows while local interrupts are disabled,
hardware latches CSR_SHPMSPC and CSR_SHPMSDATA (setting SHPMSDATA_CNTRID to
the overflowing counter index) and sets the pending PMU overflow interrupt.
Before interrupts are re-enabled, stopping or deleting the event via:

  perf_event_task_sched_out() -> riscv_pmu_stop() -> pmu_sbi_ctr_stop()
  or
  riscv_pmu_del() -> pmu_sbi_ctr_stop() / pmu_sbi_ctr_clear_idx()

stops or resets the counter in SBI (clearing its overflow bit in scountovf)
without clearing CSR_SHPMSDATA.

When local interrupts are later re-enabled and pmu_sbi_ovf_handler() runs, if
all hardware counters were removed then used_hw_ctrs is empty and
pmu_sbi_ovf_handler() returns early:

	fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS);
	if (fidx == RISCV_MAX_COUNTERS) {
		csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
		return IRQ_NONE;
	}

Or if other counters remain active, overflow can be 0 because stopping the
overflowed counter cleared its scountovf bit, which skips the
if (overflow && sspesa_available) block and returns IRQ_NONE after clearing
the pending interrupt. Similarly, pmu_sbi_starting_cpu() stops all counters
and clears pending overflow interrupts during CPU startup without zeroing
CSR_SHPMSDATA.

Because Sspesa hardware does not overwrite CSR_SHPMSPC or CSR_SHPMSDATA while
SHPMSDATA_CNTRID is non-zero, subsequent overflows on other counters will
fail to capture a sample PC. Furthermore, when the same hardware counter
index is later reused by another event or task and overflows,
pmu_sbi_ovf_handler() will see cur_cntrid == sample_cntrid and attribute the
previous task's stale sample_pc and privilege mode into perf_regs.epc:

		if (sample_pc_valid && cur_cntrid == sample_cntrid) {
			if (pmu_sbi_sspesa_regs(&perf_regs, regs, sample_pc, sample_data)) {
				sample_regs = &perf_regs;
				if (ssplcofi_available && pmu_sbi_is_pesa_event(event))
					sample_regs->status |= PERF_SR_PRECISE;
			}
		}

Should CSR_SHPMSDATA also be cleared when stopping a counter whose index
matches SHPMSDATA_CNTRID, on early exits in pmu_sbi_ovf_handler(), and during
CPU startup in pmu_sbi_starting_cpu()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261029130917.3714691-1-mayuresh.chitale@oss.qualcomm.com?part=4

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

end of thread, other threads:[~2026-10-29 13:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 13:09 [RFC PATCH v2 0/4] RISC-V Sspesa: Linux perf precise sample attribution Mayuresh Chitale
2026-10-29 13:09 ` [RFC PATCH v2 1/4] dt-bindings: riscv: Add Sspesa and Ssplcofi extensions Mayuresh Chitale
2026-10-29 13:09 ` [RFC PATCH v2 2/4] riscv: Add detection for " Mayuresh Chitale
2026-10-29 13:09 ` [RFC PATCH v2 3/4] riscv: Add perf_arch_misc_flags callback Mayuresh Chitale
2026-10-29 13:09 ` [RFC PATCH v2 4/4] perf/riscv: Use Sspesa for precise sample attribution Mayuresh Chitale
2026-10-29 13:33   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox