[RFC PATCH 3/3] perf/riscv: Use Sspesa for precise sample attribution
Mayuresh Chitale <[email protected]>
| Newsgroups | org.infradead.lists.linux-riscv,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-perf-users |
|---|---|
| Message-ID | <[email protected]> |
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, use shpmspc to report sample PC via PERF_SAMPLE_IP for the counter that caused the overflow. Shpmsdata is exported as raw data to userspace when events request PERF_SAMPLE_RAW sample type and it assists in deriving the sample PC from shpmspc if precise attribution is not supported for the event. 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 <[email protected]> --- drivers/perf/riscv_pmu_sbi.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c index dfc886dee5ad..1b0b1cc612de 100644 --- a/drivers/perf/riscv_pmu_sbi.c +++ b/drivers/perf/riscv_pmu_sbi.c @@ -63,6 +63,8 @@ PMU_FORMAT_ATTR(firmware, "config:62-63"); static bool sbi_v2_available; static bool sbi_v3_available; +static bool sspesa_available; + static DEFINE_STATIC_KEY_FALSE(sbi_pmu_snapshot_available); #define sbi_pmu_snapshot_available() \ static_branch_unlikely(&sbi_pmu_snapshot_available) @@ -1051,6 +1053,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 = cpu_hw_evt->snapshot_addr; + unsigned long sample_pc = 0; + unsigned long sample_data = 0; + int sample_cntrid = -1; + u64 raw_sample; + struct perf_raw_record raw = { 0 }; if (WARN_ON_ONCE(!cpu_hw_evt)) return IRQ_NONE; @@ -1088,6 +1095,16 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev) return IRQ_NONE; regs = get_irq_regs(); + /* + * 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 (sspesa_available) { + sample_pc = csr_read(CSR_SHPMSPC); + sample_data = csr_read(CSR_SHPMSDATA); + sample_cntrid = sample_data & SHPMSDATA_CNTRID; + } for_each_set_bit(lidx, cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS) { struct perf_event *event = cpu_hw_evt->events[lidx]; @@ -1123,6 +1140,15 @@ 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); + if (sspesa_available && hidx == sample_cntrid) { + data.ip = sample_pc; + data.sample_flags |= PERF_SAMPLE_IP; + + raw_sample = sample_data; + raw.frag.size = sizeof(raw_sample); + raw.frag.data = &raw_sample; + perf_sample_save_raw_data(&data, event, &raw); + } if (riscv_pmu_event_set_period(event)) { /* * Unlike other ISAs, RISC-V don't have to disable interrupts @@ -1194,6 +1220,9 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde struct cpu_hw_events __percpu *hw_events = pmu->hw_events; struct irq_domain *domain = NULL; + if (riscv_isa_extension_available(NULL, SSPESA)) + sspesa_available = true; + if (riscv_isa_extension_available(NULL, SSCOFPMF)) { riscv_pmu_irq_num = RV_IRQ_PMU; riscv_pmu_use_irq = true; -- 2.43.0 _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv