drm/i915/pxp: move mei-pxp and mei-gsc resources to be backend-private Signed-off-by: Alan Previn <alan.previn.teres.alexis@xxxxxxxxx> --- drivers/gpu/drm/i915/pxp/intel_pxp.c | 14 +- drivers/gpu/drm/i915/pxp/intel_pxp_huc.c | 4 +- drivers/gpu/drm/i915/pxp/intel_pxp_pm.c | 3 +- drivers/gpu/drm/i915/pxp/intel_pxp_tee.c | 8 ++ drivers/gpu/drm/i915/pxp/intel_pxp_tee.h | 2 + drivers/gpu/drm/i915/pxp/intel_pxp_tee_mei.c | 143 +++++++++++++------ drivers/gpu/drm/i915/pxp/intel_pxp_types.h | 38 ++--- 7 files changed, 132 insertions(+), 80 deletions(-) diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c index 33f86bb05148..49105bb1d694 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c @@ -230,18 +230,6 @@ static void pxp_queue_termination(struct intel_pxp *pxp) spin_unlock_irq(gt->irq_lock); } -static bool pxp_component_bound(struct intel_pxp *pxp) -{ - bool bound = false; - - mutex_lock(&pxp->tee_mutex); - if (pxp->pxp_component) - bound = true; - mutex_unlock(&pxp->tee_mutex); - - return bound; -} - /* * the arb session is restarted from the irq work when we receive the * termination completion interrupt @@ -260,7 +248,7 @@ int intel_pxp_start(struct drm_i915_private *i915) if (!intel_pxp_is_enabled_on_gt(pxp)) return -ENODEV; - if (wait_for(pxp_component_bound(pxp), 250)) + if (wait_for(intel_pxp_teelink_is_ready(pxp), 250)) return -ENXIO; mutex_lock(&pxp->arb_mutex); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c index 043344dbf566..69ee261a1f7e 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c @@ -11,10 +11,10 @@ #include "gt/intel_gt.h" #include "intel_pxp.h" +#include "intel_pxp_cmd_interface_43.h" #include "intel_pxp_huc.h" #include "intel_pxp_tee.h" #include "intel_pxp_types.h" -#include "intel_pxp_cmd_interface_43.h" int intel_pxp_huc_load_and_auth(struct intel_pxp *pxp) { @@ -25,7 +25,7 @@ int intel_pxp_huc_load_and_auth(struct intel_pxp *pxp) dma_addr_t huc_phys_addr; int err; - if (!pxp->pxp_component) + if (!intel_pxp_teelink_is_ready(pxp)) return -ENODEV; huc_phys_addr = i915_gem_object_get_dma_address(huc->fw.obj, 0); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c b/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c index 19ac8828cbde..dc907a338fdb 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_pm.c @@ -7,6 +7,7 @@ #include "intel_pxp_irq.h" #include "intel_pxp_pm.h" #include "intel_pxp_session.h" +#include "intel_pxp_tee.h" #include "i915_drv.h" void intel_pxp_suspend_prepare(struct intel_pxp *pxp) @@ -42,7 +43,7 @@ void intel_pxp_resume(struct intel_pxp *pxp) * re-bound after we come out, so in that scenario we can defer the * hw init to the bind call. */ - if (!pxp->pxp_component) + if (!intel_pxp_teelink_is_ready(pxp)) return; intel_pxp_init_hw(pxp); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c index 034e2eee5075..1171f339643c 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c @@ -43,6 +43,14 @@ int intel_pxp_teelink_send_message(struct intel_pxp *pxp, msg_out_max_size); } +bool intel_pxp_teelink_is_ready(struct intel_pxp *pxp) +{ + if (pxp->tee_link.is_ready) + return pxp->tee_link.is_ready(pxp); + + return false; +} + static bool gt_supports_teelink_via_mei(struct intel_gt *gt) { return (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && !HAS_ENGINE(gt, GSC0)); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h index 6c09fa11bcca..46852f164e36 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h @@ -13,6 +13,8 @@ struct intel_pxp; int intel_pxp_teelink_init(struct intel_pxp *pxp); void intel_pxp_teelink_fini(struct intel_pxp *pxp); +bool intel_pxp_teelink_is_ready(struct intel_pxp *pxp); + int intel_pxp_teelink_create_session(struct intel_pxp *pxp, int arb_session_id); diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee_mei.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee_mei.c index cd54219ced06..a81e8859335e 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee_mei.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee_mei.c @@ -17,6 +17,34 @@ #include "intel_pxp_session.h" #include "intel_pxp_tee_mei.h" +struct mei_teelink_priv { + /** + * @pxp_component: i915_pxp_component struct of the bound mei_pxp + * module. Only set and cleared inside component bind/unbind functions, + * which are protected by &tee_mutex. + */ + struct i915_pxp_component *pxp_component; + /** + * @pxp_component_added: track if the pxp component has been added. + * Set and cleared in tee init and fini functions respectively. + */ + bool pxp_component_added; + + /** @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; +}; + +static inline struct mei_teelink_priv *pxp_to_mei_priv(struct intel_pxp *pxp) +{ + return (struct mei_teelink_priv *)pxp->tee_link.priv; +} + static inline struct intel_pxp *i915_dev_to_pxp(struct device *i915_kdev) { struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); @@ -34,10 +62,11 @@ static int mei_tee_io_message(struct intel_pxp *pxp, size_t *msg_out_size) { struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915; - struct i915_pxp_component *pxp_component = pxp->pxp_component; + struct mei_teelink_priv *mei = pxp_to_mei_priv(pxp); + struct i915_pxp_component *pxp_component = mei->pxp_component; int ret = 0; - mutex_lock(&pxp->tee_mutex); + mutex_lock(&mei->tee_mutex); /* * The binding of the component is asynchronous from i915 probe, so we @@ -72,7 +101,7 @@ static int mei_tee_io_message(struct intel_pxp *pxp, ret = 0; unlock: - mutex_unlock(&pxp->tee_mutex); + mutex_unlock(&mei->tee_mutex); return ret; } @@ -84,7 +113,8 @@ static int mei_tee_gsc_stream_message(struct intel_pxp *pxp, /* 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; + struct mei_teelink_priv *mei = pxp_to_mei_priv(pxp); + struct i915_pxp_component *pxp_component = mei->pxp_component; unsigned int offset = 0; struct scatterlist *sg; int ret; @@ -92,28 +122,28 @@ static int mei_tee_gsc_stream_message(struct intel_pxp *pxp, if (msg_in_size > max_msg_size || msg_out_max_size > max_msg_size) return -ENOSPC; - mutex_lock(&pxp->tee_mutex); + mutex_lock(&mei->tee_mutex); if (unlikely(!pxp_component || !pxp_component->ops->gsc_command)) { ret = -ENODEV; goto unlock; } - GEM_BUG_ON(!pxp->stream_cmd.obj); + GEM_BUG_ON(!mei->stream_cmd.obj); - sg = i915_gem_object_get_sg_dma(pxp->stream_cmd.obj, 0, &offset); + sg = i915_gem_object_get_sg_dma(mei->stream_cmd.obj, 0, &offset); - memcpy(pxp->stream_cmd.vaddr, msg_in, msg_in_size); + memcpy(mei->stream_cmd.vaddr, msg_in, msg_in_size); ret = pxp_component->ops->gsc_command(pxp_component->tee_dev, 0, 0, sg, msg_in_size, 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_max_size); + memcpy(msg_out, mei->stream_cmd.vaddr, msg_out_max_size); unlock: - mutex_unlock(&pxp->tee_mutex); + mutex_unlock(&mei->tee_mutex); return ret; } @@ -127,11 +157,12 @@ static int mei_tee_gsc_stream_message(struct intel_pxp *pxp, * * Return: return 0 if successful. */ -static int i915_pxp_tee_component_bind(struct device *i915_kdev, +static int i915_mei_tee_component_bind(struct device *i915_kdev, struct device *tee_kdev, void *data) { struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev); + struct mei_teelink_priv *mei = pxp_to_mei_priv(pxp); struct intel_uc *uc; intel_wakeref_t wakeref; int ret = 0; @@ -142,10 +173,10 @@ static int i915_pxp_tee_component_bind(struct device *i915_kdev, } uc = &pxp_to_gt(pxp)->uc; - mutex_lock(&pxp->tee_mutex); - pxp->pxp_component = data; - pxp->pxp_component->tee_dev = tee_kdev; - mutex_unlock(&pxp->tee_mutex); + mutex_lock(&mei->tee_mutex); + mei->pxp_component = data; + mei->pxp_component->tee_dev = tee_kdev; + mutex_unlock(&mei->tee_mutex); if (intel_uc_uses_huc(uc) && intel_huc_is_loaded_by_gsc(&uc->huc)) { with_intel_runtime_pm(&i915->runtime_pm, wakeref) { @@ -170,36 +201,38 @@ static int i915_pxp_tee_component_bind(struct device *i915_kdev, return ret; } -static void i915_pxp_tee_component_unbind(struct device *i915_kdev, +static void i915_mei_tee_component_unbind(struct device *i915_kdev, struct device *tee_kdev, void *data) { struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev); + struct mei_teelink_priv *mei = pxp_to_mei_priv(pxp); intel_wakeref_t wakeref; if (intel_pxp_is_enabled_on_gt(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; - mutex_unlock(&pxp->tee_mutex); + mutex_lock(&mei->tee_mutex); + mei->pxp_component = NULL; + mutex_unlock(&mei->tee_mutex); } -static const struct component_ops i915_pxp_tee_component_ops = { - .bind = i915_pxp_tee_component_bind, - .unbind = i915_pxp_tee_component_unbind, +static const struct component_ops i915_mei_tee_component_ops = { + .bind = i915_mei_tee_component_bind, + .unbind = i915_mei_tee_component_unbind, }; -static int alloc_streaming_command(struct intel_pxp *pxp) +static int mei_tee_alloc_streaming_command(struct intel_pxp *pxp) { struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915; + struct mei_teelink_priv *mei = pxp_to_mei_priv(pxp); struct drm_i915_gem_object *obj = NULL; void *cmd; int err; - pxp->stream_cmd.obj = NULL; - pxp->stream_cmd.vaddr = NULL; + mei->stream_cmd.obj = NULL; + mei->stream_cmd.vaddr = NULL; if (!IS_DGFX(i915)) return 0; @@ -227,8 +260,8 @@ static int alloc_streaming_command(struct intel_pxp *pxp) memset(cmd, 0, obj->base.size); - pxp->stream_cmd.obj = obj; - pxp->stream_cmd.vaddr = cmd; + mei->stream_cmd.obj = obj; + mei->stream_cmd.vaddr = cmd; return 0; @@ -239,9 +272,9 @@ static int alloc_streaming_command(struct intel_pxp *pxp) return err; } -static void free_streaming_command(struct intel_pxp *pxp) +static void mei_tee_free_streaming_command(struct intel_pxp *pxp) { - struct drm_i915_gem_object *obj = fetch_and_zero(&pxp->stream_cmd.obj); + struct drm_i915_gem_object *obj = fetch_and_zero(&pxp_to_mei_priv(pxp)->stream_cmd.obj); if (!obj) return; @@ -251,45 +284,74 @@ static void free_streaming_command(struct intel_pxp *pxp) i915_gem_object_put(obj); } +static bool mei_tee_is_component_bound(struct intel_pxp *pxp) +{ + struct mei_teelink_priv *mei = pxp_to_mei_priv(pxp); + bool bound = false; + + mutex_lock(&mei->tee_mutex); + if (mei->pxp_component) + bound = true; + mutex_unlock(&mei->tee_mutex); + + return bound; +} + static int mei_tee_component_init(struct intel_pxp *pxp) { int ret; struct intel_gt *gt = pxp_to_gt(pxp); struct drm_i915_private *i915 = gt->i915; + struct mei_teelink_priv *mei; + + mei = kzalloc(sizeof(*mei), GFP_KERNEL); + if (!mei) + return -ENOMEM; - mutex_init(&pxp->tee_mutex); + pxp->tee_link.priv = mei; - ret = alloc_streaming_command(pxp); + mutex_init(&mei->tee_mutex); + + ret = mei_tee_alloc_streaming_command(pxp); if (ret) - return ret; + goto out_free; - ret = component_add_typed(i915->drm.dev, &i915_pxp_tee_component_ops, + ret = component_add_typed(i915->drm.dev, &i915_mei_tee_component_ops, I915_COMPONENT_PXP); if (ret < 0) { drm_err(&i915->drm, "Failed to add PXP component (%d)\n", ret); - goto out_free; + goto out_free_stream; } - pxp->pxp_component_added = true; + mei->pxp_component_added = true; return 0; +out_free_stream: + mei_tee_free_streaming_command(pxp); out_free: - free_streaming_command(pxp); + kfree(mei); + pxp->tee_link.priv = NULL; return ret; } static void mei_tee_component_fini(struct intel_pxp *pxp) { struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915; + struct mei_teelink_priv *mei = pxp_to_mei_priv(pxp); + + if (!mei) + return; - if (!pxp->pxp_component_added) + if (!mei->pxp_component_added) return; - component_del(i915->drm.dev, &i915_pxp_tee_component_ops); - pxp->pxp_component_added = false; + component_del(i915->drm.dev, &i915_mei_tee_component_ops); + mei->pxp_component_added = false; - free_streaming_command(pxp); + mei_tee_free_streaming_command(pxp); + kfree(mei); + pxp->tee_link.priv = NULL; } static int mei_tee_create_session(struct intel_pxp *pxp, @@ -326,6 +388,7 @@ void intel_pxp_init_mei_tee_hooks(struct intel_pxp *pxp) pxp->tee_link.init = mei_tee_component_init; pxp->tee_link.fini = mei_tee_component_fini; + pxp->tee_link.is_ready = mei_tee_is_component_bound; pxp->tee_link.create_session = mei_tee_create_session; if (IS_DG2(i915)) pxp->tee_link.send_message = mei_tee_gsc_stream_message; diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h index 6de79a46ceed..f1bddf8500d4 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h @@ -18,17 +18,6 @@ struct i915_pxp_component; * struct intel_pxp - pxp state */ struct intel_pxp { - /** - * @pxp_component: i915_pxp_component struct of the bound mei_pxp - * module. Only set and cleared inside component bind/unbind functions, - * which are protected by &tee_mutex. - */ - struct i915_pxp_component *pxp_component; - /** - * @pxp_component_added: track if the pxp component has been added. - * Set and cleared in tee init and fini functions respectively. - */ - bool pxp_component_added; /** @ce: kernel-owned context used for PXP operations */ struct intel_context *ce; @@ -50,15 +39,6 @@ struct intel_pxp { */ u32 key_instance; - /** @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 @@ -88,16 +68,26 @@ struct intel_pxp { * These hooks will point to device specific implementations. */ struct { - /* Called to initialize the backend transport resources.*/ + /** @priv: Pointer exclusively for backend layer to store private context.*/ + void *priv; + + /** @init: Func-ptr called to initialize the backend transport resources.*/ int (*init)(struct intel_pxp *pxp); - /* Called to free the backend transport resources.*/ + /** @fini: Func-ptr called to free the backend transport resources.*/ void (*fini)(struct intel_pxp *pxp); - /* Called to create a pxp session.*/ + /** + * @is_ready: Func-ptr called to query if the backend transport is available + * for use. Depending on the backend, some, such as mei, have asyncronous workers + * or callbacks that setup the backend tee link to the security firmware. + **/ + bool (*is_ready)(struct intel_pxp *pxp); + + /** @init: Func-ptr called to create a pxp session.*/ int (*create_session)(struct intel_pxp *pxp, int session_id); - /* Called to send message packets to pxp firmware.*/ + /** @init: Func-ptr called to send message packets to pxp firmware.*/ int (*send_message)(struct intel_pxp *pxp, void *msg_in, size_t msg_in_len, void *msg_out, size_t msg_out_max_len, -- 2.34.1