Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright(c) 2020 Intel Corporation.
0004  */
0005 #include <linux/workqueue.h>
0006 #include "intel_pxp.h"
0007 #include "intel_pxp_irq.h"
0008 #include "intel_pxp_session.h"
0009 #include "intel_pxp_tee.h"
0010 #include "gem/i915_gem_context.h"
0011 #include "gt/intel_context.h"
0012 #include "i915_drv.h"
0013 
0014 /**
0015  * DOC: PXP
0016  *
0017  * PXP (Protected Xe Path) is a feature available in Gen12 and newer platforms.
0018  * It allows execution and flip to display of protected (i.e. encrypted)
0019  * objects. The SW support is enabled via the CONFIG_DRM_I915_PXP kconfig.
0020  *
0021  * Objects can opt-in to PXP encryption at creation time via the
0022  * I915_GEM_CREATE_EXT_PROTECTED_CONTENT create_ext flag. For objects to be
0023  * correctly protected they must be used in conjunction with a context created
0024  * with the I915_CONTEXT_PARAM_PROTECTED_CONTENT flag. See the documentation
0025  * of those two uapi flags for details and restrictions.
0026  *
0027  * Protected objects are tied to a pxp session; currently we only support one
0028  * session, which i915 manages and whose index is available in the uapi
0029  * (I915_PROTECTED_CONTENT_DEFAULT_SESSION) for use in instructions targeting
0030  * protected objects.
0031  * The session is invalidated by the HW when certain events occur (e.g.
0032  * suspend/resume). When this happens, all the objects that were used with the
0033  * session are marked as invalid and all contexts marked as using protected
0034  * content are banned. Any further attempt at using them in an execbuf call is
0035  * rejected, while flips are converted to black frames.
0036  *
0037  * Some of the PXP setup operations are performed by the Management Engine,
0038  * which is handled by the mei driver; communication between i915 and mei is
0039  * performed via the mei_pxp component module.
0040  */
0041 
0042 struct intel_gt *pxp_to_gt(const struct intel_pxp *pxp)
0043 {
0044     return container_of(pxp, struct intel_gt, pxp);
0045 }
0046 
0047 bool intel_pxp_is_enabled(const struct intel_pxp *pxp)
0048 {
0049     return pxp->ce;
0050 }
0051 
0052 bool intel_pxp_is_active(const struct intel_pxp *pxp)
0053 {
0054     return pxp->arb_is_valid;
0055 }
0056 
0057 /* KCR register definitions */
0058 #define KCR_INIT _MMIO(0x320f0)
0059 /* Setting KCR Init bit is required after system boot */
0060 #define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14)
0061 
0062 static void kcr_pxp_enable(struct intel_gt *gt)
0063 {
0064     intel_uncore_write(gt->uncore, KCR_INIT,
0065                _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
0066 }
0067 
0068 static void kcr_pxp_disable(struct intel_gt *gt)
0069 {
0070     intel_uncore_write(gt->uncore, KCR_INIT,
0071                _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
0072 }
0073 
0074 static int create_vcs_context(struct intel_pxp *pxp)
0075 {
0076     static struct lock_class_key pxp_lock;
0077     struct intel_gt *gt = pxp_to_gt(pxp);
0078     struct intel_engine_cs *engine;
0079     struct intel_context *ce;
0080     int i;
0081 
0082     /*
0083      * Find the first VCS engine present. We're guaranteed there is one
0084      * if we're in this function due to the check in has_pxp
0085      */
0086     for (i = 0, engine = NULL; !engine; i++)
0087         engine = gt->engine_class[VIDEO_DECODE_CLASS][i];
0088 
0089     GEM_BUG_ON(!engine || engine->class != VIDEO_DECODE_CLASS);
0090 
0091     ce = intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_4K,
0092                         I915_GEM_HWS_PXP_ADDR,
0093                         &pxp_lock, "pxp_context");
0094     if (IS_ERR(ce)) {
0095         drm_err(&gt->i915->drm, "failed to create VCS ctx for PXP\n");
0096         return PTR_ERR(ce);
0097     }
0098 
0099     pxp->ce = ce;
0100 
0101     return 0;
0102 }
0103 
0104 static void destroy_vcs_context(struct intel_pxp *pxp)
0105 {
0106     intel_engine_destroy_pinned_context(fetch_and_zero(&pxp->ce));
0107 }
0108 
0109 void intel_pxp_init(struct intel_pxp *pxp)
0110 {
0111     struct intel_gt *gt = pxp_to_gt(pxp);
0112     int ret;
0113 
0114     if (!HAS_PXP(gt->i915))
0115         return;
0116 
0117     mutex_init(&pxp->tee_mutex);
0118 
0119     /*
0120      * we'll use the completion to check if there is a termination pending,
0121      * so we start it as completed and we reinit it when a termination
0122      * is triggered.
0123      */
0124     init_completion(&pxp->termination);
0125     complete_all(&pxp->termination);
0126 
0127     mutex_init(&pxp->arb_mutex);
0128     INIT_WORK(&pxp->session_work, intel_pxp_session_work);
0129 
0130     ret = create_vcs_context(pxp);
0131     if (ret)
0132         return;
0133 
0134     ret = intel_pxp_tee_component_init(pxp);
0135     if (ret)
0136         goto out_context;
0137 
0138     drm_info(&gt->i915->drm, "Protected Xe Path (PXP) protected content support initialized\n");
0139 
0140     return;
0141 
0142 out_context:
0143     destroy_vcs_context(pxp);
0144 }
0145 
0146 void intel_pxp_fini(struct intel_pxp *pxp)
0147 {
0148     if (!intel_pxp_is_enabled(pxp))
0149         return;
0150 
0151     pxp->arb_is_valid = false;
0152 
0153     intel_pxp_tee_component_fini(pxp);
0154 
0155     destroy_vcs_context(pxp);
0156 }
0157 
0158 void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp)
0159 {
0160     pxp->arb_is_valid = false;
0161     reinit_completion(&pxp->termination);
0162 }
0163 
0164 static void pxp_queue_termination(struct intel_pxp *pxp)
0165 {
0166     struct intel_gt *gt = pxp_to_gt(pxp);
0167 
0168     /*
0169      * We want to get the same effect as if we received a termination
0170      * interrupt, so just pretend that we did.
0171      */
0172     spin_lock_irq(&gt->irq_lock);
0173     intel_pxp_mark_termination_in_progress(pxp);
0174     pxp->session_events |= PXP_TERMINATION_REQUEST;
0175     queue_work(system_unbound_wq, &pxp->session_work);
0176     spin_unlock_irq(&gt->irq_lock);
0177 }
0178 
0179 /*
0180  * the arb session is restarted from the irq work when we receive the
0181  * termination completion interrupt
0182  */
0183 int intel_pxp_start(struct intel_pxp *pxp)
0184 {
0185     int ret = 0;
0186 
0187     if (!intel_pxp_is_enabled(pxp))
0188         return -ENODEV;
0189 
0190     mutex_lock(&pxp->arb_mutex);
0191 
0192     if (pxp->arb_is_valid)
0193         goto unlock;
0194 
0195     pxp_queue_termination(pxp);
0196 
0197     if (!wait_for_completion_timeout(&pxp->termination,
0198                     msecs_to_jiffies(250))) {
0199         ret = -ETIMEDOUT;
0200         goto unlock;
0201     }
0202 
0203     /* make sure the compiler doesn't optimize the double access */
0204     barrier();
0205 
0206     if (!pxp->arb_is_valid)
0207         ret = -EIO;
0208 
0209 unlock:
0210     mutex_unlock(&pxp->arb_mutex);
0211     return ret;
0212 }
0213 
0214 void intel_pxp_init_hw(struct intel_pxp *pxp)
0215 {
0216     kcr_pxp_enable(pxp_to_gt(pxp));
0217     intel_pxp_irq_enable(pxp);
0218 }
0219 
0220 void intel_pxp_fini_hw(struct intel_pxp *pxp)
0221 {
0222     kcr_pxp_disable(pxp_to_gt(pxp));
0223 
0224     intel_pxp_irq_disable(pxp);
0225 }
0226 
0227 int intel_pxp_key_check(struct intel_pxp *pxp,
0228             struct drm_i915_gem_object *obj,
0229             bool assign)
0230 {
0231     if (!intel_pxp_is_active(pxp))
0232         return -ENODEV;
0233 
0234     if (!i915_gem_object_is_protected(obj))
0235         return -EINVAL;
0236 
0237     GEM_BUG_ON(!pxp->key_instance);
0238 
0239     /*
0240      * If this is the first time we're using this object, it's not
0241      * encrypted yet; it will be encrypted with the current key, so mark it
0242      * as such. If the object is already encrypted, check instead if the
0243      * used key is still valid.
0244      */
0245     if (!obj->pxp_key_instance && assign)
0246         obj->pxp_key_instance = pxp->key_instance;
0247 
0248     if (obj->pxp_key_instance != pxp->key_instance)
0249         return -ENOEXEC;
0250 
0251     return 0;
0252 }
0253 
0254 void intel_pxp_invalidate(struct intel_pxp *pxp)
0255 {
0256     struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
0257     struct i915_gem_context *ctx, *cn;
0258 
0259     /* ban all contexts marked as protected */
0260     spin_lock_irq(&i915->gem.contexts.lock);
0261     list_for_each_entry_safe(ctx, cn, &i915->gem.contexts.list, link) {
0262         struct i915_gem_engines_iter it;
0263         struct intel_context *ce;
0264 
0265         if (!kref_get_unless_zero(&ctx->ref))
0266             continue;
0267 
0268         if (likely(!i915_gem_context_uses_protected_content(ctx))) {
0269             i915_gem_context_put(ctx);
0270             continue;
0271         }
0272 
0273         spin_unlock_irq(&i915->gem.contexts.lock);
0274 
0275         /*
0276          * By the time we get here we are either going to suspend with
0277          * quiesced execution or the HW keys are already long gone and
0278          * in this case it is worthless to attempt to close the context
0279          * and wait for its execution. It will hang the GPU if it has
0280          * not already. So, as a fast mitigation, we can ban the
0281          * context as quick as we can. That might race with the
0282          * execbuffer, but currently this is the best that can be done.
0283          */
0284         for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)
0285             intel_context_ban(ce, NULL);
0286         i915_gem_context_unlock_engines(ctx);
0287 
0288         /*
0289          * The context has been banned, no need to keep the wakeref.
0290          * This is safe from races because the only other place this
0291          * is touched is context_release and we're holding a ctx ref
0292          */
0293         if (ctx->pxp_wakeref) {
0294             intel_runtime_pm_put(&i915->runtime_pm,
0295                          ctx->pxp_wakeref);
0296             ctx->pxp_wakeref = 0;
0297         }
0298 
0299         spin_lock_irq(&i915->gem.contexts.lock);
0300         list_safe_reset_next(ctx, cn, link);
0301         i915_gem_context_put(ctx);
0302     }
0303     spin_unlock_irq(&i915->gem.contexts.lock);
0304 }