diff options
author | Andi Kleen <ak@linux.intel.com> | 2014-11-03 20:00:28 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-11-16 03:53:36 -0500 |
commit | 68055915c1c22489f9658bd2b7391bb11b2cf4e4 (patch) | |
tree | d1fc12606a313d76851d468b09eb1cede3a0c0d9 /arch/x86 | |
parent | 41a134a5830a5e1396723ace0a63000780d6e267 (diff) |
perf/x86/intel/uncore: Fix boot crash on SBOX PMU on Haswell-EP
There were several reports that on some systems writing the SBOX0 PMU
initialization MSR would #GP at boot. This did not happen on all
systems -- my two test systems booted fine.
Writing the three initialization bits bit-by-bit seems to avoid the
problem. So add a special callback to do just that.
This replaces an earlier patch that disabled the SBOX.
Reported-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Reported-and-Tested-by: Patrick Lu <patrick.lu@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Link: http://lkml.kernel.org/r/1415062828-19759-4-git-send-email-andi@firstfloor.org
[ Fixed a whitespace error and added attribution tags that were left out inexplicably. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c index 0af1c932fa0f..f9ed429d6e4f 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c | |||
@@ -486,14 +486,17 @@ static struct attribute_group snbep_uncore_qpi_format_group = { | |||
486 | .attrs = snbep_uncore_qpi_formats_attr, | 486 | .attrs = snbep_uncore_qpi_formats_attr, |
487 | }; | 487 | }; |
488 | 488 | ||
489 | #define SNBEP_UNCORE_MSR_OPS_COMMON_INIT() \ | 489 | #define __SNBEP_UNCORE_MSR_OPS_COMMON_INIT() \ |
490 | .init_box = snbep_uncore_msr_init_box, \ | ||
491 | .disable_box = snbep_uncore_msr_disable_box, \ | 490 | .disable_box = snbep_uncore_msr_disable_box, \ |
492 | .enable_box = snbep_uncore_msr_enable_box, \ | 491 | .enable_box = snbep_uncore_msr_enable_box, \ |
493 | .disable_event = snbep_uncore_msr_disable_event, \ | 492 | .disable_event = snbep_uncore_msr_disable_event, \ |
494 | .enable_event = snbep_uncore_msr_enable_event, \ | 493 | .enable_event = snbep_uncore_msr_enable_event, \ |
495 | .read_counter = uncore_msr_read_counter | 494 | .read_counter = uncore_msr_read_counter |
496 | 495 | ||
496 | #define SNBEP_UNCORE_MSR_OPS_COMMON_INIT() \ | ||
497 | __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(), \ | ||
498 | .init_box = snbep_uncore_msr_init_box \ | ||
499 | |||
497 | static struct intel_uncore_ops snbep_uncore_msr_ops = { | 500 | static struct intel_uncore_ops snbep_uncore_msr_ops = { |
498 | SNBEP_UNCORE_MSR_OPS_COMMON_INIT(), | 501 | SNBEP_UNCORE_MSR_OPS_COMMON_INIT(), |
499 | }; | 502 | }; |
@@ -1919,6 +1922,30 @@ static struct intel_uncore_type hswep_uncore_cbox = { | |||
1919 | .format_group = &hswep_uncore_cbox_format_group, | 1922 | .format_group = &hswep_uncore_cbox_format_group, |
1920 | }; | 1923 | }; |
1921 | 1924 | ||
1925 | /* | ||
1926 | * Write SBOX Initialization register bit by bit to avoid spurious #GPs | ||
1927 | */ | ||
1928 | static void hswep_uncore_sbox_msr_init_box(struct intel_uncore_box *box) | ||
1929 | { | ||
1930 | unsigned msr = uncore_msr_box_ctl(box); | ||
1931 | |||
1932 | if (msr) { | ||
1933 | u64 init = SNBEP_PMON_BOX_CTL_INT; | ||
1934 | u64 flags = 0; | ||
1935 | int i; | ||
1936 | |||
1937 | for_each_set_bit(i, (unsigned long *)&init, 64) { | ||
1938 | flags |= (1ULL << i); | ||
1939 | wrmsrl(msr, flags); | ||
1940 | } | ||
1941 | } | ||
1942 | } | ||
1943 | |||
1944 | static struct intel_uncore_ops hswep_uncore_sbox_msr_ops = { | ||
1945 | __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(), | ||
1946 | .init_box = hswep_uncore_sbox_msr_init_box | ||
1947 | }; | ||
1948 | |||
1922 | static struct attribute *hswep_uncore_sbox_formats_attr[] = { | 1949 | static struct attribute *hswep_uncore_sbox_formats_attr[] = { |
1923 | &format_attr_event.attr, | 1950 | &format_attr_event.attr, |
1924 | &format_attr_umask.attr, | 1951 | &format_attr_umask.attr, |
@@ -1944,7 +1971,7 @@ static struct intel_uncore_type hswep_uncore_sbox = { | |||
1944 | .event_mask = HSWEP_S_MSR_PMON_RAW_EVENT_MASK, | 1971 | .event_mask = HSWEP_S_MSR_PMON_RAW_EVENT_MASK, |
1945 | .box_ctl = HSWEP_S0_MSR_PMON_BOX_CTL, | 1972 | .box_ctl = HSWEP_S0_MSR_PMON_BOX_CTL, |
1946 | .msr_offset = HSWEP_SBOX_MSR_OFFSET, | 1973 | .msr_offset = HSWEP_SBOX_MSR_OFFSET, |
1947 | .ops = &snbep_uncore_msr_ops, | 1974 | .ops = &hswep_uncore_sbox_msr_ops, |
1948 | .format_group = &hswep_uncore_sbox_format_group, | 1975 | .format_group = &hswep_uncore_sbox_format_group, |
1949 | }; | 1976 | }; |
1950 | 1977 | ||