amdxdna_ubuf.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2025, Advanced Micro Devices, Inc.
  4. */
  5. #include <drm/amdxdna_accel.h>
  6. #include <drm/drm_device.h>
  7. #include <drm/drm_print.h>
  8. #include <linux/dma-buf.h>
  9. #include <linux/overflow.h>
  10. #include <linux/pagemap.h>
  11. #include <linux/vmalloc.h>
  12. #include "amdxdna_pci_drv.h"
  13. #include "amdxdna_ubuf.h"
  14. struct amdxdna_ubuf_priv {
  15. struct page **pages;
  16. u64 nr_pages;
  17. enum amdxdna_ubuf_flag flags;
  18. struct mm_struct *mm;
  19. };
  20. static struct sg_table *amdxdna_ubuf_map(struct dma_buf_attachment *attach,
  21. enum dma_data_direction direction)
  22. {
  23. struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
  24. struct sg_table *sg;
  25. int ret;
  26. sg = kzalloc_obj(*sg);
  27. if (!sg)
  28. return ERR_PTR(-ENOMEM);
  29. ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->nr_pages, 0,
  30. ubuf->nr_pages << PAGE_SHIFT, GFP_KERNEL);
  31. if (ret)
  32. goto err_free_sg;
  33. if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) {
  34. ret = dma_map_sgtable(attach->dev, sg, direction, 0);
  35. if (ret)
  36. goto err_free_table;
  37. }
  38. return sg;
  39. err_free_table:
  40. sg_free_table(sg);
  41. err_free_sg:
  42. kfree(sg);
  43. return ERR_PTR(ret);
  44. }
  45. static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
  46. struct sg_table *sg,
  47. enum dma_data_direction direction)
  48. {
  49. struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
  50. if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA)
  51. dma_unmap_sgtable(attach->dev, sg, direction, 0);
  52. sg_free_table(sg);
  53. kfree(sg);
  54. }
  55. static void amdxdna_ubuf_release(struct dma_buf *dbuf)
  56. {
  57. struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
  58. unpin_user_pages(ubuf->pages, ubuf->nr_pages);
  59. kvfree(ubuf->pages);
  60. atomic64_sub(ubuf->nr_pages, &ubuf->mm->pinned_vm);
  61. mmdrop(ubuf->mm);
  62. kfree(ubuf);
  63. }
  64. static vm_fault_t amdxdna_ubuf_vm_fault(struct vm_fault *vmf)
  65. {
  66. struct vm_area_struct *vma = vmf->vma;
  67. struct amdxdna_ubuf_priv *ubuf;
  68. unsigned long pfn;
  69. pgoff_t pgoff;
  70. ubuf = vma->vm_private_data;
  71. pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
  72. pfn = page_to_pfn(ubuf->pages[pgoff]);
  73. return vmf_insert_pfn(vma, vmf->address, pfn);
  74. }
  75. static const struct vm_operations_struct amdxdna_ubuf_vm_ops = {
  76. .fault = amdxdna_ubuf_vm_fault,
  77. };
  78. static int amdxdna_ubuf_mmap(struct dma_buf *dbuf, struct vm_area_struct *vma)
  79. {
  80. struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
  81. vma->vm_ops = &amdxdna_ubuf_vm_ops;
  82. vma->vm_private_data = ubuf;
  83. vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP);
  84. return 0;
  85. }
  86. static int amdxdna_ubuf_vmap(struct dma_buf *dbuf, struct iosys_map *map)
  87. {
  88. struct amdxdna_ubuf_priv *ubuf = dbuf->priv;
  89. void *kva;
  90. kva = vmap(ubuf->pages, ubuf->nr_pages, VM_MAP, PAGE_KERNEL);
  91. if (!kva)
  92. return -EINVAL;
  93. iosys_map_set_vaddr(map, kva);
  94. return 0;
  95. }
  96. static void amdxdna_ubuf_vunmap(struct dma_buf *dbuf, struct iosys_map *map)
  97. {
  98. vunmap(map->vaddr);
  99. }
  100. static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
  101. .map_dma_buf = amdxdna_ubuf_map,
  102. .unmap_dma_buf = amdxdna_ubuf_unmap,
  103. .release = amdxdna_ubuf_release,
  104. .mmap = amdxdna_ubuf_mmap,
  105. .vmap = amdxdna_ubuf_vmap,
  106. .vunmap = amdxdna_ubuf_vunmap,
  107. };
  108. struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
  109. enum amdxdna_ubuf_flag flags,
  110. u32 num_entries, void __user *va_entries)
  111. {
  112. struct amdxdna_dev *xdna = to_xdna_dev(dev);
  113. unsigned long lock_limit, new_pinned;
  114. struct amdxdna_drm_va_entry *va_ent;
  115. struct amdxdna_ubuf_priv *ubuf;
  116. u32 npages, start = 0;
  117. struct dma_buf *dbuf;
  118. int i, ret;
  119. DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
  120. if (!can_do_mlock())
  121. return ERR_PTR(-EPERM);
  122. ubuf = kzalloc_obj(*ubuf);
  123. if (!ubuf)
  124. return ERR_PTR(-ENOMEM);
  125. ubuf->flags = flags;
  126. ubuf->mm = current->mm;
  127. mmgrab(ubuf->mm);
  128. va_ent = kvzalloc_objs(*va_ent, num_entries);
  129. if (!va_ent) {
  130. ret = -ENOMEM;
  131. goto free_ubuf;
  132. }
  133. if (copy_from_user(va_ent, va_entries, sizeof(*va_ent) * num_entries)) {
  134. XDNA_DBG(xdna, "Access va entries failed");
  135. ret = -EINVAL;
  136. goto free_ent;
  137. }
  138. for (i = 0, exp_info.size = 0; i < num_entries; i++) {
  139. if (!IS_ALIGNED(va_ent[i].vaddr, PAGE_SIZE) ||
  140. !IS_ALIGNED(va_ent[i].len, PAGE_SIZE)) {
  141. XDNA_ERR(xdna, "Invalid address or len %llx, %llx",
  142. va_ent[i].vaddr, va_ent[i].len);
  143. ret = -EINVAL;
  144. goto free_ent;
  145. }
  146. if (check_add_overflow(exp_info.size, va_ent[i].len, &exp_info.size)) {
  147. ret = -EINVAL;
  148. goto free_ent;
  149. }
  150. }
  151. ubuf->nr_pages = exp_info.size >> PAGE_SHIFT;
  152. lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
  153. new_pinned = atomic64_add_return(ubuf->nr_pages, &ubuf->mm->pinned_vm);
  154. if (new_pinned > lock_limit && !capable(CAP_IPC_LOCK)) {
  155. XDNA_DBG(xdna, "New pin %ld, limit %ld, cap %d",
  156. new_pinned, lock_limit, capable(CAP_IPC_LOCK));
  157. ret = -ENOMEM;
  158. goto sub_pin_cnt;
  159. }
  160. ubuf->pages = kvmalloc_objs(*ubuf->pages, ubuf->nr_pages);
  161. if (!ubuf->pages) {
  162. ret = -ENOMEM;
  163. goto sub_pin_cnt;
  164. }
  165. for (i = 0; i < num_entries; i++) {
  166. npages = va_ent[i].len >> PAGE_SHIFT;
  167. ret = pin_user_pages_fast(va_ent[i].vaddr, npages,
  168. FOLL_WRITE | FOLL_LONGTERM,
  169. &ubuf->pages[start]);
  170. if (ret < 0 || ret != npages) {
  171. ret = -ENOMEM;
  172. XDNA_ERR(xdna, "Failed to pin pages ret %d", ret);
  173. goto destroy_pages;
  174. }
  175. start += ret;
  176. }
  177. exp_info.ops = &amdxdna_ubuf_dmabuf_ops;
  178. exp_info.priv = ubuf;
  179. exp_info.flags = O_RDWR | O_CLOEXEC;
  180. dbuf = dma_buf_export(&exp_info);
  181. if (IS_ERR(dbuf)) {
  182. ret = PTR_ERR(dbuf);
  183. goto destroy_pages;
  184. }
  185. kvfree(va_ent);
  186. return dbuf;
  187. destroy_pages:
  188. if (start)
  189. unpin_user_pages(ubuf->pages, start);
  190. kvfree(ubuf->pages);
  191. sub_pin_cnt:
  192. atomic64_sub(ubuf->nr_pages, &ubuf->mm->pinned_vm);
  193. free_ent:
  194. kvfree(va_ent);
  195. free_ubuf:
  196. mmdrop(ubuf->mm);
  197. kfree(ubuf);
  198. return ERR_PTR(ret);
  199. }