|
7 | 7 | * Contributed by Stephane Eranian <eranian@google.com> |
8 | 8 | */ |
9 | 9 | #include <linux/kernel.h> |
| 10 | +#include <linux/jump_label.h> |
10 | 11 | #include <asm/msr.h> |
11 | 12 | #include <asm/cpufeature.h> |
12 | 13 |
|
@@ -329,3 +330,35 @@ void amd_pmu_brs_sched_task(struct perf_event_context *ctx, bool sched_in) |
329 | 330 | if (sched_in) |
330 | 331 | amd_brs_poison_buffer(); |
331 | 332 | } |
| 333 | + |
| 334 | +/* |
| 335 | + * called from ACPI processor_idle.c or acpi_pad.c |
| 336 | + * with interrupts disabled |
| 337 | + */ |
| 338 | +void perf_amd_brs_lopwr_cb(bool lopwr_in) |
| 339 | +{ |
| 340 | + struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); |
| 341 | + union amd_debug_extn_cfg cfg; |
| 342 | + |
| 343 | + /* |
| 344 | + * on mwait in, we may end up in non C0 state. |
| 345 | + * we must disable branch sampling to avoid holding the NMI |
| 346 | + * for too long. We disable it in hardware but we |
| 347 | + * keep the state in cpuc, so we can re-enable. |
| 348 | + * |
| 349 | + * The hardware will deliver the NMI if needed when brsmen cleared |
| 350 | + */ |
| 351 | + if (cpuc->brs_active) { |
| 352 | + cfg.val = get_debug_extn_cfg(); |
| 353 | + cfg.brsmen = !lopwr_in; |
| 354 | + set_debug_extn_cfg(cfg.val); |
| 355 | + } |
| 356 | +} |
| 357 | + |
| 358 | +DEFINE_STATIC_CALL_NULL(perf_lopwr_cb, perf_amd_brs_lopwr_cb); |
| 359 | +EXPORT_STATIC_CALL_TRAMP_GPL(perf_lopwr_cb); |
| 360 | + |
| 361 | +void __init amd_brs_lopwr_init(void) |
| 362 | +{ |
| 363 | + static_call_update(perf_lopwr_cb, perf_amd_brs_lopwr_cb); |
| 364 | +} |
0 commit comments