File Index
Files and directories
Sign in
FILE

test_mpam_devices.c

File preview with syntax highlighting.

linux-6.19.14/drivers/resctrl/test_mpam_devices.c C
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (C) 2025 Arm Ltd.
  3/* This file is intended to be included into mpam_devices.c */
  4
  5#include <kunit/test.h>
  6
  7/*
  8 * This test catches fields that aren't being sanitised - but can't tell you
  9 * which one...
 10 */
 11static void test__props_mismatch(struct kunit *test)
 12{
 13	struct mpam_props parent = { 0 };
 14	struct mpam_props child;
 15
 16	memset(&child, 0xff, sizeof(child));
 17	__props_mismatch(&parent, &child, false);
 18
 19	memset(&child, 0, sizeof(child));
 20	KUNIT_EXPECT_EQ(test, memcmp(&parent, &child, sizeof(child)), 0);
 21
 22	memset(&child, 0xff, sizeof(child));
 23	__props_mismatch(&parent, &child, true);
 24
 25	KUNIT_EXPECT_EQ(test, memcmp(&parent, &child, sizeof(child)), 0);
 26}
 27
 28static struct list_head fake_classes_list;
 29static struct mpam_class fake_class = { 0 };
 30static struct mpam_component fake_comp1 = { 0 };
 31static struct mpam_component fake_comp2 = { 0 };
 32static struct mpam_vmsc fake_vmsc1 = { 0 };
 33static struct mpam_vmsc fake_vmsc2 = { 0 };
 34static struct mpam_msc fake_msc1 = { 0 };
 35static struct mpam_msc fake_msc2 = { 0 };
 36static struct mpam_msc_ris fake_ris1 = { 0 };
 37static struct mpam_msc_ris fake_ris2 = { 0 };
 38static struct platform_device fake_pdev = { 0 };
 39
 40static inline void reset_fake_hierarchy(void)
 41{
 42	INIT_LIST_HEAD(&fake_classes_list);
 43
 44	memset(&fake_class, 0, sizeof(fake_class));
 45	fake_class.level = 3;
 46	fake_class.type = MPAM_CLASS_CACHE;
 47	INIT_LIST_HEAD_RCU(&fake_class.components);
 48	INIT_LIST_HEAD(&fake_class.classes_list);
 49
 50	memset(&fake_comp1, 0, sizeof(fake_comp1));
 51	memset(&fake_comp2, 0, sizeof(fake_comp2));
 52	fake_comp1.comp_id = 1;
 53	fake_comp2.comp_id = 2;
 54	INIT_LIST_HEAD(&fake_comp1.vmsc);
 55	INIT_LIST_HEAD(&fake_comp1.class_list);
 56	INIT_LIST_HEAD(&fake_comp2.vmsc);
 57	INIT_LIST_HEAD(&fake_comp2.class_list);
 58
 59	memset(&fake_vmsc1, 0, sizeof(fake_vmsc1));
 60	memset(&fake_vmsc2, 0, sizeof(fake_vmsc2));
 61	INIT_LIST_HEAD(&fake_vmsc1.ris);
 62	INIT_LIST_HEAD(&fake_vmsc1.comp_list);
 63	fake_vmsc1.msc = &fake_msc1;
 64	INIT_LIST_HEAD(&fake_vmsc2.ris);
 65	INIT_LIST_HEAD(&fake_vmsc2.comp_list);
 66	fake_vmsc2.msc = &fake_msc2;
 67
 68	memset(&fake_ris1, 0, sizeof(fake_ris1));
 69	memset(&fake_ris2, 0, sizeof(fake_ris2));
 70	fake_ris1.ris_idx = 1;
 71	INIT_LIST_HEAD(&fake_ris1.msc_list);
 72	fake_ris2.ris_idx = 2;
 73	INIT_LIST_HEAD(&fake_ris2.msc_list);
 74
 75	fake_msc1.pdev = &fake_pdev;
 76	fake_msc2.pdev = &fake_pdev;
 77
 78	list_add(&fake_class.classes_list, &fake_classes_list);
 79}
 80
 81static void test_mpam_enable_merge_features(struct kunit *test)
 82{
 83	reset_fake_hierarchy();
 84
 85	mutex_lock(&mpam_list_lock);
 86
 87	/* One Class+Comp, two RIS in one vMSC with common features */
 88	fake_comp1.class = &fake_class;
 89	list_add(&fake_comp1.class_list, &fake_class.components);
 90	fake_comp2.class = NULL;
 91	fake_vmsc1.comp = &fake_comp1;
 92	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
 93	fake_vmsc2.comp = NULL;
 94	fake_ris1.vmsc = &fake_vmsc1;
 95	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
 96	fake_ris2.vmsc = &fake_vmsc1;
 97	list_add(&fake_ris2.vmsc_list, &fake_vmsc1.ris);
 98
 99	mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
100	mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
101	fake_ris1.props.cpbm_wd = 4;
102	fake_ris2.props.cpbm_wd = 4;
103
104	mpam_enable_merge_features(&fake_classes_list);
105
106	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
107	KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
108
109	reset_fake_hierarchy();
110
111	/* One Class+Comp, two RIS in one vMSC with non-overlapping features */
112	fake_comp1.class = &fake_class;
113	list_add(&fake_comp1.class_list, &fake_class.components);
114	fake_comp2.class = NULL;
115	fake_vmsc1.comp = &fake_comp1;
116	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
117	fake_vmsc2.comp = NULL;
118	fake_ris1.vmsc = &fake_vmsc1;
119	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
120	fake_ris2.vmsc = &fake_vmsc1;
121	list_add(&fake_ris2.vmsc_list, &fake_vmsc1.ris);
122
123	mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
124	mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props);
125	fake_ris1.props.cpbm_wd = 4;
126	fake_ris2.props.cmax_wd = 4;
127
128	mpam_enable_merge_features(&fake_classes_list);
129
130	/* Multiple RIS within one MSC controlling the same resource can be mismatched */
131	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
132	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props));
133	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_vmsc1.props));
134	KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
135	KUNIT_EXPECT_EQ(test, fake_vmsc1.props.cmax_wd, 4);
136	KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 4);
137
138	reset_fake_hierarchy();
139
140	/* One Class+Comp, two MSC with overlapping features */
141	fake_comp1.class = &fake_class;
142	list_add(&fake_comp1.class_list, &fake_class.components);
143	fake_comp2.class = NULL;
144	fake_vmsc1.comp = &fake_comp1;
145	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
146	fake_vmsc2.comp = &fake_comp1;
147	list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
148	fake_ris1.vmsc = &fake_vmsc1;
149	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
150	fake_ris2.vmsc = &fake_vmsc2;
151	list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
152
153	mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
154	mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
155	fake_ris1.props.cpbm_wd = 4;
156	fake_ris2.props.cpbm_wd = 4;
157
158	mpam_enable_merge_features(&fake_classes_list);
159
160	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
161	KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
162
163	reset_fake_hierarchy();
164
165	/* One Class+Comp, two MSC with non-overlapping features */
166	fake_comp1.class = &fake_class;
167	list_add(&fake_comp1.class_list, &fake_class.components);
168	fake_comp2.class = NULL;
169	fake_vmsc1.comp = &fake_comp1;
170	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
171	fake_vmsc2.comp = &fake_comp1;
172	list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
173	fake_ris1.vmsc = &fake_vmsc1;
174	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
175	fake_ris2.vmsc = &fake_vmsc2;
176	list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
177
178	mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
179	mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props);
180	fake_ris1.props.cpbm_wd = 4;
181	fake_ris2.props.cmax_wd = 4;
182
183	mpam_enable_merge_features(&fake_classes_list);
184
185	/*
186	 * Multiple RIS in different MSC can't control the same resource,
187	 * mismatched features can not be supported.
188	 */
189	KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
190	KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props));
191	KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0);
192	KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 0);
193
194	reset_fake_hierarchy();
195
196	/* One Class+Comp, two MSC with incompatible overlapping features */
197	fake_comp1.class = &fake_class;
198	list_add(&fake_comp1.class_list, &fake_class.components);
199	fake_comp2.class = NULL;
200	fake_vmsc1.comp = &fake_comp1;
201	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
202	fake_vmsc2.comp = &fake_comp1;
203	list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
204	fake_ris1.vmsc = &fake_vmsc1;
205	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
206	fake_ris2.vmsc = &fake_vmsc2;
207	list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
208
209	mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
210	mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
211	mpam_set_feature(mpam_feat_mbw_part, &fake_ris1.props);
212	mpam_set_feature(mpam_feat_mbw_part, &fake_ris2.props);
213	fake_ris1.props.cpbm_wd = 5;
214	fake_ris2.props.cpbm_wd = 3;
215	fake_ris1.props.mbw_pbm_bits = 5;
216	fake_ris2.props.mbw_pbm_bits = 3;
217
218	mpam_enable_merge_features(&fake_classes_list);
219
220	/*
221	 * Multiple RIS in different MSC can't control the same resource,
222	 * mismatched features can not be supported.
223	 */
224	KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
225	KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_mbw_part, &fake_class.props));
226	KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0);
227	KUNIT_EXPECT_EQ(test, fake_class.props.mbw_pbm_bits, 0);
228
229	reset_fake_hierarchy();
230
231	/* One Class+Comp, two MSC with overlapping features that need tweaking */
232	fake_comp1.class = &fake_class;
233	list_add(&fake_comp1.class_list, &fake_class.components);
234	fake_comp2.class = NULL;
235	fake_vmsc1.comp = &fake_comp1;
236	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
237	fake_vmsc2.comp = &fake_comp1;
238	list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
239	fake_ris1.vmsc = &fake_vmsc1;
240	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
241	fake_ris2.vmsc = &fake_vmsc2;
242	list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
243
244	mpam_set_feature(mpam_feat_mbw_min, &fake_ris1.props);
245	mpam_set_feature(mpam_feat_mbw_min, &fake_ris2.props);
246	mpam_set_feature(mpam_feat_cmax_cmax, &fake_ris1.props);
247	mpam_set_feature(mpam_feat_cmax_cmax, &fake_ris2.props);
248	fake_ris1.props.bwa_wd = 5;
249	fake_ris2.props.bwa_wd = 3;
250	fake_ris1.props.cmax_wd = 5;
251	fake_ris2.props.cmax_wd = 3;
252
253	mpam_enable_merge_features(&fake_classes_list);
254
255	/*
256	 * RIS with different control properties need to be sanitised so the
257	 * class has the common set of properties.
258	 */
259	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_class.props));
260	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmax, &fake_class.props));
261	KUNIT_EXPECT_EQ(test, fake_class.props.bwa_wd, 3);
262	KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 3);
263
264	reset_fake_hierarchy();
265
266	/* One Class Two Comp with overlapping features */
267	fake_comp1.class = &fake_class;
268	list_add(&fake_comp1.class_list, &fake_class.components);
269	fake_comp2.class = &fake_class;
270	list_add(&fake_comp2.class_list, &fake_class.components);
271	fake_vmsc1.comp = &fake_comp1;
272	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
273	fake_vmsc2.comp = &fake_comp2;
274	list_add(&fake_vmsc2.comp_list, &fake_comp2.vmsc);
275	fake_ris1.vmsc = &fake_vmsc1;
276	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
277	fake_ris2.vmsc = &fake_vmsc2;
278	list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
279
280	mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
281	mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
282	fake_ris1.props.cpbm_wd = 4;
283	fake_ris2.props.cpbm_wd = 4;
284
285	mpam_enable_merge_features(&fake_classes_list);
286
287	KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
288	KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
289
290	reset_fake_hierarchy();
291
292	/* One Class Two Comp with non-overlapping features */
293	fake_comp1.class = &fake_class;
294	list_add(&fake_comp1.class_list, &fake_class.components);
295	fake_comp2.class = &fake_class;
296	list_add(&fake_comp2.class_list, &fake_class.components);
297	fake_vmsc1.comp = &fake_comp1;
298	list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
299	fake_vmsc2.comp = &fake_comp2;
300	list_add(&fake_vmsc2.comp_list, &fake_comp2.vmsc);
301	fake_ris1.vmsc = &fake_vmsc1;
302	list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
303	fake_ris2.vmsc = &fake_vmsc2;
304	list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
305
306	mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
307	mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props);
308	fake_ris1.props.cpbm_wd = 4;
309	fake_ris2.props.cmax_wd = 4;
310
311	mpam_enable_merge_features(&fake_classes_list);
312
313	/*
314	 * Multiple components can't control the same resource, mismatched features can
315	 * not be supported.
316	 */
317	KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
318	KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props));
319	KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0);
320	KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 0);
321
322	mutex_unlock(&mpam_list_lock);
323}
324
325static void test_mpam_reset_msc_bitmap(struct kunit *test)
326{
327	char __iomem *buf = kunit_kzalloc(test, SZ_16K, GFP_KERNEL);
328	struct mpam_msc fake_msc = {};
329	u32 *test_result;
330
331	if (!buf)
332		return;
333
334	fake_msc.mapped_hwpage = buf;
335	fake_msc.mapped_hwpage_sz = SZ_16K;
336	cpumask_copy(&fake_msc.accessibility, cpu_possible_mask);
337
338	/* Satisfy lockdep checks */
339	mutex_init(&fake_msc.part_sel_lock);
340	mutex_lock(&fake_msc.part_sel_lock);
341
342	test_result = (u32 *)(buf + MPAMCFG_CPBM);
343
344	mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 0);
345	KUNIT_EXPECT_EQ(test, test_result[0], 0);
346	KUNIT_EXPECT_EQ(test, test_result[1], 0);
347	test_result[0] = 0;
348	test_result[1] = 0;
349
350	mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 1);
351	KUNIT_EXPECT_EQ(test, test_result[0], 1);
352	KUNIT_EXPECT_EQ(test, test_result[1], 0);
353	test_result[0] = 0;
354	test_result[1] = 0;
355
356	mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 16);
357	KUNIT_EXPECT_EQ(test, test_result[0], 0xffff);
358	KUNIT_EXPECT_EQ(test, test_result[1], 0);
359	test_result[0] = 0;
360	test_result[1] = 0;
361
362	mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 32);
363	KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff);
364	KUNIT_EXPECT_EQ(test, test_result[1], 0);
365	test_result[0] = 0;
366	test_result[1] = 0;
367
368	mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 33);
369	KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff);
370	KUNIT_EXPECT_EQ(test, test_result[1], 1);
371	test_result[0] = 0;
372	test_result[1] = 0;
373
374	mutex_unlock(&fake_msc.part_sel_lock);
375}
376
377static struct kunit_case mpam_devices_test_cases[] = {
378	KUNIT_CASE(test_mpam_reset_msc_bitmap),
379	KUNIT_CASE(test_mpam_enable_merge_features),
380	KUNIT_CASE(test__props_mismatch),
381	{}
382};
383
384static struct kunit_suite mpam_devices_test_suite = {
385	.name = "mpam_devices_test_suite",
386	.test_cases = mpam_devices_test_cases,
387};
388
389kunit_test_suites(&mpam_devices_test_suite);
~/ Read-only file preview.