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