Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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