xref: /linux/drivers/gpu/drm/virtio/virtgpu_vram.c (revision 4b99990cdf9560e8a071640baf19f312e6ae02f4)
1 // SPDX-License-Identifier: GPL-2.0
2 #include "virtgpu_drv.h"
3 
4 #include <linux/dma-mapping.h>
5 
6 static DEFINE_MUTEX(map_lock);
7 
8 static void virtio_gpu_vram_free(struct drm_gem_object *obj)
9 {
10 	struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
11 	struct virtio_gpu_device *vgdev = obj->dev->dev_private;
12 	struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
13 	bool unmap;
14 
15 	if (bo->created) {
16 		spin_lock(&vgdev->host_visible_lock);
17 		unmap = drm_mm_node_allocated(&vram->vram_node);
18 		spin_unlock(&vgdev->host_visible_lock);
19 
20 		if (unmap)
21 			virtio_gpu_cmd_unmap(vgdev, bo);
22 
23 		virtio_gpu_cmd_unref_resource(vgdev, bo);
24 		virtio_gpu_notify(vgdev);
25 		return;
26 	}
27 }
28 
29 static const struct vm_operations_struct virtio_gpu_vram_vm_ops = {
30 	.open = drm_gem_vm_open,
31 	.close = drm_gem_vm_close,
32 };
33 
34 static int virtio_gpu_vram_mmap(struct drm_gem_object *obj,
35 				struct vm_area_struct *vma)
36 {
37 	int ret;
38 	struct virtio_gpu_device *vgdev = obj->dev->dev_private;
39 	struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
40 	struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
41 	unsigned long vm_size = vma->vm_end - vma->vm_start;
42 	unsigned long vm_end;
43 
44 	if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
45 		return -EINVAL;
46 
47 	virtio_gpu_vram_map_deferred(vram);
48 
49 	if (vram->map_state == STATE_INITIALIZING)
50 		virtio_gpu_notify(vgdev);
51 
52 	wait_event(vgdev->resp_wq, vram->map_state != STATE_INITIALIZING);
53 	if (vram->map_state != STATE_OK)
54 		return -EINVAL;
55 
56 	vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
57 	vm_flags_set(vma, VM_MIXEDMAP | VM_DONTEXPAND);
58 	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
59 	vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
60 	vma->vm_ops = &virtio_gpu_vram_vm_ops;
61 
62 	if (vram->map_info == VIRTIO_GPU_MAP_CACHE_WC)
63 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
64 	else if (vram->map_info == VIRTIO_GPU_MAP_CACHE_UNCACHED)
65 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
66 
67 	if (check_add_overflow(vma->vm_pgoff << PAGE_SHIFT, vm_size, &vm_end))
68 		return -EINVAL;
69 
70 	if (vm_end > vram->vram_node.size)
71 		return -EINVAL;
72 
73 	ret = io_remap_pfn_range(vma, vma->vm_start,
74 				 (vram->vram_node.start >> PAGE_SHIFT) + vma->vm_pgoff,
75 				 vm_size, vma->vm_page_prot);
76 	return ret;
77 }
78 
79 struct sg_table *virtio_gpu_vram_map_dma_buf(struct virtio_gpu_object *bo,
80 					     struct device *dev,
81 					     enum dma_data_direction dir)
82 {
83 	struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
84 	struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
85 	struct sg_table *sgt;
86 	dma_addr_t addr;
87 	int ret;
88 
89 	sgt = kzalloc_obj(*sgt);
90 	if (!sgt)
91 		return ERR_PTR(-ENOMEM);
92 
93 	if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE)) {
94 		// Virtio devices can access the dma-buf via its UUID. Return a stub
95 		// sg_table so the dma-buf API still works.
96 		if (!is_virtio_device(dev) || !vgdev->has_resource_assign_uuid) {
97 			ret = -EIO;
98 			goto out;
99 		}
100 		return sgt;
101 	}
102 
103 	ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
104 	if (ret)
105 		goto out;
106 
107 	addr = dma_map_resource(dev, vram->vram_node.start,
108 				vram->vram_node.size, dir,
109 				DMA_ATTR_SKIP_CPU_SYNC);
110 	ret = dma_mapping_error(dev, addr);
111 	if (ret)
112 		goto out;
113 
114 	sg_set_page(sgt->sgl, NULL, vram->vram_node.size, 0);
115 	sg_dma_address(sgt->sgl) = addr;
116 	sg_dma_len(sgt->sgl) = vram->vram_node.size;
117 
118 	return sgt;
119 out:
120 	sg_free_table(sgt);
121 	kfree(sgt);
122 	return ERR_PTR(ret);
123 }
124 
125 void virtio_gpu_vram_unmap_dma_buf(struct device *dev,
126 				   struct sg_table *sgt,
127 				   enum dma_data_direction dir)
128 {
129 	if (sgt->nents) {
130 		dma_unmap_resource(dev, sg_dma_address(sgt->sgl),
131 				   sg_dma_len(sgt->sgl), dir,
132 				   DMA_ATTR_SKIP_CPU_SYNC);
133 	}
134 	sg_free_table(sgt);
135 	kfree(sgt);
136 }
137 
138 static const struct drm_gem_object_funcs virtio_gpu_vram_funcs = {
139 	.open = virtio_gpu_gem_object_open,
140 	.close = virtio_gpu_gem_object_close,
141 	.free = virtio_gpu_vram_free,
142 	.mmap = virtio_gpu_vram_mmap,
143 	.export = virtgpu_gem_prime_export,
144 };
145 
146 bool virtio_gpu_is_vram(struct virtio_gpu_object *bo)
147 {
148 	return bo->base.base.funcs == &virtio_gpu_vram_funcs;
149 }
150 
151 static int virtio_gpu_vram_map(struct virtio_gpu_object *bo)
152 {
153 	int ret;
154 	uint64_t offset;
155 	struct virtio_gpu_object_array *objs;
156 	struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
157 	struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
158 
159 	if (!vgdev->has_host_visible)
160 		return -EINVAL;
161 
162 	spin_lock(&vgdev->host_visible_lock);
163 	ret = drm_mm_insert_node(&vgdev->host_visible_mm, &vram->vram_node,
164 				 bo->base.base.size);
165 	spin_unlock(&vgdev->host_visible_lock);
166 
167 	if (ret)
168 		return ret;
169 
170 	objs = virtio_gpu_array_alloc(1);
171 	if (!objs) {
172 		ret = -ENOMEM;
173 		goto err_remove_node;
174 	}
175 
176 	virtio_gpu_array_add_obj(objs, &bo->base.base);
177 	/*TODO: Add an error checking helper function in drm_mm.h */
178 	offset = vram->vram_node.start - vgdev->host_visible_region.addr;
179 
180 	ret = virtio_gpu_cmd_map(vgdev, objs, offset);
181 	if (ret) {
182 		virtio_gpu_array_put_free(objs);
183 		goto err_remove_node;
184 	}
185 
186 	return 0;
187 
188 err_remove_node:
189 	spin_lock(&vgdev->host_visible_lock);
190 	drm_mm_remove_node(&vram->vram_node);
191 	spin_unlock(&vgdev->host_visible_lock);
192 	return ret;
193 }
194 
195 int virtio_gpu_vram_create(struct virtio_gpu_device *vgdev,
196 			   struct virtio_gpu_object_params *params,
197 			   struct virtio_gpu_object **bo_ptr)
198 {
199 	struct drm_gem_object *obj;
200 	struct virtio_gpu_object_vram *vram;
201 	int ret;
202 
203 	vram = kzalloc_obj(*vram);
204 	if (!vram)
205 		return -ENOMEM;
206 
207 	obj = &vram->base.base.base;
208 	obj->funcs = &virtio_gpu_vram_funcs;
209 
210 	params->size = PAGE_ALIGN(params->size);
211 	drm_gem_private_object_init(vgdev->ddev, obj, params->size);
212 
213 	/* Create fake offset */
214 	ret = drm_gem_create_mmap_offset(obj);
215 	if (ret) {
216 		kfree(vram);
217 		return ret;
218 	}
219 
220 	ret = virtio_gpu_resource_id_get(vgdev, &vram->base.hw_res_handle);
221 	if (ret) {
222 		kfree(vram);
223 		return ret;
224 	}
225 
226 	virtio_gpu_cmd_resource_create_blob(vgdev, &vram->base, params, NULL,
227 					    0);
228 	if (!(params->blob_hints & DRM_VIRTGPU_BLOB_FLAG_HINT_DEFER_MAPPING)) {
229 		if (params->blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE) {
230 			ret = virtio_gpu_vram_map(&vram->base);
231 			if (ret) {
232 				virtio_gpu_vram_free(obj);
233 				return ret;
234 			}
235 		}
236 	}
237 
238 	*bo_ptr = &vram->base;
239 	return 0;
240 }
241 
242 void virtio_gpu_vram_map_deferred(struct virtio_gpu_object_vram *vram)
243 {
244 	if (!(vram->base.blob_flags & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
245 		return;
246 
247 	mutex_lock(&map_lock);
248 	if (!drm_mm_node_allocated(&vram->vram_node))
249 		virtio_gpu_vram_map(&vram->base);
250 	mutex_unlock(&map_lock);
251 }
252