iommu-pages.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (c) 2024, Google LLC.
  4. * Pasha Tatashin <pasha.tatashin@soleen.com>
  5. */
  6. #ifndef __IOMMU_PAGES_H
  7. #define __IOMMU_PAGES_H
  8. #include <linux/iommu.h>
  9. /**
  10. * struct ioptdesc - Memory descriptor for IOMMU page tables
  11. * @iopt_freelist_elm: List element for a struct iommu_pages_list
  12. *
  13. * This struct overlays struct page for now. Do not modify without a good
  14. * understanding of the issues.
  15. */
  16. struct ioptdesc {
  17. unsigned long __page_flags;
  18. struct list_head iopt_freelist_elm;
  19. unsigned long __page_mapping;
  20. union {
  21. u8 incoherent;
  22. pgoff_t __index;
  23. };
  24. void *_private;
  25. unsigned int __page_type;
  26. atomic_t __page_refcount;
  27. #ifdef CONFIG_MEMCG
  28. unsigned long memcg_data;
  29. #endif
  30. };
  31. static inline struct ioptdesc *folio_ioptdesc(struct folio *folio)
  32. {
  33. return (struct ioptdesc *)folio;
  34. }
  35. static inline struct folio *ioptdesc_folio(struct ioptdesc *iopt)
  36. {
  37. return (struct folio *)iopt;
  38. }
  39. static inline struct ioptdesc *virt_to_ioptdesc(void *virt)
  40. {
  41. return folio_ioptdesc(virt_to_folio(virt));
  42. }
  43. void *iommu_alloc_pages_node_sz(int nid, gfp_t gfp, size_t size);
  44. void iommu_free_pages(void *virt);
  45. void iommu_put_pages_list(struct iommu_pages_list *list);
  46. /**
  47. * iommu_pages_list_add - add the page to a iommu_pages_list
  48. * @list: List to add the page to
  49. * @virt: Address returned from iommu_alloc_pages_node_sz()
  50. */
  51. static inline void iommu_pages_list_add(struct iommu_pages_list *list,
  52. void *virt)
  53. {
  54. list_add_tail(&virt_to_ioptdesc(virt)->iopt_freelist_elm, &list->pages);
  55. }
  56. /**
  57. * iommu_pages_list_splice - Put all the pages in list from into list to
  58. * @from: Source list of pages
  59. * @to: Destination list of pages
  60. *
  61. * from must be re-initialized after calling this function if it is to be
  62. * used again.
  63. */
  64. static inline void iommu_pages_list_splice(struct iommu_pages_list *from,
  65. struct iommu_pages_list *to)
  66. {
  67. list_splice(&from->pages, &to->pages);
  68. }
  69. /**
  70. * iommu_pages_list_empty - True if the list is empty
  71. * @list: List to check
  72. */
  73. static inline bool iommu_pages_list_empty(struct iommu_pages_list *list)
  74. {
  75. return list_empty(&list->pages);
  76. }
  77. /**
  78. * iommu_alloc_pages_sz - Allocate a zeroed page of a given size from
  79. * specific NUMA node
  80. * @nid: memory NUMA node id
  81. * @gfp: buddy allocator flags
  82. * @size: Memory size to allocate, this is rounded up to a power of 2
  83. *
  84. * Returns the virtual address of the allocated page.
  85. */
  86. static inline void *iommu_alloc_pages_sz(gfp_t gfp, size_t size)
  87. {
  88. return iommu_alloc_pages_node_sz(NUMA_NO_NODE, gfp, size);
  89. }
  90. int iommu_pages_start_incoherent(void *virt, struct device *dma_dev);
  91. int iommu_pages_start_incoherent_list(struct iommu_pages_list *list,
  92. struct device *dma_dev);
  93. #ifdef CONFIG_X86
  94. #define IOMMU_PAGES_USE_DMA_API 0
  95. #include <linux/cacheflush.h>
  96. static inline void iommu_pages_flush_incoherent(struct device *dma_dev,
  97. void *virt, size_t offset,
  98. size_t len)
  99. {
  100. clflush_cache_range(virt + offset, len);
  101. }
  102. static inline void
  103. iommu_pages_stop_incoherent_list(struct iommu_pages_list *list,
  104. struct device *dma_dev)
  105. {
  106. /*
  107. * For performance leave the incoherent flag alone which turns this into
  108. * a NOP. For X86 the rest of the stop/free flow ignores the flag.
  109. */
  110. }
  111. static inline void iommu_pages_free_incoherent(void *virt,
  112. struct device *dma_dev)
  113. {
  114. iommu_free_pages(virt);
  115. }
  116. #else
  117. #define IOMMU_PAGES_USE_DMA_API 1
  118. #include <linux/dma-mapping.h>
  119. static inline void iommu_pages_flush_incoherent(struct device *dma_dev,
  120. void *virt, size_t offset,
  121. size_t len)
  122. {
  123. dma_sync_single_for_device(dma_dev, (uintptr_t)virt + offset, len,
  124. DMA_TO_DEVICE);
  125. }
  126. void iommu_pages_stop_incoherent_list(struct iommu_pages_list *list,
  127. struct device *dma_dev);
  128. void iommu_pages_free_incoherent(void *virt, struct device *dma_dev);
  129. #endif
  130. #endif /* __IOMMU_PAGES_H */