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