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