| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- // SPDX-License-Identifier: GPL-2.0
- // Copyright (C) 2025 Arm Ltd.
- /* This file is intended to be included into mpam_devices.c */
- #include <kunit/test.h>
- /*
- * This test catches fields that aren't being sanitised - but can't tell you
- * which one...
- */
- static void test__props_mismatch(struct kunit *test)
- {
- struct mpam_props parent = { 0 };
- struct mpam_props child;
- memset(&child, 0xff, sizeof(child));
- __props_mismatch(&parent, &child, false);
- memset(&child, 0, sizeof(child));
- KUNIT_EXPECT_EQ(test, memcmp(&parent, &child, sizeof(child)), 0);
- memset(&child, 0xff, sizeof(child));
- __props_mismatch(&parent, &child, true);
- KUNIT_EXPECT_EQ(test, memcmp(&parent, &child, sizeof(child)), 0);
- }
- static struct list_head fake_classes_list;
- static struct mpam_class fake_class = { 0 };
- static struct mpam_component fake_comp1 = { 0 };
- static struct mpam_component fake_comp2 = { 0 };
- static struct mpam_vmsc fake_vmsc1 = { 0 };
- static struct mpam_vmsc fake_vmsc2 = { 0 };
- static struct mpam_msc fake_msc1 = { 0 };
- static struct mpam_msc fake_msc2 = { 0 };
- static struct mpam_msc_ris fake_ris1 = { 0 };
- static struct mpam_msc_ris fake_ris2 = { 0 };
- static struct platform_device fake_pdev = { 0 };
- static inline void reset_fake_hierarchy(void)
- {
- INIT_LIST_HEAD(&fake_classes_list);
- memset(&fake_class, 0, sizeof(fake_class));
- fake_class.level = 3;
- fake_class.type = MPAM_CLASS_CACHE;
- INIT_LIST_HEAD_RCU(&fake_class.components);
- INIT_LIST_HEAD(&fake_class.classes_list);
- memset(&fake_comp1, 0, sizeof(fake_comp1));
- memset(&fake_comp2, 0, sizeof(fake_comp2));
- fake_comp1.comp_id = 1;
- fake_comp2.comp_id = 2;
- INIT_LIST_HEAD(&fake_comp1.vmsc);
- INIT_LIST_HEAD(&fake_comp1.class_list);
- INIT_LIST_HEAD(&fake_comp2.vmsc);
- INIT_LIST_HEAD(&fake_comp2.class_list);
- memset(&fake_vmsc1, 0, sizeof(fake_vmsc1));
- memset(&fake_vmsc2, 0, sizeof(fake_vmsc2));
- INIT_LIST_HEAD(&fake_vmsc1.ris);
- INIT_LIST_HEAD(&fake_vmsc1.comp_list);
- fake_vmsc1.msc = &fake_msc1;
- INIT_LIST_HEAD(&fake_vmsc2.ris);
- INIT_LIST_HEAD(&fake_vmsc2.comp_list);
- fake_vmsc2.msc = &fake_msc2;
- memset(&fake_ris1, 0, sizeof(fake_ris1));
- memset(&fake_ris2, 0, sizeof(fake_ris2));
- fake_ris1.ris_idx = 1;
- INIT_LIST_HEAD(&fake_ris1.msc_list);
- fake_ris2.ris_idx = 2;
- INIT_LIST_HEAD(&fake_ris2.msc_list);
- fake_msc1.pdev = &fake_pdev;
- fake_msc2.pdev = &fake_pdev;
- list_add(&fake_class.classes_list, &fake_classes_list);
- }
- static void test_mpam_enable_merge_features(struct kunit *test)
- {
- reset_fake_hierarchy();
- mutex_lock(&mpam_list_lock);
- /* One Class+Comp, two RIS in one vMSC with common features */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = NULL;
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = NULL;
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc1;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc1.ris);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
- fake_ris1.props.cpbm_wd = 4;
- fake_ris2.props.cpbm_wd = 4;
- mpam_enable_merge_features(&fake_classes_list);
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
- reset_fake_hierarchy();
- /* One Class+Comp, two RIS in one vMSC with non-overlapping features */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = NULL;
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = NULL;
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc1;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc1.ris);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props);
- fake_ris1.props.cpbm_wd = 4;
- fake_ris2.props.cmax_wd = 4;
- mpam_enable_merge_features(&fake_classes_list);
- /* Multiple RIS within one MSC controlling the same resource can be mismatched */
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props));
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_vmsc1.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
- KUNIT_EXPECT_EQ(test, fake_vmsc1.props.cmax_wd, 4);
- KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 4);
- reset_fake_hierarchy();
- /* One Class+Comp, two MSC with overlapping features */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = NULL;
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = &fake_comp1;
- list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc2;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
- fake_ris1.props.cpbm_wd = 4;
- fake_ris2.props.cpbm_wd = 4;
- mpam_enable_merge_features(&fake_classes_list);
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
- reset_fake_hierarchy();
- /* One Class+Comp, two MSC with non-overlapping features */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = NULL;
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = &fake_comp1;
- list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc2;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props);
- fake_ris1.props.cpbm_wd = 4;
- fake_ris2.props.cmax_wd = 4;
- mpam_enable_merge_features(&fake_classes_list);
- /*
- * Multiple RIS in different MSC can't control the same resource,
- * mismatched features can not be supported.
- */
- KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
- KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0);
- KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 0);
- reset_fake_hierarchy();
- /* One Class+Comp, two MSC with incompatible overlapping features */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = NULL;
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = &fake_comp1;
- list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc2;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
- mpam_set_feature(mpam_feat_mbw_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_mbw_part, &fake_ris2.props);
- fake_ris1.props.cpbm_wd = 5;
- fake_ris2.props.cpbm_wd = 3;
- fake_ris1.props.mbw_pbm_bits = 5;
- fake_ris2.props.mbw_pbm_bits = 3;
- mpam_enable_merge_features(&fake_classes_list);
- /*
- * Multiple RIS in different MSC can't control the same resource,
- * mismatched features can not be supported.
- */
- KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
- KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_mbw_part, &fake_class.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0);
- KUNIT_EXPECT_EQ(test, fake_class.props.mbw_pbm_bits, 0);
- reset_fake_hierarchy();
- /* One Class+Comp, two MSC with overlapping features that need tweaking */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = NULL;
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = &fake_comp1;
- list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc);
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc2;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
- mpam_set_feature(mpam_feat_mbw_min, &fake_ris1.props);
- mpam_set_feature(mpam_feat_mbw_min, &fake_ris2.props);
- mpam_set_feature(mpam_feat_cmax_cmax, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cmax_cmax, &fake_ris2.props);
- fake_ris1.props.bwa_wd = 5;
- fake_ris2.props.bwa_wd = 3;
- fake_ris1.props.cmax_wd = 5;
- fake_ris2.props.cmax_wd = 3;
- mpam_enable_merge_features(&fake_classes_list);
- /*
- * RIS with different control properties need to be sanitised so the
- * class has the common set of properties.
- */
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_class.props));
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmax, &fake_class.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.bwa_wd, 3);
- KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 3);
- reset_fake_hierarchy();
- /* One Class Two Comp with overlapping features */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = &fake_class;
- list_add(&fake_comp2.class_list, &fake_class.components);
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = &fake_comp2;
- list_add(&fake_vmsc2.comp_list, &fake_comp2.vmsc);
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc2;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props);
- fake_ris1.props.cpbm_wd = 4;
- fake_ris2.props.cpbm_wd = 4;
- mpam_enable_merge_features(&fake_classes_list);
- KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4);
- reset_fake_hierarchy();
- /* One Class Two Comp with non-overlapping features */
- fake_comp1.class = &fake_class;
- list_add(&fake_comp1.class_list, &fake_class.components);
- fake_comp2.class = &fake_class;
- list_add(&fake_comp2.class_list, &fake_class.components);
- fake_vmsc1.comp = &fake_comp1;
- list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc);
- fake_vmsc2.comp = &fake_comp2;
- list_add(&fake_vmsc2.comp_list, &fake_comp2.vmsc);
- fake_ris1.vmsc = &fake_vmsc1;
- list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris);
- fake_ris2.vmsc = &fake_vmsc2;
- list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris);
- mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props);
- mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props);
- fake_ris1.props.cpbm_wd = 4;
- fake_ris2.props.cmax_wd = 4;
- mpam_enable_merge_features(&fake_classes_list);
- /*
- * Multiple components can't control the same resource, mismatched features can
- * not be supported.
- */
- KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props));
- KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props));
- KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0);
- KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 0);
- mutex_unlock(&mpam_list_lock);
- }
- static void __test_mpam_reset_msc_bitmap(struct mpam_msc *msc, u16 reg, u16 wd)
- {
- /* Avoid warnings when running with CONFIG_DEBUG_PREEMPT */
- guard(preempt)();
- mpam_reset_msc_bitmap(msc, reg, wd);
- }
- static void test_mpam_reset_msc_bitmap(struct kunit *test)
- {
- char __iomem *buf = (__force char __iomem *)kunit_kzalloc(test, SZ_16K, GFP_KERNEL);
- struct mpam_msc fake_msc = {};
- u32 *test_result;
- if (!buf)
- return;
- fake_msc.mapped_hwpage = buf;
- fake_msc.mapped_hwpage_sz = SZ_16K;
- cpumask_copy(&fake_msc.accessibility, cpu_possible_mask);
- /* Satisfy lockdep checks */
- mutex_init(&fake_msc.part_sel_lock);
- mutex_lock(&fake_msc.part_sel_lock);
- test_result = (__force u32 *)(buf + MPAMCFG_CPBM);
- __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 0);
- KUNIT_EXPECT_EQ(test, test_result[0], 0);
- KUNIT_EXPECT_EQ(test, test_result[1], 0);
- test_result[0] = 0;
- test_result[1] = 0;
- __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 1);
- KUNIT_EXPECT_EQ(test, test_result[0], 1);
- KUNIT_EXPECT_EQ(test, test_result[1], 0);
- test_result[0] = 0;
- test_result[1] = 0;
- __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 16);
- KUNIT_EXPECT_EQ(test, test_result[0], 0xffff);
- KUNIT_EXPECT_EQ(test, test_result[1], 0);
- test_result[0] = 0;
- test_result[1] = 0;
- __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 32);
- KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff);
- KUNIT_EXPECT_EQ(test, test_result[1], 0);
- test_result[0] = 0;
- test_result[1] = 0;
- __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 33);
- KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff);
- KUNIT_EXPECT_EQ(test, test_result[1], 1);
- test_result[0] = 0;
- test_result[1] = 0;
- mutex_unlock(&fake_msc.part_sel_lock);
- }
- static struct kunit_case mpam_devices_test_cases[] = {
- KUNIT_CASE(test_mpam_reset_msc_bitmap),
- KUNIT_CASE(test_mpam_enable_merge_features),
- KUNIT_CASE(test__props_mismatch),
- {}
- };
- static struct kunit_suite mpam_devices_test_suite = {
- .name = "mpam_devices_test_suite",
- .test_cases = mpam_devices_test_cases,
- };
- kunit_test_suites(&mpam_devices_test_suite);
|