18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __X86_MCE_INTERNAL_H__ 38c2ecf20Sopenharmony_ci#define __X86_MCE_INTERNAL_H__ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#undef pr_fmt 68c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "mce: " fmt 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/device.h> 98c2ecf20Sopenharmony_ci#include <asm/mce.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* Pointer to the installed machine check handler for this CPU setup. */ 128c2ecf20Sopenharmony_ciextern void (*machine_check_vector)(struct pt_regs *); 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cienum severity_level { 158c2ecf20Sopenharmony_ci MCE_NO_SEVERITY, 168c2ecf20Sopenharmony_ci MCE_DEFERRED_SEVERITY, 178c2ecf20Sopenharmony_ci MCE_UCNA_SEVERITY = MCE_DEFERRED_SEVERITY, 188c2ecf20Sopenharmony_ci MCE_KEEP_SEVERITY, 198c2ecf20Sopenharmony_ci MCE_SOME_SEVERITY, 208c2ecf20Sopenharmony_ci MCE_AO_SEVERITY, 218c2ecf20Sopenharmony_ci MCE_UC_SEVERITY, 228c2ecf20Sopenharmony_ci MCE_AR_SEVERITY, 238c2ecf20Sopenharmony_ci MCE_PANIC_SEVERITY, 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciextern struct blocking_notifier_head x86_mce_decoder_chain; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define INITIAL_CHECK_INTERVAL 5 * 60 /* 5 minutes */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct mce_evt_llist { 318c2ecf20Sopenharmony_ci struct llist_node llnode; 328c2ecf20Sopenharmony_ci struct mce mce; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_civoid mce_gen_pool_process(struct work_struct *__unused); 368c2ecf20Sopenharmony_cibool mce_gen_pool_empty(void); 378c2ecf20Sopenharmony_ciint mce_gen_pool_add(struct mce *mce); 388c2ecf20Sopenharmony_ciint mce_gen_pool_init(void); 398c2ecf20Sopenharmony_cistruct llist_node *mce_gen_pool_prepare_records(void); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ciextern int (*mce_severity)(struct mce *a, struct pt_regs *regs, 428c2ecf20Sopenharmony_ci int tolerant, char **msg, bool is_excp); 438c2ecf20Sopenharmony_cistruct dentry *mce_get_debugfs_dir(void); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ciextern mce_banks_t mce_banks_ce_disabled; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_MCE_INTEL 488c2ecf20Sopenharmony_ciunsigned long cmci_intel_adjust_timer(unsigned long interval); 498c2ecf20Sopenharmony_cibool mce_intel_cmci_poll(void); 508c2ecf20Sopenharmony_civoid mce_intel_hcpu_update(unsigned long cpu); 518c2ecf20Sopenharmony_civoid cmci_disable_bank(int bank); 528c2ecf20Sopenharmony_civoid intel_init_cmci(void); 538c2ecf20Sopenharmony_civoid intel_init_lmce(void); 548c2ecf20Sopenharmony_civoid intel_clear_lmce(void); 558c2ecf20Sopenharmony_cibool intel_filter_mce(struct mce *m); 568c2ecf20Sopenharmony_ci#else 578c2ecf20Sopenharmony_ci# define cmci_intel_adjust_timer mce_adjust_timer_default 588c2ecf20Sopenharmony_cistatic inline bool mce_intel_cmci_poll(void) { return false; } 598c2ecf20Sopenharmony_cistatic inline void mce_intel_hcpu_update(unsigned long cpu) { } 608c2ecf20Sopenharmony_cistatic inline void cmci_disable_bank(int bank) { } 618c2ecf20Sopenharmony_cistatic inline void intel_init_cmci(void) { } 628c2ecf20Sopenharmony_cistatic inline void intel_init_lmce(void) { } 638c2ecf20Sopenharmony_cistatic inline void intel_clear_lmce(void) { } 648c2ecf20Sopenharmony_cistatic inline bool intel_filter_mce(struct mce *m) { return false; }; 658c2ecf20Sopenharmony_ci#endif 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_civoid mce_timer_kick(unsigned long interval); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_APEI 708c2ecf20Sopenharmony_ciint apei_write_mce(struct mce *m); 718c2ecf20Sopenharmony_cissize_t apei_read_mce(struct mce *m, u64 *record_id); 728c2ecf20Sopenharmony_ciint apei_check_mce(void); 738c2ecf20Sopenharmony_ciint apei_clear_mce(u64 record_id); 748c2ecf20Sopenharmony_ci#else 758c2ecf20Sopenharmony_cistatic inline int apei_write_mce(struct mce *m) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci return -EINVAL; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_cistatic inline ssize_t apei_read_mce(struct mce *m, u64 *record_id) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci return 0; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_cistatic inline int apei_check_mce(void) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci return 0; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_cistatic inline int apei_clear_mce(u64 record_id) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci return -EINVAL; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci#endif 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* 948c2ecf20Sopenharmony_ci * We consider records to be equivalent if bank+status+addr+misc all match. 958c2ecf20Sopenharmony_ci * This is only used when the system is going down because of a fatal error 968c2ecf20Sopenharmony_ci * to avoid cluttering the console log with essentially repeated information. 978c2ecf20Sopenharmony_ci * In normal processing all errors seen are logged. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_cistatic inline bool mce_cmp(struct mce *m1, struct mce *m2) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci return m1->bank != m2->bank || 1028c2ecf20Sopenharmony_ci m1->status != m2->status || 1038c2ecf20Sopenharmony_ci m1->addr != m2->addr || 1048c2ecf20Sopenharmony_ci m1->misc != m2->misc; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ciextern struct device_attribute dev_attr_trigger; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_MCELOG_LEGACY 1108c2ecf20Sopenharmony_civoid mce_work_trigger(void); 1118c2ecf20Sopenharmony_civoid mce_register_injector_chain(struct notifier_block *nb); 1128c2ecf20Sopenharmony_civoid mce_unregister_injector_chain(struct notifier_block *nb); 1138c2ecf20Sopenharmony_ci#else 1148c2ecf20Sopenharmony_cistatic inline void mce_work_trigger(void) { } 1158c2ecf20Sopenharmony_cistatic inline void mce_register_injector_chain(struct notifier_block *nb) { } 1168c2ecf20Sopenharmony_cistatic inline void mce_unregister_injector_chain(struct notifier_block *nb) { } 1178c2ecf20Sopenharmony_ci#endif 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistruct mca_config { 1208c2ecf20Sopenharmony_ci bool dont_log_ce; 1218c2ecf20Sopenharmony_ci bool cmci_disabled; 1228c2ecf20Sopenharmony_ci bool ignore_ce; 1238c2ecf20Sopenharmony_ci bool print_all; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci __u64 lmce_disabled : 1, 1268c2ecf20Sopenharmony_ci disabled : 1, 1278c2ecf20Sopenharmony_ci ser : 1, 1288c2ecf20Sopenharmony_ci recovery : 1, 1298c2ecf20Sopenharmony_ci bios_cmci_threshold : 1, 1308c2ecf20Sopenharmony_ci __reserved : 59; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci s8 bootlog; 1338c2ecf20Sopenharmony_ci int tolerant; 1348c2ecf20Sopenharmony_ci int monarch_timeout; 1358c2ecf20Sopenharmony_ci int panic_timeout; 1368c2ecf20Sopenharmony_ci u32 rip_msr; 1378c2ecf20Sopenharmony_ci}; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ciextern struct mca_config mca_cfg; 1408c2ecf20Sopenharmony_ciDECLARE_PER_CPU_READ_MOSTLY(unsigned int, mce_num_banks); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistruct mce_vendor_flags { 1438c2ecf20Sopenharmony_ci /* 1448c2ecf20Sopenharmony_ci * Indicates that overflow conditions are not fatal, when set. 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_ci __u64 overflow_recov : 1, 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* 1498c2ecf20Sopenharmony_ci * (AMD) SUCCOR stands for S/W UnCorrectable error COntainment and 1508c2ecf20Sopenharmony_ci * Recovery. It indicates support for data poisoning in HW and deferred 1518c2ecf20Sopenharmony_ci * error interrupts. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ci succor : 1, 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* 1568c2ecf20Sopenharmony_ci * (AMD) SMCA: This bit indicates support for Scalable MCA which expands 1578c2ecf20Sopenharmony_ci * the register space for each MCA bank and also increases number of 1588c2ecf20Sopenharmony_ci * banks. Also, to accommodate the new banks and registers, the MCA 1598c2ecf20Sopenharmony_ci * register space is moved to a new MSR range. 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_ci smca : 1, 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* AMD-style error thresholding banks present. */ 1648c2ecf20Sopenharmony_ci amd_threshold : 1, 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci __reserved_0 : 60; 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ciextern struct mce_vendor_flags mce_flags; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cienum mca_msr { 1728c2ecf20Sopenharmony_ci MCA_CTL, 1738c2ecf20Sopenharmony_ci MCA_STATUS, 1748c2ecf20Sopenharmony_ci MCA_ADDR, 1758c2ecf20Sopenharmony_ci MCA_MISC, 1768c2ecf20Sopenharmony_ci}; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciu32 mca_msr_reg(int bank, enum mca_msr reg); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/* Decide whether to add MCE record to MCE event pool or filter it out. */ 1818c2ecf20Sopenharmony_ciextern bool filter_mce(struct mce *m); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_MCE_AMD 1848c2ecf20Sopenharmony_ciextern bool amd_filter_mce(struct mce *m); 1858c2ecf20Sopenharmony_ci#else 1868c2ecf20Sopenharmony_cistatic inline bool amd_filter_mce(struct mce *m) { return false; }; 1878c2ecf20Sopenharmony_ci#endif 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup, 1908c2ecf20Sopenharmony_ci struct pt_regs *regs, int trapnr, 1918c2ecf20Sopenharmony_ci unsigned long error_code, 1928c2ecf20Sopenharmony_ci unsigned long fault_addr); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci__visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup, 1958c2ecf20Sopenharmony_ci struct pt_regs *regs, int trapnr, 1968c2ecf20Sopenharmony_ci unsigned long error_code, 1978c2ecf20Sopenharmony_ci unsigned long fault_addr); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#endif /* __X86_MCE_INTERNAL_H__ */ 200