cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vmwgfx_ioctl.c (8772B)


      1// SPDX-License-Identifier: GPL-2.0 OR MIT
      2/**************************************************************************
      3 *
      4 * Copyright 2009-2022 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 "vmwgfx_devcaps.h"
     30#include "vmwgfx_kms.h"
     31
     32#include <drm/vmwgfx_drm.h>
     33#include <linux/pci.h>
     34
     35int vmw_getparam_ioctl(struct drm_device *dev, void *data,
     36		       struct drm_file *file_priv)
     37{
     38	struct vmw_private *dev_priv = vmw_priv(dev);
     39	struct drm_vmw_getparam_arg *param =
     40	    (struct drm_vmw_getparam_arg *)data;
     41	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
     42
     43	switch (param->param) {
     44	case DRM_VMW_PARAM_NUM_STREAMS:
     45		param->value = vmw_overlay_num_overlays(dev_priv);
     46		break;
     47	case DRM_VMW_PARAM_NUM_FREE_STREAMS:
     48		param->value = vmw_overlay_num_free_overlays(dev_priv);
     49		break;
     50	case DRM_VMW_PARAM_3D:
     51		param->value = vmw_supports_3d(dev_priv) ? 1 : 0;
     52		break;
     53	case DRM_VMW_PARAM_HW_CAPS:
     54		param->value = dev_priv->capabilities;
     55		break;
     56	case DRM_VMW_PARAM_HW_CAPS2:
     57		param->value = dev_priv->capabilities2;
     58		break;
     59	case DRM_VMW_PARAM_FIFO_CAPS:
     60		param->value = vmw_fifo_caps(dev_priv);
     61		break;
     62	case DRM_VMW_PARAM_MAX_FB_SIZE:
     63		param->value = dev_priv->max_primary_mem;
     64		break;
     65	case DRM_VMW_PARAM_FIFO_HW_VERSION:
     66	{
     67		if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
     68			param->value = SVGA3D_HWVERSION_WS8_B1;
     69		else
     70			param->value = vmw_fifo_mem_read(
     71					       dev_priv,
     72					       ((vmw_fifo_caps(dev_priv) &
     73						 SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
     74							SVGA_FIFO_3D_HWVERSION_REVISED :
     75							SVGA_FIFO_3D_HWVERSION));
     76		break;
     77	}
     78	case DRM_VMW_PARAM_MAX_SURF_MEMORY:
     79		if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
     80		    !vmw_fp->gb_aware)
     81			param->value = dev_priv->max_mob_pages * PAGE_SIZE / 2;
     82		else
     83			param->value = dev_priv->memory_size;
     84		break;
     85	case DRM_VMW_PARAM_3D_CAPS_SIZE:
     86		param->value = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
     87		break;
     88	case DRM_VMW_PARAM_MAX_MOB_MEMORY:
     89		vmw_fp->gb_aware = true;
     90		param->value = dev_priv->max_mob_pages * PAGE_SIZE;
     91		break;
     92	case DRM_VMW_PARAM_MAX_MOB_SIZE:
     93		param->value = dev_priv->max_mob_size;
     94		break;
     95	case DRM_VMW_PARAM_SCREEN_TARGET:
     96		param->value =
     97			(dev_priv->active_display_unit == vmw_du_screen_target);
     98		break;
     99	case DRM_VMW_PARAM_DX:
    100		param->value = has_sm4_context(dev_priv);
    101		break;
    102	case DRM_VMW_PARAM_SM4_1:
    103		param->value = has_sm4_1_context(dev_priv);
    104		break;
    105	case DRM_VMW_PARAM_SM5:
    106		param->value = has_sm5_context(dev_priv);
    107		break;
    108	case DRM_VMW_PARAM_GL43:
    109		param->value = has_gl43_context(dev_priv);
    110		break;
    111	case DRM_VMW_PARAM_DEVICE_ID:
    112		param->value = to_pci_dev(dev_priv->drm.dev)->device;
    113		break;
    114	default:
    115		return -EINVAL;
    116	}
    117
    118	return 0;
    119}
    120
    121
    122int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
    123			 struct drm_file *file_priv)
    124{
    125	struct drm_vmw_get_3d_cap_arg *arg =
    126		(struct drm_vmw_get_3d_cap_arg *) data;
    127	struct vmw_private *dev_priv = vmw_priv(dev);
    128	uint32_t size;
    129	void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
    130	void *bounce = NULL;
    131	int ret;
    132	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
    133
    134	if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {
    135		VMW_DEBUG_USER("Illegal GET_3D_CAP argument.\n");
    136		return -EINVAL;
    137	}
    138
    139	size = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
    140	if (unlikely(size == 0)) {
    141		DRM_ERROR("Failed to figure out the devcaps size (no 3D).\n");
    142		return -ENOMEM;
    143	}
    144
    145	if (arg->max_size < size)
    146		size = arg->max_size;
    147
    148	bounce = vzalloc(size);
    149	if (unlikely(bounce == NULL)) {
    150		DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
    151		return -ENOMEM;
    152	}
    153
    154	ret = vmw_devcaps_copy(dev_priv, vmw_fp->gb_aware, bounce, size);
    155	if (unlikely (ret != 0))
    156		goto out_err;
    157
    158	ret = copy_to_user(buffer, bounce, size);
    159	if (ret)
    160		ret = -EFAULT;
    161out_err:
    162	vfree(bounce);
    163
    164	if (unlikely(ret != 0))
    165		DRM_ERROR("Failed to report 3D caps info.\n");
    166
    167	return ret;
    168}
    169
    170int vmw_present_ioctl(struct drm_device *dev, void *data,
    171		      struct drm_file *file_priv)
    172{
    173	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    174	struct vmw_private *dev_priv = vmw_priv(dev);
    175	struct drm_vmw_present_arg *arg =
    176		(struct drm_vmw_present_arg *)data;
    177	struct vmw_surface *surface;
    178	struct drm_vmw_rect __user *clips_ptr;
    179	struct drm_vmw_rect *clips = NULL;
    180	struct drm_framebuffer *fb;
    181	struct vmw_framebuffer *vfb;
    182	struct vmw_resource *res;
    183	uint32_t num_clips;
    184	int ret;
    185
    186	num_clips = arg->num_clips;
    187	clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
    188
    189	if (unlikely(num_clips == 0))
    190		return 0;
    191
    192	if (clips_ptr == NULL) {
    193		VMW_DEBUG_USER("Variable clips_ptr must be specified.\n");
    194		ret = -EINVAL;
    195		goto out_clips;
    196	}
    197
    198	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
    199	if (clips == NULL) {
    200		DRM_ERROR("Failed to allocate clip rect list.\n");
    201		ret = -ENOMEM;
    202		goto out_clips;
    203	}
    204
    205	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
    206	if (ret) {
    207		DRM_ERROR("Failed to copy clip rects from userspace.\n");
    208		ret = -EFAULT;
    209		goto out_no_copy;
    210	}
    211
    212	drm_modeset_lock_all(dev);
    213
    214	fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
    215	if (!fb) {
    216		VMW_DEBUG_USER("Invalid framebuffer id.\n");
    217		ret = -ENOENT;
    218		goto out_no_fb;
    219	}
    220	vfb = vmw_framebuffer_to_vfb(fb);
    221
    222	ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid,
    223					      user_surface_converter,
    224					      &res);
    225	if (ret)
    226		goto out_no_surface;
    227
    228	surface = vmw_res_to_srf(res);
    229	ret = vmw_kms_present(dev_priv, file_priv,
    230			      vfb, surface, arg->sid,
    231			      arg->dest_x, arg->dest_y,
    232			      clips, num_clips);
    233
    234	/* vmw_user_surface_lookup takes one ref so does new_fb */
    235	vmw_surface_unreference(&surface);
    236
    237out_no_surface:
    238	drm_framebuffer_put(fb);
    239out_no_fb:
    240	drm_modeset_unlock_all(dev);
    241out_no_copy:
    242	kfree(clips);
    243out_clips:
    244	return ret;
    245}
    246
    247int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
    248			       struct drm_file *file_priv)
    249{
    250	struct vmw_private *dev_priv = vmw_priv(dev);
    251	struct drm_vmw_present_readback_arg *arg =
    252		(struct drm_vmw_present_readback_arg *)data;
    253	struct drm_vmw_fence_rep __user *user_fence_rep =
    254		(struct drm_vmw_fence_rep __user *)
    255		(unsigned long)arg->fence_rep;
    256	struct drm_vmw_rect __user *clips_ptr;
    257	struct drm_vmw_rect *clips = NULL;
    258	struct drm_framebuffer *fb;
    259	struct vmw_framebuffer *vfb;
    260	uint32_t num_clips;
    261	int ret;
    262
    263	num_clips = arg->num_clips;
    264	clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
    265
    266	if (unlikely(num_clips == 0))
    267		return 0;
    268
    269	if (clips_ptr == NULL) {
    270		VMW_DEBUG_USER("Argument clips_ptr must be specified.\n");
    271		ret = -EINVAL;
    272		goto out_clips;
    273	}
    274
    275	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
    276	if (clips == NULL) {
    277		DRM_ERROR("Failed to allocate clip rect list.\n");
    278		ret = -ENOMEM;
    279		goto out_clips;
    280	}
    281
    282	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
    283	if (ret) {
    284		DRM_ERROR("Failed to copy clip rects from userspace.\n");
    285		ret = -EFAULT;
    286		goto out_no_copy;
    287	}
    288
    289	drm_modeset_lock_all(dev);
    290
    291	fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
    292	if (!fb) {
    293		VMW_DEBUG_USER("Invalid framebuffer id.\n");
    294		ret = -ENOENT;
    295		goto out_no_fb;
    296	}
    297
    298	vfb = vmw_framebuffer_to_vfb(fb);
    299	if (!vfb->bo) {
    300		VMW_DEBUG_USER("Framebuffer not buffer backed.\n");
    301		ret = -EINVAL;
    302		goto out_no_ttm_lock;
    303	}
    304
    305	ret = vmw_kms_readback(dev_priv, file_priv,
    306			       vfb, user_fence_rep,
    307			       clips, num_clips);
    308
    309out_no_ttm_lock:
    310	drm_framebuffer_put(fb);
    311out_no_fb:
    312	drm_modeset_unlock_all(dev);
    313out_no_copy:
    314	kfree(clips);
    315out_clips:
    316	return ret;
    317}