pvr_gem.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. // SPDX-License-Identifier: GPL-2.0-only OR MIT
  2. /* Copyright (c) 2023 Imagination Technologies Ltd. */
  3. #include "pvr_device.h"
  4. #include "pvr_gem.h"
  5. #include "pvr_vm.h"
  6. #include <drm/drm_gem.h>
  7. #include <drm/drm_prime.h>
  8. #include <linux/compiler.h>
  9. #include <linux/compiler_attributes.h>
  10. #include <linux/dma-buf.h>
  11. #include <linux/dma-direction.h>
  12. #include <linux/dma-mapping.h>
  13. #include <linux/err.h>
  14. #include <linux/gfp.h>
  15. #include <linux/iosys-map.h>
  16. #include <linux/log2.h>
  17. #include <linux/mutex.h>
  18. #include <linux/pagemap.h>
  19. #include <linux/refcount.h>
  20. #include <linux/scatterlist.h>
  21. static void pvr_gem_object_free(struct drm_gem_object *obj)
  22. {
  23. drm_gem_shmem_object_free(obj);
  24. }
  25. static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *vma)
  26. {
  27. struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(gem_obj);
  28. struct drm_gem_shmem_object *shmem_obj = shmem_gem_from_pvr_gem(pvr_obj);
  29. if (!(pvr_obj->flags & DRM_PVR_BO_ALLOW_CPU_USERSPACE_ACCESS))
  30. return -EINVAL;
  31. return drm_gem_shmem_mmap(shmem_obj, vma);
  32. }
  33. static const struct drm_gem_object_funcs pvr_gem_object_funcs = {
  34. .free = pvr_gem_object_free,
  35. .print_info = drm_gem_shmem_object_print_info,
  36. .pin = drm_gem_shmem_object_pin,
  37. .unpin = drm_gem_shmem_object_unpin,
  38. .get_sg_table = drm_gem_shmem_object_get_sg_table,
  39. .vmap = drm_gem_shmem_object_vmap,
  40. .vunmap = drm_gem_shmem_object_vunmap,
  41. .mmap = pvr_gem_mmap,
  42. .vm_ops = &drm_gem_shmem_vm_ops,
  43. };
  44. /**
  45. * pvr_gem_object_flags_validate() - Verify that a collection of PowerVR GEM
  46. * mapping and/or creation flags form a valid combination.
  47. * @flags: PowerVR GEM mapping/creation flags to validate.
  48. *
  49. * This function explicitly allows kernel-only flags. All ioctl entrypoints
  50. * should do their own validation as well as relying on this function.
  51. *
  52. * Return:
  53. * * %true if @flags contains valid mapping and/or creation flags, or
  54. * * %false otherwise.
  55. */
  56. static bool
  57. pvr_gem_object_flags_validate(u64 flags)
  58. {
  59. static const u64 invalid_combinations[] = {
  60. /*
  61. * Memory flagged as PM/FW-protected cannot be mapped to
  62. * userspace. To make this explicit, we require that the two
  63. * flags allowing each of these respective features are never
  64. * specified together.
  65. */
  66. (DRM_PVR_BO_PM_FW_PROTECT |
  67. DRM_PVR_BO_ALLOW_CPU_USERSPACE_ACCESS),
  68. };
  69. int i;
  70. /*
  71. * Check for bits set in undefined regions. Reserved regions refer to
  72. * options that can only be set by the kernel. These are explicitly
  73. * allowed in most cases, and must be checked specifically in IOCTL
  74. * callback code.
  75. */
  76. if ((flags & PVR_BO_UNDEFINED_MASK) != 0)
  77. return false;
  78. /*
  79. * Check for all combinations of flags marked as invalid in the array
  80. * above.
  81. */
  82. for (i = 0; i < ARRAY_SIZE(invalid_combinations); ++i) {
  83. u64 combo = invalid_combinations[i];
  84. if ((flags & combo) == combo)
  85. return false;
  86. }
  87. return true;
  88. }
  89. /**
  90. * pvr_gem_object_into_handle() - Convert a reference to an object into a
  91. * userspace-accessible handle.
  92. * @pvr_obj: [IN] Target PowerVR-specific object.
  93. * @pvr_file: [IN] File to associate the handle with.
  94. * @handle: [OUT] Pointer to store the created handle in. Remains unmodified if
  95. * an error is encountered.
  96. *
  97. * If an error is encountered, ownership of @pvr_obj will not have been
  98. * transferred. If this function succeeds, however, further use of @pvr_obj is
  99. * considered undefined behaviour unless another reference to it is explicitly
  100. * held.
  101. *
  102. * Return:
  103. * * 0 on success, or
  104. * * Any error encountered while attempting to allocate a handle on @pvr_file.
  105. */
  106. int
  107. pvr_gem_object_into_handle(struct pvr_gem_object *pvr_obj,
  108. struct pvr_file *pvr_file, u32 *handle)
  109. {
  110. struct drm_gem_object *gem_obj = gem_from_pvr_gem(pvr_obj);
  111. struct drm_file *file = from_pvr_file(pvr_file);
  112. u32 new_handle;
  113. int err;
  114. err = drm_gem_handle_create(file, gem_obj, &new_handle);
  115. if (err)
  116. return err;
  117. /*
  118. * Release our reference to @pvr_obj, effectively transferring
  119. * ownership to the handle.
  120. */
  121. pvr_gem_object_put(pvr_obj);
  122. /*
  123. * Do not store the new handle in @handle until no more errors can
  124. * occur.
  125. */
  126. *handle = new_handle;
  127. return 0;
  128. }
  129. /**
  130. * pvr_gem_object_from_handle() - Obtain a reference to an object from a
  131. * userspace handle.
  132. * @pvr_file: PowerVR-specific file to which @handle is associated.
  133. * @handle: Userspace handle referencing the target object.
  134. *
  135. * On return, @handle always maintains its reference to the requested object
  136. * (if it had one in the first place). If this function succeeds, the returned
  137. * object will hold an additional reference. When the caller is finished with
  138. * the returned object, they should call pvr_gem_object_put() on it to release
  139. * this reference.
  140. *
  141. * Return:
  142. * * A pointer to the requested PowerVR-specific object on success, or
  143. * * %NULL otherwise.
  144. */
  145. struct pvr_gem_object *
  146. pvr_gem_object_from_handle(struct pvr_file *pvr_file, u32 handle)
  147. {
  148. struct drm_file *file = from_pvr_file(pvr_file);
  149. struct drm_gem_object *gem_obj;
  150. gem_obj = drm_gem_object_lookup(file, handle);
  151. if (!gem_obj)
  152. return NULL;
  153. return gem_to_pvr_gem(gem_obj);
  154. }
  155. /**
  156. * pvr_gem_object_vmap() - Map a PowerVR GEM object into CPU virtual address
  157. * space.
  158. * @pvr_obj: Target PowerVR GEM object.
  159. *
  160. * Once the caller is finished with the CPU mapping, they must call
  161. * pvr_gem_object_vunmap() on @pvr_obj.
  162. *
  163. * If @pvr_obj is CPU-cached, dma_sync_sgtable_for_cpu() is called to make
  164. * sure the CPU mapping is consistent.
  165. *
  166. * Return:
  167. * * A pointer to the CPU mapping on success,
  168. * * -%ENOMEM if the mapping fails, or
  169. * * Any error encountered while attempting to acquire a reference to the
  170. * backing pages for @pvr_obj.
  171. */
  172. void *
  173. pvr_gem_object_vmap(struct pvr_gem_object *pvr_obj)
  174. {
  175. struct drm_gem_shmem_object *shmem_obj = shmem_gem_from_pvr_gem(pvr_obj);
  176. struct drm_gem_object *obj = gem_from_pvr_gem(pvr_obj);
  177. struct iosys_map map;
  178. int err;
  179. dma_resv_lock(obj->resv, NULL);
  180. err = drm_gem_shmem_vmap(shmem_obj, &map);
  181. if (err)
  182. goto err_unlock;
  183. if (pvr_obj->flags & PVR_BO_CPU_CACHED) {
  184. struct device *dev = shmem_obj->base.dev->dev;
  185. /* If shmem_obj->sgt is NULL, that means the buffer hasn't been mapped
  186. * in GPU space yet.
  187. */
  188. if (shmem_obj->sgt)
  189. dma_sync_sgtable_for_cpu(dev, shmem_obj->sgt, DMA_BIDIRECTIONAL);
  190. }
  191. dma_resv_unlock(obj->resv);
  192. return map.vaddr;
  193. err_unlock:
  194. dma_resv_unlock(obj->resv);
  195. return ERR_PTR(err);
  196. }
  197. /**
  198. * pvr_gem_object_vunmap() - Unmap a PowerVR memory object from CPU virtual
  199. * address space.
  200. * @pvr_obj: Target PowerVR GEM object.
  201. *
  202. * If @pvr_obj is CPU-cached, dma_sync_sgtable_for_device() is called to make
  203. * sure the GPU mapping is consistent.
  204. */
  205. void
  206. pvr_gem_object_vunmap(struct pvr_gem_object *pvr_obj)
  207. {
  208. struct drm_gem_shmem_object *shmem_obj = shmem_gem_from_pvr_gem(pvr_obj);
  209. struct iosys_map map = IOSYS_MAP_INIT_VADDR(shmem_obj->vaddr);
  210. struct drm_gem_object *obj = gem_from_pvr_gem(pvr_obj);
  211. if (WARN_ON(!map.vaddr))
  212. return;
  213. dma_resv_lock(obj->resv, NULL);
  214. if (pvr_obj->flags & PVR_BO_CPU_CACHED) {
  215. struct device *dev = shmem_obj->base.dev->dev;
  216. /* If shmem_obj->sgt is NULL, that means the buffer hasn't been mapped
  217. * in GPU space yet.
  218. */
  219. if (shmem_obj->sgt)
  220. dma_sync_sgtable_for_device(dev, shmem_obj->sgt, DMA_BIDIRECTIONAL);
  221. }
  222. drm_gem_shmem_vunmap(shmem_obj, &map);
  223. dma_resv_unlock(obj->resv);
  224. }
  225. /**
  226. * pvr_gem_object_zero() - Zeroes the physical memory behind an object.
  227. * @pvr_obj: Target PowerVR GEM object.
  228. *
  229. * Return:
  230. * * 0 on success, or
  231. * * Any error encountered while attempting to map @pvr_obj to the CPU (see
  232. * pvr_gem_object_vmap()).
  233. */
  234. static int
  235. pvr_gem_object_zero(struct pvr_gem_object *pvr_obj)
  236. {
  237. void *cpu_ptr;
  238. cpu_ptr = pvr_gem_object_vmap(pvr_obj);
  239. if (IS_ERR(cpu_ptr))
  240. return PTR_ERR(cpu_ptr);
  241. memset(cpu_ptr, 0, pvr_gem_object_size(pvr_obj));
  242. /* Make sure the zero-ing is done before vumap-ing the object. */
  243. wmb();
  244. pvr_gem_object_vunmap(pvr_obj);
  245. return 0;
  246. }
  247. /**
  248. * pvr_gem_create_object() - Allocate and pre-initializes a pvr_gem_object
  249. * @drm_dev: DRM device creating this object.
  250. * @size: Size of the object to allocate in bytes.
  251. *
  252. * Return:
  253. * * The new pre-initialized GEM object on success,
  254. * * -ENOMEM if the allocation failed.
  255. */
  256. struct drm_gem_object *pvr_gem_create_object(struct drm_device *drm_dev, size_t size)
  257. {
  258. struct drm_gem_object *gem_obj;
  259. struct pvr_gem_object *pvr_obj;
  260. pvr_obj = kzalloc(sizeof(*pvr_obj), GFP_KERNEL);
  261. if (!pvr_obj)
  262. return ERR_PTR(-ENOMEM);
  263. gem_obj = gem_from_pvr_gem(pvr_obj);
  264. gem_obj->funcs = &pvr_gem_object_funcs;
  265. return gem_obj;
  266. }
  267. /**
  268. * pvr_gem_object_create() - Creates a PowerVR-specific buffer object.
  269. * @pvr_dev: Target PowerVR device.
  270. * @size: Size of the object to allocate in bytes. Must be greater than zero.
  271. * Any value which is not an exact multiple of the system page size will be
  272. * rounded up to satisfy this condition.
  273. * @flags: Options which affect both this operation and future mapping
  274. * operations performed on the returned object. Must be a combination of
  275. * DRM_PVR_BO_* and/or PVR_BO_* flags.
  276. *
  277. * The created object may be larger than @size, but can never be smaller. To
  278. * get the exact size, call pvr_gem_object_size() on the returned pointer.
  279. *
  280. * Return:
  281. * * The newly-minted PowerVR-specific buffer object on success,
  282. * * -%EINVAL if @size is zero or @flags is not valid,
  283. * * -%ENOMEM if sufficient physical memory cannot be allocated, or
  284. * * Any other error returned by drm_gem_create_mmap_offset().
  285. */
  286. struct pvr_gem_object *
  287. pvr_gem_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags)
  288. {
  289. struct drm_gem_shmem_object *shmem_obj;
  290. struct pvr_gem_object *pvr_obj;
  291. struct sg_table *sgt;
  292. int err;
  293. /* Verify @size and @flags before continuing. */
  294. if (size == 0 || !pvr_gem_object_flags_validate(flags))
  295. return ERR_PTR(-EINVAL);
  296. shmem_obj = drm_gem_shmem_create(from_pvr_device(pvr_dev), size);
  297. if (IS_ERR(shmem_obj))
  298. return ERR_CAST(shmem_obj);
  299. shmem_obj->pages_mark_dirty_on_put = true;
  300. shmem_obj->map_wc = !(flags & PVR_BO_CPU_CACHED);
  301. pvr_obj = shmem_gem_to_pvr_gem(shmem_obj);
  302. pvr_obj->flags = flags;
  303. sgt = drm_gem_shmem_get_pages_sgt(shmem_obj);
  304. if (IS_ERR(sgt)) {
  305. err = PTR_ERR(sgt);
  306. goto err_shmem_object_free;
  307. }
  308. dma_sync_sgtable_for_device(shmem_obj->base.dev->dev, sgt,
  309. DMA_BIDIRECTIONAL);
  310. /*
  311. * Do this last because pvr_gem_object_zero() requires a fully
  312. * configured instance of struct pvr_gem_object.
  313. */
  314. pvr_gem_object_zero(pvr_obj);
  315. return pvr_obj;
  316. err_shmem_object_free:
  317. drm_gem_shmem_free(shmem_obj);
  318. return ERR_PTR(err);
  319. }
  320. /**
  321. * pvr_gem_get_dma_addr() - Get DMA address for given offset in object
  322. * @pvr_obj: Pointer to object to lookup address in.
  323. * @offset: Offset within object to lookup address at.
  324. * @dma_addr_out: Pointer to location to store DMA address.
  325. *
  326. * Returns:
  327. * * 0 on success, or
  328. * * -%EINVAL if object is not currently backed, or if @offset is out of valid
  329. * range for this object.
  330. */
  331. int
  332. pvr_gem_get_dma_addr(struct pvr_gem_object *pvr_obj, u32 offset,
  333. dma_addr_t *dma_addr_out)
  334. {
  335. struct drm_gem_shmem_object *shmem_obj = shmem_gem_from_pvr_gem(pvr_obj);
  336. u32 accumulated_offset = 0;
  337. struct scatterlist *sgl;
  338. unsigned int sgt_idx;
  339. WARN_ON(!shmem_obj->sgt);
  340. for_each_sgtable_dma_sg(shmem_obj->sgt, sgl, sgt_idx) {
  341. u32 new_offset = accumulated_offset + sg_dma_len(sgl);
  342. if (offset >= accumulated_offset && offset < new_offset) {
  343. *dma_addr_out = sg_dma_address(sgl) +
  344. (offset - accumulated_offset);
  345. return 0;
  346. }
  347. accumulated_offset = new_offset;
  348. }
  349. return -EINVAL;
  350. }