Skip to content

Commit 3ed57b4

Browse files
aeglbp3tk0v
authored andcommitted
x86/mce: Remove old CMCI storm mitigation code
When a "storm" of corrected machine check interrupts (CMCI) is detected this code mitigates by disabling CMCI interrupt signalling from all of the banks owned by the CPU that saw the storm. There are problems with this approach: 1) It is very coarse grained. In all likelihood only one of the banks was generating the interrupts, but CMCI is disabled for all. This means Linux may delay seeing and processing errors logged from other banks. 2) Although CMCI stands for Corrected Machine Check Interrupt, it is also used to signal when an uncorrected error is logged. This is a problem because these errors should be handled in a timely manner. Delete all this code in preparation for a finer grained solution. Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Yazen Ghannam <yazen.ghannam@amd.com> Tested-by: Yazen Ghannam <yazen.ghannam@amd.com> Link: https://lore.kernel.org/r/20231115195450.12963-2-tony.luck@intel.com
1 parent cf05739 commit 3ed57b4

File tree

3 files changed

+1
-170
lines changed

3 files changed

+1
-170
lines changed

arch/x86/kernel/cpu/mce/core.c

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,13 +1617,6 @@ static unsigned long check_interval = INITIAL_CHECK_INTERVAL;
16171617
static DEFINE_PER_CPU(unsigned long, mce_next_interval); /* in jiffies */
16181618
static DEFINE_PER_CPU(struct timer_list, mce_timer);
16191619

1620-
static unsigned long mce_adjust_timer_default(unsigned long interval)
1621-
{
1622-
return interval;
1623-
}
1624-
1625-
static unsigned long (*mce_adjust_timer)(unsigned long interval) = mce_adjust_timer_default;
1626-
16271620
static void __start_timer(struct timer_list *t, unsigned long interval)
16281621
{
16291622
unsigned long when = jiffies + interval;
@@ -1653,15 +1646,9 @@ static void mce_timer_fn(struct timer_list *t)
16531646

16541647
iv = __this_cpu_read(mce_next_interval);
16551648

1656-
if (mce_available(this_cpu_ptr(&cpu_info))) {
1649+
if (mce_available(this_cpu_ptr(&cpu_info)))
16571650
mc_poll_banks();
16581651

1659-
if (mce_intel_cmci_poll()) {
1660-
iv = mce_adjust_timer(iv);
1661-
goto done;
1662-
}
1663-
}
1664-
16651652
/*
16661653
* Alert userspace if needed. If we logged an MCE, reduce the polling
16671654
* interval, otherwise increase the polling interval.
@@ -1671,7 +1658,6 @@ static void mce_timer_fn(struct timer_list *t)
16711658
else
16721659
iv = min(iv * 2, round_jiffies_relative(check_interval * HZ));
16731660

1674-
done:
16751661
__this_cpu_write(mce_next_interval, iv);
16761662
__start_timer(t, iv);
16771663
}
@@ -2011,7 +1997,6 @@ static void mce_zhaoxin_feature_init(struct cpuinfo_x86 *c)
20111997

20121998
intel_init_cmci();
20131999
intel_init_lmce();
2014-
mce_adjust_timer = cmci_intel_adjust_timer;
20152000
}
20162001

20172002
static void mce_zhaoxin_feature_clear(struct cpuinfo_x86 *c)
@@ -2024,7 +2009,6 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
20242009
switch (c->x86_vendor) {
20252010
case X86_VENDOR_INTEL:
20262011
mce_intel_feature_init(c);
2027-
mce_adjust_timer = cmci_intel_adjust_timer;
20282012
break;
20292013

20302014
case X86_VENDOR_AMD: {
@@ -2678,8 +2662,6 @@ static void mce_reenable_cpu(void)
26782662

26792663
static int mce_cpu_dead(unsigned int cpu)
26802664
{
2681-
mce_intel_hcpu_update(cpu);
2682-
26832665
/* intentionally ignoring frozen here */
26842666
if (!cpuhp_tasks_frozen)
26852667
cmci_rediscover();

arch/x86/kernel/cpu/mce/intel.c

Lines changed: 0 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,6 @@
4141
*/
4242
static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
4343

44-
/*
45-
* CMCI storm detection backoff counter
46-
*
47-
* During storm, we reset this counter to INITIAL_CHECK_INTERVAL in case we've
48-
* encountered an error. If not, we decrement it by one. We signal the end of
49-
* the CMCI storm when it reaches 0.
50-
*/
51-
static DEFINE_PER_CPU(int, cmci_backoff_cnt);
52-
5344
/*
5445
* cmci_discover_lock protects against parallel discovery attempts
5546
* which could race against each other.
@@ -64,21 +55,6 @@ static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
6455
static DEFINE_SPINLOCK(cmci_poll_lock);
6556

6657
#define CMCI_THRESHOLD 1
67-
#define CMCI_POLL_INTERVAL (30 * HZ)
68-
#define CMCI_STORM_INTERVAL (HZ)
69-
#define CMCI_STORM_THRESHOLD 15
70-
71-
static DEFINE_PER_CPU(unsigned long, cmci_time_stamp);
72-
static DEFINE_PER_CPU(unsigned int, cmci_storm_cnt);
73-
static DEFINE_PER_CPU(unsigned int, cmci_storm_state);
74-
75-
enum {
76-
CMCI_STORM_NONE,
77-
CMCI_STORM_ACTIVE,
78-
CMCI_STORM_SUBSIDED,
79-
};
80-
81-
static atomic_t cmci_storm_on_cpus;
8258

8359
static int cmci_supported(int *banks)
8460
{
@@ -134,124 +110,6 @@ static bool lmce_supported(void)
134110
return tmp & FEAT_CTL_LMCE_ENABLED;
135111
}
136112

137-
bool mce_intel_cmci_poll(void)
138-
{
139-
if (__this_cpu_read(cmci_storm_state) == CMCI_STORM_NONE)
140-
return false;
141-
142-
/*
143-
* Reset the counter if we've logged an error in the last poll
144-
* during the storm.
145-
*/
146-
if (machine_check_poll(0, this_cpu_ptr(&mce_banks_owned)))
147-
this_cpu_write(cmci_backoff_cnt, INITIAL_CHECK_INTERVAL);
148-
else
149-
this_cpu_dec(cmci_backoff_cnt);
150-
151-
return true;
152-
}
153-
154-
void mce_intel_hcpu_update(unsigned long cpu)
155-
{
156-
if (per_cpu(cmci_storm_state, cpu) == CMCI_STORM_ACTIVE)
157-
atomic_dec(&cmci_storm_on_cpus);
158-
159-
per_cpu(cmci_storm_state, cpu) = CMCI_STORM_NONE;
160-
}
161-
162-
static void cmci_toggle_interrupt_mode(bool on)
163-
{
164-
unsigned long flags, *owned;
165-
int bank;
166-
u64 val;
167-
168-
raw_spin_lock_irqsave(&cmci_discover_lock, flags);
169-
owned = this_cpu_ptr(mce_banks_owned);
170-
for_each_set_bit(bank, owned, MAX_NR_BANKS) {
171-
rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
172-
173-
if (on)
174-
val |= MCI_CTL2_CMCI_EN;
175-
else
176-
val &= ~MCI_CTL2_CMCI_EN;
177-
178-
wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
179-
}
180-
raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
181-
}
182-
183-
unsigned long cmci_intel_adjust_timer(unsigned long interval)
184-
{
185-
if ((this_cpu_read(cmci_backoff_cnt) > 0) &&
186-
(__this_cpu_read(cmci_storm_state) == CMCI_STORM_ACTIVE)) {
187-
mce_notify_irq();
188-
return CMCI_STORM_INTERVAL;
189-
}
190-
191-
switch (__this_cpu_read(cmci_storm_state)) {
192-
case CMCI_STORM_ACTIVE:
193-
194-
/*
195-
* We switch back to interrupt mode once the poll timer has
196-
* silenced itself. That means no events recorded and the timer
197-
* interval is back to our poll interval.
198-
*/
199-
__this_cpu_write(cmci_storm_state, CMCI_STORM_SUBSIDED);
200-
if (!atomic_sub_return(1, &cmci_storm_on_cpus))
201-
pr_notice("CMCI storm subsided: switching to interrupt mode\n");
202-
203-
fallthrough;
204-
205-
case CMCI_STORM_SUBSIDED:
206-
/*
207-
* We wait for all CPUs to go back to SUBSIDED state. When that
208-
* happens we switch back to interrupt mode.
209-
*/
210-
if (!atomic_read(&cmci_storm_on_cpus)) {
211-
__this_cpu_write(cmci_storm_state, CMCI_STORM_NONE);
212-
cmci_toggle_interrupt_mode(true);
213-
cmci_recheck();
214-
}
215-
return CMCI_POLL_INTERVAL;
216-
default:
217-
218-
/* We have shiny weather. Let the poll do whatever it thinks. */
219-
return interval;
220-
}
221-
}
222-
223-
static bool cmci_storm_detect(void)
224-
{
225-
unsigned int cnt = __this_cpu_read(cmci_storm_cnt);
226-
unsigned long ts = __this_cpu_read(cmci_time_stamp);
227-
unsigned long now = jiffies;
228-
int r;
229-
230-
if (__this_cpu_read(cmci_storm_state) != CMCI_STORM_NONE)
231-
return true;
232-
233-
if (time_before_eq(now, ts + CMCI_STORM_INTERVAL)) {
234-
cnt++;
235-
} else {
236-
cnt = 1;
237-
__this_cpu_write(cmci_time_stamp, now);
238-
}
239-
__this_cpu_write(cmci_storm_cnt, cnt);
240-
241-
if (cnt <= CMCI_STORM_THRESHOLD)
242-
return false;
243-
244-
cmci_toggle_interrupt_mode(false);
245-
__this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE);
246-
r = atomic_add_return(1, &cmci_storm_on_cpus);
247-
mce_timer_kick(CMCI_STORM_INTERVAL);
248-
this_cpu_write(cmci_backoff_cnt, INITIAL_CHECK_INTERVAL);
249-
250-
if (r == 1)
251-
pr_notice("CMCI storm detected: switching to poll mode\n");
252-
return true;
253-
}
254-
255113
/*
256114
* The interrupt handler. This is called on every event.
257115
* Just call the poller directly to log any events.
@@ -260,9 +118,6 @@ static bool cmci_storm_detect(void)
260118
*/
261119
static void intel_threshold_interrupt(void)
262120
{
263-
if (cmci_storm_detect())
264-
return;
265-
266121
machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned));
267122
}
268123

arch/x86/kernel/cpu/mce/internal.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,13 @@ struct dentry *mce_get_debugfs_dir(void);
4141
extern mce_banks_t mce_banks_ce_disabled;
4242

4343
#ifdef CONFIG_X86_MCE_INTEL
44-
unsigned long cmci_intel_adjust_timer(unsigned long interval);
45-
bool mce_intel_cmci_poll(void);
46-
void mce_intel_hcpu_update(unsigned long cpu);
4744
void cmci_disable_bank(int bank);
4845
void intel_init_cmci(void);
4946
void intel_init_lmce(void);
5047
void intel_clear_lmce(void);
5148
bool intel_filter_mce(struct mce *m);
5249
bool intel_mce_usable_address(struct mce *m);
5350
#else
54-
# define cmci_intel_adjust_timer mce_adjust_timer_default
55-
static inline bool mce_intel_cmci_poll(void) { return false; }
56-
static inline void mce_intel_hcpu_update(unsigned long cpu) { }
5751
static inline void cmci_disable_bank(int bank) { }
5852
static inline void intel_init_cmci(void) { }
5953
static inline void intel_init_lmce(void) { }

0 commit comments

Comments
 (0)