File Index
Files and directories
Sign in
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 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.