#include <linux/thread_info.h>
#include <linux/capability.h>
#include <linux/miscdevice.h>
#include <linux/ratelimit.h>
#include <linux/rcupdate.h>
#include <linux/kobject.h>
#include <linux/uaccess.h>
#include <linux/kdebug.h>
#include <linux/kernel.h>
#include <linux/percpu.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/syscore_ops.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/sched.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/poll.h>
#include <linux/nmi.h>
#include <linux/cpu.h>
#include <linux/ras.h>
#include <linux/smp.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/debugfs.h>
#include <linux/irq_work.h>
#include <linux/export.h>
#include <linux/set_memory.h>
#include <linux/sync_core.h>
#include <linux/task_work.h>
#include <linux/hardirq.h>
#include <linux/kexec.h>
#include <asm/fred.h>
#include <asm/cpu_device_id.h>
#include <asm/processor.h>
#include <asm/traps.h>
#include <asm/tlbflush.h>
#include <asm/mce.h>
#include <asm/msr.h>
#include <asm/reboot.h>
#include <asm/tdx.h>
#include "internal.h"
static DEFINE_MUTEX(mce_sysfs_mutex);
#define CREATE_TRACE_POINTS
#include <trace/events/mce.h>
#define SPINUNIT …
DEFINE_PER_CPU(unsigned, mce_exception_count);
DEFINE_PER_CPU_READ_MOSTLY(unsigned int, mce_num_banks);
DEFINE_PER_CPU_READ_MOSTLY(struct mce_bank[MAX_NR_BANKS], mce_banks_array);
#define ATTR_LEN …
struct mce_bank_dev { … };
static struct mce_bank_dev mce_bank_devs[MAX_NR_BANKS];
struct mce_vendor_flags mce_flags __read_mostly;
struct mca_config mca_cfg __read_mostly = …;
static DEFINE_PER_CPU(struct mce, mces_seen);
static unsigned long mce_need_notify;
DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = …;
mce_banks_t mce_banks_ce_disabled;
static struct work_struct mce_work;
static struct irq_work mce_irq_work;
BLOCKING_NOTIFIER_HEAD(…) …;
void mce_prep_record_common(struct mce *m)
{ … }
void mce_prep_record_per_cpu(unsigned int cpu, struct mce *m)
{ … }
void mce_prep_record(struct mce *m)
{ … }
DEFINE_PER_CPU(struct mce, injectm);
EXPORT_PER_CPU_SYMBOL_GPL(…);
void mce_log(struct mce *m)
{ … }
EXPORT_SYMBOL_GPL(…);
void mce_register_decode_chain(struct notifier_block *nb)
{ … }
EXPORT_SYMBOL_GPL(…);
void mce_unregister_decode_chain(struct notifier_block *nb)
{ … }
EXPORT_SYMBOL_GPL(…);
static void __print_mce(struct mce *m)
{ … }
static void print_mce(struct mce *m)
{ … }
#define PANIC_TIMEOUT …
static atomic_t mce_panicked;
static int fake_panic;
static atomic_t mce_fake_panicked;
static void wait_for_panic(void)
{ … }
static const char *mce_dump_aux_info(struct mce *m)
{ … }
static noinstr void mce_panic(const char *msg, struct mce *final, char *exp)
{ … }
static int msr_to_offset(u32 msr)
{ … }
void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr)
{ … }
noinstr u64 mce_rdmsrl(u32 msr)
{ … }
static noinstr void mce_wrmsrl(u32 msr, u64 v)
{ … }
static noinstr void mce_gather_info(struct mce *m, struct pt_regs *regs)
{ … }
int mce_available(struct cpuinfo_x86 *c)
{ … }
static void mce_schedule_work(void)
{ … }
static void mce_irq_work_cb(struct irq_work *entry)
{ … }
bool mce_usable_address(struct mce *m)
{ … }
EXPORT_SYMBOL_GPL(…);
bool mce_is_memory_error(struct mce *m)
{ … }
EXPORT_SYMBOL_GPL(…);
static bool whole_page(struct mce *m)
{ … }
bool mce_is_correctable(struct mce *m)
{ … }
EXPORT_SYMBOL_GPL(…);
static int mce_early_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{ … }
static struct notifier_block early_nb = …;
static int uc_decode_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{ … }
static struct notifier_block mce_uc_nb = …;
static int mce_default_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{ … }
static struct notifier_block mce_default_nb = …;
static noinstr void mce_read_aux(struct mce *m, int i)
{ … }
DEFINE_PER_CPU(unsigned, mce_poll_count);
void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
{ … }
EXPORT_SYMBOL_GPL(…);
static __always_inline void
quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs)
{ … }
static noinstr bool quirk_skylake_repmov(void)
{ … }
static __always_inline void quirk_zen_ifu(int bank, struct mce *m, struct pt_regs *regs)
{ … }
static __always_inline int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
struct pt_regs *regs)
{ … }
static atomic_t mce_executing;
static atomic_t mce_callin;
static cpumask_t mce_missing_cpus = …;
static noinstr int mce_timed_out(u64 *t, const char *msg)
{ … }
static void mce_reign(void)
{ … }
static atomic_t global_nwo;
static noinstr int mce_start(int *no_way_out)
{ … }
static noinstr int mce_end(int order)
{ … }
static __always_inline void mce_clear_state(unsigned long *toclear)
{ … }
static noinstr bool mce_check_crashing_cpu(void)
{ … }
static __always_inline int
__mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final,
unsigned long *toclear, unsigned long *valid_banks, int no_way_out,
int *worst)
{ … }
static void kill_me_now(struct callback_head *ch)
{ … }
static void kill_me_maybe(struct callback_head *cb)
{ … }
static void kill_me_never(struct callback_head *cb)
{ … }
static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *))
{ … }
static noinstr void unexpected_machine_check(struct pt_regs *regs)
{ … }
noinstr void do_machine_check(struct pt_regs *regs)
{ … }
EXPORT_SYMBOL_GPL(…);
#ifndef CONFIG_MEMORY_FAILURE
int memory_failure(unsigned long pfn, int flags)
{
BUG_ON(flags & MF_ACTION_REQUIRED);
pr_err("Uncorrected memory error in page 0x%lx ignored\n"
"Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n",
pfn);
return 0;
}
#endif
static unsigned long check_interval = …;
static DEFINE_PER_CPU(unsigned long, mce_next_interval);
static DEFINE_PER_CPU(struct timer_list, mce_timer);
static void __start_timer(struct timer_list *t, unsigned long interval)
{ … }
static void mc_poll_banks_default(void)
{ … }
void (*mc_poll_banks)(void) = …;
static void mce_timer_fn(struct timer_list *t)
{ … }
void mce_timer_kick(bool storm)
{ … }
static void mce_timer_delete_all(void)
{ … }
int mce_notify_irq(void)
{ … }
EXPORT_SYMBOL_GPL(…);
static void __mcheck_cpu_mce_banks_init(void)
{ … }
static void __mcheck_cpu_cap_init(void)
{ … }
static void __mcheck_cpu_init_generic(void)
{ … }
static void __mcheck_cpu_init_clear_banks(void)
{ … }
static void __mcheck_cpu_check_banks(void)
{ … }
static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
{ … }
static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c)
{ … }
static void __mcheck_cpu_init_early(struct cpuinfo_x86 *c)
{ … }
static void mce_centaur_feature_init(struct cpuinfo_x86 *c)
{ … }
static void mce_zhaoxin_feature_init(struct cpuinfo_x86 *c)
{ … }
static void mce_zhaoxin_feature_clear(struct cpuinfo_x86 *c)
{ … }
static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
{ … }
static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c)
{ … }
static void mce_start_timer(struct timer_list *t)
{ … }
static void __mcheck_cpu_setup_timer(void)
{ … }
static void __mcheck_cpu_init_timer(void)
{ … }
bool filter_mce(struct mce *m)
{ … }
static __always_inline void exc_machine_check_kernel(struct pt_regs *regs)
{ … }
static __always_inline void exc_machine_check_user(struct pt_regs *regs)
{ … }
#ifdef CONFIG_X86_64
DEFINE_IDTENTRY_MCE(exc_machine_check)
{ … }
DEFINE_IDTENTRY_MCE_USER(exc_machine_check)
{ … }
#ifdef CONFIG_X86_FRED
DEFINE_FREDENTRY_MCE(exc_machine_check)
{ … }
#endif
#else
DEFINE_IDTENTRY_RAW(exc_machine_check)
{
unsigned long dr7;
dr7 = local_db_save();
if (user_mode(regs))
exc_machine_check_user(regs);
else
exc_machine_check_kernel(regs);
local_db_restore(dr7);
}
#endif
void mcheck_cpu_init(struct cpuinfo_x86 *c)
{ … }
void mcheck_cpu_clear(struct cpuinfo_x86 *c)
{ … }
static void __mce_disable_bank(void *arg)
{ … }
void mce_disable_bank(int bank)
{ … }
static int __init mcheck_enable(char *str)
{ … }
__setup(…);
int __init mcheck_init(void)
{ … }
static void mce_disable_error_reporting(void)
{ … }
static void vendor_disable_error_reporting(void)
{ … }
static int mce_syscore_suspend(void)
{ … }
static void mce_syscore_shutdown(void)
{ … }
static void mce_syscore_resume(void)
{ … }
static struct syscore_ops mce_syscore_ops = …;
static void mce_cpu_restart(void *data)
{ … }
static void mce_restart(void)
{ … }
static void mce_disable_cmci(void *data)
{ … }
static void mce_enable_ce(void *all)
{ … }
static const struct bus_type mce_subsys = …;
DEFINE_PER_CPU(struct device *, mce_device);
static inline struct mce_bank_dev *attr_to_bank(struct device_attribute *attr)
{ … }
static ssize_t show_bank(struct device *s, struct device_attribute *attr,
char *buf)
{ … }
static ssize_t set_bank(struct device *s, struct device_attribute *attr,
const char *buf, size_t size)
{ … }
static ssize_t set_ignore_ce(struct device *s,
struct device_attribute *attr,
const char *buf, size_t size)
{ … }
static ssize_t set_cmci_disabled(struct device *s,
struct device_attribute *attr,
const char *buf, size_t size)
{ … }
static ssize_t store_int_with_restart(struct device *s,
struct device_attribute *attr,
const char *buf, size_t size)
{ … }
static DEVICE_INT_ATTR(monarch_timeout, 0644, mca_cfg.monarch_timeout);
static DEVICE_BOOL_ATTR(dont_log_ce, 0644, mca_cfg.dont_log_ce);
static DEVICE_BOOL_ATTR(print_all, 0644, mca_cfg.print_all);
static struct dev_ext_attribute dev_attr_check_interval = …;
static struct dev_ext_attribute dev_attr_ignore_ce = …;
static struct dev_ext_attribute dev_attr_cmci_disabled = …;
static struct device_attribute *mce_device_attrs[] = …;
static cpumask_var_t mce_device_initialized;
static void mce_device_release(struct device *dev)
{ … }
static int mce_device_create(unsigned int cpu)
{ … }
static void mce_device_remove(unsigned int cpu)
{ … }
static void mce_disable_cpu(void)
{ … }
static void mce_reenable_cpu(void)
{ … }
static int mce_cpu_dead(unsigned int cpu)
{ … }
static int mce_cpu_online(unsigned int cpu)
{ … }
static int mce_cpu_pre_down(unsigned int cpu)
{ … }
static __init void mce_init_banks(void)
{ … }
static __init int mcheck_init_device(void)
{ … }
device_initcall_sync(mcheck_init_device);
static int __init mcheck_disable(char *str)
{ … }
__setup(…);
#ifdef CONFIG_DEBUG_FS
struct dentry *mce_get_debugfs_dir(void)
{ … }
static void mce_reset(void)
{ … }
static int fake_panic_get(void *data, u64 *val)
{ … }
static int fake_panic_set(void *data, u64 val)
{ … }
DEFINE_DEBUGFS_ATTRIBUTE(…);
static void __init mcheck_debugfs_init(void)
{ … }
#else
static void __init mcheck_debugfs_init(void) { }
#endif
static int __init mcheck_late_init(void)
{ … }
late_initcall(mcheck_late_init);