1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2014-2019 Intel Corporation 4 */ 5 6 #include <linux/bsearch.h> 7 8 #include "gem/i915_gem_lmem.h" 9 #include "gt/intel_engine_regs.h" 10 #include "gt/intel_gt.h" 11 #include "gt/intel_gt_mcr.h" 12 #include "gt/intel_gt_regs.h" 13 #include "gt/intel_lrc.h" 14 #include "gt/shmem_utils.h" 15 #include "intel_guc_ads.h" 16 #include "intel_guc_capture.h" 17 #include "intel_guc_fwif.h" 18 #include "intel_guc_print.h" 19 #include "intel_uc.h" 20 #include "i915_drv.h" 21 22 /* 23 * The Additional Data Struct (ADS) has pointers for different buffers used by 24 * the GuC. One single gem object contains the ADS struct itself (guc_ads) and 25 * all the extra buffers indirectly linked via the ADS struct's entries. 26 * 27 * Layout of the ADS blob allocated for the GuC: 28 * 29 * +---------------------------------------+ <== base 30 * | guc_ads | 31 * +---------------------------------------+ 32 * | guc_policies | 33 * +---------------------------------------+ 34 * | guc_gt_system_info | 35 * +---------------------------------------+ 36 * | guc_engine_usage | 37 * +---------------------------------------+ <== static 38 * | guc_mmio_reg[countA] (engine 0.0) | 39 * | guc_mmio_reg[countB] (engine 0.1) | 40 * | guc_mmio_reg[countC] (engine 1.0) | 41 * | ... | 42 * +---------------------------------------+ <== dynamic 43 * | padding | 44 * +---------------------------------------+ <== 4K aligned 45 * | golden contexts | 46 * +---------------------------------------+ 47 * | padding | 48 * +---------------------------------------+ <== 4K aligned 49 * | capture lists | 50 * +---------------------------------------+ 51 * | padding | 52 * +---------------------------------------+ <== 4K aligned 53 * | private data | 54 * +---------------------------------------+ 55 * | padding | 56 * +---------------------------------------+ <== 4K aligned 57 */ 58 struct __guc_ads_blob { 59 struct guc_ads ads; 60 struct guc_policies policies; 61 struct guc_gt_system_info system_info; 62 struct guc_engine_usage engine_usage; 63 /* From here on, location is dynamic! Refer to above diagram. */ 64 struct guc_mmio_reg regset[]; 65 } __packed; 66 67 #define ads_blob_read(guc_, field_) \ 68 iosys_map_rd_field(&(guc_)->ads_map, 0, struct __guc_ads_blob, field_) 69 70 #define ads_blob_write(guc_, field_, val_) \ 71 iosys_map_wr_field(&(guc_)->ads_map, 0, struct __guc_ads_blob, \ 72 field_, val_) 73 74 #define info_map_write(map_, field_, val_) \ 75 iosys_map_wr_field(map_, 0, struct guc_gt_system_info, field_, val_) 76 77 #define info_map_read(map_, field_) \ 78 iosys_map_rd_field(map_, 0, struct guc_gt_system_info, field_) 79 80 static u32 guc_ads_regset_size(struct intel_guc *guc) 81 { 82 GEM_BUG_ON(!guc->ads_regset_size); 83 return guc->ads_regset_size; 84 } 85 86 static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) 87 { 88 return PAGE_ALIGN(guc->ads_golden_ctxt_size); 89 } 90 91 static u32 guc_ads_capture_size(struct intel_guc *guc) 92 { 93 return PAGE_ALIGN(guc->ads_capture_size); 94 } 95 96 static u32 guc_ads_private_data_size(struct intel_guc *guc) 97 { 98 return PAGE_ALIGN(guc->fw.private_data_size); 99 } 100 101 static u32 guc_ads_regset_offset(struct intel_guc *guc) 102 { 103 return offsetof(struct __guc_ads_blob, regset); 104 } 105 106 static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc) 107 { 108 u32 offset; 109 110 offset = guc_ads_regset_offset(guc) + 111 guc_ads_regset_size(guc); 112 113 return PAGE_ALIGN(offset); 114 } 115 116 static u32 guc_ads_capture_offset(struct intel_guc *guc) 117 { 118 u32 offset; 119 120 offset = guc_ads_golden_ctxt_offset(guc) + 121 guc_ads_golden_ctxt_size(guc); 122 123 return PAGE_ALIGN(offset); 124 } 125 126 static u32 guc_ads_private_data_offset(struct intel_guc *guc) 127 { 128 u32 offset; 129 130 offset = guc_ads_capture_offset(guc) + 131 guc_ads_capture_size(guc); 132 133 return PAGE_ALIGN(offset); 134 } 135 136 static u32 guc_ads_blob_size(struct intel_guc *guc) 137 { 138 return guc_ads_private_data_offset(guc) + 139 guc_ads_private_data_size(guc); 140 } 141 142 static void guc_policies_init(struct intel_guc *guc) 143 { 144 struct intel_gt *gt = guc_to_gt(guc); 145 struct drm_i915_private *i915 = gt->i915; 146 u32 global_flags = 0; 147 148 ads_blob_write(guc, policies.dpc_promote_time, 149 GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US); 150 ads_blob_write(guc, policies.max_num_work_items, 151 GLOBAL_POLICY_MAX_NUM_WI); 152 153 if (i915->params.reset < 2) 154 global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET; 155 156 ads_blob_write(guc, policies.global_flags, global_flags); 157 ads_blob_write(guc, policies.is_valid, 1); 158 } 159 160 void intel_guc_ads_print_policy_info(struct intel_guc *guc, 161 struct drm_printer *dp) 162 { 163 if (unlikely(iosys_map_is_null(&guc->ads_map))) 164 return; 165 166 drm_printf(dp, "Global scheduling policies:\n"); 167 drm_printf(dp, " DPC promote time = %u\n", 168 ads_blob_read(guc, policies.dpc_promote_time)); 169 drm_printf(dp, " Max num work items = %u\n", 170 ads_blob_read(guc, policies.max_num_work_items)); 171 drm_printf(dp, " Flags = %u\n", 172 ads_blob_read(guc, policies.global_flags)); 173 } 174 175 static int guc_action_policies_update(struct intel_guc *guc, u32 policy_offset) 176 { 177 u32 action[] = { 178 INTEL_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE, 179 policy_offset 180 }; 181 182 return intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true); 183 } 184 185 int intel_guc_global_policies_update(struct intel_guc *guc) 186 { 187 struct intel_gt *gt = guc_to_gt(guc); 188 u32 scheduler_policies; 189 intel_wakeref_t wakeref; 190 int ret; 191 192 if (iosys_map_is_null(&guc->ads_map)) 193 return -EOPNOTSUPP; 194 195 scheduler_policies = ads_blob_read(guc, ads.scheduler_policies); 196 GEM_BUG_ON(!scheduler_policies); 197 198 guc_policies_init(guc); 199 200 if (!intel_guc_is_ready(guc)) 201 return 0; 202 203 with_intel_runtime_pm(>->i915->runtime_pm, wakeref) 204 ret = guc_action_policies_update(guc, scheduler_policies); 205 206 return ret; 207 } 208 209 static void guc_mapping_table_init(struct intel_gt *gt, 210 struct iosys_map *info_map) 211 { 212 unsigned int i, j; 213 struct intel_engine_cs *engine; 214 enum intel_engine_id id; 215 216 /* Table must be set to invalid values for entries not used */ 217 for (i = 0; i < GUC_MAX_ENGINE_CLASSES; ++i) 218 for (j = 0; j < GUC_MAX_INSTANCES_PER_CLASS; ++j) 219 info_map_write(info_map, mapping_table[i][j], 220 GUC_MAX_INSTANCES_PER_CLASS); 221 222 for_each_engine(engine, gt, id) { 223 u8 guc_class = engine_class_to_guc_class(engine->class); 224 225 info_map_write(info_map, mapping_table[guc_class][ilog2(engine->logical_mask)], 226 engine->instance); 227 } 228 } 229 230 /* 231 * The save/restore register list must be pre-calculated to a temporary 232 * buffer before it can be copied inside the ADS. 233 */ 234 struct temp_regset { 235 /* 236 * ptr to the section of the storage for the engine currently being 237 * worked on 238 */ 239 struct guc_mmio_reg *registers; 240 /* ptr to the base of the allocated storage for all engines */ 241 struct guc_mmio_reg *storage; 242 u32 storage_used; 243 u32 storage_max; 244 }; 245 246 static int guc_mmio_reg_cmp(const void *a, const void *b) 247 { 248 const struct guc_mmio_reg *ra = a; 249 const struct guc_mmio_reg *rb = b; 250 251 return (int)ra->offset - (int)rb->offset; 252 } 253 254 static struct guc_mmio_reg * __must_check 255 __mmio_reg_add(struct temp_regset *regset, struct guc_mmio_reg *reg) 256 { 257 u32 pos = regset->storage_used; 258 struct guc_mmio_reg *slot; 259 260 if (pos >= regset->storage_max) { 261 size_t size = ALIGN((pos + 1) * sizeof(*slot), PAGE_SIZE); 262 #ifdef __linux__ 263 struct guc_mmio_reg *r = krealloc(regset->storage, 264 size, GFP_KERNEL); 265 if (!r) { 266 WARN_ONCE(1, "Incomplete regset list: can't add register (%d)\n", 267 -ENOMEM); 268 return ERR_PTR(-ENOMEM); 269 } 270 #else 271 struct guc_mmio_reg *r = kmalloc(size, GFP_KERNEL); 272 if (!r) { 273 WARN_ONCE(1, "Incomplete regset list: can't add register (%d)\n", 274 -ENOMEM); 275 return ERR_PTR(-ENOMEM); 276 } 277 memcpy(r, regset->storage, 278 ALIGN((pos) * sizeof(*slot), PAGE_SIZE)); 279 kfree(regset->storage); 280 #endif 281 282 regset->registers = r + (regset->registers - regset->storage); 283 regset->storage = r; 284 regset->storage_max = size / sizeof(*slot); 285 } 286 287 slot = ®set->storage[pos]; 288 regset->storage_used++; 289 *slot = *reg; 290 291 return slot; 292 } 293 294 static long __must_check guc_mmio_reg_add(struct intel_gt *gt, 295 struct temp_regset *regset, 296 u32 offset, u32 flags) 297 { 298 u32 count = regset->storage_used - (regset->registers - regset->storage); 299 struct guc_mmio_reg entry = { 300 .offset = offset, 301 .flags = flags, 302 }; 303 struct guc_mmio_reg *slot; 304 305 /* 306 * The mmio list is built using separate lists within the driver. 307 * It's possible that at some point we may attempt to add the same 308 * register more than once. Do not consider this an error; silently 309 * move on if the register is already in the list. 310 */ 311 if (bsearch(&entry, regset->registers, count, 312 sizeof(entry), guc_mmio_reg_cmp)) 313 return 0; 314 315 slot = __mmio_reg_add(regset, &entry); 316 if (IS_ERR(slot)) 317 return PTR_ERR(slot); 318 319 while (slot-- > regset->registers) { 320 GEM_BUG_ON(slot[0].offset == slot[1].offset); 321 if (slot[1].offset > slot[0].offset) 322 break; 323 324 swap(slot[1], slot[0]); 325 } 326 327 return 0; 328 } 329 330 #define GUC_MMIO_REG_ADD(gt, regset, reg, masked) \ 331 guc_mmio_reg_add(gt, \ 332 regset, \ 333 i915_mmio_reg_offset(reg), \ 334 (masked) ? GUC_REGSET_MASKED : 0) 335 336 #define GUC_REGSET_STEERING(group, instance) ( \ 337 FIELD_PREP(GUC_REGSET_STEERING_GROUP, (group)) | \ 338 FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, (instance)) | \ 339 GUC_REGSET_NEEDS_STEERING \ 340 ) 341 342 static long __must_check guc_mcr_reg_add(struct intel_gt *gt, 343 struct temp_regset *regset, 344 i915_mcr_reg_t reg, u32 flags) 345 { 346 u8 group, inst; 347 348 /* 349 * The GuC doesn't have a default steering, so we need to explicitly 350 * steer all registers that need steering. However, we do not keep track 351 * of all the steering ranges, only of those that have a chance of using 352 * a non-default steering from the i915 pov. Instead of adding such 353 * tracking, it is easier to just program the default steering for all 354 * regs that don't need a non-default one. 355 */ 356 intel_gt_mcr_get_nonterminated_steering(gt, reg, &group, &inst); 357 flags |= GUC_REGSET_STEERING(group, inst); 358 359 return guc_mmio_reg_add(gt, regset, i915_mmio_reg_offset(reg), flags); 360 } 361 362 #define GUC_MCR_REG_ADD(gt, regset, reg, masked) \ 363 guc_mcr_reg_add(gt, \ 364 regset, \ 365 (reg), \ 366 (masked) ? GUC_REGSET_MASKED : 0) 367 368 static int guc_mmio_regset_init(struct temp_regset *regset, 369 struct intel_engine_cs *engine) 370 { 371 struct intel_gt *gt = engine->gt; 372 const u32 base = engine->mmio_base; 373 struct i915_wa_list *wal = &engine->wa_list; 374 struct i915_wa *wa; 375 unsigned int i; 376 int ret = 0; 377 378 /* 379 * Each engine's registers point to a new start relative to 380 * storage 381 */ 382 regset->registers = regset->storage + regset->storage_used; 383 384 ret |= GUC_MMIO_REG_ADD(gt, regset, RING_MODE_GEN7(base), true); 385 ret |= GUC_MMIO_REG_ADD(gt, regset, RING_HWS_PGA(base), false); 386 ret |= GUC_MMIO_REG_ADD(gt, regset, RING_IMR(base), false); 387 388 if ((engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) && 389 CCS_MASK(engine->gt)) 390 ret |= GUC_MMIO_REG_ADD(gt, regset, GEN12_RCU_MODE, true); 391 392 for (i = 0, wa = wal->list; i < wal->count; i++, wa++) 393 ret |= GUC_MMIO_REG_ADD(gt, regset, wa->reg, wa->masked_reg); 394 395 /* Be extra paranoid and include all whitelist registers. */ 396 for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) 397 ret |= GUC_MMIO_REG_ADD(gt, regset, 398 RING_FORCE_TO_NONPRIV(base, i), 399 false); 400 401 /* add in local MOCS registers */ 402 for (i = 0; i < LNCFCMOCS_REG_COUNT; i++) 403 if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) 404 ret |= GUC_MCR_REG_ADD(gt, regset, XEHP_LNCFCMOCS(i), false); 405 else 406 ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false); 407 408 if (GRAPHICS_VER(engine->i915) >= 12) { 409 ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL0, false); 410 ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL1, false); 411 ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL2, false); 412 ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL3, false); 413 ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL4, false); 414 ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL5, false); 415 ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL6, false); 416 } 417 418 return ret ? -1 : 0; 419 } 420 421 static long guc_mmio_reg_state_create(struct intel_guc *guc) 422 { 423 struct intel_gt *gt = guc_to_gt(guc); 424 struct intel_engine_cs *engine; 425 enum intel_engine_id id; 426 struct temp_regset temp_set = {}; 427 long total = 0; 428 long ret; 429 430 for_each_engine(engine, gt, id) { 431 u32 used = temp_set.storage_used; 432 433 ret = guc_mmio_regset_init(&temp_set, engine); 434 if (ret < 0) 435 goto fail_regset_init; 436 437 guc->ads_regset_count[id] = temp_set.storage_used - used; 438 total += guc->ads_regset_count[id]; 439 } 440 441 guc->ads_regset = temp_set.storage; 442 443 guc_dbg(guc, "Used %zu KB for temporary ADS regset\n", 444 (temp_set.storage_max * sizeof(struct guc_mmio_reg)) >> 10); 445 446 return total * sizeof(struct guc_mmio_reg); 447 448 fail_regset_init: 449 kfree(temp_set.storage); 450 return ret; 451 } 452 453 static void guc_mmio_reg_state_init(struct intel_guc *guc) 454 { 455 struct intel_gt *gt = guc_to_gt(guc); 456 struct intel_engine_cs *engine; 457 enum intel_engine_id id; 458 u32 addr_ggtt, offset; 459 460 offset = guc_ads_regset_offset(guc); 461 addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; 462 463 iosys_map_memcpy_to(&guc->ads_map, offset, guc->ads_regset, 464 guc->ads_regset_size); 465 466 for_each_engine(engine, gt, id) { 467 u32 count = guc->ads_regset_count[id]; 468 u8 guc_class; 469 470 /* Class index is checked in class converter */ 471 GEM_BUG_ON(engine->instance >= GUC_MAX_INSTANCES_PER_CLASS); 472 473 guc_class = engine_class_to_guc_class(engine->class); 474 475 if (!count) { 476 ads_blob_write(guc, 477 ads.reg_state_list[guc_class][engine->instance].address, 478 0); 479 ads_blob_write(guc, 480 ads.reg_state_list[guc_class][engine->instance].count, 481 0); 482 continue; 483 } 484 485 ads_blob_write(guc, 486 ads.reg_state_list[guc_class][engine->instance].address, 487 addr_ggtt); 488 ads_blob_write(guc, 489 ads.reg_state_list[guc_class][engine->instance].count, 490 count); 491 492 addr_ggtt += count * sizeof(struct guc_mmio_reg); 493 } 494 } 495 496 static void fill_engine_enable_masks(struct intel_gt *gt, 497 struct iosys_map *info_map) 498 { 499 info_map_write(info_map, engine_enabled_masks[GUC_RENDER_CLASS], RCS_MASK(gt)); 500 info_map_write(info_map, engine_enabled_masks[GUC_COMPUTE_CLASS], CCS_MASK(gt)); 501 info_map_write(info_map, engine_enabled_masks[GUC_BLITTER_CLASS], BCS_MASK(gt)); 502 info_map_write(info_map, engine_enabled_masks[GUC_VIDEO_CLASS], VDBOX_MASK(gt)); 503 info_map_write(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS], VEBOX_MASK(gt)); 504 505 /* The GSC engine is an instance (6) of OTHER_CLASS */ 506 if (gt->engine[GSC0]) 507 info_map_write(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS], 508 BIT(gt->engine[GSC0]->instance)); 509 } 510 511 #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) 512 #define XEHP_LR_HW_CONTEXT_SIZE (96 * sizeof(u32)) 513 #define LR_HW_CONTEXT_SZ(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50) ? \ 514 XEHP_LR_HW_CONTEXT_SIZE : \ 515 LR_HW_CONTEXT_SIZE) 516 #define LRC_SKIP_SIZE(i915) (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SZ(i915)) 517 static int guc_prep_golden_context(struct intel_guc *guc) 518 { 519 struct intel_gt *gt = guc_to_gt(guc); 520 u32 addr_ggtt, offset; 521 u32 total_size = 0, alloc_size, real_size; 522 u8 engine_class, guc_class; 523 struct guc_gt_system_info local_info; 524 struct iosys_map info_map; 525 526 /* 527 * Reserve the memory for the golden contexts and point GuC at it but 528 * leave it empty for now. The context data will be filled in later 529 * once there is something available to put there. 530 * 531 * Note that the HWSP and ring context are not included. 532 * 533 * Note also that the storage must be pinned in the GGTT, so that the 534 * address won't change after GuC has been told where to find it. The 535 * GuC will also validate that the LRC base + size fall within the 536 * allowed GGTT range. 537 */ 538 if (!iosys_map_is_null(&guc->ads_map)) { 539 offset = guc_ads_golden_ctxt_offset(guc); 540 addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; 541 info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map, 542 offsetof(struct __guc_ads_blob, system_info)); 543 } else { 544 memset(&local_info, 0, sizeof(local_info)); 545 iosys_map_set_vaddr(&info_map, &local_info); 546 fill_engine_enable_masks(gt, &info_map); 547 } 548 549 for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) { 550 guc_class = engine_class_to_guc_class(engine_class); 551 552 if (!info_map_read(&info_map, engine_enabled_masks[guc_class])) 553 continue; 554 555 real_size = intel_engine_context_size(gt, engine_class); 556 alloc_size = PAGE_ALIGN(real_size); 557 total_size += alloc_size; 558 559 if (iosys_map_is_null(&guc->ads_map)) 560 continue; 561 562 /* 563 * This interface is slightly confusing. We need to pass the 564 * base address of the full golden context and the size of just 565 * the engine state, which is the section of the context image 566 * that starts after the execlists context. This is required to 567 * allow the GuC to restore just the engine state when a 568 * watchdog reset occurs. 569 * We calculate the engine state size by removing the size of 570 * what comes before it in the context image (which is identical 571 * on all engines). 572 */ 573 ads_blob_write(guc, ads.eng_state_size[guc_class], 574 real_size - LRC_SKIP_SIZE(gt->i915)); 575 ads_blob_write(guc, ads.golden_context_lrca[guc_class], 576 addr_ggtt); 577 578 addr_ggtt += alloc_size; 579 } 580 581 /* Make sure current size matches what we calculated previously */ 582 if (guc->ads_golden_ctxt_size) 583 GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size); 584 585 return total_size; 586 } 587 588 static struct intel_engine_cs *find_engine_state(struct intel_gt *gt, u8 engine_class) 589 { 590 struct intel_engine_cs *engine; 591 enum intel_engine_id id; 592 593 for_each_engine(engine, gt, id) { 594 if (engine->class != engine_class) 595 continue; 596 597 if (!engine->default_state) 598 continue; 599 600 return engine; 601 } 602 603 return NULL; 604 } 605 606 static void guc_init_golden_context(struct intel_guc *guc) 607 { 608 struct intel_engine_cs *engine; 609 struct intel_gt *gt = guc_to_gt(guc); 610 unsigned long offset; 611 u32 addr_ggtt, total_size = 0, alloc_size, real_size; 612 u8 engine_class, guc_class; 613 614 if (!intel_uc_uses_guc_submission(>->uc)) 615 return; 616 617 GEM_BUG_ON(iosys_map_is_null(&guc->ads_map)); 618 619 /* 620 * Go back and fill in the golden context data now that it is 621 * available. 622 */ 623 offset = guc_ads_golden_ctxt_offset(guc); 624 addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; 625 626 for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) { 627 guc_class = engine_class_to_guc_class(engine_class); 628 if (!ads_blob_read(guc, system_info.engine_enabled_masks[guc_class])) 629 continue; 630 631 real_size = intel_engine_context_size(gt, engine_class); 632 alloc_size = PAGE_ALIGN(real_size); 633 total_size += alloc_size; 634 635 engine = find_engine_state(gt, engine_class); 636 if (!engine) { 637 guc_err(guc, "No engine state recorded for class %d!\n", 638 engine_class); 639 ads_blob_write(guc, ads.eng_state_size[guc_class], 0); 640 ads_blob_write(guc, ads.golden_context_lrca[guc_class], 0); 641 continue; 642 } 643 644 GEM_BUG_ON(ads_blob_read(guc, ads.eng_state_size[guc_class]) != 645 real_size - LRC_SKIP_SIZE(gt->i915)); 646 GEM_BUG_ON(ads_blob_read(guc, ads.golden_context_lrca[guc_class]) != addr_ggtt); 647 648 addr_ggtt += alloc_size; 649 650 uao_read_to_iosys_map(engine->default_state, 0, &guc->ads_map, 651 offset, real_size); 652 offset += alloc_size; 653 } 654 655 GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size); 656 } 657 658 static u32 guc_get_capture_engine_mask(struct iosys_map *info_map, u32 capture_class) 659 { 660 u32 mask; 661 662 switch (capture_class) { 663 case GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE: 664 mask = info_map_read(info_map, engine_enabled_masks[GUC_RENDER_CLASS]); 665 mask |= info_map_read(info_map, engine_enabled_masks[GUC_COMPUTE_CLASS]); 666 break; 667 668 case GUC_CAPTURE_LIST_CLASS_VIDEO: 669 mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEO_CLASS]); 670 break; 671 672 case GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE: 673 mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS]); 674 break; 675 676 case GUC_CAPTURE_LIST_CLASS_BLITTER: 677 mask = info_map_read(info_map, engine_enabled_masks[GUC_BLITTER_CLASS]); 678 break; 679 680 case GUC_CAPTURE_LIST_CLASS_GSC_OTHER: 681 mask = info_map_read(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS]); 682 break; 683 684 default: 685 mask = 0; 686 } 687 688 return mask; 689 } 690 691 static int 692 guc_capture_prep_lists(struct intel_guc *guc) 693 { 694 struct intel_gt *gt = guc_to_gt(guc); 695 u32 ads_ggtt, capture_offset, null_ggtt, total_size = 0; 696 struct guc_gt_system_info local_info; 697 struct iosys_map info_map; 698 bool ads_is_mapped; 699 size_t size = 0; 700 void *ptr; 701 int i, j; 702 703 ads_is_mapped = !iosys_map_is_null(&guc->ads_map); 704 if (ads_is_mapped) { 705 capture_offset = guc_ads_capture_offset(guc); 706 ads_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma); 707 info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map, 708 offsetof(struct __guc_ads_blob, system_info)); 709 } else { 710 memset(&local_info, 0, sizeof(local_info)); 711 iosys_map_set_vaddr(&info_map, &local_info); 712 fill_engine_enable_masks(gt, &info_map); 713 } 714 715 /* first, set aside the first page for a capture_list with zero descriptors */ 716 total_size = PAGE_SIZE; 717 if (ads_is_mapped) { 718 if (!intel_guc_capture_getnullheader(guc, &ptr, &size)) 719 iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); 720 null_ggtt = ads_ggtt + capture_offset; 721 capture_offset += PAGE_SIZE; 722 } 723 724 for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { 725 for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) { 726 u32 engine_mask = guc_get_capture_engine_mask(&info_map, j); 727 728 /* null list if we dont have said engine or list */ 729 if (!engine_mask) { 730 if (ads_is_mapped) { 731 ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); 732 ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); 733 } 734 continue; 735 } 736 if (intel_guc_capture_getlistsize(guc, i, 737 GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, 738 j, &size)) { 739 if (ads_is_mapped) 740 ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); 741 goto engine_instance_list; 742 } 743 total_size += size; 744 if (ads_is_mapped) { 745 if (total_size > guc->ads_capture_size || 746 intel_guc_capture_getlist(guc, i, 747 GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, 748 j, &ptr)) { 749 ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); 750 continue; 751 } 752 ads_blob_write(guc, ads.capture_class[i][j], ads_ggtt + 753 capture_offset); 754 iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); 755 capture_offset += size; 756 } 757 engine_instance_list: 758 if (intel_guc_capture_getlistsize(guc, i, 759 GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, 760 j, &size)) { 761 if (ads_is_mapped) 762 ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); 763 continue; 764 } 765 total_size += size; 766 if (ads_is_mapped) { 767 if (total_size > guc->ads_capture_size || 768 intel_guc_capture_getlist(guc, i, 769 GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, 770 j, &ptr)) { 771 ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); 772 continue; 773 } 774 ads_blob_write(guc, ads.capture_instance[i][j], ads_ggtt + 775 capture_offset); 776 iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); 777 capture_offset += size; 778 } 779 } 780 if (intel_guc_capture_getlistsize(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &size)) { 781 if (ads_is_mapped) 782 ads_blob_write(guc, ads.capture_global[i], null_ggtt); 783 continue; 784 } 785 total_size += size; 786 if (ads_is_mapped) { 787 if (total_size > guc->ads_capture_size || 788 intel_guc_capture_getlist(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, 789 &ptr)) { 790 ads_blob_write(guc, ads.capture_global[i], null_ggtt); 791 continue; 792 } 793 ads_blob_write(guc, ads.capture_global[i], ads_ggtt + capture_offset); 794 iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); 795 capture_offset += size; 796 } 797 } 798 799 if (guc->ads_capture_size && guc->ads_capture_size != PAGE_ALIGN(total_size)) 800 guc_warn(guc, "ADS capture alloc size changed from %d to %d\n", 801 guc->ads_capture_size, PAGE_ALIGN(total_size)); 802 803 return PAGE_ALIGN(total_size); 804 } 805 806 static void __guc_ads_init(struct intel_guc *guc) 807 { 808 struct intel_gt *gt = guc_to_gt(guc); 809 struct drm_i915_private *i915 = gt->i915; 810 struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map, 811 offsetof(struct __guc_ads_blob, system_info)); 812 u32 base; 813 814 /* GuC scheduling policies */ 815 guc_policies_init(guc); 816 817 /* System info */ 818 fill_engine_enable_masks(gt, &info_map); 819 820 ads_blob_write(guc, system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_SLICE_ENABLED], 821 hweight8(gt->info.sseu.slice_mask)); 822 ads_blob_write(guc, system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_VDBOX_SFC_SUPPORT_MASK], 823 gt->info.vdbox_sfc_access); 824 825 if (GRAPHICS_VER(i915) >= 12 && !IS_DGFX(i915)) { 826 u32 distdbreg = intel_uncore_read(gt->uncore, 827 GEN12_DIST_DBS_POPULATED); 828 ads_blob_write(guc, 829 system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_DOORBELL_COUNT_PER_SQIDI], 830 ((distdbreg >> GEN12_DOORBELLS_PER_SQIDI_SHIFT) 831 & GEN12_DOORBELLS_PER_SQIDI) + 1); 832 } 833 834 /* Golden contexts for re-initialising after a watchdog reset */ 835 guc_prep_golden_context(guc); 836 837 guc_mapping_table_init(guc_to_gt(guc), &info_map); 838 839 base = intel_guc_ggtt_offset(guc, guc->ads_vma); 840 841 /* Lists for error capture debug */ 842 guc_capture_prep_lists(guc); 843 844 /* ADS */ 845 ads_blob_write(guc, ads.scheduler_policies, base + 846 offsetof(struct __guc_ads_blob, policies)); 847 ads_blob_write(guc, ads.gt_system_info, base + 848 offsetof(struct __guc_ads_blob, system_info)); 849 850 /* MMIO save/restore list */ 851 guc_mmio_reg_state_init(guc); 852 853 /* Private Data */ 854 ads_blob_write(guc, ads.private_data, base + 855 guc_ads_private_data_offset(guc)); 856 857 i915_gem_object_flush_map(guc->ads_vma->obj); 858 } 859 860 /** 861 * intel_guc_ads_create() - allocates and initializes GuC ADS. 862 * @guc: intel_guc struct 863 * 864 * GuC needs memory block (Additional Data Struct), where it will store 865 * some data. Allocate and initialize such memory block for GuC use. 866 */ 867 int intel_guc_ads_create(struct intel_guc *guc) 868 { 869 void *ads_blob; 870 u32 size; 871 int ret; 872 873 GEM_BUG_ON(guc->ads_vma); 874 875 /* 876 * Create reg state size dynamically on system memory to be copied to 877 * the final ads blob on gt init/reset 878 */ 879 ret = guc_mmio_reg_state_create(guc); 880 if (ret < 0) 881 return ret; 882 guc->ads_regset_size = ret; 883 884 /* Likewise the golden contexts: */ 885 ret = guc_prep_golden_context(guc); 886 if (ret < 0) 887 return ret; 888 guc->ads_golden_ctxt_size = ret; 889 890 /* Likewise the capture lists: */ 891 ret = guc_capture_prep_lists(guc); 892 if (ret < 0) 893 return ret; 894 guc->ads_capture_size = ret; 895 896 /* Now the total size can be determined: */ 897 size = guc_ads_blob_size(guc); 898 899 ret = intel_guc_allocate_and_map_vma(guc, size, &guc->ads_vma, 900 &ads_blob); 901 if (ret) 902 return ret; 903 904 if (i915_gem_object_is_lmem(guc->ads_vma->obj)) 905 iosys_map_set_vaddr_iomem(&guc->ads_map, (void __iomem *)ads_blob); 906 else 907 iosys_map_set_vaddr(&guc->ads_map, ads_blob); 908 909 __guc_ads_init(guc); 910 911 return 0; 912 } 913 914 void intel_guc_ads_init_late(struct intel_guc *guc) 915 { 916 /* 917 * The golden context setup requires the saved engine state from 918 * __engines_record_defaults(). However, that requires engines to be 919 * operational which means the ADS must already have been configured. 920 * Fortunately, the golden context state is not needed until a hang 921 * occurs, so it can be filled in during this late init phase. 922 */ 923 guc_init_golden_context(guc); 924 } 925 926 void intel_guc_ads_destroy(struct intel_guc *guc) 927 { 928 i915_vma_unpin_and_release(&guc->ads_vma, I915_VMA_RELEASE_MAP); 929 iosys_map_clear(&guc->ads_map); 930 kfree(guc->ads_regset); 931 } 932 933 static void guc_ads_private_data_reset(struct intel_guc *guc) 934 { 935 u32 size; 936 937 size = guc_ads_private_data_size(guc); 938 if (!size) 939 return; 940 941 iosys_map_memset(&guc->ads_map, guc_ads_private_data_offset(guc), 942 0, size); 943 } 944 945 /** 946 * intel_guc_ads_reset() - prepares GuC Additional Data Struct for reuse 947 * @guc: intel_guc struct 948 * 949 * GuC stores some data in ADS, which might be stale after a reset. 950 * Reinitialize whole ADS in case any part of it was corrupted during 951 * previous GuC run. 952 */ 953 void intel_guc_ads_reset(struct intel_guc *guc) 954 { 955 if (!guc->ads_vma) 956 return; 957 958 __guc_ads_init(guc); 959 960 guc_ads_private_data_reset(guc); 961 } 962 963 u32 intel_guc_engine_usage_offset(struct intel_guc *guc) 964 { 965 return intel_guc_ggtt_offset(guc, guc->ads_vma) + 966 offsetof(struct __guc_ads_blob, engine_usage); 967 } 968 969 struct iosys_map intel_guc_engine_usage_record_map(struct intel_engine_cs *engine) 970 { 971 struct intel_guc *guc = &engine->gt->uc.guc; 972 u8 guc_class = engine_class_to_guc_class(engine->class); 973 size_t offset = offsetof(struct __guc_ads_blob, 974 engine_usage.engines[guc_class][ilog2(engine->logical_mask)]); 975 976 return IOSYS_MAP_INIT_OFFSET(&guc->ads_map, offset); 977 } 978