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 | |
| 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>
| -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 | ||
