1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021-2022 Intel Corporation 4 */ 5 6 #include <linux/types.h> 7 8 #include <drm/drm_print.h> 9 10 #include "gt/intel_engine_regs.h" 11 #include "gt/intel_gt.h" 12 #include "gt/intel_gt_mcr.h" 13 #include "gt/intel_gt_regs.h" 14 #include "gt/intel_lrc.h" 15 #include "guc_capture_fwif.h" 16 #include "intel_guc_capture.h" 17 #include "intel_guc_fwif.h" 18 #include "intel_guc_print.h" 19 #include "i915_drv.h" 20 #include "i915_gpu_error.h" 21 #include "i915_irq.h" 22 #include "i915_memcpy.h" 23 #include "i915_reg.h" 24 25 /* 26 * Define all device tables of GuC error capture register lists 27 * NOTE: For engine-registers, GuC only needs the register offsets 28 * from the engine-mmio-base 29 */ 30 #define COMMON_BASE_GLOBAL \ 31 { FORCEWAKE_MT, 0, 0, "FORCEWAKE" } 32 33 #define COMMON_GEN8BASE_GLOBAL \ 34 { ERROR_GEN6, 0, 0, "ERROR_GEN6" }, \ 35 { DONE_REG, 0, 0, "DONE_REG" }, \ 36 { HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN" } 37 38 #define GEN8_GLOBAL \ 39 { GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \ 40 { GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" } 41 42 #define COMMON_GEN12BASE_GLOBAL \ 43 { GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0" }, \ 44 { GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1" }, \ 45 { GEN12_AUX_ERR_DBG, 0, 0, "AUX_ERR_DBG" }, \ 46 { GEN12_GAM_DONE, 0, 0, "GAM_DONE" }, \ 47 { GEN12_RING_FAULT_REG, 0, 0, "FAULT_REG" } 48 49 #define COMMON_BASE_ENGINE_INSTANCE \ 50 { RING_PSMI_CTL(0), 0, 0, "RC PSMI" }, \ 51 { RING_ESR(0), 0, 0, "ESR" }, \ 52 { RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW" }, \ 53 { RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UDW" }, \ 54 { RING_IPEIR(0), 0, 0, "IPEIR" }, \ 55 { RING_IPEHR(0), 0, 0, "IPEHR" }, \ 56 { RING_INSTPS(0), 0, 0, "INSTPS" }, \ 57 { RING_BBADDR(0), 0, 0, "RING_BBADDR_LOW32" }, \ 58 { RING_BBADDR_UDW(0), 0, 0, "RING_BBADDR_UP32" }, \ 59 { RING_BBSTATE(0), 0, 0, "BB_STATE" }, \ 60 { CCID(0), 0, 0, "CCID" }, \ 61 { RING_ACTHD(0), 0, 0, "ACTHD_LDW" }, \ 62 { RING_ACTHD_UDW(0), 0, 0, "ACTHD_UDW" }, \ 63 { RING_INSTPM(0), 0, 0, "INSTPM" }, \ 64 { RING_INSTDONE(0), 0, 0, "INSTDONE" }, \ 65 { RING_NOPID(0), 0, 0, "RING_NOPID" }, \ 66 { RING_START(0), 0, 0, "START" }, \ 67 { RING_HEAD(0), 0, 0, "HEAD" }, \ 68 { RING_TAIL(0), 0, 0, "TAIL" }, \ 69 { RING_CTL(0), 0, 0, "CTL" }, \ 70 { RING_MI_MODE(0), 0, 0, "MODE" }, \ 71 { RING_CONTEXT_CONTROL(0), 0, 0, "RING_CONTEXT_CONTROL" }, \ 72 { RING_HWS_PGA(0), 0, 0, "HWS" }, \ 73 { RING_MODE_GEN7(0), 0, 0, "GFX_MODE" }, \ 74 { GEN8_RING_PDP_LDW(0, 0), 0, 0, "PDP0_LDW" }, \ 75 { GEN8_RING_PDP_UDW(0, 0), 0, 0, "PDP0_UDW" }, \ 76 { GEN8_RING_PDP_LDW(0, 1), 0, 0, "PDP1_LDW" }, \ 77 { GEN8_RING_PDP_UDW(0, 1), 0, 0, "PDP1_UDW" }, \ 78 { GEN8_RING_PDP_LDW(0, 2), 0, 0, "PDP2_LDW" }, \ 79 { GEN8_RING_PDP_UDW(0, 2), 0, 0, "PDP2_UDW" }, \ 80 { GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW" }, \ 81 { GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW" } 82 83 #define COMMON_BASE_HAS_EU \ 84 { EIR, 0, 0, "EIR" } 85 86 #define COMMON_BASE_RENDER \ 87 { GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE" } 88 89 #define COMMON_GEN12BASE_RENDER \ 90 { GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA" }, \ 91 { GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2" } 92 93 #define COMMON_GEN12BASE_VEC \ 94 { GEN12_SFC_DONE(0), 0, 0, "SFC_DONE[0]" }, \ 95 { GEN12_SFC_DONE(1), 0, 0, "SFC_DONE[1]" }, \ 96 { GEN12_SFC_DONE(2), 0, 0, "SFC_DONE[2]" }, \ 97 { GEN12_SFC_DONE(3), 0, 0, "SFC_DONE[3]" } 98 99 /* XE_LP Global */ 100 static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { 101 COMMON_BASE_GLOBAL, 102 COMMON_GEN8BASE_GLOBAL, 103 COMMON_GEN12BASE_GLOBAL, 104 }; 105 106 /* XE_LP Render / Compute Per-Class */ 107 static const struct __guc_mmio_reg_descr xe_lp_rc_class_regs[] = { 108 COMMON_BASE_HAS_EU, 109 COMMON_BASE_RENDER, 110 COMMON_GEN12BASE_RENDER, 111 }; 112 113 /* GEN8+ Render / Compute Per-Engine-Instance */ 114 static const struct __guc_mmio_reg_descr gen8_rc_inst_regs[] = { 115 COMMON_BASE_ENGINE_INSTANCE, 116 }; 117 118 /* GEN8+ Media Decode/Encode Per-Engine-Instance */ 119 static const struct __guc_mmio_reg_descr gen8_vd_inst_regs[] = { 120 COMMON_BASE_ENGINE_INSTANCE, 121 }; 122 123 /* XE_LP Video Enhancement Per-Class */ 124 static const struct __guc_mmio_reg_descr xe_lp_vec_class_regs[] = { 125 COMMON_GEN12BASE_VEC, 126 }; 127 128 /* GEN8+ Video Enhancement Per-Engine-Instance */ 129 static const struct __guc_mmio_reg_descr gen8_vec_inst_regs[] = { 130 COMMON_BASE_ENGINE_INSTANCE, 131 }; 132 133 /* GEN8+ Blitter Per-Engine-Instance */ 134 static const struct __guc_mmio_reg_descr gen8_blt_inst_regs[] = { 135 COMMON_BASE_ENGINE_INSTANCE, 136 }; 137 138 /* XE_LP - GSC Per-Engine-Instance */ 139 static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = { 140 COMMON_BASE_ENGINE_INSTANCE, 141 }; 142 143 /* GEN8 - Global */ 144 static const struct __guc_mmio_reg_descr gen8_global_regs[] = { 145 COMMON_BASE_GLOBAL, 146 COMMON_GEN8BASE_GLOBAL, 147 GEN8_GLOBAL, 148 }; 149 150 static const struct __guc_mmio_reg_descr gen8_rc_class_regs[] = { 151 COMMON_BASE_HAS_EU, 152 COMMON_BASE_RENDER, 153 }; 154 155 /* 156 * Empty list to prevent warnings about unknown class/instance types 157 * as not all class/instanace types have entries on all platforms. 158 */ 159 static const struct __guc_mmio_reg_descr empty_regs_list[] = { 160 }; 161 162 #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) 163 #define TO_GCAP_DEF_TYPE(x) (GUC_CAPTURE_LIST_TYPE_##x) 164 #define MAKE_REGLIST(regslist, regsowner, regstype, class) \ 165 { \ 166 regslist, \ 167 ARRAY_SIZE(regslist), \ 168 TO_GCAP_DEF_OWNER(regsowner), \ 169 TO_GCAP_DEF_TYPE(regstype), \ 170 class, \ 171 NULL, \ 172 } 173 174 /* List of lists */ 175 static const struct __guc_mmio_reg_descr_group gen8_lists[] = { 176 MAKE_REGLIST(gen8_global_regs, PF, GLOBAL, 0), 177 MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), 178 MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), 179 MAKE_REGLIST(gen8_rc_class_regs, PF, ENGINE_CLASS, GUC_COMPUTE_CLASS), 180 MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_COMPUTE_CLASS), 181 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), 182 MAKE_REGLIST(gen8_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), 183 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), 184 MAKE_REGLIST(gen8_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), 185 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), 186 MAKE_REGLIST(gen8_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), 187 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_GSC_OTHER_CLASS), 188 MAKE_REGLIST(empty_regs_list, PF, ENGINE_INSTANCE, GUC_GSC_OTHER_CLASS), 189 {} 190 }; 191 192 static const struct __guc_mmio_reg_descr_group xe_lp_lists[] = { 193 MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 194 MAKE_REGLIST(xe_lp_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), 195 MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), 196 MAKE_REGLIST(xe_lp_rc_class_regs, PF, ENGINE_CLASS, GUC_COMPUTE_CLASS), 197 MAKE_REGLIST(gen8_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_COMPUTE_CLASS), 198 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), 199 MAKE_REGLIST(gen8_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), 200 MAKE_REGLIST(xe_lp_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), 201 MAKE_REGLIST(gen8_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), 202 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), 203 MAKE_REGLIST(gen8_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), 204 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_GSC_OTHER_CLASS), 205 MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_GSC_OTHER_CLASS), 206 {} 207 }; 208 209 static const struct __guc_mmio_reg_descr_group * 210 guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, 211 u32 owner, u32 type, u32 id) 212 { 213 int i; 214 215 if (!reglists) 216 return NULL; 217 218 for (i = 0; reglists[i].list; ++i) { 219 if (reglists[i].owner == owner && reglists[i].type == type && 220 (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) 221 return ®lists[i]; 222 } 223 224 return NULL; 225 } 226 227 static struct __guc_mmio_reg_descr_group * 228 guc_capture_get_one_ext_list(struct __guc_mmio_reg_descr_group *reglists, 229 u32 owner, u32 type, u32 id) 230 { 231 int i; 232 233 if (!reglists) 234 return NULL; 235 236 for (i = 0; reglists[i].extlist; ++i) { 237 if (reglists[i].owner == owner && reglists[i].type == type && 238 (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) 239 return ®lists[i]; 240 } 241 242 return NULL; 243 } 244 245 static void guc_capture_free_extlists(struct __guc_mmio_reg_descr_group *reglists) 246 { 247 int i = 0; 248 249 if (!reglists) 250 return; 251 252 while (reglists[i].extlist) 253 kfree(reglists[i++].extlist); 254 } 255 256 struct __ext_steer_reg { 257 const char *name; 258 i915_mcr_reg_t reg; 259 }; 260 261 static const struct __ext_steer_reg gen8_extregs[] = { 262 {"GEN8_SAMPLER_INSTDONE", GEN8_SAMPLER_INSTDONE}, 263 {"GEN8_ROW_INSTDONE", GEN8_ROW_INSTDONE} 264 }; 265 266 static const struct __ext_steer_reg xehpg_extregs[] = { 267 {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG} 268 }; 269 270 static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext, 271 const struct __ext_steer_reg *extlist, 272 int slice_id, int subslice_id) 273 { 274 ext->reg = _MMIO(i915_mmio_reg_offset(extlist->reg)); 275 ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id); 276 ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id); 277 ext->regname = extlist->name; 278 } 279 280 static int 281 __alloc_ext_regs(struct __guc_mmio_reg_descr_group *newlist, 282 const struct __guc_mmio_reg_descr_group *rootlist, int num_regs) 283 { 284 struct __guc_mmio_reg_descr *list; 285 286 list = kcalloc(num_regs, sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL); 287 if (!list) 288 return -ENOMEM; 289 290 newlist->extlist = list; 291 newlist->num_regs = num_regs; 292 newlist->owner = rootlist->owner; 293 newlist->engine = rootlist->engine; 294 newlist->type = rootlist->type; 295 296 return 0; 297 } 298 299 static void 300 guc_capture_alloc_steered_lists(struct intel_guc *guc, 301 const struct __guc_mmio_reg_descr_group *lists) 302 { 303 struct intel_gt *gt = guc_to_gt(guc); 304 int slice, subslice, iter, i, num_steer_regs, num_tot_regs = 0; 305 const struct __guc_mmio_reg_descr_group *list; 306 struct __guc_mmio_reg_descr_group *extlists; 307 struct __guc_mmio_reg_descr *extarray; 308 struct sseu_dev_info *sseu; 309 bool has_xehpg_extregs; 310 311 /* steered registers currently only exist for the render-class */ 312 list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, 313 GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); 314 /* skip if extlists was previously allocated */ 315 if (!list || guc->capture->extlists) 316 return; 317 318 has_xehpg_extregs = GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 55); 319 320 num_steer_regs = ARRAY_SIZE(gen8_extregs); 321 if (has_xehpg_extregs) 322 num_steer_regs += ARRAY_SIZE(xehpg_extregs); 323 324 sseu = >->info.sseu; 325 for_each_ss_steering(iter, gt, slice, subslice) 326 num_tot_regs += num_steer_regs; 327 328 if (!num_tot_regs) 329 return; 330 331 /* allocate an extra for an end marker */ 332 extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); 333 if (!extlists) 334 return; 335 336 if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) { 337 kfree(extlists); 338 return; 339 } 340 341 extarray = extlists[0].extlist; 342 for_each_ss_steering(iter, gt, slice, subslice) { 343 for (i = 0; i < ARRAY_SIZE(gen8_extregs); ++i) { 344 __fill_ext_reg(extarray, &gen8_extregs[i], slice, subslice); 345 ++extarray; 346 } 347 348 if (has_xehpg_extregs) { 349 for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) { 350 __fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice); 351 ++extarray; 352 } 353 } 354 } 355 356 guc_dbg(guc, "capture found %d ext-regs.\n", num_tot_regs); 357 guc->capture->extlists = extlists; 358 } 359 360 static const struct __guc_mmio_reg_descr_group * 361 guc_capture_get_device_reglist(struct intel_guc *guc) 362 { 363 struct drm_i915_private *i915 = guc_to_gt(guc)->i915; 364 const struct __guc_mmio_reg_descr_group *lists; 365 366 if (GRAPHICS_VER(i915) >= 12) 367 lists = xe_lp_lists; 368 else 369 lists = gen8_lists; 370 371 /* 372 * For certain engine classes, there are slice and subslice 373 * level registers requiring steering. We allocate and populate 374 * these at init time based on hw config add it as an extension 375 * list at the end of the pre-populated render list. 376 */ 377 guc_capture_alloc_steered_lists(guc, lists); 378 379 return lists; 380 } 381 382 static const char * 383 __stringify_type(u32 type) 384 { 385 switch (type) { 386 case GUC_CAPTURE_LIST_TYPE_GLOBAL: 387 return "Global"; 388 case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: 389 return "Class"; 390 case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: 391 return "Instance"; 392 default: 393 break; 394 } 395 396 return "unknown"; 397 } 398 399 static const char * 400 __stringify_engclass(u32 class) 401 { 402 switch (class) { 403 case GUC_RENDER_CLASS: 404 return "Render"; 405 case GUC_VIDEO_CLASS: 406 return "Video"; 407 case GUC_VIDEOENHANCE_CLASS: 408 return "VideoEnhance"; 409 case GUC_BLITTER_CLASS: 410 return "Blitter"; 411 case GUC_COMPUTE_CLASS: 412 return "Compute"; 413 case GUC_GSC_OTHER_CLASS: 414 return "GSC-Other"; 415 default: 416 break; 417 } 418 419 return "unknown"; 420 } 421 422 static int 423 guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, 424 struct guc_mmio_reg *ptr, u16 num_entries) 425 { 426 u32 i = 0, j = 0; 427 const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; 428 struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists; 429 const struct __guc_mmio_reg_descr_group *match; 430 struct __guc_mmio_reg_descr_group *matchext; 431 432 if (!reglists) 433 return -ENODEV; 434 435 match = guc_capture_get_one_list(reglists, owner, type, classid); 436 if (!match) 437 return -ENODATA; 438 439 for (i = 0; i < num_entries && i < match->num_regs; ++i) { 440 ptr[i].offset = match->list[i].reg.reg; 441 ptr[i].value = 0xDEADF00D; 442 ptr[i].flags = match->list[i].flags; 443 ptr[i].mask = match->list[i].mask; 444 } 445 446 matchext = guc_capture_get_one_ext_list(extlists, owner, type, classid); 447 if (matchext) { 448 for (i = match->num_regs, j = 0; i < num_entries && 449 i < (match->num_regs + matchext->num_regs) && 450 j < matchext->num_regs; ++i, ++j) { 451 ptr[i].offset = matchext->extlist[j].reg.reg; 452 ptr[i].value = 0xDEADF00D; 453 ptr[i].flags = matchext->extlist[j].flags; 454 ptr[i].mask = matchext->extlist[j].mask; 455 } 456 } 457 if (i < num_entries) 458 guc_dbg(guc, "Got short capture reglist init: %d out %d.\n", i, num_entries); 459 460 return 0; 461 } 462 463 static int 464 guc_cap_list_num_regs(struct intel_guc_state_capture *gc, u32 owner, u32 type, u32 classid) 465 { 466 const struct __guc_mmio_reg_descr_group *match; 467 struct __guc_mmio_reg_descr_group *matchext; 468 int num_regs; 469 470 match = guc_capture_get_one_list(gc->reglists, owner, type, classid); 471 if (!match) 472 return 0; 473 474 num_regs = match->num_regs; 475 476 matchext = guc_capture_get_one_ext_list(gc->extlists, owner, type, classid); 477 if (matchext) 478 num_regs += matchext->num_regs; 479 480 return num_regs; 481 } 482 483 static int 484 guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, 485 size_t *size, bool is_purpose_est) 486 { 487 struct intel_guc_state_capture *gc = guc->capture; 488 struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid]; 489 int num_regs; 490 491 if (!gc->reglists) { 492 guc_warn(guc, "No capture reglist for this device\n"); 493 return -ENODEV; 494 } 495 496 if (cache->is_valid) { 497 *size = cache->size; 498 return cache->status; 499 } 500 501 if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF && 502 !guc_capture_get_one_list(gc->reglists, owner, type, classid)) { 503 if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL) 504 guc_warn(guc, "Missing capture reglist: global!\n"); 505 else 506 guc_warn(guc, "Missing capture reglist: %s(%u):%s(%u)!\n", 507 __stringify_type(type), type, 508 __stringify_engclass(classid), classid); 509 return -ENODATA; 510 } 511 512 num_regs = guc_cap_list_num_regs(gc, owner, type, classid); 513 /* intentional empty lists can exist depending on hw config */ 514 if (!num_regs) 515 return -ENODATA; 516 517 if (size) 518 *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + 519 (num_regs * sizeof(struct guc_mmio_reg))); 520 521 return 0; 522 } 523 524 int 525 intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, 526 size_t *size) 527 { 528 return guc_capture_getlistsize(guc, owner, type, classid, size, false); 529 } 530 531 static void guc_capture_create_prealloc_nodes(struct intel_guc *guc); 532 533 int 534 intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, 535 void **outptr) 536 { 537 struct intel_guc_state_capture *gc = guc->capture; 538 struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid]; 539 struct guc_debug_capture_list *listnode; 540 int ret, num_regs; 541 u8 *caplist, *tmp; 542 size_t size = 0; 543 544 if (!gc->reglists) 545 return -ENODEV; 546 547 if (cache->is_valid) { 548 *outptr = cache->ptr; 549 return cache->status; 550 } 551 552 /* 553 * ADS population of input registers is a good 554 * time to pre-allocate cachelist output nodes 555 */ 556 guc_capture_create_prealloc_nodes(guc); 557 558 ret = intel_guc_capture_getlistsize(guc, owner, type, classid, &size); 559 if (ret) { 560 cache->is_valid = true; 561 cache->ptr = NULL; 562 cache->size = 0; 563 cache->status = ret; 564 return ret; 565 } 566 567 caplist = kzalloc(size, GFP_KERNEL); 568 if (!caplist) { 569 guc_dbg(guc, "Failed to alloc cached register capture list"); 570 return -ENOMEM; 571 } 572 573 /* populate capture list header */ 574 tmp = caplist; 575 num_regs = guc_cap_list_num_regs(guc->capture, owner, type, classid); 576 listnode = (struct guc_debug_capture_list *)tmp; 577 listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs); 578 579 /* populate list of register descriptor */ 580 tmp += sizeof(struct guc_debug_capture_list); 581 guc_capture_list_init(guc, owner, type, classid, (struct guc_mmio_reg *)tmp, num_regs); 582 583 /* cache this list */ 584 cache->is_valid = true; 585 cache->ptr = caplist; 586 cache->size = size; 587 cache->status = 0; 588 589 *outptr = caplist; 590 591 return 0; 592 } 593 594 int 595 intel_guc_capture_getnullheader(struct intel_guc *guc, 596 void **outptr, size_t *size) 597 { 598 struct intel_guc_state_capture *gc = guc->capture; 599 int tmp = sizeof(u32) * 4; 600 void *null_header; 601 602 if (gc->ads_null_cache) { 603 *outptr = gc->ads_null_cache; 604 *size = tmp; 605 return 0; 606 } 607 608 null_header = kzalloc(tmp, GFP_KERNEL); 609 if (!null_header) { 610 guc_dbg(guc, "Failed to alloc cached register capture null list"); 611 return -ENOMEM; 612 } 613 614 gc->ads_null_cache = null_header; 615 *outptr = null_header; 616 *size = tmp; 617 618 return 0; 619 } 620 621 static int 622 guc_capture_output_min_size_est(struct intel_guc *guc) 623 { 624 struct intel_gt *gt = guc_to_gt(guc); 625 struct intel_engine_cs *engine; 626 enum intel_engine_id id; 627 int worst_min_size = 0; 628 size_t tmp = 0; 629 630 if (!guc->capture) 631 return -ENODEV; 632 633 /* 634 * If every single engine-instance suffered a failure in quick succession but 635 * were all unrelated, then a burst of multiple error-capture events would dump 636 * registers for every one engine instance, one at a time. In this case, GuC 637 * would even dump the global-registers repeatedly. 638 * 639 * For each engine instance, there would be 1 x guc_state_capture_group_t output 640 * followed by 3 x guc_state_capture_t lists. The latter is how the register 641 * dumps are split across different register types (where the '3' are global vs class 642 * vs instance). 643 */ 644 for_each_engine(engine, gt, id) { 645 worst_min_size += sizeof(struct guc_state_capture_group_header_t) + 646 (3 * sizeof(struct guc_state_capture_header_t)); 647 648 if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp, true)) 649 worst_min_size += tmp; 650 651 if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, 652 engine->class, &tmp, true)) { 653 worst_min_size += tmp; 654 } 655 if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, 656 engine->class, &tmp, true)) { 657 worst_min_size += tmp; 658 } 659 } 660 661 return worst_min_size; 662 } 663 664 /* 665 * Add on a 3x multiplier to allow for multiple back-to-back captures occurring 666 * before the i915 can read the data out and process it 667 */ 668 #define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 669 670 static void check_guc_capture_size(struct intel_guc *guc) 671 { 672 int min_size = guc_capture_output_min_size_est(guc); 673 int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER; 674 u32 buffer_size = intel_guc_log_section_size_capture(&guc->log); 675 676 /* 677 * NOTE: min_size is much smaller than the capture region allocation (DG2: <80K vs 1MB) 678 * Additionally, its based on space needed to fit all engines getting reset at once 679 * within the same G2H handler task slot. This is very unlikely. However, if GuC really 680 * does run out of space for whatever reason, we will see an separate warning message 681 * when processing the G2H event capture-notification, search for: 682 * INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE. 683 */ 684 if (min_size < 0) 685 guc_warn(guc, "Failed to calculate error state capture buffer minimum size: %d!\n", 686 min_size); 687 else if (min_size > buffer_size) 688 guc_warn(guc, "Error state capture buffer maybe small: %d < %d\n", 689 buffer_size, min_size); 690 else if (spare_size > buffer_size) 691 guc_dbg(guc, "Error state capture buffer lacks spare size: %d < %d (min = %d)\n", 692 buffer_size, spare_size, min_size); 693 } 694 695 /* 696 * KMD Init time flows: 697 * -------------------- 698 * --> alloc A: GuC input capture regs lists (registered to GuC via ADS). 699 * intel_guc_ads acquires the register lists by calling 700 * intel_guc_capture_list_size and intel_guc_capture_list_get 'n' times, 701 * where n = 1 for global-reg-list + 702 * num_engine_classes for class-reg-list + 703 * num_engine_classes for instance-reg-list 704 * (since all instances of the same engine-class type 705 * have an identical engine-instance register-list). 706 * ADS module also calls separately for PF vs VF. 707 * 708 * --> alloc B: GuC output capture buf (registered via guc_init_params(log_param)) 709 * Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small) 710 * Note2: 'x 3' to hold multiple capture groups 711 * 712 * GUC Runtime notify capture: 713 * -------------------------- 714 * --> G2H STATE_CAPTURE_NOTIFICATION 715 * L--> intel_guc_capture_process 716 * L--> Loop through B (head..tail) and for each engine instance's 717 * err-state-captured register-list we find, we alloc 'C': 718 * --> alloc C: A capture-output-node structure that includes misc capture info along 719 * with 3 register list dumps (global, engine-class and engine-instance) 720 * This node is created from a pre-allocated list of blank nodes in 721 * guc->capture->cachelist and populated with the error-capture 722 * data from GuC and then it's added into guc->capture->outlist linked 723 * list. This list is used for matchup and printout by i915_gpu_coredump 724 * and err_print_gt, (when user invokes the error capture sysfs). 725 * 726 * GUC --> notify context reset: 727 * ----------------------------- 728 * --> G2H CONTEXT RESET 729 * L--> guc_handle_context_reset --> i915_capture_error_state 730 * L--> i915_gpu_coredump(..IS_GUC_CAPTURE) --> gt_record_engines 731 * --> capture_engine(..IS_GUC_CAPTURE) 732 * L--> intel_guc_capture_get_matching_node is where 733 * detach C from internal linked list and add it into 734 * intel_engine_coredump struct (if the context and 735 * engine of the event notification matches a node 736 * in the link list). 737 * 738 * User Sysfs / Debugfs 739 * -------------------- 740 * --> i915_gpu_coredump_copy_to_buffer-> 741 * L--> err_print_to_sgl --> err_print_gt 742 * L--> error_print_guc_captures 743 * L--> intel_guc_capture_print_node prints the 744 * register lists values of the attached node 745 * on the error-engine-dump being reported. 746 * L--> i915_reset_error_state ... -->__i915_gpu_coredump_free 747 * L--> ... cleanup_gt --> 748 * L--> intel_guc_capture_free_node returns the 749 * capture-output-node back to the internal 750 * cachelist for reuse. 751 * 752 */ 753 754 static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) 755 { 756 if (buf->wr >= buf->rd) 757 return (buf->wr - buf->rd); 758 return (buf->size - buf->rd) + buf->wr; 759 } 760 761 static int guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate *buf) 762 { 763 if (buf->rd > buf->wr) 764 return (buf->size - buf->rd); 765 return (buf->wr - buf->rd); 766 } 767 768 /* 769 * GuC's error-capture output is a ring buffer populated in a byte-stream fashion: 770 * 771 * The GuC Log buffer region for error-capture is managed like a ring buffer. 772 * The GuC firmware dumps error capture logs into this ring in a byte-stream flow. 773 * Additionally, as per the current and foreseeable future, all packed error- 774 * capture output structures are dword aligned. 775 * 776 * That said, if the GuC firmware is in the midst of writing a structure that is larger 777 * than one dword but the tail end of the err-capture buffer-region has lesser space left, 778 * we would need to extract that structure one dword at a time straddled across the end, 779 * onto the start of the ring. 780 * 781 * Below function, guc_capture_log_remove_dw is a helper for that. All callers of this 782 * function would typically do a straight-up memcpy from the ring contents and will only 783 * call this helper if their structure-extraction is straddling across the end of the 784 * ring. GuC firmware does not add any padding. The reason for the no-padding is to ease 785 * scalability for future expansion of output data types without requiring a redesign 786 * of the flow controls. 787 */ 788 static int 789 guc_capture_log_remove_dw(struct intel_guc *guc, struct __guc_capture_bufstate *buf, 790 u32 *dw) 791 { 792 int tries = 2; 793 int avail = 0; 794 u32 *src_data; 795 796 if (!guc_capture_buf_cnt(buf)) 797 return 0; 798 799 while (tries--) { 800 avail = guc_capture_buf_cnt_to_end(buf); 801 if (avail >= sizeof(u32)) { 802 src_data = (u32 *)(buf->data + buf->rd); 803 *dw = *src_data; 804 buf->rd += 4; 805 return 4; 806 } 807 if (avail) 808 guc_dbg(guc, "Register capture log not dword aligned, skipping.\n"); 809 buf->rd = 0; 810 } 811 812 return 0; 813 } 814 815 static bool 816 guc_capture_data_extracted(struct __guc_capture_bufstate *b, 817 int size, void *dest) 818 { 819 if (guc_capture_buf_cnt_to_end(b) >= size) { 820 memcpy(dest, (b->data + b->rd), size); 821 b->rd += size; 822 return true; 823 } 824 return false; 825 } 826 827 static int 828 guc_capture_log_get_group_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, 829 struct guc_state_capture_group_header_t *ghdr) 830 { 831 int read = 0; 832 int fullsize = sizeof(struct guc_state_capture_group_header_t); 833 834 if (fullsize > guc_capture_buf_cnt(buf)) 835 return -1; 836 837 if (guc_capture_data_extracted(buf, fullsize, (void *)ghdr)) 838 return 0; 839 840 read += guc_capture_log_remove_dw(guc, buf, &ghdr->owner); 841 read += guc_capture_log_remove_dw(guc, buf, &ghdr->info); 842 if (read != fullsize) 843 return -1; 844 845 return 0; 846 } 847 848 static int 849 guc_capture_log_get_data_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, 850 struct guc_state_capture_header_t *hdr) 851 { 852 int read = 0; 853 int fullsize = sizeof(struct guc_state_capture_header_t); 854 855 if (fullsize > guc_capture_buf_cnt(buf)) 856 return -1; 857 858 if (guc_capture_data_extracted(buf, fullsize, (void *)hdr)) 859 return 0; 860 861 read += guc_capture_log_remove_dw(guc, buf, &hdr->owner); 862 read += guc_capture_log_remove_dw(guc, buf, &hdr->info); 863 read += guc_capture_log_remove_dw(guc, buf, &hdr->lrca); 864 read += guc_capture_log_remove_dw(guc, buf, &hdr->guc_id); 865 read += guc_capture_log_remove_dw(guc, buf, &hdr->num_mmios); 866 if (read != fullsize) 867 return -1; 868 869 return 0; 870 } 871 872 static int 873 guc_capture_log_get_register(struct intel_guc *guc, struct __guc_capture_bufstate *buf, 874 struct guc_mmio_reg *reg) 875 { 876 int read = 0; 877 int fullsize = sizeof(struct guc_mmio_reg); 878 879 if (fullsize > guc_capture_buf_cnt(buf)) 880 return -1; 881 882 if (guc_capture_data_extracted(buf, fullsize, (void *)reg)) 883 return 0; 884 885 read += guc_capture_log_remove_dw(guc, buf, ®->offset); 886 read += guc_capture_log_remove_dw(guc, buf, ®->value); 887 read += guc_capture_log_remove_dw(guc, buf, ®->flags); 888 read += guc_capture_log_remove_dw(guc, buf, ®->mask); 889 if (read != fullsize) 890 return -1; 891 892 return 0; 893 } 894 895 static void 896 guc_capture_delete_one_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) 897 { 898 int i; 899 900 for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) 901 kfree(node->reginfo[i].regs); 902 list_del(&node->link); 903 kfree(node); 904 } 905 906 static void 907 guc_capture_delete_prealloc_nodes(struct intel_guc *guc) 908 { 909 struct __guc_capture_parsed_output *n, *ntmp; 910 911 /* 912 * NOTE: At the end of driver operation, we must assume that we 913 * have prealloc nodes in both the cachelist as well as outlist 914 * if unclaimed error capture events occurred prior to shutdown. 915 */ 916 list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) 917 guc_capture_delete_one_node(guc, n); 918 919 list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) 920 guc_capture_delete_one_node(guc, n); 921 } 922 923 static void 924 guc_capture_add_node_to_list(struct __guc_capture_parsed_output *node, 925 struct list_head *list) 926 { 927 list_add_tail(&node->link, list); 928 } 929 930 static void 931 guc_capture_add_node_to_outlist(struct intel_guc_state_capture *gc, 932 struct __guc_capture_parsed_output *node) 933 { 934 guc_capture_add_node_to_list(node, &gc->outlist); 935 } 936 937 static void 938 guc_capture_add_node_to_cachelist(struct intel_guc_state_capture *gc, 939 struct __guc_capture_parsed_output *node) 940 { 941 guc_capture_add_node_to_list(node, &gc->cachelist); 942 } 943 944 static void 945 guc_capture_init_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) 946 { 947 struct guc_mmio_reg *tmp[GUC_CAPTURE_LIST_TYPE_MAX]; 948 int i; 949 950 for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { 951 tmp[i] = node->reginfo[i].regs; 952 memset(tmp[i], 0, sizeof(struct guc_mmio_reg) * 953 guc->capture->max_mmio_per_node); 954 } 955 memset(node, 0, sizeof(*node)); 956 for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) 957 node->reginfo[i].regs = tmp[i]; 958 959 INIT_LIST_HEAD(&node->link); 960 } 961 962 static struct __guc_capture_parsed_output * 963 guc_capture_get_prealloc_node(struct intel_guc *guc) 964 { 965 struct __guc_capture_parsed_output *found = NULL; 966 967 if (!list_empty(&guc->capture->cachelist)) { 968 struct __guc_capture_parsed_output *n, *ntmp; 969 970 /* get first avail node from the cache list */ 971 list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) { 972 found = n; 973 list_del(&n->link); 974 break; 975 } 976 } else { 977 struct __guc_capture_parsed_output *n, *ntmp; 978 979 /* traverse down and steal back the oldest node already allocated */ 980 list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) { 981 found = n; 982 } 983 if (found) 984 list_del(&found->link); 985 } 986 if (found) 987 guc_capture_init_node(guc, found); 988 989 return found; 990 } 991 992 static struct __guc_capture_parsed_output * 993 guc_capture_alloc_one_node(struct intel_guc *guc) 994 { 995 struct __guc_capture_parsed_output *new; 996 int i; 997 998 new = kzalloc(sizeof(*new), GFP_KERNEL); 999 if (!new) 1000 return NULL; 1001 1002 for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { 1003 new->reginfo[i].regs = kcalloc(guc->capture->max_mmio_per_node, 1004 sizeof(struct guc_mmio_reg), GFP_KERNEL); 1005 if (!new->reginfo[i].regs) { 1006 while (i) 1007 kfree(new->reginfo[--i].regs); 1008 kfree(new); 1009 return NULL; 1010 } 1011 } 1012 guc_capture_init_node(guc, new); 1013 1014 return new; 1015 } 1016 1017 static struct __guc_capture_parsed_output * 1018 guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output *original, 1019 u32 keep_reglist_mask) 1020 { 1021 struct __guc_capture_parsed_output *new; 1022 int i; 1023 1024 new = guc_capture_get_prealloc_node(guc); 1025 if (!new) 1026 return NULL; 1027 if (!original) 1028 return new; 1029 1030 new->is_partial = original->is_partial; 1031 1032 /* copy reg-lists that we want to clone */ 1033 for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { 1034 if (keep_reglist_mask & BIT(i)) { 1035 GEM_BUG_ON(original->reginfo[i].num_regs > 1036 guc->capture->max_mmio_per_node); 1037 1038 memcpy(new->reginfo[i].regs, original->reginfo[i].regs, 1039 original->reginfo[i].num_regs * sizeof(struct guc_mmio_reg)); 1040 1041 new->reginfo[i].num_regs = original->reginfo[i].num_regs; 1042 new->reginfo[i].vfid = original->reginfo[i].vfid; 1043 1044 if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) { 1045 new->eng_class = original->eng_class; 1046 } else if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) { 1047 new->eng_inst = original->eng_inst; 1048 new->guc_id = original->guc_id; 1049 new->lrca = original->lrca; 1050 } 1051 } 1052 } 1053 1054 return new; 1055 } 1056 1057 static void 1058 __guc_capture_create_prealloc_nodes(struct intel_guc *guc) 1059 { 1060 struct __guc_capture_parsed_output *node = NULL; 1061 int i; 1062 1063 for (i = 0; i < PREALLOC_NODES_MAX_COUNT; ++i) { 1064 node = guc_capture_alloc_one_node(guc); 1065 if (!node) { 1066 guc_warn(guc, "Register capture pre-alloc-cache failure\n"); 1067 /* dont free the priors, use what we got and cleanup at shutdown */ 1068 return; 1069 } 1070 guc_capture_add_node_to_cachelist(guc->capture, node); 1071 } 1072 } 1073 1074 static int 1075 guc_get_max_reglist_count(struct intel_guc *guc) 1076 { 1077 int i, j, k, tmp, maxregcount = 0; 1078 1079 for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) { 1080 for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) { 1081 for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) { 1082 if (j == GUC_CAPTURE_LIST_TYPE_GLOBAL && k > 0) 1083 continue; 1084 1085 tmp = guc_cap_list_num_regs(guc->capture, i, j, k); 1086 if (tmp > maxregcount) 1087 maxregcount = tmp; 1088 } 1089 } 1090 } 1091 if (!maxregcount) 1092 maxregcount = PREALLOC_NODES_DEFAULT_NUMREGS; 1093 1094 return maxregcount; 1095 } 1096 1097 static void 1098 guc_capture_create_prealloc_nodes(struct intel_guc *guc) 1099 { 1100 /* skip if we've already done the pre-alloc */ 1101 if (guc->capture->max_mmio_per_node) 1102 return; 1103 1104 guc->capture->max_mmio_per_node = guc_get_max_reglist_count(guc); 1105 __guc_capture_create_prealloc_nodes(guc); 1106 } 1107 1108 static int 1109 guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstate *buf) 1110 { 1111 struct guc_state_capture_group_header_t ghdr = {0}; 1112 struct guc_state_capture_header_t hdr = {0}; 1113 struct __guc_capture_parsed_output *node = NULL; 1114 struct guc_mmio_reg *regs = NULL; 1115 int i, numlists, numregs, ret = 0; 1116 enum guc_capture_type datatype; 1117 struct guc_mmio_reg tmp; 1118 bool is_partial = false; 1119 1120 i = guc_capture_buf_cnt(buf); 1121 if (!i) 1122 return -ENODATA; 1123 if (i % sizeof(u32)) { 1124 guc_warn(guc, "Got mis-aligned register capture entries\n"); 1125 ret = -EIO; 1126 goto bailout; 1127 } 1128 1129 /* first get the capture group header */ 1130 if (guc_capture_log_get_group_hdr(guc, buf, &ghdr)) { 1131 ret = -EIO; 1132 goto bailout; 1133 } 1134 /* 1135 * we would typically expect a layout as below where n would be expected to be 1136 * anywhere between 3 to n where n > 3 if we are seeing multiple dependent engine 1137 * instances being reset together. 1138 * ____________________________________________ 1139 * | Capture Group | 1140 * | ________________________________________ | 1141 * | | Capture Group Header: | | 1142 * | | - num_captures = 5 | | 1143 * | |______________________________________| | 1144 * | ________________________________________ | 1145 * | | Capture1: | | 1146 * | | Hdr: GLOBAL, numregs=a | | 1147 * | | ____________________________________ | | 1148 * | | | Reglist | | | 1149 * | | | - reg1, reg2, ... rega | | | 1150 * | | |__________________________________| | | 1151 * | |______________________________________| | 1152 * | ________________________________________ | 1153 * | | Capture2: | | 1154 * | | Hdr: CLASS=RENDER/COMPUTE, numregs=b| | 1155 * | | ____________________________________ | | 1156 * | | | Reglist | | | 1157 * | | | - reg1, reg2, ... regb | | | 1158 * | | |__________________________________| | | 1159 * | |______________________________________| | 1160 * | ________________________________________ | 1161 * | | Capture3: | | 1162 * | | Hdr: INSTANCE=RCS, numregs=c | | 1163 * | | ____________________________________ | | 1164 * | | | Reglist | | | 1165 * | | | - reg1, reg2, ... regc | | | 1166 * | | |__________________________________| | | 1167 * | |______________________________________| | 1168 * | ________________________________________ | 1169 * | | Capture4: | | 1170 * | | Hdr: CLASS=RENDER/COMPUTE, numregs=d| | 1171 * | | ____________________________________ | | 1172 * | | | Reglist | | | 1173 * | | | - reg1, reg2, ... regd | | | 1174 * | | |__________________________________| | | 1175 * | |______________________________________| | 1176 * | ________________________________________ | 1177 * | | Capture5: | | 1178 * | | Hdr: INSTANCE=CCS0, numregs=e | | 1179 * | | ____________________________________ | | 1180 * | | | Reglist | | | 1181 * | | | - reg1, reg2, ... rege | | | 1182 * | | |__________________________________| | | 1183 * | |______________________________________| | 1184 * |__________________________________________| 1185 */ 1186 is_partial = FIELD_GET(CAP_GRP_HDR_CAPTURE_TYPE, ghdr.info); 1187 numlists = FIELD_GET(CAP_GRP_HDR_NUM_CAPTURES, ghdr.info); 1188 1189 while (numlists--) { 1190 if (guc_capture_log_get_data_hdr(guc, buf, &hdr)) { 1191 ret = -EIO; 1192 break; 1193 } 1194 1195 datatype = FIELD_GET(CAP_HDR_CAPTURE_TYPE, hdr.info); 1196 if (datatype > GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) { 1197 /* unknown capture type - skip over to next capture set */ 1198 numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); 1199 while (numregs--) { 1200 if (guc_capture_log_get_register(guc, buf, &tmp)) { 1201 ret = -EIO; 1202 break; 1203 } 1204 } 1205 continue; 1206 } else if (node) { 1207 /* 1208 * Based on the current capture type and what we have so far, 1209 * decide if we should add the current node into the internal 1210 * linked list for match-up when i915_gpu_coredump calls later 1211 * (and alloc a blank node for the next set of reglists) 1212 * or continue with the same node or clone the current node 1213 * but only retain the global or class registers (such as the 1214 * case of dependent engine resets). 1215 */ 1216 if (datatype == GUC_CAPTURE_LIST_TYPE_GLOBAL) { 1217 guc_capture_add_node_to_outlist(guc->capture, node); 1218 node = NULL; 1219 } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS && 1220 node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].num_regs) { 1221 /* Add to list, clone node and duplicate global list */ 1222 guc_capture_add_node_to_outlist(guc->capture, node); 1223 node = guc_capture_clone_node(guc, node, 1224 GCAP_PARSED_REGLIST_INDEX_GLOBAL); 1225 } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE && 1226 node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].num_regs) { 1227 /* Add to list, clone node and duplicate global + class lists */ 1228 guc_capture_add_node_to_outlist(guc->capture, node); 1229 node = guc_capture_clone_node(guc, node, 1230 (GCAP_PARSED_REGLIST_INDEX_GLOBAL | 1231 GCAP_PARSED_REGLIST_INDEX_ENGCLASS)); 1232 } 1233 } 1234 1235 if (!node) { 1236 node = guc_capture_get_prealloc_node(guc); 1237 if (!node) { 1238 ret = -ENOMEM; 1239 break; 1240 } 1241 if (datatype != GUC_CAPTURE_LIST_TYPE_GLOBAL) 1242 guc_dbg(guc, "Register capture missing global dump: %08x!\n", 1243 datatype); 1244 } 1245 node->is_partial = is_partial; 1246 node->reginfo[datatype].vfid = FIELD_GET(CAP_HDR_CAPTURE_VFID, hdr.owner); 1247 switch (datatype) { 1248 case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: 1249 node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); 1250 node->eng_inst = FIELD_GET(CAP_HDR_ENGINE_INSTANCE, hdr.info); 1251 node->lrca = hdr.lrca; 1252 node->guc_id = hdr.guc_id; 1253 break; 1254 case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: 1255 node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); 1256 break; 1257 default: 1258 break; 1259 } 1260 1261 numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); 1262 if (numregs > guc->capture->max_mmio_per_node) { 1263 guc_dbg(guc, "Register capture list extraction clipped by prealloc!\n"); 1264 numregs = guc->capture->max_mmio_per_node; 1265 } 1266 node->reginfo[datatype].num_regs = numregs; 1267 regs = node->reginfo[datatype].regs; 1268 i = 0; 1269 while (numregs--) { 1270 if (guc_capture_log_get_register(guc, buf, ®s[i++])) { 1271 ret = -EIO; 1272 break; 1273 } 1274 } 1275 } 1276 1277 bailout: 1278 if (node) { 1279 /* If we have data, add to linked list for match-up when i915_gpu_coredump calls */ 1280 for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { 1281 if (node->reginfo[i].regs) { 1282 guc_capture_add_node_to_outlist(guc->capture, node); 1283 node = NULL; 1284 break; 1285 } 1286 } 1287 if (node) /* else return it back to cache list */ 1288 guc_capture_add_node_to_cachelist(guc->capture, node); 1289 } 1290 return ret; 1291 } 1292 1293 static int __guc_capture_flushlog_complete(struct intel_guc *guc) 1294 { 1295 u32 action[] = { 1296 INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE, 1297 GUC_CAPTURE_LOG_BUFFER 1298 }; 1299 1300 return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0); 1301 1302 } 1303 1304 static void __guc_capture_process_output(struct intel_guc *guc) 1305 { 1306 unsigned int buffer_size, read_offset, write_offset, full_count; 1307 struct intel_uc *uc = container_of(guc, typeof(*uc), guc); 1308 struct guc_log_buffer_state log_buf_state_local; 1309 struct guc_log_buffer_state *log_buf_state; 1310 struct __guc_capture_bufstate buf; 1311 void *src_data = NULL; 1312 bool new_overflow; 1313 int ret; 1314 1315 log_buf_state = guc->log.buf_addr + 1316 (sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER); 1317 src_data = guc->log.buf_addr + 1318 intel_guc_get_log_buffer_offset(&guc->log, GUC_CAPTURE_LOG_BUFFER); 1319 1320 /* 1321 * Make a copy of the state structure, inside GuC log buffer 1322 * (which is uncached mapped), on the stack to avoid reading 1323 * from it multiple times. 1324 */ 1325 memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); 1326 buffer_size = intel_guc_get_log_buffer_size(&guc->log, GUC_CAPTURE_LOG_BUFFER); 1327 read_offset = log_buf_state_local.read_ptr; 1328 write_offset = log_buf_state_local.sampled_write_ptr; 1329 full_count = log_buf_state_local.buffer_full_cnt; 1330 1331 /* Bookkeeping stuff */ 1332 guc->log.stats[GUC_CAPTURE_LOG_BUFFER].flush += log_buf_state_local.flush_to_file; 1333 new_overflow = intel_guc_check_log_buf_overflow(&guc->log, GUC_CAPTURE_LOG_BUFFER, 1334 full_count); 1335 1336 /* Now copy the actual logs. */ 1337 if (unlikely(new_overflow)) { 1338 /* copy the whole buffer in case of overflow */ 1339 read_offset = 0; 1340 write_offset = buffer_size; 1341 } else if (unlikely((read_offset > buffer_size) || 1342 (write_offset > buffer_size))) { 1343 guc_err(guc, "Register capture buffer in invalid state: read = 0x%X, size = 0x%X!\n", 1344 read_offset, buffer_size); 1345 /* copy whole buffer as offsets are unreliable */ 1346 read_offset = 0; 1347 write_offset = buffer_size; 1348 } 1349 1350 buf.size = buffer_size; 1351 buf.rd = read_offset; 1352 buf.wr = write_offset; 1353 buf.data = src_data; 1354 1355 if (!uc->reset_in_progress) { 1356 do { 1357 ret = guc_capture_extract_reglists(guc, &buf); 1358 } while (ret >= 0); 1359 } 1360 1361 /* Update the state of log buffer err-cap state */ 1362 log_buf_state->read_ptr = write_offset; 1363 log_buf_state->flush_to_file = 0; 1364 __guc_capture_flushlog_complete(guc); 1365 } 1366 1367 #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) 1368 1369 static const char * 1370 guc_capture_reg_to_str(const struct intel_guc *guc, u32 owner, u32 type, 1371 u32 class, u32 id, u32 offset, u32 *is_ext) 1372 { 1373 const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; 1374 struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists; 1375 const struct __guc_mmio_reg_descr_group *match; 1376 struct __guc_mmio_reg_descr_group *matchext; 1377 int j; 1378 1379 *is_ext = 0; 1380 if (!reglists) 1381 return NULL; 1382 1383 match = guc_capture_get_one_list(reglists, owner, type, id); 1384 if (!match) 1385 return NULL; 1386 1387 for (j = 0; j < match->num_regs; ++j) { 1388 if (offset == match->list[j].reg.reg) 1389 return match->list[j].regname; 1390 } 1391 if (extlists) { 1392 matchext = guc_capture_get_one_ext_list(extlists, owner, type, id); 1393 if (!matchext) 1394 return NULL; 1395 for (j = 0; j < matchext->num_regs; ++j) { 1396 if (offset == matchext->extlist[j].reg.reg) { 1397 *is_ext = 1; 1398 return matchext->extlist[j].regname; 1399 } 1400 } 1401 } 1402 1403 return NULL; 1404 } 1405 1406 #define GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng) \ 1407 do { \ 1408 i915_error_printf(ebuf, " i915-Eng-Name: %s command stream\n", \ 1409 (eng)->name); \ 1410 i915_error_printf(ebuf, " i915-Eng-Inst-Class: 0x%02x\n", (eng)->class); \ 1411 i915_error_printf(ebuf, " i915-Eng-Inst-Id: 0x%02x\n", (eng)->instance); \ 1412 i915_error_printf(ebuf, " i915-Eng-LogicalMask: 0x%08x\n", \ 1413 (eng)->logical_mask); \ 1414 } while (0) 1415 1416 #define GCAP_PRINT_GUC_INST_INFO(ebuf, node) \ 1417 do { \ 1418 i915_error_printf(ebuf, " GuC-Engine-Inst-Id: 0x%08x\n", \ 1419 (node)->eng_inst); \ 1420 i915_error_printf(ebuf, " GuC-Context-Id: 0x%08x\n", (node)->guc_id); \ 1421 i915_error_printf(ebuf, " LRCA: 0x%08x\n", (node)->lrca); \ 1422 } while (0) 1423 1424 int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, 1425 const struct intel_engine_coredump *ee) 1426 { 1427 const char *grptype[GUC_STATE_CAPTURE_GROUP_TYPE_MAX] = { 1428 "full-capture", 1429 "partial-capture" 1430 }; 1431 const char *datatype[GUC_CAPTURE_LIST_TYPE_MAX] = { 1432 "Global", 1433 "Engine-Class", 1434 "Engine-Instance" 1435 }; 1436 struct intel_guc_state_capture *cap; 1437 struct __guc_capture_parsed_output *node; 1438 struct intel_engine_cs *eng; 1439 struct guc_mmio_reg *regs; 1440 struct intel_guc *guc; 1441 const char *str; 1442 int numregs, i, j; 1443 u32 is_ext; 1444 1445 if (!ebuf || !ee) 1446 return -EINVAL; 1447 cap = ee->guc_capture; 1448 if (!cap || !ee->engine) 1449 return -ENODEV; 1450 1451 guc = &ee->engine->gt->uc.guc; 1452 1453 i915_error_printf(ebuf, "global --- GuC Error Capture on %s command stream:\n", 1454 ee->engine->name); 1455 1456 node = ee->guc_capture_node; 1457 if (!node) { 1458 i915_error_printf(ebuf, " No matching ee-node\n"); 1459 return 0; 1460 } 1461 1462 i915_error_printf(ebuf, "Coverage: %s\n", grptype[node->is_partial]); 1463 1464 for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { 1465 i915_error_printf(ebuf, " RegListType: %s\n", 1466 datatype[i % GUC_CAPTURE_LIST_TYPE_MAX]); 1467 i915_error_printf(ebuf, " Owner-Id: %d\n", node->reginfo[i].vfid); 1468 1469 switch (i) { 1470 case GUC_CAPTURE_LIST_TYPE_GLOBAL: 1471 default: 1472 break; 1473 case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: 1474 i915_error_printf(ebuf, " GuC-Eng-Class: %d\n", node->eng_class); 1475 i915_error_printf(ebuf, " i915-Eng-Class: %d\n", 1476 guc_class_to_engine_class(node->eng_class)); 1477 break; 1478 case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: 1479 eng = intel_guc_lookup_engine(guc, node->eng_class, node->eng_inst); 1480 if (eng) 1481 GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng); 1482 else 1483 i915_error_printf(ebuf, " i915-Eng-Lookup Fail!\n"); 1484 GCAP_PRINT_GUC_INST_INFO(ebuf, node); 1485 break; 1486 } 1487 1488 numregs = node->reginfo[i].num_regs; 1489 i915_error_printf(ebuf, " NumRegs: %d\n", numregs); 1490 j = 0; 1491 while (numregs--) { 1492 regs = node->reginfo[i].regs; 1493 str = guc_capture_reg_to_str(guc, GUC_CAPTURE_LIST_INDEX_PF, i, 1494 node->eng_class, 0, regs[j].offset, &is_ext); 1495 if (!str) 1496 i915_error_printf(ebuf, " REG-0x%08x", regs[j].offset); 1497 else 1498 i915_error_printf(ebuf, " %s", str); 1499 if (is_ext) 1500 i915_error_printf(ebuf, "[%ld][%ld]", 1501 FIELD_GET(GUC_REGSET_STEERING_GROUP, regs[j].flags), 1502 FIELD_GET(GUC_REGSET_STEERING_INSTANCE, regs[j].flags)); 1503 i915_error_printf(ebuf, ": 0x%08x\n", regs[j].value); 1504 ++j; 1505 } 1506 } 1507 return 0; 1508 } 1509 1510 #endif //CONFIG_DRM_I915_CAPTURE_ERROR 1511 1512 static void guc_capture_find_ecode(struct intel_engine_coredump *ee) 1513 { 1514 struct gcap_reg_list_info *reginfo; 1515 struct guc_mmio_reg *regs; 1516 i915_reg_t reg_ipehr = RING_IPEHR(0); 1517 i915_reg_t reg_instdone = RING_INSTDONE(0); 1518 int i; 1519 1520 if (!ee->guc_capture_node) 1521 return; 1522 1523 reginfo = ee->guc_capture_node->reginfo + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE; 1524 regs = reginfo->regs; 1525 for (i = 0; i < reginfo->num_regs; i++) { 1526 if (regs[i].offset == reg_ipehr.reg) 1527 ee->ipehr = regs[i].value; 1528 else if (regs[i].offset == reg_instdone.reg) 1529 ee->instdone.instdone = regs[i].value; 1530 } 1531 } 1532 1533 void intel_guc_capture_free_node(struct intel_engine_coredump *ee) 1534 { 1535 if (!ee || !ee->guc_capture_node) 1536 return; 1537 1538 guc_capture_add_node_to_cachelist(ee->guc_capture, ee->guc_capture_node); 1539 ee->guc_capture = NULL; 1540 ee->guc_capture_node = NULL; 1541 } 1542 1543 bool intel_guc_capture_is_matching_engine(struct intel_gt *gt, 1544 struct intel_context *ce, 1545 struct intel_engine_cs *engine) 1546 { 1547 struct __guc_capture_parsed_output *n; 1548 struct intel_guc *guc; 1549 1550 if (!gt || !ce || !engine) 1551 return false; 1552 1553 guc = >->uc.guc; 1554 if (!guc->capture) 1555 return false; 1556 1557 /* 1558 * Look for a matching GuC reported error capture node from 1559 * the internal output link-list based on lrca, guc-id and engine 1560 * identification. 1561 */ 1562 list_for_each_entry(n, &guc->capture->outlist, link) { 1563 if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(engine->guc_id) && 1564 n->eng_class == GUC_ID_TO_ENGINE_CLASS(engine->guc_id) && 1565 n->guc_id == ce->guc_id.id && 1566 (n->lrca & CTX_GTT_ADDRESS_MASK) == (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) 1567 return true; 1568 } 1569 1570 return false; 1571 } 1572 1573 void intel_guc_capture_get_matching_node(struct intel_gt *gt, 1574 struct intel_engine_coredump *ee, 1575 struct intel_context *ce) 1576 { 1577 struct __guc_capture_parsed_output *n, *ntmp; 1578 struct intel_guc *guc; 1579 1580 if (!gt || !ee || !ce) 1581 return; 1582 1583 guc = >->uc.guc; 1584 if (!guc->capture) 1585 return; 1586 1587 GEM_BUG_ON(ee->guc_capture_node); 1588 1589 /* 1590 * Look for a matching GuC reported error capture node from 1591 * the internal output link-list based on lrca, guc-id and engine 1592 * identification. 1593 */ 1594 list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) { 1595 if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(ee->engine->guc_id) && 1596 n->eng_class == GUC_ID_TO_ENGINE_CLASS(ee->engine->guc_id) && 1597 n->guc_id == ce->guc_id.id && 1598 (n->lrca & CTX_GTT_ADDRESS_MASK) == (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) { 1599 list_del(&n->link); 1600 ee->guc_capture_node = n; 1601 ee->guc_capture = guc->capture; 1602 guc_capture_find_ecode(ee); 1603 return; 1604 } 1605 } 1606 1607 guc_warn(guc, "No register capture node found for 0x%04X / 0x%08X\n", 1608 ce->guc_id.id, ce->lrc.lrca); 1609 } 1610 1611 void intel_guc_capture_process(struct intel_guc *guc) 1612 { 1613 if (guc->capture) 1614 __guc_capture_process_output(guc); 1615 } 1616 1617 static void 1618 guc_capture_free_ads_cache(struct intel_guc_state_capture *gc) 1619 { 1620 int i, j, k; 1621 struct __guc_capture_ads_cache *cache; 1622 1623 for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) { 1624 for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) { 1625 for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) { 1626 cache = &gc->ads_cache[i][j][k]; 1627 if (cache->is_valid) 1628 kfree(cache->ptr); 1629 } 1630 } 1631 } 1632 kfree(gc->ads_null_cache); 1633 } 1634 1635 void intel_guc_capture_destroy(struct intel_guc *guc) 1636 { 1637 if (!guc->capture) 1638 return; 1639 1640 guc_capture_free_ads_cache(guc->capture); 1641 1642 guc_capture_delete_prealloc_nodes(guc); 1643 1644 guc_capture_free_extlists(guc->capture->extlists); 1645 kfree(guc->capture->extlists); 1646 1647 kfree(guc->capture); 1648 guc->capture = NULL; 1649 } 1650 1651 int intel_guc_capture_init(struct intel_guc *guc) 1652 { 1653 guc->capture = kzalloc(sizeof(*guc->capture), GFP_KERNEL); 1654 if (!guc->capture) 1655 return -ENOMEM; 1656 1657 guc->capture->reglists = guc_capture_get_device_reglist(guc); 1658 1659 INIT_LIST_HEAD(&guc->capture->outlist); 1660 INIT_LIST_HEAD(&guc->capture->cachelist); 1661 1662 check_guc_capture_size(guc); 1663 1664 return 0; 1665 } 1666