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