1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /**************************************************************************
3  *
4  * Copyright 2009-2023 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_bo.h"
29 #include "vmwgfx_drv.h"
30 #include "vmwgfx_resource_priv.h"
31 #include "vmwgfx_so.h"
32 #include "vmwgfx_binding.h"
33 #include "vmw_surface_cache.h"
34 #include "device_include/svga3d_surfacedefs.h"
35 
36 #include <drm/ttm/ttm_placement.h>
37 
38 #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
39 #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
40 #define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
41 	(svga3d_flags & ((uint64_t)U32_MAX))
42 
43 /**
44  * struct vmw_user_surface - User-space visible surface resource
45  *
46  * @prime:          The TTM prime object.
47  * @base:           The TTM base object handling user-space visibility.
48  * @srf:            The surface metadata.
49  * @master:         Master of the creating client. Used for security check.
50  */
51 struct vmw_user_surface {
52 	struct ttm_prime_object prime;
53 	struct vmw_surface srf;
54 	struct drm_master *master;
55 };
56 
57 /**
58  * struct vmw_surface_offset - Backing store mip level offset info
59  *
60  * @face:           Surface face.
61  * @mip:            Mip level.
62  * @bo_offset:      Offset into backing store of this mip level.
63  *
64  */
65 struct vmw_surface_offset {
66 	uint32_t face;
67 	uint32_t mip;
68 	uint32_t bo_offset;
69 };
70 
71 /**
72  * struct vmw_surface_dirty - Surface dirty-tracker
73  * @cache: Cached layout information of the surface.
74  * @num_subres: Number of subresources.
75  * @boxes: Array of SVGA3dBoxes indicating dirty regions. One per subresource.
76  */
77 struct vmw_surface_dirty {
78 	struct vmw_surface_cache cache;
79 	u32 num_subres;
80 	SVGA3dBox boxes[];
81 };
82 
83 static void vmw_user_surface_free(struct vmw_resource *res);
84 static struct vmw_resource *
85 vmw_user_surface_base_to_res(struct ttm_base_object *base);
86 static int vmw_legacy_srf_bind(struct vmw_resource *res,
87 			       struct ttm_validate_buffer *val_buf);
88 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
89 				 bool readback,
90 				 struct ttm_validate_buffer *val_buf);
91 static int vmw_legacy_srf_create(struct vmw_resource *res);
92 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
93 static int vmw_gb_surface_create(struct vmw_resource *res);
94 static int vmw_gb_surface_bind(struct vmw_resource *res,
95 			       struct ttm_validate_buffer *val_buf);
96 static int vmw_gb_surface_unbind(struct vmw_resource *res,
97 				 bool readback,
98 				 struct ttm_validate_buffer *val_buf);
99 static int vmw_gb_surface_destroy(struct vmw_resource *res);
100 static int
101 vmw_gb_surface_define_internal(struct drm_device *dev,
102 			       struct drm_vmw_gb_surface_create_ext_req *req,
103 			       struct drm_vmw_gb_surface_create_rep *rep,
104 			       struct drm_file *file_priv);
105 static int
106 vmw_gb_surface_reference_internal(struct drm_device *dev,
107 				  struct drm_vmw_surface_arg *req,
108 				  struct drm_vmw_gb_surface_ref_ext_rep *rep,
109 				  struct drm_file *file_priv);
110 
111 static void vmw_surface_dirty_free(struct vmw_resource *res);
112 static int vmw_surface_dirty_alloc(struct vmw_resource *res);
113 static int vmw_surface_dirty_sync(struct vmw_resource *res);
114 static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start,
115 					size_t end);
116 static int vmw_surface_clean(struct vmw_resource *res);
117 
118 static const struct vmw_user_resource_conv user_surface_conv = {
119 	.object_type = VMW_RES_SURFACE,
120 	.base_obj_to_res = vmw_user_surface_base_to_res,
121 	.res_free = vmw_user_surface_free
122 };
123 
124 const struct vmw_user_resource_conv *user_surface_converter =
125 	&user_surface_conv;
126 
127 static const struct vmw_res_func vmw_legacy_surface_func = {
128 	.res_type = vmw_res_surface,
129 	.needs_guest_memory = false,
130 	.may_evict = true,
131 	.prio = 1,
132 	.dirty_prio = 1,
133 	.type_name = "legacy surfaces",
134 	.domain = VMW_BO_DOMAIN_GMR,
135 	.busy_domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
136 	.create = &vmw_legacy_srf_create,
137 	.destroy = &vmw_legacy_srf_destroy,
138 	.bind = &vmw_legacy_srf_bind,
139 	.unbind = &vmw_legacy_srf_unbind
140 };
141 
142 static const struct vmw_res_func vmw_gb_surface_func = {
143 	.res_type = vmw_res_surface,
144 	.needs_guest_memory = true,
145 	.may_evict = true,
146 	.prio = 1,
147 	.dirty_prio = 2,
148 	.type_name = "guest backed surfaces",
149 	.domain = VMW_BO_DOMAIN_MOB,
150 	.busy_domain = VMW_BO_DOMAIN_MOB,
151 	.create = vmw_gb_surface_create,
152 	.destroy = vmw_gb_surface_destroy,
153 	.bind = vmw_gb_surface_bind,
154 	.unbind = vmw_gb_surface_unbind,
155 	.dirty_alloc = vmw_surface_dirty_alloc,
156 	.dirty_free = vmw_surface_dirty_free,
157 	.dirty_sync = vmw_surface_dirty_sync,
158 	.dirty_range_add = vmw_surface_dirty_range_add,
159 	.clean = vmw_surface_clean,
160 };
161 
162 /*
163  * struct vmw_surface_dma - SVGA3D DMA command
164  */
165 struct vmw_surface_dma {
166 	SVGA3dCmdHeader header;
167 	SVGA3dCmdSurfaceDMA body;
168 	SVGA3dCopyBox cb;
169 	SVGA3dCmdSurfaceDMASuffix suffix;
170 };
171 
172 /*
173  * struct vmw_surface_define - SVGA3D Surface Define command
174  */
175 struct vmw_surface_define {
176 	SVGA3dCmdHeader header;
177 	SVGA3dCmdDefineSurface body;
178 };
179 
180 /*
181  * struct vmw_surface_destroy - SVGA3D Surface Destroy command
182  */
183 struct vmw_surface_destroy {
184 	SVGA3dCmdHeader header;
185 	SVGA3dCmdDestroySurface body;
186 };
187 
188 
189 /**
190  * vmw_surface_dma_size - Compute fifo size for a dma command.
191  *
192  * @srf: Pointer to a struct vmw_surface
193  *
194  * Computes the required size for a surface dma command for backup or
195  * restoration of the surface represented by @srf.
196  */
vmw_surface_dma_size(const struct vmw_surface * srf)197 static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
198 {
199 	return srf->metadata.num_sizes * sizeof(struct vmw_surface_dma);
200 }
201 
202 
203 /**
204  * vmw_surface_define_size - Compute fifo size for a surface define command.
205  *
206  * @srf: Pointer to a struct vmw_surface
207  *
208  * Computes the required size for a surface define command for the definition
209  * of the surface represented by @srf.
210  */
vmw_surface_define_size(const struct vmw_surface * srf)211 static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
212 {
213 	return sizeof(struct vmw_surface_define) + srf->metadata.num_sizes *
214 		sizeof(SVGA3dSize);
215 }
216 
217 
218 /**
219  * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
220  *
221  * Computes the required size for a surface destroy command for the destruction
222  * of a hw surface.
223  */
vmw_surface_destroy_size(void)224 static inline uint32_t vmw_surface_destroy_size(void)
225 {
226 	return sizeof(struct vmw_surface_destroy);
227 }
228 
229 /**
230  * vmw_surface_destroy_encode - Encode a surface_destroy command.
231  *
232  * @id: The surface id
233  * @cmd_space: Pointer to memory area in which the commands should be encoded.
234  */
vmw_surface_destroy_encode(uint32_t id,void * cmd_space)235 static void vmw_surface_destroy_encode(uint32_t id,
236 				       void *cmd_space)
237 {
238 	struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
239 		cmd_space;
240 
241 	cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
242 	cmd->header.size = sizeof(cmd->body);
243 	cmd->body.sid = id;
244 }
245 
246 /**
247  * vmw_surface_define_encode - Encode a surface_define command.
248  *
249  * @srf: Pointer to a struct vmw_surface object.
250  * @cmd_space: Pointer to memory area in which the commands should be encoded.
251  */
vmw_surface_define_encode(const struct vmw_surface * srf,void * cmd_space)252 static void vmw_surface_define_encode(const struct vmw_surface *srf,
253 				      void *cmd_space)
254 {
255 	struct vmw_surface_define *cmd = (struct vmw_surface_define *)
256 		cmd_space;
257 	struct drm_vmw_size *src_size;
258 	SVGA3dSize *cmd_size;
259 	uint32_t cmd_len;
260 	int i;
261 
262 	cmd_len = sizeof(cmd->body) + srf->metadata.num_sizes *
263 		sizeof(SVGA3dSize);
264 
265 	cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
266 	cmd->header.size = cmd_len;
267 	cmd->body.sid = srf->res.id;
268 	/*
269 	 * Downcast of surfaceFlags, was upcasted when received from user-space,
270 	 * since driver internally stores as 64 bit.
271 	 * For legacy surface define only 32 bit flag is supported.
272 	 */
273 	cmd->body.surfaceFlags = (SVGA3dSurface1Flags)srf->metadata.flags;
274 	cmd->body.format = srf->metadata.format;
275 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
276 		cmd->body.face[i].numMipLevels = srf->metadata.mip_levels[i];
277 
278 	cmd += 1;
279 	cmd_size = (SVGA3dSize *) cmd;
280 	src_size = srf->metadata.sizes;
281 
282 	for (i = 0; i < srf->metadata.num_sizes; ++i, cmd_size++, src_size++) {
283 		cmd_size->width = src_size->width;
284 		cmd_size->height = src_size->height;
285 		cmd_size->depth = src_size->depth;
286 	}
287 }
288 
289 /**
290  * vmw_surface_dma_encode - Encode a surface_dma command.
291  *
292  * @srf: Pointer to a struct vmw_surface object.
293  * @cmd_space: Pointer to memory area in which the commands should be encoded.
294  * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
295  * should be placed or read from.
296  * @to_surface: Boolean whether to DMA to the surface or from the surface.
297  */
vmw_surface_dma_encode(struct vmw_surface * srf,void * cmd_space,const SVGAGuestPtr * ptr,bool to_surface)298 static void vmw_surface_dma_encode(struct vmw_surface *srf,
299 				   void *cmd_space,
300 				   const SVGAGuestPtr *ptr,
301 				   bool to_surface)
302 {
303 	uint32_t i;
304 	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
305 	const struct SVGA3dSurfaceDesc *desc =
306 		vmw_surface_get_desc(srf->metadata.format);
307 
308 	for (i = 0; i < srf->metadata.num_sizes; ++i) {
309 		SVGA3dCmdHeader *header = &cmd->header;
310 		SVGA3dCmdSurfaceDMA *body = &cmd->body;
311 		SVGA3dCopyBox *cb = &cmd->cb;
312 		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
313 		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
314 		const struct drm_vmw_size *cur_size = &srf->metadata.sizes[i];
315 
316 		header->id = SVGA_3D_CMD_SURFACE_DMA;
317 		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
318 
319 		body->guest.ptr = *ptr;
320 		body->guest.ptr.offset += cur_offset->bo_offset;
321 		body->guest.pitch = vmw_surface_calculate_pitch(desc, cur_size);
322 		body->host.sid = srf->res.id;
323 		body->host.face = cur_offset->face;
324 		body->host.mipmap = cur_offset->mip;
325 		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
326 				  SVGA3D_READ_HOST_VRAM);
327 		cb->x = 0;
328 		cb->y = 0;
329 		cb->z = 0;
330 		cb->srcx = 0;
331 		cb->srcy = 0;
332 		cb->srcz = 0;
333 		cb->w = cur_size->width;
334 		cb->h = cur_size->height;
335 		cb->d = cur_size->depth;
336 
337 		suffix->suffixSize = sizeof(*suffix);
338 		suffix->maximumOffset =
339 			vmw_surface_get_image_buffer_size(desc, cur_size,
340 							    body->guest.pitch);
341 		suffix->flags.discard = 0;
342 		suffix->flags.unsynchronized = 0;
343 		suffix->flags.reserved = 0;
344 		++cmd;
345 	}
346 };
347 
348 
349 /**
350  * vmw_hw_surface_destroy - destroy a Device surface
351  *
352  * @res:        Pointer to a struct vmw_resource embedded in a struct
353  *              vmw_surface.
354  *
355  * Destroys a the device surface associated with a struct vmw_surface if
356  * any, and adjusts resource count accordingly.
357  */
vmw_hw_surface_destroy(struct vmw_resource * res)358 static void vmw_hw_surface_destroy(struct vmw_resource *res)
359 {
360 
361 	struct vmw_private *dev_priv = res->dev_priv;
362 	void *cmd;
363 
364 	if (res->func->destroy == vmw_gb_surface_destroy) {
365 		(void) vmw_gb_surface_destroy(res);
366 		return;
367 	}
368 
369 	if (res->id != -1) {
370 
371 		cmd = VMW_CMD_RESERVE(dev_priv, vmw_surface_destroy_size());
372 		if (unlikely(!cmd))
373 			return;
374 
375 		vmw_surface_destroy_encode(res->id, cmd);
376 		vmw_cmd_commit(dev_priv, vmw_surface_destroy_size());
377 
378 		/*
379 		 * used_memory_size_atomic, or separate lock
380 		 * to avoid taking dev_priv::cmdbuf_mutex in
381 		 * the destroy path.
382 		 */
383 
384 		mutex_lock(&dev_priv->cmdbuf_mutex);
385 		dev_priv->used_memory_size -= res->guest_memory_size;
386 		mutex_unlock(&dev_priv->cmdbuf_mutex);
387 	}
388 }
389 
390 /**
391  * vmw_legacy_srf_create - Create a device surface as part of the
392  * resource validation process.
393  *
394  * @res: Pointer to a struct vmw_surface.
395  *
396  * If the surface doesn't have a hw id.
397  *
398  * Returns -EBUSY if there wasn't sufficient device resources to
399  * complete the validation. Retry after freeing up resources.
400  *
401  * May return other errors if the kernel is out of guest resources.
402  */
vmw_legacy_srf_create(struct vmw_resource * res)403 static int vmw_legacy_srf_create(struct vmw_resource *res)
404 {
405 	struct vmw_private *dev_priv = res->dev_priv;
406 	struct vmw_surface *srf;
407 	uint32_t submit_size;
408 	uint8_t *cmd;
409 	int ret;
410 
411 	if (likely(res->id != -1))
412 		return 0;
413 
414 	srf = vmw_res_to_srf(res);
415 	if (unlikely(dev_priv->used_memory_size + res->guest_memory_size >=
416 		     dev_priv->memory_size))
417 		return -EBUSY;
418 
419 	/*
420 	 * Alloc id for the resource.
421 	 */
422 
423 	ret = vmw_resource_alloc_id(res);
424 	if (unlikely(ret != 0)) {
425 		DRM_ERROR("Failed to allocate a surface id.\n");
426 		goto out_no_id;
427 	}
428 
429 	if (unlikely(res->id >= SVGA3D_HB_MAX_SURFACE_IDS)) {
430 		ret = -EBUSY;
431 		goto out_no_fifo;
432 	}
433 
434 	/*
435 	 * Encode surface define- commands.
436 	 */
437 
438 	submit_size = vmw_surface_define_size(srf);
439 	cmd = VMW_CMD_RESERVE(dev_priv, submit_size);
440 	if (unlikely(!cmd)) {
441 		ret = -ENOMEM;
442 		goto out_no_fifo;
443 	}
444 
445 	vmw_surface_define_encode(srf, cmd);
446 	vmw_cmd_commit(dev_priv, submit_size);
447 	vmw_fifo_resource_inc(dev_priv);
448 
449 	/*
450 	 * Surface memory usage accounting.
451 	 */
452 
453 	dev_priv->used_memory_size += res->guest_memory_size;
454 	return 0;
455 
456 out_no_fifo:
457 	vmw_resource_release_id(res);
458 out_no_id:
459 	return ret;
460 }
461 
462 /**
463  * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
464  *
465  * @res:            Pointer to a struct vmw_res embedded in a struct
466  *                  vmw_surface.
467  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
468  *                  information about the backup buffer.
469  * @bind:           Boolean wether to DMA to the surface.
470  *
471  * Transfer backup data to or from a legacy surface as part of the
472  * validation process.
473  * May return other errors if the kernel is out of guest resources.
474  * The backup buffer will be fenced or idle upon successful completion,
475  * and if the surface needs persistent backup storage, the backup buffer
476  * will also be returned reserved iff @bind is true.
477  */
vmw_legacy_srf_dma(struct vmw_resource * res,struct ttm_validate_buffer * val_buf,bool bind)478 static int vmw_legacy_srf_dma(struct vmw_resource *res,
479 			      struct ttm_validate_buffer *val_buf,
480 			      bool bind)
481 {
482 	SVGAGuestPtr ptr;
483 	struct vmw_fence_obj *fence;
484 	uint32_t submit_size;
485 	struct vmw_surface *srf = vmw_res_to_srf(res);
486 	uint8_t *cmd;
487 	struct vmw_private *dev_priv = res->dev_priv;
488 
489 	BUG_ON(!val_buf->bo);
490 	submit_size = vmw_surface_dma_size(srf);
491 	cmd = VMW_CMD_RESERVE(dev_priv, submit_size);
492 	if (unlikely(!cmd))
493 		return -ENOMEM;
494 
495 	vmw_bo_get_guest_ptr(val_buf->bo, &ptr);
496 	vmw_surface_dma_encode(srf, cmd, &ptr, bind);
497 
498 	vmw_cmd_commit(dev_priv, submit_size);
499 
500 	/*
501 	 * Create a fence object and fence the backup buffer.
502 	 */
503 
504 	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
505 					  &fence, NULL);
506 
507 	vmw_bo_fence_single(val_buf->bo, fence);
508 
509 	if (likely(fence != NULL))
510 		vmw_fence_obj_unreference(&fence);
511 
512 	return 0;
513 }
514 
515 /**
516  * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
517  *                       surface validation process.
518  *
519  * @res:            Pointer to a struct vmw_res embedded in a struct
520  *                  vmw_surface.
521  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
522  *                  information about the backup buffer.
523  *
524  * This function will copy backup data to the surface if the
525  * backup buffer is dirty.
526  */
vmw_legacy_srf_bind(struct vmw_resource * res,struct ttm_validate_buffer * val_buf)527 static int vmw_legacy_srf_bind(struct vmw_resource *res,
528 			       struct ttm_validate_buffer *val_buf)
529 {
530 	if (!res->guest_memory_dirty)
531 		return 0;
532 
533 	return vmw_legacy_srf_dma(res, val_buf, true);
534 }
535 
536 
537 /**
538  * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
539  *                         surface eviction process.
540  *
541  * @res:            Pointer to a struct vmw_res embedded in a struct
542  *                  vmw_surface.
543  * @readback:       Readback - only true if dirty
544  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
545  *                  information about the backup buffer.
546  *
547  * This function will copy backup data from the surface.
548  */
vmw_legacy_srf_unbind(struct vmw_resource * res,bool readback,struct ttm_validate_buffer * val_buf)549 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
550 				 bool readback,
551 				 struct ttm_validate_buffer *val_buf)
552 {
553 	if (unlikely(readback))
554 		return vmw_legacy_srf_dma(res, val_buf, false);
555 	return 0;
556 }
557 
558 /**
559  * vmw_legacy_srf_destroy - Destroy a device surface as part of a
560  *                          resource eviction process.
561  *
562  * @res:            Pointer to a struct vmw_res embedded in a struct
563  *                  vmw_surface.
564  */
vmw_legacy_srf_destroy(struct vmw_resource * res)565 static int vmw_legacy_srf_destroy(struct vmw_resource *res)
566 {
567 	struct vmw_private *dev_priv = res->dev_priv;
568 	uint32_t submit_size;
569 	uint8_t *cmd;
570 
571 	BUG_ON(res->id == -1);
572 
573 	/*
574 	 * Encode the dma- and surface destroy commands.
575 	 */
576 
577 	submit_size = vmw_surface_destroy_size();
578 	cmd = VMW_CMD_RESERVE(dev_priv, submit_size);
579 	if (unlikely(!cmd))
580 		return -ENOMEM;
581 
582 	vmw_surface_destroy_encode(res->id, cmd);
583 	vmw_cmd_commit(dev_priv, submit_size);
584 
585 	/*
586 	 * Surface memory usage accounting.
587 	 */
588 
589 	dev_priv->used_memory_size -= res->guest_memory_size;
590 
591 	/*
592 	 * Release the surface ID.
593 	 */
594 
595 	vmw_resource_release_id(res);
596 	vmw_fifo_resource_dec(dev_priv);
597 
598 	return 0;
599 }
600 
601 
602 /**
603  * vmw_surface_init - initialize a struct vmw_surface
604  *
605  * @dev_priv:       Pointer to a device private struct.
606  * @srf:            Pointer to the struct vmw_surface to initialize.
607  * @res_free:       Pointer to a resource destructor used to free
608  *                  the object.
609  */
vmw_surface_init(struct vmw_private * dev_priv,struct vmw_surface * srf,void (* res_free)(struct vmw_resource * res))610 static int vmw_surface_init(struct vmw_private *dev_priv,
611 			    struct vmw_surface *srf,
612 			    void (*res_free) (struct vmw_resource *res))
613 {
614 	int ret;
615 	struct vmw_resource *res = &srf->res;
616 
617 	BUG_ON(!res_free);
618 	ret = vmw_resource_init(dev_priv, res, true, res_free,
619 				(dev_priv->has_mob) ? &vmw_gb_surface_func :
620 				&vmw_legacy_surface_func);
621 
622 	if (unlikely(ret != 0)) {
623 		res_free(res);
624 		return ret;
625 	}
626 
627 	/*
628 	 * The surface won't be visible to hardware until a
629 	 * surface validate.
630 	 */
631 
632 	INIT_LIST_HEAD(&srf->view_list);
633 	res->hw_destroy = vmw_hw_surface_destroy;
634 	return ret;
635 }
636 
637 /**
638  * vmw_user_surface_base_to_res - TTM base object to resource converter for
639  *                                user visible surfaces
640  *
641  * @base:           Pointer to a TTM base object
642  *
643  * Returns the struct vmw_resource embedded in a struct vmw_surface
644  * for the user-visible object identified by the TTM base object @base.
645  */
646 static struct vmw_resource *
vmw_user_surface_base_to_res(struct ttm_base_object * base)647 vmw_user_surface_base_to_res(struct ttm_base_object *base)
648 {
649 	return &(container_of(base, struct vmw_user_surface,
650 			      prime.base)->srf.res);
651 }
652 
653 /**
654  * vmw_user_surface_free - User visible surface resource destructor
655  *
656  * @res:            A struct vmw_resource embedded in a struct vmw_surface.
657  */
vmw_user_surface_free(struct vmw_resource * res)658 static void vmw_user_surface_free(struct vmw_resource *res)
659 {
660 	struct vmw_surface *srf = vmw_res_to_srf(res);
661 	struct vmw_user_surface *user_srf =
662 	    container_of(srf, struct vmw_user_surface, srf);
663 
664 	WARN_ON_ONCE(res->dirty);
665 	if (user_srf->master)
666 		drm_master_put(&user_srf->master);
667 	kfree(srf->offsets);
668 	kfree(srf->metadata.sizes);
669 	kfree(srf->snooper.image);
670 	ttm_prime_object_kfree(user_srf, prime);
671 }
672 
673 /**
674  * vmw_user_surface_base_release - User visible surface TTM base object destructor
675  *
676  * @p_base:         Pointer to a pointer to a TTM base object
677  *                  embedded in a struct vmw_user_surface.
678  *
679  * Drops the base object's reference on its resource, and the
680  * pointer pointed to by *p_base is set to NULL.
681  */
vmw_user_surface_base_release(struct ttm_base_object ** p_base)682 static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
683 {
684 	struct ttm_base_object *base = *p_base;
685 	struct vmw_user_surface *user_srf =
686 	    container_of(base, struct vmw_user_surface, prime.base);
687 	struct vmw_resource *res = &user_srf->srf.res;
688 
689 	*p_base = NULL;
690 	vmw_resource_unreference(&res);
691 }
692 
693 /**
694  * vmw_surface_destroy_ioctl - Ioctl function implementing
695  *                                  the user surface destroy functionality.
696  *
697  * @dev:            Pointer to a struct drm_device.
698  * @data:           Pointer to data copied from / to user-space.
699  * @file_priv:      Pointer to a drm file private structure.
700  */
vmw_surface_destroy_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)701 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
702 			      struct drm_file *file_priv)
703 {
704 	struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
705 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
706 
707 	return ttm_ref_object_base_unref(tfile, arg->sid);
708 }
709 
710 /**
711  * vmw_surface_define_ioctl - Ioctl function implementing
712  *                                  the user surface define functionality.
713  *
714  * @dev:            Pointer to a struct drm_device.
715  * @data:           Pointer to data copied from / to user-space.
716  * @file_priv:      Pointer to a drm file private structure.
717  */
vmw_surface_define_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)718 int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
719 			     struct drm_file *file_priv)
720 {
721 	struct vmw_private *dev_priv = vmw_priv(dev);
722 	struct vmw_user_surface *user_srf;
723 	struct vmw_surface *srf;
724 	struct vmw_surface_metadata *metadata;
725 	struct vmw_resource *res;
726 	struct vmw_resource *tmp;
727 	union drm_vmw_surface_create_arg *arg =
728 	    (union drm_vmw_surface_create_arg *)data;
729 	struct drm_vmw_surface_create_req *req = &arg->req;
730 	struct drm_vmw_surface_arg *rep = &arg->rep;
731 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
732 	int ret;
733 	int i, j;
734 	uint32_t cur_bo_offset;
735 	struct drm_vmw_size *cur_size;
736 	struct vmw_surface_offset *cur_offset;
737 	uint32_t num_sizes;
738 	const SVGA3dSurfaceDesc *desc;
739 
740 	num_sizes = 0;
741 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
742 		if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
743 			return -EINVAL;
744 		num_sizes += req->mip_levels[i];
745 	}
746 
747 	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
748 	    num_sizes == 0)
749 		return -EINVAL;
750 
751 	desc = vmw_surface_get_desc(req->format);
752 	if (unlikely(desc->blockDesc == SVGA3DBLOCKDESC_NONE)) {
753 		VMW_DEBUG_USER("Invalid format %d for surface creation.\n",
754 			       req->format);
755 		return -EINVAL;
756 	}
757 
758 	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
759 	if (unlikely(!user_srf)) {
760 		ret = -ENOMEM;
761 		goto out_unlock;
762 	}
763 
764 	srf = &user_srf->srf;
765 	metadata = &srf->metadata;
766 	res = &srf->res;
767 
768 	/* Driver internally stores as 64-bit flags */
769 	metadata->flags = (SVGA3dSurfaceAllFlags)req->flags;
770 	metadata->format = req->format;
771 	metadata->scanout = req->scanout;
772 
773 	memcpy(metadata->mip_levels, req->mip_levels,
774 	       sizeof(metadata->mip_levels));
775 	metadata->num_sizes = num_sizes;
776 	metadata->sizes =
777 		memdup_array_user((struct drm_vmw_size __user *)(unsigned long)
778 			    req->size_addr,
779 			    metadata->num_sizes, sizeof(*metadata->sizes));
780 	if (IS_ERR(metadata->sizes)) {
781 		ret = PTR_ERR(metadata->sizes);
782 		goto out_no_sizes;
783 	}
784 	srf->offsets = kmalloc_array(metadata->num_sizes, sizeof(*srf->offsets),
785 				     GFP_KERNEL);
786 	if (unlikely(!srf->offsets)) {
787 		ret = -ENOMEM;
788 		goto out_no_offsets;
789 	}
790 
791 	metadata->base_size = *srf->metadata.sizes;
792 	metadata->autogen_filter = SVGA3D_TEX_FILTER_NONE;
793 	metadata->multisample_count = 0;
794 	metadata->multisample_pattern = SVGA3D_MS_PATTERN_NONE;
795 	metadata->quality_level = SVGA3D_MS_QUALITY_NONE;
796 
797 	cur_bo_offset = 0;
798 	cur_offset = srf->offsets;
799 	cur_size = metadata->sizes;
800 
801 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
802 		for (j = 0; j < metadata->mip_levels[i]; ++j) {
803 			uint32_t stride = vmw_surface_calculate_pitch(
804 						  desc, cur_size);
805 
806 			cur_offset->face = i;
807 			cur_offset->mip = j;
808 			cur_offset->bo_offset = cur_bo_offset;
809 			cur_bo_offset += vmw_surface_get_image_buffer_size
810 				(desc, cur_size, stride);
811 			++cur_offset;
812 			++cur_size;
813 		}
814 	}
815 	res->guest_memory_size = cur_bo_offset;
816 	if (metadata->scanout &&
817 	    metadata->num_sizes == 1 &&
818 	    metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH &&
819 	    metadata->sizes[0].height == VMW_CURSOR_SNOOP_HEIGHT &&
820 	    metadata->format == VMW_CURSOR_SNOOP_FORMAT) {
821 		const struct SVGA3dSurfaceDesc *desc =
822 			vmw_surface_get_desc(VMW_CURSOR_SNOOP_FORMAT);
823 		const u32 cursor_size_bytes = VMW_CURSOR_SNOOP_WIDTH *
824 					      VMW_CURSOR_SNOOP_HEIGHT *
825 					      desc->pitchBytesPerBlock;
826 		srf->snooper.image = kzalloc(cursor_size_bytes, GFP_KERNEL);
827 		if (!srf->snooper.image) {
828 			DRM_ERROR("Failed to allocate cursor_image\n");
829 			ret = -ENOMEM;
830 			goto out_no_copy;
831 		}
832 	} else {
833 		srf->snooper.image = NULL;
834 	}
835 
836 	user_srf->prime.base.shareable = false;
837 	user_srf->prime.base.tfile = NULL;
838 	if (drm_is_primary_client(file_priv))
839 		user_srf->master = drm_file_get_master(file_priv);
840 
841 	/**
842 	 * From this point, the generic resource management functions
843 	 * destroy the object on failure.
844 	 */
845 
846 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
847 	if (unlikely(ret != 0))
848 		goto out_unlock;
849 
850 	/*
851 	 * A gb-aware client referencing a shared surface will
852 	 * expect a backup buffer to be present.
853 	 */
854 	if (dev_priv->has_mob && req->shareable) {
855 		struct vmw_bo_params params = {
856 			.domain = VMW_BO_DOMAIN_SYS,
857 			.busy_domain = VMW_BO_DOMAIN_SYS,
858 			.bo_type = ttm_bo_type_device,
859 			.size = res->guest_memory_size,
860 			.pin = false
861 		};
862 
863 		ret = vmw_gem_object_create(dev_priv,
864 					    &params,
865 					    &res->guest_memory_bo);
866 		if (unlikely(ret != 0)) {
867 			vmw_resource_unreference(&res);
868 			goto out_unlock;
869 		}
870 	}
871 
872 	tmp = vmw_resource_reference(&srf->res);
873 	ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime,
874 				    req->shareable, VMW_RES_SURFACE,
875 				    &vmw_user_surface_base_release);
876 
877 	if (unlikely(ret != 0)) {
878 		vmw_resource_unreference(&tmp);
879 		vmw_resource_unreference(&res);
880 		goto out_unlock;
881 	}
882 
883 	rep->sid = user_srf->prime.base.handle;
884 	vmw_resource_unreference(&res);
885 
886 	return 0;
887 out_no_copy:
888 	kfree(srf->offsets);
889 out_no_offsets:
890 	kfree(metadata->sizes);
891 out_no_sizes:
892 	ttm_prime_object_kfree(user_srf, prime);
893 out_unlock:
894 	return ret;
895 }
896 
897 
898 static int
vmw_surface_handle_reference(struct vmw_private * dev_priv,struct drm_file * file_priv,uint32_t u_handle,enum drm_vmw_handle_type handle_type,struct ttm_base_object ** base_p)899 vmw_surface_handle_reference(struct vmw_private *dev_priv,
900 			     struct drm_file *file_priv,
901 			     uint32_t u_handle,
902 			     enum drm_vmw_handle_type handle_type,
903 			     struct ttm_base_object **base_p)
904 {
905 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
906 	struct vmw_user_surface *user_srf;
907 	uint32_t handle;
908 	struct ttm_base_object *base;
909 	int ret;
910 
911 	if (handle_type == DRM_VMW_HANDLE_PRIME) {
912 		ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
913 		if (unlikely(ret != 0))
914 			return ret;
915 	} else {
916 		handle = u_handle;
917 	}
918 
919 	ret = -EINVAL;
920 	base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
921 	if (unlikely(!base)) {
922 		VMW_DEBUG_USER("Could not find surface to reference.\n");
923 		goto out_no_lookup;
924 	}
925 
926 	if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
927 		VMW_DEBUG_USER("Referenced object is not a surface.\n");
928 		goto out_bad_resource;
929 	}
930 	if (handle_type != DRM_VMW_HANDLE_PRIME) {
931 		bool require_exist = false;
932 
933 		user_srf = container_of(base, struct vmw_user_surface,
934 					prime.base);
935 
936 		/* Error out if we are unauthenticated primary */
937 		if (drm_is_primary_client(file_priv) &&
938 		    !file_priv->authenticated) {
939 			ret = -EACCES;
940 			goto out_bad_resource;
941 		}
942 
943 		/*
944 		 * Make sure the surface creator has the same
945 		 * authenticating master, or is already registered with us.
946 		 */
947 		if (drm_is_primary_client(file_priv) &&
948 		    user_srf->master != file_priv->master)
949 			require_exist = true;
950 
951 		if (unlikely(drm_is_render_client(file_priv)))
952 			require_exist = true;
953 
954 		ret = ttm_ref_object_add(tfile, base, NULL, require_exist);
955 		if (unlikely(ret != 0)) {
956 			DRM_ERROR("Could not add a reference to a surface.\n");
957 			goto out_bad_resource;
958 		}
959 	}
960 
961 	*base_p = base;
962 	return 0;
963 
964 out_bad_resource:
965 	ttm_base_object_unref(&base);
966 out_no_lookup:
967 	if (handle_type == DRM_VMW_HANDLE_PRIME)
968 		(void) ttm_ref_object_base_unref(tfile, handle);
969 
970 	return ret;
971 }
972 
973 /**
974  * vmw_surface_reference_ioctl - Ioctl function implementing
975  *                                  the user surface reference functionality.
976  *
977  * @dev:            Pointer to a struct drm_device.
978  * @data:           Pointer to data copied from / to user-space.
979  * @file_priv:      Pointer to a drm file private structure.
980  */
vmw_surface_reference_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)981 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
982 				struct drm_file *file_priv)
983 {
984 	struct vmw_private *dev_priv = vmw_priv(dev);
985 	union drm_vmw_surface_reference_arg *arg =
986 	    (union drm_vmw_surface_reference_arg *)data;
987 	struct drm_vmw_surface_arg *req = &arg->req;
988 	struct drm_vmw_surface_create_req *rep = &arg->rep;
989 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
990 	struct vmw_surface *srf;
991 	struct vmw_user_surface *user_srf;
992 	struct drm_vmw_size __user *user_sizes;
993 	struct ttm_base_object *base;
994 	int ret;
995 
996 	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
997 					   req->handle_type, &base);
998 	if (unlikely(ret != 0))
999 		return ret;
1000 
1001 	user_srf = container_of(base, struct vmw_user_surface, prime.base);
1002 	srf = &user_srf->srf;
1003 
1004 	/* Downcast of flags when sending back to user space */
1005 	rep->flags = (uint32_t)srf->metadata.flags;
1006 	rep->format = srf->metadata.format;
1007 	memcpy(rep->mip_levels, srf->metadata.mip_levels,
1008 	       sizeof(srf->metadata.mip_levels));
1009 	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
1010 	    rep->size_addr;
1011 
1012 	if (user_sizes)
1013 		ret = copy_to_user(user_sizes, &srf->metadata.base_size,
1014 				   sizeof(srf->metadata.base_size));
1015 	if (unlikely(ret != 0)) {
1016 		VMW_DEBUG_USER("copy_to_user failed %p %u\n", user_sizes,
1017 			       srf->metadata.num_sizes);
1018 		ttm_ref_object_base_unref(tfile, base->handle);
1019 		ret = -EFAULT;
1020 	}
1021 
1022 	ttm_base_object_unref(&base);
1023 
1024 	return ret;
1025 }
1026 
1027 /**
1028  * vmw_gb_surface_create - Encode a surface_define command.
1029  *
1030  * @res:        Pointer to a struct vmw_resource embedded in a struct
1031  *              vmw_surface.
1032  */
vmw_gb_surface_create(struct vmw_resource * res)1033 static int vmw_gb_surface_create(struct vmw_resource *res)
1034 {
1035 	struct vmw_private *dev_priv = res->dev_priv;
1036 	struct vmw_surface *srf = vmw_res_to_srf(res);
1037 	struct vmw_surface_metadata *metadata = &srf->metadata;
1038 	uint32_t cmd_len, cmd_id, submit_len;
1039 	int ret;
1040 	struct {
1041 		SVGA3dCmdHeader header;
1042 		SVGA3dCmdDefineGBSurface body;
1043 	} *cmd;
1044 	struct {
1045 		SVGA3dCmdHeader header;
1046 		SVGA3dCmdDefineGBSurface_v2 body;
1047 	} *cmd2;
1048 	struct {
1049 		SVGA3dCmdHeader header;
1050 		SVGA3dCmdDefineGBSurface_v3 body;
1051 	} *cmd3;
1052 	struct {
1053 		SVGA3dCmdHeader header;
1054 		SVGA3dCmdDefineGBSurface_v4 body;
1055 	} *cmd4;
1056 
1057 	if (likely(res->id != -1))
1058 		return 0;
1059 
1060 	vmw_fifo_resource_inc(dev_priv);
1061 	ret = vmw_resource_alloc_id(res);
1062 	if (unlikely(ret != 0)) {
1063 		DRM_ERROR("Failed to allocate a surface id.\n");
1064 		goto out_no_id;
1065 	}
1066 
1067 	if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
1068 		ret = -EBUSY;
1069 		goto out_no_fifo;
1070 	}
1071 
1072 	if (has_sm5_context(dev_priv) && metadata->array_size > 0) {
1073 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V4;
1074 		cmd_len = sizeof(cmd4->body);
1075 		submit_len = sizeof(*cmd4);
1076 	} else if (has_sm4_1_context(dev_priv) && metadata->array_size > 0) {
1077 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V3;
1078 		cmd_len = sizeof(cmd3->body);
1079 		submit_len = sizeof(*cmd3);
1080 	} else if (metadata->array_size > 0) {
1081 		/* VMW_SM_4 support verified at creation time. */
1082 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V2;
1083 		cmd_len = sizeof(cmd2->body);
1084 		submit_len = sizeof(*cmd2);
1085 	} else {
1086 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE;
1087 		cmd_len = sizeof(cmd->body);
1088 		submit_len = sizeof(*cmd);
1089 	}
1090 
1091 	cmd = VMW_CMD_RESERVE(dev_priv, submit_len);
1092 	cmd2 = (typeof(cmd2))cmd;
1093 	cmd3 = (typeof(cmd3))cmd;
1094 	cmd4 = (typeof(cmd4))cmd;
1095 	if (unlikely(!cmd)) {
1096 		ret = -ENOMEM;
1097 		goto out_no_fifo;
1098 	}
1099 
1100 	if (has_sm5_context(dev_priv) && metadata->array_size > 0) {
1101 		cmd4->header.id = cmd_id;
1102 		cmd4->header.size = cmd_len;
1103 		cmd4->body.sid = srf->res.id;
1104 		cmd4->body.surfaceFlags = metadata->flags;
1105 		cmd4->body.format = metadata->format;
1106 		cmd4->body.numMipLevels = metadata->mip_levels[0];
1107 		cmd4->body.multisampleCount = metadata->multisample_count;
1108 		cmd4->body.multisamplePattern = metadata->multisample_pattern;
1109 		cmd4->body.qualityLevel = metadata->quality_level;
1110 		cmd4->body.autogenFilter = metadata->autogen_filter;
1111 		cmd4->body.size.width = metadata->base_size.width;
1112 		cmd4->body.size.height = metadata->base_size.height;
1113 		cmd4->body.size.depth = metadata->base_size.depth;
1114 		cmd4->body.arraySize = metadata->array_size;
1115 		cmd4->body.bufferByteStride = metadata->buffer_byte_stride;
1116 	} else if (has_sm4_1_context(dev_priv) && metadata->array_size > 0) {
1117 		cmd3->header.id = cmd_id;
1118 		cmd3->header.size = cmd_len;
1119 		cmd3->body.sid = srf->res.id;
1120 		cmd3->body.surfaceFlags = metadata->flags;
1121 		cmd3->body.format = metadata->format;
1122 		cmd3->body.numMipLevels = metadata->mip_levels[0];
1123 		cmd3->body.multisampleCount = metadata->multisample_count;
1124 		cmd3->body.multisamplePattern = metadata->multisample_pattern;
1125 		cmd3->body.qualityLevel = metadata->quality_level;
1126 		cmd3->body.autogenFilter = metadata->autogen_filter;
1127 		cmd3->body.size.width = metadata->base_size.width;
1128 		cmd3->body.size.height = metadata->base_size.height;
1129 		cmd3->body.size.depth = metadata->base_size.depth;
1130 		cmd3->body.arraySize = metadata->array_size;
1131 	} else if (metadata->array_size > 0) {
1132 		cmd2->header.id = cmd_id;
1133 		cmd2->header.size = cmd_len;
1134 		cmd2->body.sid = srf->res.id;
1135 		cmd2->body.surfaceFlags = metadata->flags;
1136 		cmd2->body.format = metadata->format;
1137 		cmd2->body.numMipLevels = metadata->mip_levels[0];
1138 		cmd2->body.multisampleCount = metadata->multisample_count;
1139 		cmd2->body.autogenFilter = metadata->autogen_filter;
1140 		cmd2->body.size.width = metadata->base_size.width;
1141 		cmd2->body.size.height = metadata->base_size.height;
1142 		cmd2->body.size.depth = metadata->base_size.depth;
1143 		cmd2->body.arraySize = metadata->array_size;
1144 	} else {
1145 		cmd->header.id = cmd_id;
1146 		cmd->header.size = cmd_len;
1147 		cmd->body.sid = srf->res.id;
1148 		cmd->body.surfaceFlags = metadata->flags;
1149 		cmd->body.format = metadata->format;
1150 		cmd->body.numMipLevels = metadata->mip_levels[0];
1151 		cmd->body.multisampleCount = metadata->multisample_count;
1152 		cmd->body.autogenFilter = metadata->autogen_filter;
1153 		cmd->body.size.width = metadata->base_size.width;
1154 		cmd->body.size.height = metadata->base_size.height;
1155 		cmd->body.size.depth = metadata->base_size.depth;
1156 	}
1157 
1158 	vmw_cmd_commit(dev_priv, submit_len);
1159 
1160 	return 0;
1161 
1162 out_no_fifo:
1163 	vmw_resource_release_id(res);
1164 out_no_id:
1165 	vmw_fifo_resource_dec(dev_priv);
1166 	return ret;
1167 }
1168 
1169 
vmw_gb_surface_bind(struct vmw_resource * res,struct ttm_validate_buffer * val_buf)1170 static int vmw_gb_surface_bind(struct vmw_resource *res,
1171 			       struct ttm_validate_buffer *val_buf)
1172 {
1173 	struct vmw_private *dev_priv = res->dev_priv;
1174 	struct {
1175 		SVGA3dCmdHeader header;
1176 		SVGA3dCmdBindGBSurface body;
1177 	} *cmd1;
1178 	struct {
1179 		SVGA3dCmdHeader header;
1180 		SVGA3dCmdUpdateGBSurface body;
1181 	} *cmd2;
1182 	uint32_t submit_size;
1183 	struct ttm_buffer_object *bo = val_buf->bo;
1184 
1185 	BUG_ON(bo->resource->mem_type != VMW_PL_MOB);
1186 
1187 	submit_size = sizeof(*cmd1) + (res->guest_memory_dirty ? sizeof(*cmd2) : 0);
1188 
1189 	cmd1 = VMW_CMD_RESERVE(dev_priv, submit_size);
1190 	if (unlikely(!cmd1))
1191 		return -ENOMEM;
1192 
1193 	cmd1->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
1194 	cmd1->header.size = sizeof(cmd1->body);
1195 	cmd1->body.sid = res->id;
1196 	cmd1->body.mobid = bo->resource->start;
1197 	if (res->guest_memory_dirty) {
1198 		cmd2 = (void *) &cmd1[1];
1199 		cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;
1200 		cmd2->header.size = sizeof(cmd2->body);
1201 		cmd2->body.sid = res->id;
1202 	}
1203 	vmw_cmd_commit(dev_priv, submit_size);
1204 
1205 	if (res->guest_memory_bo->dirty && res->guest_memory_dirty) {
1206 		/* We've just made a full upload. Cear dirty regions. */
1207 		vmw_bo_dirty_clear_res(res);
1208 	}
1209 
1210 	res->guest_memory_dirty = false;
1211 
1212 	return 0;
1213 }
1214 
vmw_gb_surface_unbind(struct vmw_resource * res,bool readback,struct ttm_validate_buffer * val_buf)1215 static int vmw_gb_surface_unbind(struct vmw_resource *res,
1216 				 bool readback,
1217 				 struct ttm_validate_buffer *val_buf)
1218 {
1219 	struct vmw_private *dev_priv = res->dev_priv;
1220 	struct ttm_buffer_object *bo = val_buf->bo;
1221 	struct vmw_fence_obj *fence;
1222 
1223 	struct {
1224 		SVGA3dCmdHeader header;
1225 		SVGA3dCmdReadbackGBSurface body;
1226 	} *cmd1;
1227 	struct {
1228 		SVGA3dCmdHeader header;
1229 		SVGA3dCmdInvalidateGBSurface body;
1230 	} *cmd2;
1231 	struct {
1232 		SVGA3dCmdHeader header;
1233 		SVGA3dCmdBindGBSurface body;
1234 	} *cmd3;
1235 	uint32_t submit_size;
1236 	uint8_t *cmd;
1237 
1238 
1239 	BUG_ON(bo->resource->mem_type != VMW_PL_MOB);
1240 
1241 	submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));
1242 	cmd = VMW_CMD_RESERVE(dev_priv, submit_size);
1243 	if (unlikely(!cmd))
1244 		return -ENOMEM;
1245 
1246 	if (readback) {
1247 		cmd1 = (void *) cmd;
1248 		cmd1->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
1249 		cmd1->header.size = sizeof(cmd1->body);
1250 		cmd1->body.sid = res->id;
1251 		cmd3 = (void *) &cmd1[1];
1252 	} else {
1253 		cmd2 = (void *) cmd;
1254 		cmd2->header.id = SVGA_3D_CMD_INVALIDATE_GB_SURFACE;
1255 		cmd2->header.size = sizeof(cmd2->body);
1256 		cmd2->body.sid = res->id;
1257 		cmd3 = (void *) &cmd2[1];
1258 	}
1259 
1260 	cmd3->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
1261 	cmd3->header.size = sizeof(cmd3->body);
1262 	cmd3->body.sid = res->id;
1263 	cmd3->body.mobid = SVGA3D_INVALID_ID;
1264 
1265 	vmw_cmd_commit(dev_priv, submit_size);
1266 
1267 	/*
1268 	 * Create a fence object and fence the backup buffer.
1269 	 */
1270 
1271 	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
1272 					  &fence, NULL);
1273 
1274 	vmw_bo_fence_single(val_buf->bo, fence);
1275 
1276 	if (likely(fence != NULL))
1277 		vmw_fence_obj_unreference(&fence);
1278 
1279 	return 0;
1280 }
1281 
vmw_gb_surface_destroy(struct vmw_resource * res)1282 static int vmw_gb_surface_destroy(struct vmw_resource *res)
1283 {
1284 	struct vmw_private *dev_priv = res->dev_priv;
1285 	struct vmw_surface *srf = vmw_res_to_srf(res);
1286 	struct {
1287 		SVGA3dCmdHeader header;
1288 		SVGA3dCmdDestroyGBSurface body;
1289 	} *cmd;
1290 
1291 	if (likely(res->id == -1))
1292 		return 0;
1293 
1294 	mutex_lock(&dev_priv->binding_mutex);
1295 	vmw_view_surface_list_destroy(dev_priv, &srf->view_list);
1296 	vmw_binding_res_list_scrub(&res->binding_head);
1297 
1298 	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
1299 	if (unlikely(!cmd)) {
1300 		mutex_unlock(&dev_priv->binding_mutex);
1301 		return -ENOMEM;
1302 	}
1303 
1304 	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SURFACE;
1305 	cmd->header.size = sizeof(cmd->body);
1306 	cmd->body.sid = res->id;
1307 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
1308 	mutex_unlock(&dev_priv->binding_mutex);
1309 	vmw_resource_release_id(res);
1310 	vmw_fifo_resource_dec(dev_priv);
1311 
1312 	return 0;
1313 }
1314 
1315 /**
1316  * vmw_gb_surface_define_ioctl - Ioctl function implementing
1317  * the user surface define functionality.
1318  *
1319  * @dev: Pointer to a struct drm_device.
1320  * @data: Pointer to data copied from / to user-space.
1321  * @file_priv: Pointer to a drm file private structure.
1322  */
vmw_gb_surface_define_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1323 int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1324 				struct drm_file *file_priv)
1325 {
1326 	union drm_vmw_gb_surface_create_arg *arg =
1327 	    (union drm_vmw_gb_surface_create_arg *)data;
1328 	struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
1329 	struct drm_vmw_gb_surface_create_ext_req req_ext;
1330 
1331 	req_ext.base = arg->req;
1332 	req_ext.version = drm_vmw_gb_surface_v1;
1333 	req_ext.svga3d_flags_upper_32_bits = 0;
1334 	req_ext.multisample_pattern = SVGA3D_MS_PATTERN_NONE;
1335 	req_ext.quality_level = SVGA3D_MS_QUALITY_NONE;
1336 	req_ext.buffer_byte_stride = 0;
1337 	req_ext.must_be_zero = 0;
1338 
1339 	return vmw_gb_surface_define_internal(dev, &req_ext, rep, file_priv);
1340 }
1341 
1342 /**
1343  * vmw_gb_surface_reference_ioctl - Ioctl function implementing
1344  * the user surface reference functionality.
1345  *
1346  * @dev: Pointer to a struct drm_device.
1347  * @data: Pointer to data copied from / to user-space.
1348  * @file_priv: Pointer to a drm file private structure.
1349  */
vmw_gb_surface_reference_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1350 int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1351 				   struct drm_file *file_priv)
1352 {
1353 	union drm_vmw_gb_surface_reference_arg *arg =
1354 	    (union drm_vmw_gb_surface_reference_arg *)data;
1355 	struct drm_vmw_surface_arg *req = &arg->req;
1356 	struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep;
1357 	struct drm_vmw_gb_surface_ref_ext_rep rep_ext;
1358 	int ret;
1359 
1360 	ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv);
1361 
1362 	if (unlikely(ret != 0))
1363 		return ret;
1364 
1365 	rep->creq = rep_ext.creq.base;
1366 	rep->crep = rep_ext.crep;
1367 
1368 	return ret;
1369 }
1370 
1371 /**
1372  * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing
1373  * the user surface define functionality.
1374  *
1375  * @dev: Pointer to a struct drm_device.
1376  * @data: Pointer to data copied from / to user-space.
1377  * @file_priv: Pointer to a drm file private structure.
1378  */
vmw_gb_surface_define_ext_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1379 int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data,
1380 				struct drm_file *file_priv)
1381 {
1382 	union drm_vmw_gb_surface_create_ext_arg *arg =
1383 	    (union drm_vmw_gb_surface_create_ext_arg *)data;
1384 	struct drm_vmw_gb_surface_create_ext_req *req = &arg->req;
1385 	struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
1386 
1387 	return vmw_gb_surface_define_internal(dev, req, rep, file_priv);
1388 }
1389 
1390 /**
1391  * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing
1392  * the user surface reference functionality.
1393  *
1394  * @dev: Pointer to a struct drm_device.
1395  * @data: Pointer to data copied from / to user-space.
1396  * @file_priv: Pointer to a drm file private structure.
1397  */
vmw_gb_surface_reference_ext_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1398 int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
1399 				   struct drm_file *file_priv)
1400 {
1401 	union drm_vmw_gb_surface_reference_ext_arg *arg =
1402 	    (union drm_vmw_gb_surface_reference_ext_arg *)data;
1403 	struct drm_vmw_surface_arg *req = &arg->req;
1404 	struct drm_vmw_gb_surface_ref_ext_rep *rep = &arg->rep;
1405 
1406 	return vmw_gb_surface_reference_internal(dev, req, rep, file_priv);
1407 }
1408 
1409 /**
1410  * vmw_gb_surface_define_internal - Ioctl function implementing
1411  * the user surface define functionality.
1412  *
1413  * @dev: Pointer to a struct drm_device.
1414  * @req: Request argument from user-space.
1415  * @rep: Response argument to user-space.
1416  * @file_priv: Pointer to a drm file private structure.
1417  */
1418 static int
vmw_gb_surface_define_internal(struct drm_device * dev,struct drm_vmw_gb_surface_create_ext_req * req,struct drm_vmw_gb_surface_create_rep * rep,struct drm_file * file_priv)1419 vmw_gb_surface_define_internal(struct drm_device *dev,
1420 			       struct drm_vmw_gb_surface_create_ext_req *req,
1421 			       struct drm_vmw_gb_surface_create_rep *rep,
1422 			       struct drm_file *file_priv)
1423 {
1424 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1425 	struct vmw_private *dev_priv = vmw_priv(dev);
1426 	struct vmw_user_surface *user_srf;
1427 	struct vmw_surface_metadata metadata = {0};
1428 	struct vmw_surface *srf;
1429 	struct vmw_resource *res;
1430 	struct vmw_resource *tmp;
1431 	int ret = 0;
1432 	uint32_t backup_handle = 0;
1433 	SVGA3dSurfaceAllFlags svga3d_flags_64 =
1434 		SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits,
1435 				req->base.svga3d_flags);
1436 
1437 	/* array_size must be null for non-GL3 host. */
1438 	if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
1439 		VMW_DEBUG_USER("SM4 surface not supported.\n");
1440 		return -EINVAL;
1441 	}
1442 
1443 	if (!has_sm4_1_context(dev_priv)) {
1444 		if (req->svga3d_flags_upper_32_bits != 0)
1445 			ret = -EINVAL;
1446 
1447 		if (req->base.multisample_count != 0)
1448 			ret = -EINVAL;
1449 
1450 		if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE)
1451 			ret = -EINVAL;
1452 
1453 		if (req->quality_level != SVGA3D_MS_QUALITY_NONE)
1454 			ret = -EINVAL;
1455 
1456 		if (ret) {
1457 			VMW_DEBUG_USER("SM4.1 surface not supported.\n");
1458 			return ret;
1459 		}
1460 	}
1461 
1462 	if (req->buffer_byte_stride > 0 && !has_sm5_context(dev_priv)) {
1463 		VMW_DEBUG_USER("SM5 surface not supported.\n");
1464 		return -EINVAL;
1465 	}
1466 
1467 	if ((svga3d_flags_64 & SVGA3D_SURFACE_MULTISAMPLE) &&
1468 	    req->base.multisample_count == 0) {
1469 		VMW_DEBUG_USER("Invalid sample count.\n");
1470 		return -EINVAL;
1471 	}
1472 
1473 	if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS) {
1474 		VMW_DEBUG_USER("Invalid mip level.\n");
1475 		return -EINVAL;
1476 	}
1477 
1478 	metadata.flags = svga3d_flags_64;
1479 	metadata.format = req->base.format;
1480 	metadata.mip_levels[0] = req->base.mip_levels;
1481 	metadata.multisample_count = req->base.multisample_count;
1482 	metadata.multisample_pattern = req->multisample_pattern;
1483 	metadata.quality_level = req->quality_level;
1484 	metadata.array_size = req->base.array_size;
1485 	metadata.buffer_byte_stride = req->buffer_byte_stride;
1486 	metadata.num_sizes = 1;
1487 	metadata.base_size = req->base.base_size;
1488 	metadata.scanout = req->base.drm_surface_flags &
1489 		drm_vmw_surface_flag_scanout;
1490 
1491 	/* Define a surface based on the parameters. */
1492 	ret = vmw_gb_surface_define(dev_priv, &metadata, &srf);
1493 	if (ret != 0) {
1494 		VMW_DEBUG_USER("Failed to define surface.\n");
1495 		return ret;
1496 	}
1497 
1498 	user_srf = container_of(srf, struct vmw_user_surface, srf);
1499 	if (drm_is_primary_client(file_priv))
1500 		user_srf->master = drm_file_get_master(file_priv);
1501 
1502 	res = &user_srf->srf.res;
1503 
1504 	if (req->base.buffer_handle != SVGA3D_INVALID_ID) {
1505 		ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle,
1506 					 &res->guest_memory_bo);
1507 		if (ret == 0) {
1508 			if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) {
1509 				VMW_DEBUG_USER("Surface backup buffer too small.\n");
1510 				vmw_user_bo_unref(&res->guest_memory_bo);
1511 				ret = -EINVAL;
1512 				goto out_unlock;
1513 			} else {
1514 				backup_handle = req->base.buffer_handle;
1515 			}
1516 		}
1517 	} else if (req->base.drm_surface_flags &
1518 		   (drm_vmw_surface_flag_create_buffer |
1519 		    drm_vmw_surface_flag_coherent)) {
1520 		ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,
1521 							res->guest_memory_size,
1522 							&backup_handle,
1523 							&res->guest_memory_bo);
1524 	}
1525 
1526 	if (unlikely(ret != 0)) {
1527 		vmw_resource_unreference(&res);
1528 		goto out_unlock;
1529 	}
1530 
1531 	if (req->base.drm_surface_flags & drm_vmw_surface_flag_coherent) {
1532 		struct vmw_bo *backup = res->guest_memory_bo;
1533 
1534 		ttm_bo_reserve(&backup->tbo, false, false, NULL);
1535 		if (!res->func->dirty_alloc)
1536 			ret = -EINVAL;
1537 		if (!ret)
1538 			ret = vmw_bo_dirty_add(backup);
1539 		if (!ret) {
1540 			res->coherent = true;
1541 			ret = res->func->dirty_alloc(res);
1542 		}
1543 		ttm_bo_unreserve(&backup->tbo);
1544 		if (ret) {
1545 			vmw_resource_unreference(&res);
1546 			goto out_unlock;
1547 		}
1548 
1549 	}
1550 
1551 	tmp = vmw_resource_reference(res);
1552 	ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime,
1553 				    req->base.drm_surface_flags &
1554 				    drm_vmw_surface_flag_shareable,
1555 				    VMW_RES_SURFACE,
1556 				    &vmw_user_surface_base_release);
1557 
1558 	if (unlikely(ret != 0)) {
1559 		vmw_resource_unreference(&tmp);
1560 		vmw_resource_unreference(&res);
1561 		goto out_unlock;
1562 	}
1563 
1564 	rep->handle      = user_srf->prime.base.handle;
1565 	rep->backup_size = res->guest_memory_size;
1566 	if (res->guest_memory_bo) {
1567 		rep->buffer_map_handle =
1568 			drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node);
1569 		rep->buffer_size = res->guest_memory_bo->tbo.base.size;
1570 		rep->buffer_handle = backup_handle;
1571 	} else {
1572 		rep->buffer_map_handle = 0;
1573 		rep->buffer_size = 0;
1574 		rep->buffer_handle = SVGA3D_INVALID_ID;
1575 	}
1576 	vmw_resource_unreference(&res);
1577 
1578 out_unlock:
1579 	return ret;
1580 }
1581 
1582 /**
1583  * vmw_gb_surface_reference_internal - Ioctl function implementing
1584  * the user surface reference functionality.
1585  *
1586  * @dev: Pointer to a struct drm_device.
1587  * @req: Pointer to user-space request surface arg.
1588  * @rep: Pointer to response to user-space.
1589  * @file_priv: Pointer to a drm file private structure.
1590  */
1591 static int
vmw_gb_surface_reference_internal(struct drm_device * dev,struct drm_vmw_surface_arg * req,struct drm_vmw_gb_surface_ref_ext_rep * rep,struct drm_file * file_priv)1592 vmw_gb_surface_reference_internal(struct drm_device *dev,
1593 				  struct drm_vmw_surface_arg *req,
1594 				  struct drm_vmw_gb_surface_ref_ext_rep *rep,
1595 				  struct drm_file *file_priv)
1596 {
1597 	struct vmw_private *dev_priv = vmw_priv(dev);
1598 	struct vmw_surface *srf;
1599 	struct vmw_user_surface *user_srf;
1600 	struct vmw_surface_metadata *metadata;
1601 	struct ttm_base_object *base;
1602 	u32 backup_handle;
1603 	int ret;
1604 
1605 	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1606 					   req->handle_type, &base);
1607 	if (unlikely(ret != 0))
1608 		return ret;
1609 
1610 	user_srf = container_of(base, struct vmw_user_surface, prime.base);
1611 	srf = &user_srf->srf;
1612 	if (!srf->res.guest_memory_bo) {
1613 		DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
1614 		goto out_bad_resource;
1615 	}
1616 	metadata = &srf->metadata;
1617 
1618 	mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
1619 	ret = drm_gem_handle_create(file_priv, &srf->res.guest_memory_bo->tbo.base,
1620 				    &backup_handle);
1621 	mutex_unlock(&dev_priv->cmdbuf_mutex);
1622 	if (ret != 0) {
1623 		drm_err(dev, "Wasn't able to create a backing handle for surface sid = %u.\n",
1624 			req->sid);
1625 		goto out_bad_resource;
1626 	}
1627 
1628 	rep->creq.base.svga3d_flags = SVGA3D_FLAGS_LOWER_32(metadata->flags);
1629 	rep->creq.base.format = metadata->format;
1630 	rep->creq.base.mip_levels = metadata->mip_levels[0];
1631 	rep->creq.base.drm_surface_flags = 0;
1632 	rep->creq.base.multisample_count = metadata->multisample_count;
1633 	rep->creq.base.autogen_filter = metadata->autogen_filter;
1634 	rep->creq.base.array_size = metadata->array_size;
1635 	rep->creq.base.buffer_handle = backup_handle;
1636 	rep->creq.base.base_size = metadata->base_size;
1637 	rep->crep.handle = user_srf->prime.base.handle;
1638 	rep->crep.backup_size = srf->res.guest_memory_size;
1639 	rep->crep.buffer_handle = backup_handle;
1640 	rep->crep.buffer_map_handle =
1641 		drm_vma_node_offset_addr(&srf->res.guest_memory_bo->tbo.base.vma_node);
1642 	rep->crep.buffer_size = srf->res.guest_memory_bo->tbo.base.size;
1643 
1644 	rep->creq.version = drm_vmw_gb_surface_v1;
1645 	rep->creq.svga3d_flags_upper_32_bits =
1646 		SVGA3D_FLAGS_UPPER_32(metadata->flags);
1647 	rep->creq.multisample_pattern = metadata->multisample_pattern;
1648 	rep->creq.quality_level = metadata->quality_level;
1649 	rep->creq.must_be_zero = 0;
1650 
1651 out_bad_resource:
1652 	ttm_base_object_unref(&base);
1653 
1654 	return ret;
1655 }
1656 
1657 /**
1658  * vmw_subres_dirty_add - Add a dirty region to a subresource
1659  * @dirty: The surfaces's dirty tracker.
1660  * @loc_start: The location corresponding to the start of the region.
1661  * @loc_end: The location corresponding to the end of the region.
1662  *
1663  * As we are assuming that @loc_start and @loc_end represent a sequential
1664  * range of backing store memory, if the region spans multiple lines then
1665  * regardless of the x coordinate, the full lines are dirtied.
1666  * Correspondingly if the region spans multiple z slices, then full rather
1667  * than partial z slices are dirtied.
1668  */
vmw_subres_dirty_add(struct vmw_surface_dirty * dirty,const struct vmw_surface_loc * loc_start,const struct vmw_surface_loc * loc_end)1669 static void vmw_subres_dirty_add(struct vmw_surface_dirty *dirty,
1670 				 const struct vmw_surface_loc *loc_start,
1671 				 const struct vmw_surface_loc *loc_end)
1672 {
1673 	const struct vmw_surface_cache *cache = &dirty->cache;
1674 	SVGA3dBox *box = &dirty->boxes[loc_start->sub_resource];
1675 	u32 mip = loc_start->sub_resource % cache->num_mip_levels;
1676 	const struct drm_vmw_size *size = &cache->mip[mip].size;
1677 	u32 box_c2 = box->z + box->d;
1678 
1679 	if (WARN_ON(loc_start->sub_resource >= dirty->num_subres))
1680 		return;
1681 
1682 	if (box->d == 0 || box->z > loc_start->z)
1683 		box->z = loc_start->z;
1684 	if (box_c2 < loc_end->z)
1685 		box->d = loc_end->z - box->z;
1686 
1687 	if (loc_start->z + 1 == loc_end->z) {
1688 		box_c2 = box->y + box->h;
1689 		if (box->h == 0 || box->y > loc_start->y)
1690 			box->y = loc_start->y;
1691 		if (box_c2 < loc_end->y)
1692 			box->h = loc_end->y - box->y;
1693 
1694 		if (loc_start->y + 1 == loc_end->y) {
1695 			box_c2 = box->x + box->w;
1696 			if (box->w == 0 || box->x > loc_start->x)
1697 				box->x = loc_start->x;
1698 			if (box_c2 < loc_end->x)
1699 				box->w = loc_end->x - box->x;
1700 		} else {
1701 			box->x = 0;
1702 			box->w = size->width;
1703 		}
1704 	} else {
1705 		box->y = 0;
1706 		box->h = size->height;
1707 		box->x = 0;
1708 		box->w = size->width;
1709 	}
1710 }
1711 
1712 /**
1713  * vmw_subres_dirty_full - Mark a full subresource as dirty
1714  * @dirty: The surface's dirty tracker.
1715  * @subres: The subresource
1716  */
vmw_subres_dirty_full(struct vmw_surface_dirty * dirty,u32 subres)1717 static void vmw_subres_dirty_full(struct vmw_surface_dirty *dirty, u32 subres)
1718 {
1719 	const struct vmw_surface_cache *cache = &dirty->cache;
1720 	u32 mip = subres % cache->num_mip_levels;
1721 	const struct drm_vmw_size *size = &cache->mip[mip].size;
1722 	SVGA3dBox *box = &dirty->boxes[subres];
1723 
1724 	box->x = 0;
1725 	box->y = 0;
1726 	box->z = 0;
1727 	box->w = size->width;
1728 	box->h = size->height;
1729 	box->d = size->depth;
1730 }
1731 
1732 /*
1733  * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for texture
1734  * surfaces.
1735  */
vmw_surface_tex_dirty_range_add(struct vmw_resource * res,size_t start,size_t end)1736 static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res,
1737 					    size_t start, size_t end)
1738 {
1739 	struct vmw_surface_dirty *dirty =
1740 		(struct vmw_surface_dirty *) res->dirty;
1741 	size_t backup_end = res->guest_memory_offset + res->guest_memory_size;
1742 	struct vmw_surface_loc loc1, loc2;
1743 	const struct vmw_surface_cache *cache;
1744 
1745 	start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset;
1746 	end = min(end, backup_end) - res->guest_memory_offset;
1747 	cache = &dirty->cache;
1748 	vmw_surface_get_loc(cache, &loc1, start);
1749 	vmw_surface_get_loc(cache, &loc2, end - 1);
1750 	vmw_surface_inc_loc(cache, &loc2);
1751 
1752 	if (loc1.sheet != loc2.sheet) {
1753 		u32 sub_res;
1754 
1755 		/*
1756 		 * Multiple multisample sheets. To do this in an optimized
1757 		 * fashion, compute the dirty region for each sheet and the
1758 		 * resulting union. Since this is not a common case, just dirty
1759 		 * the whole surface.
1760 		 */
1761 		for (sub_res = 0; sub_res < dirty->num_subres; ++sub_res)
1762 			vmw_subres_dirty_full(dirty, sub_res);
1763 		return;
1764 	}
1765 	if (loc1.sub_resource + 1 == loc2.sub_resource) {
1766 		/* Dirty range covers a single sub-resource */
1767 		vmw_subres_dirty_add(dirty, &loc1, &loc2);
1768 	} else {
1769 		/* Dirty range covers multiple sub-resources */
1770 		struct vmw_surface_loc loc_min, loc_max;
1771 		u32 sub_res;
1772 
1773 		vmw_surface_max_loc(cache, loc1.sub_resource, &loc_max);
1774 		vmw_subres_dirty_add(dirty, &loc1, &loc_max);
1775 		vmw_surface_min_loc(cache, loc2.sub_resource - 1, &loc_min);
1776 		vmw_subres_dirty_add(dirty, &loc_min, &loc2);
1777 		for (sub_res = loc1.sub_resource + 1;
1778 		     sub_res < loc2.sub_resource - 1; ++sub_res)
1779 			vmw_subres_dirty_full(dirty, sub_res);
1780 	}
1781 }
1782 
1783 /*
1784  * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for buffer
1785  * surfaces.
1786  */
vmw_surface_buf_dirty_range_add(struct vmw_resource * res,size_t start,size_t end)1787 static void vmw_surface_buf_dirty_range_add(struct vmw_resource *res,
1788 					    size_t start, size_t end)
1789 {
1790 	struct vmw_surface_dirty *dirty =
1791 		(struct vmw_surface_dirty *) res->dirty;
1792 	const struct vmw_surface_cache *cache = &dirty->cache;
1793 	size_t backup_end = res->guest_memory_offset + cache->mip_chain_bytes;
1794 	SVGA3dBox *box = &dirty->boxes[0];
1795 	u32 box_c2;
1796 
1797 	box->h = box->d = 1;
1798 	start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset;
1799 	end = min(end, backup_end) - res->guest_memory_offset;
1800 	box_c2 = box->x + box->w;
1801 	if (box->w == 0 || box->x > start)
1802 		box->x = start;
1803 	if (box_c2 < end)
1804 		box->w = end - box->x;
1805 }
1806 
1807 /*
1808  * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for surfaces
1809  */
vmw_surface_dirty_range_add(struct vmw_resource * res,size_t start,size_t end)1810 static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start,
1811 					size_t end)
1812 {
1813 	struct vmw_surface *srf = vmw_res_to_srf(res);
1814 
1815 	if (WARN_ON(end <= res->guest_memory_offset ||
1816 		    start >= res->guest_memory_offset + res->guest_memory_size))
1817 		return;
1818 
1819 	if (srf->metadata.format == SVGA3D_BUFFER)
1820 		vmw_surface_buf_dirty_range_add(res, start, end);
1821 	else
1822 		vmw_surface_tex_dirty_range_add(res, start, end);
1823 }
1824 
1825 /*
1826  * vmw_surface_dirty_sync - The surface's dirty_sync callback.
1827  */
vmw_surface_dirty_sync(struct vmw_resource * res)1828 static int vmw_surface_dirty_sync(struct vmw_resource *res)
1829 {
1830 	struct vmw_private *dev_priv = res->dev_priv;
1831 	u32 i, num_dirty;
1832 	struct vmw_surface_dirty *dirty =
1833 		(struct vmw_surface_dirty *) res->dirty;
1834 	size_t alloc_size;
1835 	const struct vmw_surface_cache *cache = &dirty->cache;
1836 	struct {
1837 		SVGA3dCmdHeader header;
1838 		SVGA3dCmdDXUpdateSubResource body;
1839 	} *cmd1;
1840 	struct {
1841 		SVGA3dCmdHeader header;
1842 		SVGA3dCmdUpdateGBImage body;
1843 	} *cmd2;
1844 	void *cmd;
1845 
1846 	num_dirty = 0;
1847 	for (i = 0; i < dirty->num_subres; ++i) {
1848 		const SVGA3dBox *box = &dirty->boxes[i];
1849 
1850 		if (box->d)
1851 			num_dirty++;
1852 	}
1853 
1854 	if (!num_dirty)
1855 		goto out;
1856 
1857 	alloc_size = num_dirty * ((has_sm4_context(dev_priv)) ? sizeof(*cmd1) : sizeof(*cmd2));
1858 	cmd = VMW_CMD_RESERVE(dev_priv, alloc_size);
1859 	if (!cmd)
1860 		return -ENOMEM;
1861 
1862 	cmd1 = cmd;
1863 	cmd2 = cmd;
1864 
1865 	for (i = 0; i < dirty->num_subres; ++i) {
1866 		const SVGA3dBox *box = &dirty->boxes[i];
1867 
1868 		if (!box->d)
1869 			continue;
1870 
1871 		/*
1872 		 * DX_UPDATE_SUBRESOURCE is aware of array surfaces.
1873 		 * UPDATE_GB_IMAGE is not.
1874 		 */
1875 		if (has_sm4_context(dev_priv)) {
1876 			cmd1->header.id = SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE;
1877 			cmd1->header.size = sizeof(cmd1->body);
1878 			cmd1->body.sid = res->id;
1879 			cmd1->body.subResource = i;
1880 			cmd1->body.box = *box;
1881 			cmd1++;
1882 		} else {
1883 			cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
1884 			cmd2->header.size = sizeof(cmd2->body);
1885 			cmd2->body.image.sid = res->id;
1886 			cmd2->body.image.face = i / cache->num_mip_levels;
1887 			cmd2->body.image.mipmap = i -
1888 				(cache->num_mip_levels * cmd2->body.image.face);
1889 			cmd2->body.box = *box;
1890 			cmd2++;
1891 		}
1892 
1893 	}
1894 	vmw_cmd_commit(dev_priv, alloc_size);
1895  out:
1896 	memset(&dirty->boxes[0], 0, sizeof(dirty->boxes[0]) *
1897 	       dirty->num_subres);
1898 
1899 	return 0;
1900 }
1901 
1902 /*
1903  * vmw_surface_dirty_alloc - The surface's dirty_alloc callback.
1904  */
vmw_surface_dirty_alloc(struct vmw_resource * res)1905 static int vmw_surface_dirty_alloc(struct vmw_resource *res)
1906 {
1907 	struct vmw_surface *srf = vmw_res_to_srf(res);
1908 	const struct vmw_surface_metadata *metadata = &srf->metadata;
1909 	struct vmw_surface_dirty *dirty;
1910 	u32 num_layers = 1;
1911 	u32 num_mip;
1912 	u32 num_subres;
1913 	u32 num_samples;
1914 	size_t dirty_size;
1915 	int ret;
1916 
1917 	if (metadata->array_size)
1918 		num_layers = metadata->array_size;
1919 	else if (metadata->flags & SVGA3D_SURFACE_CUBEMAP)
1920 		num_layers *= SVGA3D_MAX_SURFACE_FACES;
1921 
1922 	num_mip = metadata->mip_levels[0];
1923 	if (!num_mip)
1924 		num_mip = 1;
1925 
1926 	num_subres = num_layers * num_mip;
1927 	dirty_size = struct_size(dirty, boxes, num_subres);
1928 
1929 	dirty = kvzalloc(dirty_size, GFP_KERNEL);
1930 	if (!dirty) {
1931 		ret = -ENOMEM;
1932 		goto out_no_dirty;
1933 	}
1934 
1935 	num_samples = max_t(u32, 1, metadata->multisample_count);
1936 	ret = vmw_surface_setup_cache(&metadata->base_size, metadata->format,
1937 				      num_mip, num_layers, num_samples,
1938 				      &dirty->cache);
1939 	if (ret)
1940 		goto out_no_cache;
1941 
1942 	dirty->num_subres = num_subres;
1943 	res->dirty = (struct vmw_resource_dirty *) dirty;
1944 
1945 	return 0;
1946 
1947 out_no_cache:
1948 	kvfree(dirty);
1949 out_no_dirty:
1950 	return ret;
1951 }
1952 
1953 /*
1954  * vmw_surface_dirty_free - The surface's dirty_free callback
1955  */
vmw_surface_dirty_free(struct vmw_resource * res)1956 static void vmw_surface_dirty_free(struct vmw_resource *res)
1957 {
1958 	struct vmw_surface_dirty *dirty =
1959 		(struct vmw_surface_dirty *) res->dirty;
1960 
1961 	kvfree(dirty);
1962 	res->dirty = NULL;
1963 }
1964 
1965 /*
1966  * vmw_surface_clean - The surface's clean callback
1967  */
vmw_surface_clean(struct vmw_resource * res)1968 static int vmw_surface_clean(struct vmw_resource *res)
1969 {
1970 	struct vmw_private *dev_priv = res->dev_priv;
1971 	size_t alloc_size;
1972 	struct {
1973 		SVGA3dCmdHeader header;
1974 		SVGA3dCmdReadbackGBSurface body;
1975 	} *cmd;
1976 
1977 	alloc_size = sizeof(*cmd);
1978 	cmd = VMW_CMD_RESERVE(dev_priv, alloc_size);
1979 	if (!cmd)
1980 		return -ENOMEM;
1981 
1982 	cmd->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
1983 	cmd->header.size = sizeof(cmd->body);
1984 	cmd->body.sid = res->id;
1985 	vmw_cmd_commit(dev_priv, alloc_size);
1986 
1987 	return 0;
1988 }
1989 
1990 /*
1991  * vmw_gb_surface_define - Define a private GB surface
1992  *
1993  * @dev_priv: Pointer to a device private.
1994  * @metadata: Metadata representing the surface to create.
1995  * @user_srf_out: allocated user_srf. Set to NULL on failure.
1996  *
1997  * GB surfaces allocated by this function will not have a user mode handle, and
1998  * thus will only be visible to vmwgfx.  For optimization reasons the
1999  * surface may later be given a user mode handle by another function to make
2000  * it available to user mode drivers.
2001  */
vmw_gb_surface_define(struct vmw_private * dev_priv,const struct vmw_surface_metadata * req,struct vmw_surface ** srf_out)2002 int vmw_gb_surface_define(struct vmw_private *dev_priv,
2003 			  const struct vmw_surface_metadata *req,
2004 			  struct vmw_surface **srf_out)
2005 {
2006 	struct vmw_surface_metadata *metadata;
2007 	struct vmw_user_surface *user_srf;
2008 	struct vmw_surface *srf;
2009 	u32 sample_count = 1;
2010 	u32 num_layers = 1;
2011 	int ret;
2012 
2013 	*srf_out = NULL;
2014 
2015 	if (req->scanout) {
2016 		if (!vmw_surface_is_screen_target_format(req->format)) {
2017 			VMW_DEBUG_USER("Invalid Screen Target surface format.");
2018 			return -EINVAL;
2019 		}
2020 
2021 		if (req->base_size.width > dev_priv->texture_max_width ||
2022 		    req->base_size.height > dev_priv->texture_max_height) {
2023 			VMW_DEBUG_USER("%ux%u\n, exceed max surface size %ux%u",
2024 				       req->base_size.width,
2025 				       req->base_size.height,
2026 				       dev_priv->texture_max_width,
2027 				       dev_priv->texture_max_height);
2028 			return -EINVAL;
2029 		}
2030 	} else {
2031 		const SVGA3dSurfaceDesc *desc =
2032 			vmw_surface_get_desc(req->format);
2033 
2034 		if (desc->blockDesc == SVGA3DBLOCKDESC_NONE) {
2035 			VMW_DEBUG_USER("Invalid surface format.\n");
2036 			return -EINVAL;
2037 		}
2038 	}
2039 
2040 	if (req->autogen_filter != SVGA3D_TEX_FILTER_NONE)
2041 		return -EINVAL;
2042 
2043 	if (req->num_sizes != 1)
2044 		return -EINVAL;
2045 
2046 	if (req->sizes != NULL)
2047 		return -EINVAL;
2048 
2049 	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
2050 	if (unlikely(!user_srf)) {
2051 		ret = -ENOMEM;
2052 		goto out_unlock;
2053 	}
2054 
2055 	*srf_out  = &user_srf->srf;
2056 	user_srf->prime.base.shareable = false;
2057 	user_srf->prime.base.tfile = NULL;
2058 
2059 	srf = &user_srf->srf;
2060 	srf->metadata = *req;
2061 	srf->offsets = NULL;
2062 
2063 	metadata = &srf->metadata;
2064 
2065 	if (metadata->array_size)
2066 		num_layers = req->array_size;
2067 	else if (metadata->flags & SVGA3D_SURFACE_CUBEMAP)
2068 		num_layers = SVGA3D_MAX_SURFACE_FACES;
2069 
2070 	if (metadata->flags & SVGA3D_SURFACE_MULTISAMPLE)
2071 		sample_count = metadata->multisample_count;
2072 
2073 	srf->res.guest_memory_size =
2074 		vmw_surface_get_serialized_size_extended(
2075 				metadata->format,
2076 				metadata->base_size,
2077 				metadata->mip_levels[0],
2078 				num_layers,
2079 				sample_count);
2080 
2081 	if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
2082 		srf->res.guest_memory_size += sizeof(SVGA3dDXSOState);
2083 
2084 	/*
2085 	 * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with
2086 	 * size greater than STDU max width/height. This is really a workaround
2087 	 * to support creation of big framebuffer requested by some user-space
2088 	 * for whole topology. That big framebuffer won't really be used for
2089 	 * binding with screen target as during prepare_fb a separate surface is
2090 	 * created so it's safe to ignore SVGA3D_SURFACE_SCREENTARGET flag.
2091 	 */
2092 	if (dev_priv->active_display_unit == vmw_du_screen_target &&
2093 	    metadata->scanout &&
2094 	    metadata->base_size.width <= dev_priv->stdu_max_width &&
2095 	    metadata->base_size.height <= dev_priv->stdu_max_height)
2096 		metadata->flags |= SVGA3D_SURFACE_SCREENTARGET;
2097 
2098 	/*
2099 	 * From this point, the generic resource management functions
2100 	 * destroy the object on failure.
2101 	 */
2102 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
2103 
2104 	return ret;
2105 
2106 out_unlock:
2107 	return ret;
2108 }
2109