mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/7] EDAC/intel-bff: Driver to reset bitfix filters
@ 2026-08-28 15:29 Tony Luck
  2026-08-28 15:29 ` [PATCH v2 1/7] cacheinfo: Export get_cpu_cacheinfo_id() for loadable modules Tony Luck
                   ` (6 more replies)
  0 siblings, 7 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

Some Intel CPUs implement a "bitfix filter" to suppress reporting of the
same corrected errors repeatedly in the case where aging silicon
develops stuck bits.

But when systems run for weeks, or months, the filters may become clogged
with transient errors.

When the filter is full (indicated by a "yellow" signature in a machine
check bank) clear the filter. This may make space for additional hard
errors.

Save a time stamp when clearing a filter. Log with "WARN" severity if
the filter overflows quickly (in tem minutes or less).

Signed-off-by: Tony Luck <tony.luck@intel.com>
---
Changes since v1: https://lore.kernel.org/all/20260825181526.13203-1-tony.luck@intel.com/

Boris:
	Change from a platform driver to an EDAC driver to avoid
	spreading RAS code into yet another corner of the source tree.

Ilpo:
	Use <linux/bitfield.h> macros FIELD_GET() and FIELD_PREP() for
	bit wrangling.
	Did NOT add comma to last initializer for dmr_mcbanks[]. The
	list is complete, this CPU model won't add extra banks that
	support the bitfix filter.

Sashiko: https://sashiko.dev/#/patchset/20260825181526.13203-1-tony.luck%40intel.com
	Ignored complaint about lost #GP faults. The driver
	checks that the feature is enumerated, so #GP can't happen.
	Ignored complaint about overwriting bits 63:1 in the reset
	MSRs. Only bit 0 is defined in these MSRs.
	Applied suggestion to save bank number in upper 32 bits of bff_id.
	a/IS_ERR()/xa_is_err()/ for check of return from xa_store()

Miscellaneous:
	Added entry in MAINTAINERS file
	Applied some cleanup suggestions from internal AI review.

Qiuxu Zhuo (1):
  cacheinfo: Export get_cpu_cacheinfo_id() for loadable modules

Tony Luck (6):
  x86/mce: Add enumeration for Intel bitfix filter reset
  EDAC/intel-bff: Add stub Intel bitfix filter driver
  EDAC/intel-bff: Add Diamond Rapids support
  EDAC/intel-bff: Reset bitfix filter when it overflows
  EDAC/intel-bff: Compute unique ID for overflowed filter
  EDAC/intel-bff: Report frequent filter overflows

 include/linux/cacheinfo.h        |  12 +-
 arch/x86/include/asm/mce.h       |   5 +
 arch/x86/include/asm/msr-index.h |   2 +
 drivers/base/cacheinfo.c         |  17 ++
 drivers/edac/intel-bff.c         | 295 +++++++++++++++++++++++++++++++
 MAINTAINERS                      |   6 +
 drivers/edac/Kconfig             |  13 ++
 drivers/edac/Makefile            |   2 +
 8 files changed, 341 insertions(+), 11 deletions(-)
 create mode 100644 drivers/edac/intel-bff.c


base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
-- 
2.55.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [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

end of thread, other threads:[~2026-08-28 15:30 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH v2 3/7] EDAC/intel-bff: Add stub Intel bitfix filter driver Tony Luck
2026-08-28 15:29 ` [PATCH v2 4/7] EDAC/intel-bff: Add Diamond Rapids support Tony Luck
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 ` [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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®