summaryrefslogtreecommitdiffstats
path: root/arch/x86/events/amd
diff options
context:
space:
mode:
authorSandipan Das <sandipan.das@amd.com>2022-08-11 14:29:59 +0200
committerPeter Zijlstra <peterz@infradead.org>2022-08-27 00:05:45 +0200
commit245268c19f701c7222dedcb6a383bc73d63925d4 (patch)
tree8bf43f1f7935c452c71db5a4b752290d4d3a2496 /arch/x86/events/amd
parentperf/x86: Make branch classifier fusion-aware (diff)
downloadlinux-245268c19f701c7222dedcb6a383bc73d63925d4.tar.xz
linux-245268c19f701c7222dedcb6a383bc73d63925d4.zip
perf/x86/amd/lbr: Use fusion-aware branch classifier
AMD Last Branch Record Extension Version 2 (LbrExtV2) can report a branch from address that points to an instruction preceding the actual branch by several bytes due to branch fusion and further optimizations in Zen4 processors. In such cases, software should move forward sequentially in the instruction stream from the reported address and the address of the first branch encountered should be used instead. Hence, use the fusion-aware branch classifier to determine the correct branch type and get the offset for adjusting the branch from address. Signed-off-by: Sandipan Das <sandipan.das@amd.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/c324d2d0a9c3976da30b9563d09e50bfee0f264d.1660211399.git.sandipan.das@amd.com
Diffstat (limited to 'arch/x86/events/amd')
-rw-r--r--arch/x86/events/amd/lbr.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c
index 1a8d27e0c145..eb84f196b2ca 100644
--- a/arch/x86/events/amd/lbr.c
+++ b/arch/x86/events/amd/lbr.c
@@ -97,7 +97,7 @@ static __always_inline u64 sign_ext_branch_ip(u64 ip)
static void amd_pmu_lbr_filter(void)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
- int br_sel = cpuc->br_sel, type, i, j;
+ int br_sel = cpuc->br_sel, offset, type, i, j;
bool compress = false;
u64 from, to;
@@ -109,7 +109,15 @@ static void amd_pmu_lbr_filter(void)
for (i = 0; i < cpuc->lbr_stack.nr; i++) {
from = cpuc->lbr_entries[i].from;
to = cpuc->lbr_entries[i].to;
- type = branch_type(from, to, 0);
+ type = branch_type_fused(from, to, 0, &offset);
+
+ /*
+ * Adjust the branch from address in case of instruction
+ * fusion where it points to an instruction preceding the
+ * actual branch
+ */
+ if (offset)
+ cpuc->lbr_entries[i].from += offset;
/* If type does not correspond, then discard */
if (type == X86_BR_NONE || (br_sel & type) != type) {