Skip to content

Commit cb92a32

Browse files
Roland Scheideggerthomashvmw
authored andcommitted
drm/vmwgfx: add ioctl for messaging from/to guest userspace to/from host
Up to now, guest userspace does logging directly to host using essentially the same rather complex port assembly stuff as the kernel. We'd rather use the same mechanism than duplicate it (it may also change in the future), hence add a new ioctl for relaying guest/host messaging (logging is just one application of it). Signed-off-by: Roland Scheidegger <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Thomas Hellstrom <[email protected]>
1 parent 40efb09 commit cb92a32

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@
150150
#define DRM_IOCTL_VMW_GB_SURFACE_REF_EXT \
151151
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_REF_EXT, \
152152
union drm_vmw_gb_surface_reference_ext_arg)
153+
#define DRM_IOCTL_VMW_MSG \
154+
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_MSG, \
155+
struct drm_vmw_msg_arg)
153156

154157
/**
155158
* The core DRM version of this macro doesn't account for
@@ -243,6 +246,9 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
243246
VMW_IOCTL_DEF(VMW_GB_SURFACE_REF_EXT,
244247
vmw_gb_surface_reference_ext_ioctl,
245248
DRM_RENDER_ALLOW),
249+
VMW_IOCTL_DEF(VMW_MSG,
250+
vmw_msg_ioctl,
251+
DRM_RENDER_ALLOW),
246252
};
247253

248254
static const struct pci_device_id vmw_pci_id_list[] = {

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,8 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
14031403
int vmw_host_get_guestinfo(const char *guest_info_param,
14041404
char *buffer, size_t *length);
14051405
int vmw_host_log(const char *log);
1406+
int vmw_msg_ioctl(struct drm_device *dev, void *data,
1407+
struct drm_file *file_priv);
14061408

14071409
/* VMW logging */
14081410

drivers/gpu/drm/vmwgfx/vmwgfx_msg.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757

5858
#define HIGH_WORD(X) ((X & 0xFFFF0000) >> 16)
5959

60+
#define MAX_USER_MSG_LENGTH PAGE_SIZE
61+
6062
static u32 vmw_msg_enabled = 1;
6163

6264
enum rpc_msg_type {
@@ -517,3 +519,84 @@ int vmw_host_log(const char *log)
517519

518520
return -EINVAL;
519521
}
522+
523+
524+
/**
525+
* vmw_msg_ioctl: Sends and receveives a message to/from host from/to user-space
526+
*
527+
* Sends a message from user-space to host.
528+
* Can also receive a result from host and return that to user-space.
529+
*
530+
* @dev: Identifies the drm device.
531+
* @data: Pointer to the ioctl argument.
532+
* @file_priv: Identifies the caller.
533+
* Return: Zero on success, negative error code on error.
534+
*/
535+
536+
int vmw_msg_ioctl(struct drm_device *dev, void *data,
537+
struct drm_file *file_priv)
538+
{
539+
struct drm_vmw_msg_arg *arg =
540+
(struct drm_vmw_msg_arg *) data;
541+
struct rpc_channel channel;
542+
char *msg;
543+
int length;
544+
545+
msg = kmalloc(MAX_USER_MSG_LENGTH, GFP_KERNEL);
546+
if (!msg) {
547+
DRM_ERROR("Cannot allocate memory for log message.\n");
548+
return -ENOMEM;
549+
}
550+
551+
length = strncpy_from_user(msg, (void __user *)((unsigned long)arg->send),
552+
MAX_USER_MSG_LENGTH);
553+
if (length < 0 || length >= MAX_USER_MSG_LENGTH) {
554+
DRM_ERROR("Userspace message access failure.\n");
555+
kfree(msg);
556+
return -EINVAL;
557+
}
558+
559+
560+
if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) {
561+
DRM_ERROR("Failed to open channel.\n");
562+
goto out_open;
563+
}
564+
565+
if (vmw_send_msg(&channel, msg)) {
566+
DRM_ERROR("Failed to send message to host.\n");
567+
goto out_msg;
568+
}
569+
570+
if (!arg->send_only) {
571+
char *reply = NULL;
572+
size_t reply_len = 0;
573+
574+
if (vmw_recv_msg(&channel, (void *) &reply, &reply_len)) {
575+
DRM_ERROR("Failed to receive message from host.\n");
576+
goto out_msg;
577+
}
578+
if (reply && reply_len > 0) {
579+
if (copy_to_user((void __user *)((unsigned long)arg->receive),
580+
reply, reply_len)) {
581+
DRM_ERROR("Failed to copy message to userspace.\n");
582+
kfree(reply);
583+
goto out_msg;
584+
}
585+
arg->receive_len = (__u32)reply_len;
586+
}
587+
kfree(reply);
588+
}
589+
590+
vmw_close_channel(&channel);
591+
kfree(msg);
592+
593+
return 0;
594+
595+
out_msg:
596+
vmw_close_channel(&channel);
597+
out_open:
598+
kfree(msg);
599+
600+
return -EINVAL;
601+
}
602+

include/uapi/drm/vmwgfx_drm.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ extern "C" {
7171
#define DRM_VMW_CREATE_EXTENDED_CONTEXT 26
7272
#define DRM_VMW_GB_SURFACE_CREATE_EXT 27
7373
#define DRM_VMW_GB_SURFACE_REF_EXT 28
74+
#define DRM_VMW_MSG 29
7475

7576
/*************************************************************************/
7677
/**
@@ -1213,6 +1214,22 @@ union drm_vmw_gb_surface_reference_ext_arg {
12131214
struct drm_vmw_surface_arg req;
12141215
};
12151216

1217+
/**
1218+
* struct drm_vmw_msg_arg
1219+
*
1220+
* @send: Pointer to user-space msg string (null terminated).
1221+
* @receive: Pointer to user-space receive buffer.
1222+
* @send_only: Boolean whether this is only sending or receiving too.
1223+
*
1224+
* Argument to the DRM_VMW_MSG ioctl.
1225+
*/
1226+
struct drm_vmw_msg_arg {
1227+
__u64 send;
1228+
__u64 receive;
1229+
__s32 send_only;
1230+
__u32 receive_len;
1231+
};
1232+
12161233
#if defined(__cplusplus)
12171234
}
12181235
#endif

0 commit comments

Comments
 (0)