drm/i915/pxp: implement function for sending tee stream command
authorVitaly Lubart <vitaly.lubart@intel.com>
Wed, 28 Sep 2022 00:41:38 +0000 (17:41 -0700)
committerDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Mon, 3 Oct 2022 18:29:14 +0000 (11:29 -0700)
Command to be sent via the stream interface are written to a local
memory page, whose address is then provided to the GSC.
The interface supports providing a full sg with multiple pages for both
input and output messages, but since for now we only aim to support short
and synchronous messages we can use a single page for both input and
output.

Note that the mei interface expects an sg of 4k pages, while our lmem pages
are 64k. If we ever need to support more than 4k we'll need to convert.
Added a TODO comment to the code to record this.

Signed-off-by: Vitaly Lubart <vitaly.lubart@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220928004145.745803-9-daniele.ceraolospurio@intel.com
drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
drivers/gpu/drm/i915/pxp/intel_pxp_tee.h
drivers/gpu/drm/i915/pxp/intel_pxp_types.h

index 2c1fc49ecec1380022ab2b21db8d43d8ee7264f8..f5912a446f2ec1c5cd6e883f66ab8feca3ce30f6 100644 (file)
@@ -8,6 +8,8 @@
 #include <drm/i915_pxp_tee_interface.h>
 #include <drm/i915_component.h>
 
+#include "gem/i915_gem_lmem.h"
+
 #include "i915_drv.h"
 #include "intel_pxp.h"
 #include "intel_pxp_session.h"
@@ -69,6 +71,47 @@ unlock:
        return ret;
 }
 
+int intel_pxp_tee_stream_message(struct intel_pxp *pxp,
+                                u8 client_id, u32 fence_id,
+                                void *msg_in, size_t msg_in_len,
+                                void *msg_out, size_t msg_out_len)
+{
+       /* TODO: for bigger objects we need to use a sg of 4k pages */
+       const size_t max_msg_size = PAGE_SIZE;
+       struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
+       struct i915_pxp_component *pxp_component = pxp->pxp_component;
+       unsigned int offset = 0;
+       struct scatterlist *sg;
+       int ret;
+
+       if (msg_in_len > max_msg_size || msg_out_len > max_msg_size)
+               return -ENOSPC;
+
+       mutex_lock(&pxp->tee_mutex);
+
+       if (unlikely(!pxp_component || !pxp_component->ops->gsc_command)) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+
+       GEM_BUG_ON(!pxp->stream_cmd.obj);
+
+       sg = i915_gem_object_get_sg_dma(pxp->stream_cmd.obj, 0, &offset);
+
+       memcpy(pxp->stream_cmd.vaddr, msg_in, msg_in_len);
+
+       ret = pxp_component->ops->gsc_command(pxp_component->tee_dev, client_id,
+                                             fence_id, sg, msg_in_len, sg);
+       if (ret < 0)
+               drm_err(&i915->drm, "Failed to send PXP TEE gsc command\n");
+       else
+               memcpy(msg_out, pxp->stream_cmd.vaddr, msg_out_len);
+
+unlock:
+       mutex_unlock(&pxp->tee_mutex);
+       return ret;
+}
+
 /**
  * i915_pxp_tee_component_bind - bind function to pass the function pointers to pxp_tee
  * @i915_kdev: pointer to i915 kernel device
@@ -126,6 +169,66 @@ static const struct component_ops i915_pxp_tee_component_ops = {
        .unbind = i915_pxp_tee_component_unbind,
 };
 
+static int alloc_streaming_command(struct intel_pxp *pxp)
+{
+       struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
+       struct drm_i915_gem_object *obj = NULL;
+       void *cmd;
+       int err;
+
+       pxp->stream_cmd.obj = NULL;
+       pxp->stream_cmd.vaddr = NULL;
+
+       if (!IS_DGFX(i915))
+               return 0;
+
+       /* allocate lmem object of one page for PXP command memory and store it */
+       obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, I915_BO_ALLOC_CONTIGUOUS);
+       if (IS_ERR(obj)) {
+               drm_err(&i915->drm, "Failed to allocate pxp streaming command!\n");
+               return PTR_ERR(obj);
+       }
+
+       err = i915_gem_object_pin_pages_unlocked(obj);
+       if (err) {
+               drm_err(&i915->drm, "Failed to pin gsc message page!\n");
+               goto out_put;
+       }
+
+       /* map the lmem into the virtual memory pointer */
+       cmd = i915_gem_object_pin_map_unlocked(obj, i915_coherent_map_type(i915, obj, true));
+       if (IS_ERR(cmd)) {
+               drm_err(&i915->drm, "Failed to map gsc message page!\n");
+               err = PTR_ERR(cmd);
+               goto out_unpin;
+       }
+
+       memset(cmd, 0, obj->base.size);
+
+       pxp->stream_cmd.obj = obj;
+       pxp->stream_cmd.vaddr = cmd;
+
+       return 0;
+
+out_unpin:
+       i915_gem_object_unpin_pages(obj);
+out_put:
+       i915_gem_object_put(obj);
+       return err;
+}
+
+static void free_streaming_command(struct intel_pxp *pxp)
+{
+       struct drm_i915_gem_object *obj = fetch_and_zero(&pxp->stream_cmd.obj);
+
+       if (!obj)
+               return;
+
+       i915_gem_object_unpin_map(obj);
+       i915_gem_object_unpin_pages(obj);
+       i915_gem_object_put(obj);
+}
+
 int intel_pxp_tee_component_init(struct intel_pxp *pxp)
 {
        int ret;
@@ -134,16 +237,24 @@ int intel_pxp_tee_component_init(struct intel_pxp *pxp)
 
        mutex_init(&pxp->tee_mutex);
 
+       ret = alloc_streaming_command(pxp);
+       if (ret)
+               return ret;
+
        ret = component_add_typed(i915->drm.dev, &i915_pxp_tee_component_ops,
                                  I915_COMPONENT_PXP);
        if (ret < 0) {
                drm_err(&i915->drm, "Failed to add PXP component (%d)\n", ret);
-               return ret;
+               goto out_free;
        }
 
        pxp->pxp_component_added = true;
 
        return 0;
+
+out_free:
+       free_streaming_command(pxp);
+       return ret;
 }
 
 void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
@@ -155,6 +266,8 @@ void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
 
        component_del(i915->drm.dev, &i915_pxp_tee_component_ops);
        pxp->pxp_component_added = false;
+
+       free_streaming_command(pxp);
 }
 
 int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
index c136053ce3406535761e4e9448dc6eef292e1fba..aeb3dfe7ce960ff1c659d1bafd698db669c27d85 100644 (file)
@@ -14,4 +14,9 @@ void intel_pxp_tee_component_fini(struct intel_pxp *pxp);
 int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
                                         int arb_session_id);
 
+int intel_pxp_tee_stream_message(struct intel_pxp *pxp,
+                                u8 client_id, u32 fence_id,
+                                void *msg_in, size_t msg_in_len,
+                                void *msg_out, size_t msg_out_len);
+
 #endif /* __INTEL_PXP_TEE_H__ */
index 7ce5f37ee12e12e8eff87338dca05b02bd837dbe..f74b1e11a505f8d1416418f94d82349bd38c0db0 100644 (file)
@@ -53,6 +53,12 @@ struct intel_pxp {
        /** @tee_mutex: protects the tee channel binding and messaging. */
        struct mutex tee_mutex;
 
+       /** @stream_cmd: LMEM obj used to send stream PXP commands to the GSC */
+       struct {
+               struct drm_i915_gem_object *obj; /* contains PXP command memory */
+               void *vaddr; /* virtual memory for PXP command */
+       } stream_cmd;
+
        /**
         * @hw_state_invalidated: if the HW perceives an attack on the integrity
         * of the encryption it will invalidate the keys and expect SW to