FILE
arm-smmu-v3-test.c
File preview with syntax highlighting.
linux-6.19.14/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright 2024 Google LLC. 4 */ 5#include <kunit/test.h> 6#include <linux/io-pgtable.h> 7 8#include "arm-smmu-v3.h" 9 10struct arm_smmu_test_writer { 11 struct arm_smmu_entry_writer writer; 12 struct kunit *test; 13 const __le64 *init_entry; 14 const __le64 *target_entry; 15 __le64 *entry; 16 17 bool invalid_entry_written; 18 unsigned int num_syncs; 19}; 20 21#define NUM_ENTRY_QWORDS 8 22#define NUM_EXPECTED_SYNCS(x) x 23 24static struct arm_smmu_ste bypass_ste; 25static struct arm_smmu_ste abort_ste; 26static struct arm_smmu_device smmu = { 27 .features = ARM_SMMU_FEAT_STALLS | ARM_SMMU_FEAT_ATTR_TYPES_OVR 28}; 29static struct mm_struct sva_mm = { 30 .pgd = (void *)0xdaedbeefdeadbeefULL, 31}; 32 33enum arm_smmu_test_master_feat { 34 ARM_SMMU_MASTER_TEST_ATS = BIT(0), 35 ARM_SMMU_MASTER_TEST_STALL = BIT(1), 36}; 37 38static bool arm_smmu_entry_differs_in_used_bits(const __le64 *entry, 39 const __le64 *used_bits, 40 const __le64 *target, 41 const __le64 *safe, 42 unsigned int length) 43{ 44 bool differs = false; 45 unsigned int i; 46 47 for (i = 0; i < length; i++) { 48 __le64 used = used_bits[i] & ~safe[i]; 49 50 if ((entry[i] & used) != (target[i] & used)) 51 differs = true; 52 } 53 return differs; 54} 55 56static void 57arm_smmu_test_writer_record_syncs(struct arm_smmu_entry_writer *writer) 58{ 59 struct arm_smmu_test_writer *test_writer = 60 container_of(writer, struct arm_smmu_test_writer, writer); 61 __le64 *entry_used_bits; 62 __le64 *safe_target; 63 __le64 *safe_init; 64 65 entry_used_bits = kunit_kzalloc( 66 test_writer->test, sizeof(*entry_used_bits) * NUM_ENTRY_QWORDS, 67 GFP_KERNEL); 68 KUNIT_ASSERT_NOT_NULL(test_writer->test, entry_used_bits); 69 70 safe_target = kunit_kzalloc(test_writer->test, 71 sizeof(*safe_target) * NUM_ENTRY_QWORDS, 72 GFP_KERNEL); 73 KUNIT_ASSERT_NOT_NULL(test_writer->test, safe_target); 74 75 safe_init = kunit_kzalloc(test_writer->test, 76 sizeof(*safe_init) * NUM_ENTRY_QWORDS, 77 GFP_KERNEL); 78 KUNIT_ASSERT_NOT_NULL(test_writer->test, safe_init); 79 80 pr_debug("STE value is now set to: "); 81 print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 16, 8, 82 test_writer->entry, 83 NUM_ENTRY_QWORDS * sizeof(*test_writer->entry), 84 false); 85 86 test_writer->num_syncs += 1; 87 if (!test_writer->entry[0]) { 88 test_writer->invalid_entry_written = true; 89 } else { 90 /* 91 * At any stage in a hitless transition, the entry must be 92 * equivalent to either the initial entry or the target entry 93 * when only considering the bits used by the current 94 * configuration. 95 */ 96 writer->ops->get_used(test_writer->entry, entry_used_bits); 97 if (writer->ops->get_update_safe) 98 writer->ops->get_update_safe(test_writer->entry, 99 test_writer->init_entry, 100 safe_init); 101 if (writer->ops->get_update_safe) 102 writer->ops->get_update_safe(test_writer->entry, 103 test_writer->target_entry, 104 safe_target); 105 KUNIT_EXPECT_FALSE( 106 test_writer->test, 107 arm_smmu_entry_differs_in_used_bits( 108 test_writer->entry, entry_used_bits, 109 test_writer->init_entry, safe_init, 110 NUM_ENTRY_QWORDS) && 111 arm_smmu_entry_differs_in_used_bits( 112 test_writer->entry, entry_used_bits, 113 test_writer->target_entry, safe_target, 114 NUM_ENTRY_QWORDS)); 115 } 116} 117 118static void 119arm_smmu_v3_test_debug_print_used_bits(struct arm_smmu_entry_writer *writer, 120 const __le64 *ste) 121{ 122 __le64 used_bits[NUM_ENTRY_QWORDS] = {}; 123 124 arm_smmu_get_ste_used(ste, used_bits); 125 pr_debug("STE used bits: "); 126 print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 16, 8, used_bits, 127 sizeof(used_bits), false); 128} 129 130static const struct arm_smmu_entry_writer_ops test_ste_ops = { 131 .sync = arm_smmu_test_writer_record_syncs, 132 .get_used = arm_smmu_get_ste_used, 133 .get_update_safe = arm_smmu_get_ste_update_safe, 134}; 135 136static const struct arm_smmu_entry_writer_ops test_cd_ops = { 137 .sync = arm_smmu_test_writer_record_syncs, 138 .get_used = arm_smmu_get_cd_used, 139}; 140 141static void arm_smmu_v3_test_ste_expect_transition( 142 struct kunit *test, const struct arm_smmu_ste *cur, 143 const struct arm_smmu_ste *target, unsigned int num_syncs_expected, 144 bool hitless) 145{ 146 struct arm_smmu_ste cur_copy = *cur; 147 struct arm_smmu_test_writer test_writer = { 148 .writer = { 149 .ops = &test_ste_ops, 150 }, 151 .test = test, 152 .init_entry = cur->data, 153 .target_entry = target->data, 154 .entry = cur_copy.data, 155 .num_syncs = 0, 156 .invalid_entry_written = false, 157 158 }; 159 160 pr_debug("STE initial value: "); 161 print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 16, 8, cur_copy.data, 162 sizeof(cur_copy), false); 163 arm_smmu_v3_test_debug_print_used_bits(&test_writer.writer, cur->data); 164 pr_debug("STE target value: "); 165 print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 16, 8, target->data, 166 sizeof(cur_copy), false); 167 arm_smmu_v3_test_debug_print_used_bits(&test_writer.writer, 168 target->data); 169 170 arm_smmu_write_entry(&test_writer.writer, cur_copy.data, target->data); 171 172 KUNIT_EXPECT_EQ(test, test_writer.invalid_entry_written, !hitless); 173 KUNIT_EXPECT_EQ(test, test_writer.num_syncs, num_syncs_expected); 174 KUNIT_EXPECT_MEMEQ(test, target->data, cur_copy.data, sizeof(cur_copy)); 175} 176 177static void arm_smmu_v3_test_ste_expect_non_hitless_transition( 178 struct kunit *test, const struct arm_smmu_ste *cur, 179 const struct arm_smmu_ste *target, unsigned int num_syncs_expected) 180{ 181 arm_smmu_v3_test_ste_expect_transition(test, cur, target, 182 num_syncs_expected, false); 183} 184 185static void arm_smmu_v3_test_ste_expect_hitless_transition( 186 struct kunit *test, const struct arm_smmu_ste *cur, 187 const struct arm_smmu_ste *target, unsigned int num_syncs_expected) 188{ 189 arm_smmu_v3_test_ste_expect_transition(test, cur, target, 190 num_syncs_expected, true); 191} 192 193static const dma_addr_t fake_cdtab_dma_addr = 0xF0F0F0F0F0F0; 194 195static void arm_smmu_test_make_cdtable_ste(struct arm_smmu_ste *ste, 196 unsigned int s1dss, 197 const dma_addr_t dma_addr, 198 enum arm_smmu_test_master_feat feat) 199{ 200 bool ats_enabled = feat & ARM_SMMU_MASTER_TEST_ATS; 201 bool stall_enabled = feat & ARM_SMMU_MASTER_TEST_STALL; 202 203 struct arm_smmu_master master = { 204 .ats_enabled = ats_enabled, 205 .cd_table.cdtab_dma = dma_addr, 206 .cd_table.s1cdmax = 0xFF, 207 .cd_table.s1fmt = STRTAB_STE_0_S1FMT_64K_L2, 208 .smmu = &smmu, 209 .stall_enabled = stall_enabled, 210 }; 211 212 arm_smmu_make_cdtable_ste(ste, &master, ats_enabled, s1dss); 213} 214 215static void arm_smmu_v3_write_ste_test_bypass_to_abort(struct kunit *test) 216{ 217 /* 218 * Bypass STEs has used bits in the first two Qwords, while abort STEs 219 * only have used bits in the first QWord. Transitioning from bypass to 220 * abort requires two syncs: the first to set the first qword and make 221 * the STE into an abort, the second to clean up the second qword. 222 */ 223 arm_smmu_v3_test_ste_expect_hitless_transition( 224 test, &bypass_ste, &abort_ste, NUM_EXPECTED_SYNCS(2)); 225} 226 227static void arm_smmu_v3_write_ste_test_abort_to_bypass(struct kunit *test) 228{ 229 /* 230 * Transitioning from abort to bypass also requires two syncs: the first 231 * to set the second qword data required by the bypass STE, and the 232 * second to set the first qword and switch to bypass. 233 */ 234 arm_smmu_v3_test_ste_expect_hitless_transition( 235 test, &abort_ste, &bypass_ste, NUM_EXPECTED_SYNCS(2)); 236} 237 238static void arm_smmu_v3_write_ste_test_cdtable_to_abort(struct kunit *test) 239{ 240 struct arm_smmu_ste ste; 241 242 arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0, 243 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 244 arm_smmu_v3_test_ste_expect_hitless_transition(test, &ste, &abort_ste, 245 NUM_EXPECTED_SYNCS(2)); 246} 247 248static void arm_smmu_v3_write_ste_test_abort_to_cdtable(struct kunit *test) 249{ 250 struct arm_smmu_ste ste; 251 252 arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0, 253 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 254 arm_smmu_v3_test_ste_expect_hitless_transition(test, &abort_ste, &ste, 255 NUM_EXPECTED_SYNCS(2)); 256} 257 258static void arm_smmu_v3_write_ste_test_cdtable_to_bypass(struct kunit *test) 259{ 260 struct arm_smmu_ste ste; 261 262 arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0, 263 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 264 arm_smmu_v3_test_ste_expect_hitless_transition(test, &ste, &bypass_ste, 265 NUM_EXPECTED_SYNCS(3)); 266} 267 268static void arm_smmu_v3_write_ste_test_bypass_to_cdtable(struct kunit *test) 269{ 270 struct arm_smmu_ste ste; 271 272 arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0, 273 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 274 arm_smmu_v3_test_ste_expect_hitless_transition(test, &bypass_ste, &ste, 275 NUM_EXPECTED_SYNCS(3)); 276} 277 278static void arm_smmu_v3_write_ste_test_cdtable_s1dss_change(struct kunit *test) 279{ 280 struct arm_smmu_ste ste; 281 struct arm_smmu_ste s1dss_bypass; 282 283 arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0, 284 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 285 arm_smmu_test_make_cdtable_ste(&s1dss_bypass, STRTAB_STE_1_S1DSS_BYPASS, 286 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 287 288 /* 289 * Flipping s1dss on a CD table STE only involves changes to the second 290 * qword of an STE and can be done in a single write. 291 */ 292 arm_smmu_v3_test_ste_expect_hitless_transition( 293 test, &ste, &s1dss_bypass, NUM_EXPECTED_SYNCS(1)); 294 arm_smmu_v3_test_ste_expect_hitless_transition( 295 test, &s1dss_bypass, &ste, NUM_EXPECTED_SYNCS(1)); 296} 297 298static void 299arm_smmu_v3_write_ste_test_s1dssbypass_to_stebypass(struct kunit *test) 300{ 301 struct arm_smmu_ste s1dss_bypass; 302 303 arm_smmu_test_make_cdtable_ste(&s1dss_bypass, STRTAB_STE_1_S1DSS_BYPASS, 304 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 305 arm_smmu_v3_test_ste_expect_hitless_transition( 306 test, &s1dss_bypass, &bypass_ste, NUM_EXPECTED_SYNCS(2)); 307} 308 309static void 310arm_smmu_v3_write_ste_test_stebypass_to_s1dssbypass(struct kunit *test) 311{ 312 struct arm_smmu_ste s1dss_bypass; 313 314 arm_smmu_test_make_cdtable_ste(&s1dss_bypass, STRTAB_STE_1_S1DSS_BYPASS, 315 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 316 arm_smmu_v3_test_ste_expect_hitless_transition( 317 test, &bypass_ste, &s1dss_bypass, NUM_EXPECTED_SYNCS(2)); 318} 319 320static void arm_smmu_test_make_s2_ste(struct arm_smmu_ste *ste, 321 enum arm_smmu_test_master_feat feat) 322{ 323 bool ats_enabled = feat & ARM_SMMU_MASTER_TEST_ATS; 324 bool stall_enabled = feat & ARM_SMMU_MASTER_TEST_STALL; 325 struct arm_smmu_master master = { 326 .ats_enabled = ats_enabled, 327 .smmu = &smmu, 328 .stall_enabled = stall_enabled, 329 }; 330 struct io_pgtable io_pgtable = {}; 331 struct arm_smmu_domain smmu_domain = { 332 .pgtbl_ops = &io_pgtable.ops, 333 }; 334 335 io_pgtable.cfg.arm_lpae_s2_cfg.vttbr = 0xdaedbeefdeadbeefULL; 336 io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.ps = 1; 337 io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.tg = 2; 338 io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.sh = 3; 339 io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.orgn = 1; 340 io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.irgn = 2; 341 io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.sl = 3; 342 io_pgtable.cfg.arm_lpae_s2_cfg.vtcr.tsz = 4; 343 344 arm_smmu_make_s2_domain_ste(ste, &master, &smmu_domain, ats_enabled); 345} 346 347static void arm_smmu_v3_write_ste_test_s2_to_abort(struct kunit *test) 348{ 349 struct arm_smmu_ste ste; 350 351 arm_smmu_test_make_s2_ste(&ste, ARM_SMMU_MASTER_TEST_ATS); 352 arm_smmu_v3_test_ste_expect_hitless_transition(test, &ste, &abort_ste, 353 NUM_EXPECTED_SYNCS(2)); 354} 355 356static void arm_smmu_v3_write_ste_test_abort_to_s2(struct kunit *test) 357{ 358 struct arm_smmu_ste ste; 359 360 arm_smmu_test_make_s2_ste(&ste, ARM_SMMU_MASTER_TEST_ATS); 361 arm_smmu_v3_test_ste_expect_hitless_transition(test, &abort_ste, &ste, 362 NUM_EXPECTED_SYNCS(2)); 363} 364 365static void arm_smmu_v3_write_ste_test_s2_to_bypass(struct kunit *test) 366{ 367 struct arm_smmu_ste ste; 368 369 arm_smmu_test_make_s2_ste(&ste, ARM_SMMU_MASTER_TEST_ATS); 370 arm_smmu_v3_test_ste_expect_hitless_transition(test, &ste, &bypass_ste, 371 NUM_EXPECTED_SYNCS(2)); 372} 373 374static void arm_smmu_v3_write_ste_test_bypass_to_s2(struct kunit *test) 375{ 376 struct arm_smmu_ste ste; 377 378 arm_smmu_test_make_s2_ste(&ste, ARM_SMMU_MASTER_TEST_ATS); 379 arm_smmu_v3_test_ste_expect_hitless_transition(test, &bypass_ste, &ste, 380 NUM_EXPECTED_SYNCS(2)); 381} 382 383static void arm_smmu_v3_write_ste_test_s1_to_s2(struct kunit *test) 384{ 385 struct arm_smmu_ste s1_ste; 386 struct arm_smmu_ste s2_ste; 387 388 arm_smmu_test_make_cdtable_ste(&s1_ste, STRTAB_STE_1_S1DSS_SSID0, 389 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 390 arm_smmu_test_make_s2_ste(&s2_ste, ARM_SMMU_MASTER_TEST_ATS); 391 arm_smmu_v3_test_ste_expect_hitless_transition(test, &s1_ste, &s2_ste, 392 NUM_EXPECTED_SYNCS(3)); 393} 394 395static void arm_smmu_v3_write_ste_test_s2_to_s1(struct kunit *test) 396{ 397 struct arm_smmu_ste s1_ste; 398 struct arm_smmu_ste s2_ste; 399 400 arm_smmu_test_make_cdtable_ste(&s1_ste, STRTAB_STE_1_S1DSS_SSID0, 401 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 402 arm_smmu_test_make_s2_ste(&s2_ste, ARM_SMMU_MASTER_TEST_ATS); 403 arm_smmu_v3_test_ste_expect_hitless_transition(test, &s2_ste, &s1_ste, 404 NUM_EXPECTED_SYNCS(3)); 405} 406 407static void arm_smmu_v3_write_ste_test_non_hitless(struct kunit *test) 408{ 409 struct arm_smmu_ste ste; 410 struct arm_smmu_ste ste_2; 411 412 /* 413 * Although no flow resembles this in practice, one way to force an STE 414 * update to be non-hitless is to change its CD table pointer as well as 415 * s1 dss field in the same update. 416 */ 417 arm_smmu_test_make_cdtable_ste(&ste, STRTAB_STE_1_S1DSS_SSID0, 418 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_ATS); 419 arm_smmu_test_make_cdtable_ste(&ste_2, STRTAB_STE_1_S1DSS_BYPASS, 420 0x4B4B4b4B4B, ARM_SMMU_MASTER_TEST_ATS); 421 arm_smmu_v3_test_ste_expect_non_hitless_transition( 422 test, &ste, &ste_2, NUM_EXPECTED_SYNCS(3)); 423} 424 425static void arm_smmu_v3_test_cd_expect_transition( 426 struct kunit *test, const struct arm_smmu_cd *cur, 427 const struct arm_smmu_cd *target, unsigned int num_syncs_expected, 428 bool hitless) 429{ 430 struct arm_smmu_cd cur_copy = *cur; 431 struct arm_smmu_test_writer test_writer = { 432 .writer = { 433 .ops = &test_cd_ops, 434 }, 435 .test = test, 436 .init_entry = cur->data, 437 .target_entry = target->data, 438 .entry = cur_copy.data, 439 .num_syncs = 0, 440 .invalid_entry_written = false, 441 442 }; 443 444 pr_debug("CD initial value: "); 445 print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 16, 8, cur_copy.data, 446 sizeof(cur_copy), false); 447 arm_smmu_v3_test_debug_print_used_bits(&test_writer.writer, cur->data); 448 pr_debug("CD target value: "); 449 print_hex_dump_debug(" ", DUMP_PREFIX_NONE, 16, 8, target->data, 450 sizeof(cur_copy), false); 451 arm_smmu_v3_test_debug_print_used_bits(&test_writer.writer, 452 target->data); 453 454 arm_smmu_write_entry(&test_writer.writer, cur_copy.data, target->data); 455 456 KUNIT_EXPECT_EQ(test, test_writer.invalid_entry_written, !hitless); 457 KUNIT_EXPECT_EQ(test, test_writer.num_syncs, num_syncs_expected); 458 KUNIT_EXPECT_MEMEQ(test, target->data, cur_copy.data, sizeof(cur_copy)); 459} 460 461static void arm_smmu_v3_test_cd_expect_non_hitless_transition( 462 struct kunit *test, const struct arm_smmu_cd *cur, 463 const struct arm_smmu_cd *target, unsigned int num_syncs_expected) 464{ 465 arm_smmu_v3_test_cd_expect_transition(test, cur, target, 466 num_syncs_expected, false); 467} 468 469static void arm_smmu_v3_test_cd_expect_hitless_transition( 470 struct kunit *test, const struct arm_smmu_cd *cur, 471 const struct arm_smmu_cd *target, unsigned int num_syncs_expected) 472{ 473 arm_smmu_v3_test_cd_expect_transition(test, cur, target, 474 num_syncs_expected, true); 475} 476 477static void arm_smmu_test_make_s1_cd(struct arm_smmu_cd *cd, unsigned int asid) 478{ 479 struct arm_smmu_master master = { 480 .smmu = &smmu, 481 }; 482 struct io_pgtable io_pgtable = {}; 483 struct arm_smmu_domain smmu_domain = { 484 .pgtbl_ops = &io_pgtable.ops, 485 .cd = { 486 .asid = asid, 487 }, 488 }; 489 490 io_pgtable.cfg.arm_lpae_s1_cfg.ttbr = 0xdaedbeefdeadbeefULL; 491 io_pgtable.cfg.arm_lpae_s1_cfg.tcr.ips = 1; 492 io_pgtable.cfg.arm_lpae_s1_cfg.tcr.tg = 2; 493 io_pgtable.cfg.arm_lpae_s1_cfg.tcr.sh = 3; 494 io_pgtable.cfg.arm_lpae_s1_cfg.tcr.orgn = 1; 495 io_pgtable.cfg.arm_lpae_s1_cfg.tcr.irgn = 2; 496 io_pgtable.cfg.arm_lpae_s1_cfg.tcr.tsz = 4; 497 io_pgtable.cfg.arm_lpae_s1_cfg.mair = 0xabcdef012345678ULL; 498 499 arm_smmu_make_s1_cd(cd, &master, &smmu_domain); 500} 501 502static void arm_smmu_v3_write_cd_test_s1_clear(struct kunit *test) 503{ 504 struct arm_smmu_cd cd = {}; 505 struct arm_smmu_cd cd_2; 506 507 arm_smmu_test_make_s1_cd(&cd_2, 1997); 508 arm_smmu_v3_test_cd_expect_non_hitless_transition( 509 test, &cd, &cd_2, NUM_EXPECTED_SYNCS(2)); 510 arm_smmu_v3_test_cd_expect_non_hitless_transition( 511 test, &cd_2, &cd, NUM_EXPECTED_SYNCS(2)); 512} 513 514static void arm_smmu_v3_write_cd_test_s1_change_asid(struct kunit *test) 515{ 516 struct arm_smmu_cd cd = {}; 517 struct arm_smmu_cd cd_2; 518 519 arm_smmu_test_make_s1_cd(&cd, 778); 520 arm_smmu_test_make_s1_cd(&cd_2, 1997); 521 arm_smmu_v3_test_cd_expect_hitless_transition(test, &cd, &cd_2, 522 NUM_EXPECTED_SYNCS(1)); 523 arm_smmu_v3_test_cd_expect_hitless_transition(test, &cd_2, &cd, 524 NUM_EXPECTED_SYNCS(1)); 525} 526 527static void arm_smmu_test_make_sva_cd(struct arm_smmu_cd *cd, unsigned int asid) 528{ 529 struct arm_smmu_master master = { 530 .smmu = &smmu, 531 }; 532 533 arm_smmu_make_sva_cd(cd, &master, &sva_mm, asid); 534} 535 536static void arm_smmu_test_make_sva_release_cd(struct arm_smmu_cd *cd, 537 unsigned int asid) 538{ 539 struct arm_smmu_master master = { 540 .smmu = &smmu, 541 }; 542 543 arm_smmu_make_sva_cd(cd, &master, NULL, asid); 544} 545 546static void arm_smmu_v3_write_ste_test_s1_to_s2_stall(struct kunit *test) 547{ 548 struct arm_smmu_ste s1_ste; 549 struct arm_smmu_ste s2_ste; 550 551 arm_smmu_test_make_cdtable_ste(&s1_ste, STRTAB_STE_1_S1DSS_SSID0, 552 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_STALL); 553 arm_smmu_test_make_s2_ste(&s2_ste, ARM_SMMU_MASTER_TEST_STALL); 554 arm_smmu_v3_test_ste_expect_hitless_transition(test, &s1_ste, &s2_ste, 555 NUM_EXPECTED_SYNCS(3)); 556} 557 558static void arm_smmu_v3_write_ste_test_s2_to_s1_stall(struct kunit *test) 559{ 560 struct arm_smmu_ste s1_ste; 561 struct arm_smmu_ste s2_ste; 562 563 arm_smmu_test_make_cdtable_ste(&s1_ste, STRTAB_STE_1_S1DSS_SSID0, 564 fake_cdtab_dma_addr, ARM_SMMU_MASTER_TEST_STALL); 565 arm_smmu_test_make_s2_ste(&s2_ste, ARM_SMMU_MASTER_TEST_STALL); 566 arm_smmu_v3_test_ste_expect_hitless_transition(test, &s2_ste, &s1_ste, 567 NUM_EXPECTED_SYNCS(3)); 568} 569 570static void arm_smmu_v3_write_cd_test_sva_clear(struct kunit *test) 571{ 572 struct arm_smmu_cd cd = {}; 573 struct arm_smmu_cd cd_2; 574 575 arm_smmu_test_make_sva_cd(&cd_2, 1997); 576 arm_smmu_v3_test_cd_expect_non_hitless_transition( 577 test, &cd, &cd_2, NUM_EXPECTED_SYNCS(2)); 578 arm_smmu_v3_test_cd_expect_non_hitless_transition( 579 test, &cd_2, &cd, NUM_EXPECTED_SYNCS(2)); 580} 581 582static void arm_smmu_v3_write_cd_test_sva_release(struct kunit *test) 583{ 584 struct arm_smmu_cd cd; 585 struct arm_smmu_cd cd_2; 586 587 arm_smmu_test_make_sva_cd(&cd, 1997); 588 arm_smmu_test_make_sva_release_cd(&cd_2, 1997); 589 arm_smmu_v3_test_cd_expect_hitless_transition(test, &cd, &cd_2, 590 NUM_EXPECTED_SYNCS(2)); 591 arm_smmu_v3_test_cd_expect_hitless_transition(test, &cd_2, &cd, 592 NUM_EXPECTED_SYNCS(2)); 593} 594 595static struct kunit_case arm_smmu_v3_test_cases[] = { 596 KUNIT_CASE(arm_smmu_v3_write_ste_test_bypass_to_abort), 597 KUNIT_CASE(arm_smmu_v3_write_ste_test_abort_to_bypass), 598 KUNIT_CASE(arm_smmu_v3_write_ste_test_cdtable_to_abort), 599 KUNIT_CASE(arm_smmu_v3_write_ste_test_abort_to_cdtable), 600 KUNIT_CASE(arm_smmu_v3_write_ste_test_cdtable_to_bypass), 601 KUNIT_CASE(arm_smmu_v3_write_ste_test_bypass_to_cdtable), 602 KUNIT_CASE(arm_smmu_v3_write_ste_test_cdtable_s1dss_change), 603 KUNIT_CASE(arm_smmu_v3_write_ste_test_s1dssbypass_to_stebypass), 604 KUNIT_CASE(arm_smmu_v3_write_ste_test_stebypass_to_s1dssbypass), 605 KUNIT_CASE(arm_smmu_v3_write_ste_test_s2_to_abort), 606 KUNIT_CASE(arm_smmu_v3_write_ste_test_abort_to_s2), 607 KUNIT_CASE(arm_smmu_v3_write_ste_test_s2_to_bypass), 608 KUNIT_CASE(arm_smmu_v3_write_ste_test_bypass_to_s2), 609 KUNIT_CASE(arm_smmu_v3_write_ste_test_s1_to_s2), 610 KUNIT_CASE(arm_smmu_v3_write_ste_test_s2_to_s1), 611 KUNIT_CASE(arm_smmu_v3_write_ste_test_non_hitless), 612 KUNIT_CASE(arm_smmu_v3_write_cd_test_s1_clear), 613 KUNIT_CASE(arm_smmu_v3_write_cd_test_s1_change_asid), 614 KUNIT_CASE(arm_smmu_v3_write_ste_test_s1_to_s2_stall), 615 KUNIT_CASE(arm_smmu_v3_write_ste_test_s2_to_s1_stall), 616 KUNIT_CASE(arm_smmu_v3_write_cd_test_sva_clear), 617 KUNIT_CASE(arm_smmu_v3_write_cd_test_sva_release), 618 {}, 619}; 620 621static int arm_smmu_v3_test_suite_init(struct kunit_suite *test) 622{ 623 arm_smmu_make_bypass_ste(&smmu, &bypass_ste); 624 arm_smmu_make_abort_ste(&abort_ste); 625 return 0; 626} 627 628static struct kunit_suite arm_smmu_v3_test_module = { 629 .name = "arm-smmu-v3-kunit-test", 630 .suite_init = arm_smmu_v3_test_suite_init, 631 .test_cases = arm_smmu_v3_test_cases, 632}; 633kunit_test_suites(&arm_smmu_v3_test_module); 634 635MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 636MODULE_DESCRIPTION("KUnit tests for arm-smmu-v3 driver"); 637MODULE_LICENSE("GPL v2");
~/
Read-only file preview.