iommu-debug-pagealloc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2025 - Google Inc
  4. * Author: Mostafa Saleh <smostafa@google.com>
  5. * IOMMU API debug page alloc sanitizer
  6. */
  7. #include <linux/atomic.h>
  8. #include <linux/iommu.h>
  9. #include <linux/iommu-debug-pagealloc.h>
  10. #include <linux/kernel.h>
  11. #include <linux/page_ext.h>
  12. #include <linux/page_owner.h>
  13. #include "iommu-priv.h"
  14. static bool needed;
  15. DEFINE_STATIC_KEY_FALSE(iommu_debug_initialized);
  16. struct iommu_debug_metadata {
  17. atomic_t ref;
  18. };
  19. static __init bool need_iommu_debug(void)
  20. {
  21. return needed;
  22. }
  23. struct page_ext_operations page_iommu_debug_ops = {
  24. .size = sizeof(struct iommu_debug_metadata),
  25. .need = need_iommu_debug,
  26. };
  27. static struct iommu_debug_metadata *get_iommu_data(struct page_ext *page_ext)
  28. {
  29. return page_ext_data(page_ext, &page_iommu_debug_ops);
  30. }
  31. static void iommu_debug_inc_page(phys_addr_t phys)
  32. {
  33. struct page_ext *page_ext = page_ext_from_phys(phys);
  34. struct iommu_debug_metadata *d;
  35. if (!page_ext)
  36. return;
  37. d = get_iommu_data(page_ext);
  38. WARN_ON(atomic_inc_return_relaxed(&d->ref) <= 0);
  39. page_ext_put(page_ext);
  40. }
  41. static void iommu_debug_dec_page(phys_addr_t phys)
  42. {
  43. struct page_ext *page_ext = page_ext_from_phys(phys);
  44. struct iommu_debug_metadata *d;
  45. if (!page_ext)
  46. return;
  47. d = get_iommu_data(page_ext);
  48. WARN_ON(atomic_dec_return_relaxed(&d->ref) < 0);
  49. page_ext_put(page_ext);
  50. }
  51. /*
  52. * IOMMU page size doesn't have to match the CPU page size. So, we use
  53. * the smallest IOMMU page size to refcount the pages in the vmemmap.
  54. * That is important as both map and unmap has to use the same page size
  55. * to update the refcount to avoid double counting the same page.
  56. * And as we can't know from iommu_unmap() what was the original page size
  57. * used for map, we just use the minimum supported one for both.
  58. */
  59. static size_t iommu_debug_page_size(struct iommu_domain *domain)
  60. {
  61. return 1UL << __ffs(domain->pgsize_bitmap);
  62. }
  63. static bool iommu_debug_page_count(const struct page *page)
  64. {
  65. unsigned int ref;
  66. struct page_ext *page_ext = page_ext_get(page);
  67. struct iommu_debug_metadata *d = get_iommu_data(page_ext);
  68. ref = atomic_read(&d->ref);
  69. page_ext_put(page_ext);
  70. return ref != 0;
  71. }
  72. void __iommu_debug_check_unmapped(const struct page *page, int numpages)
  73. {
  74. while (numpages--) {
  75. if (WARN_ON(iommu_debug_page_count(page))) {
  76. pr_warn("iommu: Detected page leak!\n");
  77. dump_page_owner(page);
  78. }
  79. page++;
  80. }
  81. }
  82. void __iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
  83. {
  84. size_t off, end;
  85. size_t page_size = iommu_debug_page_size(domain);
  86. if (WARN_ON(!phys || check_add_overflow(phys, size, &end)))
  87. return;
  88. for (off = 0 ; off < size ; off += page_size)
  89. iommu_debug_inc_page(phys + off);
  90. }
  91. static void __iommu_debug_update_iova(struct iommu_domain *domain,
  92. unsigned long iova, size_t size, bool inc)
  93. {
  94. size_t off, end;
  95. size_t page_size = iommu_debug_page_size(domain);
  96. if (WARN_ON(check_add_overflow(iova, size, &end)))
  97. return;
  98. for (off = 0 ; off < size ; off += page_size) {
  99. phys_addr_t phys = iommu_iova_to_phys(domain, iova + off);
  100. if (!phys)
  101. continue;
  102. if (inc)
  103. iommu_debug_inc_page(phys);
  104. else
  105. iommu_debug_dec_page(phys);
  106. }
  107. }
  108. void __iommu_debug_unmap_begin(struct iommu_domain *domain,
  109. unsigned long iova, size_t size)
  110. {
  111. __iommu_debug_update_iova(domain, iova, size, false);
  112. }
  113. void __iommu_debug_unmap_end(struct iommu_domain *domain,
  114. unsigned long iova, size_t size,
  115. size_t unmapped)
  116. {
  117. if ((unmapped == size) || WARN_ON_ONCE(unmapped > size))
  118. return;
  119. /* If unmap failed, re-increment the refcount. */
  120. __iommu_debug_update_iova(domain, iova + unmapped,
  121. size - unmapped, true);
  122. }
  123. void iommu_debug_init(void)
  124. {
  125. if (!needed)
  126. return;
  127. pr_info("iommu: Debugging page allocations, expect overhead or disable iommu.debug_pagealloc");
  128. static_branch_enable(&iommu_debug_initialized);
  129. }
  130. static int __init iommu_debug_pagealloc(char *str)
  131. {
  132. return kstrtobool(str, &needed);
  133. }
  134. early_param("iommu.debug_pagealloc", iommu_debug_pagealloc);