io-pgtable-arm-selftests.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * CPU-agnostic ARM page table allocator.
  4. *
  5. * Copyright (C) 2014 ARM Limited
  6. *
  7. * Author: Will Deacon <will.deacon@arm.com>
  8. */
  9. #define pr_fmt(fmt) "arm-lpae io-pgtable: " fmt
  10. #include <kunit/device.h>
  11. #include <kunit/test.h>
  12. #include <linux/io-pgtable.h>
  13. #include <linux/kernel.h>
  14. #include "io-pgtable-arm.h"
  15. static struct io_pgtable_cfg *cfg_cookie;
  16. static void dummy_tlb_flush_all(void *cookie)
  17. {
  18. WARN_ON(cookie != cfg_cookie);
  19. }
  20. static void dummy_tlb_flush(unsigned long iova, size_t size,
  21. size_t granule, void *cookie)
  22. {
  23. WARN_ON(cookie != cfg_cookie);
  24. WARN_ON(!(size & cfg_cookie->pgsize_bitmap));
  25. }
  26. static void dummy_tlb_add_page(struct iommu_iotlb_gather *gather,
  27. unsigned long iova, size_t granule,
  28. void *cookie)
  29. {
  30. dummy_tlb_flush(iova, granule, granule, cookie);
  31. }
  32. static const struct iommu_flush_ops dummy_tlb_ops = {
  33. .tlb_flush_all = dummy_tlb_flush_all,
  34. .tlb_flush_walk = dummy_tlb_flush,
  35. .tlb_add_page = dummy_tlb_add_page,
  36. };
  37. #define __FAIL(test, i) ({ \
  38. KUNIT_FAIL(test, "test failed for fmt idx %d\n", (i)); \
  39. -EFAULT; \
  40. })
  41. static int arm_lpae_run_tests(struct kunit *test, struct io_pgtable_cfg *cfg)
  42. {
  43. static const enum io_pgtable_fmt fmts[] = {
  44. ARM_64_LPAE_S1,
  45. ARM_64_LPAE_S2,
  46. };
  47. int i, j;
  48. unsigned long iova;
  49. size_t size, mapped;
  50. struct io_pgtable_ops *ops;
  51. for (i = 0; i < ARRAY_SIZE(fmts); ++i) {
  52. cfg_cookie = cfg;
  53. ops = alloc_io_pgtable_ops(fmts[i], cfg, cfg);
  54. if (!ops) {
  55. kunit_err(test, "failed to allocate io pgtable ops\n");
  56. return -ENOMEM;
  57. }
  58. /*
  59. * Initial sanity checks.
  60. * Empty page tables shouldn't provide any translations.
  61. */
  62. if (ops->iova_to_phys(ops, 42))
  63. return __FAIL(test, i);
  64. if (ops->iova_to_phys(ops, SZ_1G + 42))
  65. return __FAIL(test, i);
  66. if (ops->iova_to_phys(ops, SZ_2G + 42))
  67. return __FAIL(test, i);
  68. /*
  69. * Distinct mappings of different granule sizes.
  70. */
  71. iova = 0;
  72. for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) {
  73. size = 1UL << j;
  74. if (ops->map_pages(ops, iova, iova, size, 1,
  75. IOMMU_READ | IOMMU_WRITE |
  76. IOMMU_NOEXEC | IOMMU_CACHE,
  77. GFP_KERNEL, &mapped))
  78. return __FAIL(test, i);
  79. /* Overlapping mappings */
  80. if (!ops->map_pages(ops, iova, iova + size, size, 1,
  81. IOMMU_READ | IOMMU_NOEXEC,
  82. GFP_KERNEL, &mapped))
  83. return __FAIL(test, i);
  84. if (ops->iova_to_phys(ops, iova + 42) != (iova + 42))
  85. return __FAIL(test, i);
  86. iova += SZ_1G;
  87. }
  88. /* Full unmap */
  89. iova = 0;
  90. for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) {
  91. size = 1UL << j;
  92. if (ops->unmap_pages(ops, iova, size, 1, NULL) != size)
  93. return __FAIL(test, i);
  94. if (ops->iova_to_phys(ops, iova + 42))
  95. return __FAIL(test, i);
  96. /* Remap full block */
  97. if (ops->map_pages(ops, iova, iova, size, 1,
  98. IOMMU_WRITE, GFP_KERNEL, &mapped))
  99. return __FAIL(test, i);
  100. if (ops->iova_to_phys(ops, iova + 42) != (iova + 42))
  101. return __FAIL(test, i);
  102. iova += SZ_1G;
  103. }
  104. /*
  105. * Map/unmap the last largest supported page of the IAS, this can
  106. * trigger corner cases in the concatednated page tables.
  107. */
  108. mapped = 0;
  109. size = 1UL << __fls(cfg->pgsize_bitmap);
  110. iova = (1UL << cfg->ias) - size;
  111. if (ops->map_pages(ops, iova, iova, size, 1,
  112. IOMMU_READ | IOMMU_WRITE |
  113. IOMMU_NOEXEC | IOMMU_CACHE,
  114. GFP_KERNEL, &mapped))
  115. return __FAIL(test, i);
  116. if (mapped != size)
  117. return __FAIL(test, i);
  118. if (ops->unmap_pages(ops, iova, size, 1, NULL) != size)
  119. return __FAIL(test, i);
  120. free_io_pgtable_ops(ops);
  121. }
  122. return 0;
  123. }
  124. static void arm_lpae_do_selftests(struct kunit *test)
  125. {
  126. static const unsigned long pgsize[] = {
  127. SZ_4K | SZ_2M | SZ_1G,
  128. SZ_16K | SZ_32M,
  129. SZ_64K | SZ_512M,
  130. };
  131. static const unsigned int address_size[] = {
  132. 32, 36, 40, 42, 44, 48,
  133. };
  134. int i, j, k, pass = 0, fail = 0;
  135. struct device *dev;
  136. struct io_pgtable_cfg cfg = {
  137. .tlb = &dummy_tlb_ops,
  138. .coherent_walk = true,
  139. .quirks = IO_PGTABLE_QUIRK_NO_WARN,
  140. };
  141. dev = kunit_device_register(test, "io-pgtable-test");
  142. KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
  143. if (IS_ERR_OR_NULL(dev))
  144. return;
  145. cfg.iommu_dev = dev;
  146. for (i = 0; i < ARRAY_SIZE(pgsize); ++i) {
  147. for (j = 0; j < ARRAY_SIZE(address_size); ++j) {
  148. /* Don't use ias > oas as it is not valid for stage-2. */
  149. for (k = 0; k <= j; ++k) {
  150. cfg.pgsize_bitmap = pgsize[i];
  151. cfg.ias = address_size[k];
  152. cfg.oas = address_size[j];
  153. kunit_info(test, "pgsize_bitmap 0x%08lx, IAS %u OAS %u\n",
  154. pgsize[i], cfg.ias, cfg.oas);
  155. if (arm_lpae_run_tests(test, &cfg))
  156. fail++;
  157. else
  158. pass++;
  159. }
  160. }
  161. }
  162. kunit_info(test, "completed with %d PASS %d FAIL\n", pass, fail);
  163. }
  164. static struct kunit_case io_pgtable_arm_test_cases[] = {
  165. KUNIT_CASE(arm_lpae_do_selftests),
  166. {},
  167. };
  168. static struct kunit_suite io_pgtable_arm_test = {
  169. .name = "io-pgtable-arm-test",
  170. .test_cases = io_pgtable_arm_test_cases,
  171. };
  172. kunit_test_suite(io_pgtable_arm_test);
  173. MODULE_DESCRIPTION("io-pgtable-arm library kunit tests");
  174. MODULE_LICENSE("GPL");