@@ -10,7 +10,11 @@
#include "intel_pxp_cmd_interface_cmn.h"
/* PXP-Cmd-Op definitions */
-#define PXP43_CMDID_START_HUC_AUTH 0x0000003A
+#define PXP43_CMDID_START_HUC_AUTH 0x0000003A
+
+/* PXP-Packet sizes for MTL's GSCCS-HECI instruction */
+#define PXP43_MAX_HECI_IN_SIZE (SZ_32K)
+#define PXP43_MAX_HECI_OUT_SIZE (SZ_32K)
/* PXP-Input-Packet: HUC-Authentication */
struct pxp43_start_huc_auth_in {
@@ -3,9 +3,41 @@
* Copyright(c) 2023 Intel Corporation.
*/
+#include "gem/i915_gem_internal.h"
+
+#include "gt/intel_context.h"
+
#include "i915_drv.h"
-#include "intel_pxp_types.h"
+#include "intel_pxp_cmd_interface_43.h"
#include "intel_pxp_gsccs.h"
+#include "intel_pxp_types.h"
+
+struct gsccs_session_resources {
+ struct mutex cmd_mutex; /* Protects submission for arb session */
+ u64 host_session_handle; /* used by firmware to link commands to sessions */
+
+ struct intel_context *ce; /* context for gsc command submission */
+ struct i915_ppgtt *ppgtt; /* ppgtt for gsc command submission */
+
+ struct drm_i915_gem_object *pkt_obj; /* PXP HECI message packet buffer */
+ struct i915_vma *pkt_vma; /* PXP HECI message packet vma */
+ void *pkt_vaddr; /* PXP HECI message packet virt memory pointer */
+
+ /* Buffer info for GSC engine batch buffer: */
+ struct drm_i915_gem_object *bb_obj; /* batch buffer object */
+ struct i915_vma *bb_vma; /* batch buffer vma */
+ void *bb_vaddr; /* batch buffer virtual memory pointer */
+};
+
+struct gsccs_teelink_priv {
+ /** @arb_exec_res: resources for arb-session GSC-CS PXP command submission */
+ struct gsccs_session_resources arb_exec_res;
+};
+
+static inline struct gsccs_teelink_priv *pxp_to_gsccs_priv(struct intel_pxp *pxp)
+{
+ return (struct gsccs_teelink_priv *)pxp->gsccs_priv;
+}
int intel_pxp_gsccs_create_session(struct intel_pxp *pxp,
int arb_session_id)
@@ -13,11 +45,193 @@ int intel_pxp_gsccs_create_session(struct intel_pxp *pxp,
return -ENODEV;
}
+static void
+gsccs_destroy_buffer(struct drm_i915_private *i915, struct i915_vma *vma,
+ struct drm_i915_gem_object *obj)
+{
+ int err;
+
+ i915_vma_unpin(vma);
+ err = i915_vma_unbind(vma);
+ if (err)
+ drm_dbg(&i915->drm, "Unexpected failure when vma-unbinding = %d\n", err);
+
+ i915_gem_object_unpin_map(obj);
+ i915_gem_object_unpin_pages(obj);
+ i915_gem_object_put(obj);
+}
+
+static int
+gsccs_create_buffer(struct drm_i915_private *i915, const char *bufname,
+ size_t size, struct i915_ppgtt *ppgtt,
+ struct drm_i915_gem_object **obj,
+ struct i915_vma **vma, void **map)
+{
+ int err = 0;
+
+ *obj = i915_gem_object_create_internal(i915, size);
+ if (IS_ERR(*obj)) {
+ drm_err(&i915->drm, "Failed to allocate gsccs backend %s.\n", bufname);
+ err = PTR_ERR(*obj);
+ goto out_none;
+ }
+
+ *vma = i915_vma_instance(*obj, &ppgtt->vm, NULL);
+ if (IS_ERR(*vma)) {
+ drm_err(&i915->drm, "Failed to vma-instance gsccs backend %s.\n", bufname);
+ err = PTR_ERR(*vma);
+ goto out_put;
+ }
+
+ err = i915_gem_object_pin_pages_unlocked(*obj);
+ if (err) {
+ drm_err(&i915->drm, "Failed to pin gsccs backend %s.\n", bufname);
+ goto out_put;
+ }
+
+ /* map to the virtual memory pointer */
+ *map = i915_gem_object_pin_map_unlocked(*obj, i915_coherent_map_type(i915, *obj, true));
+ if (IS_ERR(*map)) {
+ drm_err(&i915->drm, "Failed to map gsccs backend %s.\n", bufname);
+ err = PTR_ERR(*map);
+ goto out_unpin;
+ }
+
+ /* all PXP sessions commands are treated as non-priveleged */
+ err = i915_vma_pin(*vma, 0, 0, PIN_USER);
+ if (err) {
+ drm_err(&i915->drm, "Failed to vma-pin gsccs backend %s.\n", bufname);
+ goto out_unmap;
+ }
+
+ return 0;
+
+out_unmap:
+ i915_gem_object_unpin_map(*obj);
+out_unpin:
+ i915_gem_object_unpin_pages(*obj);
+out_put:
+ i915_gem_object_put(*obj);
+out_none:
+ *obj = NULL;
+ *vma = NULL;
+ *map = NULL;
+
+ return err;
+}
+
+static void
+gsccs_destroy_execution_resource(struct intel_pxp *pxp,
+ struct gsccs_session_resources *strm_res)
+{
+ if (strm_res->ce)
+ intel_context_put(strm_res->ce);
+ if (strm_res->bb_obj)
+ gsccs_destroy_buffer(pxp->ctrl_gt->i915, strm_res->bb_vma, strm_res->bb_obj);
+ if (strm_res->pkt_obj)
+ gsccs_destroy_buffer(pxp->ctrl_gt->i915, strm_res->pkt_vma, strm_res->pkt_obj);
+ if (strm_res->ppgtt)
+ i915_vm_put(&strm_res->ppgtt->vm);
+
+ memset(strm_res, 0, sizeof(*strm_res));
+}
+
+static int
+gsccs_allocate_execution_resource(struct intel_pxp *pxp,
+ struct gsccs_session_resources *strm_res)
+{
+ struct intel_gt *gt = pxp->ctrl_gt;
+ struct intel_engine_cs *engine = gt->engine[GSC0];
+ struct i915_ppgtt *ppgtt;
+ struct intel_context *ce;
+ int err = 0;
+
+ /*
+ * First, ensure the GSC engine is present.
+ * NOTE: Backend should would only be called with the correct gt.
+ */
+ if (!engine)
+ return -ENODEV;
+
+ mutex_init(&strm_res->cmd_mutex);
+
+ ppgtt = i915_ppgtt_create(gt, 0);
+ if (IS_ERR(ppgtt))
+ return PTR_ERR(ppgtt);
+
+ strm_res->ppgtt = ppgtt;
+
+ /*
+ * Now, allocate, pin and map two objects, one for the heci message packet
+ * and another for the batch buffer we submit into GSC engine (that includes the packet).
+ * NOTE: GSC-CS backend is currently only supported on MTL, so we allocate shmem.
+ */
+ err = gsccs_create_buffer(pxp->ctrl_gt->i915, "Heci Packet",
+ PXP43_MAX_HECI_IN_SIZE + PXP43_MAX_HECI_OUT_SIZE,
+ strm_res->ppgtt,
+ &strm_res->pkt_obj, &strm_res->pkt_vma,
+ &strm_res->pkt_vaddr);
+ if (err) {
+ gsccs_destroy_execution_resource(pxp, strm_res);
+ return err;
+ }
+
+ err = gsccs_create_buffer(pxp->ctrl_gt->i915, "Batch Buffer",
+ PAGE_SIZE, strm_res->ppgtt,
+ &strm_res->bb_obj, &strm_res->bb_vma,
+ &strm_res->bb_vaddr);
+ if (err) {
+ gsccs_destroy_execution_resource(pxp, strm_res);
+ return err;
+ }
+ /*
+ * TODO: Consider optimization of pre-populating batch buffer
+ * with the send-HECI instruction now at init and reuse through its life.
+ */
+
+ /* Finally, create an intel_context to be used during the submission */
+ ce = intel_context_create(engine);
+ if (IS_ERR(ce)) {
+ drm_err(>->i915->drm, "Failed creating gsccs backend ctx\n");
+ gsccs_destroy_execution_resource(pxp, strm_res);
+ return PTR_ERR(ce);
+ }
+ i915_vm_put(ce->vm);
+ ce->vm = i915_vm_get(&ppgtt->vm);
+
+ strm_res->ce = ce;
+
+ return 0;
+}
+
void intel_pxp_gsccs_fini(struct intel_pxp *pxp)
{
+ struct gsccs_teelink_priv *gsccs = pxp_to_gsccs_priv(pxp);
+
+ if (!gsccs)
+ return;
+
+ gsccs_destroy_execution_resource(pxp, &gsccs->arb_exec_res);
+ kfree(gsccs);
+ pxp->gsccs_priv = NULL;
}
int intel_pxp_gsccs_init(struct intel_pxp *pxp)
{
+ struct gsccs_teelink_priv *gsccs;
+ int ret;
+
+ gsccs = kzalloc(sizeof(*gsccs), GFP_KERNEL);
+ if (!gsccs)
+ return -ENOMEM;
+
+ ret = gsccs_allocate_execution_resource(pxp, &gsccs->arb_exec_res);
+ if (ret) {
+ kfree(gsccs);
+ return ret;
+ }
+
+ pxp->gsccs_priv = gsccs;
+
return 0;
}
@@ -32,6 +32,11 @@ struct intel_pxp {
*/
bool uses_gsccs;
+ /**
+ * @gsccs_priv: GSC-CS based tee-link private context.
+ */
+ void *gsccs_priv;
+
/**
* @pxp_component: i915_pxp_component struct of the bound mei_pxp
* module. Only set and cleared inside component bind/unbind functions,
For MTL, PXP transport back-end uses the GSC engine to submit HECI packets for PXP arb session management. The command submission that uses non-priveleged mode requires us to allocate (or free) a set of execution submission resources (buffer-object, batch-buffer and context). Thus, do this one time allocation of resources in GSC-CS init and clean them up in fini. Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com> --- .../drm/i915/pxp/intel_pxp_cmd_interface_43.h | 6 +- drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.c | 216 +++++++++++++++++- drivers/gpu/drm/i915/pxp/intel_pxp_types.h | 5 + 3 files changed, 225 insertions(+), 2 deletions(-)