Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kernel/cpu/mce/internal.h
50376 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
#ifndef __X86_MCE_INTERNAL_H__
3
#define __X86_MCE_INTERNAL_H__
4
5
#undef pr_fmt
6
#define pr_fmt(fmt) "mce: " fmt
7
8
#include <linux/device.h>
9
#include <asm/mce.h>
10
11
enum severity_level {
12
MCE_NO_SEVERITY,
13
MCE_DEFERRED_SEVERITY,
14
MCE_UCNA_SEVERITY = MCE_DEFERRED_SEVERITY,
15
MCE_KEEP_SEVERITY,
16
MCE_SOME_SEVERITY,
17
MCE_AO_SEVERITY,
18
MCE_UC_SEVERITY,
19
MCE_AR_SEVERITY,
20
MCE_PANIC_SEVERITY,
21
};
22
23
extern struct blocking_notifier_head x86_mce_decoder_chain;
24
25
#define INITIAL_CHECK_INTERVAL 5 * 60 /* 5 minutes */
26
27
struct mce_evt_llist {
28
struct llist_node llnode;
29
struct mce_hw_err err;
30
};
31
32
void mce_gen_pool_process(struct work_struct *__unused);
33
bool mce_gen_pool_empty(void);
34
bool mce_gen_pool_add(struct mce_hw_err *err);
35
bool mce_gen_pool_init(void);
36
struct llist_node *mce_gen_pool_prepare_records(void);
37
38
int mce_severity(struct mce *a, struct pt_regs *regs, char **msg, bool is_excp);
39
struct dentry *mce_get_debugfs_dir(void);
40
41
extern mce_banks_t mce_banks_ce_disabled;
42
43
#ifdef CONFIG_X86_MCE_INTEL
44
void mce_intel_handle_storm(int bank, bool on);
45
void cmci_disable_bank(int bank);
46
void intel_init_cmci(void);
47
void intel_init_lmce(void);
48
void intel_clear_lmce(void);
49
bool intel_filter_mce(struct mce *m);
50
bool intel_mce_usable_address(struct mce *m);
51
#else
52
static inline void mce_intel_handle_storm(int bank, bool on) { }
53
static inline void cmci_disable_bank(int bank) { }
54
static inline void intel_init_cmci(void) { }
55
static inline void intel_init_lmce(void) { }
56
static inline void intel_clear_lmce(void) { }
57
static inline bool intel_filter_mce(struct mce *m) { return false; }
58
static inline bool intel_mce_usable_address(struct mce *m) { return false; }
59
#endif
60
61
void mce_timer_kick(bool storm);
62
63
#ifdef CONFIG_X86_MCE_THRESHOLD
64
void cmci_storm_begin(unsigned int bank);
65
void cmci_storm_end(unsigned int bank);
66
void mce_track_storm(struct mce *mce);
67
void mce_inherit_storm(unsigned int bank);
68
bool mce_get_storm_mode(void);
69
void mce_set_storm_mode(bool storm);
70
u32 mce_get_apei_thr_limit(void);
71
#else
72
static inline void cmci_storm_begin(unsigned int bank) {}
73
static inline void cmci_storm_end(unsigned int bank) {}
74
static inline void mce_track_storm(struct mce *mce) {}
75
static inline void mce_inherit_storm(unsigned int bank) {}
76
static inline bool mce_get_storm_mode(void) { return false; }
77
static inline void mce_set_storm_mode(bool storm) {}
78
static inline u32 mce_get_apei_thr_limit(void) { return 0; }
79
#endif
80
81
/*
82
* history: Bitmask tracking errors occurrence. Each set bit
83
* represents an error seen.
84
*
85
* timestamp: Last time (in jiffies) that the bank was polled.
86
* in_storm_mode: Is this bank in storm mode?
87
* poll_only: Bank does not support CMCI, skip storm tracking.
88
*/
89
struct storm_bank {
90
u64 history;
91
u64 timestamp;
92
bool in_storm_mode;
93
bool poll_only;
94
};
95
96
#define NUM_HISTORY_BITS (sizeof(u64) * BITS_PER_BYTE)
97
98
/* How many errors within the history buffer mark the start of a storm. */
99
#define STORM_BEGIN_THRESHOLD 5
100
101
/*
102
* How many polls of machine check bank without an error before declaring
103
* the storm is over. Since it is tracked by the bitmasks in the history
104
* field of struct storm_bank the mask is 30 bits [0 ... 29].
105
*/
106
#define STORM_END_POLL_THRESHOLD 29
107
108
/*
109
* banks: per-cpu, per-bank details
110
* stormy_bank_count: count of MC banks in storm state
111
* poll_mode: CPU is in poll mode
112
*/
113
struct mca_storm_desc {
114
struct storm_bank banks[MAX_NR_BANKS];
115
u8 stormy_bank_count;
116
bool poll_mode;
117
};
118
119
DECLARE_PER_CPU(struct mca_storm_desc, storm_desc);
120
121
#ifdef CONFIG_ACPI_APEI
122
int apei_write_mce(struct mce *m);
123
ssize_t apei_read_mce(struct mce *m, u64 *record_id);
124
int apei_check_mce(void);
125
int apei_clear_mce(u64 record_id);
126
#else
127
static inline int apei_write_mce(struct mce *m)
128
{
129
return -EINVAL;
130
}
131
static inline ssize_t apei_read_mce(struct mce *m, u64 *record_id)
132
{
133
return 0;
134
}
135
static inline int apei_check_mce(void)
136
{
137
return 0;
138
}
139
static inline int apei_clear_mce(u64 record_id)
140
{
141
return -EINVAL;
142
}
143
#endif
144
145
/*
146
* We consider records to be equivalent if bank+status+addr+misc all match.
147
* This is only used when the system is going down because of a fatal error
148
* to avoid cluttering the console log with essentially repeated information.
149
* In normal processing all errors seen are logged.
150
*/
151
static inline bool mce_cmp(struct mce *m1, struct mce *m2)
152
{
153
return m1->bank != m2->bank ||
154
m1->status != m2->status ||
155
m1->addr != m2->addr ||
156
m1->misc != m2->misc;
157
}
158
159
extern struct device_attribute dev_attr_trigger;
160
161
#ifdef CONFIG_X86_MCELOG_LEGACY
162
void mce_work_trigger(void);
163
void mce_register_injector_chain(struct notifier_block *nb);
164
void mce_unregister_injector_chain(struct notifier_block *nb);
165
#else
166
static inline void mce_work_trigger(void) { }
167
static inline void mce_register_injector_chain(struct notifier_block *nb) { }
168
static inline void mce_unregister_injector_chain(struct notifier_block *nb) { }
169
#endif
170
171
struct mca_config {
172
__u64 lmce_disabled : 1,
173
disabled : 1,
174
ser : 1,
175
recovery : 1,
176
bios_cmci_threshold : 1,
177
/* Proper #MC exception handler is set */
178
initialized : 1,
179
__reserved : 58;
180
181
bool dont_log_ce;
182
bool cmci_disabled;
183
bool ignore_ce;
184
bool print_all;
185
186
int monarch_timeout;
187
int panic_timeout;
188
u32 rip_msr;
189
s8 bootlog;
190
};
191
192
extern struct mca_config mca_cfg;
193
DECLARE_PER_CPU_READ_MOSTLY(unsigned int, mce_num_banks);
194
195
struct mce_vendor_flags {
196
/*
197
* Indicates that overflow conditions are not fatal, when set.
198
*/
199
__u64 overflow_recov : 1,
200
201
/*
202
* (AMD) SUCCOR stands for S/W UnCorrectable error COntainment and
203
* Recovery. It indicates support for data poisoning in HW and deferred
204
* error interrupts.
205
*/
206
succor : 1,
207
208
/*
209
* (AMD) SMCA: This bit indicates support for Scalable MCA which expands
210
* the register space for each MCA bank and also increases number of
211
* banks. Also, to accommodate the new banks and registers, the MCA
212
* register space is moved to a new MSR range.
213
*/
214
smca : 1,
215
216
/* Zen IFU quirk */
217
zen_ifu_quirk : 1,
218
219
/* AMD-style error thresholding banks present. */
220
amd_threshold : 1,
221
222
/* Pentium, family 5-style MCA */
223
p5 : 1,
224
225
/* Centaur Winchip C6-style MCA */
226
winchip : 1,
227
228
/* SandyBridge IFU quirk */
229
snb_ifu_quirk : 1,
230
231
/* Skylake, Cascade Lake, Cooper Lake REP;MOVS* quirk */
232
skx_repmov_quirk : 1,
233
234
__reserved_0 : 55;
235
};
236
237
extern struct mce_vendor_flags mce_flags;
238
239
struct mce_bank {
240
/* subevents to enable */
241
u64 ctl;
242
243
/* initialise bank? */
244
__u64 init : 1,
245
246
/*
247
* (AMD) MCA_CONFIG[McaLsbInStatusSupported]: When set, this bit indicates
248
* the LSB field is found in MCA_STATUS and not in MCA_ADDR.
249
*/
250
lsb_in_status : 1,
251
252
__reserved_1 : 62;
253
};
254
255
DECLARE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
256
257
enum mca_msr {
258
MCA_CTL,
259
MCA_STATUS,
260
MCA_ADDR,
261
MCA_MISC,
262
};
263
264
/* Decide whether to add MCE record to MCE event pool or filter it out. */
265
extern bool filter_mce(struct mce *m);
266
void mce_prep_record_common(struct mce *m);
267
void mce_prep_record_per_cpu(unsigned int cpu, struct mce *m);
268
269
#ifdef CONFIG_X86_MCE_AMD
270
void mce_threshold_create_device(unsigned int cpu);
271
void mce_threshold_remove_device(unsigned int cpu);
272
void mce_amd_handle_storm(unsigned int bank, bool on);
273
extern bool amd_filter_mce(struct mce *m);
274
bool amd_mce_usable_address(struct mce *m);
275
void amd_clear_bank(struct mce *m);
276
277
/*
278
* If MCA_CONFIG[McaLsbInStatusSupported] is set, extract ErrAddr in bits
279
* [56:0] of MCA_STATUS, else in bits [55:0] of MCA_ADDR.
280
*/
281
static __always_inline void smca_extract_err_addr(struct mce *m)
282
{
283
u8 lsb;
284
285
if (!mce_flags.smca)
286
return;
287
288
if (this_cpu_ptr(mce_banks_array)[m->bank].lsb_in_status) {
289
lsb = (m->status >> 24) & 0x3f;
290
291
m->addr &= GENMASK_ULL(56, lsb);
292
293
return;
294
}
295
296
lsb = (m->addr >> 56) & 0x3f;
297
298
m->addr &= GENMASK_ULL(55, lsb);
299
}
300
301
void smca_bsp_init(void);
302
#else
303
static inline void mce_threshold_create_device(unsigned int cpu) { }
304
static inline void mce_threshold_remove_device(unsigned int cpu) { }
305
static inline void mce_amd_handle_storm(unsigned int bank, bool on) { }
306
static inline bool amd_filter_mce(struct mce *m) { return false; }
307
static inline bool amd_mce_usable_address(struct mce *m) { return false; }
308
static inline void amd_clear_bank(struct mce *m) { }
309
static inline void smca_extract_err_addr(struct mce *m) { }
310
static inline void smca_bsp_init(void) { }
311
#endif
312
313
#ifdef CONFIG_X86_ANCIENT_MCE
314
void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
315
void winchip_mcheck_init(struct cpuinfo_x86 *c);
316
noinstr void pentium_machine_check(struct pt_regs *regs);
317
noinstr void winchip_machine_check(struct pt_regs *regs);
318
static inline void enable_p5_mce(void) { mce_p5_enabled = 1; }
319
#else
320
static __always_inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
321
static __always_inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
322
static __always_inline void enable_p5_mce(void) {}
323
static __always_inline void pentium_machine_check(struct pt_regs *regs) {}
324
static __always_inline void winchip_machine_check(struct pt_regs *regs) {}
325
#endif
326
327
noinstr u64 mce_rdmsrq(u32 msr);
328
noinstr void mce_wrmsrq(u32 msr, u64 v);
329
330
static __always_inline u32 mca_msr_reg(int bank, enum mca_msr reg)
331
{
332
if (cpu_feature_enabled(X86_FEATURE_SMCA)) {
333
switch (reg) {
334
case MCA_CTL: return MSR_AMD64_SMCA_MCx_CTL(bank);
335
case MCA_ADDR: return MSR_AMD64_SMCA_MCx_ADDR(bank);
336
case MCA_MISC: return MSR_AMD64_SMCA_MCx_MISC(bank);
337
case MCA_STATUS: return MSR_AMD64_SMCA_MCx_STATUS(bank);
338
}
339
}
340
341
switch (reg) {
342
case MCA_CTL: return MSR_IA32_MCx_CTL(bank);
343
case MCA_ADDR: return MSR_IA32_MCx_ADDR(bank);
344
case MCA_MISC: return MSR_IA32_MCx_MISC(bank);
345
case MCA_STATUS: return MSR_IA32_MCx_STATUS(bank);
346
}
347
348
return 0;
349
}
350
351
extern void (*mc_poll_banks)(void);
352
#endif /* __X86_MCE_INTERNAL_H__ */
353
354