xref: /linux/drivers/edac/intel-bff.c (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2026 Intel Corporation. */
3 
4 /*
5  * Intel driver to reset bitfix filters when they overflow.
6  *
7  * Each bitfix filter has limited slots to track corrected errors.
8  * These slots can be filled by transient corrected errors (e.g.,
9  * bit flips from particle strikes) that don't represent permanent
10  * hardware defects.
11  *
12  * When the filter overflows (yellow status), reset it to reclaim
13  * slots occupied by transient corrected errors. If the overflow
14  * repeats frequently after reset, it indicates persistent hardware
15  * defects that need attention: the system should be scheduled for
16  * servicing.
17  */
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 
20 #include <linux/bitfield.h>
21 #include <linux/bits.h>
22 #include <linux/cacheinfo.h>
23 #include <linux/cleanup.h>
24 #include <linux/cpufeature.h>
25 #include <linux/cpuhplock.h>
26 #include <linux/device-id/x86_cpu.h>
27 #include <linux/errno.h>
28 #include <linux/gfp_types.h>
29 #include <linux/init.h>
30 #include <linux/jiffies.h>
31 #include <linux/limits.h>
32 #include <linux/module.h>
33 #include <linux/notifier.h>
34 #include <linux/printk.h>
35 #include <linux/slab.h>
36 #include <linux/topology.h>
37 #include <linux/types.h>
38 #include <linux/xarray.h>
39 
40 #include <asm/cpu_device_id.h>
41 #include <asm/cpufeatures.h>
42 #include <asm/intel-family.h>
43 #include <asm/mce.h>
44 #include <asm/msr.h>
45 #include <asm/msr-index.h>
46 
47 /*
48  * A 10-minute observation period helps distinguish between:
49  *
50  *  - A long-term accumulation of transient corrected errors
51  *    (filter stays clear after reset).
52  *
53  *  - Permanent defects (filter overflows again quickly).
54  */
55 #define BFF_OVERFLOW_INTERVAL	secs_to_jiffies(10 * 60)
56 
57 /* Intel bitfix filter control register defines */
58 #define MSR_MC0_BFF_CTL		0x000006c0
59 #define MSR_MCx_BFF_CTL(x)	(MSR_MC0_BFF_CTL + (x))
60 #define  MCI_BFF_RESET		BIT_ULL(0)
61 
62 /* Machine check bank hardware unit types */
63 enum bff_bank_type {
64 	BFF_BANK_NONE = 0,
65 	BFF_BANK_DCU,
66 	BFF_BANK_DTLB,
67 	BFF_BANK_MLC,
68 	BFF_BANK_CCF,
69 	BFF_BANK_HSF,
70 	BFF_BANK_IOCACHE,
71 };
72 
73 /*
74  * Mapping from machine check bank numbers on Diamond Rapids CPU, that are
75  * supported by a bitfix filter, to hardware unit type.
76  */
77 static const enum bff_bank_type dmr_mcbanks[MAX_NR_BANKS] = {
78 	[1]	= BFF_BANK_DCU,
79 	[2]	= BFF_BANK_DTLB,
80 	[3]	= BFF_BANK_MLC,
81 	[6]	= BFF_BANK_CCF,
82 	[13]	= BFF_BANK_HSF,
83 	[17]	= BFF_BANK_IOCACHE
84 };
85 
86 static const struct x86_cpu_id bff_cpu_ids[] __initconst = {
87 	X86_MATCH_VFM(INTEL_DIAMONDRAPIDS_X, dmr_mcbanks),
88 	{}
89 };
90 MODULE_DEVICE_TABLE(x86cpu, bff_cpu_ids);
91 
92 static const enum bff_bank_type *bff_bank_types;
93 
94 static DEFINE_XARRAY(bff_bank_xa);
95 
96 /* Diamond Rapids maps APICID[2] to the IMH instance within a socket. */
97 #define APICID_IMH_NUM		GENMASK(2, 2)
98 #define IMH_NUM(apicid)		FIELD_GET(APICID_IMH_NUM, apicid)
99 #define NUM_IMH_PER_SOCKET	2
100 
101 static void bff_set_imh_id(struct mce *mce, unsigned long *id)
102 {
103 	int imh_num;
104 
105 	imh_num = NUM_IMH_PER_SOCKET * topology_physical_package_id(mce->extcpu) +
106 			IMH_NUM(mce->apicid);
107 
108 	*id |= imh_num;
109 }
110 
111 static bool bff_set_cache_id(int cpu, int level, unsigned long *id)
112 {
113 	int cacheid;
114 
115 	guard(cpus_read_lock)();
116 
117 	cacheid = get_cpu_cacheinfo_id(cpu, level);
118 	if (cacheid == -1) {
119 		pr_warn("Could not get L%d cache id for CPU %d\n", level, cpu);
120 		return false;
121 	}
122 
123 	*id |= cacheid;
124 
125 	return true;
126 }
127 
128 /*
129  * Cache IDs are only unique within a cache level.
130  * Include the MCA bank number so each BFF-capable hardware
131  * resource has a unique tracking ID.
132  */
133 #define BFF_ID_BANK_FIELD	GENMASK(63, 32)
134 
135 static unsigned long bff_get_id(struct mce *mce)
136 {
137 	unsigned long id = FIELD_PREP(BFF_ID_BANK_FIELD, mce->bank);
138 
139 	switch (bff_bank_types[mce->bank]) {
140 	case BFF_BANK_DCU:
141 	case BFF_BANK_DTLB:
142 		if (!bff_set_cache_id(mce->extcpu, 1, &id))
143 			return ULONG_MAX;
144 		break;
145 
146 	case BFF_BANK_MLC:
147 		if (!bff_set_cache_id(mce->extcpu, 2, &id))
148 			return ULONG_MAX;
149 		break;
150 
151 	case BFF_BANK_CCF:
152 		if (!bff_set_cache_id(mce->extcpu, 3, &id))
153 			return ULONG_MAX;
154 		break;
155 
156 	case BFF_BANK_HSF:
157 	case BFF_BANK_IOCACHE:
158 		bff_set_imh_id(mce, &id);
159 		break;
160 
161 	default:
162 		return ULONG_MAX;
163 	}
164 
165 	return id;
166 }
167 
168 /*
169  * Save current timestamp for bff_id. Return true if it is within
170  * BFF_OVERFLOW_INTERVAL of previous timestamp for this bff_id.
171  */
172 static bool bff_overflow_is_frequent(unsigned long bff_id)
173 {
174 	unsigned long now = jiffies, interval_end;
175 	unsigned long *ts;
176 
177 	if (bff_id == ULONG_MAX)
178 		return false;
179 
180 	ts = xa_load(&bff_bank_xa, bff_id);
181 	if (!ts) {
182 		ts = kzalloc_obj(*ts);
183 		if (!ts) {
184 			pr_warn("Failed to allocate timestamp for bitfix filter 0x%lx\n", bff_id);
185 			return false;
186 		}
187 		if (xa_is_err(xa_store(&bff_bank_xa, bff_id, ts, GFP_KERNEL))) {
188 			kfree(ts);
189 			pr_warn("Failed to record timestamp for bitfix filter 0x%lx\n", bff_id);
190 			return false;
191 		}
192 		*ts = now;
193 
194 		return false;
195 	}
196 
197 	interval_end = *ts + BFF_OVERFLOW_INTERVAL;
198 	*ts = now;
199 
200 	return time_before(now, interval_end);
201 }
202 
203 static void bff_reset_and_report(struct mce *mce)
204 {
205 	/* Reset bitfix filter using the CPU that logged the yellow status */
206 	if (wrmsrq_on_cpu(mce->extcpu, MSR_MCx_BFF_CTL(mce->bank), MCI_BFF_RESET))
207 		pr_warn("Failed to reset bitfix filter for CPU %d Bank %d\n",
208 			mce->extcpu, mce->bank);
209 
210 	/*
211 	 * Use the unique id for the bitfix filter instance that overflowed and
212 	 * check if this is a repeat within the BFF_OVERFLOW_INTERVAL. If it
213 	 * is, then report at WARN severity as the user may want to take action.
214 	 */
215 	if (bff_overflow_is_frequent(bff_get_id(mce))) {
216 		pr_warn_ratelimited(HW_ERR "Socket %d CPU %d Bank %d bitfix filter overflowed frequently\n",
217 				    mce->socketid, mce->extcpu, mce->bank);
218 	} else {
219 		pr_notice_ratelimited(HW_ERR "Socket %d CPU %d Bank %d bitfix filter overflowed\n",
220 				      mce->socketid, mce->extcpu, mce->bank);
221 	}
222 }
223 
224 static int bff_mce_notify(struct notifier_block *nb, unsigned long val, void *data)
225 {
226 	struct mce *mce = data;
227 
228 	/* TES is undefined for uncorrected errors. */
229 	if (mce->status & MCI_STATUS_UC)
230 		return NOTIFY_DONE;
231 
232 	if (MCI_STATUS_TES(mce->status) != MCI_STATUS_TES_YELLOW)
233 		return NOTIFY_DONE;
234 
235 	if (mce->bank >= MAX_NR_BANKS || bff_bank_types[mce->bank] == BFF_BANK_NONE)
236 		return NOTIFY_DONE;
237 
238 	bff_reset_and_report(mce);
239 
240 	return NOTIFY_DONE;
241 }
242 
243 static struct notifier_block bff_notifier = {
244 	.notifier_call	= bff_mce_notify,
245 	.priority	= MCE_PRIO_EDAC,
246 };
247 
248 static int __init bff_init(void)
249 {
250 	const struct x86_cpu_id *m;
251 	u64 core_caps, mcg_cap;
252 
253 	if (!cpu_feature_enabled(X86_FEATURE_MCA))
254 		return -ENODEV;
255 	rdmsrq(MSR_IA32_MCG_CAP, mcg_cap);
256 	if (!(mcg_cap & MCG_TES_P))
257 		return -ENODEV;
258 
259 	if (!cpu_feature_enabled(X86_FEATURE_CORE_CAPABILITIES))
260 		return -ENODEV;
261 	rdmsrq(MSR_IA32_CORE_CAPS, core_caps);
262 	if (!(core_caps & MSR_IA32_CORE_CAPS_BFF_RESET))
263 		return -ENODEV;
264 
265 	m = x86_match_cpu(bff_cpu_ids);
266 	if (!m) {
267 		pr_info("CPU model not supported by the bitfix filter reset driver\n");
268 		return -ENODEV;
269 	}
270 
271 	bff_bank_types = (const enum bff_bank_type *)m->driver_data;
272 
273 	mce_register_decode_chain(&bff_notifier);
274 
275 	return 0;
276 }
277 
278 static void __exit bff_exit(void)
279 {
280 	unsigned long bff_id;
281 	unsigned long *ts;
282 
283 	mce_unregister_decode_chain(&bff_notifier);
284 
285 	xa_for_each(&bff_bank_xa, bff_id, ts)
286 		kfree(ts);
287 	xa_destroy(&bff_bank_xa);
288 }
289 
290 module_init(bff_init);
291 module_exit(bff_exit);
292 
293 MODULE_LICENSE("GPL");
294 MODULE_AUTHOR("Tony Luck");
295 MODULE_DESCRIPTION("Intel bitfix filter reset driver");
296