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
bff_set_imh_id(struct mce * mce,unsigned long * id)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
bff_set_cache_id(int cpu,int level,unsigned long * id)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
bff_get_id(struct mce * mce)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 */
bff_overflow_is_frequent(unsigned long bff_id)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
bff_reset_and_report(struct mce * mce)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
bff_mce_notify(struct notifier_block * nb,unsigned long val,void * data)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
bff_init(void)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
bff_exit(void)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