From: Thomas Hellstrom <thellstrom@xxxxxxxxxx> With AMD-SEV high-bandwidth port messaging runs into trouble since the message content is encrypted using the vm-specific key, and the hypervisor is unable to read it. So use unencrypted dma-coherent bounce buffers for temporary message storage space. Allocating that memory is expensive so a future optimization might include a static unencrypted memory area for messages. Signed-off-by: Thomas Hellstrom <thellstrom@xxxxxxxxxx> Reviewed-by: Brian Paul <brianp@xxxxxxxxxx> --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 4 +-- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 +-- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 45 +++++++++++++++++------------ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 81a95651643f..fc0283659c41 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -908,13 +908,13 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) snprintf(host_log, sizeof(host_log), "vmwgfx: %s-%s", VMWGFX_REPO, VMWGFX_GIT_VERSION); - vmw_host_log(host_log); + vmw_host_log(dev->dev, host_log); memset(host_log, 0, sizeof(host_log)); snprintf(host_log, sizeof(host_log), "vmwgfx: Module Version: %d.%d.%d", VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR, VMWGFX_DRIVER_PATCHLEVEL); - vmw_host_log(host_log); + vmw_host_log(dev->dev, host_log); if (dev_priv->enable_fb) { vmw_fifo_resource_inc(dev_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index b18842f73081..a77bf72cb9ac 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1389,9 +1389,9 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, struct vmw_diff_cpy *diff); /* Host messaging -vmwgfx_msg.c: */ -int vmw_host_get_guestinfo(const char *guest_info_param, +int vmw_host_get_guestinfo(struct device *dev, const char *guest_info_param, char *buffer, size_t *length); -int vmw_host_log(const char *log); +int vmw_host_log(struct device *dev, const char *log); /* VMW logging */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c index b6c5e4c2ac3c..f439b7afa3a5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c @@ -304,8 +304,8 @@ STACK_FRAME_NON_STANDARD(vmw_send_msg); * @msg: [OUT] message received from the host * @msg_len: message length */ -static int vmw_recv_msg(struct rpc_channel *channel, void **msg, - size_t *msg_len) +static int vmw_recv_msg(struct device *dev, struct rpc_channel *channel, + void **msg, size_t *msg_len, dma_addr_t *dma_handle) { unsigned long eax, ebx, ecx, edx, si, di; char *reply; @@ -339,7 +339,8 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg, return 0; reply_len = ebx; - reply = kzalloc(reply_len + 1, GFP_KERNEL); + reply = dma_alloc_coherent(dev, reply_len + 1, dma_handle, + GFP_KERNEL); if (!reply) { DRM_ERROR("Cannot allocate memory for host message reply.\n"); return -ENOMEM; @@ -350,7 +351,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg, ebx = vmw_port_hb_in(channel, reply, reply_len, !!(HIGH_WORD(ecx) & MESSAGE_STATUS_HB)); if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) == 0) { - kfree(reply); + dma_free_coherent(dev, reply_len + 1, reply, *dma_handle); reply = NULL; if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) { /* A checkpoint occurred. Retry. */ @@ -374,7 +375,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg, eax, ebx, ecx, edx, si, di); if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { - kfree(reply); + dma_free_coherent(dev, reply_len + 1, reply, *dma_handle); reply = NULL; if ((HIGH_WORD(ecx) & MESSAGE_STATUS_CPT) != 0) { /* A checkpoint occurred. Retry. */ @@ -404,18 +405,21 @@ STACK_FRAME_NON_STANDARD(vmw_recv_msg); * Gets the value of a GuestInfo.* parameter. The value returned will be in * a string, and it is up to the caller to post-process. * + * @dev: Pointer to struct device used for coherent memory allocation * @guest_info_param: Parameter to get, e.g. GuestInfo.svga.gl3 * @buffer: if NULL, *reply_len will contain reply size. * @length: size of the reply_buf. Set to size of reply upon return * * Returns: 0 on success */ -int vmw_host_get_guestinfo(const char *guest_info_param, +int vmw_host_get_guestinfo(struct device *dev, const char *guest_info_param, char *buffer, size_t *length) { struct rpc_channel channel; char *msg, *reply = NULL; size_t reply_len = 0; + dma_addr_t req_handle, reply_handle; + int req_len = strlen("info-get ") + strlen(guest_info_param) + 1; if (!vmw_msg_enabled) return -ENODEV; @@ -423,18 +427,20 @@ int vmw_host_get_guestinfo(const char *guest_info_param, if (!guest_info_param || !length) return -EINVAL; - msg = kasprintf(GFP_KERNEL, "info-get %s", guest_info_param); + msg = dma_alloc_coherent(dev, req_len, &req_handle, GFP_KERNEL); if (!msg) { DRM_ERROR("Cannot allocate memory to get guest info \"%s\".", guest_info_param); return -ENOMEM; } + snprintf(msg, req_len, "info-get %s", guest_info_param); if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) goto out_open; if (vmw_send_msg(&channel, msg) || - vmw_recv_msg(&channel, (void *) &reply, &reply_len)) + vmw_recv_msg(dev, &channel, (void *) &reply, &reply_len, + &reply_handle)) goto out_msg; vmw_close_channel(&channel); @@ -451,19 +457,19 @@ int vmw_host_get_guestinfo(const char *guest_info_param, *length = reply_len; - kfree(reply); - kfree(msg); + dma_free_coherent(dev, reply_len + 1, reply, reply_handle); + dma_free_coherent(dev, req_len, msg, req_handle); return 0; out_msg: vmw_close_channel(&channel); - kfree(reply); + dma_free_coherent(dev, reply_len + 1, reply, reply_handle); out_open: *length = 0; - kfree(msg); - DRM_ERROR("Failed to get guest info \"%s\".", guest_info_param); + DRM_ERROR("Failed to get guest info \"%s\".", guest_info_param); + dma_free_coherent(dev, req_len, msg, req_handle); return -EINVAL; } @@ -472,16 +478,18 @@ int vmw_host_get_guestinfo(const char *guest_info_param, /** * vmw_host_log: Sends a log message to the host * + * @dev: Pointer to struct device used for coherent memory allocation * @log: NULL terminated string * * Returns: 0 on success */ -int vmw_host_log(const char *log) +int vmw_host_log(struct device *dev, const char *log) { struct rpc_channel channel; char *msg; int ret = 0; - + dma_addr_t log_handle; + int log_len = strlen("log ") + strlen(log) + 1; if (!vmw_msg_enabled) return -ENODEV; @@ -489,11 +497,12 @@ int vmw_host_log(const char *log) if (!log) return ret; - msg = kasprintf(GFP_KERNEL, "log %s", log); + msg = dma_alloc_coherent(dev, log_len, &log_handle, GFP_KERNEL); if (!msg) { DRM_ERROR("Cannot allocate memory for host log message.\n"); return -ENOMEM; } + snprintf(msg, log_len, "log %s", log); if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM)) goto out_open; @@ -502,14 +511,14 @@ int vmw_host_log(const char *log) goto out_msg; vmw_close_channel(&channel); - kfree(msg); + dma_free_coherent(dev, log_len, msg, log_handle); return 0; out_msg: vmw_close_channel(&channel); out_open: - kfree(msg); + dma_free_coherent(dev, log_len, msg, log_handle); DRM_ERROR("Failed to send host log message.\n"); return -EINVAL; -- 2.21.0 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel