aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2013-08-12 11:54:05 -0400
committerIngo Molnar <mingo@kernel.org>2013-08-12 11:54:05 -0400
commit0237d7f355eef4d9ab8557e1597e8c9debd6c8c2 (patch)
tree753837a9fb9e3f65bc7450994159683a47f086a6 /arch/x86/kernel/cpu
parentbf6c216282a260d3ce727c23fc15f28a76beff0b (diff)
parentcf870c70a194443f8fc654ddc9d6cfd02c58003b (diff)
Merge branch 'x86/mce' into x86/ras
Pursue a single RAS/MCE topic branch on x86. Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-internal.h3
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c28
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c42
3 files changed, 63 insertions, 10 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index 5b7d4fa5d3b7..09edd0b65fef 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -25,15 +25,18 @@ int mce_severity(struct mce *a, int tolerant, char **msg);
25struct dentry *mce_get_debugfs_dir(void); 25struct dentry *mce_get_debugfs_dir(void);
26 26
27extern struct mce_bank *mce_banks; 27extern struct mce_bank *mce_banks;
28extern mce_banks_t mce_banks_ce_disabled;
28 29
29#ifdef CONFIG_X86_MCE_INTEL 30#ifdef CONFIG_X86_MCE_INTEL
30unsigned long mce_intel_adjust_timer(unsigned long interval); 31unsigned long mce_intel_adjust_timer(unsigned long interval);
31void mce_intel_cmci_poll(void); 32void mce_intel_cmci_poll(void);
32void mce_intel_hcpu_update(unsigned long cpu); 33void mce_intel_hcpu_update(unsigned long cpu);
34void cmci_disable_bank(int bank);
33#else 35#else
34# define mce_intel_adjust_timer mce_adjust_timer_default 36# define mce_intel_adjust_timer mce_adjust_timer_default
35static inline void mce_intel_cmci_poll(void) { } 37static inline void mce_intel_cmci_poll(void) { }
36static inline void mce_intel_hcpu_update(unsigned long cpu) { } 38static inline void mce_intel_hcpu_update(unsigned long cpu) { }
39static inline void cmci_disable_bank(int bank) { }
37#endif 40#endif
38 41
39void mce_timer_kick(unsigned long interval); 42void mce_timer_kick(unsigned long interval);
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 87a65c939bcd..b3218cdee95f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -97,6 +97,15 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {
97 [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL 97 [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
98}; 98};
99 99
100/*
101 * MCA banks controlled through firmware first for corrected errors.
102 * This is a global list of banks for which we won't enable CMCI and we
103 * won't poll. Firmware controls these banks and is responsible for
104 * reporting corrected errors through GHES. Uncorrected/recoverable
105 * errors are still notified through a machine check.
106 */
107mce_banks_t mce_banks_ce_disabled;
108
100static DEFINE_PER_CPU(struct work_struct, mce_work); 109static DEFINE_PER_CPU(struct work_struct, mce_work);
101 110
102static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); 111static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs);
@@ -1935,6 +1944,25 @@ static struct miscdevice mce_chrdev_device = {
1935 &mce_chrdev_ops, 1944 &mce_chrdev_ops,
1936}; 1945};
1937 1946
1947static void __mce_disable_bank(void *arg)
1948{
1949 int bank = *((int *)arg);
1950 __clear_bit(bank, __get_cpu_var(mce_poll_banks));
1951 cmci_disable_bank(bank);
1952}
1953
1954void mce_disable_bank(int bank)
1955{
1956 if (bank >= mca_cfg.banks) {
1957 pr_warn(FW_BUG
1958 "Ignoring request to disable invalid MCA bank %d.\n",
1959 bank);
1960 return;
1961 }
1962 set_bit(bank, mce_banks_ce_disabled);
1963 on_each_cpu(__mce_disable_bank, &bank, 1);
1964}
1965
1938/* 1966/*
1939 * mce=off Disables machine check 1967 * mce=off Disables machine check
1940 * mce=no_cmci Disables CMCI 1968 * mce=no_cmci Disables CMCI
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index d56405309dc1..4cfe0458ca66 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -203,6 +203,10 @@ static void cmci_discover(int banks)
203 if (test_bit(i, owned)) 203 if (test_bit(i, owned))
204 continue; 204 continue;
205 205
206 /* Skip banks in firmware first mode */
207 if (test_bit(i, mce_banks_ce_disabled))
208 continue;
209
206 rdmsrl(MSR_IA32_MCx_CTL2(i), val); 210 rdmsrl(MSR_IA32_MCx_CTL2(i), val);
207 211
208 /* Already owned by someone else? */ 212 /* Already owned by someone else? */
@@ -271,6 +275,19 @@ void cmci_recheck(void)
271 local_irq_restore(flags); 275 local_irq_restore(flags);
272} 276}
273 277
278/* Caller must hold the lock on cmci_discover_lock */
279static void __cmci_disable_bank(int bank)
280{
281 u64 val;
282
283 if (!test_bit(bank, __get_cpu_var(mce_banks_owned)))
284 return;
285 rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
286 val &= ~MCI_CTL2_CMCI_EN;
287 wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
288 __clear_bit(bank, __get_cpu_var(mce_banks_owned));
289}
290
274/* 291/*
275 * Disable CMCI on this CPU for all banks it owns when it goes down. 292 * Disable CMCI on this CPU for all banks it owns when it goes down.
276 * This allows other CPUs to claim the banks on rediscovery. 293 * This allows other CPUs to claim the banks on rediscovery.
@@ -280,20 +297,12 @@ void cmci_clear(void)
280 unsigned long flags; 297 unsigned long flags;
281 int i; 298 int i;
282 int banks; 299 int banks;
283 u64 val;
284 300
285 if (!cmci_supported(&banks)) 301 if (!cmci_supported(&banks))
286 return; 302 return;
287 raw_spin_lock_irqsave(&cmci_discover_lock, flags); 303 raw_spin_lock_irqsave(&cmci_discover_lock, flags);
288 for (i = 0; i < banks; i++) { 304 for (i = 0; i < banks; i++)
289 if (!test_bit(i, __get_cpu_var(mce_banks_owned))) 305 __cmci_disable_bank(i);
290 continue;
291 /* Disable CMCI */
292 rdmsrl(MSR_IA32_MCx_CTL2(i), val);
293 val &= ~MCI_CTL2_CMCI_EN;
294 wrmsrl(MSR_IA32_MCx_CTL2(i), val);
295 __clear_bit(i, __get_cpu_var(mce_banks_owned));
296 }
297 raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); 306 raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
298} 307}
299 308
@@ -327,6 +336,19 @@ void cmci_reenable(void)
327 cmci_discover(banks); 336 cmci_discover(banks);
328} 337}
329 338
339void cmci_disable_bank(int bank)
340{
341 int banks;
342 unsigned long flags;
343
344 if (!cmci_supported(&banks))
345 return;
346
347 raw_spin_lock_irqsave(&cmci_discover_lock, flags);
348 __cmci_disable_bank(bank);
349 raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
350}
351
330static void intel_init_cmci(void) 352static void intel_init_cmci(void)
331{ 353{
332 int banks; 354 int banks;