lkml.org 
[lkml]   [2021]   [Nov]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
Subject[PATCH v2 05/13] perf/x86/amd: enable branch sampling priv level filtering
From
The AMD Branch Sampling features does not provide hardware filtering by
privilege level. The associated PMU counter does but not the branch sampling
by itself. Given how BRS operates there is a possibility that BRS captures
kernel level branches even though the event is programmed to count only at
the user level. This patch implements a workaround in software by removing
the branches which belong to the wrong privilege level. The privilege level
is evaluated on the target of the branch and not the source so as to be
compatible with other architectures. As a consequence of this patch, the
number of entries in the PERF_RECORD_BRANCH_STACK buffer may be less than
the maximum (16). It could even be zero. Another consequence is that
consecutive entries in the branch stack may not reflect actual code path and
may have discontinuities, in case kernel branches were suppressed. But this
is no different than what happens on other architectures.

Signed-off-by: Stephane Eranian <eranian@google.com>
---
arch/x86/events/amd/brs.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/arch/x86/events/amd/brs.c b/arch/x86/events/amd/brs.c
index f0d33511000d..771c4248979e 100644
--- a/arch/x86/events/amd/brs.c
+++ b/arch/x86/events/amd/brs.c
@@ -92,10 +92,6 @@ int amd_brs_setup_filter(struct perf_event *event)
if ((type & ~PERF_SAMPLE_BRANCH_PLM_ALL) != PERF_SAMPLE_BRANCH_ANY)
return -EINVAL;

- /* can only capture at all priv levels due to the way BRS works */
- if ((type & PERF_SAMPLE_BRANCH_PLM_ALL) != PERF_SAMPLE_BRANCH_PLM_ALL)
- return -EINVAL;
-
return 0;
}

@@ -181,6 +177,21 @@ void amd_brs_disable(void)
}
}

+static bool amd_brs_match_plm(struct perf_event *event, u64 to)
+{
+ int type = event->attr.branch_sample_type;
+ int plm_k = PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV;
+ int plm_u = PERF_SAMPLE_BRANCH_USER;
+
+ if (!(type & plm_k) && kernel_ip(to))
+ return 0;
+
+ if (!(type & plm_u) && !kernel_ip(to))
+ return 0;
+
+ return 1;
+}
+
/*
* Caller must ensure amd_brs_inuse() is true before calling
* return:
@@ -238,8 +249,6 @@ void amd_brs_drain(void)
if (to == BRS_POISON)
break;

- rdmsrl(brs_from(brs_idx), from);
-
/*
* Sign-extend SAMP_BR_TO to 64 bits, bits 61-63 are reserved.
* Necessary to generate proper virtual addresses suitable for
@@ -247,6 +256,11 @@ void amd_brs_drain(void)
*/
to = (u64)(((s64)to << shift) >> shift);

+ if (!amd_brs_match_plm(event, to))
+ continue;
+
+ rdmsrl(brs_from(brs_idx), from);
+
perf_clear_branch_entry_bitfields(br+nr);

br[nr].from = from;
--
2.34.0.rc0.344.g81b53c2807-goog
\
 
 \ /
  Last update: 2021-11-11 09:52    [W:0.166 / U:0.976 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site