1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /**************************************************************************
3  *
4  * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include "vmwgfx_drv.h"
29 #include <drm/vmwgfx_drm.h>
30 #include "vmwgfx_kms.h"
31 #include "device_include/svga3d_caps.h"
32 
33 struct svga_3d_compat_cap {
34 	SVGA3dCapsRecordHeader header;
35 	SVGA3dCapPair pairs[SVGA3D_DEVCAP_MAX];
36 };
37 
38 int vmw_getparam_ioctl(struct drm_device *dev, void *data,
39 		       struct drm_file *file_priv)
40 {
41 	struct vmw_private *dev_priv = vmw_priv(dev);
42 	struct drm_vmw_getparam_arg *param =
43 	    (struct drm_vmw_getparam_arg *)data;
44 	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
45 
46 	switch (param->param) {
47 	case DRM_VMW_PARAM_NUM_STREAMS:
48 		param->value = vmw_overlay_num_overlays(dev_priv);
49 		break;
50 	case DRM_VMW_PARAM_NUM_FREE_STREAMS:
51 		param->value = vmw_overlay_num_free_overlays(dev_priv);
52 		break;
53 	case DRM_VMW_PARAM_3D:
54 		param->value = vmw_supports_3d(dev_priv) ? 1 : 0;
55 		break;
56 	case DRM_VMW_PARAM_HW_CAPS:
57 		param->value = dev_priv->capabilities;
58 		break;
59 	case DRM_VMW_PARAM_HW_CAPS2:
60 		param->value = dev_priv->capabilities2;
61 		break;
62 	case DRM_VMW_PARAM_FIFO_CAPS:
63 		param->value = vmw_fifo_caps(dev_priv);
64 		break;
65 	case DRM_VMW_PARAM_MAX_FB_SIZE:
66 		param->value = dev_priv->prim_bb_mem;
67 		break;
68 	case DRM_VMW_PARAM_FIFO_HW_VERSION:
69 	{
70 		if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) {
71 			param->value = SVGA3D_HWVERSION_WS8_B1;
72 			break;
73 		}
74 
75 		param->value =
76 			vmw_fifo_mem_read(dev_priv,
77 					  ((vmw_fifo_caps(dev_priv) &
78 					    SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
79 						   SVGA_FIFO_3D_HWVERSION_REVISED :
80 						   SVGA_FIFO_3D_HWVERSION));
81 		break;
82 	}
83 	case DRM_VMW_PARAM_MAX_SURF_MEMORY:
84 		if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
85 		    !vmw_fp->gb_aware)
86 			param->value = dev_priv->max_mob_pages * PAGE_SIZE / 2;
87 		else
88 			param->value = dev_priv->memory_size;
89 		break;
90 	case DRM_VMW_PARAM_3D_CAPS_SIZE:
91 		if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
92 		    vmw_fp->gb_aware)
93 			param->value = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
94 		else if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
95 			param->value = sizeof(struct svga_3d_compat_cap) +
96 				sizeof(uint32_t);
97 		else
98 			param->value = (SVGA_FIFO_3D_CAPS_LAST -
99 					SVGA_FIFO_3D_CAPS + 1) *
100 				sizeof(uint32_t);
101 		break;
102 	case DRM_VMW_PARAM_MAX_MOB_MEMORY:
103 		vmw_fp->gb_aware = true;
104 		param->value = dev_priv->max_mob_pages * PAGE_SIZE;
105 		break;
106 	case DRM_VMW_PARAM_MAX_MOB_SIZE:
107 		param->value = dev_priv->max_mob_size;
108 		break;
109 	case DRM_VMW_PARAM_SCREEN_TARGET:
110 		param->value =
111 			(dev_priv->active_display_unit == vmw_du_screen_target);
112 		break;
113 	case DRM_VMW_PARAM_DX:
114 		param->value = has_sm4_context(dev_priv);
115 		break;
116 	case DRM_VMW_PARAM_SM4_1:
117 		param->value = has_sm4_1_context(dev_priv);
118 		break;
119 	case DRM_VMW_PARAM_SM5:
120 		param->value = has_sm5_context(dev_priv);
121 		break;
122 	default:
123 		return -EINVAL;
124 	}
125 
126 	return 0;
127 }
128 
129 static u32 vmw_mask_legacy_multisample(unsigned int cap, u32 fmt_value)
130 {
131 	/*
132 	 * A version of user-space exists which use MULTISAMPLE_MASKABLESAMPLES
133 	 * to check the sample count supported by virtual device. Since there
134 	 * never was support for multisample count for backing MOB return 0.
135 	 *
136 	 * MULTISAMPLE_MASKABLESAMPLES devcap is marked as deprecated by virtual
137 	 * device.
138 	 */
139 	if (cap == SVGA3D_DEVCAP_DEAD5)
140 		return 0;
141 
142 	return fmt_value;
143 }
144 
145 static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
146 			       size_t size)
147 {
148 	struct svga_3d_compat_cap *compat_cap =
149 		(struct svga_3d_compat_cap *) bounce;
150 	unsigned int i;
151 	size_t pair_offset = offsetof(struct svga_3d_compat_cap, pairs);
152 	unsigned int max_size;
153 
154 	if (size < pair_offset)
155 		return -EINVAL;
156 
157 	max_size = (size - pair_offset) / sizeof(SVGA3dCapPair);
158 
159 	if (max_size > SVGA3D_DEVCAP_MAX)
160 		max_size = SVGA3D_DEVCAP_MAX;
161 
162 	compat_cap->header.length =
163 		(pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32);
164 	compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
165 
166 	spin_lock(&dev_priv->cap_lock);
167 	for (i = 0; i < max_size; ++i) {
168 		vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
169 		compat_cap->pairs[i][0] = i;
170 		compat_cap->pairs[i][1] = vmw_mask_legacy_multisample
171 			(i, vmw_read(dev_priv, SVGA_REG_DEV_CAP));
172 	}
173 	spin_unlock(&dev_priv->cap_lock);
174 
175 	return 0;
176 }
177 
178 
179 int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
180 			 struct drm_file *file_priv)
181 {
182 	struct drm_vmw_get_3d_cap_arg *arg =
183 		(struct drm_vmw_get_3d_cap_arg *) data;
184 	struct vmw_private *dev_priv = vmw_priv(dev);
185 	uint32_t size;
186 	u32 *fifo_mem;
187 	void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
188 	void *bounce;
189 	int ret;
190 	bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
191 	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
192 
193 	if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {
194 		VMW_DEBUG_USER("Illegal GET_3D_CAP argument.\n");
195 		return -EINVAL;
196 	}
197 
198 	if (gb_objects && vmw_fp->gb_aware)
199 		size = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
200 	else if (gb_objects)
201 		size = sizeof(struct svga_3d_compat_cap) + sizeof(uint32_t);
202 	else
203 		size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) *
204 			sizeof(uint32_t);
205 
206 	if (arg->max_size < size)
207 		size = arg->max_size;
208 
209 	bounce = vzalloc(size);
210 	if (unlikely(bounce == NULL)) {
211 		DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
212 		return -ENOMEM;
213 	}
214 
215 	if (gb_objects && vmw_fp->gb_aware) {
216 		int i, num;
217 		uint32_t *bounce32 = (uint32_t *) bounce;
218 
219 		num = size / sizeof(uint32_t);
220 		if (num > SVGA3D_DEVCAP_MAX)
221 			num = SVGA3D_DEVCAP_MAX;
222 
223 		spin_lock(&dev_priv->cap_lock);
224 		for (i = 0; i < num; ++i) {
225 			vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
226 			*bounce32++ = vmw_mask_legacy_multisample
227 				(i, vmw_read(dev_priv, SVGA_REG_DEV_CAP));
228 		}
229 		spin_unlock(&dev_priv->cap_lock);
230 	} else if (gb_objects) {
231 		ret = vmw_fill_compat_cap(dev_priv, bounce, size);
232 		if (unlikely(ret != 0))
233 			goto out_err;
234 	} else {
235 		fifo_mem = dev_priv->fifo_mem;
236 		memcpy(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
237 	}
238 
239 	ret = copy_to_user(buffer, bounce, size);
240 	if (ret)
241 		ret = -EFAULT;
242 out_err:
243 	vfree(bounce);
244 
245 	if (unlikely(ret != 0))
246 		DRM_ERROR("Failed to report 3D caps info.\n");
247 
248 	return ret;
249 }
250 
251 int vmw_present_ioctl(struct drm_device *dev, void *data,
252 		      struct drm_file *file_priv)
253 {
254 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
255 	struct vmw_private *dev_priv = vmw_priv(dev);
256 	struct drm_vmw_present_arg *arg =
257 		(struct drm_vmw_present_arg *)data;
258 	struct vmw_surface *surface;
259 	struct drm_vmw_rect __user *clips_ptr;
260 	struct drm_vmw_rect *clips = NULL;
261 	struct drm_framebuffer *fb;
262 	struct vmw_framebuffer *vfb;
263 	struct vmw_resource *res;
264 	uint32_t num_clips;
265 	int ret;
266 
267 	num_clips = arg->num_clips;
268 	clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
269 
270 	if (unlikely(num_clips == 0))
271 		return 0;
272 
273 	if (clips_ptr == NULL) {
274 		VMW_DEBUG_USER("Variable clips_ptr must be specified.\n");
275 		ret = -EINVAL;
276 		goto out_clips;
277 	}
278 
279 	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
280 	if (clips == NULL) {
281 		DRM_ERROR("Failed to allocate clip rect list.\n");
282 		ret = -ENOMEM;
283 		goto out_clips;
284 	}
285 
286 	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
287 	if (ret) {
288 		DRM_ERROR("Failed to copy clip rects from userspace.\n");
289 		ret = -EFAULT;
290 		goto out_no_copy;
291 	}
292 
293 	drm_modeset_lock_all(dev);
294 
295 	fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
296 	if (!fb) {
297 		VMW_DEBUG_USER("Invalid framebuffer id.\n");
298 		ret = -ENOENT;
299 		goto out_no_fb;
300 	}
301 	vfb = vmw_framebuffer_to_vfb(fb);
302 
303 	ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid,
304 					      user_surface_converter,
305 					      &res);
306 	if (ret)
307 		goto out_no_surface;
308 
309 	surface = vmw_res_to_srf(res);
310 	ret = vmw_kms_present(dev_priv, file_priv,
311 			      vfb, surface, arg->sid,
312 			      arg->dest_x, arg->dest_y,
313 			      clips, num_clips);
314 
315 	/* vmw_user_surface_lookup takes one ref so does new_fb */
316 	vmw_surface_unreference(&surface);
317 
318 out_no_surface:
319 	drm_framebuffer_put(fb);
320 out_no_fb:
321 	drm_modeset_unlock_all(dev);
322 out_no_copy:
323 	kfree(clips);
324 out_clips:
325 	return ret;
326 }
327 
328 int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
329 			       struct drm_file *file_priv)
330 {
331 	struct vmw_private *dev_priv = vmw_priv(dev);
332 	struct drm_vmw_present_readback_arg *arg =
333 		(struct drm_vmw_present_readback_arg *)data;
334 	struct drm_vmw_fence_rep __user *user_fence_rep =
335 		(struct drm_vmw_fence_rep __user *)
336 		(unsigned long)arg->fence_rep;
337 	struct drm_vmw_rect __user *clips_ptr;
338 	struct drm_vmw_rect *clips = NULL;
339 	struct drm_framebuffer *fb;
340 	struct vmw_framebuffer *vfb;
341 	uint32_t num_clips;
342 	int ret;
343 
344 	num_clips = arg->num_clips;
345 	clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
346 
347 	if (unlikely(num_clips == 0))
348 		return 0;
349 
350 	if (clips_ptr == NULL) {
351 		VMW_DEBUG_USER("Argument clips_ptr must be specified.\n");
352 		ret = -EINVAL;
353 		goto out_clips;
354 	}
355 
356 	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
357 	if (clips == NULL) {
358 		DRM_ERROR("Failed to allocate clip rect list.\n");
359 		ret = -ENOMEM;
360 		goto out_clips;
361 	}
362 
363 	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
364 	if (ret) {
365 		DRM_ERROR("Failed to copy clip rects from userspace.\n");
366 		ret = -EFAULT;
367 		goto out_no_copy;
368 	}
369 
370 	drm_modeset_lock_all(dev);
371 
372 	fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
373 	if (!fb) {
374 		VMW_DEBUG_USER("Invalid framebuffer id.\n");
375 		ret = -ENOENT;
376 		goto out_no_fb;
377 	}
378 
379 	vfb = vmw_framebuffer_to_vfb(fb);
380 	if (!vfb->bo) {
381 		VMW_DEBUG_USER("Framebuffer not buffer backed.\n");
382 		ret = -EINVAL;
383 		goto out_no_ttm_lock;
384 	}
385 
386 	ret = vmw_kms_readback(dev_priv, file_priv,
387 			       vfb, user_fence_rep,
388 			       clips, num_clips);
389 
390 out_no_ttm_lock:
391 	drm_framebuffer_put(fb);
392 out_no_fb:
393 	drm_modeset_unlock_all(dev);
394 out_no_copy:
395 	kfree(clips);
396 out_clips:
397 	return ret;
398 }
399