[PATCH v5 2/3] x86/mce/threshold: Use atomic bit operations on mce_poll_banks
From: Aaron Tomlin
Date: Thu Sep 03 2026 - 15:43:51 EST
cmci_storm_begin() and cmci_storm_end() modify the per-CPU bitmap
mce_poll_banks using non-atomic __set_bit() and __clear_bit().
While mce_poll_banks is a per-CPU variable, cmci_storm_end() runs in timer
softirq context with local hardirqs enabled, whereas cmci_storm_begin()
can be invoked from CMCI hardirq context (via intel_threshold_interrupt()).
If a CMCI hardirq fires while a timer softirq is midway through a
non-atomic read-modify-write operation on mce_poll_banks, the hardirq's
bit update will be overwritten and lost when the softirq resumes.
If a bank entering storm mode loses its bit in mce_poll_banks, it will
neither generate interrupts (as its hardware threshold is bumped to
CMCI_STORM_THRESHOLD) nor be polled by mce_timer_fn(). Consequently, the
bank remains unpolled and its error telemetry is permanently lost until
the next reboot.
Fix this by switching to atomic set_bit() and clear_bit() operations in
cmci_storm_begin() and cmci_storm_end().
Fixes: 7eae17c4add5 ("x86/mce: Add per-bank CMCI storm mitigation")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Aaron Tomlin <atomlin@xxxxxxxxxxx>
---
arch/x86/kernel/cpu/mce/threshold.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/mce/threshold.c b/arch/x86/kernel/cpu/mce/threshold.c
index 6c370d5af5bd..af8346f06318 100644
--- a/arch/x86/kernel/cpu/mce/threshold.c
+++ b/arch/x86/kernel/cpu/mce/threshold.c
@@ -86,7 +86,7 @@ void cmci_storm_begin(unsigned int bank)
{
struct mca_storm_desc *storm = this_cpu_ptr(&storm_desc);
- __set_bit(bank, this_cpu_ptr(mce_poll_banks));
+ set_bit(bank, this_cpu_ptr(mce_poll_banks));
storm->banks[bank].in_storm_mode = true;
/*
@@ -102,7 +102,7 @@ void cmci_storm_end(unsigned int bank)
struct mca_storm_desc *storm = this_cpu_ptr(&storm_desc);
if (!mce_flags.amd_threshold)
- __clear_bit(bank, this_cpu_ptr(mce_poll_banks));
+ clear_bit(bank, this_cpu_ptr(mce_poll_banks));
storm->banks[bank].history = 0;
storm->banks[bank].in_storm_mode = false;
--
2.55.0