mirror of
https://github.com/torvalds/linux.git
synced 2024-12-18 17:12:55 +00:00
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:
commit
61ff410fae
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 @@ out_open:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user