Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright(c) 2020 Intel Corporation.
  4 */
  5#include <linux/workqueue.h>
  6#include "intel_pxp.h"
  7#include "intel_pxp_irq.h"
  8#include "intel_pxp_session.h"
  9#include "intel_pxp_tee.h"
 10#include "gem/i915_gem_context.h"
 11#include "gt/intel_context.h"
 12#include "i915_drv.h"
 13
 14/**
 15 * DOC: PXP
 16 *
 17 * PXP (Protected Xe Path) is a feature available in Gen12 and newer platforms.
 18 * It allows execution and flip to display of protected (i.e. encrypted)
 19 * objects. The SW support is enabled via the CONFIG_DRM_I915_PXP kconfig.
 20 *
 21 * Objects can opt-in to PXP encryption at creation time via the
 22 * I915_GEM_CREATE_EXT_PROTECTED_CONTENT create_ext flag. For objects to be
 23 * correctly protected they must be used in conjunction with a context created
 24 * with the I915_CONTEXT_PARAM_PROTECTED_CONTENT flag. See the documentation
 25 * of those two uapi flags for details and restrictions.
 26 *
 27 * Protected objects are tied to a pxp session; currently we only support one
 28 * session, which i915 manages and whose index is available in the uapi
 29 * (I915_PROTECTED_CONTENT_DEFAULT_SESSION) for use in instructions targeting
 30 * protected objects.
 31 * The session is invalidated by the HW when certain events occur (e.g.
 32 * suspend/resume). When this happens, all the objects that were used with the
 33 * session are marked as invalid and all contexts marked as using protected
 34 * content are banned. Any further attempt at using them in an execbuf call is
 35 * rejected, while flips are converted to black frames.
 36 *
 37 * Some of the PXP setup operations are performed by the Management Engine,
 38 * which is handled by the mei driver; communication between i915 and mei is
 39 * performed via the mei_pxp component module.
 40 */
 41
 42struct intel_gt *pxp_to_gt(const struct intel_pxp *pxp)
 43{
 44	return container_of(pxp, struct intel_gt, pxp);
 45}
 46
 47bool intel_pxp_is_enabled(const struct intel_pxp *pxp)
 48{
 49	return pxp->ce;
 50}
 51
 52bool intel_pxp_is_active(const struct intel_pxp *pxp)
 53{
 54	return pxp->arb_is_valid;
 55}
 56
 57/* KCR register definitions */
 58#define KCR_INIT _MMIO(0x320f0)
 59/* Setting KCR Init bit is required after system boot */
 60#define KCR_INIT_ALLOW_DISPLAY_ME_WRITES REG_BIT(14)
 61
 62static void kcr_pxp_enable(struct intel_gt *gt)
 63{
 64	intel_uncore_write(gt->uncore, KCR_INIT,
 65			   _MASKED_BIT_ENABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
 66}
 67
 68static void kcr_pxp_disable(struct intel_gt *gt)
 69{
 70	intel_uncore_write(gt->uncore, KCR_INIT,
 71			   _MASKED_BIT_DISABLE(KCR_INIT_ALLOW_DISPLAY_ME_WRITES));
 72}
 73
 74static int create_vcs_context(struct intel_pxp *pxp)
 75{
 76	static struct lock_class_key pxp_lock;
 77	struct intel_gt *gt = pxp_to_gt(pxp);
 78	struct intel_engine_cs *engine;
 79	struct intel_context *ce;
 80	int i;
 81
 82	/*
 83	 * Find the first VCS engine present. We're guaranteed there is one
 84	 * if we're in this function due to the check in has_pxp
 85	 */
 86	for (i = 0, engine = NULL; !engine; i++)
 87		engine = gt->engine_class[VIDEO_DECODE_CLASS][i];
 88
 89	GEM_BUG_ON(!engine || engine->class != VIDEO_DECODE_CLASS);
 90
 91	ce = intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_4K,
 92						I915_GEM_HWS_PXP_ADDR,
 93						&pxp_lock, "pxp_context");
 94	if (IS_ERR(ce)) {
 95		drm_err(&gt->i915->drm, "failed to create VCS ctx for PXP\n");
 96		return PTR_ERR(ce);
 97	}
 98
 99	pxp->ce = ce;
100
101	return 0;
102}
103
104static void destroy_vcs_context(struct intel_pxp *pxp)
105{
106	if (pxp->ce)
107		intel_engine_destroy_pinned_context(fetch_and_zero(&pxp->ce));
108}
109
110static void pxp_init_full(struct intel_pxp *pxp)
111{
112	struct intel_gt *gt = pxp_to_gt(pxp);
113	int ret;
114
115	/*
116	 * we'll use the completion to check if there is a termination pending,
117	 * so we start it as completed and we reinit it when a termination
118	 * is triggered.
119	 */
120	init_completion(&pxp->termination);
121	complete_all(&pxp->termination);
122
123	intel_pxp_session_management_init(pxp);
124
125	ret = create_vcs_context(pxp);
126	if (ret)
127		return;
128
129	ret = intel_pxp_tee_component_init(pxp);
130	if (ret)
131		goto out_context;
132
133	drm_info(&gt->i915->drm, "Protected Xe Path (PXP) protected content support initialized\n");
134
135	return;
136
137out_context:
138	destroy_vcs_context(pxp);
139}
140
141void intel_pxp_init(struct intel_pxp *pxp)
142{
143	struct intel_gt *gt = pxp_to_gt(pxp);
144
145	/* we rely on the mei PXP module */
146	if (!IS_ENABLED(CONFIG_INTEL_MEI_PXP))
147		return;
148
149	/*
150	 * If HuC is loaded by GSC but PXP is disabled, we can skip the init of
151	 * the full PXP session/object management and just init the tee channel.
152	 */
153	if (HAS_PXP(gt->i915))
154		pxp_init_full(pxp);
155	else if (intel_huc_is_loaded_by_gsc(&gt->uc.huc) && intel_uc_uses_huc(&gt->uc))
156		intel_pxp_tee_component_init(pxp);
157}
158
159void intel_pxp_fini(struct intel_pxp *pxp)
160{
161	pxp->arb_is_valid = false;
162
163	intel_pxp_tee_component_fini(pxp);
164
165	destroy_vcs_context(pxp);
166}
167
168void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp)
169{
170	pxp->arb_is_valid = false;
171	reinit_completion(&pxp->termination);
172}
173
174static void pxp_queue_termination(struct intel_pxp *pxp)
175{
176	struct intel_gt *gt = pxp_to_gt(pxp);
177
178	/*
179	 * We want to get the same effect as if we received a termination
180	 * interrupt, so just pretend that we did.
181	 */
182	spin_lock_irq(gt->irq_lock);
183	intel_pxp_mark_termination_in_progress(pxp);
184	pxp->session_events |= PXP_TERMINATION_REQUEST;
185	queue_work(system_unbound_wq, &pxp->session_work);
186	spin_unlock_irq(gt->irq_lock);
187}
188
189static bool pxp_component_bound(struct intel_pxp *pxp)
190{
191	bool bound = false;
192
193	mutex_lock(&pxp->tee_mutex);
194	if (pxp->pxp_component)
195		bound = true;
196	mutex_unlock(&pxp->tee_mutex);
197
198	return bound;
199}
200
201/*
202 * the arb session is restarted from the irq work when we receive the
203 * termination completion interrupt
204 */
205int intel_pxp_start(struct intel_pxp *pxp)
206{
207	int ret = 0;
208
209	if (!intel_pxp_is_enabled(pxp))
210		return -ENODEV;
211
212	if (wait_for(pxp_component_bound(pxp), 250))
213		return -ENXIO;
214
215	mutex_lock(&pxp->arb_mutex);
216
217	if (pxp->arb_is_valid)
218		goto unlock;
219
220	pxp_queue_termination(pxp);
221
222	if (!wait_for_completion_timeout(&pxp->termination,
223					msecs_to_jiffies(250))) {
224		ret = -ETIMEDOUT;
225		goto unlock;
226	}
227
228	/* make sure the compiler doesn't optimize the double access */
229	barrier();
230
231	if (!pxp->arb_is_valid)
232		ret = -EIO;
233
234unlock:
235	mutex_unlock(&pxp->arb_mutex);
236	return ret;
237}
238
239void intel_pxp_init_hw(struct intel_pxp *pxp)
240{
241	kcr_pxp_enable(pxp_to_gt(pxp));
242	intel_pxp_irq_enable(pxp);
243}
244
245void intel_pxp_fini_hw(struct intel_pxp *pxp)
246{
247	kcr_pxp_disable(pxp_to_gt(pxp));
248
249	intel_pxp_irq_disable(pxp);
250}
251
252int intel_pxp_key_check(struct intel_pxp *pxp,
253			struct drm_i915_gem_object *obj,
254			bool assign)
255{
256	if (!intel_pxp_is_active(pxp))
257		return -ENODEV;
258
259	if (!i915_gem_object_is_protected(obj))
260		return -EINVAL;
261
262	GEM_BUG_ON(!pxp->key_instance);
263
264	/*
265	 * If this is the first time we're using this object, it's not
266	 * encrypted yet; it will be encrypted with the current key, so mark it
267	 * as such. If the object is already encrypted, check instead if the
268	 * used key is still valid.
269	 */
270	if (!obj->pxp_key_instance && assign)
271		obj->pxp_key_instance = pxp->key_instance;
272
273	if (obj->pxp_key_instance != pxp->key_instance)
274		return -ENOEXEC;
275
276	return 0;
277}
278
279void intel_pxp_invalidate(struct intel_pxp *pxp)
280{
281	struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
282	struct i915_gem_context *ctx, *cn;
283
284	/* ban all contexts marked as protected */
285	spin_lock_irq(&i915->gem.contexts.lock);
286	list_for_each_entry_safe(ctx, cn, &i915->gem.contexts.list, link) {
287		struct i915_gem_engines_iter it;
288		struct intel_context *ce;
289
290		if (!kref_get_unless_zero(&ctx->ref))
291			continue;
292
293		if (likely(!i915_gem_context_uses_protected_content(ctx))) {
294			i915_gem_context_put(ctx);
295			continue;
296		}
297
298		spin_unlock_irq(&i915->gem.contexts.lock);
299
300		/*
301		 * By the time we get here we are either going to suspend with
302		 * quiesced execution or the HW keys are already long gone and
303		 * in this case it is worthless to attempt to close the context
304		 * and wait for its execution. It will hang the GPU if it has
305		 * not already. So, as a fast mitigation, we can ban the
306		 * context as quick as we can. That might race with the
307		 * execbuffer, but currently this is the best that can be done.
308		 */
309		for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)
310			intel_context_ban(ce, NULL);
311		i915_gem_context_unlock_engines(ctx);
312
313		/*
314		 * The context has been banned, no need to keep the wakeref.
315		 * This is safe from races because the only other place this
316		 * is touched is context_release and we're holding a ctx ref
317		 */
318		if (ctx->pxp_wakeref) {
319			intel_runtime_pm_put(&i915->runtime_pm,
320					     ctx->pxp_wakeref);
321			ctx->pxp_wakeref = 0;
322		}
323
324		spin_lock_irq(&i915->gem.contexts.lock);
325		list_safe_reset_next(ctx, cn, link);
326		i915_gem_context_put(ctx);
327	}
328	spin_unlock_irq(&i915->gem.contexts.lock);
329}