提交 00f91adf 编写于 作者: B Borislav Petkov 提交者: Greg Kroah-Hartman

x86/MCE/AMD: Fix the thresholding machinery initialization order

commit 60c8144afc287ef09ce8c1230c6aa972659ba1bb upstream.

Currently, the code sets up the thresholding interrupt vector and only
then goes about initializing the thresholding banks. Which is wrong,
because an early thresholding interrupt would cause a NULL pointer
dereference when accessing those banks and prevent the machine from
booting.

Therefore, set the thresholding interrupt vector only *after* having
initialized the banks successfully.

Fixes: 18807ddb ("x86/mce/AMD: Reset Threshold Limit after logging error")
Reported-by: NRafał Miłecki <rafal@milecki.pl>
Reported-by: NJohn Clemens <clemej@gmail.com>
Signed-off-by: NBorislav Petkov <bp@suse.de>
Tested-by: NRafał Miłecki <rafal@milecki.pl>
Tested-by: NJohn Clemens <john@deater.net>
Cc: Aravind Gopalakrishnan <aravindksg.lkml@gmail.com>
Cc: linux-edac@vger.kernel.org
Cc: stable@vger.kernel.org
Cc: Tony Luck <tony.luck@intel.com>
Cc: x86@kernel.org
Cc: Yazen Ghannam <Yazen.Ghannam@amd.com>
Link: https://lkml.kernel.org/r/20181127101700.2964-1-zajec5@gmail.com
Link: https://bugzilla.kernel.org/show_bug.cgi?id=201291Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 8af02415
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
/* Threshold LVT offset is at MSR0xC0000410[15:12] */ /* Threshold LVT offset is at MSR0xC0000410[15:12] */
#define SMCA_THR_LVT_OFF 0xF000 #define SMCA_THR_LVT_OFF 0xF000
static bool thresholding_en; static bool thresholding_irq_en;
static const char * const th_names[] = { static const char * const th_names[] = {
"load_store", "load_store",
...@@ -534,9 +534,8 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr, ...@@ -534,9 +534,8 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
set_offset: set_offset:
offset = setup_APIC_mce_threshold(offset, new); offset = setup_APIC_mce_threshold(offset, new);
if (offset == new)
if ((offset == new) && (mce_threshold_vector != amd_threshold_interrupt)) thresholding_irq_en = true;
mce_threshold_vector = amd_threshold_interrupt;
done: done:
mce_threshold_block_init(&b, offset); mce_threshold_block_init(&b, offset);
...@@ -1357,9 +1356,6 @@ int mce_threshold_remove_device(unsigned int cpu) ...@@ -1357,9 +1356,6 @@ int mce_threshold_remove_device(unsigned int cpu)
{ {
unsigned int bank; unsigned int bank;
if (!thresholding_en)
return 0;
for (bank = 0; bank < mca_cfg.banks; ++bank) { for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank))) if (!(per_cpu(bank_map, cpu) & (1 << bank)))
continue; continue;
...@@ -1377,9 +1373,6 @@ int mce_threshold_create_device(unsigned int cpu) ...@@ -1377,9 +1373,6 @@ int mce_threshold_create_device(unsigned int cpu)
struct threshold_bank **bp; struct threshold_bank **bp;
int err = 0; int err = 0;
if (!thresholding_en)
return 0;
bp = per_cpu(threshold_banks, cpu); bp = per_cpu(threshold_banks, cpu);
if (bp) if (bp)
return 0; return 0;
...@@ -1408,9 +1401,6 @@ static __init int threshold_init_device(void) ...@@ -1408,9 +1401,6 @@ static __init int threshold_init_device(void)
{ {
unsigned lcpu = 0; unsigned lcpu = 0;
if (mce_threshold_vector == amd_threshold_interrupt)
thresholding_en = true;
/* to hit CPUs online before the notifier is up */ /* to hit CPUs online before the notifier is up */
for_each_online_cpu(lcpu) { for_each_online_cpu(lcpu) {
int err = mce_threshold_create_device(lcpu); int err = mce_threshold_create_device(lcpu);
...@@ -1419,6 +1409,9 @@ static __init int threshold_init_device(void) ...@@ -1419,6 +1409,9 @@ static __init int threshold_init_device(void)
return err; return err;
} }
if (thresholding_irq_en)
mce_threshold_vector = amd_threshold_interrupt;
return 0; return 0;
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册