0001
0002
0003
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
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
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
0058 #define KCR_INIT _MMIO(0x320f0)
0059
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
0084
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(>->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
0121
0122
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(>->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
0170
0171
0172 spin_lock_irq(>->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(>->irq_lock);
0177 }
0178
0179
0180
0181
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
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
0241
0242
0243
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
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
0277
0278
0279
0280
0281
0282
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
0290
0291
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 }