From: Thomas Hellstrom <thellst...@vmware.com>

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 <thellst...@vmware.com>
Reviewed-by: Brian Paul <bri...@vmware.com>
---
 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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to