Merge tag 'drm-intel-gt-next-2022-11-03' of git://anongit.freedesktop.org/drm/drm...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / pxp / intel_pxp_tee.c
index a90905039216c76abe0b21289eed7a55537cda12..052fd2f9a583291b68c7d69fb8e5b41f794e29ca 100644 (file)
@@ -8,11 +8,14 @@
 #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"
 #include "intel_pxp_tee.h"
 #include "intel_pxp_tee_interface.h"
+#include "intel_pxp_huc.h"
 
 static inline struct intel_pxp *i915_dev_to_pxp(struct device *i915_kdev)
 {
@@ -69,6 +72,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
@@ -84,24 +128,36 @@ static int i915_pxp_tee_component_bind(struct device *i915_kdev,
 {
        struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
        struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
+       struct intel_uc *uc = &pxp_to_gt(pxp)->uc;
        intel_wakeref_t wakeref;
+       int ret = 0;
 
        mutex_lock(&pxp->tee_mutex);
        pxp->pxp_component = data;
        pxp->pxp_component->tee_dev = tee_kdev;
        mutex_unlock(&pxp->tee_mutex);
 
+       if (intel_uc_uses_huc(uc) && intel_huc_is_loaded_by_gsc(&uc->huc)) {
+               with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+                       /* load huc via pxp */
+                       ret = intel_huc_fw_load_and_auth_via_gsc(&uc->huc);
+                       if (ret < 0)
+                               drm_err(&i915->drm, "failed to load huc via gsc %d\n", ret);
+               }
+       }
+
        /* if we are suspended, the HW will be re-initialized on resume */
        wakeref = intel_runtime_pm_get_if_in_use(&i915->runtime_pm);
        if (!wakeref)
                return 0;
 
        /* the component is required to fully start the PXP HW */
-       intel_pxp_init_hw(pxp);
+       if (intel_pxp_is_enabled(pxp))
+               intel_pxp_init_hw(pxp);
 
        intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 
-       return 0;
+       return ret;
 }
 
 static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
@@ -111,8 +167,9 @@ static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
        struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
        intel_wakeref_t wakeref;
 
-       with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
-               intel_pxp_fini_hw(pxp);
+       if (intel_pxp_is_enabled(pxp))
+               with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
+                       intel_pxp_fini_hw(pxp);
 
        mutex_lock(&pxp->tee_mutex);
        pxp->pxp_component = NULL;
@@ -124,22 +181,92 @@ 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;
        struct intel_gt *gt = pxp_to_gt(pxp);
        struct drm_i915_private *i915 = gt->i915;
 
+       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)
@@ -151,6 +278,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,