* [PATCH v2 1/7] cacheinfo: Export get_cpu_cacheinfo_id() for loadable modules
2026-08-28 15:29 [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters Tony Luck
@ 2026-08-28 15:29 ` Tony Luck
2026-08-28 15:29 ` [PATCH v2 2/7] x86/mce: Add enumeration for Intel bitfix filter reset Tony Luck
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tony Luck @ 2026-08-28 15:29 UTC (permalink / raw)
To: Tony Luck
Cc: Borislav Petkov, Qiuxu Zhuo, Ilpo Järvinen, Breno Leitao,
linux-edac, linux-kernel, patches
From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
get_cpu_cacheinfo_id() is a static inline that requires get_cpu_cacheinfo(),
which is not exported. Modules that need to identify which cache instance
a CPU belongs to therefore cannot use it.
Move it out of line and export it.
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
include/linux/cacheinfo.h | 12 +-----------
drivers/base/cacheinfo.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
index fc879ac4cc4f..56fa646df0d1 100644
--- a/include/linux/cacheinfo.h
+++ b/include/linux/cacheinfo.h
@@ -82,6 +82,7 @@ struct cpu_cacheinfo {
};
struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu);
+int get_cpu_cacheinfo_id(int cpu, int level);
int early_cache_level(unsigned int cpu);
int init_cache_level(unsigned int cpu);
int init_of_cache_level(unsigned int cpu);
@@ -137,17 +138,6 @@ static inline struct cacheinfo *get_cpu_cacheinfo_level(int cpu, int level)
return NULL;
}
-/*
- * Get the id of the cache associated with @cpu at level @level.
- * cpuhp lock must be held.
- */
-static inline int get_cpu_cacheinfo_id(int cpu, int level)
-{
- struct cacheinfo *ci = get_cpu_cacheinfo_level(cpu, level);
-
- return ci ? ci->id : -1;
-}
-
#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
#define use_arch_cache_info() (true)
#else
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 70701d3bc81c..28d193bf6064 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -38,6 +38,23 @@ struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu)
return ci_cacheinfo(cpu);
}
+/**
+ * get_cpu_cacheinfo_id - Return the cache ID for a CPU and cache level
+ * @cpu: CPU number
+ * @level: Cache level
+ *
+ * The caller must hold the cpuhp lock.
+ *
+ * Return: Cache ID on success, or -1 if no matching cache exists.
+ */
+int get_cpu_cacheinfo_id(int cpu, int level)
+{
+ struct cacheinfo *ci = get_cpu_cacheinfo_level(cpu, level);
+
+ return ci ? ci->id : -1;
+}
+EXPORT_SYMBOL_GPL(get_cpu_cacheinfo_id);
+
static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf,
struct cacheinfo *sib_leaf)
{
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 2/7] x86/mce: Add enumeration for Intel bitfix filter reset
2026-08-28 15:29 [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters Tony Luck
2026-08-28 15:29 ` [PATCH v2 1/7] cacheinfo: Export get_cpu_cacheinfo_id() for loadable modules Tony Luck
@ 2026-08-28 15:29 ` Tony Luck
2026-08-28 15:29 ` [PATCH v2 3/7] EDAC/intel-bff: Add stub Intel bitfix filter driver Tony Luck
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tony Luck @ 2026-08-28 15:29 UTC (permalink / raw)
To: Tony Luck
Cc: Borislav Petkov, Qiuxu Zhuo, Ilpo Järvinen, Breno Leitao,
linux-edac, linux-kernel, patches
IA32_CORE_CAPABILITIES enumerates the bitfix filter reset feature.
Intel specifies two values for the threshold status field in the
IA32_MCi_STATUS MSR:
1 = GREEN (threshold has not been reached)
2 = YELLOW (threshold exceeded, try bitfix filter reset)
Co-developed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
arch/x86/include/asm/mce.h | 5 +++++
arch/x86/include/asm/msr-index.h | 2 ++
2 files changed, 7 insertions(+)
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index e575b702063d..9995176d6879 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -13,6 +13,7 @@
#define MCG_CTL_P BIT_ULL(8) /* MCG_CTL register available */
#define MCG_EXT_P BIT_ULL(9) /* Extended registers available */
#define MCG_CMCI_P BIT_ULL(10) /* CMCI supported */
+#define MCG_TES_P BIT_ULL(11) /* Threshold-based error status supported */
#define MCG_SEAM_NR BIT_ULL(12) /* MCG_STATUS_SEAM_NR supported */
#define MCG_EXT_CNT_MASK 0xff0000 /* Number of Extended registers */
#define MCG_EXT_CNT_SHIFT 16
@@ -41,6 +42,10 @@
#define MCI_STATUS_PCC BIT_ULL(57) /* processor context corrupt */
#define MCI_STATUS_S BIT_ULL(56) /* Signaled machine check */
#define MCI_STATUS_AR BIT_ULL(55) /* Action required */
+#define MCI_STATUS_TES_MASK GENMASK_ULL(54, 53)
+#define MCI_STATUS_TES(s) FIELD_GET(MCI_STATUS_TES_MASK, s)
+#define MCI_STATUS_TES_GREEN 1 /* Threshold-based errors below threshold */
+#define MCI_STATUS_TES_YELLOW 2 /* Threshold-based errors above threshold */
#define MCI_STATUS_CEC_SHIFT 38 /* Corrected Error Count */
#define MCI_STATUS_CEC_MASK GENMASK_ULL(52,38)
#define MCI_STATUS_CEC(c) (((c) & MCI_STATUS_CEC_MASK) >> MCI_STATUS_CEC_SHIFT)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 18c4be75e927..cea60d3ccb2b 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -114,6 +114,8 @@
#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS BIT(MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT)
#define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT 5
#define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT)
+#define MSR_IA32_CORE_CAPS_BFF_RESET_BIT 9
+#define MSR_IA32_CORE_CAPS_BFF_RESET BIT(MSR_IA32_CORE_CAPS_BFF_RESET_BIT)
#define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
#define NHM_C3_AUTO_DEMOTE (1UL << 25)
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 3/7] EDAC/intel-bff: Add stub Intel bitfix filter driver
2026-08-28 15:29 [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters Tony Luck
2026-08-28 15:29 ` [PATCH v2 1/7] cacheinfo: Export get_cpu_cacheinfo_id() for loadable modules Tony Luck
2026-08-28 15:29 ` [PATCH v2 2/7] x86/mce: Add enumeration for Intel bitfix filter reset Tony Luck
@ 2026-08-28 15:29 ` Tony Luck
2026-08-28 15:29 ` [PATCH v2 4/7] EDAC/intel-bff: Add Diamond Rapids support Tony Luck
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tony Luck @ 2026-08-28 15:29 UTC (permalink / raw)
To: Tony Luck
Cc: Borislav Petkov, Qiuxu Zhuo, Ilpo Järvinen, Breno Leitao,
linux-edac, linux-kernel, patches
Check if the platform supports threshold based cache error reporting and
the bitfix filter reset feature.
Co-developed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
drivers/edac/intel-bff.c | 54 ++++++++++++++++++++++++++++++++++++++++
MAINTAINERS | 6 +++++
drivers/edac/Kconfig | 13 ++++++++++
drivers/edac/Makefile | 2 ++
4 files changed, 75 insertions(+)
create mode 100644 drivers/edac/intel-bff.c
diff --git a/drivers/edac/intel-bff.c b/drivers/edac/intel-bff.c
new file mode 100644
index 000000000000..905cbe58bc53
--- /dev/null
+++ b/drivers/edac/intel-bff.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2026 Intel Corporation. */
+
+/*
+ * Intel driver to reset bitfix filters when they overflow.
+ *
+ * Each bitfix filter has limited slots to track corrected errors.
+ * These slots can be filled by transient corrected errors (e.g.,
+ * bit flips from particle strikes) that don't represent permanent
+ * hardware defects.
+ *
+ * When the filter overflows (yellow status), reset it to reclaim
+ * slots occupied by transient corrected errors. If the overflow
+ * repeats frequently after reset, it indicates persistent hardware
+ * defects that need attention: the system should be scheduled for
+ * servicing.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpufeature.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/cpufeatures.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+
+static int __init bff_init(void)
+{
+ u64 core_caps, mcg_cap;
+
+ if (!cpu_feature_enabled(X86_FEATURE_MCA))
+ return -ENODEV;
+ rdmsrq(MSR_IA32_MCG_CAP, mcg_cap);
+ if (!(mcg_cap & MCG_TES_P))
+ return -ENODEV;
+
+ if (!cpu_feature_enabled(X86_FEATURE_CORE_CAPABILITIES))
+ return -ENODEV;
+ rdmsrq(MSR_IA32_CORE_CAPS, core_caps);
+ if (!(core_caps & MSR_IA32_CORE_CAPS_BFF_RESET))
+ return -ENODEV;
+
+ return 0;
+}
+
+module_init(bff_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tony Luck");
+MODULE_DESCRIPTION("Intel bitfix filter reset driver");
diff --git a/MAINTAINERS b/MAINTAINERS
index 8014b9f8253e..edc50f7cb025 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9405,6 +9405,12 @@ L: linux-edac@vger.kernel.org
S: Maintained
F: drivers/edac/igen6_edac.c
+EDAC-INTEL-BFF-RESET
+M: Tony Luck <tony.luck@intel.com>
+L: linux-edac@vger.kernel.org
+S: Maintained
+F: drivers/edac/intel-bff.c
+
EDAC-MPC85XX
M: Johannes Thumshirn <morbidrsa@gmail.com>
L: linux-edac@vger.kernel.org
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index a44b85c440ca..f7964cd9545e 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -280,6 +280,19 @@ config EDAC_IMH
first used on the Diamond Rapids servers but may appear on
others in the future.
+config EDAC_INTEL_BFF_RESET
+ tristate "Intel bitfix filter reset driver"
+ depends on X86_64 && X86_MCE_INTEL
+ help
+ Support for Intel systems that implement bitfix filters to
+ suppress repeated logging and signaling of the same corrected
+ error. Those filters can become clogged with transient errors
+ over time. Clearing the filter may make space for additional
+ hard errors.
+
+ To compile this driver as a module, choose M here: the module
+ will be called intel_bff.
+
config EDAC_PND2
tristate "Intel Pondicherry2"
depends on PCI && X86_64 && X86_MCE_INTEL
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index a37534300ab9..c2bae03f247b 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -66,6 +66,8 @@ obj-$(CONFIG_EDAC_I10NM) += i10nm_edac.o skx_edac_common.o
imh_edac-y := imh_base.o
obj-$(CONFIG_EDAC_IMH) += imh_edac.o skx_edac_common.o
+obj-$(CONFIG_EDAC_INTEL_BFF_RESET) += intel-bff.o
+
obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o
obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 4/7] EDAC/intel-bff: Add Diamond Rapids support
2026-08-28 15:29 [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters Tony Luck
` (2 preceding siblings ...)
2026-08-28 15:29 ` [PATCH v2 3/7] EDAC/intel-bff: Add stub Intel bitfix filter driver Tony Luck
@ 2026-08-28 15:29 ` Tony Luck
2026-08-28 15:30 ` [PATCH v2 5/7] EDAC/intel-bff: Reset bitfix filter when it overflows Tony Luck
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Tony Luck @ 2026-08-28 15:29 UTC (permalink / raw)
To: Tony Luck
Cc: Borislav Petkov, Qiuxu Zhuo, Ilpo Järvinen, Breno Leitao,
linux-edac, linux-kernel, patches
There are potentially bitfix filters associated with each machine check
bank. Only some banks may implement them.
Machine check banks have varying scope. E.g. there is a separate L2
cache for each module, each instance has its own bitfix filter.
Add information that will be used to map a <cpu,bank> pair to a unique
instance number for a bitfix filter.
Co-developed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
drivers/edac/intel-bff.c | 45 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/drivers/edac/intel-bff.c b/drivers/edac/intel-bff.c
index 905cbe58bc53..f70c5e697dae 100644
--- a/drivers/edac/intel-bff.c
+++ b/drivers/edac/intel-bff.c
@@ -18,18 +18,55 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/cpufeature.h>
+#include <linux/device-id/x86_cpu.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/printk.h>
#include <linux/types.h>
+#include <asm/cpu_device_id.h>
#include <asm/cpufeatures.h>
+#include <asm/intel-family.h>
#include <asm/mce.h>
#include <asm/msr.h>
#include <asm/msr-index.h>
+/* Machine check bank hardware unit types */
+enum bff_bank_type {
+ BFF_BANK_NONE = 0,
+ BFF_BANK_DCU,
+ BFF_BANK_DTLB,
+ BFF_BANK_MLC,
+ BFF_BANK_CCF,
+ BFF_BANK_HSF,
+ BFF_BANK_IOCACHE,
+};
+
+/*
+ * Mapping from machine check bank numbers on Diamond Rapids CPU, that are
+ * supported by a bitfix filter, to hardware unit type.
+ */
+static const enum bff_bank_type dmr_mcbanks[MAX_NR_BANKS] = {
+ [1] = BFF_BANK_DCU,
+ [2] = BFF_BANK_DTLB,
+ [3] = BFF_BANK_MLC,
+ [6] = BFF_BANK_CCF,
+ [13] = BFF_BANK_HSF,
+ [17] = BFF_BANK_IOCACHE
+};
+
+static const struct x86_cpu_id bff_cpu_ids[] __initconst = {
+ X86_MATCH_VFM(INTEL_DIAMONDRAPIDS_X, dmr_mcbanks),
+ {}
+};
+MODULE_DEVICE_TABLE(x86cpu, bff_cpu_ids);
+
+static const enum bff_bank_type *bff_bank_types;
+
static int __init bff_init(void)
{
+ const struct x86_cpu_id *m;
u64 core_caps, mcg_cap;
if (!cpu_feature_enabled(X86_FEATURE_MCA))
@@ -44,6 +81,14 @@ static int __init bff_init(void)
if (!(core_caps & MSR_IA32_CORE_CAPS_BFF_RESET))
return -ENODEV;
+ m = x86_match_cpu(bff_cpu_ids);
+ if (!m) {
+ pr_info("CPU model not supported by the bitfix filter reset driver\n");
+ return -ENODEV;
+ }
+
+ bff_bank_types = (const enum bff_bank_type *)m->driver_data;
+
return 0;
}
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 5/7] EDAC/intel-bff: Reset bitfix filter when it overflows
2026-08-28 15:29 [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters Tony Luck
` (3 preceding siblings ...)
2026-08-28 15:29 ` [PATCH v2 4/7] EDAC/intel-bff: Add Diamond Rapids support Tony Luck
@ 2026-08-28 15:30 ` Tony Luck
2026-08-28 15:30 ` [PATCH v2 6/7] EDAC/intel-bff: Compute unique ID for overflowed filter Tony Luck
2026-08-28 15:30 ` [PATCH v2 7/7] EDAC/intel-bff: Report frequent filter overflows Tony Luck
6 siblings, 0 replies; 8+ messages in thread
From: Tony Luck @ 2026-08-28 15:30 UTC (permalink / raw)
To: Tony Luck
Cc: Borislav Petkov, Qiuxu Zhuo, Ilpo Järvinen, Breno Leitao,
linux-edac, linux-kernel, patches
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 <qiuxu.zhuo@intel.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <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 <linux/bitfield.h>
+#include <linux/bits.h>
#include <linux/cpufeature.h>
#include <linux/device-id/x86_cpu.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/printk.h>
#include <linux/types.h>
@@ -32,6 +35,11 @@
#include <asm/msr.h>
#include <asm/msr-index.h>
+/* 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");
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 6/7] EDAC/intel-bff: Compute unique ID for overflowed filter
2026-08-28 15:29 [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters Tony Luck
` (4 preceding siblings ...)
2026-08-28 15:30 ` [PATCH v2 5/7] EDAC/intel-bff: Reset bitfix filter when it overflows Tony Luck
@ 2026-08-28 15:30 ` Tony Luck
2026-08-28 15:30 ` [PATCH v2 7/7] EDAC/intel-bff: Report frequent filter overflows Tony Luck
6 siblings, 0 replies; 8+ messages in thread
From: Tony Luck @ 2026-08-28 15:30 UTC (permalink / raw)
To: Tony Luck
Cc: Borislav Petkov, Qiuxu Zhuo, Ilpo Järvinen, Breno Leitao,
linux-edac, linux-kernel, patches
Each L2 cache instance has its own bitfix filter, but always reports
errors in machine check bank 3 (on Diamond Rapids).
Compute a unique bitfix filter instance number based on the CPU that
logged the error and the machine check bank number.
Special-case the banks associated with the Integrated Memory Hub (IMH).
Here the "even" numbered CPU modules are associated with IMH0 and the
"odd" modules with IMH1.
The unique id will be used to store a time stamp of when the bitfix
filter overflowed so that frequent overflows can be logged.
Co-developed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
drivers/edac/intel-bff.c | 80 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/drivers/edac/intel-bff.c b/drivers/edac/intel-bff.c
index c46d5255f34b..06a79745c2fb 100644
--- a/drivers/edac/intel-bff.c
+++ b/drivers/edac/intel-bff.c
@@ -19,13 +19,18 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/cacheinfo.h>
+#include <linux/cleanup.h>
#include <linux/cpufeature.h>
+#include <linux/cpuhplock.h>
#include <linux/device-id/x86_cpu.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/limits.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/printk.h>
+#include <linux/topology.h>
#include <linux/types.h>
#include <asm/cpu_device_id.h>
@@ -72,12 +77,87 @@ MODULE_DEVICE_TABLE(x86cpu, bff_cpu_ids);
static const enum bff_bank_type *bff_bank_types;
+/* Diamond Rapids maps APICID[2] to the IMH instance within a socket. */
+#define APICID_IMH_NUM GENMASK(2, 2)
+#define IMH_NUM(apicid) FIELD_GET(APICID_IMH_NUM, apicid)
+#define NUM_IMH_PER_SOCKET 2
+
+static void bff_set_imh_id(struct mce *mce, unsigned long *id)
+{
+ int imh_num;
+
+ imh_num = NUM_IMH_PER_SOCKET * topology_physical_package_id(mce->extcpu) +
+ IMH_NUM(mce->apicid);
+
+ *id |= imh_num;
+}
+
+static bool bff_set_cache_id(int cpu, int level, unsigned long *id)
+{
+ int cacheid;
+
+ guard(cpus_read_lock)();
+
+ cacheid = get_cpu_cacheinfo_id(cpu, level);
+ if (cacheid == -1) {
+ pr_warn("Could not get L%d cache id for CPU %d\n", level, cpu);
+ return false;
+ }
+
+ *id |= cacheid;
+
+ return true;
+}
+
+/*
+ * Cache IDs are only unique within a cache level.
+ * Include the MCA bank number so each BFF-capable hardware
+ * resource has a unique tracking ID.
+ */
+#define BFF_ID_BANK_FIELD GENMASK(63, 32)
+
+static unsigned long bff_get_id(struct mce *mce)
+{
+ unsigned long id = FIELD_PREP(BFF_ID_BANK_FIELD, mce->bank);
+
+ switch (bff_bank_types[mce->bank]) {
+ case BFF_BANK_DCU:
+ case BFF_BANK_DTLB:
+ if (!bff_set_cache_id(mce->extcpu, 1, &id))
+ return ULONG_MAX;
+ break;
+
+ case BFF_BANK_MLC:
+ if (!bff_set_cache_id(mce->extcpu, 2, &id))
+ return ULONG_MAX;
+ break;
+
+ case BFF_BANK_CCF:
+ if (!bff_set_cache_id(mce->extcpu, 3, &id))
+ return ULONG_MAX;
+ break;
+
+ case BFF_BANK_HSF:
+ case BFF_BANK_IOCACHE:
+ bff_set_imh_id(mce, &id);
+ break;
+
+ default:
+ return ULONG_MAX;
+ }
+
+ return id;
+}
+
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);
+
+ /* Placeholder use of bff_get_id() */
+ pr_debug("unique_id = 0x%lx\n", bff_get_id(mce));
}
static int bff_mce_notify(struct notifier_block *nb, unsigned long val, void *data)
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 7/7] EDAC/intel-bff: Report frequent filter overflows
2026-08-28 15:29 [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters Tony Luck
` (5 preceding siblings ...)
2026-08-28 15:30 ` [PATCH v2 6/7] EDAC/intel-bff: Compute unique ID for overflowed filter Tony Luck
@ 2026-08-28 15:30 ` Tony Luck
6 siblings, 0 replies; 8+ messages in thread
From: Tony Luck @ 2026-08-28 15:30 UTC (permalink / raw)
To: Tony Luck
Cc: Borislav Petkov, Qiuxu Zhuo, Ilpo Järvinen, Breno Leitao,
linux-edac, linux-kernel, patches
If an instance of a bitfix filter contains some transient errors built
up over time, then resetting the filter will free up slots in the filter
to store persistent errors.
Save a timestamp when "yellow" status is seen and clear the filter.
Log at KERN_WARNING level if the overflow occurred quickly after a
previous overflow on the same bitfix filter instance. Use KERN_NOTICE
for first, or long delayed, overflow.
Co-developed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
drivers/edac/intel-bff.c | 72 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 2 deletions(-)
diff --git a/drivers/edac/intel-bff.c b/drivers/edac/intel-bff.c
index 06a79745c2fb..adf2ec343129 100644
--- a/drivers/edac/intel-bff.c
+++ b/drivers/edac/intel-bff.c
@@ -25,13 +25,17 @@
#include <linux/cpuhplock.h>
#include <linux/device-id/x86_cpu.h>
#include <linux/errno.h>
+#include <linux/gfp_types.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/printk.h>
+#include <linux/slab.h>
#include <linux/topology.h>
#include <linux/types.h>
+#include <linux/xarray.h>
#include <asm/cpu_device_id.h>
#include <asm/cpufeatures.h>
@@ -40,6 +44,16 @@
#include <asm/msr.h>
#include <asm/msr-index.h>
+/*
+ * A 10-minute observation period helps distinguish between:
+ *
+ * - A long-term accumulation of transient corrected errors
+ * (filter stays clear after reset).
+ *
+ * - Permanent defects (filter overflows again quickly).
+ */
+#define BFF_OVERFLOW_INTERVAL secs_to_jiffies(10 * 60)
+
/* Intel bitfix filter control register defines */
#define MSR_MC0_BFF_CTL 0x000006c0
#define MSR_MCx_BFF_CTL(x) (MSR_MC0_BFF_CTL + (x))
@@ -77,6 +91,8 @@ MODULE_DEVICE_TABLE(x86cpu, bff_cpu_ids);
static const enum bff_bank_type *bff_bank_types;
+static DEFINE_XARRAY(bff_bank_xa);
+
/* Diamond Rapids maps APICID[2] to the IMH instance within a socket. */
#define APICID_IMH_NUM GENMASK(2, 2)
#define IMH_NUM(apicid) FIELD_GET(APICID_IMH_NUM, apicid)
@@ -149,6 +165,41 @@ static unsigned long bff_get_id(struct mce *mce)
return id;
}
+/*
+ * Save current timestamp for bff_id. Return true if it is within
+ * BFF_OVERFLOW_INTERVAL of previous timestamp for this bff_id.
+ */
+static bool bff_overflow_is_frequent(unsigned long bff_id)
+{
+ unsigned long now = jiffies, interval_end;
+ unsigned long *ts;
+
+ if (bff_id == ULONG_MAX)
+ return false;
+
+ ts = xa_load(&bff_bank_xa, bff_id);
+ if (!ts) {
+ ts = kzalloc_obj(*ts);
+ if (!ts) {
+ pr_warn("Failed to allocate timestamp for bitfix filter 0x%lx\n", bff_id);
+ return false;
+ }
+ if (xa_is_err(xa_store(&bff_bank_xa, bff_id, ts, GFP_KERNEL))) {
+ kfree(ts);
+ pr_warn("Failed to record timestamp for bitfix filter 0x%lx\n", bff_id);
+ return false;
+ }
+ *ts = now;
+
+ return false;
+ }
+
+ interval_end = *ts + BFF_OVERFLOW_INTERVAL;
+ *ts = now;
+
+ return time_before(now, interval_end);
+}
+
static void bff_reset_and_report(struct mce *mce)
{
/* Reset bitfix filter using the CPU that logged the yellow status */
@@ -156,8 +207,18 @@ static void bff_reset_and_report(struct mce *mce)
pr_warn("Failed to reset bitfix filter for CPU %d Bank %d\n",
mce->extcpu, mce->bank);
- /* Placeholder use of bff_get_id() */
- pr_debug("unique_id = 0x%lx\n", bff_get_id(mce));
+ /*
+ * Use the unique id for the bitfix filter instance that overflowed and
+ * check if this is a repeat within the BFF_OVERFLOW_INTERVAL. If it
+ * is, then report at WARN severity as the user may want to take action.
+ */
+ if (bff_overflow_is_frequent(bff_get_id(mce))) {
+ pr_warn_ratelimited(HW_ERR "Socket %d CPU %d Bank %d bitfix filter overflowed frequently\n",
+ mce->socketid, mce->extcpu, mce->bank);
+ } else {
+ pr_notice_ratelimited(HW_ERR "Socket %d CPU %d Bank %d bitfix filter overflowed\n",
+ mce->socketid, mce->extcpu, mce->bank);
+ }
}
static int bff_mce_notify(struct notifier_block *nb, unsigned long val, void *data)
@@ -216,7 +277,14 @@ static int __init bff_init(void)
static void __exit bff_exit(void)
{
+ unsigned long bff_id;
+ unsigned long *ts;
+
mce_unregister_decode_chain(&bff_notifier);
+
+ xa_for_each(&bff_bank_xa, bff_id, ts)
+ kfree(ts);
+ xa_destroy(&bff_bank_xa);
}
module_init(bff_init);
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread