projects/linux·commit ae171014

Merge tag 'edac_updates_for_v7.4_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras

ae171014 · Linus Torvalds <[email protected]> · 2026-10-20 08:14:43 -10:00

Pull EDAC updates from Borislav Petkov:

 - Orphan several EDAC drivers: i82975x, x38, xgene, i3200. Those have
   been receiving just drive-by updates and no one really uses them. At
   least there are no traces of usage on the mailing lists. So, with the
   advent of AI-generated fixes frenzy, and because no one can really
   test fixes on those, it is time to sunset them and point them towards
   the eternal happy hunting-grounds

 - Add a dummy EDAC driver with which the EDAC core glue can be
   exercised in a VM for the cases where one does not necessarily have
   access to the hardware. This glue should be extended with all the
   necessary functionality that needs and can be tested this way

 - Add an EDAC driver to reset bitfix filters in Intel hardware. Bitfix
   filters are a hw mechanism for tracking stuck bits in memory and CPU
   arrays due to, e.g., silicon aging. Those filters can become clogged
   by transient errors accumulating over a long system uptime so this
   intel-bff (LOL :)) driver glue resets those filters on overflow. Work
   by Qiuxu Zhuo and Tony Luck

 - Export get_cpu_cacheinfo_id() for use by the new intel-bff driver

 - i10nm: Handle the case where hw disables memory controllers which
   leads to reporting the wrong memory controller when reporting an
   error

 - The now-usual AI-powered fixes and other misc cleanups and updates
   all over the place

* tag 'edac_updates_for_v7.4_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras:
  MAINTAINERS: Orphan drivers/edac/i3200_edac.c
  EDAC/skx_base: Fix ambiguous bitwise and logical operator style
  EDAC/i10nm: Fix mdev reference leak in i10nm_get_ddr_munits()
  MAINTAINERS: Orphan drivers/edac/xgene_edac.c
  MAINTAINERS: Orphan drivers/edac/x38_edac.c
  MAINTAINERS: Orphan drivers/edac/i82975x_edac.c
  EDAC/dummy: Add a dummy EDAC driver
  EDAC/ie31200: Disable PCI device when probing fails
  EDAC/{bluefield,loongson}: Use named initializers for acpi_device_id
  MAINTAINERS: Update Qiuxu Zhuo's email address
  EDAC/intel-bff: Report frequent filter overflows
  EDAC/intel-bff: Compute unique ID for overflowed filter
  EDAC/intel-bff: Reset bitfix filter when it overflows
  EDAC/intel-bff: Add Diamond Rapids support
  EDAC/intel-bff: Add stub Intel bitfix filter driver
  x86/mce: Add enumeration for Intel bitfix filter reset
  cacheinfo: Export get_cpu_cacheinfo_id() for loadable modules
  EDAC/i10nm: Fix Granite Rapids ADXL MC mapping
Commit
ae171014b7988fabf1dbbc7cc4036c416a5b0230
Parents
303bff36 · 5dbc181a

Merge commit. Changes below are compared with the first parent: 303bff36.

Changes

14 files changed · +567 −24

Only the first 600 diff lines are shown. Download the complete patch.

MAINTAINERS

View file
diff --git a/MAINTAINERS b/MAINTAINERS
index 56c38a9..83aa851 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2076,8 +2076,7 @@ S: Supported
F: arch/arm64/boot/dts/apm/
APPLIED MICRO (APM) X-GENE SOC EDAC
-M: Khuong Dinh <[email protected]>
-S: Supported
+S: Orphan
F: Documentation/devicetree/bindings/edac/apm,xgene-edac.yaml
F: drivers/edac/xgene_edac.c
@@ -9450,6 +9449,11 @@ L: [email protected]
S: Orphan
F: drivers/edac/i3000_edac.c
+EDAC-I3200
+S: Orphan
+F: drivers/edac/i3200_edac.c
+
EDAC-I5000
S: Maintained
@@ -9474,9 +9478,8 @@ S: Maintained
F: drivers/edac/i7core_edac.c
EDAC-I82975X
-M: "Arvind R." <[email protected]>
-S: Maintained
+S: Orphan
F: drivers/edac/i82975x_edac.c
EDAC-IE31200
@@ -9487,11 +9490,17 @@ F: drivers/edac/ie31200_edac.c
EDAC-IGEN6
M: Tony Luck <[email protected]>
-R: Qiuxu Zhuo <[email protected]>
+R: Qiuxu Zhuo <[email protected]>
S: Maintained
F: drivers/edac/igen6_edac.c
+EDAC-INTEL-BFF-RESET
+M: Tony Luck <[email protected]>
+S: Maintained
+F: drivers/edac/intel-bff.c
+
EDAC-MPC85XX
S: Orphan
@@ -9526,7 +9535,7 @@ F: drivers/edac/qcom_edac.c
EDAC-SBRIDGE
M: Tony Luck <[email protected]>
-R: Qiuxu Zhuo <[email protected]>
+R: Qiuxu Zhuo <[email protected]>
S: Maintained
F: drivers/edac/sb_edac.c
@@ -9543,6 +9552,11 @@ L: [email protected]
S: Odd Fixes
F: drivers/edac/ti_edac.c
+EDAC-X38
+S: Orphan
+F: drivers/edac/x38_edac.c
+
EDIROL UA-101/UA-1000 DRIVER
M: Clemens Ladisch <[email protected]>

arch/x86/include/asm/mce.h

View file
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index e575b70..9995176 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)

arch/x86/include/asm/msr-index.h

View file
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 3a8e51a..1787fbb 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)

drivers/base/cacheinfo.c

View file
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 7a47a39..eb8a907 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)
{

drivers/edac/Kconfig

View file
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index a44b85c..4c70729 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
@@ -581,4 +594,13 @@ config EDAC_VERSALNET
and other system errors from various IP subsystems like RPU, NOCs,
HNICX, PL on the AMD Versal NET DDR memory controller.
+config EDAC_DUMMY
+ tristate "Dummy EDAC driver"
+ default n
+ help
+ A dummy EDAC driver is useful for testing purposes in a VM when one
+ doesn't have all the hardware needed to test aspects of the EDAC
+ subsystem code.
+
+ You definitely wanna say N here.
endif # EDAC

drivers/edac/Makefile

View file
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index a375343..4020ea6 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_EDAC_I7300) += i7300_edac.o
obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o
obj-$(CONFIG_EDAC_SBRIDGE) += sb_edac.o
obj-$(CONFIG_EDAC_PND2) += pnd2_edac.o
-obj-$(CONFIG_EDAC_IGEN6) += igen6_edac.o
+obj-$(CONFIG_EDAC_IGEN6) += igen6_edac.o
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
@@ -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
@@ -91,3 +93,4 @@ obj-$(CONFIG_EDAC_VERSAL) += versal_edac.o
obj-$(CONFIG_EDAC_LOONGSON) += loongson_edac.o
obj-$(CONFIG_EDAC_VERSALNET) += versalnet_edac.o
obj-$(CONFIG_EDAC_CORTEX_A72) += a72_edac.o
+obj-$(CONFIG_EDAC_DUMMY) += dummy_edac.o

drivers/edac/bluefield_edac.c

View file
diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c
index ae3bb7a..472fc87 100644
--- a/drivers/edac/bluefield_edac.c
+++ b/drivers/edac/bluefield_edac.c
@@ -472,8 +472,8 @@ static void bluefield_edac_mc_remove(struct platform_device *pdev)
}
static const struct acpi_device_id bluefield_mc_acpi_ids[] = {
- {"MLNXBF08", 0},
- {}
+ { .id = "MLNXBF08" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, bluefield_mc_acpi_ids);

drivers/edac/dummy_edac.c

View file
diff --git a/drivers/edac/dummy_edac.c b/drivers/edac/dummy_edac.c
new file mode 100644
index 0000000..193f561
--- /dev/null
+++ b/drivers/edac/dummy_edac.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Dummy EDAC driver
+ *
+ * A minimal EDAC device driver that registers its own platform device
+ * unconditionally, so it probes successfully on any system -- including
+ * VMs and guests that have no real ECC-capable cache/memory hardware
+ * exposed to them. Useful for exercising the EDAC core, sysfs interface,
+ * and userspace tooling (edac-utils, mcelog, etc.) without needing the
+ * physical hardware the "real" drivers depend on.
+ *
+ * Modeled after drivers/edac/a72_edac.c (Cortex A72 EDAC L1/L2 cache
+ * error detection), but with all of the hardware-specific bits (system
+ * register reads, SMP cross-calls, devicetree compatible matching)
+ * replaced by a software-only error source that can be poked from
+ * debugfs or left to generate nothing at all.
+ */
+
+#include <linux/cpu.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "edac_module.h"
+
+#define DRVNAME "dummy-edac"
+#define MESSAGE_SIZE 64
+
+/*
+ * Simulated "error syndrome". In real hardware drivers this would be
+ * read out of a per-CPU system/MMIO register. Here userspace (via
+ * debugfs) or nothing at all drives it, which is exactly the point:
+ * the driver has no dependency on any physical error source.
+ */
+struct dummy_edac_priv {
+ struct dentry *debugfs_dir;
+ atomic_t inject_ce;
+ atomic_t inject_ue;
+};
+
+static void dummy_edac_check(struct edac_device_ctl_info *edac_ctl)
+{
+ struct dummy_edac_priv *priv = edac_ctl->pvt_info;
+ int cpu = raw_smp_processor_id();
+ char msg[MESSAGE_SIZE];
+
+ if (atomic_xchg(&priv->inject_ce, 0)) {
+ snprintf(msg, MESSAGE_SIZE,
+ "simulated correctable error on CPU %d", cpu);
+ edac_device_handle_ce(edac_ctl, cpu, 0, msg);
+ }
+
+ if (atomic_xchg(&priv->inject_ue, 0)) {
+ snprintf(msg, MESSAGE_SIZE,
+ "simulated uncorrectable error on CPU %d", cpu);
+ edac_device_handle_ue(edac_ctl, cpu, 0, msg);
+ }
+}
+
+/*
+ * debugfs knobs so you can drive the driver from userspace inside the
+ * guest, e.g.:
+ * echo 1 > /sys/kernel/debug/dummy-edac/inject_ce
+ * echo 1 > /sys/kernel/debug/dummy-edac/inject_ue
+ */
+static int inject_ce_set(void *data, u64 val)
+{
+ struct dummy_edac_priv *priv = data;
+
+ if (val)
+ atomic_set(&priv->inject_ce, 1);
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(inject_ce_fops, NULL, inject_ce_set, "%llu\n");
+
+static int inject_ue_set(void *data, u64 val)
+{
+ struct dummy_edac_priv *priv = data;
+
+ if (val)
+ atomic_set(&priv->inject_ue, 1);
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(inject_ue_fops, NULL, inject_ue_set, "%llu\n");
+
+static int dummy_edac_probe(struct platform_device *pdev)
+{
+ struct edac_device_ctl_info *edac_ctl;
+ struct dummy_edac_priv *priv;
+ struct device *dev = &pdev->dev;
+ int rc;
+
+ edac_ctl = edac_device_alloc_ctl_info(sizeof(*priv), "cpu",
+ num_possible_cpus(), "L", 1, 1,
+ edac_device_alloc_index());
+ if (!edac_ctl)
+ return -ENOMEM;
+
+ priv = edac_ctl->pvt_info;
+ atomic_set(&priv->inject_ce, 0);
+ atomic_set(&priv->inject_ue, 0);
+
+ edac_ctl->edac_check = dummy_edac_check;
+ edac_ctl->dev = dev;
+ edac_ctl->mod_name = dev_name(dev);
+ edac_ctl->dev_name = dev_name(dev);
+ edac_ctl->ctl_name = DRVNAME;
+ /* Poll fairly slowly; this is a software source, not real hardware. */
+ edac_ctl->poll_msec = 1000;
+ dev_set_drvdata(dev, edac_ctl);
+
+ rc = edac_device_add_device(edac_ctl);
+ if (rc)
+ goto out_dev;
+
+ priv->debugfs_dir = debugfs_create_dir(DRVNAME, NULL);
+ debugfs_create_file_unsafe("inject_ce", 0200, priv->debugfs_dir,
+ priv, &inject_ce_fops);
+ debugfs_create_file_unsafe("inject_ue", 0200, priv->debugfs_dir,
+ priv, &inject_ue_fops);
+
+ return 0;
+
+out_dev:
+ edac_device_free_ctl_info(edac_ctl);
+
+ return rc;
+}
+
+static void dummy_edac_remove(struct platform_device *pdev)
+{
+ struct edac_device_ctl_info *edac_ctl = dev_get_drvdata(&pdev->dev);
+ struct dummy_edac_priv *priv = edac_ctl->pvt_info;
+
+ debugfs_remove_recursive(priv->debugfs_dir);
+ edac_device_del_device(edac_ctl->dev);
+ edac_device_free_ctl_info(edac_ctl);
+}
+
+static struct platform_driver dummy_edac_driver = {
+ .probe = dummy_edac_probe,
+ .remove = dummy_edac_remove,
+ .driver = {
+ .name = DRVNAME,
+ },
+};
+
+/*
+ * No devicetree/ACPI match table, and no scan of CPU nodes for a "compatible"
+ * + enable property: simply register a platform device unconditionally so
+ * probe() always runs. There is nothing here that depends on the underlying
+ * platform actually exposing the corresponding hardware, so it loads fine
+ * under QEMU/KVM, containers-with-a-kernel, or any other guest environment.
+ */
+static struct platform_device *dummy_pdev;
+
+static int __init dummy_edac_driver_init(void)
+{
+ int rc;
+
+ dummy_pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
+ if (IS_ERR(dummy_pdev)) {
+ pr_err(DRVNAME ": failed to register dummy platform device\n");
+ return PTR_ERR(dummy_pdev);
+ }
+
+ rc = platform_driver_register(&dummy_edac_driver);
+ if (rc) {
+ platform_device_unregister(dummy_pdev);
+ return rc;
+ }
+
+ pr_info("Loading %s\n", DRVNAME);
+
+ return 0;
+}
+
+static void __exit dummy_edac_driver_exit(void)
+{
+ platform_driver_unregister(&dummy_edac_driver);
+ platform_device_unregister(dummy_pdev);
+
+ pr_info("Removing %s\n", DRVNAME);
+}
+
+module_init(dummy_edac_driver_init);
+module_exit(dummy_edac_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Dummy EDAC driver for testing without real ECC hardware");

drivers/edac/i10nm_base.c

View file
diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
index fa1853f..87e541c 100644
--- a/drivers/edac/i10nm_base.c
+++ b/drivers/edac/i10nm_base.c
@@ -479,6 +479,7 @@ static struct pci_dev *get_gnr_mdev(struct skx_dev *d, int logical_idx, int *phy
if (mdev) {
if (logical == logical_idx) {
*physical_idx = i;
+ skx_set_mc_mapping(d, i, logical_idx);
return mdev;
}
@@ -634,6 +635,7 @@ static int i10nm_get_ddr_munits(void)
mbase = ioremap(base + off, size);
if (!mbase) {
+ pci_dev_put(mdev);
i10nm_printk(KERN_ERR, "Failed to ioremap 0x%llx\n",
base + off);
return -ENODEV;

drivers/edac/ie31200_edac.c

View file
diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c
index 6f5fdf4..88af77e 100644
--- a/drivers/edac/ie31200_edac.c
+++ b/drivers/edac/ie31200_edac.c
@@ -660,7 +660,9 @@ static int ie31200_init_one(struct pci_dev *pdev,
if (pci_enable_device(pdev) < 0)
return -EIO;
rc = ie31200_probe1(pdev, (struct res_config *)ent->driver_data);
- if (rc == 0 && !mci_pdev)
+ if (rc)
+ pci_disable_device(pdev);
+ else if (!mci_pdev)
mci_pdev = pci_dev_get(pdev);
return rc;

drivers/edac/intel-bff.c

View file
diff --git a/drivers/edac/intel-bff.c b/drivers/edac/intel-bff.c
new file mode 100644
index 0000000..adf2ec3
--- /dev/null
+++ b/drivers/edac/intel-bff.c
@@ -0,0 +1,295 @@
+// 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/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/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>
+#include <asm/intel-family.h>
+#include <asm/mce.h>
+#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))
+#define MCI_BFF_RESET BIT_ULL(0)
+
+/* 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 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)
+#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:

This diff is incomplete. Download the complete patch.

drivers/edac/loongson_edac.c

View file

This diff is incomplete. Download the complete patch.

drivers/edac/skx_base.c

View file

This diff is incomplete. Download the complete patch.

include/linux/cacheinfo.h

View file

This diff is incomplete. Download the complete patch.