xref: /linux/drivers/resctrl/mpam_devices.c (revision 01fb4b8224726aa0f2170b63e4685cf0eec85d8d)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2025 Arm Ltd.
3 
4 #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
5 
6 #include <linux/acpi.h>
7 #include <linux/arm_mpam.h>
8 #include <linux/cacheinfo.h>
9 #include <linux/cpumask.h>
10 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/gfp.h>
13 #include <linux/list.h>
14 #include <linux/lockdep.h>
15 #include <linux/mutex.h>
16 #include <linux/platform_device.h>
17 #include <linux/printk.h>
18 #include <linux/srcu.h>
19 #include <linux/types.h>
20 
21 #include "mpam_internal.h"
22 
23 /*
24  * mpam_list_lock protects the SRCU lists when writing. Once the
25  * mpam_enabled key is enabled these lists are read-only,
26  * unless the error interrupt disables the driver.
27  */
28 static DEFINE_MUTEX(mpam_list_lock);
29 static LIST_HEAD(mpam_all_msc);
30 
31 struct srcu_struct mpam_srcu;
32 
33 /*
34  * Number of MSCs that have been probed. Once all MSCs have been probed MPAM
35  * can be enabled.
36  */
37 static atomic_t mpam_num_msc;
38 
39 /*
40  * An MSC is a physical container for controls and monitors, each identified by
41  * their RIS index. These share a base-address, interrupts and some MMIO
42  * registers. A vMSC is a virtual container for RIS in an MSC that control or
43  * monitor the same thing. Members of a vMSC are all RIS in the same MSC, but
44  * not all RIS in an MSC share a vMSC.
45  *
46  * Components are a group of vMSC that control or monitor the same thing but
47  * are from different MSC, so have different base-address, interrupts etc.
48  * Classes are the set components of the same type.
49  *
50  * The features of a vMSC is the union of the RIS it contains.
51  * The features of a Class and Component are the common subset of the vMSC
52  * they contain.
53  *
54  * e.g. The system cache may have bandwidth controls on multiple interfaces,
55  * for regulating traffic from devices independently of traffic from CPUs.
56  * If these are two RIS in one MSC, they will be treated as controlling
57  * different things, and will not share a vMSC/component/class.
58  *
59  * e.g. The L2 may have one MSC and two RIS, one for cache-controls another
60  * for bandwidth. These two RIS are members of the same vMSC.
61  *
62  * e.g. The set of RIS that make up the L2 are grouped as a component. These
63  * are sometimes termed slices. They should be configured the same, as if there
64  * were only one.
65  *
66  * e.g. The SoC probably has more than one L2, each attached to a distinct set
67  * of CPUs. All the L2 components are grouped as a class.
68  *
69  * When creating an MSC, struct mpam_msc is added to the all mpam_all_msc list,
70  * then linked via struct mpam_ris to a vmsc, component and class.
71  * The same MSC may exist under different class->component->vmsc paths, but the
72  * RIS index will be unique.
73  */
74 LIST_HEAD(mpam_classes);
75 
76 /* List of all objects that can be free()d after synchronise_srcu() */
77 static LLIST_HEAD(mpam_garbage);
78 
79 static inline void init_garbage(struct mpam_garbage *garbage)
80 {
81 	init_llist_node(&garbage->llist);
82 }
83 
84 #define add_to_garbage(x)				\
85 do {							\
86 	__typeof__(x) _x = (x);				\
87 	_x->garbage.to_free = _x;			\
88 	llist_add(&_x->garbage.llist, &mpam_garbage);	\
89 } while (0)
90 
91 static void mpam_free_garbage(void)
92 {
93 	struct mpam_garbage *iter, *tmp;
94 	struct llist_node *to_free = llist_del_all(&mpam_garbage);
95 
96 	if (!to_free)
97 		return;
98 
99 	synchronize_srcu(&mpam_srcu);
100 
101 	llist_for_each_entry_safe(iter, tmp, to_free, llist) {
102 		if (iter->pdev)
103 			devm_kfree(&iter->pdev->dev, iter->to_free);
104 		else
105 			kfree(iter->to_free);
106 	}
107 }
108 
109 static struct mpam_class *
110 mpam_class_alloc(u8 level_idx, enum mpam_class_types type)
111 {
112 	struct mpam_class *class;
113 
114 	lockdep_assert_held(&mpam_list_lock);
115 
116 	class = kzalloc(sizeof(*class), GFP_KERNEL);
117 	if (!class)
118 		return ERR_PTR(-ENOMEM);
119 	init_garbage(&class->garbage);
120 
121 	INIT_LIST_HEAD_RCU(&class->components);
122 	/* Affinity is updated when ris are added */
123 	class->level = level_idx;
124 	class->type = type;
125 	INIT_LIST_HEAD_RCU(&class->classes_list);
126 
127 	list_add_rcu(&class->classes_list, &mpam_classes);
128 
129 	return class;
130 }
131 
132 static void mpam_class_destroy(struct mpam_class *class)
133 {
134 	lockdep_assert_held(&mpam_list_lock);
135 
136 	list_del_rcu(&class->classes_list);
137 	add_to_garbage(class);
138 }
139 
140 static struct mpam_class *
141 mpam_class_find(u8 level_idx, enum mpam_class_types type)
142 {
143 	struct mpam_class *class;
144 
145 	lockdep_assert_held(&mpam_list_lock);
146 
147 	list_for_each_entry(class, &mpam_classes, classes_list) {
148 		if (class->type == type && class->level == level_idx)
149 			return class;
150 	}
151 
152 	return mpam_class_alloc(level_idx, type);
153 }
154 
155 static struct mpam_component *
156 mpam_component_alloc(struct mpam_class *class, int id)
157 {
158 	struct mpam_component *comp;
159 
160 	lockdep_assert_held(&mpam_list_lock);
161 
162 	comp = kzalloc(sizeof(*comp), GFP_KERNEL);
163 	if (!comp)
164 		return ERR_PTR(-ENOMEM);
165 	init_garbage(&comp->garbage);
166 
167 	comp->comp_id = id;
168 	INIT_LIST_HEAD_RCU(&comp->vmsc);
169 	/* Affinity is updated when RIS are added */
170 	INIT_LIST_HEAD_RCU(&comp->class_list);
171 	comp->class = class;
172 
173 	list_add_rcu(&comp->class_list, &class->components);
174 
175 	return comp;
176 }
177 
178 static void mpam_component_destroy(struct mpam_component *comp)
179 {
180 	struct mpam_class *class = comp->class;
181 
182 	lockdep_assert_held(&mpam_list_lock);
183 
184 	list_del_rcu(&comp->class_list);
185 	add_to_garbage(comp);
186 
187 	if (list_empty(&class->components))
188 		mpam_class_destroy(class);
189 }
190 
191 static struct mpam_component *
192 mpam_component_find(struct mpam_class *class, int id)
193 {
194 	struct mpam_component *comp;
195 
196 	lockdep_assert_held(&mpam_list_lock);
197 
198 	list_for_each_entry(comp, &class->components, class_list) {
199 		if (comp->comp_id == id)
200 			return comp;
201 	}
202 
203 	return mpam_component_alloc(class, id);
204 }
205 
206 static struct mpam_vmsc *
207 mpam_vmsc_alloc(struct mpam_component *comp, struct mpam_msc *msc)
208 {
209 	struct mpam_vmsc *vmsc;
210 
211 	lockdep_assert_held(&mpam_list_lock);
212 
213 	vmsc = kzalloc(sizeof(*vmsc), GFP_KERNEL);
214 	if (!vmsc)
215 		return ERR_PTR(-ENOMEM);
216 	init_garbage(&vmsc->garbage);
217 
218 	INIT_LIST_HEAD_RCU(&vmsc->ris);
219 	INIT_LIST_HEAD_RCU(&vmsc->comp_list);
220 	vmsc->comp = comp;
221 	vmsc->msc = msc;
222 
223 	list_add_rcu(&vmsc->comp_list, &comp->vmsc);
224 
225 	return vmsc;
226 }
227 
228 static void mpam_vmsc_destroy(struct mpam_vmsc *vmsc)
229 {
230 	struct mpam_component *comp = vmsc->comp;
231 
232 	lockdep_assert_held(&mpam_list_lock);
233 
234 	list_del_rcu(&vmsc->comp_list);
235 	add_to_garbage(vmsc);
236 
237 	if (list_empty(&comp->vmsc))
238 		mpam_component_destroy(comp);
239 }
240 
241 static struct mpam_vmsc *
242 mpam_vmsc_find(struct mpam_component *comp, struct mpam_msc *msc)
243 {
244 	struct mpam_vmsc *vmsc;
245 
246 	lockdep_assert_held(&mpam_list_lock);
247 
248 	list_for_each_entry(vmsc, &comp->vmsc, comp_list) {
249 		if (vmsc->msc->id == msc->id)
250 			return vmsc;
251 	}
252 
253 	return mpam_vmsc_alloc(comp, msc);
254 }
255 
256 /*
257  * The cacheinfo structures are only populated when CPUs are online.
258  * This helper walks the acpi tables to include offline CPUs too.
259  */
260 int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level,
261 				   cpumask_t *affinity)
262 {
263 	return acpi_pptt_get_cpumask_from_cache_id(cache_id, affinity);
264 }
265 
266 /*
267  * cpumask_of_node() only knows about online CPUs. This can't tell us whether
268  * a class is represented on all possible CPUs.
269  */
270 static void get_cpumask_from_node_id(u32 node_id, cpumask_t *affinity)
271 {
272 	int cpu;
273 
274 	for_each_possible_cpu(cpu) {
275 		if (node_id == cpu_to_node(cpu))
276 			cpumask_set_cpu(cpu, affinity);
277 	}
278 }
279 
280 static int mpam_ris_get_affinity(struct mpam_msc *msc, cpumask_t *affinity,
281 				 enum mpam_class_types type,
282 				 struct mpam_class *class,
283 				 struct mpam_component *comp)
284 {
285 	int err;
286 
287 	switch (type) {
288 	case MPAM_CLASS_CACHE:
289 		err = mpam_get_cpumask_from_cache_id(comp->comp_id, class->level,
290 						     affinity);
291 		if (err) {
292 			dev_warn_once(&msc->pdev->dev,
293 				      "Failed to determine CPU affinity\n");
294 			return err;
295 		}
296 
297 		if (cpumask_empty(affinity))
298 			dev_warn_once(&msc->pdev->dev, "no CPUs associated with cache node\n");
299 
300 		break;
301 	case MPAM_CLASS_MEMORY:
302 		get_cpumask_from_node_id(comp->comp_id, affinity);
303 		/* affinity may be empty for CPU-less memory nodes */
304 		break;
305 	case MPAM_CLASS_UNKNOWN:
306 		return 0;
307 	}
308 
309 	cpumask_and(affinity, affinity, &msc->accessibility);
310 
311 	return 0;
312 }
313 
314 static int mpam_ris_create_locked(struct mpam_msc *msc, u8 ris_idx,
315 				  enum mpam_class_types type, u8 class_id,
316 				  int component_id)
317 {
318 	int err;
319 	struct mpam_vmsc *vmsc;
320 	struct mpam_msc_ris *ris;
321 	struct mpam_class *class;
322 	struct mpam_component *comp;
323 	struct platform_device *pdev = msc->pdev;
324 
325 	lockdep_assert_held(&mpam_list_lock);
326 
327 	if (ris_idx > MPAM_MSC_MAX_NUM_RIS)
328 		return -EINVAL;
329 
330 	if (test_and_set_bit(ris_idx, &msc->ris_idxs))
331 		return -EBUSY;
332 
333 	ris = devm_kzalloc(&msc->pdev->dev, sizeof(*ris), GFP_KERNEL);
334 	if (!ris)
335 		return -ENOMEM;
336 	init_garbage(&ris->garbage);
337 	ris->garbage.pdev = pdev;
338 
339 	class = mpam_class_find(class_id, type);
340 	if (IS_ERR(class))
341 		return PTR_ERR(class);
342 
343 	comp = mpam_component_find(class, component_id);
344 	if (IS_ERR(comp)) {
345 		if (list_empty(&class->components))
346 			mpam_class_destroy(class);
347 		return PTR_ERR(comp);
348 	}
349 
350 	vmsc = mpam_vmsc_find(comp, msc);
351 	if (IS_ERR(vmsc)) {
352 		if (list_empty(&comp->vmsc))
353 			mpam_component_destroy(comp);
354 		return PTR_ERR(vmsc);
355 	}
356 
357 	err = mpam_ris_get_affinity(msc, &ris->affinity, type, class, comp);
358 	if (err) {
359 		if (list_empty(&vmsc->ris))
360 			mpam_vmsc_destroy(vmsc);
361 		return err;
362 	}
363 
364 	ris->ris_idx = ris_idx;
365 	INIT_LIST_HEAD_RCU(&ris->msc_list);
366 	INIT_LIST_HEAD_RCU(&ris->vmsc_list);
367 	ris->vmsc = vmsc;
368 
369 	cpumask_or(&comp->affinity, &comp->affinity, &ris->affinity);
370 	cpumask_or(&class->affinity, &class->affinity, &ris->affinity);
371 	list_add_rcu(&ris->vmsc_list, &vmsc->ris);
372 	list_add_rcu(&ris->msc_list, &msc->ris);
373 
374 	return 0;
375 }
376 
377 static void mpam_ris_destroy(struct mpam_msc_ris *ris)
378 {
379 	struct mpam_vmsc *vmsc = ris->vmsc;
380 	struct mpam_msc *msc = vmsc->msc;
381 	struct mpam_component *comp = vmsc->comp;
382 	struct mpam_class *class = comp->class;
383 
384 	lockdep_assert_held(&mpam_list_lock);
385 
386 	/*
387 	 * It is assumed affinities don't overlap. If they do the class becomes
388 	 * unusable immediately.
389 	 */
390 	cpumask_andnot(&class->affinity, &class->affinity, &ris->affinity);
391 	cpumask_andnot(&comp->affinity, &comp->affinity, &ris->affinity);
392 	clear_bit(ris->ris_idx, &msc->ris_idxs);
393 	list_del_rcu(&ris->msc_list);
394 	list_del_rcu(&ris->vmsc_list);
395 	add_to_garbage(ris);
396 
397 	if (list_empty(&vmsc->ris))
398 		mpam_vmsc_destroy(vmsc);
399 }
400 
401 int mpam_ris_create(struct mpam_msc *msc, u8 ris_idx,
402 		    enum mpam_class_types type, u8 class_id, int component_id)
403 {
404 	int err;
405 
406 	mutex_lock(&mpam_list_lock);
407 	err = mpam_ris_create_locked(msc, ris_idx, type, class_id,
408 				     component_id);
409 	mutex_unlock(&mpam_list_lock);
410 	if (err)
411 		mpam_free_garbage();
412 
413 	return err;
414 }
415 
416 /*
417  * An MSC can control traffic from a set of CPUs, but may only be accessible
418  * from a (hopefully wider) set of CPUs. The common reason for this is power
419  * management. If all the CPUs in a cluster are in PSCI:CPU_SUSPEND, the
420  * corresponding cache may also be powered off. By making accesses from
421  * one of those CPUs, we ensure we don't access a cache that's powered off.
422  */
423 static void update_msc_accessibility(struct mpam_msc *msc)
424 {
425 	u32 affinity_id;
426 	int err;
427 
428 	err = device_property_read_u32(&msc->pdev->dev, "cpu_affinity",
429 				       &affinity_id);
430 	if (err)
431 		cpumask_copy(&msc->accessibility, cpu_possible_mask);
432 	else
433 		acpi_pptt_get_cpus_from_container(affinity_id, &msc->accessibility);
434 }
435 
436 /*
437  * There are two ways of reaching a struct mpam_msc_ris. Via the
438  * class->component->vmsc->ris, or via the msc.
439  * When destroying the msc, the other side needs unlinking and cleaning up too.
440  */
441 static void mpam_msc_destroy(struct mpam_msc *msc)
442 {
443 	struct platform_device *pdev = msc->pdev;
444 	struct mpam_msc_ris *ris, *tmp;
445 
446 	lockdep_assert_held(&mpam_list_lock);
447 
448 	list_for_each_entry_safe(ris, tmp, &msc->ris, msc_list)
449 		mpam_ris_destroy(ris);
450 
451 	list_del_rcu(&msc->all_msc_list);
452 	platform_set_drvdata(pdev, NULL);
453 
454 	add_to_garbage(msc);
455 }
456 
457 static void mpam_msc_drv_remove(struct platform_device *pdev)
458 {
459 	struct mpam_msc *msc = platform_get_drvdata(pdev);
460 
461 	mutex_lock(&mpam_list_lock);
462 	mpam_msc_destroy(msc);
463 	mutex_unlock(&mpam_list_lock);
464 
465 	mpam_free_garbage();
466 }
467 
468 static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev)
469 {
470 	int err;
471 	u32 tmp;
472 	struct mpam_msc *msc;
473 	struct resource *msc_res;
474 	struct device *dev = &pdev->dev;
475 
476 	lockdep_assert_held(&mpam_list_lock);
477 
478 	msc = devm_kzalloc(&pdev->dev, sizeof(*msc), GFP_KERNEL);
479 	if (!msc)
480 		return ERR_PTR(-ENOMEM);
481 	init_garbage(&msc->garbage);
482 	msc->garbage.pdev = pdev;
483 
484 	err = devm_mutex_init(dev, &msc->probe_lock);
485 	if (err)
486 		return ERR_PTR(err);
487 
488 	err = devm_mutex_init(dev, &msc->part_sel_lock);
489 	if (err)
490 		return ERR_PTR(err);
491 
492 	msc->id = pdev->id;
493 	msc->pdev = pdev;
494 	INIT_LIST_HEAD_RCU(&msc->all_msc_list);
495 	INIT_LIST_HEAD_RCU(&msc->ris);
496 
497 	update_msc_accessibility(msc);
498 	if (cpumask_empty(&msc->accessibility)) {
499 		dev_err_once(dev, "MSC is not accessible from any CPU!");
500 		return ERR_PTR(-EINVAL);
501 	}
502 
503 	if (device_property_read_u32(&pdev->dev, "pcc-channel", &tmp))
504 		msc->iface = MPAM_IFACE_MMIO;
505 	else
506 		msc->iface = MPAM_IFACE_PCC;
507 
508 	if (msc->iface == MPAM_IFACE_MMIO) {
509 		void __iomem *io;
510 
511 		io = devm_platform_get_and_ioremap_resource(pdev, 0,
512 							    &msc_res);
513 		if (IS_ERR(io)) {
514 			dev_err_once(dev, "Failed to map MSC base address\n");
515 			return ERR_CAST(io);
516 		}
517 		msc->mapped_hwpage_sz = msc_res->end - msc_res->start;
518 		msc->mapped_hwpage = io;
519 	} else {
520 		return ERR_PTR(-EINVAL);
521 	}
522 
523 	list_add_rcu(&msc->all_msc_list, &mpam_all_msc);
524 	platform_set_drvdata(pdev, msc);
525 
526 	return msc;
527 }
528 
529 static int fw_num_msc;
530 
531 static int mpam_msc_drv_probe(struct platform_device *pdev)
532 {
533 	int err;
534 	struct mpam_msc *msc = NULL;
535 	void *plat_data = pdev->dev.platform_data;
536 
537 	mutex_lock(&mpam_list_lock);
538 	msc = do_mpam_msc_drv_probe(pdev);
539 	mutex_unlock(&mpam_list_lock);
540 
541 	if (IS_ERR(msc))
542 		return PTR_ERR(msc);
543 
544 	/* Create RIS entries described by firmware */
545 	err = acpi_mpam_parse_resources(msc, plat_data);
546 	if (err) {
547 		mpam_msc_drv_remove(pdev);
548 		return err;
549 	}
550 
551 	if (atomic_add_return(1, &mpam_num_msc) == fw_num_msc)
552 		pr_info("Discovered all MSCs\n");
553 
554 	return 0;
555 }
556 
557 static struct platform_driver mpam_msc_driver = {
558 	.driver = {
559 		.name = "mpam_msc",
560 	},
561 	.probe = mpam_msc_drv_probe,
562 	.remove = mpam_msc_drv_remove,
563 };
564 
565 static int __init mpam_msc_driver_init(void)
566 {
567 	if (!system_supports_mpam())
568 		return -EOPNOTSUPP;
569 
570 	init_srcu_struct(&mpam_srcu);
571 
572 	fw_num_msc = acpi_mpam_count_msc();
573 	if (fw_num_msc <= 0) {
574 		pr_err("No MSC devices found in firmware\n");
575 		return -EINVAL;
576 	}
577 
578 	return platform_driver_register(&mpam_msc_driver);
579 }
580 subsys_initcall(mpam_msc_driver_init);
581