i915_gem_userptr.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. * SPDX-License-Identifier: MIT
  3. *
  4. * Copyright © 2012-2014 Intel Corporation
  5. *
  6. * Based on amdgpu_mn, which bears the following notice:
  7. *
  8. * Copyright 2014 Advanced Micro Devices, Inc.
  9. * All Rights Reserved.
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a
  12. * copy of this software and associated documentation files (the
  13. * "Software"), to deal in the Software without restriction, including
  14. * without limitation the rights to use, copy, modify, merge, publish,
  15. * distribute, sub license, and/or sell copies of the Software, and to
  16. * permit persons to whom the Software is furnished to do so, subject to
  17. * the following conditions:
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  22. * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  23. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  25. * USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. * The above copyright notice and this permission notice (including the
  28. * next paragraph) shall be included in all copies or substantial portions
  29. * of the Software.
  30. *
  31. */
  32. /*
  33. * Authors:
  34. * Christian König <christian.koenig@amd.com>
  35. */
  36. #include <linux/mmu_context.h>
  37. #include <linux/mempolicy.h>
  38. #include <linux/swap.h>
  39. #include <linux/sched/mm.h>
  40. #include "i915_drv.h"
  41. #include "i915_gem_ioctls.h"
  42. #include "i915_gem_object.h"
  43. #include "i915_scatterlist.h"
  44. #ifdef CONFIG_MMU_NOTIFIER
  45. /**
  46. * i915_gem_userptr_invalidate - callback to notify about mm change
  47. *
  48. * @mni: the range (mm) is about to update
  49. * @range: details on the invalidation
  50. * @cur_seq: Value to pass to mmu_interval_set_seq()
  51. *
  52. * Block for operations on BOs to finish and mark pages as accessed and
  53. * potentially dirty.
  54. */
  55. static bool i915_gem_userptr_invalidate(struct mmu_interval_notifier *mni,
  56. const struct mmu_notifier_range *range,
  57. unsigned long cur_seq)
  58. {
  59. mmu_interval_set_seq(mni, cur_seq);
  60. return true;
  61. }
  62. static const struct mmu_interval_notifier_ops i915_gem_userptr_notifier_ops = {
  63. .invalidate = i915_gem_userptr_invalidate,
  64. };
  65. static int
  66. i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj)
  67. {
  68. return mmu_interval_notifier_insert(&obj->userptr.notifier, current->mm,
  69. obj->userptr.ptr, obj->base.size,
  70. &i915_gem_userptr_notifier_ops);
  71. }
  72. static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
  73. {
  74. struct page **pvec = NULL;
  75. assert_object_held_shared(obj);
  76. if (!--obj->userptr.page_ref) {
  77. pvec = obj->userptr.pvec;
  78. obj->userptr.pvec = NULL;
  79. }
  80. GEM_BUG_ON(obj->userptr.page_ref < 0);
  81. if (pvec) {
  82. const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
  83. unpin_user_pages(pvec, num_pages);
  84. kvfree(pvec);
  85. }
  86. }
  87. static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
  88. {
  89. unsigned int max_segment = i915_sg_segment_size(obj->base.dev->dev);
  90. struct sg_table *st;
  91. struct page **pvec;
  92. unsigned int num_pages; /* limited by sg_alloc_table_from_pages_segment */
  93. int ret;
  94. if (overflows_type(obj->base.size >> PAGE_SHIFT, num_pages))
  95. return -E2BIG;
  96. num_pages = obj->base.size >> PAGE_SHIFT;
  97. st = kmalloc(sizeof(*st), GFP_KERNEL);
  98. if (!st)
  99. return -ENOMEM;
  100. if (!obj->userptr.page_ref) {
  101. ret = -EAGAIN;
  102. goto err_free;
  103. }
  104. obj->userptr.page_ref++;
  105. pvec = obj->userptr.pvec;
  106. alloc_table:
  107. ret = sg_alloc_table_from_pages_segment(st, pvec, num_pages, 0,
  108. num_pages << PAGE_SHIFT,
  109. max_segment, GFP_KERNEL);
  110. if (ret)
  111. goto err;
  112. ret = i915_gem_gtt_prepare_pages(obj, st);
  113. if (ret) {
  114. sg_free_table(st);
  115. if (max_segment > PAGE_SIZE) {
  116. max_segment = PAGE_SIZE;
  117. goto alloc_table;
  118. }
  119. goto err;
  120. }
  121. WARN_ON_ONCE(!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE));
  122. if (i915_gem_object_can_bypass_llc(obj))
  123. obj->cache_dirty = true;
  124. __i915_gem_object_set_pages(obj, st);
  125. return 0;
  126. err:
  127. i915_gem_object_userptr_drop_ref(obj);
  128. err_free:
  129. kfree(st);
  130. return ret;
  131. }
  132. static void
  133. i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
  134. struct sg_table *pages)
  135. {
  136. struct sgt_iter sgt_iter;
  137. struct page *page;
  138. if (!pages)
  139. return;
  140. __i915_gem_object_release_shmem(obj, pages, true);
  141. i915_gem_gtt_finish_pages(obj, pages);
  142. /*
  143. * We always mark objects as dirty when they are used by the GPU,
  144. * just in case. However, if we set the vma as being read-only we know
  145. * that the object will never have been written to.
  146. */
  147. if (i915_gem_object_is_readonly(obj))
  148. obj->mm.dirty = false;
  149. for_each_sgt_page(page, sgt_iter, pages) {
  150. if (obj->mm.dirty && trylock_page(page)) {
  151. /*
  152. * As this may not be anonymous memory (e.g. shmem)
  153. * but exist on a real mapping, we have to lock
  154. * the page in order to dirty it -- holding
  155. * the page reference is not sufficient to
  156. * prevent the inode from being truncated.
  157. * Play safe and take the lock.
  158. *
  159. * However...!
  160. *
  161. * The mmu-notifier can be invalidated for a
  162. * migrate_folio, that is alreadying holding the lock
  163. * on the folio. Such a try_to_unmap() will result
  164. * in us calling put_pages() and so recursively try
  165. * to lock the page. We avoid that deadlock with
  166. * a trylock_page() and in exchange we risk missing
  167. * some page dirtying.
  168. */
  169. set_page_dirty(page);
  170. unlock_page(page);
  171. }
  172. mark_page_accessed(page);
  173. }
  174. obj->mm.dirty = false;
  175. sg_free_table(pages);
  176. kfree(pages);
  177. i915_gem_object_userptr_drop_ref(obj);
  178. }
  179. static int i915_gem_object_userptr_unbind(struct drm_i915_gem_object *obj)
  180. {
  181. struct sg_table *pages;
  182. int err;
  183. err = i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE);
  184. if (err)
  185. return err;
  186. if (GEM_WARN_ON(i915_gem_object_has_pinned_pages(obj)))
  187. return -EBUSY;
  188. assert_object_held(obj);
  189. pages = __i915_gem_object_unset_pages(obj);
  190. if (!IS_ERR_OR_NULL(pages))
  191. i915_gem_userptr_put_pages(obj, pages);
  192. return err;
  193. }
  194. int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
  195. {
  196. const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
  197. struct page **pvec;
  198. unsigned int gup_flags = 0;
  199. unsigned long notifier_seq;
  200. int pinned, ret;
  201. if (obj->userptr.notifier.mm != current->mm)
  202. return -EFAULT;
  203. notifier_seq = mmu_interval_read_begin(&obj->userptr.notifier);
  204. ret = i915_gem_object_lock_interruptible(obj, NULL);
  205. if (ret)
  206. return ret;
  207. if (notifier_seq == obj->userptr.notifier_seq && obj->userptr.pvec) {
  208. i915_gem_object_unlock(obj);
  209. return 0;
  210. }
  211. ret = i915_gem_object_userptr_unbind(obj);
  212. i915_gem_object_unlock(obj);
  213. if (ret)
  214. return ret;
  215. pvec = kvmalloc_array(num_pages, sizeof(struct page *), GFP_KERNEL);
  216. if (!pvec)
  217. return -ENOMEM;
  218. if (!i915_gem_object_is_readonly(obj))
  219. gup_flags |= FOLL_WRITE;
  220. pinned = 0;
  221. while (pinned < num_pages) {
  222. ret = pin_user_pages_fast(obj->userptr.ptr + pinned * PAGE_SIZE,
  223. num_pages - pinned, gup_flags,
  224. &pvec[pinned]);
  225. if (ret < 0)
  226. goto out;
  227. pinned += ret;
  228. }
  229. ret = i915_gem_object_lock_interruptible(obj, NULL);
  230. if (ret)
  231. goto out;
  232. if (mmu_interval_read_retry(&obj->userptr.notifier,
  233. !obj->userptr.page_ref ? notifier_seq :
  234. obj->userptr.notifier_seq)) {
  235. ret = -EAGAIN;
  236. goto out_unlock;
  237. }
  238. if (!obj->userptr.page_ref++) {
  239. obj->userptr.pvec = pvec;
  240. obj->userptr.notifier_seq = notifier_seq;
  241. pvec = NULL;
  242. ret = ____i915_gem_object_get_pages(obj);
  243. }
  244. obj->userptr.page_ref--;
  245. out_unlock:
  246. i915_gem_object_unlock(obj);
  247. out:
  248. if (pvec) {
  249. unpin_user_pages(pvec, pinned);
  250. kvfree(pvec);
  251. }
  252. return ret;
  253. }
  254. int i915_gem_object_userptr_submit_done(struct drm_i915_gem_object *obj)
  255. {
  256. if (mmu_interval_read_retry(&obj->userptr.notifier,
  257. obj->userptr.notifier_seq)) {
  258. /* We collided with the mmu notifier, need to retry */
  259. return -EAGAIN;
  260. }
  261. return 0;
  262. }
  263. int i915_gem_object_userptr_validate(struct drm_i915_gem_object *obj)
  264. {
  265. int err;
  266. err = i915_gem_object_userptr_submit_init(obj);
  267. if (err)
  268. return err;
  269. err = i915_gem_object_lock_interruptible(obj, NULL);
  270. if (!err) {
  271. /*
  272. * Since we only check validity, not use the pages,
  273. * it doesn't matter if we collide with the mmu notifier,
  274. * and -EAGAIN handling is not required.
  275. */
  276. err = i915_gem_object_pin_pages(obj);
  277. if (!err)
  278. i915_gem_object_unpin_pages(obj);
  279. i915_gem_object_unlock(obj);
  280. }
  281. return err;
  282. }
  283. static void
  284. i915_gem_userptr_release(struct drm_i915_gem_object *obj)
  285. {
  286. GEM_WARN_ON(obj->userptr.page_ref);
  287. if (!obj->userptr.notifier.mm)
  288. return;
  289. mmu_interval_notifier_remove(&obj->userptr.notifier);
  290. obj->userptr.notifier.mm = NULL;
  291. }
  292. static int
  293. i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj)
  294. {
  295. drm_dbg(obj->base.dev, "Exporting userptr no longer allowed\n");
  296. return -EINVAL;
  297. }
  298. static int
  299. i915_gem_userptr_pwrite(struct drm_i915_gem_object *obj,
  300. const struct drm_i915_gem_pwrite *args)
  301. {
  302. drm_dbg(obj->base.dev, "pwrite to userptr no longer allowed\n");
  303. return -EINVAL;
  304. }
  305. static int
  306. i915_gem_userptr_pread(struct drm_i915_gem_object *obj,
  307. const struct drm_i915_gem_pread *args)
  308. {
  309. drm_dbg(obj->base.dev, "pread from userptr no longer allowed\n");
  310. return -EINVAL;
  311. }
  312. static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
  313. .name = "i915_gem_object_userptr",
  314. .flags = I915_GEM_OBJECT_IS_SHRINKABLE |
  315. I915_GEM_OBJECT_NO_MMAP |
  316. I915_GEM_OBJECT_IS_PROXY,
  317. .get_pages = i915_gem_userptr_get_pages,
  318. .put_pages = i915_gem_userptr_put_pages,
  319. .dmabuf_export = i915_gem_userptr_dmabuf_export,
  320. .pwrite = i915_gem_userptr_pwrite,
  321. .pread = i915_gem_userptr_pread,
  322. .release = i915_gem_userptr_release,
  323. };
  324. #endif
  325. static int
  326. probe_range(struct mm_struct *mm, unsigned long addr, unsigned long len)
  327. {
  328. VMA_ITERATOR(vmi, mm, addr);
  329. struct vm_area_struct *vma;
  330. unsigned long end = addr + len;
  331. mmap_read_lock(mm);
  332. for_each_vma_range(vmi, vma, end) {
  333. /* Check for holes, note that we also update the addr below */
  334. if (vma->vm_start > addr)
  335. break;
  336. if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
  337. break;
  338. addr = vma->vm_end;
  339. }
  340. mmap_read_unlock(mm);
  341. if (vma || addr < end)
  342. return -EFAULT;
  343. return 0;
  344. }
  345. /*
  346. * Creates a new mm object that wraps some normal memory from the process
  347. * context - user memory.
  348. *
  349. * We impose several restrictions upon the memory being mapped
  350. * into the GPU.
  351. * 1. It must be page aligned (both start/end addresses, i.e ptr and size).
  352. * 2. It must be normal system memory, not a pointer into another map of IO
  353. * space (e.g. it must not be a GTT mmapping of another object).
  354. * 3. We only allow a bo as large as we could in theory map into the GTT,
  355. * that is we limit the size to the total size of the GTT.
  356. * 4. The bo is marked as being snoopable. The backing pages are left
  357. * accessible directly by the CPU, but reads and writes by the GPU may
  358. * incur the cost of a snoop (unless you have an LLC architecture).
  359. *
  360. * Synchronisation between multiple users and the GPU is left to userspace
  361. * through the normal set-domain-ioctl. The kernel will enforce that the
  362. * GPU relinquishes the VMA before it is returned back to the system
  363. * i.e. upon free(), munmap() or process termination. However, the userspace
  364. * malloc() library may not immediately relinquish the VMA after free() and
  365. * instead reuse it whilst the GPU is still reading and writing to the VMA.
  366. * Caveat emptor.
  367. *
  368. * Also note, that the object created here is not currently a "first class"
  369. * object, in that several ioctls are banned. These are the CPU access
  370. * ioctls: mmap(), pwrite and pread. In practice, you are expected to use
  371. * direct access via your pointer rather than use those ioctls. Another
  372. * restriction is that we do not allow userptr surfaces to be pinned to the
  373. * hardware and so we reject any attempt to create a framebuffer out of a
  374. * userptr.
  375. *
  376. * If you think this is a good interface to use to pass GPU memory between
  377. * drivers, please use dma-buf instead. In fact, wherever possible use
  378. * dma-buf instead.
  379. */
  380. int
  381. i915_gem_userptr_ioctl(struct drm_device *dev,
  382. void *data,
  383. struct drm_file *file)
  384. {
  385. static struct lock_class_key __maybe_unused lock_class;
  386. struct drm_i915_private *i915 = to_i915(dev);
  387. struct drm_i915_gem_userptr *args = data;
  388. struct drm_i915_gem_object __maybe_unused *obj;
  389. int __maybe_unused ret;
  390. u32 __maybe_unused handle;
  391. if (!HAS_LLC(i915) && !HAS_SNOOP(i915)) {
  392. /* We cannot support coherent userptr objects on hw without
  393. * LLC and broken snooping.
  394. */
  395. return -ENODEV;
  396. }
  397. if (args->flags & ~(I915_USERPTR_READ_ONLY |
  398. I915_USERPTR_UNSYNCHRONIZED |
  399. I915_USERPTR_PROBE))
  400. return -EINVAL;
  401. if (i915_gem_object_size_2big(args->user_size))
  402. return -E2BIG;
  403. if (!args->user_size)
  404. return -EINVAL;
  405. if (offset_in_page(args->user_ptr | args->user_size))
  406. return -EINVAL;
  407. if (!access_ok((char __user *)(unsigned long)args->user_ptr, args->user_size))
  408. return -EFAULT;
  409. if (args->flags & I915_USERPTR_UNSYNCHRONIZED)
  410. return -ENODEV;
  411. if (args->flags & I915_USERPTR_READ_ONLY) {
  412. /*
  413. * On almost all of the older hw, we cannot tell the GPU that
  414. * a page is readonly.
  415. */
  416. if (!to_gt(i915)->vm->has_read_only)
  417. return -ENODEV;
  418. }
  419. if (args->flags & I915_USERPTR_PROBE) {
  420. /*
  421. * Check that the range pointed to represents real struct
  422. * pages and not iomappings (at this moment in time!)
  423. */
  424. ret = probe_range(current->mm, args->user_ptr, args->user_size);
  425. if (ret)
  426. return ret;
  427. }
  428. #ifdef CONFIG_MMU_NOTIFIER
  429. obj = i915_gem_object_alloc();
  430. if (obj == NULL)
  431. return -ENOMEM;
  432. drm_gem_private_object_init(dev, &obj->base, args->user_size);
  433. i915_gem_object_init(obj, &i915_gem_userptr_ops, &lock_class,
  434. I915_BO_ALLOC_USER);
  435. obj->mem_flags = I915_BO_FLAG_STRUCT_PAGE;
  436. obj->read_domains = I915_GEM_DOMAIN_CPU;
  437. obj->write_domain = I915_GEM_DOMAIN_CPU;
  438. i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC);
  439. obj->userptr.ptr = args->user_ptr;
  440. obj->userptr.notifier_seq = ULONG_MAX;
  441. if (args->flags & I915_USERPTR_READ_ONLY)
  442. i915_gem_object_set_readonly(obj);
  443. /* And keep a pointer to the current->mm for resolving the user pages
  444. * at binding. This means that we need to hook into the mmu_notifier
  445. * in order to detect if the mmu is destroyed.
  446. */
  447. ret = i915_gem_userptr_init__mmu_notifier(obj);
  448. if (ret == 0)
  449. ret = drm_gem_handle_create(file, &obj->base, &handle);
  450. /* drop reference from allocate - handle holds it now */
  451. i915_gem_object_put(obj);
  452. if (ret)
  453. return ret;
  454. args->handle = handle;
  455. return 0;
  456. #else
  457. return -ENODEV;
  458. #endif
  459. }