aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt5
-rw-r--r--arch/x86/events/intel/core.c113
-rw-r--r--arch/x86/events/perf_event.h4
-rw-r--r--arch/x86/include/asm/msr-index.h1
4 files changed, 122 insertions, 1 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 92eb1f42240d..6795dedcbd1e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -856,6 +856,11 @@
856 causing system reset or hang due to sending 856 causing system reset or hang due to sending
857 INIT from AP to BSP. 857 INIT from AP to BSP.
858 858
859 disable_counter_freezing [HW]
860 Disable Intel PMU counter freezing feature.
861 The feature only exists starting from
862 Arch Perfmon v4 (Skylake and newer).
863
859 disable_ddw [PPC/PSERIES] 864 disable_ddw [PPC/PSERIES]
860 Disable Dynamic DMA Window support. Use this if 865 Disable Dynamic DMA Window support. Use this if
861 to workaround buggy firmware. 866 to workaround buggy firmware.
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 9b320a51f82f..bd3b8f3600b2 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -1995,6 +1995,18 @@ static void intel_pmu_nhm_enable_all(int added)
1995 intel_pmu_enable_all(added); 1995 intel_pmu_enable_all(added);
1996} 1996}
1997 1997
1998static void enable_counter_freeze(void)
1999{
2000 update_debugctlmsr(get_debugctlmsr() |
2001 DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI);
2002}
2003
2004static void disable_counter_freeze(void)
2005{
2006 update_debugctlmsr(get_debugctlmsr() &
2007 ~DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI);
2008}
2009
1998static inline u64 intel_pmu_get_status(void) 2010static inline u64 intel_pmu_get_status(void)
1999{ 2011{
2000 u64 status; 2012 u64 status;
@@ -2290,6 +2302,91 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
2290 return handled; 2302 return handled;
2291} 2303}
2292 2304
2305static bool disable_counter_freezing;
2306static int __init intel_perf_counter_freezing_setup(char *s)
2307{
2308 disable_counter_freezing = true;
2309 pr_info("Intel PMU Counter freezing feature disabled\n");
2310 return 1;
2311}
2312__setup("disable_counter_freezing", intel_perf_counter_freezing_setup);
2313
2314/*
2315 * Simplified handler for Arch Perfmon v4:
2316 * - We rely on counter freezing/unfreezing to enable/disable the PMU.
2317 * This is done automatically on PMU ack.
2318 * - Ack the PMU only after the APIC.
2319 */
2320
2321static int intel_pmu_handle_irq_v4(struct pt_regs *regs)
2322{
2323 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
2324 int handled = 0;
2325 bool bts = false;
2326 u64 status;
2327 int pmu_enabled = cpuc->enabled;
2328 int loops = 0;
2329
2330 /* PMU has been disabled because of counter freezing */
2331 cpuc->enabled = 0;
2332 if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
2333 bts = true;
2334 intel_bts_disable_local();
2335 handled = intel_pmu_drain_bts_buffer();
2336 handled += intel_bts_interrupt();
2337 }
2338 status = intel_pmu_get_status();
2339 if (!status)
2340 goto done;
2341again:
2342 intel_pmu_lbr_read();
2343 if (++loops > 100) {
2344 static bool warned;
2345
2346 if (!warned) {
2347 WARN(1, "perfevents: irq loop stuck!\n");
2348 perf_event_print_debug();
2349 warned = true;
2350 }
2351 intel_pmu_reset();
2352 goto done;
2353 }
2354
2355
2356 handled += handle_pmi_common(regs, status);
2357done:
2358 /* Ack the PMI in the APIC */
2359 apic_write(APIC_LVTPC, APIC_DM_NMI);
2360
2361 /*
2362 * The counters start counting immediately while ack the status.
2363 * Make it as close as possible to IRET. This avoids bogus
2364 * freezing on Skylake CPUs.
2365 */
2366 if (status) {
2367 intel_pmu_ack_status(status);
2368 } else {
2369 /*
2370 * CPU may issues two PMIs very close to each other.
2371 * When the PMI handler services the first one, the
2372 * GLOBAL_STATUS is already updated to reflect both.
2373 * When it IRETs, the second PMI is immediately
2374 * handled and it sees clear status. At the meantime,
2375 * there may be a third PMI, because the freezing bit
2376 * isn't set since the ack in first PMI handlers.
2377 * Double check if there is more work to be done.
2378 */
2379 status = intel_pmu_get_status();
2380 if (status)
2381 goto again;
2382 }
2383
2384 if (bts)
2385 intel_bts_enable_local();
2386 cpuc->enabled = pmu_enabled;
2387 return handled;
2388}
2389
2293/* 2390/*
2294 * This handler is triggered by the local APIC, so the APIC IRQ handling 2391 * This handler is triggered by the local APIC, so the APIC IRQ handling
2295 * rules apply: 2392 * rules apply:
@@ -3361,6 +3458,9 @@ static void intel_pmu_cpu_starting(int cpu)
3361 if (x86_pmu.version > 1) 3458 if (x86_pmu.version > 1)
3362 flip_smm_bit(&x86_pmu.attr_freeze_on_smi); 3459 flip_smm_bit(&x86_pmu.attr_freeze_on_smi);
3363 3460
3461 if (x86_pmu.counter_freezing)
3462 enable_counter_freeze();
3463
3364 if (!cpuc->shared_regs) 3464 if (!cpuc->shared_regs)
3365 return; 3465 return;
3366 3466
@@ -3432,6 +3532,9 @@ static void intel_pmu_cpu_dying(int cpu)
3432 free_excl_cntrs(cpu); 3532 free_excl_cntrs(cpu);
3433 3533
3434 fini_debug_store_on_cpu(cpu); 3534 fini_debug_store_on_cpu(cpu);
3535
3536 if (x86_pmu.counter_freezing)
3537 disable_counter_freeze();
3435} 3538}
3436 3539
3437static void intel_pmu_sched_task(struct perf_event_context *ctx, 3540static void intel_pmu_sched_task(struct perf_event_context *ctx,
@@ -3946,6 +4049,9 @@ __init int intel_pmu_init(void)
3946 max((int)edx.split.num_counters_fixed, assume); 4049 max((int)edx.split.num_counters_fixed, assume);
3947 } 4050 }
3948 4051
4052 if (version >= 4)
4053 x86_pmu.counter_freezing = !disable_counter_freezing;
4054
3949 if (boot_cpu_has(X86_FEATURE_PDCM)) { 4055 if (boot_cpu_has(X86_FEATURE_PDCM)) {
3950 u64 capabilities; 4056 u64 capabilities;
3951 4057
@@ -4442,6 +4548,13 @@ __init int intel_pmu_init(void)
4442 pr_cont("full-width counters, "); 4548 pr_cont("full-width counters, ");
4443 } 4549 }
4444 4550
4551 /*
4552 * For arch perfmon 4 use counter freezing to avoid
4553 * several MSR accesses in the PMI.
4554 */
4555 if (x86_pmu.counter_freezing)
4556 x86_pmu.handle_irq = intel_pmu_handle_irq_v4;
4557
4445 kfree(to_free); 4558 kfree(to_free);
4446 return 0; 4559 return 0;
4447} 4560}
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 156286335351..adae087cecdd 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -560,9 +560,11 @@ struct x86_pmu {
560 struct event_constraint *event_constraints; 560 struct event_constraint *event_constraints;
561 struct x86_pmu_quirk *quirks; 561 struct x86_pmu_quirk *quirks;
562 int perfctr_second_write; 562 int perfctr_second_write;
563 bool late_ack;
564 u64 (*limit_period)(struct perf_event *event, u64 l); 563 u64 (*limit_period)(struct perf_event *event, u64 l);
565 564
565 /* PMI handler bits */
566 unsigned int late_ack :1,
567 counter_freezing :1;
566 /* 568 /*
567 * sysfs attrs 569 * sysfs attrs
568 */ 570 */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 4731f0cf97c5..80f4a4f38c79 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -164,6 +164,7 @@
164#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9) 164#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9)
165#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10) 165#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10)
166#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11) 166#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
167#define DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI (1UL << 12)
167#define DEBUGCTLMSR_FREEZE_IN_SMM_BIT 14 168#define DEBUGCTLMSR_FREEZE_IN_SMM_BIT 14
168#define DEBUGCTLMSR_FREEZE_IN_SMM (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT) 169#define DEBUGCTLMSR_FREEZE_IN_SMM (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT)
169 170