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