1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright © 2017 Intel Corporation 5 */ 6 7 #include <linux/prime_numbers.h> 8 9 #include "gem/i915_gem_pm.h" 10 #include "gt/intel_gt.h" 11 #include "gt/intel_reset.h" 12 #include "i915_selftest.h" 13 14 #include "gem/selftests/igt_gem_utils.h" 15 #include "selftests/i915_random.h" 16 #include "selftests/igt_flush_test.h" 17 #include "selftests/igt_live_test.h" 18 #include "selftests/igt_reset.h" 19 #include "selftests/igt_spinner.h" 20 #include "selftests/mock_drm.h" 21 #include "selftests/mock_gem_device.h" 22 23 #include "huge_gem_object.h" 24 #include "igt_gem_utils.h" 25 26 #define DW_PER_PAGE (PAGE_SIZE / sizeof(u32)) 27 28 static int live_nop_switch(void *arg) 29 { 30 const unsigned int nctx = 1024; 31 struct drm_i915_private *i915 = arg; 32 struct intel_engine_cs *engine; 33 struct i915_gem_context **ctx; 34 enum intel_engine_id id; 35 struct igt_live_test t; 36 struct drm_file *file; 37 unsigned long n; 38 int err = -ENODEV; 39 40 /* 41 * Create as many contexts as we can feasibly get away with 42 * and check we can switch between them rapidly. 43 * 44 * Serves as very simple stress test for submission and HW switching 45 * between contexts. 46 */ 47 48 if (!DRIVER_CAPS(i915)->has_logical_contexts) 49 return 0; 50 51 file = mock_file(i915); 52 if (IS_ERR(file)) 53 return PTR_ERR(file); 54 55 mutex_lock(&i915->drm.struct_mutex); 56 57 ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL); 58 if (!ctx) { 59 err = -ENOMEM; 60 goto out_unlock; 61 } 62 63 for (n = 0; n < nctx; n++) { 64 ctx[n] = live_context(i915, file); 65 if (IS_ERR(ctx[n])) { 66 err = PTR_ERR(ctx[n]); 67 goto out_unlock; 68 } 69 } 70 71 for_each_engine(engine, i915, id) { 72 struct i915_request *rq; 73 unsigned long end_time, prime; 74 ktime_t times[2] = {}; 75 76 times[0] = ktime_get_raw(); 77 for (n = 0; n < nctx; n++) { 78 rq = igt_request_alloc(ctx[n], engine); 79 if (IS_ERR(rq)) { 80 err = PTR_ERR(rq); 81 goto out_unlock; 82 } 83 i915_request_add(rq); 84 } 85 if (i915_request_wait(rq, 0, HZ / 5) < 0) { 86 pr_err("Failed to populated %d contexts\n", nctx); 87 intel_gt_set_wedged(&i915->gt); 88 err = -EIO; 89 goto out_unlock; 90 } 91 92 times[1] = ktime_get_raw(); 93 94 pr_info("Populated %d contexts on %s in %lluns\n", 95 nctx, engine->name, ktime_to_ns(times[1] - times[0])); 96 97 err = igt_live_test_begin(&t, i915, __func__, engine->name); 98 if (err) 99 goto out_unlock; 100 101 end_time = jiffies + i915_selftest.timeout_jiffies; 102 for_each_prime_number_from(prime, 2, 8192) { 103 times[1] = ktime_get_raw(); 104 105 for (n = 0; n < prime; n++) { 106 rq = igt_request_alloc(ctx[n % nctx], engine); 107 if (IS_ERR(rq)) { 108 err = PTR_ERR(rq); 109 goto out_unlock; 110 } 111 112 /* 113 * This space is left intentionally blank. 114 * 115 * We do not actually want to perform any 116 * action with this request, we just want 117 * to measure the latency in allocation 118 * and submission of our breadcrumbs - 119 * ensuring that the bare request is sufficient 120 * for the system to work (i.e. proper HEAD 121 * tracking of the rings, interrupt handling, 122 * etc). It also gives us the lowest bounds 123 * for latency. 124 */ 125 126 i915_request_add(rq); 127 } 128 if (i915_request_wait(rq, 0, HZ / 5) < 0) { 129 pr_err("Switching between %ld contexts timed out\n", 130 prime); 131 intel_gt_set_wedged(&i915->gt); 132 break; 133 } 134 135 times[1] = ktime_sub(ktime_get_raw(), times[1]); 136 if (prime == 2) 137 times[0] = times[1]; 138 139 if (__igt_timeout(end_time, NULL)) 140 break; 141 } 142 143 err = igt_live_test_end(&t); 144 if (err) 145 goto out_unlock; 146 147 pr_info("Switch latencies on %s: 1 = %lluns, %lu = %lluns\n", 148 engine->name, 149 ktime_to_ns(times[0]), 150 prime - 1, div64_u64(ktime_to_ns(times[1]), prime - 1)); 151 } 152 153 out_unlock: 154 mutex_unlock(&i915->drm.struct_mutex); 155 mock_file_free(i915, file); 156 return err; 157 } 158 159 static struct i915_vma * 160 gpu_fill_dw(struct i915_vma *vma, u64 offset, unsigned long count, u32 value) 161 { 162 struct drm_i915_gem_object *obj; 163 const int gen = INTEL_GEN(vma->vm->i915); 164 unsigned long n, size; 165 u32 *cmd; 166 int err; 167 168 size = (4 * count + 1) * sizeof(u32); 169 size = round_up(size, PAGE_SIZE); 170 obj = i915_gem_object_create_internal(vma->vm->i915, size); 171 if (IS_ERR(obj)) 172 return ERR_CAST(obj); 173 174 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); 175 if (IS_ERR(cmd)) { 176 err = PTR_ERR(cmd); 177 goto err; 178 } 179 180 GEM_BUG_ON(offset + (count - 1) * PAGE_SIZE > vma->node.size); 181 offset += vma->node.start; 182 183 for (n = 0; n < count; n++) { 184 if (gen >= 8) { 185 *cmd++ = MI_STORE_DWORD_IMM_GEN4; 186 *cmd++ = lower_32_bits(offset); 187 *cmd++ = upper_32_bits(offset); 188 *cmd++ = value; 189 } else if (gen >= 4) { 190 *cmd++ = MI_STORE_DWORD_IMM_GEN4 | 191 (gen < 6 ? MI_USE_GGTT : 0); 192 *cmd++ = 0; 193 *cmd++ = offset; 194 *cmd++ = value; 195 } else { 196 *cmd++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL; 197 *cmd++ = offset; 198 *cmd++ = value; 199 } 200 offset += PAGE_SIZE; 201 } 202 *cmd = MI_BATCH_BUFFER_END; 203 i915_gem_object_flush_map(obj); 204 i915_gem_object_unpin_map(obj); 205 206 vma = i915_vma_instance(obj, vma->vm, NULL); 207 if (IS_ERR(vma)) { 208 err = PTR_ERR(vma); 209 goto err; 210 } 211 212 err = i915_vma_pin(vma, 0, 0, PIN_USER); 213 if (err) 214 goto err; 215 216 return vma; 217 218 err: 219 i915_gem_object_put(obj); 220 return ERR_PTR(err); 221 } 222 223 static unsigned long real_page_count(struct drm_i915_gem_object *obj) 224 { 225 return huge_gem_object_phys_size(obj) >> PAGE_SHIFT; 226 } 227 228 static unsigned long fake_page_count(struct drm_i915_gem_object *obj) 229 { 230 return huge_gem_object_dma_size(obj) >> PAGE_SHIFT; 231 } 232 233 static int gpu_fill(struct drm_i915_gem_object *obj, 234 struct i915_gem_context *ctx, 235 struct intel_engine_cs *engine, 236 unsigned int dw) 237 { 238 struct i915_address_space *vm = ctx->vm ?: &engine->gt->ggtt->vm; 239 struct i915_request *rq; 240 struct i915_vma *vma; 241 struct i915_vma *batch; 242 unsigned int flags; 243 int err; 244 245 GEM_BUG_ON(obj->base.size > vm->total); 246 GEM_BUG_ON(!intel_engine_can_store_dword(engine)); 247 248 vma = i915_vma_instance(obj, vm, NULL); 249 if (IS_ERR(vma)) 250 return PTR_ERR(vma); 251 252 i915_gem_object_lock(obj); 253 err = i915_gem_object_set_to_gtt_domain(obj, false); 254 i915_gem_object_unlock(obj); 255 if (err) 256 return err; 257 258 err = i915_vma_pin(vma, 0, 0, PIN_HIGH | PIN_USER); 259 if (err) 260 return err; 261 262 /* Within the GTT the huge objects maps every page onto 263 * its 1024 real pages (using phys_pfn = dma_pfn % 1024). 264 * We set the nth dword within the page using the nth 265 * mapping via the GTT - this should exercise the GTT mapping 266 * whilst checking that each context provides a unique view 267 * into the object. 268 */ 269 batch = gpu_fill_dw(vma, 270 (dw * real_page_count(obj)) << PAGE_SHIFT | 271 (dw * sizeof(u32)), 272 real_page_count(obj), 273 dw); 274 if (IS_ERR(batch)) { 275 err = PTR_ERR(batch); 276 goto err_vma; 277 } 278 279 rq = igt_request_alloc(ctx, engine); 280 if (IS_ERR(rq)) { 281 err = PTR_ERR(rq); 282 goto err_batch; 283 } 284 285 flags = 0; 286 if (INTEL_GEN(vm->i915) <= 5) 287 flags |= I915_DISPATCH_SECURE; 288 289 err = engine->emit_bb_start(rq, 290 batch->node.start, batch->node.size, 291 flags); 292 if (err) 293 goto err_request; 294 295 i915_vma_lock(batch); 296 err = i915_vma_move_to_active(batch, rq, 0); 297 i915_vma_unlock(batch); 298 if (err) 299 goto skip_request; 300 301 i915_vma_lock(vma); 302 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); 303 i915_vma_unlock(vma); 304 if (err) 305 goto skip_request; 306 307 i915_request_add(rq); 308 309 i915_vma_unpin(batch); 310 i915_vma_close(batch); 311 i915_vma_put(batch); 312 313 i915_vma_unpin(vma); 314 315 return 0; 316 317 skip_request: 318 i915_request_skip(rq, err); 319 err_request: 320 i915_request_add(rq); 321 err_batch: 322 i915_vma_unpin(batch); 323 i915_vma_put(batch); 324 err_vma: 325 i915_vma_unpin(vma); 326 return err; 327 } 328 329 static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) 330 { 331 const bool has_llc = HAS_LLC(to_i915(obj->base.dev)); 332 unsigned int n, m, need_flush; 333 int err; 334 335 err = i915_gem_object_prepare_write(obj, &need_flush); 336 if (err) 337 return err; 338 339 for (n = 0; n < real_page_count(obj); n++) { 340 u32 *map; 341 342 map = kmap_atomic(i915_gem_object_get_page(obj, n)); 343 for (m = 0; m < DW_PER_PAGE; m++) 344 map[m] = value; 345 if (!has_llc) 346 drm_clflush_virt_range(map, PAGE_SIZE); 347 kunmap_atomic(map); 348 } 349 350 i915_gem_object_finish_access(obj); 351 obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; 352 obj->write_domain = 0; 353 return 0; 354 } 355 356 static noinline int cpu_check(struct drm_i915_gem_object *obj, 357 unsigned int idx, unsigned int max) 358 { 359 unsigned int n, m, needs_flush; 360 int err; 361 362 err = i915_gem_object_prepare_read(obj, &needs_flush); 363 if (err) 364 return err; 365 366 for (n = 0; n < real_page_count(obj); n++) { 367 u32 *map; 368 369 map = kmap_atomic(i915_gem_object_get_page(obj, n)); 370 if (needs_flush & CLFLUSH_BEFORE) 371 drm_clflush_virt_range(map, PAGE_SIZE); 372 373 for (m = 0; m < max; m++) { 374 if (map[m] != m) { 375 pr_err("%pS: Invalid value at object %d page %d/%ld, offset %d/%d: found %x expected %x\n", 376 __builtin_return_address(0), idx, 377 n, real_page_count(obj), m, max, 378 map[m], m); 379 err = -EINVAL; 380 goto out_unmap; 381 } 382 } 383 384 for (; m < DW_PER_PAGE; m++) { 385 if (map[m] != STACK_MAGIC) { 386 pr_err("%pS: Invalid value at object %d page %d, offset %d: found %x expected %x (uninitialised)\n", 387 __builtin_return_address(0), idx, n, m, 388 map[m], STACK_MAGIC); 389 err = -EINVAL; 390 goto out_unmap; 391 } 392 } 393 394 out_unmap: 395 kunmap_atomic(map); 396 if (err) 397 break; 398 } 399 400 i915_gem_object_finish_access(obj); 401 return err; 402 } 403 404 static int file_add_object(struct drm_file *file, 405 struct drm_i915_gem_object *obj) 406 { 407 int err; 408 409 GEM_BUG_ON(obj->base.handle_count); 410 411 /* tie the object to the drm_file for easy reaping */ 412 err = idr_alloc(&file->object_idr, &obj->base, 1, 0, GFP_KERNEL); 413 if (err < 0) 414 return err; 415 416 i915_gem_object_get(obj); 417 obj->base.handle_count++; 418 return 0; 419 } 420 421 static struct drm_i915_gem_object * 422 create_test_object(struct i915_gem_context *ctx, 423 struct drm_file *file, 424 struct list_head *objects) 425 { 426 struct drm_i915_gem_object *obj; 427 struct i915_address_space *vm = ctx->vm ?: &ctx->i915->ggtt.vm; 428 u64 size; 429 int err; 430 431 /* Keep in GEM's good graces */ 432 i915_retire_requests(ctx->i915); 433 434 size = min(vm->total / 2, 1024ull * DW_PER_PAGE * PAGE_SIZE); 435 size = round_down(size, DW_PER_PAGE * PAGE_SIZE); 436 437 obj = huge_gem_object(ctx->i915, DW_PER_PAGE * PAGE_SIZE, size); 438 if (IS_ERR(obj)) 439 return obj; 440 441 err = file_add_object(file, obj); 442 i915_gem_object_put(obj); 443 if (err) 444 return ERR_PTR(err); 445 446 err = cpu_fill(obj, STACK_MAGIC); 447 if (err) { 448 pr_err("Failed to fill object with cpu, err=%d\n", 449 err); 450 return ERR_PTR(err); 451 } 452 453 list_add_tail(&obj->st_link, objects); 454 return obj; 455 } 456 457 static unsigned long max_dwords(struct drm_i915_gem_object *obj) 458 { 459 unsigned long npages = fake_page_count(obj); 460 461 GEM_BUG_ON(!IS_ALIGNED(npages, DW_PER_PAGE)); 462 return npages / DW_PER_PAGE; 463 } 464 465 static int igt_ctx_exec(void *arg) 466 { 467 struct drm_i915_private *i915 = arg; 468 struct intel_engine_cs *engine; 469 enum intel_engine_id id; 470 int err = -ENODEV; 471 472 /* 473 * Create a few different contexts (with different mm) and write 474 * through each ctx/mm using the GPU making sure those writes end 475 * up in the expected pages of our obj. 476 */ 477 478 if (!DRIVER_CAPS(i915)->has_logical_contexts) 479 return 0; 480 481 for_each_engine(engine, i915, id) { 482 struct drm_i915_gem_object *obj = NULL; 483 unsigned long ncontexts, ndwords, dw; 484 struct igt_live_test t; 485 struct drm_file *file; 486 IGT_TIMEOUT(end_time); 487 LIST_HEAD(objects); 488 489 if (!intel_engine_can_store_dword(engine)) 490 continue; 491 492 if (!engine->context_size) 493 continue; /* No logical context support in HW */ 494 495 file = mock_file(i915); 496 if (IS_ERR(file)) 497 return PTR_ERR(file); 498 499 mutex_lock(&i915->drm.struct_mutex); 500 501 err = igt_live_test_begin(&t, i915, __func__, engine->name); 502 if (err) 503 goto out_unlock; 504 505 ncontexts = 0; 506 ndwords = 0; 507 dw = 0; 508 while (!time_after(jiffies, end_time)) { 509 struct i915_gem_context *ctx; 510 511 ctx = live_context(i915, file); 512 if (IS_ERR(ctx)) { 513 err = PTR_ERR(ctx); 514 goto out_unlock; 515 } 516 517 if (!obj) { 518 obj = create_test_object(ctx, file, &objects); 519 if (IS_ERR(obj)) { 520 err = PTR_ERR(obj); 521 goto out_unlock; 522 } 523 } 524 525 err = gpu_fill(obj, ctx, engine, dw); 526 if (err) { 527 pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n", 528 ndwords, dw, max_dwords(obj), 529 engine->name, ctx->hw_id, 530 yesno(!!ctx->vm), err); 531 goto out_unlock; 532 } 533 534 if (++dw == max_dwords(obj)) { 535 obj = NULL; 536 dw = 0; 537 } 538 539 ndwords++; 540 ncontexts++; 541 } 542 543 pr_info("Submitted %lu contexts to %s, filling %lu dwords\n", 544 ncontexts, engine->name, ndwords); 545 546 ncontexts = dw = 0; 547 list_for_each_entry(obj, &objects, st_link) { 548 unsigned int rem = 549 min_t(unsigned int, ndwords - dw, max_dwords(obj)); 550 551 err = cpu_check(obj, ncontexts++, rem); 552 if (err) 553 break; 554 555 dw += rem; 556 } 557 558 out_unlock: 559 if (igt_live_test_end(&t)) 560 err = -EIO; 561 mutex_unlock(&i915->drm.struct_mutex); 562 563 mock_file_free(i915, file); 564 if (err) 565 return err; 566 567 i915_gem_drain_freed_objects(i915); 568 } 569 570 return 0; 571 } 572 573 static int igt_shared_ctx_exec(void *arg) 574 { 575 struct drm_i915_private *i915 = arg; 576 struct i915_gem_context *parent; 577 struct intel_engine_cs *engine; 578 enum intel_engine_id id; 579 struct igt_live_test t; 580 struct drm_file *file; 581 int err = 0; 582 583 /* 584 * Create a few different contexts with the same mm and write 585 * through each ctx using the GPU making sure those writes end 586 * up in the expected pages of our obj. 587 */ 588 if (!DRIVER_CAPS(i915)->has_logical_contexts) 589 return 0; 590 591 file = mock_file(i915); 592 if (IS_ERR(file)) 593 return PTR_ERR(file); 594 595 mutex_lock(&i915->drm.struct_mutex); 596 597 parent = live_context(i915, file); 598 if (IS_ERR(parent)) { 599 err = PTR_ERR(parent); 600 goto out_unlock; 601 } 602 603 if (!parent->vm) { /* not full-ppgtt; nothing to share */ 604 err = 0; 605 goto out_unlock; 606 } 607 608 err = igt_live_test_begin(&t, i915, __func__, ""); 609 if (err) 610 goto out_unlock; 611 612 for_each_engine(engine, i915, id) { 613 unsigned long ncontexts, ndwords, dw; 614 struct drm_i915_gem_object *obj = NULL; 615 IGT_TIMEOUT(end_time); 616 LIST_HEAD(objects); 617 618 if (!intel_engine_can_store_dword(engine)) 619 continue; 620 621 dw = 0; 622 ndwords = 0; 623 ncontexts = 0; 624 while (!time_after(jiffies, end_time)) { 625 struct i915_gem_context *ctx; 626 627 ctx = kernel_context(i915); 628 if (IS_ERR(ctx)) { 629 err = PTR_ERR(ctx); 630 goto out_test; 631 } 632 633 __assign_ppgtt(ctx, parent->vm); 634 635 if (!obj) { 636 obj = create_test_object(parent, file, &objects); 637 if (IS_ERR(obj)) { 638 err = PTR_ERR(obj); 639 kernel_context_close(ctx); 640 goto out_test; 641 } 642 } 643 644 err = gpu_fill(obj, ctx, engine, dw); 645 if (err) { 646 pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n", 647 ndwords, dw, max_dwords(obj), 648 engine->name, ctx->hw_id, 649 yesno(!!ctx->vm), err); 650 kernel_context_close(ctx); 651 goto out_test; 652 } 653 654 if (++dw == max_dwords(obj)) { 655 obj = NULL; 656 dw = 0; 657 } 658 659 ndwords++; 660 ncontexts++; 661 662 kernel_context_close(ctx); 663 } 664 pr_info("Submitted %lu contexts to %s, filling %lu dwords\n", 665 ncontexts, engine->name, ndwords); 666 667 ncontexts = dw = 0; 668 list_for_each_entry(obj, &objects, st_link) { 669 unsigned int rem = 670 min_t(unsigned int, ndwords - dw, max_dwords(obj)); 671 672 err = cpu_check(obj, ncontexts++, rem); 673 if (err) 674 goto out_test; 675 676 dw += rem; 677 } 678 679 mutex_unlock(&i915->drm.struct_mutex); 680 i915_gem_drain_freed_objects(i915); 681 mutex_lock(&i915->drm.struct_mutex); 682 } 683 out_test: 684 if (igt_live_test_end(&t)) 685 err = -EIO; 686 out_unlock: 687 mutex_unlock(&i915->drm.struct_mutex); 688 689 mock_file_free(i915, file); 690 return err; 691 } 692 693 static struct i915_vma *rpcs_query_batch(struct i915_vma *vma) 694 { 695 struct drm_i915_gem_object *obj; 696 u32 *cmd; 697 int err; 698 699 if (INTEL_GEN(vma->vm->i915) < 8) 700 return ERR_PTR(-EINVAL); 701 702 obj = i915_gem_object_create_internal(vma->vm->i915, PAGE_SIZE); 703 if (IS_ERR(obj)) 704 return ERR_CAST(obj); 705 706 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); 707 if (IS_ERR(cmd)) { 708 err = PTR_ERR(cmd); 709 goto err; 710 } 711 712 *cmd++ = MI_STORE_REGISTER_MEM_GEN8; 713 *cmd++ = i915_mmio_reg_offset(GEN8_R_PWR_CLK_STATE); 714 *cmd++ = lower_32_bits(vma->node.start); 715 *cmd++ = upper_32_bits(vma->node.start); 716 *cmd = MI_BATCH_BUFFER_END; 717 718 __i915_gem_object_flush_map(obj, 0, 64); 719 i915_gem_object_unpin_map(obj); 720 721 vma = i915_vma_instance(obj, vma->vm, NULL); 722 if (IS_ERR(vma)) { 723 err = PTR_ERR(vma); 724 goto err; 725 } 726 727 err = i915_vma_pin(vma, 0, 0, PIN_USER); 728 if (err) 729 goto err; 730 731 return vma; 732 733 err: 734 i915_gem_object_put(obj); 735 return ERR_PTR(err); 736 } 737 738 static int 739 emit_rpcs_query(struct drm_i915_gem_object *obj, 740 struct intel_context *ce, 741 struct i915_request **rq_out) 742 { 743 struct i915_request *rq; 744 struct i915_vma *batch; 745 struct i915_vma *vma; 746 int err; 747 748 GEM_BUG_ON(!intel_engine_can_store_dword(ce->engine)); 749 750 vma = i915_vma_instance(obj, ce->vm, NULL); 751 if (IS_ERR(vma)) 752 return PTR_ERR(vma); 753 754 i915_gem_object_lock(obj); 755 err = i915_gem_object_set_to_gtt_domain(obj, false); 756 i915_gem_object_unlock(obj); 757 if (err) 758 return err; 759 760 err = i915_vma_pin(vma, 0, 0, PIN_USER); 761 if (err) 762 return err; 763 764 batch = rpcs_query_batch(vma); 765 if (IS_ERR(batch)) { 766 err = PTR_ERR(batch); 767 goto err_vma; 768 } 769 770 rq = i915_request_create(ce); 771 if (IS_ERR(rq)) { 772 err = PTR_ERR(rq); 773 goto err_batch; 774 } 775 776 err = rq->engine->emit_bb_start(rq, 777 batch->node.start, batch->node.size, 778 0); 779 if (err) 780 goto err_request; 781 782 i915_vma_lock(batch); 783 err = i915_vma_move_to_active(batch, rq, 0); 784 i915_vma_unlock(batch); 785 if (err) 786 goto skip_request; 787 788 i915_vma_lock(vma); 789 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); 790 i915_vma_unlock(vma); 791 if (err) 792 goto skip_request; 793 794 i915_vma_unpin(batch); 795 i915_vma_close(batch); 796 i915_vma_put(batch); 797 798 i915_vma_unpin(vma); 799 800 *rq_out = i915_request_get(rq); 801 802 i915_request_add(rq); 803 804 return 0; 805 806 skip_request: 807 i915_request_skip(rq, err); 808 err_request: 809 i915_request_add(rq); 810 err_batch: 811 i915_vma_unpin(batch); 812 i915_vma_put(batch); 813 err_vma: 814 i915_vma_unpin(vma); 815 816 return err; 817 } 818 819 #define TEST_IDLE BIT(0) 820 #define TEST_BUSY BIT(1) 821 #define TEST_RESET BIT(2) 822 823 static int 824 __sseu_prepare(struct drm_i915_private *i915, 825 const char *name, 826 unsigned int flags, 827 struct intel_context *ce, 828 struct igt_spinner **spin) 829 { 830 struct i915_request *rq; 831 int ret; 832 833 *spin = NULL; 834 if (!(flags & (TEST_BUSY | TEST_RESET))) 835 return 0; 836 837 *spin = kzalloc(sizeof(**spin), GFP_KERNEL); 838 if (!*spin) 839 return -ENOMEM; 840 841 ret = igt_spinner_init(*spin, i915); 842 if (ret) 843 goto err_free; 844 845 rq = igt_spinner_create_request(*spin, 846 ce->gem_context, 847 ce->engine, 848 MI_NOOP); 849 if (IS_ERR(rq)) { 850 ret = PTR_ERR(rq); 851 goto err_fini; 852 } 853 854 i915_request_add(rq); 855 856 if (!igt_wait_for_spinner(*spin, rq)) { 857 pr_err("%s: Spinner failed to start!\n", name); 858 ret = -ETIMEDOUT; 859 goto err_end; 860 } 861 862 return 0; 863 864 err_end: 865 igt_spinner_end(*spin); 866 err_fini: 867 igt_spinner_fini(*spin); 868 err_free: 869 kfree(fetch_and_zero(spin)); 870 return ret; 871 } 872 873 static int 874 __read_slice_count(struct drm_i915_private *i915, 875 struct intel_context *ce, 876 struct drm_i915_gem_object *obj, 877 struct igt_spinner *spin, 878 u32 *rpcs) 879 { 880 struct i915_request *rq = NULL; 881 u32 s_mask, s_shift; 882 unsigned int cnt; 883 u32 *buf, val; 884 long ret; 885 886 ret = emit_rpcs_query(obj, ce, &rq); 887 if (ret) 888 return ret; 889 890 if (spin) 891 igt_spinner_end(spin); 892 893 ret = i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT); 894 i915_request_put(rq); 895 if (ret < 0) 896 return ret; 897 898 buf = i915_gem_object_pin_map(obj, I915_MAP_WB); 899 if (IS_ERR(buf)) { 900 ret = PTR_ERR(buf); 901 return ret; 902 } 903 904 if (INTEL_GEN(i915) >= 11) { 905 s_mask = GEN11_RPCS_S_CNT_MASK; 906 s_shift = GEN11_RPCS_S_CNT_SHIFT; 907 } else { 908 s_mask = GEN8_RPCS_S_CNT_MASK; 909 s_shift = GEN8_RPCS_S_CNT_SHIFT; 910 } 911 912 val = *buf; 913 cnt = (val & s_mask) >> s_shift; 914 *rpcs = val; 915 916 i915_gem_object_unpin_map(obj); 917 918 return cnt; 919 } 920 921 static int 922 __check_rpcs(const char *name, u32 rpcs, int slices, unsigned int expected, 923 const char *prefix, const char *suffix) 924 { 925 if (slices == expected) 926 return 0; 927 928 if (slices < 0) { 929 pr_err("%s: %s read slice count failed with %d%s\n", 930 name, prefix, slices, suffix); 931 return slices; 932 } 933 934 pr_err("%s: %s slice count %d is not %u%s\n", 935 name, prefix, slices, expected, suffix); 936 937 pr_info("RPCS=0x%x; %u%sx%u%s\n", 938 rpcs, slices, 939 (rpcs & GEN8_RPCS_S_CNT_ENABLE) ? "*" : "", 940 (rpcs & GEN8_RPCS_SS_CNT_MASK) >> GEN8_RPCS_SS_CNT_SHIFT, 941 (rpcs & GEN8_RPCS_SS_CNT_ENABLE) ? "*" : ""); 942 943 return -EINVAL; 944 } 945 946 static int 947 __sseu_finish(struct drm_i915_private *i915, 948 const char *name, 949 unsigned int flags, 950 struct intel_context *ce, 951 struct drm_i915_gem_object *obj, 952 unsigned int expected, 953 struct igt_spinner *spin) 954 { 955 unsigned int slices = hweight32(ce->engine->sseu.slice_mask); 956 u32 rpcs = 0; 957 int ret = 0; 958 959 if (flags & TEST_RESET) { 960 ret = intel_engine_reset(ce->engine, "sseu"); 961 if (ret) 962 goto out; 963 } 964 965 ret = __read_slice_count(i915, ce, obj, 966 flags & TEST_RESET ? NULL : spin, &rpcs); 967 ret = __check_rpcs(name, rpcs, ret, expected, "Context", "!"); 968 if (ret) 969 goto out; 970 971 ret = __read_slice_count(i915, ce->engine->kernel_context, obj, 972 NULL, &rpcs); 973 ret = __check_rpcs(name, rpcs, ret, slices, "Kernel context", "!"); 974 975 out: 976 if (spin) 977 igt_spinner_end(spin); 978 979 if ((flags & TEST_IDLE) && ret == 0) { 980 ret = i915_gem_wait_for_idle(i915, 0, MAX_SCHEDULE_TIMEOUT); 981 if (ret) 982 return ret; 983 984 ret = __read_slice_count(i915, ce, obj, NULL, &rpcs); 985 ret = __check_rpcs(name, rpcs, ret, expected, 986 "Context", " after idle!"); 987 } 988 989 return ret; 990 } 991 992 static int 993 __sseu_test(struct drm_i915_private *i915, 994 const char *name, 995 unsigned int flags, 996 struct intel_context *ce, 997 struct drm_i915_gem_object *obj, 998 struct intel_sseu sseu) 999 { 1000 struct igt_spinner *spin = NULL; 1001 int ret; 1002 1003 ret = __sseu_prepare(i915, name, flags, ce, &spin); 1004 if (ret) 1005 return ret; 1006 1007 ret = __intel_context_reconfigure_sseu(ce, sseu); 1008 if (ret) 1009 goto out_spin; 1010 1011 ret = __sseu_finish(i915, name, flags, ce, obj, 1012 hweight32(sseu.slice_mask), spin); 1013 1014 out_spin: 1015 if (spin) { 1016 igt_spinner_end(spin); 1017 igt_spinner_fini(spin); 1018 kfree(spin); 1019 } 1020 return ret; 1021 } 1022 1023 static int 1024 __igt_ctx_sseu(struct drm_i915_private *i915, 1025 const char *name, 1026 unsigned int flags) 1027 { 1028 struct intel_engine_cs *engine = i915->engine[RCS0]; 1029 struct drm_i915_gem_object *obj; 1030 struct i915_gem_context *ctx; 1031 struct intel_context *ce; 1032 struct intel_sseu pg_sseu; 1033 struct drm_file *file; 1034 int ret; 1035 1036 if (INTEL_GEN(i915) < 9 || !engine) 1037 return 0; 1038 1039 if (!RUNTIME_INFO(i915)->sseu.has_slice_pg) 1040 return 0; 1041 1042 if (hweight32(engine->sseu.slice_mask) < 2) 1043 return 0; 1044 1045 /* 1046 * Gen11 VME friendly power-gated configuration with half enabled 1047 * sub-slices. 1048 */ 1049 pg_sseu = engine->sseu; 1050 pg_sseu.slice_mask = 1; 1051 pg_sseu.subslice_mask = 1052 ~(~0 << (hweight32(engine->sseu.subslice_mask) / 2)); 1053 1054 pr_info("SSEU subtest '%s', flags=%x, def_slices=%u, pg_slices=%u\n", 1055 name, flags, hweight32(engine->sseu.slice_mask), 1056 hweight32(pg_sseu.slice_mask)); 1057 1058 file = mock_file(i915); 1059 if (IS_ERR(file)) 1060 return PTR_ERR(file); 1061 1062 if (flags & TEST_RESET) 1063 igt_global_reset_lock(&i915->gt); 1064 1065 mutex_lock(&i915->drm.struct_mutex); 1066 1067 ctx = live_context(i915, file); 1068 if (IS_ERR(ctx)) { 1069 ret = PTR_ERR(ctx); 1070 goto out_unlock; 1071 } 1072 i915_gem_context_clear_bannable(ctx); /* to reset and beyond! */ 1073 1074 obj = i915_gem_object_create_internal(i915, PAGE_SIZE); 1075 if (IS_ERR(obj)) { 1076 ret = PTR_ERR(obj); 1077 goto out_unlock; 1078 } 1079 1080 ce = i915_gem_context_get_engine(ctx, RCS0); 1081 if (IS_ERR(ce)) { 1082 ret = PTR_ERR(ce); 1083 goto out_put; 1084 } 1085 1086 ret = intel_context_pin(ce); 1087 if (ret) 1088 goto out_context; 1089 1090 /* First set the default mask. */ 1091 ret = __sseu_test(i915, name, flags, ce, obj, engine->sseu); 1092 if (ret) 1093 goto out_fail; 1094 1095 /* Then set a power-gated configuration. */ 1096 ret = __sseu_test(i915, name, flags, ce, obj, pg_sseu); 1097 if (ret) 1098 goto out_fail; 1099 1100 /* Back to defaults. */ 1101 ret = __sseu_test(i915, name, flags, ce, obj, engine->sseu); 1102 if (ret) 1103 goto out_fail; 1104 1105 /* One last power-gated configuration for the road. */ 1106 ret = __sseu_test(i915, name, flags, ce, obj, pg_sseu); 1107 if (ret) 1108 goto out_fail; 1109 1110 out_fail: 1111 if (igt_flush_test(i915, I915_WAIT_LOCKED)) 1112 ret = -EIO; 1113 1114 intel_context_unpin(ce); 1115 out_context: 1116 intel_context_put(ce); 1117 out_put: 1118 i915_gem_object_put(obj); 1119 1120 out_unlock: 1121 mutex_unlock(&i915->drm.struct_mutex); 1122 1123 if (flags & TEST_RESET) 1124 igt_global_reset_unlock(&i915->gt); 1125 1126 mock_file_free(i915, file); 1127 1128 if (ret) 1129 pr_err("%s: Failed with %d!\n", name, ret); 1130 1131 return ret; 1132 } 1133 1134 static int igt_ctx_sseu(void *arg) 1135 { 1136 struct { 1137 const char *name; 1138 unsigned int flags; 1139 } *phase, phases[] = { 1140 { .name = "basic", .flags = 0 }, 1141 { .name = "idle", .flags = TEST_IDLE }, 1142 { .name = "busy", .flags = TEST_BUSY }, 1143 { .name = "busy-reset", .flags = TEST_BUSY | TEST_RESET }, 1144 { .name = "busy-idle", .flags = TEST_BUSY | TEST_IDLE }, 1145 { .name = "reset-idle", .flags = TEST_RESET | TEST_IDLE }, 1146 }; 1147 unsigned int i; 1148 int ret = 0; 1149 1150 for (i = 0, phase = phases; ret == 0 && i < ARRAY_SIZE(phases); 1151 i++, phase++) 1152 ret = __igt_ctx_sseu(arg, phase->name, phase->flags); 1153 1154 return ret; 1155 } 1156 1157 static int igt_ctx_readonly(void *arg) 1158 { 1159 struct drm_i915_private *i915 = arg; 1160 struct drm_i915_gem_object *obj = NULL; 1161 struct i915_address_space *vm; 1162 struct i915_gem_context *ctx; 1163 unsigned long idx, ndwords, dw; 1164 struct igt_live_test t; 1165 struct drm_file *file; 1166 I915_RND_STATE(prng); 1167 IGT_TIMEOUT(end_time); 1168 LIST_HEAD(objects); 1169 int err = -ENODEV; 1170 1171 /* 1172 * Create a few read-only objects (with the occasional writable object) 1173 * and try to write into these object checking that the GPU discards 1174 * any write to a read-only object. 1175 */ 1176 1177 file = mock_file(i915); 1178 if (IS_ERR(file)) 1179 return PTR_ERR(file); 1180 1181 mutex_lock(&i915->drm.struct_mutex); 1182 1183 err = igt_live_test_begin(&t, i915, __func__, ""); 1184 if (err) 1185 goto out_unlock; 1186 1187 ctx = live_context(i915, file); 1188 if (IS_ERR(ctx)) { 1189 err = PTR_ERR(ctx); 1190 goto out_unlock; 1191 } 1192 1193 vm = ctx->vm ?: &i915->ggtt.alias->vm; 1194 if (!vm || !vm->has_read_only) { 1195 err = 0; 1196 goto out_unlock; 1197 } 1198 1199 ndwords = 0; 1200 dw = 0; 1201 while (!time_after(jiffies, end_time)) { 1202 struct intel_engine_cs *engine; 1203 unsigned int id; 1204 1205 for_each_engine(engine, i915, id) { 1206 if (!intel_engine_can_store_dword(engine)) 1207 continue; 1208 1209 if (!obj) { 1210 obj = create_test_object(ctx, file, &objects); 1211 if (IS_ERR(obj)) { 1212 err = PTR_ERR(obj); 1213 goto out_unlock; 1214 } 1215 1216 if (prandom_u32_state(&prng) & 1) 1217 i915_gem_object_set_readonly(obj); 1218 } 1219 1220 err = gpu_fill(obj, ctx, engine, dw); 1221 if (err) { 1222 pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n", 1223 ndwords, dw, max_dwords(obj), 1224 engine->name, ctx->hw_id, 1225 yesno(!!ctx->vm), err); 1226 goto out_unlock; 1227 } 1228 1229 if (++dw == max_dwords(obj)) { 1230 obj = NULL; 1231 dw = 0; 1232 } 1233 ndwords++; 1234 } 1235 } 1236 pr_info("Submitted %lu dwords (across %u engines)\n", 1237 ndwords, RUNTIME_INFO(i915)->num_engines); 1238 1239 dw = 0; 1240 idx = 0; 1241 list_for_each_entry(obj, &objects, st_link) { 1242 unsigned int rem = 1243 min_t(unsigned int, ndwords - dw, max_dwords(obj)); 1244 unsigned int num_writes; 1245 1246 num_writes = rem; 1247 if (i915_gem_object_is_readonly(obj)) 1248 num_writes = 0; 1249 1250 err = cpu_check(obj, idx++, num_writes); 1251 if (err) 1252 break; 1253 1254 dw += rem; 1255 } 1256 1257 out_unlock: 1258 if (igt_live_test_end(&t)) 1259 err = -EIO; 1260 mutex_unlock(&i915->drm.struct_mutex); 1261 1262 mock_file_free(i915, file); 1263 return err; 1264 } 1265 1266 static int check_scratch(struct i915_gem_context *ctx, u64 offset) 1267 { 1268 struct drm_mm_node *node = 1269 __drm_mm_interval_first(&ctx->vm->mm, 1270 offset, offset + sizeof(u32) - 1); 1271 if (!node || node->start > offset) 1272 return 0; 1273 1274 GEM_BUG_ON(offset >= node->start + node->size); 1275 1276 pr_err("Target offset 0x%08x_%08x overlaps with a node in the mm!\n", 1277 upper_32_bits(offset), lower_32_bits(offset)); 1278 return -EINVAL; 1279 } 1280 1281 static int write_to_scratch(struct i915_gem_context *ctx, 1282 struct intel_engine_cs *engine, 1283 u64 offset, u32 value) 1284 { 1285 struct drm_i915_private *i915 = ctx->i915; 1286 struct drm_i915_gem_object *obj; 1287 struct i915_request *rq; 1288 struct i915_vma *vma; 1289 u32 *cmd; 1290 int err; 1291 1292 GEM_BUG_ON(offset < I915_GTT_PAGE_SIZE); 1293 1294 obj = i915_gem_object_create_internal(i915, PAGE_SIZE); 1295 if (IS_ERR(obj)) 1296 return PTR_ERR(obj); 1297 1298 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); 1299 if (IS_ERR(cmd)) { 1300 err = PTR_ERR(cmd); 1301 goto err; 1302 } 1303 1304 *cmd++ = MI_STORE_DWORD_IMM_GEN4; 1305 if (INTEL_GEN(i915) >= 8) { 1306 *cmd++ = lower_32_bits(offset); 1307 *cmd++ = upper_32_bits(offset); 1308 } else { 1309 *cmd++ = 0; 1310 *cmd++ = offset; 1311 } 1312 *cmd++ = value; 1313 *cmd = MI_BATCH_BUFFER_END; 1314 __i915_gem_object_flush_map(obj, 0, 64); 1315 i915_gem_object_unpin_map(obj); 1316 1317 vma = i915_vma_instance(obj, ctx->vm, NULL); 1318 if (IS_ERR(vma)) { 1319 err = PTR_ERR(vma); 1320 goto err; 1321 } 1322 1323 err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED); 1324 if (err) 1325 goto err; 1326 1327 err = check_scratch(ctx, offset); 1328 if (err) 1329 goto err_unpin; 1330 1331 rq = igt_request_alloc(ctx, engine); 1332 if (IS_ERR(rq)) { 1333 err = PTR_ERR(rq); 1334 goto err_unpin; 1335 } 1336 1337 err = engine->emit_bb_start(rq, vma->node.start, vma->node.size, 0); 1338 if (err) 1339 goto err_request; 1340 1341 i915_vma_lock(vma); 1342 err = i915_vma_move_to_active(vma, rq, 0); 1343 i915_vma_unlock(vma); 1344 if (err) 1345 goto skip_request; 1346 1347 i915_vma_unpin(vma); 1348 i915_vma_close(vma); 1349 i915_vma_put(vma); 1350 1351 i915_request_add(rq); 1352 1353 return 0; 1354 1355 skip_request: 1356 i915_request_skip(rq, err); 1357 err_request: 1358 i915_request_add(rq); 1359 err_unpin: 1360 i915_vma_unpin(vma); 1361 err: 1362 i915_gem_object_put(obj); 1363 return err; 1364 } 1365 1366 static int read_from_scratch(struct i915_gem_context *ctx, 1367 struct intel_engine_cs *engine, 1368 u64 offset, u32 *value) 1369 { 1370 struct drm_i915_private *i915 = ctx->i915; 1371 struct drm_i915_gem_object *obj; 1372 const u32 RCS_GPR0 = 0x2600; /* not all engines have their own GPR! */ 1373 const u32 result = 0x100; 1374 struct i915_request *rq; 1375 struct i915_vma *vma; 1376 u32 *cmd; 1377 int err; 1378 1379 GEM_BUG_ON(offset < I915_GTT_PAGE_SIZE); 1380 1381 obj = i915_gem_object_create_internal(i915, PAGE_SIZE); 1382 if (IS_ERR(obj)) 1383 return PTR_ERR(obj); 1384 1385 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); 1386 if (IS_ERR(cmd)) { 1387 err = PTR_ERR(cmd); 1388 goto err; 1389 } 1390 1391 memset(cmd, POISON_INUSE, PAGE_SIZE); 1392 if (INTEL_GEN(i915) >= 8) { 1393 *cmd++ = MI_LOAD_REGISTER_MEM_GEN8; 1394 *cmd++ = RCS_GPR0; 1395 *cmd++ = lower_32_bits(offset); 1396 *cmd++ = upper_32_bits(offset); 1397 *cmd++ = MI_STORE_REGISTER_MEM_GEN8; 1398 *cmd++ = RCS_GPR0; 1399 *cmd++ = result; 1400 *cmd++ = 0; 1401 } else { 1402 *cmd++ = MI_LOAD_REGISTER_MEM; 1403 *cmd++ = RCS_GPR0; 1404 *cmd++ = offset; 1405 *cmd++ = MI_STORE_REGISTER_MEM; 1406 *cmd++ = RCS_GPR0; 1407 *cmd++ = result; 1408 } 1409 *cmd = MI_BATCH_BUFFER_END; 1410 1411 i915_gem_object_flush_map(obj); 1412 i915_gem_object_unpin_map(obj); 1413 1414 vma = i915_vma_instance(obj, ctx->vm, NULL); 1415 if (IS_ERR(vma)) { 1416 err = PTR_ERR(vma); 1417 goto err; 1418 } 1419 1420 err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED); 1421 if (err) 1422 goto err; 1423 1424 err = check_scratch(ctx, offset); 1425 if (err) 1426 goto err_unpin; 1427 1428 rq = igt_request_alloc(ctx, engine); 1429 if (IS_ERR(rq)) { 1430 err = PTR_ERR(rq); 1431 goto err_unpin; 1432 } 1433 1434 err = engine->emit_bb_start(rq, vma->node.start, vma->node.size, 0); 1435 if (err) 1436 goto err_request; 1437 1438 i915_vma_lock(vma); 1439 err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); 1440 i915_vma_unlock(vma); 1441 if (err) 1442 goto skip_request; 1443 1444 i915_vma_unpin(vma); 1445 i915_vma_close(vma); 1446 1447 i915_request_add(rq); 1448 1449 i915_gem_object_lock(obj); 1450 err = i915_gem_object_set_to_cpu_domain(obj, false); 1451 i915_gem_object_unlock(obj); 1452 if (err) 1453 goto err; 1454 1455 cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); 1456 if (IS_ERR(cmd)) { 1457 err = PTR_ERR(cmd); 1458 goto err; 1459 } 1460 1461 *value = cmd[result / sizeof(*cmd)]; 1462 i915_gem_object_unpin_map(obj); 1463 i915_gem_object_put(obj); 1464 1465 return 0; 1466 1467 skip_request: 1468 i915_request_skip(rq, err); 1469 err_request: 1470 i915_request_add(rq); 1471 err_unpin: 1472 i915_vma_unpin(vma); 1473 err: 1474 i915_gem_object_put(obj); 1475 return err; 1476 } 1477 1478 static int igt_vm_isolation(void *arg) 1479 { 1480 struct drm_i915_private *i915 = arg; 1481 struct i915_gem_context *ctx_a, *ctx_b; 1482 struct intel_engine_cs *engine; 1483 struct igt_live_test t; 1484 struct drm_file *file; 1485 I915_RND_STATE(prng); 1486 unsigned long count; 1487 unsigned int id; 1488 u64 vm_total; 1489 int err; 1490 1491 if (INTEL_GEN(i915) < 7) 1492 return 0; 1493 1494 /* 1495 * The simple goal here is that a write into one context is not 1496 * observed in a second (separate page tables and scratch). 1497 */ 1498 1499 file = mock_file(i915); 1500 if (IS_ERR(file)) 1501 return PTR_ERR(file); 1502 1503 mutex_lock(&i915->drm.struct_mutex); 1504 1505 err = igt_live_test_begin(&t, i915, __func__, ""); 1506 if (err) 1507 goto out_unlock; 1508 1509 ctx_a = live_context(i915, file); 1510 if (IS_ERR(ctx_a)) { 1511 err = PTR_ERR(ctx_a); 1512 goto out_unlock; 1513 } 1514 1515 ctx_b = live_context(i915, file); 1516 if (IS_ERR(ctx_b)) { 1517 err = PTR_ERR(ctx_b); 1518 goto out_unlock; 1519 } 1520 1521 /* We can only test vm isolation, if the vm are distinct */ 1522 if (ctx_a->vm == ctx_b->vm) 1523 goto out_unlock; 1524 1525 vm_total = ctx_a->vm->total; 1526 GEM_BUG_ON(ctx_b->vm->total != vm_total); 1527 vm_total -= I915_GTT_PAGE_SIZE; 1528 1529 count = 0; 1530 for_each_engine(engine, i915, id) { 1531 IGT_TIMEOUT(end_time); 1532 unsigned long this = 0; 1533 1534 if (!intel_engine_can_store_dword(engine)) 1535 continue; 1536 1537 while (!__igt_timeout(end_time, NULL)) { 1538 u32 value = 0xc5c5c5c5; 1539 u64 offset; 1540 1541 div64_u64_rem(i915_prandom_u64_state(&prng), 1542 vm_total, &offset); 1543 offset = round_down(offset, alignof_dword); 1544 offset += I915_GTT_PAGE_SIZE; 1545 1546 err = write_to_scratch(ctx_a, engine, 1547 offset, 0xdeadbeef); 1548 if (err == 0) 1549 err = read_from_scratch(ctx_b, engine, 1550 offset, &value); 1551 if (err) 1552 goto out_unlock; 1553 1554 if (value) { 1555 pr_err("%s: Read %08x from scratch (offset 0x%08x_%08x), after %lu reads!\n", 1556 engine->name, value, 1557 upper_32_bits(offset), 1558 lower_32_bits(offset), 1559 this); 1560 err = -EINVAL; 1561 goto out_unlock; 1562 } 1563 1564 this++; 1565 } 1566 count += this; 1567 } 1568 pr_info("Checked %lu scratch offsets across %d engines\n", 1569 count, RUNTIME_INFO(i915)->num_engines); 1570 1571 out_unlock: 1572 if (igt_live_test_end(&t)) 1573 err = -EIO; 1574 mutex_unlock(&i915->drm.struct_mutex); 1575 1576 mock_file_free(i915, file); 1577 return err; 1578 } 1579 1580 static __maybe_unused const char * 1581 __engine_name(struct drm_i915_private *i915, intel_engine_mask_t engines) 1582 { 1583 struct intel_engine_cs *engine; 1584 intel_engine_mask_t tmp; 1585 1586 if (engines == ALL_ENGINES) 1587 return "all"; 1588 1589 for_each_engine_masked(engine, i915, engines, tmp) 1590 return engine->name; 1591 1592 return "none"; 1593 } 1594 1595 static bool skip_unused_engines(struct intel_context *ce, void *data) 1596 { 1597 return !ce->state; 1598 } 1599 1600 static void mock_barrier_task(void *data) 1601 { 1602 unsigned int *counter = data; 1603 1604 ++*counter; 1605 } 1606 1607 static int mock_context_barrier(void *arg) 1608 { 1609 #undef pr_fmt 1610 #define pr_fmt(x) "context_barrier_task():" # x 1611 struct drm_i915_private *i915 = arg; 1612 struct i915_gem_context *ctx; 1613 struct i915_request *rq; 1614 unsigned int counter; 1615 int err; 1616 1617 /* 1618 * The context barrier provides us with a callback after it emits 1619 * a request; useful for retiring old state after loading new. 1620 */ 1621 1622 mutex_lock(&i915->drm.struct_mutex); 1623 1624 ctx = mock_context(i915, "mock"); 1625 if (!ctx) { 1626 err = -ENOMEM; 1627 goto unlock; 1628 } 1629 1630 counter = 0; 1631 err = context_barrier_task(ctx, 0, 1632 NULL, NULL, mock_barrier_task, &counter); 1633 if (err) { 1634 pr_err("Failed at line %d, err=%d\n", __LINE__, err); 1635 goto out; 1636 } 1637 if (counter == 0) { 1638 pr_err("Did not retire immediately with 0 engines\n"); 1639 err = -EINVAL; 1640 goto out; 1641 } 1642 1643 counter = 0; 1644 err = context_barrier_task(ctx, ALL_ENGINES, 1645 skip_unused_engines, 1646 NULL, 1647 mock_barrier_task, 1648 &counter); 1649 if (err) { 1650 pr_err("Failed at line %d, err=%d\n", __LINE__, err); 1651 goto out; 1652 } 1653 if (counter == 0) { 1654 pr_err("Did not retire immediately for all unused engines\n"); 1655 err = -EINVAL; 1656 goto out; 1657 } 1658 1659 rq = igt_request_alloc(ctx, i915->engine[RCS0]); 1660 if (IS_ERR(rq)) { 1661 pr_err("Request allocation failed!\n"); 1662 goto out; 1663 } 1664 i915_request_add(rq); 1665 1666 counter = 0; 1667 context_barrier_inject_fault = BIT(RCS0); 1668 err = context_barrier_task(ctx, ALL_ENGINES, 1669 NULL, NULL, mock_barrier_task, &counter); 1670 context_barrier_inject_fault = 0; 1671 if (err == -ENXIO) 1672 err = 0; 1673 else 1674 pr_err("Did not hit fault injection!\n"); 1675 if (counter != 0) { 1676 pr_err("Invoked callback on error!\n"); 1677 err = -EIO; 1678 } 1679 if (err) 1680 goto out; 1681 1682 counter = 0; 1683 err = context_barrier_task(ctx, ALL_ENGINES, 1684 skip_unused_engines, 1685 NULL, 1686 mock_barrier_task, 1687 &counter); 1688 if (err) { 1689 pr_err("Failed at line %d, err=%d\n", __LINE__, err); 1690 goto out; 1691 } 1692 mock_device_flush(i915); 1693 if (counter == 0) { 1694 pr_err("Did not retire on each active engines\n"); 1695 err = -EINVAL; 1696 goto out; 1697 } 1698 1699 out: 1700 mock_context_close(ctx); 1701 unlock: 1702 mutex_unlock(&i915->drm.struct_mutex); 1703 return err; 1704 #undef pr_fmt 1705 #define pr_fmt(x) x 1706 } 1707 1708 int i915_gem_context_mock_selftests(void) 1709 { 1710 static const struct i915_subtest tests[] = { 1711 SUBTEST(mock_context_barrier), 1712 }; 1713 struct drm_i915_private *i915; 1714 int err; 1715 1716 i915 = mock_gem_device(); 1717 if (!i915) 1718 return -ENOMEM; 1719 1720 err = i915_subtests(tests, i915); 1721 1722 drm_dev_put(&i915->drm); 1723 return err; 1724 } 1725 1726 int i915_gem_context_live_selftests(struct drm_i915_private *i915) 1727 { 1728 static const struct i915_subtest tests[] = { 1729 SUBTEST(live_nop_switch), 1730 SUBTEST(igt_ctx_exec), 1731 SUBTEST(igt_ctx_readonly), 1732 SUBTEST(igt_ctx_sseu), 1733 SUBTEST(igt_shared_ctx_exec), 1734 SUBTEST(igt_vm_isolation), 1735 }; 1736 1737 if (intel_gt_is_wedged(&i915->gt)) 1738 return 0; 1739 1740 return i915_live_subtests(tests, i915); 1741 } 1742