]> Git Repo - J-linux.git/blob - drivers/gpu/drm/i915/pxp/intel_pxp.c
Merge tag 'x86_cleanups_for_v6.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[J-linux.git] / drivers / gpu / drm / i915 / pxp / intel_pxp.c
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
42 struct intel_gt *pxp_to_gt(const struct intel_pxp *pxp)
43 {
44         return container_of(pxp, struct intel_gt, pxp);
45 }
46
47 bool intel_pxp_is_enabled(const struct intel_pxp *pxp)
48 {
49         return pxp->ce;
50 }
51
52 bool 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
62 static 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
68 static 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
74 static 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
104 static void destroy_vcs_context(struct intel_pxp *pxp)
105 {
106         intel_engine_destroy_pinned_context(fetch_and_zero(&pxp->ce));
107 }
108
109 void intel_pxp_init(struct intel_pxp *pxp)
110 {
111         struct intel_gt *gt = pxp_to_gt(pxp);
112         int ret;
113
114         if (!HAS_PXP(gt->i915))
115                 return;
116
117         mutex_init(&pxp->tee_mutex);
118
119         /*
120          * we'll use the completion to check if there is a termination pending,
121          * so we start it as completed and we reinit it when a termination
122          * is triggered.
123          */
124         init_completion(&pxp->termination);
125         complete_all(&pxp->termination);
126
127         mutex_init(&pxp->arb_mutex);
128         INIT_WORK(&pxp->session_work, intel_pxp_session_work);
129
130         ret = create_vcs_context(pxp);
131         if (ret)
132                 return;
133
134         ret = intel_pxp_tee_component_init(pxp);
135         if (ret)
136                 goto out_context;
137
138         drm_info(&gt->i915->drm, "Protected Xe Path (PXP) protected content support initialized\n");
139
140         return;
141
142 out_context:
143         destroy_vcs_context(pxp);
144 }
145
146 void intel_pxp_fini(struct intel_pxp *pxp)
147 {
148         if (!intel_pxp_is_enabled(pxp))
149                 return;
150
151         pxp->arb_is_valid = false;
152
153         intel_pxp_tee_component_fini(pxp);
154
155         destroy_vcs_context(pxp);
156 }
157
158 void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp)
159 {
160         pxp->arb_is_valid = false;
161         reinit_completion(&pxp->termination);
162 }
163
164 static void pxp_queue_termination(struct intel_pxp *pxp)
165 {
166         struct intel_gt *gt = pxp_to_gt(pxp);
167
168         /*
169          * We want to get the same effect as if we received a termination
170          * interrupt, so just pretend that we did.
171          */
172         spin_lock_irq(&gt->irq_lock);
173         intel_pxp_mark_termination_in_progress(pxp);
174         pxp->session_events |= PXP_TERMINATION_REQUEST;
175         queue_work(system_unbound_wq, &pxp->session_work);
176         spin_unlock_irq(&gt->irq_lock);
177 }
178
179 /*
180  * the arb session is restarted from the irq work when we receive the
181  * termination completion interrupt
182  */
183 int intel_pxp_start(struct intel_pxp *pxp)
184 {
185         int ret = 0;
186
187         if (!intel_pxp_is_enabled(pxp))
188                 return -ENODEV;
189
190         mutex_lock(&pxp->arb_mutex);
191
192         if (pxp->arb_is_valid)
193                 goto unlock;
194
195         pxp_queue_termination(pxp);
196
197         if (!wait_for_completion_timeout(&pxp->termination,
198                                         msecs_to_jiffies(250))) {
199                 ret = -ETIMEDOUT;
200                 goto unlock;
201         }
202
203         /* make sure the compiler doesn't optimize the double access */
204         barrier();
205
206         if (!pxp->arb_is_valid)
207                 ret = -EIO;
208
209 unlock:
210         mutex_unlock(&pxp->arb_mutex);
211         return ret;
212 }
213
214 void intel_pxp_init_hw(struct intel_pxp *pxp)
215 {
216         kcr_pxp_enable(pxp_to_gt(pxp));
217         intel_pxp_irq_enable(pxp);
218 }
219
220 void intel_pxp_fini_hw(struct intel_pxp *pxp)
221 {
222         kcr_pxp_disable(pxp_to_gt(pxp));
223
224         intel_pxp_irq_disable(pxp);
225 }
226
227 int intel_pxp_key_check(struct intel_pxp *pxp,
228                         struct drm_i915_gem_object *obj,
229                         bool assign)
230 {
231         if (!intel_pxp_is_active(pxp))
232                 return -ENODEV;
233
234         if (!i915_gem_object_is_protected(obj))
235                 return -EINVAL;
236
237         GEM_BUG_ON(!pxp->key_instance);
238
239         /*
240          * If this is the first time we're using this object, it's not
241          * encrypted yet; it will be encrypted with the current key, so mark it
242          * as such. If the object is already encrypted, check instead if the
243          * used key is still valid.
244          */
245         if (!obj->pxp_key_instance && assign)
246                 obj->pxp_key_instance = pxp->key_instance;
247
248         if (obj->pxp_key_instance != pxp->key_instance)
249                 return -ENOEXEC;
250
251         return 0;
252 }
253
254 void intel_pxp_invalidate(struct intel_pxp *pxp)
255 {
256         struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
257         struct i915_gem_context *ctx, *cn;
258
259         /* ban all contexts marked as protected */
260         spin_lock_irq(&i915->gem.contexts.lock);
261         list_for_each_entry_safe(ctx, cn, &i915->gem.contexts.list, link) {
262                 struct i915_gem_engines_iter it;
263                 struct intel_context *ce;
264
265                 if (!kref_get_unless_zero(&ctx->ref))
266                         continue;
267
268                 if (likely(!i915_gem_context_uses_protected_content(ctx))) {
269                         i915_gem_context_put(ctx);
270                         continue;
271                 }
272
273                 spin_unlock_irq(&i915->gem.contexts.lock);
274
275                 /*
276                  * By the time we get here we are either going to suspend with
277                  * quiesced execution or the HW keys are already long gone and
278                  * in this case it is worthless to attempt to close the context
279                  * and wait for its execution. It will hang the GPU if it has
280                  * not already. So, as a fast mitigation, we can ban the
281                  * context as quick as we can. That might race with the
282                  * execbuffer, but currently this is the best that can be done.
283                  */
284                 for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)
285                         intel_context_ban(ce, NULL);
286                 i915_gem_context_unlock_engines(ctx);
287
288                 /*
289                  * The context has been banned, no need to keep the wakeref.
290                  * This is safe from races because the only other place this
291                  * is touched is context_release and we're holding a ctx ref
292                  */
293                 if (ctx->pxp_wakeref) {
294                         intel_runtime_pm_put(&i915->runtime_pm,
295                                              ctx->pxp_wakeref);
296                         ctx->pxp_wakeref = 0;
297                 }
298
299                 spin_lock_irq(&i915->gem.contexts.lock);
300                 list_safe_reset_next(ctx, cn, link);
301                 i915_gem_context_put(ctx);
302         }
303         spin_unlock_irq(&i915->gem.contexts.lock);
304 }
This page took 0.05155 seconds and 4 git commands to generate.