aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0067-perf-x86-amd-Add-idle-hooks-for-branch-sampling.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0067-perf-x86-amd-Add-idle-hooks-for-branch-sampling.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0067-perf-x86-amd-Add-idle-hooks-for-branch-sampling.patch153
1 files changed, 153 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0067-perf-x86-amd-Add-idle-hooks-for-branch-sampling.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0067-perf-x86-amd-Add-idle-hooks-for-branch-sampling.patch
new file mode 100644
index 00000000..fe0cd084
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0067-perf-x86-amd-Add-idle-hooks-for-branch-sampling.patch
@@ -0,0 +1,153 @@
+From fbc9f8129c3070cebecd797ee9f9facfc238dd1e Mon Sep 17 00:00:00 2001
+From: Stephane Eranian <eranian@google.com>
+Date: Tue, 22 Mar 2022 15:15:13 -0700
+Subject: [PATCH 67/86] perf/x86/amd: Add idle hooks for branch sampling
+
+commit d5616bac7adadbf42a3b63b8717e75eb82a2cc2c upstream
+
+On AMD Fam19h Zen3, the branch sampling (BRS) feature must be disabled before
+entering low power and re-enabled (if was active) when returning from low
+power. Otherwise, the NMI interrupt may be held up for too long and cause
+problems. Stopping BRS will cause the NMI to be delivered if it was held up.
+
+Define a perf_amd_brs_lopwr_cb() callback to stop/restart BRS. The callback
+is protected by a jump label which is enabled only when AMD BRS is detected.
+In all other cases, the callback is never called.
+
+Signed-off-by: Stephane Eranian <eranian@google.com>
+[peterz: static_call() and build fixes]
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20220322221517.2510440-10-eranian@google.com
+Signed-off-by: Zhaolong Zhang <zhaolong.zhang@windriver.com>
+---
+ arch/x86/events/amd/brs.c | 33 +++++++++++++++++++++++++++++++
+ arch/x86/events/amd/core.c | 4 ++++
+ arch/x86/events/perf_event.h | 1 +
+ arch/x86/include/asm/perf_event.h | 23 +++++++++++++++++++++
+ 4 files changed, 61 insertions(+)
+
+diff --git a/arch/x86/events/amd/brs.c b/arch/x86/events/amd/brs.c
+index 40461c3ce714..895c82165d85 100644
+--- a/arch/x86/events/amd/brs.c
++++ b/arch/x86/events/amd/brs.c
+@@ -7,6 +7,7 @@
+ * Contributed by Stephane Eranian <eranian@google.com>
+ */
+ #include <linux/kernel.h>
++#include <linux/jump_label.h>
+ #include <asm/msr.h>
+ #include <asm/cpufeature.h>
+
+@@ -329,3 +330,35 @@ void amd_pmu_brs_sched_task(struct perf_event_context *ctx, bool sched_in)
+ if (sched_in)
+ amd_brs_poison_buffer();
+ }
++
++/*
++ * called from ACPI processor_idle.c or acpi_pad.c
++ * with interrupts disabled
++ */
++void perf_amd_brs_lopwr_cb(bool lopwr_in)
++{
++ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
++ union amd_debug_extn_cfg cfg;
++
++ /*
++ * on mwait in, we may end up in non C0 state.
++ * we must disable branch sampling to avoid holding the NMI
++ * for too long. We disable it in hardware but we
++ * keep the state in cpuc, so we can re-enable.
++ *
++ * The hardware will deliver the NMI if needed when brsmen cleared
++ */
++ if (cpuc->brs_active) {
++ cfg.val = get_debug_extn_cfg();
++ cfg.brsmen = !lopwr_in;
++ set_debug_extn_cfg(cfg.val);
++ }
++}
++
++DEFINE_STATIC_CALL_NULL(perf_lopwr_cb, perf_amd_brs_lopwr_cb);
++EXPORT_STATIC_CALL_TRAMP_GPL(perf_lopwr_cb);
++
++void __init amd_brs_lopwr_init(void)
++{
++ static_call_update(perf_lopwr_cb, perf_amd_brs_lopwr_cb);
++}
+diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
+index f7bce8364fe4..8e1e818f8195 100644
+--- a/arch/x86/events/amd/core.c
++++ b/arch/x86/events/amd/core.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ #include <linux/perf_event.h>
++#include <linux/jump_label.h>
+ #include <linux/export.h>
+ #include <linux/types.h>
+ #include <linux/init.h>
+@@ -1225,6 +1226,9 @@ static int __init amd_core_pmu_init(void)
+ /*
+ * put_event_constraints callback same as Fam17h, set above
+ */
++
++ /* branch sampling must be stopped when entering low power */
++ amd_brs_lopwr_init();
+ }
+
+ x86_pmu.attr_update = amd_attr_update;
+diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
+index e2c4dc114bda..49948372b44a 100644
+--- a/arch/x86/events/perf_event.h
++++ b/arch/x86/events/perf_event.h
+@@ -1224,6 +1224,7 @@ void amd_brs_enable(void);
+ void amd_brs_enable_all(void);
+ void amd_brs_disable_all(void);
+ void amd_brs_drain(void);
++void amd_brs_lopwr_init(void);
+ void amd_brs_disable_all(void);
+ int amd_brs_setup_filter(struct perf_event *event);
+ void amd_brs_reset(void);
+diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
+index a2b6626c681f..0e72770c45ff 100644
+--- a/arch/x86/include/asm/perf_event.h
++++ b/arch/x86/include/asm/perf_event.h
+@@ -2,6 +2,8 @@
+ #ifndef _ASM_X86_PERF_EVENT_H
+ #define _ASM_X86_PERF_EVENT_H
+
++#include <linux/static_call.h>
++
+ /*
+ * Performance event hw details:
+ */
+@@ -518,6 +520,27 @@ static inline void intel_pt_handle_vmx(int on)
+ #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
+ extern void amd_pmu_enable_virt(void);
+ extern void amd_pmu_disable_virt(void);
++
++#if defined(CONFIG_PERF_EVENTS_AMD_BRS)
++
++#define PERF_NEEDS_LOPWR_CB 1
++
++/*
++ * architectural low power callback impacts
++ * drivers/acpi/processor_idle.c
++ * drivers/acpi/acpi_pad.c
++ */
++extern void perf_amd_brs_lopwr_cb(bool lopwr_in);
++
++DECLARE_STATIC_CALL(perf_lopwr_cb, perf_amd_brs_lopwr_cb);
++
++static inline void perf_lopwr_cb(bool lopwr_in)
++{
++ static_call_mod(perf_lopwr_cb)(lopwr_in);
++}
++
++#endif /* PERF_NEEDS_LOPWR_CB */
++
+ #else
+ static inline void amd_pmu_enable_virt(void) { }
+ static inline void amd_pmu_disable_virt(void) { }
+--
+2.37.3
+