0001
0002
0003
0004
0005
0006 #include <linux/prime_numbers.h>
0007
0008 #include "gem/i915_gem_internal.h"
0009
0010 #include "i915_selftest.h"
0011 #include "intel_engine_heartbeat.h"
0012 #include "intel_engine_pm.h"
0013 #include "intel_reset.h"
0014 #include "intel_ring.h"
0015 #include "selftest_engine_heartbeat.h"
0016 #include "selftests/i915_random.h"
0017 #include "selftests/igt_flush_test.h"
0018 #include "selftests/igt_live_test.h"
0019 #include "selftests/igt_spinner.h"
0020 #include "selftests/lib_sw_fence.h"
0021 #include "shmem_utils.h"
0022
0023 #include "gem/selftests/igt_gem_utils.h"
0024 #include "gem/selftests/mock_context.h"
0025
0026 #define CS_GPR(engine, n) ((engine)->mmio_base + 0x600 + (n) * 4)
0027 #define NUM_GPR 16
0028 #define NUM_GPR_DW (NUM_GPR * 2)
0029
0030 static struct i915_vma *create_scratch(struct intel_gt *gt)
0031 {
0032 return __vm_create_scratch_for_read_pinned(>->ggtt->vm, PAGE_SIZE);
0033 }
0034
0035 static bool is_active(struct i915_request *rq)
0036 {
0037 if (i915_request_is_active(rq))
0038 return true;
0039
0040 if (i915_request_on_hold(rq))
0041 return true;
0042
0043 if (i915_request_has_initial_breadcrumb(rq) && i915_request_started(rq))
0044 return true;
0045
0046 return false;
0047 }
0048
0049 static int wait_for_submit(struct intel_engine_cs *engine,
0050 struct i915_request *rq,
0051 unsigned long timeout)
0052 {
0053
0054 tasklet_hi_schedule(&engine->sched_engine->tasklet);
0055
0056 timeout += jiffies;
0057 do {
0058 bool done = time_after(jiffies, timeout);
0059
0060 if (i915_request_completed(rq))
0061 return 0;
0062
0063
0064 intel_engine_flush_submission(engine);
0065 if (!READ_ONCE(engine->execlists.pending[0]) && is_active(rq))
0066 return 0;
0067
0068 if (done)
0069 return -ETIME;
0070
0071 cond_resched();
0072 } while (1);
0073 }
0074
0075 static int emit_semaphore_signal(struct intel_context *ce, void *slot)
0076 {
0077 const u32 offset =
0078 i915_ggtt_offset(ce->engine->status_page.vma) +
0079 offset_in_page(slot);
0080 struct i915_request *rq;
0081 u32 *cs;
0082
0083 rq = intel_context_create_request(ce);
0084 if (IS_ERR(rq))
0085 return PTR_ERR(rq);
0086
0087 cs = intel_ring_begin(rq, 4);
0088 if (IS_ERR(cs)) {
0089 i915_request_add(rq);
0090 return PTR_ERR(cs);
0091 }
0092
0093 *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
0094 *cs++ = offset;
0095 *cs++ = 0;
0096 *cs++ = 1;
0097
0098 intel_ring_advance(rq, cs);
0099
0100 rq->sched.attr.priority = I915_PRIORITY_BARRIER;
0101 i915_request_add(rq);
0102 return 0;
0103 }
0104
0105 static int context_flush(struct intel_context *ce, long timeout)
0106 {
0107 struct i915_request *rq;
0108 struct dma_fence *fence;
0109 int err = 0;
0110
0111 rq = intel_engine_create_kernel_request(ce->engine);
0112 if (IS_ERR(rq))
0113 return PTR_ERR(rq);
0114
0115 fence = i915_active_fence_get(&ce->timeline->last_request);
0116 if (fence) {
0117 i915_request_await_dma_fence(rq, fence);
0118 dma_fence_put(fence);
0119 }
0120
0121 rq = i915_request_get(rq);
0122 i915_request_add(rq);
0123 if (i915_request_wait(rq, 0, timeout) < 0)
0124 err = -ETIME;
0125 i915_request_put(rq);
0126
0127 rmb();
0128 return err;
0129 }
0130
0131 static int get_lri_mask(struct intel_engine_cs *engine, u32 lri)
0132 {
0133 if ((lri & MI_LRI_LRM_CS_MMIO) == 0)
0134 return ~0u;
0135
0136 if (GRAPHICS_VER(engine->i915) < 12)
0137 return 0xfff;
0138
0139 switch (engine->class) {
0140 default:
0141 case RENDER_CLASS:
0142 case COMPUTE_CLASS:
0143 return 0x07ff;
0144 case COPY_ENGINE_CLASS:
0145 return 0x0fff;
0146 case VIDEO_DECODE_CLASS:
0147 case VIDEO_ENHANCEMENT_CLASS:
0148 return 0x3fff;
0149 }
0150 }
0151
0152 static int live_lrc_layout(void *arg)
0153 {
0154 struct intel_gt *gt = arg;
0155 struct intel_engine_cs *engine;
0156 enum intel_engine_id id;
0157 u32 *lrc;
0158 int err;
0159
0160
0161
0162
0163
0164
0165 lrc = (u32 *)__get_free_page(GFP_KERNEL);
0166 if (!lrc)
0167 return -ENOMEM;
0168 GEM_BUG_ON(offset_in_page(lrc));
0169
0170 err = 0;
0171 for_each_engine(engine, gt, id) {
0172 u32 *hw;
0173 int dw;
0174
0175 if (!engine->default_state)
0176 continue;
0177
0178 hw = shmem_pin_map(engine->default_state);
0179 if (!hw) {
0180 err = -ENOMEM;
0181 break;
0182 }
0183 hw += LRC_STATE_OFFSET / sizeof(*hw);
0184
0185 __lrc_init_regs(memset(lrc, POISON_INUSE, PAGE_SIZE),
0186 engine->kernel_context, engine, true);
0187
0188 dw = 0;
0189 do {
0190 u32 lri = READ_ONCE(hw[dw]);
0191 u32 lri_mask;
0192
0193 if (lri == 0) {
0194 dw++;
0195 continue;
0196 }
0197
0198 if (lrc[dw] == 0) {
0199 pr_debug("%s: skipped instruction %x at dword %d\n",
0200 engine->name, lri, dw);
0201 dw++;
0202 continue;
0203 }
0204
0205 if ((lri & GENMASK(31, 23)) != MI_INSTR(0x22, 0)) {
0206 pr_err("%s: Expected LRI command at dword %d, found %08x\n",
0207 engine->name, dw, lri);
0208 err = -EINVAL;
0209 break;
0210 }
0211
0212 if (lrc[dw] != lri) {
0213 pr_err("%s: LRI command mismatch at dword %d, expected %08x found %08x\n",
0214 engine->name, dw, lri, lrc[dw]);
0215 err = -EINVAL;
0216 break;
0217 }
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 lri_mask = get_lri_mask(engine, lri);
0230
0231 lri &= 0x7f;
0232 lri++;
0233 dw++;
0234
0235 while (lri) {
0236 u32 offset = READ_ONCE(hw[dw]);
0237
0238 if ((offset ^ lrc[dw]) & lri_mask) {
0239 pr_err("%s: Different registers found at dword %d, expected %x, found %x\n",
0240 engine->name, dw, offset, lrc[dw]);
0241 err = -EINVAL;
0242 break;
0243 }
0244
0245
0246
0247
0248
0249 dw += 2;
0250 lri -= 2;
0251 }
0252 } while (!err && (lrc[dw] & ~BIT(0)) != MI_BATCH_BUFFER_END);
0253
0254 if (err) {
0255 pr_info("%s: HW register image:\n", engine->name);
0256 igt_hexdump(hw, PAGE_SIZE);
0257
0258 pr_info("%s: SW register image:\n", engine->name);
0259 igt_hexdump(lrc, PAGE_SIZE);
0260 }
0261
0262 shmem_unpin_map(engine->default_state, hw);
0263 if (err)
0264 break;
0265 }
0266
0267 free_page((unsigned long)lrc);
0268 return err;
0269 }
0270
0271 static int find_offset(const u32 *lri, u32 offset)
0272 {
0273 int i;
0274
0275 for (i = 0; i < PAGE_SIZE / sizeof(u32); i++)
0276 if (lri[i] == offset)
0277 return i;
0278
0279 return -1;
0280 }
0281
0282 static int live_lrc_fixed(void *arg)
0283 {
0284 struct intel_gt *gt = arg;
0285 struct intel_engine_cs *engine;
0286 enum intel_engine_id id;
0287 int err = 0;
0288
0289
0290
0291
0292
0293
0294 for_each_engine(engine, gt, id) {
0295 const struct {
0296 u32 reg;
0297 u32 offset;
0298 const char *name;
0299 } tbl[] = {
0300 {
0301 i915_mmio_reg_offset(RING_START(engine->mmio_base)),
0302 CTX_RING_START - 1,
0303 "RING_START"
0304 },
0305 {
0306 i915_mmio_reg_offset(RING_CTL(engine->mmio_base)),
0307 CTX_RING_CTL - 1,
0308 "RING_CTL"
0309 },
0310 {
0311 i915_mmio_reg_offset(RING_HEAD(engine->mmio_base)),
0312 CTX_RING_HEAD - 1,
0313 "RING_HEAD"
0314 },
0315 {
0316 i915_mmio_reg_offset(RING_TAIL(engine->mmio_base)),
0317 CTX_RING_TAIL - 1,
0318 "RING_TAIL"
0319 },
0320 {
0321 i915_mmio_reg_offset(RING_MI_MODE(engine->mmio_base)),
0322 lrc_ring_mi_mode(engine),
0323 "RING_MI_MODE"
0324 },
0325 {
0326 i915_mmio_reg_offset(RING_BBSTATE(engine->mmio_base)),
0327 CTX_BB_STATE - 1,
0328 "BB_STATE"
0329 },
0330 {
0331 i915_mmio_reg_offset(RING_BB_PER_CTX_PTR(engine->mmio_base)),
0332 lrc_ring_wa_bb_per_ctx(engine),
0333 "RING_BB_PER_CTX_PTR"
0334 },
0335 {
0336 i915_mmio_reg_offset(RING_INDIRECT_CTX(engine->mmio_base)),
0337 lrc_ring_indirect_ptr(engine),
0338 "RING_INDIRECT_CTX_PTR"
0339 },
0340 {
0341 i915_mmio_reg_offset(RING_INDIRECT_CTX_OFFSET(engine->mmio_base)),
0342 lrc_ring_indirect_offset(engine),
0343 "RING_INDIRECT_CTX_OFFSET"
0344 },
0345 {
0346 i915_mmio_reg_offset(RING_CTX_TIMESTAMP(engine->mmio_base)),
0347 CTX_TIMESTAMP - 1,
0348 "RING_CTX_TIMESTAMP"
0349 },
0350 {
0351 i915_mmio_reg_offset(GEN8_RING_CS_GPR(engine->mmio_base, 0)),
0352 lrc_ring_gpr0(engine),
0353 "RING_CS_GPR0"
0354 },
0355 {
0356 i915_mmio_reg_offset(RING_CMD_BUF_CCTL(engine->mmio_base)),
0357 lrc_ring_cmd_buf_cctl(engine),
0358 "RING_CMD_BUF_CCTL"
0359 },
0360 { },
0361 }, *t;
0362 u32 *hw;
0363
0364 if (!engine->default_state)
0365 continue;
0366
0367 hw = shmem_pin_map(engine->default_state);
0368 if (!hw) {
0369 err = -ENOMEM;
0370 break;
0371 }
0372 hw += LRC_STATE_OFFSET / sizeof(*hw);
0373
0374 for (t = tbl; t->name; t++) {
0375 int dw = find_offset(hw, t->reg);
0376
0377 if (dw != t->offset) {
0378 pr_err("%s: Offset for %s [0x%x] mismatch, found %x, expected %x\n",
0379 engine->name,
0380 t->name,
0381 t->reg,
0382 dw,
0383 t->offset);
0384 err = -EINVAL;
0385 }
0386 }
0387
0388 shmem_unpin_map(engine->default_state, hw);
0389 }
0390
0391 return err;
0392 }
0393
0394 static int __live_lrc_state(struct intel_engine_cs *engine,
0395 struct i915_vma *scratch)
0396 {
0397 struct intel_context *ce;
0398 struct i915_request *rq;
0399 struct i915_gem_ww_ctx ww;
0400 enum {
0401 RING_START_IDX = 0,
0402 RING_TAIL_IDX,
0403 MAX_IDX
0404 };
0405 u32 expected[MAX_IDX];
0406 u32 *cs;
0407 int err;
0408 int n;
0409
0410 ce = intel_context_create(engine);
0411 if (IS_ERR(ce))
0412 return PTR_ERR(ce);
0413
0414 i915_gem_ww_ctx_init(&ww, false);
0415 retry:
0416 err = i915_gem_object_lock(scratch->obj, &ww);
0417 if (!err)
0418 err = intel_context_pin_ww(ce, &ww);
0419 if (err)
0420 goto err_put;
0421
0422 rq = i915_request_create(ce);
0423 if (IS_ERR(rq)) {
0424 err = PTR_ERR(rq);
0425 goto err_unpin;
0426 }
0427
0428 cs = intel_ring_begin(rq, 4 * MAX_IDX);
0429 if (IS_ERR(cs)) {
0430 err = PTR_ERR(cs);
0431 i915_request_add(rq);
0432 goto err_unpin;
0433 }
0434
0435 *cs++ = MI_STORE_REGISTER_MEM_GEN8 | MI_USE_GGTT;
0436 *cs++ = i915_mmio_reg_offset(RING_START(engine->mmio_base));
0437 *cs++ = i915_ggtt_offset(scratch) + RING_START_IDX * sizeof(u32);
0438 *cs++ = 0;
0439
0440 expected[RING_START_IDX] = i915_ggtt_offset(ce->ring->vma);
0441
0442 *cs++ = MI_STORE_REGISTER_MEM_GEN8 | MI_USE_GGTT;
0443 *cs++ = i915_mmio_reg_offset(RING_TAIL(engine->mmio_base));
0444 *cs++ = i915_ggtt_offset(scratch) + RING_TAIL_IDX * sizeof(u32);
0445 *cs++ = 0;
0446
0447 err = i915_request_await_object(rq, scratch->obj, true);
0448 if (!err)
0449 err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE);
0450
0451 i915_request_get(rq);
0452 i915_request_add(rq);
0453 if (err)
0454 goto err_rq;
0455
0456 intel_engine_flush_submission(engine);
0457 expected[RING_TAIL_IDX] = ce->ring->tail;
0458
0459 if (i915_request_wait(rq, 0, HZ / 5) < 0) {
0460 err = -ETIME;
0461 goto err_rq;
0462 }
0463
0464 cs = i915_gem_object_pin_map(scratch->obj, I915_MAP_WB);
0465 if (IS_ERR(cs)) {
0466 err = PTR_ERR(cs);
0467 goto err_rq;
0468 }
0469
0470 for (n = 0; n < MAX_IDX; n++) {
0471 if (cs[n] != expected[n]) {
0472 pr_err("%s: Stored register[%d] value[0x%x] did not match expected[0x%x]\n",
0473 engine->name, n, cs[n], expected[n]);
0474 err = -EINVAL;
0475 break;
0476 }
0477 }
0478
0479 i915_gem_object_unpin_map(scratch->obj);
0480
0481 err_rq:
0482 i915_request_put(rq);
0483 err_unpin:
0484 intel_context_unpin(ce);
0485 err_put:
0486 if (err == -EDEADLK) {
0487 err = i915_gem_ww_ctx_backoff(&ww);
0488 if (!err)
0489 goto retry;
0490 }
0491 i915_gem_ww_ctx_fini(&ww);
0492 intel_context_put(ce);
0493 return err;
0494 }
0495
0496 static int live_lrc_state(void *arg)
0497 {
0498 struct intel_gt *gt = arg;
0499 struct intel_engine_cs *engine;
0500 struct i915_vma *scratch;
0501 enum intel_engine_id id;
0502 int err = 0;
0503
0504
0505
0506
0507
0508
0509 scratch = create_scratch(gt);
0510 if (IS_ERR(scratch))
0511 return PTR_ERR(scratch);
0512
0513 for_each_engine(engine, gt, id) {
0514 err = __live_lrc_state(engine, scratch);
0515 if (err)
0516 break;
0517 }
0518
0519 if (igt_flush_test(gt->i915))
0520 err = -EIO;
0521
0522 i915_vma_unpin_and_release(&scratch, 0);
0523 return err;
0524 }
0525
0526 static int gpr_make_dirty(struct intel_context *ce)
0527 {
0528 struct i915_request *rq;
0529 u32 *cs;
0530 int n;
0531
0532 rq = intel_context_create_request(ce);
0533 if (IS_ERR(rq))
0534 return PTR_ERR(rq);
0535
0536 cs = intel_ring_begin(rq, 2 * NUM_GPR_DW + 2);
0537 if (IS_ERR(cs)) {
0538 i915_request_add(rq);
0539 return PTR_ERR(cs);
0540 }
0541
0542 *cs++ = MI_LOAD_REGISTER_IMM(NUM_GPR_DW);
0543 for (n = 0; n < NUM_GPR_DW; n++) {
0544 *cs++ = CS_GPR(ce->engine, n);
0545 *cs++ = STACK_MAGIC;
0546 }
0547 *cs++ = MI_NOOP;
0548
0549 intel_ring_advance(rq, cs);
0550
0551 rq->sched.attr.priority = I915_PRIORITY_BARRIER;
0552 i915_request_add(rq);
0553
0554 return 0;
0555 }
0556
0557 static struct i915_request *
0558 __gpr_read(struct intel_context *ce, struct i915_vma *scratch, u32 *slot)
0559 {
0560 const u32 offset =
0561 i915_ggtt_offset(ce->engine->status_page.vma) +
0562 offset_in_page(slot);
0563 struct i915_request *rq;
0564 u32 *cs;
0565 int err;
0566 int n;
0567
0568 rq = intel_context_create_request(ce);
0569 if (IS_ERR(rq))
0570 return rq;
0571
0572 cs = intel_ring_begin(rq, 6 + 4 * NUM_GPR_DW);
0573 if (IS_ERR(cs)) {
0574 i915_request_add(rq);
0575 return ERR_CAST(cs);
0576 }
0577
0578 *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
0579 *cs++ = MI_NOOP;
0580
0581 *cs++ = MI_SEMAPHORE_WAIT |
0582 MI_SEMAPHORE_GLOBAL_GTT |
0583 MI_SEMAPHORE_POLL |
0584 MI_SEMAPHORE_SAD_NEQ_SDD;
0585 *cs++ = 0;
0586 *cs++ = offset;
0587 *cs++ = 0;
0588
0589 for (n = 0; n < NUM_GPR_DW; n++) {
0590 *cs++ = MI_STORE_REGISTER_MEM_GEN8 | MI_USE_GGTT;
0591 *cs++ = CS_GPR(ce->engine, n);
0592 *cs++ = i915_ggtt_offset(scratch) + n * sizeof(u32);
0593 *cs++ = 0;
0594 }
0595
0596 i915_vma_lock(scratch);
0597 err = i915_request_await_object(rq, scratch->obj, true);
0598 if (!err)
0599 err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE);
0600 i915_vma_unlock(scratch);
0601
0602 i915_request_get(rq);
0603 i915_request_add(rq);
0604 if (err) {
0605 i915_request_put(rq);
0606 rq = ERR_PTR(err);
0607 }
0608
0609 return rq;
0610 }
0611
0612 static int __live_lrc_gpr(struct intel_engine_cs *engine,
0613 struct i915_vma *scratch,
0614 bool preempt)
0615 {
0616 u32 *slot = memset32(engine->status_page.addr + 1000, 0, 4);
0617 struct intel_context *ce;
0618 struct i915_request *rq;
0619 u32 *cs;
0620 int err;
0621 int n;
0622
0623 if (GRAPHICS_VER(engine->i915) < 9 && engine->class != RENDER_CLASS)
0624 return 0;
0625
0626 err = gpr_make_dirty(engine->kernel_context);
0627 if (err)
0628 return err;
0629
0630 ce = intel_context_create(engine);
0631 if (IS_ERR(ce))
0632 return PTR_ERR(ce);
0633
0634 rq = __gpr_read(ce, scratch, slot);
0635 if (IS_ERR(rq)) {
0636 err = PTR_ERR(rq);
0637 goto err_put;
0638 }
0639
0640 err = wait_for_submit(engine, rq, HZ / 2);
0641 if (err)
0642 goto err_rq;
0643
0644 if (preempt) {
0645 err = gpr_make_dirty(engine->kernel_context);
0646 if (err)
0647 goto err_rq;
0648
0649 err = emit_semaphore_signal(engine->kernel_context, slot);
0650 if (err)
0651 goto err_rq;
0652
0653 err = wait_for_submit(engine, rq, HZ / 2);
0654 if (err)
0655 goto err_rq;
0656 } else {
0657 slot[0] = 1;
0658 wmb();
0659 }
0660
0661 if (i915_request_wait(rq, 0, HZ / 5) < 0) {
0662 err = -ETIME;
0663 goto err_rq;
0664 }
0665
0666 cs = i915_gem_object_pin_map_unlocked(scratch->obj, I915_MAP_WB);
0667 if (IS_ERR(cs)) {
0668 err = PTR_ERR(cs);
0669 goto err_rq;
0670 }
0671
0672 for (n = 0; n < NUM_GPR_DW; n++) {
0673 if (cs[n]) {
0674 pr_err("%s: GPR[%d].%s was not zero, found 0x%08x!\n",
0675 engine->name,
0676 n / 2, n & 1 ? "udw" : "ldw",
0677 cs[n]);
0678 err = -EINVAL;
0679 break;
0680 }
0681 }
0682
0683 i915_gem_object_unpin_map(scratch->obj);
0684
0685 err_rq:
0686 memset32(&slot[0], -1, 4);
0687 wmb();
0688 i915_request_put(rq);
0689 err_put:
0690 intel_context_put(ce);
0691 return err;
0692 }
0693
0694 static int live_lrc_gpr(void *arg)
0695 {
0696 struct intel_gt *gt = arg;
0697 struct intel_engine_cs *engine;
0698 struct i915_vma *scratch;
0699 enum intel_engine_id id;
0700 int err = 0;
0701
0702
0703
0704
0705
0706
0707 scratch = create_scratch(gt);
0708 if (IS_ERR(scratch))
0709 return PTR_ERR(scratch);
0710
0711 for_each_engine(engine, gt, id) {
0712 st_engine_heartbeat_disable(engine);
0713
0714 err = __live_lrc_gpr(engine, scratch, false);
0715 if (err)
0716 goto err;
0717
0718 err = __live_lrc_gpr(engine, scratch, true);
0719 if (err)
0720 goto err;
0721
0722 err:
0723 st_engine_heartbeat_enable(engine);
0724 if (igt_flush_test(gt->i915))
0725 err = -EIO;
0726 if (err)
0727 break;
0728 }
0729
0730 i915_vma_unpin_and_release(&scratch, 0);
0731 return err;
0732 }
0733
0734 static struct i915_request *
0735 create_timestamp(struct intel_context *ce, void *slot, int idx)
0736 {
0737 const u32 offset =
0738 i915_ggtt_offset(ce->engine->status_page.vma) +
0739 offset_in_page(slot);
0740 struct i915_request *rq;
0741 u32 *cs;
0742 int err;
0743
0744 rq = intel_context_create_request(ce);
0745 if (IS_ERR(rq))
0746 return rq;
0747
0748 cs = intel_ring_begin(rq, 10);
0749 if (IS_ERR(cs)) {
0750 err = PTR_ERR(cs);
0751 goto err;
0752 }
0753
0754 *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
0755 *cs++ = MI_NOOP;
0756
0757 *cs++ = MI_SEMAPHORE_WAIT |
0758 MI_SEMAPHORE_GLOBAL_GTT |
0759 MI_SEMAPHORE_POLL |
0760 MI_SEMAPHORE_SAD_NEQ_SDD;
0761 *cs++ = 0;
0762 *cs++ = offset;
0763 *cs++ = 0;
0764
0765 *cs++ = MI_STORE_REGISTER_MEM_GEN8 | MI_USE_GGTT;
0766 *cs++ = i915_mmio_reg_offset(RING_CTX_TIMESTAMP(rq->engine->mmio_base));
0767 *cs++ = offset + idx * sizeof(u32);
0768 *cs++ = 0;
0769
0770 intel_ring_advance(rq, cs);
0771
0772 err = 0;
0773 err:
0774 i915_request_get(rq);
0775 i915_request_add(rq);
0776 if (err) {
0777 i915_request_put(rq);
0778 return ERR_PTR(err);
0779 }
0780
0781 return rq;
0782 }
0783
0784 struct lrc_timestamp {
0785 struct intel_engine_cs *engine;
0786 struct intel_context *ce[2];
0787 u32 poison;
0788 };
0789
0790 static bool timestamp_advanced(u32 start, u32 end)
0791 {
0792 return (s32)(end - start) > 0;
0793 }
0794
0795 static int __lrc_timestamp(const struct lrc_timestamp *arg, bool preempt)
0796 {
0797 u32 *slot = memset32(arg->engine->status_page.addr + 1000, 0, 4);
0798 struct i915_request *rq;
0799 u32 timestamp;
0800 int err = 0;
0801
0802 arg->ce[0]->lrc_reg_state[CTX_TIMESTAMP] = arg->poison;
0803 rq = create_timestamp(arg->ce[0], slot, 1);
0804 if (IS_ERR(rq))
0805 return PTR_ERR(rq);
0806
0807 err = wait_for_submit(rq->engine, rq, HZ / 2);
0808 if (err)
0809 goto err;
0810
0811 if (preempt) {
0812 arg->ce[1]->lrc_reg_state[CTX_TIMESTAMP] = 0xdeadbeef;
0813 err = emit_semaphore_signal(arg->ce[1], slot);
0814 if (err)
0815 goto err;
0816 } else {
0817 slot[0] = 1;
0818 wmb();
0819 }
0820
0821
0822 err = context_flush(arg->ce[0], HZ / 2);
0823 if (err)
0824 goto err;
0825
0826 if (!timestamp_advanced(arg->poison, slot[1])) {
0827 pr_err("%s(%s): invalid timestamp on restore, context:%x, request:%x\n",
0828 arg->engine->name, preempt ? "preempt" : "simple",
0829 arg->poison, slot[1]);
0830 err = -EINVAL;
0831 }
0832
0833 timestamp = READ_ONCE(arg->ce[0]->lrc_reg_state[CTX_TIMESTAMP]);
0834 if (!timestamp_advanced(slot[1], timestamp)) {
0835 pr_err("%s(%s): invalid timestamp on save, request:%x, context:%x\n",
0836 arg->engine->name, preempt ? "preempt" : "simple",
0837 slot[1], timestamp);
0838 err = -EINVAL;
0839 }
0840
0841 err:
0842 memset32(slot, -1, 4);
0843 i915_request_put(rq);
0844 return err;
0845 }
0846
0847 static int live_lrc_timestamp(void *arg)
0848 {
0849 struct lrc_timestamp data = {};
0850 struct intel_gt *gt = arg;
0851 enum intel_engine_id id;
0852 const u32 poison[] = {
0853 0,
0854 S32_MAX,
0855 (u32)S32_MAX + 1,
0856 U32_MAX,
0857 };
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868 for_each_engine(data.engine, gt, id) {
0869 int i, err = 0;
0870
0871 st_engine_heartbeat_disable(data.engine);
0872
0873 for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
0874 struct intel_context *tmp;
0875
0876 tmp = intel_context_create(data.engine);
0877 if (IS_ERR(tmp)) {
0878 err = PTR_ERR(tmp);
0879 goto err;
0880 }
0881
0882 err = intel_context_pin(tmp);
0883 if (err) {
0884 intel_context_put(tmp);
0885 goto err;
0886 }
0887
0888 data.ce[i] = tmp;
0889 }
0890
0891 for (i = 0; i < ARRAY_SIZE(poison); i++) {
0892 data.poison = poison[i];
0893
0894 err = __lrc_timestamp(&data, false);
0895 if (err)
0896 break;
0897
0898 err = __lrc_timestamp(&data, true);
0899 if (err)
0900 break;
0901 }
0902
0903 err:
0904 st_engine_heartbeat_enable(data.engine);
0905 for (i = 0; i < ARRAY_SIZE(data.ce); i++) {
0906 if (!data.ce[i])
0907 break;
0908
0909 intel_context_unpin(data.ce[i]);
0910 intel_context_put(data.ce[i]);
0911 }
0912
0913 if (igt_flush_test(gt->i915))
0914 err = -EIO;
0915 if (err)
0916 return err;
0917 }
0918
0919 return 0;
0920 }
0921
0922 static struct i915_vma *
0923 create_user_vma(struct i915_address_space *vm, unsigned long size)
0924 {
0925 struct drm_i915_gem_object *obj;
0926 struct i915_vma *vma;
0927 int err;
0928
0929 obj = i915_gem_object_create_internal(vm->i915, size);
0930 if (IS_ERR(obj))
0931 return ERR_CAST(obj);
0932
0933 vma = i915_vma_instance(obj, vm, NULL);
0934 if (IS_ERR(vma)) {
0935 i915_gem_object_put(obj);
0936 return vma;
0937 }
0938
0939 err = i915_vma_pin(vma, 0, 0, PIN_USER);
0940 if (err) {
0941 i915_gem_object_put(obj);
0942 return ERR_PTR(err);
0943 }
0944
0945 return vma;
0946 }
0947
0948 static u32 safe_poison(u32 offset, u32 poison)
0949 {
0950
0951
0952
0953
0954
0955 if (offset == i915_mmio_reg_offset(RING_PREDICATE_RESULT(0)))
0956 poison &= ~REG_BIT(0);
0957
0958 return poison;
0959 }
0960
0961 static struct i915_vma *
0962 store_context(struct intel_context *ce, struct i915_vma *scratch)
0963 {
0964 struct i915_vma *batch;
0965 u32 dw, x, *cs, *hw;
0966 u32 *defaults;
0967
0968 batch = create_user_vma(ce->vm, SZ_64K);
0969 if (IS_ERR(batch))
0970 return batch;
0971
0972 cs = i915_gem_object_pin_map_unlocked(batch->obj, I915_MAP_WC);
0973 if (IS_ERR(cs)) {
0974 i915_vma_put(batch);
0975 return ERR_CAST(cs);
0976 }
0977
0978 defaults = shmem_pin_map(ce->engine->default_state);
0979 if (!defaults) {
0980 i915_gem_object_unpin_map(batch->obj);
0981 i915_vma_put(batch);
0982 return ERR_PTR(-ENOMEM);
0983 }
0984
0985 x = 0;
0986 dw = 0;
0987 hw = defaults;
0988 hw += LRC_STATE_OFFSET / sizeof(*hw);
0989 do {
0990 u32 len = hw[dw] & 0x7f;
0991
0992 if (hw[dw] == 0) {
0993 dw++;
0994 continue;
0995 }
0996
0997 if ((hw[dw] & GENMASK(31, 23)) != MI_INSTR(0x22, 0)) {
0998 dw += len + 2;
0999 continue;
1000 }
1001
1002 dw++;
1003 len = (len + 1) / 2;
1004 while (len--) {
1005 *cs++ = MI_STORE_REGISTER_MEM_GEN8;
1006 *cs++ = hw[dw];
1007 *cs++ = lower_32_bits(scratch->node.start + x);
1008 *cs++ = upper_32_bits(scratch->node.start + x);
1009
1010 dw += 2;
1011 x += 4;
1012 }
1013 } while (dw < PAGE_SIZE / sizeof(u32) &&
1014 (hw[dw] & ~BIT(0)) != MI_BATCH_BUFFER_END);
1015
1016 *cs++ = MI_BATCH_BUFFER_END;
1017
1018 shmem_unpin_map(ce->engine->default_state, defaults);
1019
1020 i915_gem_object_flush_map(batch->obj);
1021 i915_gem_object_unpin_map(batch->obj);
1022
1023 return batch;
1024 }
1025
1026 static int move_to_active(struct i915_request *rq,
1027 struct i915_vma *vma,
1028 unsigned int flags)
1029 {
1030 int err;
1031
1032 i915_vma_lock(vma);
1033 err = i915_request_await_object(rq, vma->obj, flags);
1034 if (!err)
1035 err = i915_vma_move_to_active(vma, rq, flags);
1036 i915_vma_unlock(vma);
1037
1038 return err;
1039 }
1040
1041 static struct i915_request *
1042 record_registers(struct intel_context *ce,
1043 struct i915_vma *before,
1044 struct i915_vma *after,
1045 u32 *sema)
1046 {
1047 struct i915_vma *b_before, *b_after;
1048 struct i915_request *rq;
1049 u32 *cs;
1050 int err;
1051
1052 b_before = store_context(ce, before);
1053 if (IS_ERR(b_before))
1054 return ERR_CAST(b_before);
1055
1056 b_after = store_context(ce, after);
1057 if (IS_ERR(b_after)) {
1058 rq = ERR_CAST(b_after);
1059 goto err_before;
1060 }
1061
1062 rq = intel_context_create_request(ce);
1063 if (IS_ERR(rq))
1064 goto err_after;
1065
1066 err = move_to_active(rq, before, EXEC_OBJECT_WRITE);
1067 if (err)
1068 goto err_rq;
1069
1070 err = move_to_active(rq, b_before, 0);
1071 if (err)
1072 goto err_rq;
1073
1074 err = move_to_active(rq, after, EXEC_OBJECT_WRITE);
1075 if (err)
1076 goto err_rq;
1077
1078 err = move_to_active(rq, b_after, 0);
1079 if (err)
1080 goto err_rq;
1081
1082 cs = intel_ring_begin(rq, 14);
1083 if (IS_ERR(cs)) {
1084 err = PTR_ERR(cs);
1085 goto err_rq;
1086 }
1087
1088 *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE;
1089 *cs++ = MI_BATCH_BUFFER_START_GEN8 | BIT(8);
1090 *cs++ = lower_32_bits(b_before->node.start);
1091 *cs++ = upper_32_bits(b_before->node.start);
1092
1093 *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
1094 *cs++ = MI_SEMAPHORE_WAIT |
1095 MI_SEMAPHORE_GLOBAL_GTT |
1096 MI_SEMAPHORE_POLL |
1097 MI_SEMAPHORE_SAD_NEQ_SDD;
1098 *cs++ = 0;
1099 *cs++ = i915_ggtt_offset(ce->engine->status_page.vma) +
1100 offset_in_page(sema);
1101 *cs++ = 0;
1102 *cs++ = MI_NOOP;
1103
1104 *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE;
1105 *cs++ = MI_BATCH_BUFFER_START_GEN8 | BIT(8);
1106 *cs++ = lower_32_bits(b_after->node.start);
1107 *cs++ = upper_32_bits(b_after->node.start);
1108
1109 intel_ring_advance(rq, cs);
1110
1111 WRITE_ONCE(*sema, 0);
1112 i915_request_get(rq);
1113 i915_request_add(rq);
1114 err_after:
1115 i915_vma_put(b_after);
1116 err_before:
1117 i915_vma_put(b_before);
1118 return rq;
1119
1120 err_rq:
1121 i915_request_add(rq);
1122 rq = ERR_PTR(err);
1123 goto err_after;
1124 }
1125
1126 static struct i915_vma *load_context(struct intel_context *ce, u32 poison)
1127 {
1128 struct i915_vma *batch;
1129 u32 dw, *cs, *hw;
1130 u32 *defaults;
1131
1132 batch = create_user_vma(ce->vm, SZ_64K);
1133 if (IS_ERR(batch))
1134 return batch;
1135
1136 cs = i915_gem_object_pin_map_unlocked(batch->obj, I915_MAP_WC);
1137 if (IS_ERR(cs)) {
1138 i915_vma_put(batch);
1139 return ERR_CAST(cs);
1140 }
1141
1142 defaults = shmem_pin_map(ce->engine->default_state);
1143 if (!defaults) {
1144 i915_gem_object_unpin_map(batch->obj);
1145 i915_vma_put(batch);
1146 return ERR_PTR(-ENOMEM);
1147 }
1148
1149 dw = 0;
1150 hw = defaults;
1151 hw += LRC_STATE_OFFSET / sizeof(*hw);
1152 do {
1153 u32 len = hw[dw] & 0x7f;
1154
1155 if (hw[dw] == 0) {
1156 dw++;
1157 continue;
1158 }
1159
1160 if ((hw[dw] & GENMASK(31, 23)) != MI_INSTR(0x22, 0)) {
1161 dw += len + 2;
1162 continue;
1163 }
1164
1165 dw++;
1166 len = (len + 1) / 2;
1167 *cs++ = MI_LOAD_REGISTER_IMM(len);
1168 while (len--) {
1169 *cs++ = hw[dw];
1170 *cs++ = safe_poison(hw[dw] & get_lri_mask(ce->engine,
1171 MI_LRI_LRM_CS_MMIO),
1172 poison);
1173 dw += 2;
1174 }
1175 } while (dw < PAGE_SIZE / sizeof(u32) &&
1176 (hw[dw] & ~BIT(0)) != MI_BATCH_BUFFER_END);
1177
1178 *cs++ = MI_BATCH_BUFFER_END;
1179
1180 shmem_unpin_map(ce->engine->default_state, defaults);
1181
1182 i915_gem_object_flush_map(batch->obj);
1183 i915_gem_object_unpin_map(batch->obj);
1184
1185 return batch;
1186 }
1187
1188 static int poison_registers(struct intel_context *ce, u32 poison, u32 *sema)
1189 {
1190 struct i915_request *rq;
1191 struct i915_vma *batch;
1192 u32 *cs;
1193 int err;
1194
1195 batch = load_context(ce, poison);
1196 if (IS_ERR(batch))
1197 return PTR_ERR(batch);
1198
1199 rq = intel_context_create_request(ce);
1200 if (IS_ERR(rq)) {
1201 err = PTR_ERR(rq);
1202 goto err_batch;
1203 }
1204
1205 err = move_to_active(rq, batch, 0);
1206 if (err)
1207 goto err_rq;
1208
1209 cs = intel_ring_begin(rq, 8);
1210 if (IS_ERR(cs)) {
1211 err = PTR_ERR(cs);
1212 goto err_rq;
1213 }
1214
1215 *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE;
1216 *cs++ = MI_BATCH_BUFFER_START_GEN8 | BIT(8);
1217 *cs++ = lower_32_bits(batch->node.start);
1218 *cs++ = upper_32_bits(batch->node.start);
1219
1220 *cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
1221 *cs++ = i915_ggtt_offset(ce->engine->status_page.vma) +
1222 offset_in_page(sema);
1223 *cs++ = 0;
1224 *cs++ = 1;
1225
1226 intel_ring_advance(rq, cs);
1227
1228 rq->sched.attr.priority = I915_PRIORITY_BARRIER;
1229 err_rq:
1230 i915_request_add(rq);
1231 err_batch:
1232 i915_vma_put(batch);
1233 return err;
1234 }
1235
1236 static bool is_moving(u32 a, u32 b)
1237 {
1238 return a != b;
1239 }
1240
1241 static int compare_isolation(struct intel_engine_cs *engine,
1242 struct i915_vma *ref[2],
1243 struct i915_vma *result[2],
1244 struct intel_context *ce,
1245 u32 poison)
1246 {
1247 u32 x, dw, *hw, *lrc;
1248 u32 *A[2], *B[2];
1249 u32 *defaults;
1250 int err = 0;
1251
1252 A[0] = i915_gem_object_pin_map_unlocked(ref[0]->obj, I915_MAP_WC);
1253 if (IS_ERR(A[0]))
1254 return PTR_ERR(A[0]);
1255
1256 A[1] = i915_gem_object_pin_map_unlocked(ref[1]->obj, I915_MAP_WC);
1257 if (IS_ERR(A[1])) {
1258 err = PTR_ERR(A[1]);
1259 goto err_A0;
1260 }
1261
1262 B[0] = i915_gem_object_pin_map_unlocked(result[0]->obj, I915_MAP_WC);
1263 if (IS_ERR(B[0])) {
1264 err = PTR_ERR(B[0]);
1265 goto err_A1;
1266 }
1267
1268 B[1] = i915_gem_object_pin_map_unlocked(result[1]->obj, I915_MAP_WC);
1269 if (IS_ERR(B[1])) {
1270 err = PTR_ERR(B[1]);
1271 goto err_B0;
1272 }
1273
1274 lrc = i915_gem_object_pin_map_unlocked(ce->state->obj,
1275 i915_coherent_map_type(engine->i915,
1276 ce->state->obj,
1277 false));
1278 if (IS_ERR(lrc)) {
1279 err = PTR_ERR(lrc);
1280 goto err_B1;
1281 }
1282 lrc += LRC_STATE_OFFSET / sizeof(*hw);
1283
1284 defaults = shmem_pin_map(ce->engine->default_state);
1285 if (!defaults) {
1286 err = -ENOMEM;
1287 goto err_lrc;
1288 }
1289
1290 x = 0;
1291 dw = 0;
1292 hw = defaults;
1293 hw += LRC_STATE_OFFSET / sizeof(*hw);
1294 do {
1295 u32 len = hw[dw] & 0x7f;
1296
1297 if (hw[dw] == 0) {
1298 dw++;
1299 continue;
1300 }
1301
1302 if ((hw[dw] & GENMASK(31, 23)) != MI_INSTR(0x22, 0)) {
1303 dw += len + 2;
1304 continue;
1305 }
1306
1307 dw++;
1308 len = (len + 1) / 2;
1309 while (len--) {
1310 if (!is_moving(A[0][x], A[1][x]) &&
1311 (A[0][x] != B[0][x] || A[1][x] != B[1][x])) {
1312 switch (hw[dw] & 4095) {
1313 case 0x30:
1314 case 0x34:
1315 break;
1316
1317 default:
1318 pr_err("%s[%d]: Mismatch for register %4x, default %08x, reference %08x, result (%08x, %08x), poison %08x, context %08x\n",
1319 engine->name, dw,
1320 hw[dw], hw[dw + 1],
1321 A[0][x], B[0][x], B[1][x],
1322 poison, lrc[dw + 1]);
1323 err = -EINVAL;
1324 }
1325 }
1326 dw += 2;
1327 x++;
1328 }
1329 } while (dw < PAGE_SIZE / sizeof(u32) &&
1330 (hw[dw] & ~BIT(0)) != MI_BATCH_BUFFER_END);
1331
1332 shmem_unpin_map(ce->engine->default_state, defaults);
1333 err_lrc:
1334 i915_gem_object_unpin_map(ce->state->obj);
1335 err_B1:
1336 i915_gem_object_unpin_map(result[1]->obj);
1337 err_B0:
1338 i915_gem_object_unpin_map(result[0]->obj);
1339 err_A1:
1340 i915_gem_object_unpin_map(ref[1]->obj);
1341 err_A0:
1342 i915_gem_object_unpin_map(ref[0]->obj);
1343 return err;
1344 }
1345
1346 static int __lrc_isolation(struct intel_engine_cs *engine, u32 poison)
1347 {
1348 u32 *sema = memset32(engine->status_page.addr + 1000, 0, 1);
1349 struct i915_vma *ref[2], *result[2];
1350 struct intel_context *A, *B;
1351 struct i915_request *rq;
1352 int err;
1353
1354 A = intel_context_create(engine);
1355 if (IS_ERR(A))
1356 return PTR_ERR(A);
1357
1358 B = intel_context_create(engine);
1359 if (IS_ERR(B)) {
1360 err = PTR_ERR(B);
1361 goto err_A;
1362 }
1363
1364 ref[0] = create_user_vma(A->vm, SZ_64K);
1365 if (IS_ERR(ref[0])) {
1366 err = PTR_ERR(ref[0]);
1367 goto err_B;
1368 }
1369
1370 ref[1] = create_user_vma(A->vm, SZ_64K);
1371 if (IS_ERR(ref[1])) {
1372 err = PTR_ERR(ref[1]);
1373 goto err_ref0;
1374 }
1375
1376 rq = record_registers(A, ref[0], ref[1], sema);
1377 if (IS_ERR(rq)) {
1378 err = PTR_ERR(rq);
1379 goto err_ref1;
1380 }
1381
1382 WRITE_ONCE(*sema, 1);
1383 wmb();
1384
1385 if (i915_request_wait(rq, 0, HZ / 2) < 0) {
1386 i915_request_put(rq);
1387 err = -ETIME;
1388 goto err_ref1;
1389 }
1390 i915_request_put(rq);
1391
1392 result[0] = create_user_vma(A->vm, SZ_64K);
1393 if (IS_ERR(result[0])) {
1394 err = PTR_ERR(result[0]);
1395 goto err_ref1;
1396 }
1397
1398 result[1] = create_user_vma(A->vm, SZ_64K);
1399 if (IS_ERR(result[1])) {
1400 err = PTR_ERR(result[1]);
1401 goto err_result0;
1402 }
1403
1404 rq = record_registers(A, result[0], result[1], sema);
1405 if (IS_ERR(rq)) {
1406 err = PTR_ERR(rq);
1407 goto err_result1;
1408 }
1409
1410 err = poison_registers(B, poison, sema);
1411 if (err) {
1412 WRITE_ONCE(*sema, -1);
1413 i915_request_put(rq);
1414 goto err_result1;
1415 }
1416
1417 if (i915_request_wait(rq, 0, HZ / 2) < 0) {
1418 i915_request_put(rq);
1419 err = -ETIME;
1420 goto err_result1;
1421 }
1422 i915_request_put(rq);
1423
1424 err = compare_isolation(engine, ref, result, A, poison);
1425
1426 err_result1:
1427 i915_vma_put(result[1]);
1428 err_result0:
1429 i915_vma_put(result[0]);
1430 err_ref1:
1431 i915_vma_put(ref[1]);
1432 err_ref0:
1433 i915_vma_put(ref[0]);
1434 err_B:
1435 intel_context_put(B);
1436 err_A:
1437 intel_context_put(A);
1438 return err;
1439 }
1440
1441 static bool skip_isolation(const struct intel_engine_cs *engine)
1442 {
1443 if (engine->class == COPY_ENGINE_CLASS && GRAPHICS_VER(engine->i915) == 9)
1444 return true;
1445
1446 if (engine->class == RENDER_CLASS && GRAPHICS_VER(engine->i915) == 11)
1447 return true;
1448
1449 return false;
1450 }
1451
1452 static int live_lrc_isolation(void *arg)
1453 {
1454 struct intel_gt *gt = arg;
1455 struct intel_engine_cs *engine;
1456 enum intel_engine_id id;
1457 const u32 poison[] = {
1458 STACK_MAGIC,
1459 0x3a3a3a3a,
1460 0x5c5c5c5c,
1461 0xffffffff,
1462 0xffff0000,
1463 };
1464 int err = 0;
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474 for_each_engine(engine, gt, id) {
1475 int i;
1476
1477
1478 if (!IS_ENABLED(CONFIG_DRM_I915_SELFTEST_BROKEN) &&
1479 skip_isolation(engine))
1480 continue;
1481
1482 intel_engine_pm_get(engine);
1483 for (i = 0; i < ARRAY_SIZE(poison); i++) {
1484 int result;
1485
1486 result = __lrc_isolation(engine, poison[i]);
1487 if (result && !err)
1488 err = result;
1489
1490 result = __lrc_isolation(engine, ~poison[i]);
1491 if (result && !err)
1492 err = result;
1493 }
1494 intel_engine_pm_put(engine);
1495 if (igt_flush_test(gt->i915)) {
1496 err = -EIO;
1497 break;
1498 }
1499 }
1500
1501 return err;
1502 }
1503
1504 static int indirect_ctx_submit_req(struct intel_context *ce)
1505 {
1506 struct i915_request *rq;
1507 int err = 0;
1508
1509 rq = intel_context_create_request(ce);
1510 if (IS_ERR(rq))
1511 return PTR_ERR(rq);
1512
1513 i915_request_get(rq);
1514 i915_request_add(rq);
1515
1516 if (i915_request_wait(rq, 0, HZ / 5) < 0)
1517 err = -ETIME;
1518
1519 i915_request_put(rq);
1520
1521 return err;
1522 }
1523
1524 #define CTX_BB_CANARY_OFFSET (3 * 1024)
1525 #define CTX_BB_CANARY_INDEX (CTX_BB_CANARY_OFFSET / sizeof(u32))
1526
1527 static u32 *
1528 emit_indirect_ctx_bb_canary(const struct intel_context *ce, u32 *cs)
1529 {
1530 *cs++ = MI_STORE_REGISTER_MEM_GEN8 |
1531 MI_SRM_LRM_GLOBAL_GTT |
1532 MI_LRI_LRM_CS_MMIO;
1533 *cs++ = i915_mmio_reg_offset(RING_START(0));
1534 *cs++ = i915_ggtt_offset(ce->state) +
1535 context_wa_bb_offset(ce) +
1536 CTX_BB_CANARY_OFFSET;
1537 *cs++ = 0;
1538
1539 return cs;
1540 }
1541
1542 static void
1543 indirect_ctx_bb_setup(struct intel_context *ce)
1544 {
1545 u32 *cs = context_indirect_bb(ce);
1546
1547 cs[CTX_BB_CANARY_INDEX] = 0xdeadf00d;
1548
1549 setup_indirect_ctx_bb(ce, ce->engine, emit_indirect_ctx_bb_canary);
1550 }
1551
1552 static bool check_ring_start(struct intel_context *ce)
1553 {
1554 const u32 * const ctx_bb = (void *)(ce->lrc_reg_state) -
1555 LRC_STATE_OFFSET + context_wa_bb_offset(ce);
1556
1557 if (ctx_bb[CTX_BB_CANARY_INDEX] == ce->lrc_reg_state[CTX_RING_START])
1558 return true;
1559
1560 pr_err("ring start mismatch: canary 0x%08x vs state 0x%08x\n",
1561 ctx_bb[CTX_BB_CANARY_INDEX],
1562 ce->lrc_reg_state[CTX_RING_START]);
1563
1564 return false;
1565 }
1566
1567 static int indirect_ctx_bb_check(struct intel_context *ce)
1568 {
1569 int err;
1570
1571 err = indirect_ctx_submit_req(ce);
1572 if (err)
1573 return err;
1574
1575 if (!check_ring_start(ce))
1576 return -EINVAL;
1577
1578 return 0;
1579 }
1580
1581 static int __live_lrc_indirect_ctx_bb(struct intel_engine_cs *engine)
1582 {
1583 struct intel_context *a, *b;
1584 int err;
1585
1586 a = intel_context_create(engine);
1587 if (IS_ERR(a))
1588 return PTR_ERR(a);
1589 err = intel_context_pin(a);
1590 if (err)
1591 goto put_a;
1592
1593 b = intel_context_create(engine);
1594 if (IS_ERR(b)) {
1595 err = PTR_ERR(b);
1596 goto unpin_a;
1597 }
1598 err = intel_context_pin(b);
1599 if (err)
1600 goto put_b;
1601
1602
1603 if (!a->wa_bb_page) {
1604 GEM_BUG_ON(b->wa_bb_page);
1605 GEM_BUG_ON(GRAPHICS_VER(engine->i915) == 12);
1606 goto unpin_b;
1607 }
1608
1609
1610
1611
1612
1613
1614
1615
1616 indirect_ctx_bb_setup(a);
1617 indirect_ctx_bb_setup(b);
1618
1619 err = indirect_ctx_bb_check(a);
1620 if (err)
1621 goto unpin_b;
1622
1623 err = indirect_ctx_bb_check(b);
1624
1625 unpin_b:
1626 intel_context_unpin(b);
1627 put_b:
1628 intel_context_put(b);
1629 unpin_a:
1630 intel_context_unpin(a);
1631 put_a:
1632 intel_context_put(a);
1633
1634 return err;
1635 }
1636
1637 static int live_lrc_indirect_ctx_bb(void *arg)
1638 {
1639 struct intel_gt *gt = arg;
1640 struct intel_engine_cs *engine;
1641 enum intel_engine_id id;
1642 int err = 0;
1643
1644 for_each_engine(engine, gt, id) {
1645 intel_engine_pm_get(engine);
1646 err = __live_lrc_indirect_ctx_bb(engine);
1647 intel_engine_pm_put(engine);
1648
1649 if (igt_flush_test(gt->i915))
1650 err = -EIO;
1651
1652 if (err)
1653 break;
1654 }
1655
1656 return err;
1657 }
1658
1659 static void garbage_reset(struct intel_engine_cs *engine,
1660 struct i915_request *rq)
1661 {
1662 const unsigned int bit = I915_RESET_ENGINE + engine->id;
1663 unsigned long *lock = &engine->gt->reset.flags;
1664
1665 local_bh_disable();
1666 if (!test_and_set_bit(bit, lock)) {
1667 tasklet_disable(&engine->sched_engine->tasklet);
1668
1669 if (!rq->fence.error)
1670 __intel_engine_reset_bh(engine, NULL);
1671
1672 tasklet_enable(&engine->sched_engine->tasklet);
1673 clear_and_wake_up_bit(bit, lock);
1674 }
1675 local_bh_enable();
1676 }
1677
1678 static struct i915_request *garbage(struct intel_context *ce,
1679 struct rnd_state *prng)
1680 {
1681 struct i915_request *rq;
1682 int err;
1683
1684 err = intel_context_pin(ce);
1685 if (err)
1686 return ERR_PTR(err);
1687
1688 prandom_bytes_state(prng,
1689 ce->lrc_reg_state,
1690 ce->engine->context_size -
1691 LRC_STATE_OFFSET);
1692
1693 rq = intel_context_create_request(ce);
1694 if (IS_ERR(rq)) {
1695 err = PTR_ERR(rq);
1696 goto err_unpin;
1697 }
1698
1699 i915_request_get(rq);
1700 i915_request_add(rq);
1701 return rq;
1702
1703 err_unpin:
1704 intel_context_unpin(ce);
1705 return ERR_PTR(err);
1706 }
1707
1708 static int __lrc_garbage(struct intel_engine_cs *engine, struct rnd_state *prng)
1709 {
1710 struct intel_context *ce;
1711 struct i915_request *hang;
1712 int err = 0;
1713
1714 ce = intel_context_create(engine);
1715 if (IS_ERR(ce))
1716 return PTR_ERR(ce);
1717
1718 hang = garbage(ce, prng);
1719 if (IS_ERR(hang)) {
1720 err = PTR_ERR(hang);
1721 goto err_ce;
1722 }
1723
1724 if (wait_for_submit(engine, hang, HZ / 2)) {
1725 i915_request_put(hang);
1726 err = -ETIME;
1727 goto err_ce;
1728 }
1729
1730 intel_context_set_banned(ce);
1731 garbage_reset(engine, hang);
1732
1733 intel_engine_flush_submission(engine);
1734 if (!hang->fence.error) {
1735 i915_request_put(hang);
1736 pr_err("%s: corrupted context was not reset\n",
1737 engine->name);
1738 err = -EINVAL;
1739 goto err_ce;
1740 }
1741
1742 if (i915_request_wait(hang, 0, HZ / 2) < 0) {
1743 pr_err("%s: corrupted context did not recover\n",
1744 engine->name);
1745 i915_request_put(hang);
1746 err = -EIO;
1747 goto err_ce;
1748 }
1749 i915_request_put(hang);
1750
1751 err_ce:
1752 intel_context_put(ce);
1753 return err;
1754 }
1755
1756 static int live_lrc_garbage(void *arg)
1757 {
1758 struct intel_gt *gt = arg;
1759 struct intel_engine_cs *engine;
1760 enum intel_engine_id id;
1761
1762
1763
1764
1765
1766
1767 if (!IS_ENABLED(CONFIG_DRM_I915_SELFTEST_BROKEN))
1768 return 0;
1769
1770 for_each_engine(engine, gt, id) {
1771 I915_RND_STATE(prng);
1772 int err = 0, i;
1773
1774 if (!intel_has_reset_engine(engine->gt))
1775 continue;
1776
1777 intel_engine_pm_get(engine);
1778 for (i = 0; i < 3; i++) {
1779 err = __lrc_garbage(engine, &prng);
1780 if (err)
1781 break;
1782 }
1783 intel_engine_pm_put(engine);
1784
1785 if (igt_flush_test(gt->i915))
1786 err = -EIO;
1787 if (err)
1788 return err;
1789 }
1790
1791 return 0;
1792 }
1793
1794 static int __live_pphwsp_runtime(struct intel_engine_cs *engine)
1795 {
1796 struct intel_context *ce;
1797 struct i915_request *rq;
1798 IGT_TIMEOUT(end_time);
1799 int err;
1800
1801 ce = intel_context_create(engine);
1802 if (IS_ERR(ce))
1803 return PTR_ERR(ce);
1804
1805 ce->stats.runtime.num_underflow = 0;
1806 ce->stats.runtime.max_underflow = 0;
1807
1808 do {
1809 unsigned int loop = 1024;
1810
1811 while (loop) {
1812 rq = intel_context_create_request(ce);
1813 if (IS_ERR(rq)) {
1814 err = PTR_ERR(rq);
1815 goto err_rq;
1816 }
1817
1818 if (--loop == 0)
1819 i915_request_get(rq);
1820
1821 i915_request_add(rq);
1822 }
1823
1824 if (__igt_timeout(end_time, NULL))
1825 break;
1826
1827 i915_request_put(rq);
1828 } while (1);
1829
1830 err = i915_request_wait(rq, 0, HZ / 5);
1831 if (err < 0) {
1832 pr_err("%s: request not completed!\n", engine->name);
1833 goto err_wait;
1834 }
1835
1836 igt_flush_test(engine->i915);
1837
1838 pr_info("%s: pphwsp runtime %lluns, average %lluns\n",
1839 engine->name,
1840 intel_context_get_total_runtime_ns(ce),
1841 intel_context_get_avg_runtime_ns(ce));
1842
1843 err = 0;
1844 if (ce->stats.runtime.num_underflow) {
1845 pr_err("%s: pphwsp underflow %u time(s), max %u cycles!\n",
1846 engine->name,
1847 ce->stats.runtime.num_underflow,
1848 ce->stats.runtime.max_underflow);
1849 GEM_TRACE_DUMP();
1850 err = -EOVERFLOW;
1851 }
1852
1853 err_wait:
1854 i915_request_put(rq);
1855 err_rq:
1856 intel_context_put(ce);
1857 return err;
1858 }
1859
1860 static int live_pphwsp_runtime(void *arg)
1861 {
1862 struct intel_gt *gt = arg;
1863 struct intel_engine_cs *engine;
1864 enum intel_engine_id id;
1865 int err = 0;
1866
1867
1868
1869
1870
1871
1872 for_each_engine(engine, gt, id) {
1873 err = __live_pphwsp_runtime(engine);
1874 if (err)
1875 break;
1876 }
1877
1878 if (igt_flush_test(gt->i915))
1879 err = -EIO;
1880
1881 return err;
1882 }
1883
1884 int intel_lrc_live_selftests(struct drm_i915_private *i915)
1885 {
1886 static const struct i915_subtest tests[] = {
1887 SUBTEST(live_lrc_layout),
1888 SUBTEST(live_lrc_fixed),
1889 SUBTEST(live_lrc_state),
1890 SUBTEST(live_lrc_gpr),
1891 SUBTEST(live_lrc_isolation),
1892 SUBTEST(live_lrc_timestamp),
1893 SUBTEST(live_lrc_garbage),
1894 SUBTEST(live_pphwsp_runtime),
1895 SUBTEST(live_lrc_indirect_ctx_bb),
1896 };
1897
1898 if (!HAS_LOGICAL_RING_CONTEXTS(i915))
1899 return 0;
1900
1901 return intel_gt_live_subtests(tests, to_gt(i915));
1902 }