diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-04-23 08:16:36 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-04-23 08:16:36 -0400 |
commit | 84eaae155a16d7864f0f814934e5062885cb0709 (patch) | |
tree | afdbb8a4375a2d755f6e4d63767396bfc4124c50 /arch/x86/events | |
parent | f454bfddf6ba557381d8bf5df50eff778602ff23 (diff) | |
parent | c3b46c73264b03000d1e18b22f5caf63332547c9 (diff) |
Merge tag 'v4.6-rc4' into sched/core, to refresh the tree
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/events')
-rw-r--r-- | arch/x86/events/amd/core.c | 21 | ||||
-rw-r--r-- | arch/x86/events/amd/ibs.c | 52 | ||||
-rw-r--r-- | arch/x86/events/perf_event.h | 11 |
3 files changed, 71 insertions, 13 deletions
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c index 049ada8d4e9c..86a9bec18dab 100644 --- a/arch/x86/events/amd/core.c +++ b/arch/x86/events/amd/core.c | |||
@@ -369,7 +369,7 @@ static int amd_pmu_cpu_prepare(int cpu) | |||
369 | 369 | ||
370 | WARN_ON_ONCE(cpuc->amd_nb); | 370 | WARN_ON_ONCE(cpuc->amd_nb); |
371 | 371 | ||
372 | if (boot_cpu_data.x86_max_cores < 2) | 372 | if (!x86_pmu.amd_nb_constraints) |
373 | return NOTIFY_OK; | 373 | return NOTIFY_OK; |
374 | 374 | ||
375 | cpuc->amd_nb = amd_alloc_nb(cpu); | 375 | cpuc->amd_nb = amd_alloc_nb(cpu); |
@@ -388,7 +388,7 @@ static void amd_pmu_cpu_starting(int cpu) | |||
388 | 388 | ||
389 | cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY; | 389 | cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY; |
390 | 390 | ||
391 | if (boot_cpu_data.x86_max_cores < 2) | 391 | if (!x86_pmu.amd_nb_constraints) |
392 | return; | 392 | return; |
393 | 393 | ||
394 | nb_id = amd_get_nb_id(cpu); | 394 | nb_id = amd_get_nb_id(cpu); |
@@ -414,7 +414,7 @@ static void amd_pmu_cpu_dead(int cpu) | |||
414 | { | 414 | { |
415 | struct cpu_hw_events *cpuhw; | 415 | struct cpu_hw_events *cpuhw; |
416 | 416 | ||
417 | if (boot_cpu_data.x86_max_cores < 2) | 417 | if (!x86_pmu.amd_nb_constraints) |
418 | return; | 418 | return; |
419 | 419 | ||
420 | cpuhw = &per_cpu(cpu_hw_events, cpu); | 420 | cpuhw = &per_cpu(cpu_hw_events, cpu); |
@@ -648,6 +648,8 @@ static __initconst const struct x86_pmu amd_pmu = { | |||
648 | .cpu_prepare = amd_pmu_cpu_prepare, | 648 | .cpu_prepare = amd_pmu_cpu_prepare, |
649 | .cpu_starting = amd_pmu_cpu_starting, | 649 | .cpu_starting = amd_pmu_cpu_starting, |
650 | .cpu_dead = amd_pmu_cpu_dead, | 650 | .cpu_dead = amd_pmu_cpu_dead, |
651 | |||
652 | .amd_nb_constraints = 1, | ||
651 | }; | 653 | }; |
652 | 654 | ||
653 | static int __init amd_core_pmu_init(void) | 655 | static int __init amd_core_pmu_init(void) |
@@ -674,6 +676,11 @@ static int __init amd_core_pmu_init(void) | |||
674 | x86_pmu.eventsel = MSR_F15H_PERF_CTL; | 676 | x86_pmu.eventsel = MSR_F15H_PERF_CTL; |
675 | x86_pmu.perfctr = MSR_F15H_PERF_CTR; | 677 | x86_pmu.perfctr = MSR_F15H_PERF_CTR; |
676 | x86_pmu.num_counters = AMD64_NUM_COUNTERS_CORE; | 678 | x86_pmu.num_counters = AMD64_NUM_COUNTERS_CORE; |
679 | /* | ||
680 | * AMD Core perfctr has separate MSRs for the NB events, see | ||
681 | * the amd/uncore.c driver. | ||
682 | */ | ||
683 | x86_pmu.amd_nb_constraints = 0; | ||
677 | 684 | ||
678 | pr_cont("core perfctr, "); | 685 | pr_cont("core perfctr, "); |
679 | return 0; | 686 | return 0; |
@@ -693,6 +700,14 @@ __init int amd_pmu_init(void) | |||
693 | if (ret) | 700 | if (ret) |
694 | return ret; | 701 | return ret; |
695 | 702 | ||
703 | if (num_possible_cpus() == 1) { | ||
704 | /* | ||
705 | * No point in allocating data structures to serialize | ||
706 | * against other CPUs, when there is only the one CPU. | ||
707 | */ | ||
708 | x86_pmu.amd_nb_constraints = 0; | ||
709 | } | ||
710 | |||
696 | /* Events are common for all AMDs */ | 711 | /* Events are common for all AMDs */ |
697 | memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, | 712 | memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, |
698 | sizeof(hw_cache_event_ids)); | 713 | sizeof(hw_cache_event_ids)); |
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c index 3ea25c3917c0..feb90f6730e8 100644 --- a/arch/x86/events/amd/ibs.c +++ b/arch/x86/events/amd/ibs.c | |||
@@ -28,10 +28,46 @@ static u32 ibs_caps; | |||
28 | #define IBS_FETCH_CONFIG_MASK (IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT) | 28 | #define IBS_FETCH_CONFIG_MASK (IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT) |
29 | #define IBS_OP_CONFIG_MASK IBS_OP_MAX_CNT | 29 | #define IBS_OP_CONFIG_MASK IBS_OP_MAX_CNT |
30 | 30 | ||
31 | |||
32 | /* | ||
33 | * IBS states: | ||
34 | * | ||
35 | * ENABLED; tracks the pmu::add(), pmu::del() state, when set the counter is taken | ||
36 | * and any further add()s must fail. | ||
37 | * | ||
38 | * STARTED/STOPPING/STOPPED; deal with pmu::start(), pmu::stop() state but are | ||
39 | * complicated by the fact that the IBS hardware can send late NMIs (ie. after | ||
40 | * we've cleared the EN bit). | ||
41 | * | ||
42 | * In order to consume these late NMIs we have the STOPPED state, any NMI that | ||
43 | * happens after we've cleared the EN state will clear this bit and report the | ||
44 | * NMI handled (this is fundamentally racy in the face or multiple NMI sources, | ||
45 | * someone else can consume our BIT and our NMI will go unhandled). | ||
46 | * | ||
47 | * And since we cannot set/clear this separate bit together with the EN bit, | ||
48 | * there are races; if we cleared STARTED early, an NMI could land in | ||
49 | * between clearing STARTED and clearing the EN bit (in fact multiple NMIs | ||
50 | * could happen if the period is small enough), and consume our STOPPED bit | ||
51 | * and trigger streams of unhandled NMIs. | ||
52 | * | ||
53 | * If, however, we clear STARTED late, an NMI can hit between clearing the | ||
54 | * EN bit and clearing STARTED, still see STARTED set and process the event. | ||
55 | * If this event will have the VALID bit clear, we bail properly, but this | ||
56 | * is not a given. With VALID set we can end up calling pmu::stop() again | ||
57 | * (the throttle logic) and trigger the WARNs in there. | ||
58 | * | ||
59 | * So what we do is set STOPPING before clearing EN to avoid the pmu::stop() | ||
60 | * nesting, and clear STARTED late, so that we have a well defined state over | ||
61 | * the clearing of the EN bit. | ||
62 | * | ||
63 | * XXX: we could probably be using !atomic bitops for all this. | ||
64 | */ | ||
65 | |||
31 | enum ibs_states { | 66 | enum ibs_states { |
32 | IBS_ENABLED = 0, | 67 | IBS_ENABLED = 0, |
33 | IBS_STARTED = 1, | 68 | IBS_STARTED = 1, |
34 | IBS_STOPPING = 2, | 69 | IBS_STOPPING = 2, |
70 | IBS_STOPPED = 3, | ||
35 | 71 | ||
36 | IBS_MAX_STATES, | 72 | IBS_MAX_STATES, |
37 | }; | 73 | }; |
@@ -377,11 +413,10 @@ static void perf_ibs_start(struct perf_event *event, int flags) | |||
377 | 413 | ||
378 | perf_ibs_set_period(perf_ibs, hwc, &period); | 414 | perf_ibs_set_period(perf_ibs, hwc, &period); |
379 | /* | 415 | /* |
380 | * Set STARTED before enabling the hardware, such that | 416 | * Set STARTED before enabling the hardware, such that a subsequent NMI |
381 | * a subsequent NMI must observe it. Then clear STOPPING | 417 | * must observe it. |
382 | * such that we don't consume NMIs by accident. | ||
383 | */ | 418 | */ |
384 | set_bit(IBS_STARTED, pcpu->state); | 419 | set_bit(IBS_STARTED, pcpu->state); |
385 | clear_bit(IBS_STOPPING, pcpu->state); | 420 | clear_bit(IBS_STOPPING, pcpu->state); |
386 | perf_ibs_enable_event(perf_ibs, hwc, period >> 4); | 421 | perf_ibs_enable_event(perf_ibs, hwc, period >> 4); |
387 | 422 | ||
@@ -396,6 +431,9 @@ static void perf_ibs_stop(struct perf_event *event, int flags) | |||
396 | u64 config; | 431 | u64 config; |
397 | int stopping; | 432 | int stopping; |
398 | 433 | ||
434 | if (test_and_set_bit(IBS_STOPPING, pcpu->state)) | ||
435 | return; | ||
436 | |||
399 | stopping = test_bit(IBS_STARTED, pcpu->state); | 437 | stopping = test_bit(IBS_STARTED, pcpu->state); |
400 | 438 | ||
401 | if (!stopping && (hwc->state & PERF_HES_UPTODATE)) | 439 | if (!stopping && (hwc->state & PERF_HES_UPTODATE)) |
@@ -405,12 +443,12 @@ static void perf_ibs_stop(struct perf_event *event, int flags) | |||
405 | 443 | ||
406 | if (stopping) { | 444 | if (stopping) { |
407 | /* | 445 | /* |
408 | * Set STOPPING before disabling the hardware, such that it | 446 | * Set STOPPED before disabling the hardware, such that it |
409 | * must be visible to NMIs the moment we clear the EN bit, | 447 | * must be visible to NMIs the moment we clear the EN bit, |
410 | * at which point we can generate an !VALID sample which | 448 | * at which point we can generate an !VALID sample which |
411 | * we need to consume. | 449 | * we need to consume. |
412 | */ | 450 | */ |
413 | set_bit(IBS_STOPPING, pcpu->state); | 451 | set_bit(IBS_STOPPED, pcpu->state); |
414 | perf_ibs_disable_event(perf_ibs, hwc, config); | 452 | perf_ibs_disable_event(perf_ibs, hwc, config); |
415 | /* | 453 | /* |
416 | * Clear STARTED after disabling the hardware; if it were | 454 | * Clear STARTED after disabling the hardware; if it were |
@@ -556,7 +594,7 @@ fail: | |||
556 | * with samples that even have the valid bit cleared. | 594 | * with samples that even have the valid bit cleared. |
557 | * Mark all this NMIs as handled. | 595 | * Mark all this NMIs as handled. |
558 | */ | 596 | */ |
559 | if (test_and_clear_bit(IBS_STOPPING, pcpu->state)) | 597 | if (test_and_clear_bit(IBS_STOPPED, pcpu->state)) |
560 | return 1; | 598 | return 1; |
561 | 599 | ||
562 | return 0; | 600 | return 0; |
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index ba6ef18528c9..ad4dc7ffffb5 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h | |||
@@ -608,6 +608,11 @@ struct x86_pmu { | |||
608 | atomic_t lbr_exclusive[x86_lbr_exclusive_max]; | 608 | atomic_t lbr_exclusive[x86_lbr_exclusive_max]; |
609 | 609 | ||
610 | /* | 610 | /* |
611 | * AMD bits | ||
612 | */ | ||
613 | unsigned int amd_nb_constraints : 1; | ||
614 | |||
615 | /* | ||
611 | * Extra registers for events | 616 | * Extra registers for events |
612 | */ | 617 | */ |
613 | struct extra_reg *extra_regs; | 618 | struct extra_reg *extra_regs; |
@@ -795,6 +800,9 @@ ssize_t intel_event_sysfs_show(char *page, u64 config); | |||
795 | 800 | ||
796 | struct attribute **merge_attr(struct attribute **a, struct attribute **b); | 801 | struct attribute **merge_attr(struct attribute **a, struct attribute **b); |
797 | 802 | ||
803 | ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, | ||
804 | char *page); | ||
805 | |||
798 | #ifdef CONFIG_CPU_SUP_AMD | 806 | #ifdef CONFIG_CPU_SUP_AMD |
799 | 807 | ||
800 | int amd_pmu_init(void); | 808 | int amd_pmu_init(void); |
@@ -925,9 +933,6 @@ int p6_pmu_init(void); | |||
925 | 933 | ||
926 | int knc_pmu_init(void); | 934 | int knc_pmu_init(void); |
927 | 935 | ||
928 | ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, | ||
929 | char *page); | ||
930 | |||
931 | static inline int is_ht_workaround_enabled(void) | 936 | static inline int is_ht_workaround_enabled(void) |
932 | { | 937 | { |
933 | return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED); | 938 | return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED); |