linux/drivers/gpu/drm/i915/gt/selftest_workarounds.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2018 Intel Corporation
   4 */
   5
   6#include "gem/i915_gem_internal.h"
   7#include "gem/i915_gem_pm.h"
   8#include "gt/intel_engine_user.h"
   9#include "gt/intel_gt.h"
  10#include "i915_selftest.h"
  11#include "intel_reset.h"
  12
  13#include "selftests/igt_flush_test.h"
  14#include "selftests/igt_reset.h"
  15#include "selftests/igt_spinner.h"
  16#include "selftests/intel_scheduler_helpers.h"
  17#include "selftests/mock_drm.h"
  18
  19#include "gem/selftests/igt_gem_utils.h"
  20#include "gem/selftests/mock_context.h"
  21
  22static const struct wo_register {
  23        enum intel_platform platform;
  24        u32 reg;
  25} wo_registers[] = {
  26        { INTEL_GEMINILAKE, 0x731c }
  27};
  28
  29struct wa_lists {
  30        struct i915_wa_list gt_wa_list;
  31        struct {
  32                struct i915_wa_list wa_list;
  33                struct i915_wa_list ctx_wa_list;
  34        } engine[I915_NUM_ENGINES];
  35};
  36
  37static int request_add_sync(struct i915_request *rq, int err)
  38{
  39        i915_request_get(rq);
  40        i915_request_add(rq);
  41        if (i915_request_wait(rq, 0, HZ / 5) < 0)
  42                err = -EIO;
  43        i915_request_put(rq);
  44
  45        return err;
  46}
  47
  48static int request_add_spin(struct i915_request *rq, struct igt_spinner *spin)
  49{
  50        int err = 0;
  51
  52        i915_request_get(rq);
  53        i915_request_add(rq);
  54        if (spin && !igt_wait_for_spinner(spin, rq))
  55                err = -ETIMEDOUT;
  56        i915_request_put(rq);
  57
  58        return err;
  59}
  60
  61static void
  62reference_lists_init(struct intel_gt *gt, struct wa_lists *lists)
  63{
  64        struct intel_engine_cs *engine;
  65        enum intel_engine_id id;
  66
  67        memset(lists, 0, sizeof(*lists));
  68
  69        wa_init_start(&lists->gt_wa_list, "GT_REF", "global");
  70        gt_init_workarounds(gt, &lists->gt_wa_list);
  71        wa_init_finish(&lists->gt_wa_list);
  72
  73        for_each_engine(engine, gt, id) {
  74                struct i915_wa_list *wal = &lists->engine[id].wa_list;
  75
  76                wa_init_start(wal, "REF", engine->name);
  77                engine_init_workarounds(engine, wal);
  78                wa_init_finish(wal);
  79
  80                __intel_engine_init_ctx_wa(engine,
  81                                           &lists->engine[id].ctx_wa_list,
  82                                           "CTX_REF");
  83        }
  84}
  85
  86static void
  87reference_lists_fini(struct intel_gt *gt, struct wa_lists *lists)
  88{
  89        struct intel_engine_cs *engine;
  90        enum intel_engine_id id;
  91
  92        for_each_engine(engine, gt, id)
  93                intel_wa_list_free(&lists->engine[id].wa_list);
  94
  95        intel_wa_list_free(&lists->gt_wa_list);
  96}
  97
  98static struct drm_i915_gem_object *
  99read_nonprivs(struct intel_context *ce)
 100{
 101        struct intel_engine_cs *engine = ce->engine;
 102        const u32 base = engine->mmio_base;
 103        struct drm_i915_gem_object *result;
 104        struct i915_request *rq;
 105        struct i915_vma *vma;
 106        u32 srm, *cs;
 107        int err;
 108        int i;
 109
 110        result = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
 111        if (IS_ERR(result))
 112                return result;
 113
 114        i915_gem_object_set_cache_coherency(result, I915_CACHE_LLC);
 115
 116        cs = i915_gem_object_pin_map_unlocked(result, I915_MAP_WB);
 117        if (IS_ERR(cs)) {
 118                err = PTR_ERR(cs);
 119                goto err_obj;
 120        }
 121        memset(cs, 0xc5, PAGE_SIZE);
 122        i915_gem_object_flush_map(result);
 123        i915_gem_object_unpin_map(result);
 124
 125        vma = i915_vma_instance(result, &engine->gt->ggtt->vm, NULL);
 126        if (IS_ERR(vma)) {
 127                err = PTR_ERR(vma);
 128                goto err_obj;
 129        }
 130
 131        err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
 132        if (err)
 133                goto err_obj;
 134
 135        rq = intel_context_create_request(ce);
 136        if (IS_ERR(rq)) {
 137                err = PTR_ERR(rq);
 138                goto err_pin;
 139        }
 140
 141        i915_vma_lock(vma);
 142        err = i915_request_await_object(rq, vma->obj, true);
 143        if (err == 0)
 144                err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
 145        i915_vma_unlock(vma);
 146        if (err)
 147                goto err_req;
 148
 149        srm = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
 150        if (GRAPHICS_VER(engine->i915) >= 8)
 151                srm++;
 152
 153        cs = intel_ring_begin(rq, 4 * RING_MAX_NONPRIV_SLOTS);
 154        if (IS_ERR(cs)) {
 155                err = PTR_ERR(cs);
 156                goto err_req;
 157        }
 158
 159        for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
 160                *cs++ = srm;
 161                *cs++ = i915_mmio_reg_offset(RING_FORCE_TO_NONPRIV(base, i));
 162                *cs++ = i915_ggtt_offset(vma) + sizeof(u32) * i;
 163                *cs++ = 0;
 164        }
 165        intel_ring_advance(rq, cs);
 166
 167        i915_request_add(rq);
 168        i915_vma_unpin(vma);
 169
 170        return result;
 171
 172err_req:
 173        i915_request_add(rq);
 174err_pin:
 175        i915_vma_unpin(vma);
 176err_obj:
 177        i915_gem_object_put(result);
 178        return ERR_PTR(err);
 179}
 180
 181static u32
 182get_whitelist_reg(const struct intel_engine_cs *engine, unsigned int i)
 183{
 184        i915_reg_t reg = i < engine->whitelist.count ?
 185                         engine->whitelist.list[i].reg :
 186                         RING_NOPID(engine->mmio_base);
 187
 188        return i915_mmio_reg_offset(reg);
 189}
 190
 191static void
 192print_results(const struct intel_engine_cs *engine, const u32 *results)
 193{
 194        unsigned int i;
 195
 196        for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
 197                u32 expected = get_whitelist_reg(engine, i);
 198                u32 actual = results[i];
 199
 200                pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n",
 201                        i, expected, actual);
 202        }
 203}
 204
 205static int check_whitelist(struct intel_context *ce)
 206{
 207        struct intel_engine_cs *engine = ce->engine;
 208        struct drm_i915_gem_object *results;
 209        struct intel_wedge_me wedge;
 210        u32 *vaddr;
 211        int err;
 212        int i;
 213
 214        results = read_nonprivs(ce);
 215        if (IS_ERR(results))
 216                return PTR_ERR(results);
 217
 218        err = 0;
 219        i915_gem_object_lock(results, NULL);
 220        intel_wedge_on_timeout(&wedge, engine->gt, HZ / 5) /* safety net! */
 221                err = i915_gem_object_set_to_cpu_domain(results, false);
 222
 223        if (intel_gt_is_wedged(engine->gt))
 224                err = -EIO;
 225        if (err)
 226                goto out_put;
 227
 228        vaddr = i915_gem_object_pin_map(results, I915_MAP_WB);
 229        if (IS_ERR(vaddr)) {
 230                err = PTR_ERR(vaddr);
 231                goto out_put;
 232        }
 233
 234        for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
 235                u32 expected = get_whitelist_reg(engine, i);
 236                u32 actual = vaddr[i];
 237
 238                if (expected != actual) {
 239                        print_results(engine, vaddr);
 240                        pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n",
 241                               i, expected, actual);
 242
 243                        err = -EINVAL;
 244                        break;
 245                }
 246        }
 247
 248        i915_gem_object_unpin_map(results);
 249out_put:
 250        i915_gem_object_unlock(results);
 251        i915_gem_object_put(results);
 252        return err;
 253}
 254
 255static int do_device_reset(struct intel_engine_cs *engine)
 256{
 257        intel_gt_reset(engine->gt, engine->mask, "live_workarounds");
 258        return 0;
 259}
 260
 261static int do_engine_reset(struct intel_engine_cs *engine)
 262{
 263        return intel_engine_reset(engine, "live_workarounds");
 264}
 265
 266static int do_guc_reset(struct intel_engine_cs *engine)
 267{
 268        /* Currently a no-op as the reset is handled by GuC */
 269        return 0;
 270}
 271
 272static int
 273switch_to_scratch_context(struct intel_engine_cs *engine,
 274                          struct igt_spinner *spin,
 275                          struct i915_request **rq)
 276{
 277        struct intel_context *ce;
 278        int err = 0;
 279
 280        ce = intel_context_create(engine);
 281        if (IS_ERR(ce))
 282                return PTR_ERR(ce);
 283
 284        *rq = igt_spinner_create_request(spin, ce, MI_NOOP);
 285        intel_context_put(ce);
 286
 287        if (IS_ERR(*rq)) {
 288                spin = NULL;
 289                err = PTR_ERR(*rq);
 290                goto err;
 291        }
 292
 293        err = request_add_spin(*rq, spin);
 294err:
 295        if (err && spin)
 296                igt_spinner_end(spin);
 297
 298        return err;
 299}
 300
 301static int check_whitelist_across_reset(struct intel_engine_cs *engine,
 302                                        int (*reset)(struct intel_engine_cs *),
 303                                        const char *name)
 304{
 305        struct intel_context *ce, *tmp;
 306        struct igt_spinner spin;
 307        struct i915_request *rq;
 308        intel_wakeref_t wakeref;
 309        int err;
 310
 311        pr_info("Checking %d whitelisted registers on %s (RING_NONPRIV) [%s]\n",
 312                engine->whitelist.count, engine->name, name);
 313
 314        ce = intel_context_create(engine);
 315        if (IS_ERR(ce))
 316                return PTR_ERR(ce);
 317
 318        err = igt_spinner_init(&spin, engine->gt);
 319        if (err)
 320                goto out_ctx;
 321
 322        err = check_whitelist(ce);
 323        if (err) {
 324                pr_err("Invalid whitelist *before* %s reset!\n", name);
 325                goto out_spin;
 326        }
 327
 328        err = switch_to_scratch_context(engine, &spin, &rq);
 329        if (err)
 330                goto out_spin;
 331
 332        /* Ensure the spinner hasn't aborted */
 333        if (i915_request_completed(rq)) {
 334                pr_err("%s spinner failed to start\n", name);
 335                err = -ETIMEDOUT;
 336                goto out_spin;
 337        }
 338
 339        with_intel_runtime_pm(engine->uncore->rpm, wakeref)
 340                err = reset(engine);
 341
 342        /* Ensure the reset happens and kills the engine */
 343        if (err == 0)
 344                err = intel_selftest_wait_for_rq(rq);
 345
 346        igt_spinner_end(&spin);
 347
 348        if (err) {
 349                pr_err("%s reset failed\n", name);
 350                goto out_spin;
 351        }
 352
 353        err = check_whitelist(ce);
 354        if (err) {
 355                pr_err("Whitelist not preserved in context across %s reset!\n",
 356                       name);
 357                goto out_spin;
 358        }
 359
 360        tmp = intel_context_create(engine);
 361        if (IS_ERR(tmp)) {
 362                err = PTR_ERR(tmp);
 363                goto out_spin;
 364        }
 365        intel_context_put(ce);
 366        ce = tmp;
 367
 368        err = check_whitelist(ce);
 369        if (err) {
 370                pr_err("Invalid whitelist *after* %s reset in fresh context!\n",
 371                       name);
 372                goto out_spin;
 373        }
 374
 375out_spin:
 376        igt_spinner_fini(&spin);
 377out_ctx:
 378        intel_context_put(ce);
 379        return err;
 380}
 381
 382static struct i915_vma *create_batch(struct i915_address_space *vm)
 383{
 384        struct drm_i915_gem_object *obj;
 385        struct i915_vma *vma;
 386        int err;
 387
 388        obj = i915_gem_object_create_internal(vm->i915, 16 * PAGE_SIZE);
 389        if (IS_ERR(obj))
 390                return ERR_CAST(obj);
 391
 392        vma = i915_vma_instance(obj, vm, NULL);
 393        if (IS_ERR(vma)) {
 394                err = PTR_ERR(vma);
 395                goto err_obj;
 396        }
 397
 398        err = i915_vma_pin(vma, 0, 0, PIN_USER);
 399        if (err)
 400                goto err_obj;
 401
 402        return vma;
 403
 404err_obj:
 405        i915_gem_object_put(obj);
 406        return ERR_PTR(err);
 407}
 408
 409static u32 reg_write(u32 old, u32 new, u32 rsvd)
 410{
 411        if (rsvd == 0x0000ffff) {
 412                old &= ~(new >> 16);
 413                old |= new & (new >> 16);
 414        } else {
 415                old &= ~rsvd;
 416                old |= new & rsvd;
 417        }
 418
 419        return old;
 420}
 421
 422static bool wo_register(struct intel_engine_cs *engine, u32 reg)
 423{
 424        enum intel_platform platform = INTEL_INFO(engine->i915)->platform;
 425        int i;
 426
 427        if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
 428             RING_FORCE_TO_NONPRIV_ACCESS_WR)
 429                return true;
 430
 431        for (i = 0; i < ARRAY_SIZE(wo_registers); i++) {
 432                if (wo_registers[i].platform == platform &&
 433                    wo_registers[i].reg == reg)
 434                        return true;
 435        }
 436
 437        return false;
 438}
 439
 440static bool timestamp(const struct intel_engine_cs *engine, u32 reg)
 441{
 442        reg = (reg - engine->mmio_base) & ~RING_FORCE_TO_NONPRIV_ACCESS_MASK;
 443        switch (reg) {
 444        case 0x358:
 445        case 0x35c:
 446        case 0x3a8:
 447                return true;
 448
 449        default:
 450                return false;
 451        }
 452}
 453
 454static bool ro_register(u32 reg)
 455{
 456        if ((reg & RING_FORCE_TO_NONPRIV_ACCESS_MASK) ==
 457             RING_FORCE_TO_NONPRIV_ACCESS_RD)
 458                return true;
 459
 460        return false;
 461}
 462
 463static int whitelist_writable_count(struct intel_engine_cs *engine)
 464{
 465        int count = engine->whitelist.count;
 466        int i;
 467
 468        for (i = 0; i < engine->whitelist.count; i++) {
 469                u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
 470
 471                if (ro_register(reg))
 472                        count--;
 473        }
 474
 475        return count;
 476}
 477
 478static int check_dirty_whitelist(struct intel_context *ce)
 479{
 480        const u32 values[] = {
 481                0x00000000,
 482                0x01010101,
 483                0x10100101,
 484                0x03030303,
 485                0x30300303,
 486                0x05050505,
 487                0x50500505,
 488                0x0f0f0f0f,
 489                0xf00ff00f,
 490                0x10101010,
 491                0xf0f01010,
 492                0x30303030,
 493                0xa0a03030,
 494                0x50505050,
 495                0xc0c05050,
 496                0xf0f0f0f0,
 497                0x11111111,
 498                0x33333333,
 499                0x55555555,
 500                0x0000ffff,
 501                0x00ff00ff,
 502                0xff0000ff,
 503                0xffff00ff,
 504                0xffffffff,
 505        };
 506        struct intel_engine_cs *engine = ce->engine;
 507        struct i915_vma *scratch;
 508        struct i915_vma *batch;
 509        int err = 0, i, v, sz;
 510        u32 *cs, *results;
 511
 512        sz = (2 * ARRAY_SIZE(values) + 1) * sizeof(u32);
 513        scratch = __vm_create_scratch_for_read_pinned(ce->vm, sz);
 514        if (IS_ERR(scratch))
 515                return PTR_ERR(scratch);
 516
 517        batch = create_batch(ce->vm);
 518        if (IS_ERR(batch)) {
 519                err = PTR_ERR(batch);
 520                goto out_scratch;
 521        }
 522
 523        for (i = 0; i < engine->whitelist.count; i++) {
 524                u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
 525                struct i915_gem_ww_ctx ww;
 526                u64 addr = scratch->node.start;
 527                struct i915_request *rq;
 528                u32 srm, lrm, rsvd;
 529                u32 expect;
 530                int idx;
 531                bool ro_reg;
 532
 533                if (wo_register(engine, reg))
 534                        continue;
 535
 536                if (timestamp(engine, reg))
 537                        continue; /* timestamps are expected to autoincrement */
 538
 539                ro_reg = ro_register(reg);
 540
 541                i915_gem_ww_ctx_init(&ww, false);
 542retry:
 543                cs = NULL;
 544                err = i915_gem_object_lock(scratch->obj, &ww);
 545                if (!err)
 546                        err = i915_gem_object_lock(batch->obj, &ww);
 547                if (!err)
 548                        err = intel_context_pin_ww(ce, &ww);
 549                if (err)
 550                        goto out;
 551
 552                cs = i915_gem_object_pin_map(batch->obj, I915_MAP_WC);
 553                if (IS_ERR(cs)) {
 554                        err = PTR_ERR(cs);
 555                        goto out_ctx;
 556                }
 557
 558                results = i915_gem_object_pin_map(scratch->obj, I915_MAP_WB);
 559                if (IS_ERR(results)) {
 560                        err = PTR_ERR(results);
 561                        goto out_unmap_batch;
 562                }
 563
 564                /* Clear non priv flags */
 565                reg &= RING_FORCE_TO_NONPRIV_ADDRESS_MASK;
 566
 567                srm = MI_STORE_REGISTER_MEM;
 568                lrm = MI_LOAD_REGISTER_MEM;
 569                if (GRAPHICS_VER(engine->i915) >= 8)
 570                        lrm++, srm++;
 571
 572                pr_debug("%s: Writing garbage to %x\n",
 573                         engine->name, reg);
 574
 575                /* SRM original */
 576                *cs++ = srm;
 577                *cs++ = reg;
 578                *cs++ = lower_32_bits(addr);
 579                *cs++ = upper_32_bits(addr);
 580
 581                idx = 1;
 582                for (v = 0; v < ARRAY_SIZE(values); v++) {
 583                        /* LRI garbage */
 584                        *cs++ = MI_LOAD_REGISTER_IMM(1);
 585                        *cs++ = reg;
 586                        *cs++ = values[v];
 587
 588                        /* SRM result */
 589                        *cs++ = srm;
 590                        *cs++ = reg;
 591                        *cs++ = lower_32_bits(addr + sizeof(u32) * idx);
 592                        *cs++ = upper_32_bits(addr + sizeof(u32) * idx);
 593                        idx++;
 594                }
 595                for (v = 0; v < ARRAY_SIZE(values); v++) {
 596                        /* LRI garbage */
 597                        *cs++ = MI_LOAD_REGISTER_IMM(1);
 598                        *cs++ = reg;
 599                        *cs++ = ~values[v];
 600
 601                        /* SRM result */
 602                        *cs++ = srm;
 603                        *cs++ = reg;
 604                        *cs++ = lower_32_bits(addr + sizeof(u32) * idx);
 605                        *cs++ = upper_32_bits(addr + sizeof(u32) * idx);
 606                        idx++;
 607                }
 608                GEM_BUG_ON(idx * sizeof(u32) > scratch->size);
 609
 610                /* LRM original -- don't leave garbage in the context! */
 611                *cs++ = lrm;
 612                *cs++ = reg;
 613                *cs++ = lower_32_bits(addr);
 614                *cs++ = upper_32_bits(addr);
 615
 616                *cs++ = MI_BATCH_BUFFER_END;
 617
 618                i915_gem_object_flush_map(batch->obj);
 619                i915_gem_object_unpin_map(batch->obj);
 620                intel_gt_chipset_flush(engine->gt);
 621                cs = NULL;
 622
 623                rq = i915_request_create(ce);
 624                if (IS_ERR(rq)) {
 625                        err = PTR_ERR(rq);
 626                        goto out_unmap_scratch;
 627                }
 628
 629                if (engine->emit_init_breadcrumb) { /* Be nice if we hang */
 630                        err = engine->emit_init_breadcrumb(rq);
 631                        if (err)
 632                                goto err_request;
 633                }
 634
 635                err = i915_request_await_object(rq, batch->obj, false);
 636                if (err == 0)
 637                        err = i915_vma_move_to_active(batch, rq, 0);
 638                if (err)
 639                        goto err_request;
 640
 641                err = i915_request_await_object(rq, scratch->obj, true);
 642                if (err == 0)
 643                        err = i915_vma_move_to_active(scratch, rq,
 644                                                      EXEC_OBJECT_WRITE);
 645                if (err)
 646                        goto err_request;
 647
 648                err = engine->emit_bb_start(rq,
 649                                            batch->node.start, PAGE_SIZE,
 650                                            0);
 651                if (err)
 652                        goto err_request;
 653
 654err_request:
 655                err = request_add_sync(rq, err);
 656                if (err) {
 657                        pr_err("%s: Futzing %x timedout; cancelling test\n",
 658                               engine->name, reg);
 659                        intel_gt_set_wedged(engine->gt);
 660                        goto out_unmap_scratch;
 661                }
 662
 663                GEM_BUG_ON(values[ARRAY_SIZE(values) - 1] != 0xffffffff);
 664                if (!ro_reg) {
 665                        /* detect write masking */
 666                        rsvd = results[ARRAY_SIZE(values)];
 667                        if (!rsvd) {
 668                                pr_err("%s: Unable to write to whitelisted register %x\n",
 669                                       engine->name, reg);
 670                                err = -EINVAL;
 671                                goto out_unmap_scratch;
 672                        }
 673                } else {
 674                        rsvd = 0;
 675                }
 676
 677                expect = results[0];
 678                idx = 1;
 679                for (v = 0; v < ARRAY_SIZE(values); v++) {
 680                        if (ro_reg)
 681                                expect = results[0];
 682                        else
 683                                expect = reg_write(expect, values[v], rsvd);
 684
 685                        if (results[idx] != expect)
 686                                err++;
 687                        idx++;
 688                }
 689                for (v = 0; v < ARRAY_SIZE(values); v++) {
 690                        if (ro_reg)
 691                                expect = results[0];
 692                        else
 693                                expect = reg_write(expect, ~values[v], rsvd);
 694
 695                        if (results[idx] != expect)
 696                                err++;
 697                        idx++;
 698                }
 699                if (err) {
 700                        pr_err("%s: %d mismatch between values written to whitelisted register [%x], and values read back!\n",
 701                               engine->name, err, reg);
 702
 703                        if (ro_reg)
 704                                pr_info("%s: Whitelisted read-only register: %x, original value %08x\n",
 705                                        engine->name, reg, results[0]);
 706                        else
 707                                pr_info("%s: Whitelisted register: %x, original value %08x, rsvd %08x\n",
 708                                        engine->name, reg, results[0], rsvd);
 709
 710                        expect = results[0];
 711                        idx = 1;
 712                        for (v = 0; v < ARRAY_SIZE(values); v++) {
 713                                u32 w = values[v];
 714
 715                                if (ro_reg)
 716                                        expect = results[0];
 717                                else
 718                                        expect = reg_write(expect, w, rsvd);
 719                                pr_info("Wrote %08x, read %08x, expect %08x\n",
 720                                        w, results[idx], expect);
 721                                idx++;
 722                        }
 723                        for (v = 0; v < ARRAY_SIZE(values); v++) {
 724                                u32 w = ~values[v];
 725
 726                                if (ro_reg)
 727                                        expect = results[0];
 728                                else
 729                                        expect = reg_write(expect, w, rsvd);
 730                                pr_info("Wrote %08x, read %08x, expect %08x\n",
 731                                        w, results[idx], expect);
 732                                idx++;
 733                        }
 734
 735                        err = -EINVAL;
 736                }
 737out_unmap_scratch:
 738                i915_gem_object_unpin_map(scratch->obj);
 739out_unmap_batch:
 740                if (cs)
 741                        i915_gem_object_unpin_map(batch->obj);
 742out_ctx:
 743                intel_context_unpin(ce);
 744out:
 745                if (err == -EDEADLK) {
 746                        err = i915_gem_ww_ctx_backoff(&ww);
 747                        if (!err)
 748                                goto retry;
 749                }
 750                i915_gem_ww_ctx_fini(&ww);
 751                if (err)
 752                        break;
 753        }
 754
 755        if (igt_flush_test(engine->i915))
 756                err = -EIO;
 757
 758        i915_vma_unpin_and_release(&batch, 0);
 759out_scratch:
 760        i915_vma_unpin_and_release(&scratch, 0);
 761        return err;
 762}
 763
 764static int live_dirty_whitelist(void *arg)
 765{
 766        struct intel_gt *gt = arg;
 767        struct intel_engine_cs *engine;
 768        enum intel_engine_id id;
 769
 770        /* Can the user write to the whitelisted registers? */
 771
 772        if (GRAPHICS_VER(gt->i915) < 7) /* minimum requirement for LRI, SRM, LRM */
 773                return 0;
 774
 775        for_each_engine(engine, gt, id) {
 776                struct intel_context *ce;
 777                int err;
 778
 779                if (engine->whitelist.count == 0)
 780                        continue;
 781
 782                ce = intel_context_create(engine);
 783                if (IS_ERR(ce))
 784                        return PTR_ERR(ce);
 785
 786                err = check_dirty_whitelist(ce);
 787                intel_context_put(ce);
 788                if (err)
 789                        return err;
 790        }
 791
 792        return 0;
 793}
 794
 795static int live_reset_whitelist(void *arg)
 796{
 797        struct intel_gt *gt = arg;
 798        struct intel_engine_cs *engine;
 799        enum intel_engine_id id;
 800        int err = 0;
 801
 802        /* If we reset the gpu, we should not lose the RING_NONPRIV */
 803        igt_global_reset_lock(gt);
 804
 805        for_each_engine(engine, gt, id) {
 806                if (engine->whitelist.count == 0)
 807                        continue;
 808
 809                if (intel_has_reset_engine(gt)) {
 810                        if (intel_engine_uses_guc(engine)) {
 811                                struct intel_selftest_saved_policy saved;
 812                                int err2;
 813
 814                                err = intel_selftest_modify_policy(engine, &saved,
 815                                                                   SELFTEST_SCHEDULER_MODIFY_FAST_RESET);
 816                                if (err)
 817                                        goto out;
 818
 819                                err = check_whitelist_across_reset(engine,
 820                                                                   do_guc_reset,
 821                                                                   "guc");
 822
 823                                err2 = intel_selftest_restore_policy(engine, &saved);
 824                                if (err == 0)
 825                                        err = err2;
 826                        } else {
 827                                err = check_whitelist_across_reset(engine,
 828                                                                   do_engine_reset,
 829                                                                   "engine");
 830                        }
 831
 832                        if (err)
 833                                goto out;
 834                }
 835
 836                if (intel_has_gpu_reset(gt)) {
 837                        err = check_whitelist_across_reset(engine,
 838                                                           do_device_reset,
 839                                                           "device");
 840                        if (err)
 841                                goto out;
 842                }
 843        }
 844
 845out:
 846        igt_global_reset_unlock(gt);
 847        return err;
 848}
 849
 850static int read_whitelisted_registers(struct intel_context *ce,
 851                                      struct i915_vma *results)
 852{
 853        struct intel_engine_cs *engine = ce->engine;
 854        struct i915_request *rq;
 855        int i, err = 0;
 856        u32 srm, *cs;
 857
 858        rq = intel_context_create_request(ce);
 859        if (IS_ERR(rq))
 860                return PTR_ERR(rq);
 861
 862        i915_vma_lock(results);
 863        err = i915_request_await_object(rq, results->obj, true);
 864        if (err == 0)
 865                err = i915_vma_move_to_active(results, rq, EXEC_OBJECT_WRITE);
 866        i915_vma_unlock(results);
 867        if (err)
 868                goto err_req;
 869
 870        srm = MI_STORE_REGISTER_MEM;
 871        if (GRAPHICS_VER(engine->i915) >= 8)
 872                srm++;
 873
 874        cs = intel_ring_begin(rq, 4 * engine->whitelist.count);
 875        if (IS_ERR(cs)) {
 876                err = PTR_ERR(cs);
 877                goto err_req;
 878        }
 879
 880        for (i = 0; i < engine->whitelist.count; i++) {
 881                u64 offset = results->node.start + sizeof(u32) * i;
 882                u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
 883
 884                /* Clear non priv flags */
 885                reg &= RING_FORCE_TO_NONPRIV_ADDRESS_MASK;
 886
 887                *cs++ = srm;
 888                *cs++ = reg;
 889                *cs++ = lower_32_bits(offset);
 890                *cs++ = upper_32_bits(offset);
 891        }
 892        intel_ring_advance(rq, cs);
 893
 894err_req:
 895        return request_add_sync(rq, err);
 896}
 897
 898static int scrub_whitelisted_registers(struct intel_context *ce)
 899{
 900        struct intel_engine_cs *engine = ce->engine;
 901        struct i915_request *rq;
 902        struct i915_vma *batch;
 903        int i, err = 0;
 904        u32 *cs;
 905
 906        batch = create_batch(ce->vm);
 907        if (IS_ERR(batch))
 908                return PTR_ERR(batch);
 909
 910        cs = i915_gem_object_pin_map_unlocked(batch->obj, I915_MAP_WC);
 911        if (IS_ERR(cs)) {
 912                err = PTR_ERR(cs);
 913                goto err_batch;
 914        }
 915
 916        *cs++ = MI_LOAD_REGISTER_IMM(whitelist_writable_count(engine));
 917        for (i = 0; i < engine->whitelist.count; i++) {
 918                u32 reg = i915_mmio_reg_offset(engine->whitelist.list[i].reg);
 919
 920                if (ro_register(reg))
 921                        continue;
 922
 923                /* Clear non priv flags */
 924                reg &= RING_FORCE_TO_NONPRIV_ADDRESS_MASK;
 925
 926                *cs++ = reg;
 927                *cs++ = 0xffffffff;
 928        }
 929        *cs++ = MI_BATCH_BUFFER_END;
 930
 931        i915_gem_object_flush_map(batch->obj);
 932        intel_gt_chipset_flush(engine->gt);
 933
 934        rq = intel_context_create_request(ce);
 935        if (IS_ERR(rq)) {
 936                err = PTR_ERR(rq);
 937                goto err_unpin;
 938        }
 939
 940        if (engine->emit_init_breadcrumb) { /* Be nice if we hang */
 941                err = engine->emit_init_breadcrumb(rq);
 942                if (err)
 943                        goto err_request;
 944        }
 945
 946        i915_vma_lock(batch);
 947        err = i915_request_await_object(rq, batch->obj, false);
 948        if (err == 0)
 949                err = i915_vma_move_to_active(batch, rq, 0);
 950        i915_vma_unlock(batch);
 951        if (err)
 952                goto err_request;
 953
 954        /* Perform the writes from an unprivileged "user" batch */
 955        err = engine->emit_bb_start(rq, batch->node.start, 0, 0);
 956
 957err_request:
 958        err = request_add_sync(rq, err);
 959
 960err_unpin:
 961        i915_gem_object_unpin_map(batch->obj);
 962err_batch:
 963        i915_vma_unpin_and_release(&batch, 0);
 964        return err;
 965}
 966
 967struct regmask {
 968        i915_reg_t reg;
 969        u8 graphics_ver;
 970};
 971
 972static bool find_reg(struct drm_i915_private *i915,
 973                     i915_reg_t reg,
 974                     const struct regmask *tbl,
 975                     unsigned long count)
 976{
 977        u32 offset = i915_mmio_reg_offset(reg);
 978
 979        while (count--) {
 980                if (GRAPHICS_VER(i915) == tbl->graphics_ver &&
 981                    i915_mmio_reg_offset(tbl->reg) == offset)
 982                        return true;
 983                tbl++;
 984        }
 985
 986        return false;
 987}
 988
 989static bool pardon_reg(struct drm_i915_private *i915, i915_reg_t reg)
 990{
 991        /* Alas, we must pardon some whitelists. Mistakes already made */
 992        static const struct regmask pardon[] = {
 993                { GEN9_CTX_PREEMPT_REG, 9 },
 994                { GEN8_L3SQCREG4, 9 },
 995        };
 996
 997        return find_reg(i915, reg, pardon, ARRAY_SIZE(pardon));
 998}
 999
1000static bool result_eq(struct intel_engine_cs *engine,
1001                      u32 a, u32 b, i915_reg_t reg)
1002{
1003        if (a != b && !pardon_reg(engine->i915, reg)) {
1004                pr_err("Whitelisted register 0x%4x not context saved: A=%08x, B=%08x\n",
1005                       i915_mmio_reg_offset(reg), a, b);
1006                return false;
1007        }
1008
1009        return true;
1010}
1011
1012static bool writeonly_reg(struct drm_i915_private *i915, i915_reg_t reg)
1013{
1014        /* Some registers do not seem to behave and our writes unreadable */
1015        static const struct regmask wo[] = {
1016                { GEN9_SLICE_COMMON_ECO_CHICKEN1, 9 },
1017        };
1018
1019        return find_reg(i915, reg, wo, ARRAY_SIZE(wo));
1020}
1021
1022static bool result_neq(struct intel_engine_cs *engine,
1023                       u32 a, u32 b, i915_reg_t reg)
1024{
1025        if (a == b && !writeonly_reg(engine->i915, reg)) {
1026                pr_err("Whitelist register 0x%4x:%08x was unwritable\n",
1027                       i915_mmio_reg_offset(reg), a);
1028                return false;
1029        }
1030
1031        return true;
1032}
1033
1034static int
1035check_whitelisted_registers(struct intel_engine_cs *engine,
1036                            struct i915_vma *A,
1037                            struct i915_vma *B,
1038                            bool (*fn)(struct intel_engine_cs *engine,
1039                                       u32 a, u32 b,
1040                                       i915_reg_t reg))
1041{
1042        u32 *a, *b;
1043        int i, err;
1044
1045        a = i915_gem_object_pin_map_unlocked(A->obj, I915_MAP_WB);
1046        if (IS_ERR(a))
1047                return PTR_ERR(a);
1048
1049        b = i915_gem_object_pin_map_unlocked(B->obj, I915_MAP_WB);
1050        if (IS_ERR(b)) {
1051                err = PTR_ERR(b);
1052                goto err_a;
1053        }
1054
1055        err = 0;
1056        for (i = 0; i < engine->whitelist.count; i++) {
1057                const struct i915_wa *wa = &engine->whitelist.list[i];
1058
1059                if (i915_mmio_reg_offset(wa->reg) &
1060                    RING_FORCE_TO_NONPRIV_ACCESS_RD)
1061                        continue;
1062
1063                if (!fn(engine, a[i], b[i], wa->reg))
1064                        err = -EINVAL;
1065        }
1066
1067        i915_gem_object_unpin_map(B->obj);
1068err_a:
1069        i915_gem_object_unpin_map(A->obj);
1070        return err;
1071}
1072
1073static int live_isolated_whitelist(void *arg)
1074{
1075        struct intel_gt *gt = arg;
1076        struct {
1077                struct i915_vma *scratch[2];
1078        } client[2] = {};
1079        struct intel_engine_cs *engine;
1080        enum intel_engine_id id;
1081        int i, err = 0;
1082
1083        /*
1084         * Check that a write into a whitelist register works, but
1085         * invisible to a second context.
1086         */
1087
1088        if (!intel_engines_has_context_isolation(gt->i915))
1089                return 0;
1090
1091        for (i = 0; i < ARRAY_SIZE(client); i++) {
1092                client[i].scratch[0] =
1093                        __vm_create_scratch_for_read_pinned(gt->vm, 4096);
1094                if (IS_ERR(client[i].scratch[0])) {
1095                        err = PTR_ERR(client[i].scratch[0]);
1096                        goto err;
1097                }
1098
1099                client[i].scratch[1] =
1100                        __vm_create_scratch_for_read_pinned(gt->vm, 4096);
1101                if (IS_ERR(client[i].scratch[1])) {
1102                        err = PTR_ERR(client[i].scratch[1]);
1103                        i915_vma_unpin_and_release(&client[i].scratch[0], 0);
1104                        goto err;
1105                }
1106        }
1107
1108        for_each_engine(engine, gt, id) {
1109                struct intel_context *ce[2];
1110
1111                if (!engine->kernel_context->vm)
1112                        continue;
1113
1114                if (!whitelist_writable_count(engine))
1115                        continue;
1116
1117                ce[0] = intel_context_create(engine);
1118                if (IS_ERR(ce[0])) {
1119                        err = PTR_ERR(ce[0]);
1120                        break;
1121                }
1122                ce[1] = intel_context_create(engine);
1123                if (IS_ERR(ce[1])) {
1124                        err = PTR_ERR(ce[1]);
1125                        intel_context_put(ce[0]);
1126                        break;
1127                }
1128
1129                /* Read default values */
1130                err = read_whitelisted_registers(ce[0], client[0].scratch[0]);
1131                if (err)
1132                        goto err_ce;
1133
1134                /* Try to overwrite registers (should only affect ctx0) */
1135                err = scrub_whitelisted_registers(ce[0]);
1136                if (err)
1137                        goto err_ce;
1138
1139                /* Read values from ctx1, we expect these to be defaults */
1140                err = read_whitelisted_registers(ce[1], client[1].scratch[0]);
1141                if (err)
1142                        goto err_ce;
1143
1144                /* Verify that both reads return the same default values */
1145                err = check_whitelisted_registers(engine,
1146                                                  client[0].scratch[0],
1147                                                  client[1].scratch[0],
1148                                                  result_eq);
1149                if (err)
1150                        goto err_ce;
1151
1152                /* Read back the updated values in ctx0 */
1153                err = read_whitelisted_registers(ce[0], client[0].scratch[1]);
1154                if (err)
1155                        goto err_ce;
1156
1157                /* User should be granted privilege to overwhite regs */
1158                err = check_whitelisted_registers(engine,
1159                                                  client[0].scratch[0],
1160                                                  client[0].scratch[1],
1161                                                  result_neq);
1162err_ce:
1163                intel_context_put(ce[1]);
1164                intel_context_put(ce[0]);
1165                if (err)
1166                        break;
1167        }
1168
1169err:
1170        for (i = 0; i < ARRAY_SIZE(client); i++) {
1171                i915_vma_unpin_and_release(&client[i].scratch[1], 0);
1172                i915_vma_unpin_and_release(&client[i].scratch[0], 0);
1173        }
1174
1175        if (igt_flush_test(gt->i915))
1176                err = -EIO;
1177
1178        return err;
1179}
1180
1181static bool
1182verify_wa_lists(struct intel_gt *gt, struct wa_lists *lists,
1183                const char *str)
1184{
1185        struct intel_engine_cs *engine;
1186        enum intel_engine_id id;
1187        bool ok = true;
1188
1189        ok &= wa_list_verify(gt, &lists->gt_wa_list, str);
1190
1191        for_each_engine(engine, gt, id) {
1192                struct intel_context *ce;
1193
1194                ce = intel_context_create(engine);
1195                if (IS_ERR(ce))
1196                        return false;
1197
1198                ok &= engine_wa_list_verify(ce,
1199                                            &lists->engine[id].wa_list,
1200                                            str) == 0;
1201
1202                ok &= engine_wa_list_verify(ce,
1203                                            &lists->engine[id].ctx_wa_list,
1204                                            str) == 0;
1205
1206                intel_context_put(ce);
1207        }
1208
1209        return ok;
1210}
1211
1212static int
1213live_gpu_reset_workarounds(void *arg)
1214{
1215        struct intel_gt *gt = arg;
1216        intel_wakeref_t wakeref;
1217        struct wa_lists *lists;
1218        bool ok;
1219
1220        if (!intel_has_gpu_reset(gt))
1221                return 0;
1222
1223        lists = kzalloc(sizeof(*lists), GFP_KERNEL);
1224        if (!lists)
1225                return -ENOMEM;
1226
1227        pr_info("Verifying after GPU reset...\n");
1228
1229        igt_global_reset_lock(gt);
1230        wakeref = intel_runtime_pm_get(gt->uncore->rpm);
1231
1232        reference_lists_init(gt, lists);
1233
1234        ok = verify_wa_lists(gt, lists, "before reset");
1235        if (!ok)
1236                goto out;
1237
1238        intel_gt_reset(gt, ALL_ENGINES, "live_workarounds");
1239
1240        ok = verify_wa_lists(gt, lists, "after reset");
1241
1242out:
1243        reference_lists_fini(gt, lists);
1244        intel_runtime_pm_put(gt->uncore->rpm, wakeref);
1245        igt_global_reset_unlock(gt);
1246        kfree(lists);
1247
1248        return ok ? 0 : -ESRCH;
1249}
1250
1251static int
1252live_engine_reset_workarounds(void *arg)
1253{
1254        struct intel_gt *gt = arg;
1255        struct intel_engine_cs *engine;
1256        enum intel_engine_id id;
1257        struct intel_context *ce;
1258        struct igt_spinner spin;
1259        struct i915_request *rq;
1260        intel_wakeref_t wakeref;
1261        struct wa_lists *lists;
1262        int ret = 0;
1263
1264        if (!intel_has_reset_engine(gt))
1265                return 0;
1266
1267        lists = kzalloc(sizeof(*lists), GFP_KERNEL);
1268        if (!lists)
1269                return -ENOMEM;
1270
1271        igt_global_reset_lock(gt);
1272        wakeref = intel_runtime_pm_get(gt->uncore->rpm);
1273
1274        reference_lists_init(gt, lists);
1275
1276        for_each_engine(engine, gt, id) {
1277                struct intel_selftest_saved_policy saved;
1278                bool using_guc = intel_engine_uses_guc(engine);
1279                bool ok;
1280                int ret2;
1281
1282                pr_info("Verifying after %s reset...\n", engine->name);
1283                ret = intel_selftest_modify_policy(engine, &saved,
1284                                                   SELFTEST_SCHEDULER_MODIFY_FAST_RESET);
1285                if (ret)
1286                        break;
1287
1288                ce = intel_context_create(engine);
1289                if (IS_ERR(ce)) {
1290                        ret = PTR_ERR(ce);
1291                        goto restore;
1292                }
1293
1294                if (!using_guc) {
1295                        ok = verify_wa_lists(gt, lists, "before reset");
1296                        if (!ok) {
1297                                ret = -ESRCH;
1298                                goto err;
1299                        }
1300
1301                        ret = intel_engine_reset(engine, "live_workarounds:idle");
1302                        if (ret) {
1303                                pr_err("%s: Reset failed while idle\n", engine->name);
1304                                goto err;
1305                        }
1306
1307                        ok = verify_wa_lists(gt, lists, "after idle reset");
1308                        if (!ok) {
1309                                ret = -ESRCH;
1310                                goto err;
1311                        }
1312                }
1313
1314                ret = igt_spinner_init(&spin, engine->gt);
1315                if (ret)
1316                        goto err;
1317
1318                rq = igt_spinner_create_request(&spin, ce, MI_NOOP);
1319                if (IS_ERR(rq)) {
1320                        ret = PTR_ERR(rq);
1321                        igt_spinner_fini(&spin);
1322                        goto err;
1323                }
1324
1325                ret = request_add_spin(rq, &spin);
1326                if (ret) {
1327                        pr_err("%s: Spinner failed to start\n", engine->name);
1328                        igt_spinner_fini(&spin);
1329                        goto err;
1330                }
1331
1332                /* Ensure the spinner hasn't aborted */
1333                if (i915_request_completed(rq)) {
1334                        ret = -ETIMEDOUT;
1335                        goto skip;
1336                }
1337
1338                if (!using_guc) {
1339                        ret = intel_engine_reset(engine, "live_workarounds:active");
1340                        if (ret) {
1341                                pr_err("%s: Reset failed on an active spinner\n",
1342                                       engine->name);
1343                                igt_spinner_fini(&spin);
1344                                goto err;
1345                        }
1346                }
1347
1348                /* Ensure the reset happens and kills the engine */
1349                if (ret == 0)
1350                        ret = intel_selftest_wait_for_rq(rq);
1351
1352skip:
1353                igt_spinner_end(&spin);
1354                igt_spinner_fini(&spin);
1355
1356                ok = verify_wa_lists(gt, lists, "after busy reset");
1357                if (!ok)
1358                        ret = -ESRCH;
1359
1360err:
1361                intel_context_put(ce);
1362
1363restore:
1364                ret2 = intel_selftest_restore_policy(engine, &saved);
1365                if (ret == 0)
1366                        ret = ret2;
1367                if (ret)
1368                        break;
1369        }
1370
1371        reference_lists_fini(gt, lists);
1372        intel_runtime_pm_put(gt->uncore->rpm, wakeref);
1373        igt_global_reset_unlock(gt);
1374        kfree(lists);
1375
1376        igt_flush_test(gt->i915);
1377
1378        return ret;
1379}
1380
1381int intel_workarounds_live_selftests(struct drm_i915_private *i915)
1382{
1383        static const struct i915_subtest tests[] = {
1384                SUBTEST(live_dirty_whitelist),
1385                SUBTEST(live_reset_whitelist),
1386                SUBTEST(live_isolated_whitelist),
1387                SUBTEST(live_gpu_reset_workarounds),
1388                SUBTEST(live_engine_reset_workarounds),
1389        };
1390
1391        if (intel_gt_is_wedged(to_gt(i915)))
1392                return 0;
1393
1394        return intel_gt_live_subtests(tests, to_gt(i915));
1395}
1396