Userspace access using rdpmc only makes sense if the event is valid for
the current CPU. However, cap_user_rdpmc is currently set no matter which
CPU the event is associated with. The result is userspace reading another
CPU's event thinks it can use rdpmc to read the counter. In doing so, the
wrong counter will be read.

Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: [email protected]
Cc: "H. Peter Anvin" <[email protected]>
Signed-off-by: Rob Herring <[email protected]>
---
I'm working on adding userspace counter access for arm64 along with a
common access routine in libperf. I found this issue when testing per CPU
events. More details are here[1]. 

I'm going to need the same thing for arm64. This could possibly go into
perf_event_update_userpage() instead, but perhaps there could be an arch
where userspace can read other cpu's counters.

What's the ABI between libperf and kernel versions? This change will 
only help the libperf implementation if libperf doesn't need to support 
old kernels.

[1] 
https://lore.kernel.org/r/CAL_JsqJzeCebq4VP+xBtfh=fbomvajovmp35aqqdgtyd-fr...@mail.gmail.com
---
 arch/x86/events/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index a88c94d65693..6e6d4c1d03ca 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2490,7 +2490,8 @@ void arch_perf_update_userpage(struct perf_event *event,
        userpg->cap_user_time = 0;
        userpg->cap_user_time_zero = 0;
        userpg->cap_user_rdpmc =
-               !!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED);
+               !!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED) &&
+               (event->oncpu == smp_processor_id());
        userpg->pmc_width = x86_pmu.cntval_bits;
 
        if (!using_native_sched_clock() || !sched_clock_stable())
-- 
2.27.0

Reply via email to