GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / gpu / drm / i915 / selftests / intel_workarounds.c
1 /*
2  * SPDX-License-Identifier: MIT
3  *
4  * Copyright © 2018 Intel Corporation
5  */
6
7 #include "../i915_selftest.h"
8
9 #include "igt_wedge_me.h"
10 #include "mock_context.h"
11
12 static struct drm_i915_gem_object *
13 read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
14 {
15         struct drm_i915_gem_object *result;
16         struct i915_request *rq;
17         struct i915_vma *vma;
18         const u32 base = engine->mmio_base;
19         u32 srm, *cs;
20         int err;
21         int i;
22
23         result = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
24         if (IS_ERR(result))
25                 return result;
26
27         i915_gem_object_set_cache_level(result, I915_CACHE_LLC);
28
29         cs = i915_gem_object_pin_map(result, I915_MAP_WB);
30         if (IS_ERR(cs)) {
31                 err = PTR_ERR(cs);
32                 goto err_obj;
33         }
34         memset(cs, 0xc5, PAGE_SIZE);
35         i915_gem_object_unpin_map(result);
36
37         vma = i915_vma_instance(result, &engine->i915->ggtt.vm, NULL);
38         if (IS_ERR(vma)) {
39                 err = PTR_ERR(vma);
40                 goto err_obj;
41         }
42
43         err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
44         if (err)
45                 goto err_obj;
46
47         rq = i915_request_alloc(engine, ctx);
48         if (IS_ERR(rq)) {
49                 err = PTR_ERR(rq);
50                 goto err_pin;
51         }
52
53         err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
54         if (err)
55                 goto err_req;
56
57         srm = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
58         if (INTEL_GEN(ctx->i915) >= 8)
59                 srm++;
60
61         cs = intel_ring_begin(rq, 4 * RING_MAX_NONPRIV_SLOTS);
62         if (IS_ERR(cs)) {
63                 err = PTR_ERR(cs);
64                 goto err_req;
65         }
66
67         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
68                 *cs++ = srm;
69                 *cs++ = i915_mmio_reg_offset(RING_FORCE_TO_NONPRIV(base, i));
70                 *cs++ = i915_ggtt_offset(vma) + sizeof(u32) * i;
71                 *cs++ = 0;
72         }
73         intel_ring_advance(rq, cs);
74
75         i915_gem_object_get(result);
76         i915_gem_object_set_active_reference(result);
77
78         i915_request_add(rq);
79         i915_vma_unpin(vma);
80
81         return result;
82
83 err_req:
84         i915_request_add(rq);
85 err_pin:
86         i915_vma_unpin(vma);
87 err_obj:
88         i915_gem_object_put(result);
89         return ERR_PTR(err);
90 }
91
92 static u32 get_whitelist_reg(const struct whitelist *w, unsigned int i)
93 {
94         return i < w->count ? i915_mmio_reg_offset(w->reg[i]) : w->nopid;
95 }
96
97 static void print_results(const struct whitelist *w, const u32 *results)
98 {
99         unsigned int i;
100
101         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
102                 u32 expected = get_whitelist_reg(w, i);
103                 u32 actual = results[i];
104
105                 pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n",
106                         i, expected, actual);
107         }
108 }
109
110 static int check_whitelist(const struct whitelist *w,
111                            struct i915_gem_context *ctx,
112                            struct intel_engine_cs *engine)
113 {
114         struct drm_i915_gem_object *results;
115         struct igt_wedge_me wedge;
116         u32 *vaddr;
117         int err;
118         int i;
119
120         results = read_nonprivs(ctx, engine);
121         if (IS_ERR(results))
122                 return PTR_ERR(results);
123
124         err = 0;
125         igt_wedge_on_timeout(&wedge, ctx->i915, HZ / 5) /* a safety net! */
126                 err = i915_gem_object_set_to_cpu_domain(results, false);
127         if (i915_terminally_wedged(&ctx->i915->gpu_error))
128                 err = -EIO;
129         if (err)
130                 goto out_put;
131
132         vaddr = i915_gem_object_pin_map(results, I915_MAP_WB);
133         if (IS_ERR(vaddr)) {
134                 err = PTR_ERR(vaddr);
135                 goto out_put;
136         }
137
138         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
139                 u32 expected = get_whitelist_reg(w, i);
140                 u32 actual = vaddr[i];
141
142                 if (expected != actual) {
143                         print_results(w, vaddr);
144                         pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n",
145                                i, expected, actual);
146
147                         err = -EINVAL;
148                         break;
149                 }
150         }
151
152         i915_gem_object_unpin_map(results);
153 out_put:
154         i915_gem_object_put(results);
155         return err;
156 }
157
158 static int do_device_reset(struct intel_engine_cs *engine)
159 {
160         i915_reset(engine->i915, ENGINE_MASK(engine->id), NULL);
161         return 0;
162 }
163
164 static int do_engine_reset(struct intel_engine_cs *engine)
165 {
166         return i915_reset_engine(engine, NULL);
167 }
168
169 static int switch_to_scratch_context(struct intel_engine_cs *engine)
170 {
171         struct i915_gem_context *ctx;
172         struct i915_request *rq;
173
174         ctx = kernel_context(engine->i915);
175         if (IS_ERR(ctx))
176                 return PTR_ERR(ctx);
177
178         rq = i915_request_alloc(engine, ctx);
179         kernel_context_close(ctx);
180         if (IS_ERR(rq))
181                 return PTR_ERR(rq);
182
183         i915_request_add(rq);
184
185         return 0;
186 }
187
188 static int check_whitelist_across_reset(struct intel_engine_cs *engine,
189                                         int (*reset)(struct intel_engine_cs *),
190                                         const struct whitelist *w,
191                                         const char *name)
192 {
193         struct i915_gem_context *ctx;
194         int err;
195
196         ctx = kernel_context(engine->i915);
197         if (IS_ERR(ctx))
198                 return PTR_ERR(ctx);
199
200         err = check_whitelist(w, ctx, engine);
201         if (err) {
202                 pr_err("Invalid whitelist *before* %s reset!\n", name);
203                 goto out;
204         }
205
206         err = switch_to_scratch_context(engine);
207         if (err)
208                 goto out;
209
210         err = reset(engine);
211         if (err) {
212                 pr_err("%s reset failed\n", name);
213                 goto out;
214         }
215
216         err = check_whitelist(w, ctx, engine);
217         if (err) {
218                 pr_err("Whitelist not preserved in context across %s reset!\n",
219                        name);
220                 goto out;
221         }
222
223         kernel_context_close(ctx);
224
225         ctx = kernel_context(engine->i915);
226         if (IS_ERR(ctx))
227                 return PTR_ERR(ctx);
228
229         err = check_whitelist(w, ctx, engine);
230         if (err) {
231                 pr_err("Invalid whitelist *after* %s reset in fresh context!\n",
232                        name);
233                 goto out;
234         }
235
236 out:
237         kernel_context_close(ctx);
238         return err;
239 }
240
241 static int live_reset_whitelist(void *arg)
242 {
243         struct drm_i915_private *i915 = arg;
244         struct intel_engine_cs *engine = i915->engine[RCS];
245         struct i915_gpu_error *error = &i915->gpu_error;
246         struct whitelist w;
247         int err = 0;
248
249         /* If we reset the gpu, we should not lose the RING_NONPRIV */
250
251         if (!engine)
252                 return 0;
253
254         if (!whitelist_build(engine, &w))
255                 return 0;
256
257         pr_info("Checking %d whitelisted registers (RING_NONPRIV)\n", w.count);
258
259         set_bit(I915_RESET_BACKOFF, &error->flags);
260         set_bit(I915_RESET_ENGINE + engine->id, &error->flags);
261
262         if (intel_has_reset_engine(i915)) {
263                 err = check_whitelist_across_reset(engine,
264                                                    do_engine_reset, &w,
265                                                    "engine");
266                 if (err)
267                         goto out;
268         }
269
270         if (intel_has_gpu_reset(i915)) {
271                 err = check_whitelist_across_reset(engine,
272                                                    do_device_reset, &w,
273                                                    "device");
274                 if (err)
275                         goto out;
276         }
277
278 out:
279         clear_bit(I915_RESET_ENGINE + engine->id, &error->flags);
280         clear_bit(I915_RESET_BACKOFF, &error->flags);
281         return err;
282 }
283
284 int intel_workarounds_live_selftests(struct drm_i915_private *i915)
285 {
286         static const struct i915_subtest tests[] = {
287                 SUBTEST(live_reset_whitelist),
288         };
289         int err;
290
291         if (i915_terminally_wedged(&i915->gpu_error))
292                 return 0;
293
294         mutex_lock(&i915->drm.struct_mutex);
295         err = i915_subtests(tests, i915);
296         mutex_unlock(&i915->drm.struct_mutex);
297
298         return err;
299 }