[PATCH] x86, MCE, AMD: save IA32_MCi_STATUS before machine_check_poll() resets it

Chen Yucong
2014-09-23T08:19:31Z

machine_check_poll() will reset IA32_MCi_STATUS register to zero.
So we need to save the content of IA32_MCi_STATUS MSRs before
calling machine_check_poll() for logging threshold interrupt event.

mce_setup() does not gather the content of IA32_MCG_STATUS, so it
should be read explicitly.

Signed-off-by: Chen Yucong <slaoub@gmail.com>
---
arch/x86/kernel/cpu/mcheck/mce_amd.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index f8c56bd..9148b4d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -275,6 +275,12 @@ static void amd_threshold_interrupt(void)

mce_setup(&m);

+ /*
+ * mce_setup() can't gather the content of IA32_MCG_STATUS,
+ * so it should be read explicitly.
+ */
+ rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
+
/* assume first bank caused it */
for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
@@ -305,6 +311,12 @@ static void amd_threshold_interrupt(void)
(high & MASK_LOCKED_HI))
continue;

+ /*
+ * machine_check_poll() will reset IA32_MCi_STATUS
+ * register to zero, save it for use later.
+ */
+ rdmsrl(MSR_IA32_MCx_STATUS(bank), m.status);
+
/*
* Log the machine check that caused the threshold
* event.
@@ -314,7 +326,6 @@ static void amd_threshold_interrupt(void)

if (high & MASK_OVERFLOW_HI) {
rdmsrl(address, m.misc);
- rdmsrl(MSR_IA32_MCx_STATUS(bank), m.status);
m.bank = K8_MCE_THRESHOLD_BASE
+ bank * NR_BLOCKS
+ block;
--
1.7.10.4