Skip to content

RISC-V PMU

RISC-V PMU: a firmware-mediated counter stack whose sampling and branch-record capabilities are spec-ratified but only partly landed in Linux.

FieldValue
Privilege layeringkernel (S-mode) → SBI ecall → M-mode firmware
CountingZicntr / Zihpm counters + SBI PMU extension (EID 0x504D55)
SamplingSscofpmf — LCOFI local interrupt, sip/sie bit 13
Guest (VS-mode) sampling+ Ssaia/Smaia (AIA) — KVM injects via HVIEN bit 13
Branch recordsSmctr/Ssctr (CTR v1.0, ratified 2024-11-22) — no Linux consumer at v7.1-rc6
Precise data samplingnone — no PEBS/SPE analog in ratified RISC-V
FirmwareOpenSBI (reference SBI implementation)
Kernel driversriscv_pmu.c · riscv_pmu_sbi.c · riscv_pmu_legacy.c @ Linux v7.1-rc6
Verification scope[source-verified] + [literature] only — no RISC-V silicon, no [hw-verified] claims

IMPORTANT

Scope: spec and source, not silicon. Every claim on this page is grounded in ratified RISC-V specification text or in Linux/OpenSBI source at a pinned SHA — no RISC-V hardware was measured, so there are no [hw-verified] figures. Unlike the other deep-dives in this tree, this page ships no runnable examples/ probe: nothing an x86 CI runner could execute would exercise the SBI/Sscofpmf path meaningfully, so the grounding is primary-source line citations instead of a compiled program. The survey's internal QA ledger records the two prompt hypotheses this page refutes (see Concern 5).


Overview

What it solves

RISC-V exposes performance counters through a three-level privilege indirection that is unlike x86 (rdpmc + wrmsr from ring 0) or ARM (PMEVTYPER<n>_EL0 written directly by EL1). On RISC-V, supervisor mode — where Linux runs — can read the counters but cannot select, start, or stop them. Only M-mode may write the mcountinhibit and mhpmeventX control CSRs. The kernel therefore drives counting by asking firmware to do it, over the SBI PMU extension, and OpenSBI performs the actual register writes.

LevelRunsReads countersSelects / starts / stops events
U / S-mode (unprivileged)user code, Linux kernelyes — cycle, instret, hpmcounterX CSRsno
S-mode via SBIriscv_pmu_sbi.c perf driverHW counters directly; FW counters via SBIrequests through an SBI ecall (config_match/start/stop)
M-mode firmware (OpenSBI)the SBI implementationyes — writes mhpmeventX, mcountinhibit

The counting CSRs come from the base ISA's Zicntr (cycle, time, instret) and Zihpm (hpmcounter3..31) extensions; a firmware SBI implementation may even refuse the SBI PMU extension entirely if mcountinhibit is unimplemented, since without it firmware cannot atomically freeze a group (riscv-sbi-doc@8a545eff src/ext-pmu.adoc:3-12).

Design philosophy

The SBI PMU extension is deliberately shaped to back a Linux perf PMU. From its specification (riscv-sbi-doc@8a545eff src/ext-pmu.adoc:22-29):

"The SBI PMU extension provides: 1. An interface for supervisor-mode software to discover and configure per-hart hardware/firmware counters 2. A typical Linux perf compatible interface for hardware/firmware performance counters and events 3. Full access to microarchitecture's raw event encodings"

Three consequences shape the whole stack:

  1. Counter allocation is firmware's job. The kernel never picks a physical counter; it hands firmware an event and asks it to find a counter that can monitor it (config_match). This keeps the S-mode driver microarchitecture-agnostic at the cost of an ecall per configuration.
  2. The event→register mapping is implementation-defined. The SBI standardizes event classes (event_idx); the concrete mhpmeventX selector values are per-vendor, supplied to firmware out-of-band via the device tree. This is the RISC-V flavour of architected-vs-implementation-defined events.
  3. Sampling is a separate, optional extension. Base counting is always available; overflow interrupts, privilege filtering, and (eventually) branch records each ride on a distinct ratified extension the platform may or may not implement. The kernel treats each as a runtime-probed capability — the theme of the seven concerns below.

How it works

Event encoding: the SBI event_idx

Every event the kernel wants counted is named by a 20-bit event_idx (riscv-sbi-doc@8a545eff src/ext-pmu.adoc:37-59):

type (event_idx[19:16])Classcode (event_idx[15:0])
0HW general1..10CPU_CYCLESREF_CPU_CYCLES
1HW cachecache_id[15:3], op_id[2:1], result_id[0]
2raw v1selector programmed into mhpmevent[0:47]
3raw v2selector programmed into mhpmevent[0:55]
15firmwarefirmware-counted software events (RFENCE/IPI/SFENCE counts, traps, …)

HW-cache codes compose a cache id (L1D/L1I/LL/DTLB/ITLB/BPU/NODE) with an operation (READ/WRITE/PREFETCH) and a result (ACCESS/MISS) (src/ext-pmu.adoc:62-160). For raw events the supervisor passes an event_data blob that firmware programs into the low bits of mhpmevent, firmware owning the top bits (src/ext-pmu.adoc:165-201). See Concern 7 for how Linux maps PERF_TYPE_RAW onto this.

The counter lifecycle: config_match → start / stop / read

The SBI PMU interface is a small set of function IDs (riscv-sbi-doc@8a545eff src/ext-pmu.adoc:699-715):

FIDFunctionSince
0sbi_pmu_num_countersbase
1sbi_pmu_counter_get_infobase
2sbi_pmu_counter_config_matchingbase
3sbi_pmu_counter_startbase
4sbi_pmu_counter_stopbase
5sbi_pmu_counter_fw_readbase
6sbi_pmu_counter_fw_read_hiSBI 2.0
7sbi_pmu_snapshot_set_shmemSBI 2.0
8sbi_pmu_event_get_infoSBI 3.0

Linux allocates a counter by calling SBI_EXT_PMU_COUNTER_CFG_MATCH — firmware picks a free counter able to monitor the event and returns its index (linux@e43ffb69 drivers/perf/riscv_pmu_sbi.c:538-594, pmu_sbi_ctr_get_idx) — then starts, stops, and reads it via the matching calls (:799-856, :739-779). counter_get_info (FID 1) packs the counter's CSR number in bits[11:0], its Width (minus one) in [17:12], and a Type bit at [XLEN-1] distinguishing a hardware counter (0) from a firmware counter (1) (src/ext-pmu.adoc:285-296). That Type bit decides how the kernel reads it: a hardware counter is a direct CSR read (riscv_pmu_ctr_read_csr(info.csr)), a firmware counter is another SBI call, SBI_EXT_PMU_COUNTER_FW_READ (riscv_pmu_sbi.c:756-776).

Firmware-side selector translation

OpenSBI cannot invent the per-vendor mhpmevent selector for an architected event, so a platform supplies the mapping out-of-band — via the device-tree properties riscv,event-to-mhpmcounters and riscv,event-to-mhpmevent, or via platform hooks; without them SBI PMU is not enabled (opensbi@26257121 docs/pmu_support.md:1-45, opensbi@26257121 lib/utils/fdt/fdt_pmu.c:49,75,121). At config_match time firmware translates the event_idx to a raw selector with sbi_platform_pmu_xlate_to_mhpmevent(...), then writes it into the counter's control register with csr_write_num(CSR_MHPMEVENT3 + ctr_idx - 3, …) (opensbi@26257121 lib/sbi/sbi_pmu.c:516-557). The generic platform simply zero-extends the event_idx as the selector for HW-general and HW-cache events.

User-space direct reads: the RISC-V self-monitoring story

RISC-V's self-monitoring / user-space counter read path is rdcycle/rdinstret/rdhpmcounter, gated by the scounteren CSR. The SBI driver programs scounteren to control which counters an unprivileged read can see, toggling the mapped event's bit as the counter is mmap'd and un-mmap'd (riscv_pmu_sbi.c:781-797, :1157-1160), and supports the perf_event_mmap_page user-read seam that x86's rdpmc path also uses (:1322-1355). This is the lowest-overhead acquisition path — the natural fit for per-iteration bracketing inside a benchmark loop — but, exactly as the concepts note, its availability is arch- and OS-policy-dependent.


The seven concerns

This tree analyses every backend against the same seven-concern spine. RISC-V's headline is how many cells are explicit absences — the survey's value here is recording precisely what the ratified ISA does not yet standardize and what has not yet reached Linux.

#ConcernRISC-V status
1Scalar counting✅ SBI PMU; cycle/instret legacy fallback
2Overflow / IP sampling⚠️ conditional on Sscofpmf; skidded IP; guest needs AIA
3Precise data-source samplingabsent — no PEBS/SPE analog
4Code-space decode✅ ISA-neutral ELF/DWARF; no HW branch stack yet
5Event-space & branch records⚠️ CTR ratified, no Linux consumer
6NUMA & topology◐ SBI CACHE_NODE counter only; topology is ISA-neutral
7Event naming & encoding✅ SBI classes + impl-defined selectors; perf vendor JSON

Concern 1: Scalar counting

Available. Counting is the mature path: the driver discovers counters, allocates them by config_match, and reads them per the lifecycle above. When SBI PMU (≥ 0.3) is absent the kernel falls back to riscv_pmu_legacy.c, which exposes only two fixed counterscycle (index 0) and instret (index 2), 63-bit — with no start/stop, no interrupt, and no exclude (PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE) (linux@e43ffb69 drivers/perf/riscv_pmu_legacy.c:15-32,40-44,110-130). A harness that stays within the physical counter budget avoids multiplexing the same way it does on any other backend; because firmware owns allocation, a group that firmware cannot place is simply refused rather than scaled.

Concern 2: Overflow / IP sampling

Available, but conditional on the Sscofpmf extension. Overflow sampling needs an interrupt on counter overflow — the RISC-V PMI. That interrupt is defined by Sscofpmf, which adds to mhpmevent[63:58] the fields OF, MINH, SINH, UINH, VSINH, VUINH: OF is a sticky overflow-and-interrupt-disable bit, and the xINH bits inhibit counting per privilege mode (riscv-isa-manual@fbae3b43 src/priv/sscofpmf.adoc:29-64). When a counter overflows with OF == 0, hardware raises a Local Count-Overflow Interrupt (LCOFI) — standard local interrupt bit 13 of mip/mie/sip/sie, delegable to S-mode via mideleg (sscofpmf.adoc:69-91; kernel IRQ_PMU_OVF = 13, RV_IRQ_PMU at linux@e43ffb69 arch/riscv/include/asm/csr.h:101,537). The specification is explicit about the dual role of OF (sscofpmf.adoc:69-73):

"If an hpmcounter overflows while the associated OF bit is zero, then a "count overflow interrupt request" is generated. If the OF bit is one, then no interrupt request is generated. Consequently the OF bit also functions as a count overflow interrupt disable for the associated hpmcounter."

To let the S-mode handler find which counters overflowed without an SBI round-trip, Sscofpmf adds scountovf (CSR 0xda0) — a read-only 32-bit shadow of the OF bits of mhpmevent3..31, per-bit gated by mcounteren/hcounteren (sscofpmf.adoc:111-129; csr.h:317). The overflow handler reads scountovf (or the SBI snapshot bitmap, below), stops counters, and for each sampling event whose OF bit is set calls perf_event_overflow(event, &data, regs) (riscv_pmu_sbi.c:1041-1146, esp. :1091 get_irq_regs, :1136perf_event_overflow).

WARNING

The sampled IP is inherently skidded. PERF_SAMPLE_IP is the trapped program counter (xepc) at the point the LCOFI is taken — not a hardware-tagged retirement address. RISC-V has no mechanism to remove skid; the IP lands some distance past the instruction that caused the overflow, exactly the bias precise sampling corrects on x86 (PEBS) and ARM (SPE). See Concern 3.

Degradation without Sscofpmf. The kernel enables sampling only if RV_IRQ_PMU (Sscofpmf) — or the T-Head C9xx / Andes vendor errata IRQs — is present; otherwise pmu_sbi_setup_irqs returns -EOPNOTSUPP and the PMU advertises PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE, logging "Perf sampling/filtering is not supported as sscof extension is not available" (riscv_pmu_sbi.c:1192-1218,1449-1454). This is the RISC-V analogue of the way the sparkles baseline harness degrades under a restrictive perf_event_paranoid: sampling and privilege filtering are runtime capabilities to probe, never to assume.

Privilege filtering rides on the same extension. exclude_kernel → SINH, exclude_user → UINH, and the guest variants → VSINH/VUINH are threaded through the SBI config_flags SET_{V,}{U,S,M}INH bits, which firmware applies to mhpmeventand firmware only applies them when Sscofpmf is present (pmu_update_inhibit_flags guards on SBI_HART_EXT_SSCOFPMF) (riscv_pmu_sbi.c:517-536; src/ext-pmu.adoc:332-354; opensbi@26257121 lib/sbi/sbi_pmu.c:504-514,534-543). So exclude_user/ exclude_kernel is not free with base counting — it is a Sscofpmf capability, matching the NO_EXCLUDE fallback.

SBI counter snapshot (SBI 2.0). FID 7 registers a shared-memory page carrying a counter_overflow_bitmap (valid only under Sscofpmf) and 64-bit counter_values[], so the overflow handler reads overflow state and values without per-counter SBI calls (src/ext-pmu.adoc:549-609; consumer riscv_pmu_sbi.c:1076-1078,919-946).

Guest (VS-mode) sampling needs AIA on top

Host sampling needs only Sscofpmf. Guest sampling needs more. KVM builds a real host perf_event per guest counter with an overflow handler kvm_riscv_pmu_overflow that calls kvm_riscv_vcpu_set_interrupt(vcpu, IRQ_PMU_OVF) (linux@e43ffb69 arch/riscv/kvm/vcpu_pmu.c:293-331,334-361). But injecting bit 13 into a guest is not something the base hypervisor extension can do — hvip can only inject the three standard VS interrupts (soft/timer/external). Delivery of the LCOFI to a guest therefore requires AIA (Ssaia/Smaia): kvm_riscv_aia_enable sets csr_set(CSR_HVIEN, BIT(IRQ_PMU_OVF)), guarded by both __riscv_isa_extension_available(NULL, RISCV_ISA_EXT_SSCOFPMF) and kvm_riscv_aia_available() (arch/riscv/kvm/aia.c:565-567,581-582; guest-side sync arch/riscv/kvm/vcpu.c:391-396).

NOTE

Do not overstate this as "sampling needs AIA". The precise statement: host sampling needs only Sscofpmf; guest sampling needs Sscofpmf and AIA. Absent Sscofpmf a guest falls back to the legacy driver reading only cycle/instret (KVM returns 0 for those and traps other hpmcounter reads as illegal) (arch/riscv/kvm/vcpu_pmu.c:388-402).

Concern 3: Precise data-source sampling

Absent. There is no PEBS/IBS/SPE analog in ratified RISC-V. A full-tree search of the unified ISA manual for a sampled-data-address, load-latency, or data-source-attribution mechanism found nothing relevant — only the unrelated RVWMO "data source register" and PMA "imprecise trap" text (search over riscv-isa-manual@fbae3b43 src/**). Concretely, there is no RISC-V producer for PERF_SAMPLE_ADDR, PERF_SAMPLE_PHYS_ADDR, or PERF_SAMPLE_DATA_SRC: the SBI/Sscofpmf sampling path carries IP plus counter deltas only. The closest standardized construct is the SBI HW-cache NODE event (SBI_PMU_HW_CACHE_NODE, "NUMA node cache event") — a counter, not a per-sample data-source tag (riscv-sbi-doc@8a545eff src/ext-pmu.adoc:140).

This immaturity is corroborated by field experience. The "Dissecting RISC-V Performance" roofline paper [literature] reports needing a "workaround to circumvent hardware bugs in one of the popular RISC-V implementations, enabling robust event sampling" and deliberately builds a PMU-independent compiler roofline because hardware PMUs are unreliable (arXiv 2507.22451, abstract). In the tree's comparison the whole precise-sampling / data-source column reads "unavailable" for RISC-V.

Concern 4: Code-space decode & symbolization

ISA-neutral. The RISC-V perf PMU registers as an ordinary perf_pmu (name "cpu", PERF_TYPE_RAW) producing standard perf_event samples (linux@e43ffb69 drivers/perf/riscv_pmu_sbi.c:1475), so address → module → symbol → line symbolization is the same ELF/DWARF pipeline every architecture uses — libelf/libdw/libdwfl, with no RISC-V-specific seam. Likewise there is no hardware call-stack or branch-stack producer at v7.1-rc6 (no CTR consumer — see Concern 5), so callchains rely on frame-pointer or DWARF-CFI userspace unwinding exactly as elsewhere. When CTR lands it would supply the LBR-style branch stack that AutoFDO and path-sensitive analyses want (riscv-ctr@42e299ca intro.adoc:4-6).

Concern 5: Event-space & branch records (CTR)

The RISC-V branch-record extension is CTR — Control Transfer Records (Smctr/Ssctr), v1.0, ratified 2024-11-22. It is the direct LBR/BRBE analog: a circular FIFO recording qualified control transfers, each entry holding a source PC (ctrsource), target PC (ctrtarget), and metadata (ctrdata), with a software-selectable depth of 2^(DEPTH+4) = 16 … 256 entries, accessed via the indirect-CSR window siselect 0x200–0x2FF (riscv-ctr@42e299ca header.adoc:4-6,39-47, intro.adoc:4-8, body.adoc:161-208,285-296). The header carries the ratified-state banner (header.adoc:39-47):

"This document is in the [Ratified state]. No changes are allowed. Any desired or needed changes can be the subject of a follow-on new extension. Ratified extensions are never revised."

ctrdata.TYPE[3:0] classifies each transfer into 16 kinds (body.adoc:340-373,574-595):

TYPETransferTYPETransfer
1Exception9Direct call
2Interrupt10Indirect jump
3Trap return11Direct jump
4Not-taken branch12Co-routine swap
5Taken branch13Function return
8Indirect call14/15Other indirect / direct jump-with-linkage

Filtering is rich: mctrctl/sctrctl select privilege modes (U/S/M) and apply per-transfer-type inhibits (EXCINH, INTRINH, TRETINH, TKBRINH, NTBREN, INDCALLINH, DIRCALLINH, INDJMPINH, DIRJMPINH, CORSWAPINH, RETINH, …), plus RASEMU (return-address-stack emulation mode) and an optional per-record cycle count CC (mantissa + exponent) (body.adoc:10-99,340-373). CTR depends on S-mode and the Sscsrind indirect-CSR extension (intro.adoc:28; src/priv/smctr.adoc).

The seam that ties CTR to sampling is freeze-on-LCOFI: LCOFIFRZ sets sctrstatus.FROZEN on a local count-overflow interrupt so the branch history leading to the sampled xepc is preserved for the ISR — the exact LBR-at-sample pattern (body.adoc:55,734):

"Freeze on LCOFI ensures that the execution path leading to the sampled instruction (xepc) is preserved, and that the local counter overflow interrupt (LCOFI) and associated Interrupt Service Routine (ISR) do not displace any recorded transfer history state."

WARNING

CTR is ratified but has no Linux consumer at v7.1-rc6. drivers/perf/riscv_ctr.cdoes not exist in the tree, and a full-tree grep for ssctr|smctr|control_transfer|RISCV_ISA_EXT_S[MS]CTR across arch/riscv/, drivers/perf/, and include/ returns only unrelated hits (linux@e43ffb69, "Linux 7.1-rc6", 2026-05-31). The ratified branch-record capability exists only as spec: no kernel driver publishes a PERF_SAMPLE_BRANCH_STACK on RISC-V yet. This refutes a prompt hypothesis and is the page's headline gap — carried in the comparison's open questions.

CTR is also already folded into the unified ISA manual as src/priv/smctr.adoc ("ext:smctr[] … Version 1.0"), so the ratified extension has two concurring primary sources; this page cites the standalone riscv-ctr repo for line precision.

Beyond CTR and counters, there is no Intel-PT / Arm-ETM-style full instruction-trace standard. The only other standardized "event space" is SBI firmware events (type 15: RFENCE/IPI/SFENCE/HFENCE counts, misaligned and access-fault traps, …) — and those are counts, not traces (riscv-sbi-doc@8a545eff src/ext-pmu.adoc:203-259).

Concern 6: NUMA & topology

Collapses to a single counter. There is no architected NUMA-source PMU classification analogous to the vendor data-source engines. The only NUMA-aware PMU construct is the SBI HW-cache NODE event above — a counter, not a per-sample tag (src/ext-pmu.adoc:140; kernel cache-event map linux@e43ffb69 drivers/perf/riscv_pmu_sbi.c:281-300). Node and topology discovery itself is the ISA-neutral OS/ACPI/DT path — libnuma and sysfs — not a RISC-V-specific seam. There is likewise no standardized uncore / system-PMU framework (uncore PMU) analogous to Arm CMN/DSU/DMC in drivers/perf/ at this SHA — only the riscv_pmu*.c core plus SBI and legacy drivers exist (ls linux@e43ffb69 drivers/perf/riscv*).

Concern 7: Event naming & encoding

Two layers: standardized classes, implementation-defined selectors. The SBI standardizes the event_idx class encoding above (HW-general, HW-cache, raw-v1/v2, firmware), but the actual mhpmevent selector values are per-vendor — RISC-V architects no hardware event numbers, only the SBI classes, matching its position on the architected-vs-implementation-defined axis. Linux distinguishes raw / firmware / platform-firmware events via config[63:62] and maps PERF_TYPE_RAW onto the SBI raw class (riscv_pmu_sbi.c:416-478; src/ext-pmu.adoc:165-201).

The perf tool carries per-microarchitecture JSON tables under tools/perf/pmu-events/arch/riscv/, keyed by mvendorid-marchid-mimpid:

VendorMicroarchitectures (JSON dirs)
sifivebullet, bullet-07, bullet-0d, p550, p650
theadc900-legacy
openhwgroupcva6
starfivedubhe-80
andesax45

Entries are {EventName, EventCode, BriefDescription} (or ArchStdEvent references for the standard firmware events) (linux@e43ffb69 tools/perf/pmu-events/arch/riscv/mapfile.csv and the per-vendor *.json). The cross-ISA naming story — how these relate to libpfm4, PAPI, and the other ISAs' tables — is event-naming.md's subject.


Strengths

  • Microarchitecture-agnostic S-mode driver. Firmware owns counter allocation and selector translation, so the kernel driver is small and portable; adding a new core is a device-tree map plus (optionally) a perf JSON, not a kernel change.
  • Clean, ratified sampling primitive. Sscofpmf's LCOFI + scountovf shadow give a well-specified overflow-interrupt path with per-privilege-mode inhibit bits standardized in the ISA rather than bolted on per vendor.
  • User-space direct reads are first-class. rdcycle/rdinstret gated by scounteren, wired through perf_event_mmap_page, give a genuinely low-overhead counting path suited to per-iteration benchmark bracketing.
  • Branch records are already ratified. CTR is a complete, ratified LBR/BRBE-class design (16 transfer types, depth 16–256, RASEMU, freeze-on-LCOFI) — the specification work is done, ahead of silicon and software.
  • Firmware-counted software events (RFENCE/IPI/trap counts) come "for free" as a standardized class alongside hardware events.

Weaknesses

  • No precise sampling at all. No PEBS/IBS/SPE analog: no de-skidded IP, no sampled data address, no data-source or load-latency attribution. Memory-hierarchy analysis that other backends get from precise sampling is simply unavailable.
  • Branch records are spec-only. CTR is ratified but has no Linux consumer at v7.1-rc6 — no PERF_SAMPLE_BRANCH_STACK on RISC-V, so AutoFDO / path-sensitive tooling has nothing to consume.
  • Sampling and privilege filtering are optional. Without Sscofpmf the PMU is counting-only (NO_INTERRUPT | NO_EXCLUDE); exclude_user/exclude_kernel cannot be assumed.
  • An extra indirection on every configuration. Counter config crosses an SBI ecall into M-mode firmware; the S-mode driver never touches the control CSRs directly.
  • Fragmented, immature implementations. Per the roofline paper, real RISC-V PMUs carry hardware bugs and platform-specific defects that force workarounds [literature].
  • No uncore / system-PMU framework and no NUMA data-source classification beyond a single CACHE_NODE counter.

Key design decisions and trade-offs

DecisionRationaleTrade-off
Counting via M-mode firmware over an SBI ecall (not direct S-mode)S-mode cannot write the control CSRs; firmware indirection keeps the kernel driver portableAn ecall per configuration; behaviour depends on the firmware/platform DT map being present
Firmware picks the physical counter (config_match)Kernel stays microarchitecture-agnostic; no per-core counter-allocation logic in LinuxThe kernel cannot pin a specific counter; placement policy lives in opaque firmware
Sampling as a separate extension (Sscofpmf), probed at runtimeSmall cores can ship counting-only silicon; the interrupt path is opt-inSampling and privilege filtering degrade to NO_INTERRUPT | NO_EXCLUDE without Sscofpmf
Skidded xepc as the sampled IP; no precise mechanismKeeps the sampling path to a single overflow interrupt + trap frameBiased profiles on out-of-order cores; no data-address / data-source attribution at all
Guest LCOFI delivery layered on AIA (HVIEN) rather than base H-extThe base hypervisor extension can only inject three standard VS interruptsGuest sampling adds an Ssaia/Smaia dependency on top of Sscofpmf
Event classes standardized; mhpmevent selectors implementation-definedPortable event names without dictating hardware encodingsPortable names exist only as far as per-microarchitecture JSON/DT maps are maintained
Model RISC-V as a capability subset in the sparkles backendCleanly mirrors the ratified/landed reality and the runtime-probe discipline the tree advocatesAdvertise counting always, sampling only under Sscofpmf, privilege filtering with it, branch records never (yet), and precise/data-source never

The last row is the survey's recommendation for how a portable harness should treat RISC-V: not as a reduced x86, but as a distinct capability set to advertise and probe — counting is a given, sampling is conditional, and precise/branch-record features are absent (one permanently, one pending a Linux driver). This is the same capability-not-assumption stance the privilege-gating concept and the baseline harness apply elsewhere.


Sources

Linux kernel [source-verified]linux@e43ffb69e0438cddd72aaa30898b4dc446f664f8 (v7.1-rc6, 2026-05-31):

  • drivers/perf/riscv_pmu_sbi.c — SBI PMU driver: allocation, start/stop/read, overflow handler, scounteren, snapshot, PERF_TYPE_RAW mapping
  • drivers/perf/riscv_pmu_legacy.ccycle/instret-only fallback
  • drivers/perf/riscv_pmu.c — shared core; tools/perf/pmu-events/arch/riscv/** vendor JSON
  • arch/riscv/kvm/{vcpu_pmu,vcpu,aia}.c — guest counters and AIA-mediated LCOFI injection
  • arch/riscv/include/asm/csr.hIRQ_PMU_OVF, scountovf CSR number

RISC-V specifications [source-verified]:

Literature [literature]:

Related pages: concepts · Linux perf_events · precise sampling · ARMv8+ · event naming & encoding · comparison.