Merge branch 'vmwgfx-next' of git://people.freedesktop.org/~thomash/linux into drm-next

vmwgfx updates + new logging uapi

https://patchwork.freedesktop.org/patch/349809/ is appropriate userpsace patch.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m=20=28VMware=29?=
Link: https://patchwork.freedesktop.org/patch/msgid/20200116092934.5276-1-thomas_os@shipmail.org
This commit is contained in:
Dave Airlie 2020-01-20 14:16:32 +10:00
commit 61ff410fae
8 changed files with 200 additions and 34 deletions

View File

@ -209,8 +209,10 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
cres->hash.key = user_key | (res_type << 24);
ret = drm_ht_insert_item(&man->resources, &cres->hash);
if (unlikely(ret != 0))
if (unlikely(ret != 0)) {
kfree(cres);
goto out_invalid_key;
}
cres->state = VMW_CMDBUF_RES_ADD;
cres->res = vmw_resource_reference(res);

View File

@ -28,10 +28,10 @@
#include <linux/console.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <drm/drm_drv.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_pci.h>
#include <drm/drm_sysfs.h>
#include <drm/ttm/ttm_bo_driver.h>
#include <drm/ttm/ttm_module.h>
@ -150,6 +150,9 @@
#define DRM_IOCTL_VMW_GB_SURFACE_REF_EXT \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_REF_EXT, \
union drm_vmw_gb_surface_reference_ext_arg)
#define DRM_IOCTL_VMW_MSG \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_MSG, \
struct drm_vmw_msg_arg)
/**
* The core DRM version of this macro doesn't account for
@ -165,9 +168,9 @@
static const struct drm_ioctl_desc vmw_ioctls[] = {
VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_bo_alloc_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl,
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
@ -182,16 +185,16 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
DRM_MASTER),
VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl, DRM_AUTH |
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
DRM_RENDER_ALLOW),
@ -201,9 +204,9 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
/* these allow direct access to the framebuffers mark as master only */
VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
@ -221,28 +224,31 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_CREATE_SHADER,
vmw_shader_define_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_UNREF_SHADER,
vmw_shader_destroy_ioctl,
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
vmw_gb_surface_define_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
vmw_gb_surface_reference_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_SYNCCPU,
vmw_user_bo_synccpu_ioctl,
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT,
vmw_extended_context_define_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE_EXT,
vmw_gb_surface_define_ext_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_GB_SURFACE_REF_EXT,
vmw_gb_surface_reference_ext_ioctl,
DRM_AUTH | DRM_RENDER_ALLOW),
DRM_RENDER_ALLOW),
VMW_IOCTL_DEF(VMW_MSG,
vmw_msg_ioctl,
DRM_RENDER_ALLOW),
};
static const struct pci_device_id vmw_pci_id_list[] = {
@ -1211,8 +1217,10 @@ static void vmw_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
drm_dev_unregister(dev);
vmw_driver_unload(dev);
drm_dev_put(dev);
pci_disable_device(pdev);
drm_put_dev(dev);
}
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
@ -1391,8 +1399,6 @@ static const struct file_operations vmwgfx_driver_fops = {
static struct drm_driver driver = {
.driver_features =
DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC,
.load = vmw_driver_load,
.unload = vmw_driver_unload,
.get_vblank_counter = vmw_get_vblank_counter,
.enable_vblank = vmw_enable_vblank,
.disable_vblank = vmw_disable_vblank,
@ -1431,7 +1437,39 @@ static struct pci_driver vmw_pci_driver = {
static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
return drm_get_pci_dev(pdev, ent, &driver);
struct drm_device *dev;
int ret;
ret = pci_enable_device(pdev);
if (ret)
return ret;
dev = drm_dev_alloc(&driver, &pdev->dev);
if (IS_ERR(dev)) {
ret = PTR_ERR(dev);
goto err_pci_disable_device;
}
dev->pdev = pdev;
pci_set_drvdata(pdev, dev);
ret = vmw_driver_load(dev, ent->driver_data);
if (ret)
goto err_drm_dev_put;
ret = drm_dev_register(dev, ent->driver_data);
if (ret)
goto err_vmw_driver_unload;
return 0;
err_vmw_driver_unload:
vmw_driver_unload(dev);
err_drm_dev_put:
drm_dev_put(dev);
err_pci_disable_device:
pci_disable_device(pdev);
return ret;
}
static int __init vmwgfx_init(void)

View File

@ -56,9 +56,9 @@
#define VMWGFX_DRIVER_NAME "vmwgfx"
#define VMWGFX_DRIVER_DATE "20190328"
#define VMWGFX_DRIVER_DATE "20200114"
#define VMWGFX_DRIVER_MAJOR 2
#define VMWGFX_DRIVER_MINOR 16
#define VMWGFX_DRIVER_MINOR 17
#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
@ -1403,6 +1403,8 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
int vmw_host_get_guestinfo(const char *guest_info_param,
char *buffer, size_t *length);
int vmw_host_log(const char *log);
int vmw_msg_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
/* VMW logging */

View File

@ -2377,9 +2377,12 @@ static int vmw_cmd_dx_clear_rendertarget_view(struct vmw_private *dev_priv,
{
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXClearRenderTargetView) =
container_of(header, typeof(*cmd), header);
struct vmw_resource *ret;
return PTR_RET(vmw_view_id_val_add(sw_context, vmw_view_rt,
cmd->body.renderTargetViewId));
ret = vmw_view_id_val_add(sw_context, vmw_view_rt,
cmd->body.renderTargetViewId);
return PTR_ERR_OR_ZERO(ret);
}
/**
@ -2396,9 +2399,12 @@ static int vmw_cmd_dx_clear_depthstencil_view(struct vmw_private *dev_priv,
{
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXClearDepthStencilView) =
container_of(header, typeof(*cmd), header);
struct vmw_resource *ret;
return PTR_RET(vmw_view_id_val_add(sw_context, vmw_view_ds,
cmd->body.depthStencilViewId));
ret = vmw_view_id_val_add(sw_context, vmw_view_ds,
cmd->body.depthStencilViewId);
return PTR_ERR_OR_ZERO(ret);
}
static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv,
@ -2741,9 +2747,12 @@ static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv,
{
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXGenMips) =
container_of(header, typeof(*cmd), header);
struct vmw_resource *ret;
return PTR_RET(vmw_view_id_val_add(sw_context, vmw_view_sr,
cmd->body.shaderResourceViewId));
ret = vmw_view_id_val_add(sw_context, vmw_view_sr,
cmd->body.shaderResourceViewId);
return PTR_ERR_OR_ZERO(ret);
}
/**

View File

@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mem_encrypt.h>
#include <asm/hypervisor.h>
@ -56,6 +57,8 @@
#define HIGH_WORD(X) ((X & 0xFFFF0000) >> 16)
#define MAX_USER_MSG_LENGTH PAGE_SIZE
static u32 vmw_msg_enabled = 1;
enum rpc_msg_type {
@ -148,7 +151,8 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
unsigned long si, di, eax, ebx, ecx, edx;
unsigned long msg_len = strlen(msg);
if (hb) {
/* HB port can't access encrypted memory. */
if (hb && !mem_encrypt_active()) {
unsigned long bp = channel->cookie_high;
si = (uintptr_t) msg;
@ -202,7 +206,8 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
{
unsigned long si, di, eax, ebx, ecx, edx;
if (hb) {
/* HB port can't access encrypted memory */
if (hb && !mem_encrypt_active()) {
unsigned long bp = channel->cookie_low;
si = channel->cookie_high;
@ -514,3 +519,84 @@ int vmw_host_log(const char *log)
return -EINVAL;
}
/**
* vmw_msg_ioctl: Sends and receveives a message to/from host from/to user-space
*
* Sends a message from user-space to host.
* Can also receive a result from host and return that to user-space.
*
* @dev: Identifies the drm device.
* @data: Pointer to the ioctl argument.
* @file_priv: Identifies the caller.
* Return: Zero on success, negative error code on error.
*/
int vmw_msg_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_vmw_msg_arg *arg =
(struct drm_vmw_msg_arg *) data;
struct rpc_channel channel;
char *msg;
int length;
msg = kmalloc(MAX_USER_MSG_LENGTH, GFP_KERNEL);
if (!msg) {
DRM_ERROR("Cannot allocate memory for log message.\n");
return -ENOMEM;
}
length = strncpy_from_user(msg, (void __user *)((unsigned long)arg->send),
MAX_USER_MSG_LENGTH);
if (length < 0 || length >= MAX_USER_MSG_LENGTH) {
DRM_ERROR("Userspace message access failure.\n");
kfree(msg);
return -EINVAL;
}
if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) {
DRM_ERROR("Failed to open channel.\n");
goto out_open;
}
if (vmw_send_msg(&channel, msg)) {
DRM_ERROR("Failed to send message to host.\n");
goto out_msg;
}
if (!arg->send_only) {
char *reply = NULL;
size_t reply_len = 0;
if (vmw_recv_msg(&channel, (void *) &reply, &reply_len)) {
DRM_ERROR("Failed to receive message from host.\n");
goto out_msg;
}
if (reply && reply_len > 0) {
if (copy_to_user((void __user *)((unsigned long)arg->receive),
reply, reply_len)) {
DRM_ERROR("Failed to copy message to userspace.\n");
kfree(reply);
goto out_msg;
}
arg->receive_len = (__u32)reply_len;
}
kfree(reply);
}
vmw_close_channel(&channel);
kfree(msg);
return 0;
out_msg:
vmw_close_channel(&channel);
out_open:
kfree(msg);
return -EINVAL;
}

View File

@ -934,16 +934,12 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
uint32_t handle;
struct ttm_base_object *base;
int ret;
bool require_exist = false;
if (handle_type == DRM_VMW_HANDLE_PRIME) {
ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
if (unlikely(ret != 0))
return ret;
} else {
if (unlikely(drm_is_render_client(file_priv)))
require_exist = true;
handle = u_handle;
}
@ -960,9 +956,18 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
}
if (handle_type != DRM_VMW_HANDLE_PRIME) {
bool require_exist = false;
user_srf = container_of(base, struct vmw_user_surface,
prime.base);
/* Error out if we are unauthenticated primary */
if (drm_is_primary_client(file_priv) &&
!file_priv->authenticated) {
ret = -EACCES;
goto out_bad_resource;
}
/*
* Make sure the surface creator has the same
* authenticating master, or is already registered with us.
@ -971,6 +976,9 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
user_srf->master != file_priv->master)
require_exist = true;
if (unlikely(drm_is_render_client(file_priv)))
require_exist = true;
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL,
require_exist);
if (unlikely(ret != 0)) {

View File

@ -45,6 +45,10 @@ int vmw_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &vmw_vm_ops;
/* Use VM_PFNMAP rather than VM_MIXEDMAP if not a COW mapping */
if ((vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) != VM_MAYWRITE)
vma->vm_flags = (vma->vm_flags & ~VM_MIXEDMAP) | VM_PFNMAP;
return 0;
}

View File

@ -71,6 +71,7 @@ extern "C" {
#define DRM_VMW_CREATE_EXTENDED_CONTEXT 26
#define DRM_VMW_GB_SURFACE_CREATE_EXT 27
#define DRM_VMW_GB_SURFACE_REF_EXT 28
#define DRM_VMW_MSG 29
/*************************************************************************/
/**
@ -1213,6 +1214,22 @@ union drm_vmw_gb_surface_reference_ext_arg {
struct drm_vmw_surface_arg req;
};
/**
* struct drm_vmw_msg_arg
*
* @send: Pointer to user-space msg string (null terminated).
* @receive: Pointer to user-space receive buffer.
* @send_only: Boolean whether this is only sending or receiving too.
*
* Argument to the DRM_VMW_MSG ioctl.
*/
struct drm_vmw_msg_arg {
__u64 send;
__u64 receive;
__s32 send_only;
__u32 receive_len;
};
#if defined(__cplusplus)
}
#endif