drm_gem_shmem_helper.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2018 Noralf Trønnes
  4. */
  5. #include <linux/dma-buf.h>
  6. #include <linux/export.h>
  7. #include <linux/module.h>
  8. #include <linux/mutex.h>
  9. #include <linux/shmem_fs.h>
  10. #include <linux/slab.h>
  11. #include <linux/vmalloc.h>
  12. #ifdef CONFIG_X86
  13. #include <asm/set_memory.h>
  14. #endif
  15. #include <kunit/visibility.h>
  16. #include <drm/drm.h>
  17. #include <drm/drm_device.h>
  18. #include <drm/drm_drv.h>
  19. #include <drm/drm_dumb_buffers.h>
  20. #include <drm/drm_gem_shmem_helper.h>
  21. #include <drm/drm_prime.h>
  22. #include <drm/drm_print.h>
  23. MODULE_IMPORT_NS("DMA_BUF");
  24. /**
  25. * DOC: overview
  26. *
  27. * This library provides helpers for GEM objects backed by shmem buffers
  28. * allocated using anonymous pageable memory.
  29. *
  30. * Functions that operate on the GEM object receive struct &drm_gem_shmem_object.
  31. * For GEM callback helpers in struct &drm_gem_object functions, see likewise
  32. * named functions with an _object_ infix (e.g., drm_gem_shmem_object_vmap() wraps
  33. * drm_gem_shmem_vmap()). These helpers perform the necessary type conversion.
  34. */
  35. static const struct drm_gem_object_funcs drm_gem_shmem_funcs = {
  36. .free = drm_gem_shmem_object_free,
  37. .print_info = drm_gem_shmem_object_print_info,
  38. .pin = drm_gem_shmem_object_pin,
  39. .unpin = drm_gem_shmem_object_unpin,
  40. .get_sg_table = drm_gem_shmem_object_get_sg_table,
  41. .vmap = drm_gem_shmem_object_vmap,
  42. .vunmap = drm_gem_shmem_object_vunmap,
  43. .mmap = drm_gem_shmem_object_mmap,
  44. .vm_ops = &drm_gem_shmem_vm_ops,
  45. };
  46. static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem,
  47. size_t size, bool private)
  48. {
  49. struct drm_gem_object *obj = &shmem->base;
  50. int ret = 0;
  51. if (!obj->funcs)
  52. obj->funcs = &drm_gem_shmem_funcs;
  53. if (private) {
  54. drm_gem_private_object_init(dev, obj, size);
  55. shmem->map_wc = false; /* dma-buf mappings use always writecombine */
  56. } else {
  57. ret = drm_gem_object_init(dev, obj, size);
  58. }
  59. if (ret) {
  60. drm_gem_private_object_fini(obj);
  61. return ret;
  62. }
  63. ret = drm_gem_create_mmap_offset(obj);
  64. if (ret)
  65. goto err_release;
  66. INIT_LIST_HEAD(&shmem->madv_list);
  67. if (!private) {
  68. /*
  69. * Our buffers are kept pinned, so allocating them
  70. * from the MOVABLE zone is a really bad idea, and
  71. * conflicts with CMA. See comments above new_inode()
  72. * why this is required _and_ expected if you're
  73. * going to pin these pages.
  74. */
  75. mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER |
  76. __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
  77. }
  78. return 0;
  79. err_release:
  80. drm_gem_object_release(obj);
  81. return ret;
  82. }
  83. /**
  84. * drm_gem_shmem_init - Initialize an allocated object.
  85. * @dev: DRM device
  86. * @shmem: shmem GEM object to initialize
  87. * @size: Buffer size in bytes
  88. *
  89. * This function initializes an allocated shmem GEM object.
  90. *
  91. * Returns:
  92. * 0 on success, or a negative error code on failure.
  93. */
  94. int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size)
  95. {
  96. return __drm_gem_shmem_init(dev, shmem, size, false);
  97. }
  98. EXPORT_SYMBOL_GPL(drm_gem_shmem_init);
  99. static struct drm_gem_shmem_object *
  100. __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private)
  101. {
  102. struct drm_gem_shmem_object *shmem;
  103. struct drm_gem_object *obj;
  104. int ret = 0;
  105. size = PAGE_ALIGN(size);
  106. if (dev->driver->gem_create_object) {
  107. obj = dev->driver->gem_create_object(dev, size);
  108. if (IS_ERR(obj))
  109. return ERR_CAST(obj);
  110. shmem = to_drm_gem_shmem_obj(obj);
  111. } else {
  112. shmem = kzalloc_obj(*shmem);
  113. if (!shmem)
  114. return ERR_PTR(-ENOMEM);
  115. obj = &shmem->base;
  116. }
  117. ret = __drm_gem_shmem_init(dev, shmem, size, private);
  118. if (ret) {
  119. kfree(obj);
  120. return ERR_PTR(ret);
  121. }
  122. return shmem;
  123. }
  124. /**
  125. * drm_gem_shmem_create - Allocate an object with the given size
  126. * @dev: DRM device
  127. * @size: Size of the object to allocate
  128. *
  129. * This function creates a shmem GEM object.
  130. *
  131. * Returns:
  132. * A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative
  133. * error code on failure.
  134. */
  135. struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)
  136. {
  137. return __drm_gem_shmem_create(dev, size, false);
  138. }
  139. EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
  140. /**
  141. * drm_gem_shmem_release - Release resources associated with a shmem GEM object.
  142. * @shmem: shmem GEM object
  143. *
  144. * This function cleans up the GEM object state, but does not free the memory used to store the
  145. * object itself. This function is meant to be a dedicated helper for the Rust GEM bindings.
  146. */
  147. void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem)
  148. {
  149. struct drm_gem_object *obj = &shmem->base;
  150. if (drm_gem_is_imported(obj)) {
  151. drm_prime_gem_destroy(obj, shmem->sgt);
  152. } else {
  153. dma_resv_lock(shmem->base.resv, NULL);
  154. drm_WARN_ON(obj->dev, refcount_read(&shmem->vmap_use_count));
  155. if (shmem->sgt) {
  156. dma_unmap_sgtable(obj->dev->dev, shmem->sgt,
  157. DMA_BIDIRECTIONAL, 0);
  158. sg_free_table(shmem->sgt);
  159. kfree(shmem->sgt);
  160. }
  161. if (shmem->pages)
  162. drm_gem_shmem_put_pages_locked(shmem);
  163. drm_WARN_ON(obj->dev, refcount_read(&shmem->pages_use_count));
  164. drm_WARN_ON(obj->dev, refcount_read(&shmem->pages_pin_count));
  165. dma_resv_unlock(shmem->base.resv);
  166. }
  167. drm_gem_object_release(obj);
  168. }
  169. EXPORT_SYMBOL_GPL(drm_gem_shmem_release);
  170. /**
  171. * drm_gem_shmem_free - Free resources associated with a shmem GEM object
  172. * @shmem: shmem GEM object to free
  173. *
  174. * This function cleans up the GEM object state and frees the memory used to
  175. * store the object itself.
  176. */
  177. void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem)
  178. {
  179. drm_gem_shmem_release(shmem);
  180. kfree(shmem);
  181. }
  182. EXPORT_SYMBOL_GPL(drm_gem_shmem_free);
  183. static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem)
  184. {
  185. struct drm_gem_object *obj = &shmem->base;
  186. struct page **pages;
  187. dma_resv_assert_held(shmem->base.resv);
  188. if (refcount_inc_not_zero(&shmem->pages_use_count))
  189. return 0;
  190. pages = drm_gem_get_pages(obj);
  191. if (IS_ERR(pages)) {
  192. drm_dbg_kms(obj->dev, "Failed to get pages (%ld)\n",
  193. PTR_ERR(pages));
  194. return PTR_ERR(pages);
  195. }
  196. /*
  197. * TODO: Allocating WC pages which are correctly flushed is only
  198. * supported on x86. Ideal solution would be a GFP_WC flag, which also
  199. * ttm_pool.c could use.
  200. */
  201. #ifdef CONFIG_X86
  202. if (shmem->map_wc)
  203. set_pages_array_wc(pages, obj->size >> PAGE_SHIFT);
  204. #endif
  205. shmem->pages = pages;
  206. refcount_set(&shmem->pages_use_count, 1);
  207. return 0;
  208. }
  209. /*
  210. * drm_gem_shmem_put_pages_locked - Decrease use count on the backing pages for a shmem GEM object
  211. * @shmem: shmem GEM object
  212. *
  213. * This function decreases the use count and puts the backing pages when use drops to zero.
  214. */
  215. void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem)
  216. {
  217. struct drm_gem_object *obj = &shmem->base;
  218. dma_resv_assert_held(shmem->base.resv);
  219. if (refcount_dec_and_test(&shmem->pages_use_count)) {
  220. #ifdef CONFIG_X86
  221. if (shmem->map_wc)
  222. set_pages_array_wb(shmem->pages, obj->size >> PAGE_SHIFT);
  223. #endif
  224. drm_gem_put_pages(obj, shmem->pages,
  225. shmem->pages_mark_dirty_on_put,
  226. shmem->pages_mark_accessed_on_put);
  227. shmem->pages = NULL;
  228. }
  229. }
  230. EXPORT_SYMBOL_GPL(drm_gem_shmem_put_pages_locked);
  231. int drm_gem_shmem_pin_locked(struct drm_gem_shmem_object *shmem)
  232. {
  233. int ret;
  234. dma_resv_assert_held(shmem->base.resv);
  235. drm_WARN_ON(shmem->base.dev, drm_gem_is_imported(&shmem->base));
  236. if (refcount_inc_not_zero(&shmem->pages_pin_count))
  237. return 0;
  238. ret = drm_gem_shmem_get_pages_locked(shmem);
  239. if (!ret)
  240. refcount_set(&shmem->pages_pin_count, 1);
  241. return ret;
  242. }
  243. EXPORT_SYMBOL(drm_gem_shmem_pin_locked);
  244. void drm_gem_shmem_unpin_locked(struct drm_gem_shmem_object *shmem)
  245. {
  246. dma_resv_assert_held(shmem->base.resv);
  247. if (refcount_dec_and_test(&shmem->pages_pin_count))
  248. drm_gem_shmem_put_pages_locked(shmem);
  249. }
  250. EXPORT_SYMBOL(drm_gem_shmem_unpin_locked);
  251. /**
  252. * drm_gem_shmem_pin - Pin backing pages for a shmem GEM object
  253. * @shmem: shmem GEM object
  254. *
  255. * This function makes sure the backing pages are pinned in memory while the
  256. * buffer is exported.
  257. *
  258. * Returns:
  259. * 0 on success or a negative error code on failure.
  260. */
  261. int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem)
  262. {
  263. struct drm_gem_object *obj = &shmem->base;
  264. int ret;
  265. drm_WARN_ON(obj->dev, drm_gem_is_imported(obj));
  266. if (refcount_inc_not_zero(&shmem->pages_pin_count))
  267. return 0;
  268. ret = dma_resv_lock_interruptible(shmem->base.resv, NULL);
  269. if (ret)
  270. return ret;
  271. ret = drm_gem_shmem_pin_locked(shmem);
  272. dma_resv_unlock(shmem->base.resv);
  273. return ret;
  274. }
  275. EXPORT_SYMBOL_GPL(drm_gem_shmem_pin);
  276. /**
  277. * drm_gem_shmem_unpin - Unpin backing pages for a shmem GEM object
  278. * @shmem: shmem GEM object
  279. *
  280. * This function removes the requirement that the backing pages are pinned in
  281. * memory.
  282. */
  283. void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem)
  284. {
  285. struct drm_gem_object *obj = &shmem->base;
  286. drm_WARN_ON(obj->dev, drm_gem_is_imported(obj));
  287. if (refcount_dec_not_one(&shmem->pages_pin_count))
  288. return;
  289. dma_resv_lock(shmem->base.resv, NULL);
  290. drm_gem_shmem_unpin_locked(shmem);
  291. dma_resv_unlock(shmem->base.resv);
  292. }
  293. EXPORT_SYMBOL_GPL(drm_gem_shmem_unpin);
  294. /*
  295. * drm_gem_shmem_vmap_locked - Create a virtual mapping for a shmem GEM object
  296. * @shmem: shmem GEM object
  297. * @map: Returns the kernel virtual address of the SHMEM GEM object's backing
  298. * store.
  299. *
  300. * This function makes sure that a contiguous kernel virtual address mapping
  301. * exists for the buffer backing the shmem GEM object. It hides the differences
  302. * between dma-buf imported and natively allocated objects.
  303. *
  304. * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap_locked().
  305. *
  306. * Returns:
  307. * 0 on success or a negative error code on failure.
  308. */
  309. int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem,
  310. struct iosys_map *map)
  311. {
  312. struct drm_gem_object *obj = &shmem->base;
  313. int ret = 0;
  314. dma_resv_assert_held(obj->resv);
  315. if (drm_gem_is_imported(obj)) {
  316. ret = dma_buf_vmap(obj->import_attach->dmabuf, map);
  317. } else {
  318. pgprot_t prot = PAGE_KERNEL;
  319. dma_resv_assert_held(shmem->base.resv);
  320. if (refcount_inc_not_zero(&shmem->vmap_use_count)) {
  321. iosys_map_set_vaddr(map, shmem->vaddr);
  322. return 0;
  323. }
  324. ret = drm_gem_shmem_pin_locked(shmem);
  325. if (ret)
  326. return ret;
  327. if (shmem->map_wc)
  328. prot = pgprot_writecombine(prot);
  329. shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT,
  330. VM_MAP, prot);
  331. if (!shmem->vaddr) {
  332. ret = -ENOMEM;
  333. } else {
  334. iosys_map_set_vaddr(map, shmem->vaddr);
  335. refcount_set(&shmem->vmap_use_count, 1);
  336. }
  337. }
  338. if (ret) {
  339. drm_dbg_kms(obj->dev, "Failed to vmap pages, error %d\n", ret);
  340. goto err_put_pages;
  341. }
  342. return 0;
  343. err_put_pages:
  344. if (!drm_gem_is_imported(obj))
  345. drm_gem_shmem_unpin_locked(shmem);
  346. return ret;
  347. }
  348. EXPORT_SYMBOL_GPL(drm_gem_shmem_vmap_locked);
  349. /*
  350. * drm_gem_shmem_vunmap_locked - Unmap a virtual mapping for a shmem GEM object
  351. * @shmem: shmem GEM object
  352. * @map: Kernel virtual address where the SHMEM GEM object was mapped
  353. *
  354. * This function cleans up a kernel virtual address mapping acquired by
  355. * drm_gem_shmem_vmap_locked(). The mapping is only removed when the use count
  356. * drops to zero.
  357. *
  358. * This function hides the differences between dma-buf imported and natively
  359. * allocated objects.
  360. */
  361. void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
  362. struct iosys_map *map)
  363. {
  364. struct drm_gem_object *obj = &shmem->base;
  365. dma_resv_assert_held(obj->resv);
  366. if (drm_gem_is_imported(obj)) {
  367. dma_buf_vunmap(obj->import_attach->dmabuf, map);
  368. } else {
  369. dma_resv_assert_held(shmem->base.resv);
  370. if (refcount_dec_and_test(&shmem->vmap_use_count)) {
  371. vunmap(shmem->vaddr);
  372. shmem->vaddr = NULL;
  373. drm_gem_shmem_unpin_locked(shmem);
  374. }
  375. }
  376. }
  377. EXPORT_SYMBOL_GPL(drm_gem_shmem_vunmap_locked);
  378. static int
  379. drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
  380. struct drm_device *dev, size_t size,
  381. uint32_t *handle)
  382. {
  383. struct drm_gem_shmem_object *shmem;
  384. int ret;
  385. shmem = drm_gem_shmem_create(dev, size);
  386. if (IS_ERR(shmem))
  387. return PTR_ERR(shmem);
  388. /*
  389. * Allocate an id of idr table where the obj is registered
  390. * and handle has the id what user can see.
  391. */
  392. ret = drm_gem_handle_create(file_priv, &shmem->base, handle);
  393. /* drop reference from allocate - handle holds it now. */
  394. drm_gem_object_put(&shmem->base);
  395. return ret;
  396. }
  397. /* Update madvise status, returns true if not purged, else
  398. * false or -errno.
  399. */
  400. int drm_gem_shmem_madvise_locked(struct drm_gem_shmem_object *shmem, int madv)
  401. {
  402. dma_resv_assert_held(shmem->base.resv);
  403. if (shmem->madv >= 0)
  404. shmem->madv = madv;
  405. madv = shmem->madv;
  406. return (madv >= 0);
  407. }
  408. EXPORT_SYMBOL_GPL(drm_gem_shmem_madvise_locked);
  409. void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem)
  410. {
  411. struct drm_gem_object *obj = &shmem->base;
  412. struct drm_device *dev = obj->dev;
  413. dma_resv_assert_held(shmem->base.resv);
  414. drm_WARN_ON(obj->dev, !drm_gem_shmem_is_purgeable(shmem));
  415. dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0);
  416. sg_free_table(shmem->sgt);
  417. kfree(shmem->sgt);
  418. shmem->sgt = NULL;
  419. drm_gem_shmem_put_pages_locked(shmem);
  420. shmem->madv = -1;
  421. drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping);
  422. drm_gem_free_mmap_offset(obj);
  423. /* Our goal here is to return as much of the memory as
  424. * is possible back to the system as we are called from OOM.
  425. * To do this we must instruct the shmfs to drop all of its
  426. * backing pages, *now*.
  427. */
  428. shmem_truncate_range(file_inode(obj->filp), 0, (loff_t)-1);
  429. invalidate_mapping_pages(file_inode(obj->filp)->i_mapping, 0, (loff_t)-1);
  430. }
  431. EXPORT_SYMBOL_GPL(drm_gem_shmem_purge_locked);
  432. /**
  433. * drm_gem_shmem_dumb_create - Create a dumb shmem buffer object
  434. * @file: DRM file structure to create the dumb buffer for
  435. * @dev: DRM device
  436. * @args: IOCTL data
  437. *
  438. * This function computes the pitch of the dumb buffer and rounds it up to an
  439. * integer number of bytes per pixel. Drivers for hardware that doesn't have
  440. * any additional restrictions on the pitch can directly use this function as
  441. * their &drm_driver.dumb_create callback.
  442. *
  443. * For hardware with additional restrictions, drivers can adjust the fields
  444. * set up by userspace before calling into this function.
  445. *
  446. * Returns:
  447. * 0 on success or a negative error code on failure.
  448. */
  449. int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
  450. struct drm_mode_create_dumb *args)
  451. {
  452. int ret;
  453. ret = drm_mode_size_dumb(dev, args, 0, 0);
  454. if (ret)
  455. return ret;
  456. return drm_gem_shmem_create_with_handle(file, dev, args->size, &args->handle);
  457. }
  458. EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
  459. static vm_fault_t try_insert_pfn(struct vm_fault *vmf, unsigned int order,
  460. unsigned long pfn)
  461. {
  462. if (!order) {
  463. return vmf_insert_pfn(vmf->vma, vmf->address, pfn);
  464. #ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
  465. } else if (order == PMD_ORDER) {
  466. unsigned long paddr = pfn << PAGE_SHIFT;
  467. bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
  468. if (aligned &&
  469. folio_test_pmd_mappable(page_folio(pfn_to_page(pfn)))) {
  470. pfn &= PMD_MASK >> PAGE_SHIFT;
  471. return vmf_insert_pfn_pmd(vmf, pfn, false);
  472. }
  473. #endif
  474. }
  475. return VM_FAULT_FALLBACK;
  476. }
  477. static vm_fault_t drm_gem_shmem_any_fault(struct vm_fault *vmf, unsigned int order)
  478. {
  479. struct vm_area_struct *vma = vmf->vma;
  480. struct drm_gem_object *obj = vma->vm_private_data;
  481. struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
  482. loff_t num_pages = obj->size >> PAGE_SHIFT;
  483. vm_fault_t ret;
  484. struct page **pages = shmem->pages;
  485. pgoff_t page_offset;
  486. unsigned long pfn;
  487. if (order && order != PMD_ORDER)
  488. return VM_FAULT_FALLBACK;
  489. /* Offset to faulty address in the VMA. */
  490. page_offset = vmf->pgoff - vma->vm_pgoff;
  491. dma_resv_lock(shmem->base.resv, NULL);
  492. if (page_offset >= num_pages ||
  493. drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
  494. shmem->madv < 0) {
  495. ret = VM_FAULT_SIGBUS;
  496. goto out;
  497. }
  498. pfn = page_to_pfn(pages[page_offset]);
  499. ret = try_insert_pfn(vmf, order, pfn);
  500. out:
  501. dma_resv_unlock(shmem->base.resv);
  502. return ret;
  503. }
  504. static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
  505. {
  506. return drm_gem_shmem_any_fault(vmf, 0);
  507. }
  508. static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
  509. {
  510. struct drm_gem_object *obj = vma->vm_private_data;
  511. struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
  512. drm_WARN_ON(obj->dev, drm_gem_is_imported(obj));
  513. dma_resv_lock(shmem->base.resv, NULL);
  514. /*
  515. * We should have already pinned the pages when the buffer was first
  516. * mmap'd, vm_open() just grabs an additional reference for the new
  517. * mm the vma is getting copied into (ie. on fork()).
  518. */
  519. drm_WARN_ON_ONCE(obj->dev,
  520. !refcount_inc_not_zero(&shmem->pages_use_count));
  521. dma_resv_unlock(shmem->base.resv);
  522. drm_gem_vm_open(vma);
  523. }
  524. static void drm_gem_shmem_vm_close(struct vm_area_struct *vma)
  525. {
  526. struct drm_gem_object *obj = vma->vm_private_data;
  527. struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
  528. dma_resv_lock(shmem->base.resv, NULL);
  529. drm_gem_shmem_put_pages_locked(shmem);
  530. dma_resv_unlock(shmem->base.resv);
  531. drm_gem_vm_close(vma);
  532. }
  533. const struct vm_operations_struct drm_gem_shmem_vm_ops = {
  534. .fault = drm_gem_shmem_fault,
  535. #ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
  536. .huge_fault = drm_gem_shmem_any_fault,
  537. #endif
  538. .open = drm_gem_shmem_vm_open,
  539. .close = drm_gem_shmem_vm_close,
  540. };
  541. EXPORT_SYMBOL_GPL(drm_gem_shmem_vm_ops);
  542. /**
  543. * drm_gem_shmem_mmap - Memory-map a shmem GEM object
  544. * @shmem: shmem GEM object
  545. * @vma: VMA for the area to be mapped
  546. *
  547. * This function implements an augmented version of the GEM DRM file mmap
  548. * operation for shmem objects.
  549. *
  550. * Returns:
  551. * 0 on success or a negative error code on failure.
  552. */
  553. int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct *vma)
  554. {
  555. struct drm_gem_object *obj = &shmem->base;
  556. int ret;
  557. if (drm_gem_is_imported(obj)) {
  558. /* Reset both vm_ops and vm_private_data, so we don't end up with
  559. * vm_ops pointing to our implementation if the dma-buf backend
  560. * doesn't set those fields.
  561. */
  562. vma->vm_private_data = NULL;
  563. vma->vm_ops = NULL;
  564. ret = dma_buf_mmap(obj->dma_buf, vma, 0);
  565. /* Drop the reference drm_gem_mmap_obj() acquired.*/
  566. if (!ret)
  567. drm_gem_object_put(obj);
  568. return ret;
  569. }
  570. if (is_cow_mapping(vma->vm_flags))
  571. return -EINVAL;
  572. dma_resv_lock(shmem->base.resv, NULL);
  573. ret = drm_gem_shmem_get_pages_locked(shmem);
  574. dma_resv_unlock(shmem->base.resv);
  575. if (ret)
  576. return ret;
  577. vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP);
  578. vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
  579. if (shmem->map_wc)
  580. vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  581. return 0;
  582. }
  583. EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap);
  584. /**
  585. * drm_gem_shmem_print_info() - Print &drm_gem_shmem_object info for debugfs
  586. * @shmem: shmem GEM object
  587. * @p: DRM printer
  588. * @indent: Tab indentation level
  589. */
  590. void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem,
  591. struct drm_printer *p, unsigned int indent)
  592. {
  593. if (drm_gem_is_imported(&shmem->base))
  594. return;
  595. drm_printf_indent(p, indent, "pages_pin_count=%u\n", refcount_read(&shmem->pages_pin_count));
  596. drm_printf_indent(p, indent, "pages_use_count=%u\n", refcount_read(&shmem->pages_use_count));
  597. drm_printf_indent(p, indent, "vmap_use_count=%u\n", refcount_read(&shmem->vmap_use_count));
  598. drm_printf_indent(p, indent, "vaddr=%p\n", shmem->vaddr);
  599. }
  600. EXPORT_SYMBOL_GPL(drm_gem_shmem_print_info);
  601. /**
  602. * drm_gem_shmem_get_sg_table - Provide a scatter/gather table of pinned
  603. * pages for a shmem GEM object
  604. * @shmem: shmem GEM object
  605. *
  606. * This function exports a scatter/gather table suitable for PRIME usage by
  607. * calling the standard DMA mapping API.
  608. *
  609. * Drivers who need to acquire an scatter/gather table for objects need to call
  610. * drm_gem_shmem_get_pages_sgt() instead.
  611. *
  612. * Returns:
  613. * A pointer to the scatter/gather table of pinned pages or error pointer on failure.
  614. */
  615. struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem)
  616. {
  617. struct drm_gem_object *obj = &shmem->base;
  618. drm_WARN_ON(obj->dev, drm_gem_is_imported(obj));
  619. return drm_prime_pages_to_sg(obj->dev, shmem->pages, obj->size >> PAGE_SHIFT);
  620. }
  621. EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table);
  622. static struct sg_table *drm_gem_shmem_get_pages_sgt_locked(struct drm_gem_shmem_object *shmem)
  623. {
  624. struct drm_gem_object *obj = &shmem->base;
  625. int ret;
  626. struct sg_table *sgt;
  627. if (shmem->sgt)
  628. return shmem->sgt;
  629. drm_WARN_ON(obj->dev, drm_gem_is_imported(obj));
  630. ret = drm_gem_shmem_get_pages_locked(shmem);
  631. if (ret)
  632. return ERR_PTR(ret);
  633. sgt = drm_gem_shmem_get_sg_table(shmem);
  634. if (IS_ERR(sgt)) {
  635. ret = PTR_ERR(sgt);
  636. goto err_put_pages;
  637. }
  638. /* Map the pages for use by the h/w. */
  639. ret = dma_map_sgtable(obj->dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
  640. if (ret)
  641. goto err_free_sgt;
  642. shmem->sgt = sgt;
  643. return sgt;
  644. err_free_sgt:
  645. sg_free_table(sgt);
  646. kfree(sgt);
  647. err_put_pages:
  648. drm_gem_shmem_put_pages_locked(shmem);
  649. return ERR_PTR(ret);
  650. }
  651. /**
  652. * drm_gem_shmem_get_pages_sgt - Pin pages, dma map them, and return a
  653. * scatter/gather table for a shmem GEM object.
  654. * @shmem: shmem GEM object
  655. *
  656. * This function returns a scatter/gather table suitable for driver usage. If
  657. * the sg table doesn't exist, the pages are pinned, dma-mapped, and a sg
  658. * table created.
  659. *
  660. * This is the main function for drivers to get at backing storage, and it hides
  661. * and difference between dma-buf imported and natively allocated objects.
  662. * drm_gem_shmem_get_sg_table() should not be directly called by drivers.
  663. *
  664. * Returns:
  665. * A pointer to the scatter/gather table of pinned pages or errno on failure.
  666. */
  667. struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem)
  668. {
  669. int ret;
  670. struct sg_table *sgt;
  671. ret = dma_resv_lock_interruptible(shmem->base.resv, NULL);
  672. if (ret)
  673. return ERR_PTR(ret);
  674. sgt = drm_gem_shmem_get_pages_sgt_locked(shmem);
  675. dma_resv_unlock(shmem->base.resv);
  676. return sgt;
  677. }
  678. EXPORT_SYMBOL_GPL(drm_gem_shmem_get_pages_sgt);
  679. /**
  680. * drm_gem_shmem_prime_import_sg_table - Produce a shmem GEM object from
  681. * another driver's scatter/gather table of pinned pages
  682. * @dev: Device to import into
  683. * @attach: DMA-BUF attachment
  684. * @sgt: Scatter/gather table of pinned pages
  685. *
  686. * This function imports a scatter/gather table exported via DMA-BUF by
  687. * another driver. Drivers that use the shmem helpers should set this as their
  688. * &drm_driver.gem_prime_import_sg_table callback.
  689. *
  690. * Returns:
  691. * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
  692. * error code on failure.
  693. */
  694. struct drm_gem_object *
  695. drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
  696. struct dma_buf_attachment *attach,
  697. struct sg_table *sgt)
  698. {
  699. size_t size = PAGE_ALIGN(attach->dmabuf->size);
  700. struct drm_gem_shmem_object *shmem;
  701. shmem = __drm_gem_shmem_create(dev, size, true);
  702. if (IS_ERR(shmem))
  703. return ERR_CAST(shmem);
  704. shmem->sgt = sgt;
  705. drm_dbg_prime(dev, "size = %zu\n", size);
  706. return &shmem->base;
  707. }
  708. EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_sg_table);
  709. /**
  710. * drm_gem_shmem_prime_import_no_map - Import dmabuf without mapping its sg_table
  711. * @dev: Device to import into
  712. * @dma_buf: dma-buf object to import
  713. *
  714. * Drivers that use the shmem helpers but also wants to import dmabuf without
  715. * mapping its sg_table can use this as their &drm_driver.gem_prime_import
  716. * implementation.
  717. */
  718. struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device *dev,
  719. struct dma_buf *dma_buf)
  720. {
  721. struct dma_buf_attachment *attach;
  722. struct drm_gem_shmem_object *shmem;
  723. struct drm_gem_object *obj;
  724. size_t size;
  725. int ret;
  726. if (drm_gem_is_prime_exported_dma_buf(dev, dma_buf)) {
  727. /*
  728. * Importing dmabuf exported from our own gem increases
  729. * refcount on gem itself instead of f_count of dmabuf.
  730. */
  731. obj = dma_buf->priv;
  732. drm_gem_object_get(obj);
  733. return obj;
  734. }
  735. attach = dma_buf_attach(dma_buf, dev->dev);
  736. if (IS_ERR(attach))
  737. return ERR_CAST(attach);
  738. get_dma_buf(dma_buf);
  739. size = PAGE_ALIGN(attach->dmabuf->size);
  740. shmem = __drm_gem_shmem_create(dev, size, true);
  741. if (IS_ERR(shmem)) {
  742. ret = PTR_ERR(shmem);
  743. goto fail_detach;
  744. }
  745. drm_dbg_prime(dev, "size = %zu\n", size);
  746. shmem->base.import_attach = attach;
  747. shmem->base.resv = dma_buf->resv;
  748. return &shmem->base;
  749. fail_detach:
  750. dma_buf_detach(dma_buf, attach);
  751. dma_buf_put(dma_buf);
  752. return ERR_PTR(ret);
  753. }
  754. EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_no_map);
  755. /*
  756. * Kunit helpers
  757. */
  758. #if IS_ENABLED(CONFIG_KUNIT)
  759. int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem, struct iosys_map *map)
  760. {
  761. struct drm_gem_object *obj = &shmem->base;
  762. int ret;
  763. ret = dma_resv_lock_interruptible(obj->resv, NULL);
  764. if (ret)
  765. return ret;
  766. ret = drm_gem_shmem_vmap_locked(shmem, map);
  767. dma_resv_unlock(obj->resv);
  768. return ret;
  769. }
  770. EXPORT_SYMBOL_IF_KUNIT(drm_gem_shmem_vmap);
  771. void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem, struct iosys_map *map)
  772. {
  773. struct drm_gem_object *obj = &shmem->base;
  774. dma_resv_lock_interruptible(obj->resv, NULL);
  775. drm_gem_shmem_vunmap_locked(shmem, map);
  776. dma_resv_unlock(obj->resv);
  777. }
  778. EXPORT_SYMBOL_IF_KUNIT(drm_gem_shmem_vunmap);
  779. int drm_gem_shmem_madvise(struct drm_gem_shmem_object *shmem, int madv)
  780. {
  781. struct drm_gem_object *obj = &shmem->base;
  782. int ret;
  783. ret = dma_resv_lock_interruptible(obj->resv, NULL);
  784. if (ret)
  785. return ret;
  786. ret = drm_gem_shmem_madvise_locked(shmem, madv);
  787. dma_resv_unlock(obj->resv);
  788. return ret;
  789. }
  790. EXPORT_SYMBOL_IF_KUNIT(drm_gem_shmem_madvise);
  791. int drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem)
  792. {
  793. struct drm_gem_object *obj = &shmem->base;
  794. int ret;
  795. ret = dma_resv_lock_interruptible(obj->resv, NULL);
  796. if (ret)
  797. return ret;
  798. drm_gem_shmem_purge_locked(shmem);
  799. dma_resv_unlock(obj->resv);
  800. return 0;
  801. }
  802. EXPORT_SYMBOL_IF_KUNIT(drm_gem_shmem_purge);
  803. #endif
  804. MODULE_DESCRIPTION("DRM SHMEM memory-management helpers");
  805. MODULE_IMPORT_NS("DMA_BUF");
  806. MODULE_LICENSE("GPL");