Skip to content

Commit 92f2b8b

Browse files
Anshuman Khandualwilldeacon
authored andcommitted
drivers/perf: arm_spe: Fix consistency of SYS_PMSCR_EL1.CX
The arm_spe_pmu driver will enable SYS_PMSCR_EL1.CX in order to add CONTEXT packets into the traces, if the owner of the perf event runs with required capabilities i.e CAP_PERFMON or CAP_SYS_ADMIN via perfmon_capable() helper. The value of this bit is computed in the arm_spe_event_to_pmscr() function but the check for capabilities happens in the pmu event init callback i.e arm_spe_pmu_event_init(). This suggests that the value of the CX bit should remain consistent for the duration of the perf session. However, the function arm_spe_event_to_pmscr() may be called later during the event start callback i.e arm_spe_pmu_start() when the "current" process is not the owner of the perf session, hence the CX bit setting is currently not consistent. One way to fix this, is by caching the required value of the CX bit during the initialization of the PMU event, so that it remains consistent for the duration of the session. It uses currently unused 'event->hw.flags' element to cache perfmon_capable() value, which can be referred during event start callback to compute SYS_PMSCR_EL1.CX. This ensures consistent availability of context packets in the trace as per event owner capabilities. Drop BIT(SYS_PMSCR_EL1_CX_SHIFT) check in arm_spe_pmu_event_init(), because now CX bit cannot be set in arm_spe_event_to_pmscr() with perfmon_capable() disabled. Cc: Will Deacon <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Alexey Budankov <[email protected]> Cc: [email protected] Cc: [email protected] Fixes: d5d9696 ("drivers/perf: Add support for ARMv8.2 Statistical Profiling Extension") Reported-by: German Gomez <[email protected]> Signed-off-by: Anshuman Khandual <[email protected]> Reviewed-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 491f10d commit 92f2b8b

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

drivers/perf/arm_spe_pmu.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,24 @@
3939
#include <asm/mmu.h>
4040
#include <asm/sysreg.h>
4141

42+
/*
43+
* Cache if the event is allowed to trace Context information.
44+
* This allows us to perform the check, i.e, perfmon_capable(),
45+
* in the context of the event owner, once, during the event_init().
46+
*/
47+
#define SPE_PMU_HW_FLAGS_CX BIT(0)
48+
49+
static void set_spe_event_has_cx(struct perf_event *event)
50+
{
51+
if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable())
52+
event->hw.flags |= SPE_PMU_HW_FLAGS_CX;
53+
}
54+
55+
static bool get_spe_event_has_cx(struct perf_event *event)
56+
{
57+
return !!(event->hw.flags & SPE_PMU_HW_FLAGS_CX);
58+
}
59+
4260
#define ARM_SPE_BUF_PAD_BYTE 0
4361

4462
struct arm_spe_pmu_buf {
@@ -272,7 +290,7 @@ static u64 arm_spe_event_to_pmscr(struct perf_event *event)
272290
if (!attr->exclude_kernel)
273291
reg |= BIT(SYS_PMSCR_EL1_E1SPE_SHIFT);
274292

275-
if (IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR) && perfmon_capable())
293+
if (get_spe_event_has_cx(event))
276294
reg |= BIT(SYS_PMSCR_EL1_CX_SHIFT);
277295

278296
return reg;
@@ -709,10 +727,10 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
709727
!(spe_pmu->features & SPE_PMU_FEAT_FILT_LAT))
710728
return -EOPNOTSUPP;
711729

730+
set_spe_event_has_cx(event);
712731
reg = arm_spe_event_to_pmscr(event);
713732
if (!perfmon_capable() &&
714733
(reg & (BIT(SYS_PMSCR_EL1_PA_SHIFT) |
715-
BIT(SYS_PMSCR_EL1_CX_SHIFT) |
716734
BIT(SYS_PMSCR_EL1_PCT_SHIFT))))
717735
return -EACCES;
718736

0 commit comments

Comments
 (0)