From 666192e18fafde5259360a7b8e6b030386d7edcb Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 28 Aug 2026 08:30:00 -0700 Subject: [PATCH] EDAC/intel-bff: Reset bitfix filter when it overflows Get notifications for all errors logged in machine check banks. Skip any that do not indicate a bitfix filter overflow. Machine check banks are scoped to a hardware unit, so the reset has to be issued from a CPU within that unit. Use the CPU that reported the error. Co-developed-by: Qiuxu Zhuo Signed-off-by: Qiuxu Zhuo Signed-off-by: Tony Luck Link: https://patch.msgid.link/20260828153002.10290-6-tony.luck@intel.com --- drivers/edac/intel-bff.c | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/edac/intel-bff.c b/drivers/edac/intel-bff.c index f70c5e697dae..c46d5255f34b 100644 --- a/drivers/edac/intel-bff.c +++ b/drivers/edac/intel-bff.c @@ -17,11 +17,14 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include #include #include #include #include #include +#include #include #include @@ -32,6 +35,11 @@ #include #include +/* Intel bitfix filter control register defines */ +#define MSR_MC0_BFF_CTL 0x000006c0 +#define MSR_MCx_BFF_CTL(x) (MSR_MC0_BFF_CTL + (x)) +#define MCI_BFF_RESET BIT_ULL(0) + /* Machine check bank hardware unit types */ enum bff_bank_type { BFF_BANK_NONE = 0, @@ -64,6 +72,38 @@ MODULE_DEVICE_TABLE(x86cpu, bff_cpu_ids); static const enum bff_bank_type *bff_bank_types; +static void bff_reset_and_report(struct mce *mce) +{ + /* Reset bitfix filter using the CPU that logged the yellow status */ + if (wrmsrq_on_cpu(mce->extcpu, MSR_MCx_BFF_CTL(mce->bank), MCI_BFF_RESET)) + pr_warn("Failed to reset bitfix filter for CPU %d Bank %d\n", + mce->extcpu, mce->bank); +} + +static int bff_mce_notify(struct notifier_block *nb, unsigned long val, void *data) +{ + struct mce *mce = data; + + /* TES is undefined for uncorrected errors. */ + if (mce->status & MCI_STATUS_UC) + return NOTIFY_DONE; + + if (MCI_STATUS_TES(mce->status) != MCI_STATUS_TES_YELLOW) + return NOTIFY_DONE; + + if (mce->bank >= MAX_NR_BANKS || bff_bank_types[mce->bank] == BFF_BANK_NONE) + return NOTIFY_DONE; + + bff_reset_and_report(mce); + + return NOTIFY_DONE; +} + +static struct notifier_block bff_notifier = { + .notifier_call = bff_mce_notify, + .priority = MCE_PRIO_EDAC, +}; + static int __init bff_init(void) { const struct x86_cpu_id *m; @@ -89,10 +129,18 @@ static int __init bff_init(void) bff_bank_types = (const enum bff_bank_type *)m->driver_data; + mce_register_decode_chain(&bff_notifier); + return 0; } +static void __exit bff_exit(void) +{ + mce_unregister_decode_chain(&bff_notifier); +} + module_init(bff_init); +module_exit(bff_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tony Luck");