1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021-2024 Intel Corporation 4 */ 5 6 #include <linux/types.h> 7 8 #include <drm/drm_managed.h> 9 #include <drm/drm_print.h> 10 11 #include "abi/guc_actions_abi.h" 12 #include "abi/guc_capture_abi.h" 13 #include "abi/guc_log_abi.h" 14 #include "regs/xe_engine_regs.h" 15 #include "regs/xe_gt_regs.h" 16 #include "regs/xe_guc_regs.h" 17 #include "regs/xe_regs.h" 18 19 #include "xe_bo.h" 20 #include "xe_device.h" 21 #include "xe_exec_queue_types.h" 22 #include "xe_gt.h" 23 #include "xe_gt_mcr.h" 24 #include "xe_gt_printk.h" 25 #include "xe_guc.h" 26 #include "xe_guc_ads.h" 27 #include "xe_guc_capture.h" 28 #include "xe_guc_capture_types.h" 29 #include "xe_guc_ct.h" 30 #include "xe_guc_exec_queue_types.h" 31 #include "xe_guc_log.h" 32 #include "xe_guc_submit_types.h" 33 #include "xe_guc_submit.h" 34 #include "xe_hw_engine_types.h" 35 #include "xe_hw_engine.h" 36 #include "xe_lrc.h" 37 #include "xe_macros.h" 38 #include "xe_map.h" 39 #include "xe_mmio.h" 40 #include "xe_sched_job.h" 41 42 /* 43 * struct __guc_capture_bufstate 44 * 45 * Book-keeping structure used to track read and write pointers 46 * as we extract error capture data from the GuC-log-buffer's 47 * error-capture region as a stream of dwords. 48 */ 49 struct __guc_capture_bufstate { 50 u32 size; 51 u32 data_offset; 52 u32 rd; 53 u32 wr; 54 }; 55 56 /* 57 * struct __guc_capture_parsed_output - extracted error capture node 58 * 59 * A single unit of extracted error-capture output data grouped together 60 * at an engine-instance level. We keep these nodes in a linked list. 61 * See cachelist and outlist below. 62 */ 63 struct __guc_capture_parsed_output { 64 /* 65 * A single set of 3 capture lists: a global-list 66 * an engine-class-list and an engine-instance list. 67 * outlist in __guc_capture_parsed_output will keep 68 * a linked list of these nodes that will eventually 69 * be detached from outlist and attached into to 70 * xe_codedump in response to a context reset 71 */ 72 struct list_head link; 73 bool is_partial; 74 u32 eng_class; 75 u32 eng_inst; 76 u32 guc_id; 77 u32 lrca; 78 u32 type; 79 bool locked; 80 enum xe_hw_engine_snapshot_source_id source; 81 struct gcap_reg_list_info { 82 u32 vfid; 83 u32 num_regs; 84 struct guc_mmio_reg *regs; 85 } reginfo[GUC_STATE_CAPTURE_TYPE_MAX]; 86 #define GCAP_PARSED_REGLIST_INDEX_GLOBAL BIT(GUC_STATE_CAPTURE_TYPE_GLOBAL) 87 #define GCAP_PARSED_REGLIST_INDEX_ENGCLASS BIT(GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS) 88 }; 89 90 /* 91 * Define all device tables of GuC error capture register lists 92 * NOTE: 93 * For engine-registers, GuC only needs the register offsets 94 * from the engine-mmio-base 95 * 96 * 64 bit registers need 2 entries for low 32 bit register and high 32 bit 97 * register, for example: 98 * Register data_type flags mask Register name 99 * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, 100 * { XXX_REG_HI(0), REG_64BIT_HI_DW,, 0, 0, "XXX_REG"}, 101 * 1. data_type: Indicate is hi/low 32 bit for a 64 bit register 102 * A 64 bit register define requires 2 consecutive entries, 103 * with low dword first and hi dword the second. 104 * 2. Register name: null for incompleted define 105 */ 106 #define COMMON_XELP_BASE_GLOBAL \ 107 { FORCEWAKE_GT, REG_32BIT, 0, 0, "FORCEWAKE_GT"} 108 109 #define COMMON_BASE_ENGINE_INSTANCE \ 110 { RING_HWSTAM(0), REG_32BIT, 0, 0, "HWSTAM"}, \ 111 { RING_HWS_PGA(0), REG_32BIT, 0, 0, "RING_HWS_PGA"}, \ 112 { RING_HEAD(0), REG_32BIT, 0, 0, "RING_HEAD"}, \ 113 { RING_TAIL(0), REG_32BIT, 0, 0, "RING_TAIL"}, \ 114 { RING_CTL(0), REG_32BIT, 0, 0, "RING_CTL"}, \ 115 { RING_MI_MODE(0), REG_32BIT, 0, 0, "RING_MI_MODE"}, \ 116 { RING_MODE(0), REG_32BIT, 0, 0, "RING_MODE"}, \ 117 { RING_ESR(0), REG_32BIT, 0, 0, "RING_ESR"}, \ 118 { RING_EMR(0), REG_32BIT, 0, 0, "RING_EMR"}, \ 119 { RING_EIR(0), REG_32BIT, 0, 0, "RING_EIR"}, \ 120 { RING_IMR(0), REG_32BIT, 0, 0, "RING_IMR"}, \ 121 { RING_IPEHR(0), REG_32BIT, 0, 0, "IPEHR"}, \ 122 { RING_INSTDONE(0), REG_32BIT, 0, 0, "RING_INSTDONE"}, \ 123 { INDIRECT_RING_STATE(0), REG_32BIT, 0, 0, "INDIRECT_RING_STATE"}, \ 124 { RING_ACTHD(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 125 { RING_ACTHD_UDW(0), REG_64BIT_HI_DW, 0, 0, "ACTHD"}, \ 126 { RING_BBADDR(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 127 { RING_BBADDR_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_BBADDR"}, \ 128 { RING_START(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 129 { RING_START_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_START"}, \ 130 { RING_DMA_FADD(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 131 { RING_DMA_FADD_UDW(0), REG_64BIT_HI_DW, 0, 0, "RING_DMA_FADD"}, \ 132 { RING_EXECLIST_STATUS_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 133 { RING_EXECLIST_STATUS_HI(0), REG_64BIT_HI_DW, 0, 0, "RING_EXECLIST_STATUS"}, \ 134 { RING_EXECLIST_SQ_CONTENTS_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL}, \ 135 { RING_EXECLIST_SQ_CONTENTS_HI(0), REG_64BIT_HI_DW, 0, 0, "RING_EXECLIST_SQ_CONTENTS"} 136 137 #define COMMON_XELP_RC_CLASS \ 138 { RCU_MODE, REG_32BIT, 0, 0, "RCU_MODE"} 139 140 #define COMMON_XELP_RC_CLASS_INSTDONE \ 141 { SC_INSTDONE, REG_32BIT, 0, 0, "SC_INSTDONE"}, \ 142 { SC_INSTDONE_EXTRA, REG_32BIT, 0, 0, "SC_INSTDONE_EXTRA"}, \ 143 { SC_INSTDONE_EXTRA2, REG_32BIT, 0, 0, "SC_INSTDONE_EXTRA2"} 144 145 #define XELP_VEC_CLASS_REGS \ 146 { SFC_DONE(0), 0, 0, 0, "SFC_DONE[0]"}, \ 147 { SFC_DONE(1), 0, 0, 0, "SFC_DONE[1]"}, \ 148 { SFC_DONE(2), 0, 0, 0, "SFC_DONE[2]"}, \ 149 { SFC_DONE(3), 0, 0, 0, "SFC_DONE[3]"} 150 151 /* XE_LP Global */ 152 static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { 153 COMMON_XELP_BASE_GLOBAL, 154 }; 155 156 /* Render / Compute Per-Engine-Instance */ 157 static const struct __guc_mmio_reg_descr xe_rc_inst_regs[] = { 158 COMMON_BASE_ENGINE_INSTANCE, 159 }; 160 161 /* Render / Compute Engine-Class */ 162 static const struct __guc_mmio_reg_descr xe_rc_class_regs[] = { 163 COMMON_XELP_RC_CLASS, 164 COMMON_XELP_RC_CLASS_INSTDONE, 165 }; 166 167 /* Render / Compute Engine-Class for xehpg */ 168 static const struct __guc_mmio_reg_descr xe_hpg_rc_class_regs[] = { 169 COMMON_XELP_RC_CLASS, 170 }; 171 172 /* Media Decode/Encode Per-Engine-Instance */ 173 static const struct __guc_mmio_reg_descr xe_vd_inst_regs[] = { 174 COMMON_BASE_ENGINE_INSTANCE, 175 }; 176 177 /* Video Enhancement Engine-Class */ 178 static const struct __guc_mmio_reg_descr xe_vec_class_regs[] = { 179 XELP_VEC_CLASS_REGS, 180 }; 181 182 /* Video Enhancement Per-Engine-Instance */ 183 static const struct __guc_mmio_reg_descr xe_vec_inst_regs[] = { 184 COMMON_BASE_ENGINE_INSTANCE, 185 }; 186 187 /* Blitter Per-Engine-Instance */ 188 static const struct __guc_mmio_reg_descr xe_blt_inst_regs[] = { 189 COMMON_BASE_ENGINE_INSTANCE, 190 }; 191 192 /* XE_LP - GSC Per-Engine-Instance */ 193 static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = { 194 COMMON_BASE_ENGINE_INSTANCE, 195 }; 196 197 /* 198 * Empty list to prevent warnings about unknown class/instance types 199 * as not all class/instance types have entries on all platforms. 200 */ 201 static const struct __guc_mmio_reg_descr empty_regs_list[] = { 202 }; 203 204 #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) 205 #define TO_GCAP_DEF_TYPE(x) (GUC_STATE_CAPTURE_TYPE_##x) 206 #define MAKE_REGLIST(regslist, regsowner, regstype, class) \ 207 { \ 208 regslist, \ 209 ARRAY_SIZE(regslist), \ 210 TO_GCAP_DEF_OWNER(regsowner), \ 211 TO_GCAP_DEF_TYPE(regstype), \ 212 class \ 213 } 214 215 /* List of lists for legacy graphic product version < 1255 */ 216 static const struct __guc_mmio_reg_descr_group xe_lp_lists[] = { 217 MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 218 MAKE_REGLIST(xe_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 219 MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 220 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), 221 MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), 222 MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 223 MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 224 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER), 225 MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER), 226 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 227 MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 228 {} 229 }; 230 231 /* List of lists for graphic product version >= 1255 */ 232 static const struct __guc_mmio_reg_descr_group xe_hpg_lists[] = { 233 MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0), 234 MAKE_REGLIST(xe_hpg_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 235 MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE), 236 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO), 237 MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO), 238 MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 239 MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE), 240 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER), 241 MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER), 242 MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 243 MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER), 244 {} 245 }; 246 247 static const char * const capture_list_type_names[] = { 248 "Global", 249 "Class", 250 "Instance", 251 }; 252 253 static const char * const capture_engine_class_names[] = { 254 "Render/Compute", 255 "Video", 256 "VideoEnhance", 257 "Blitter", 258 "GSC-Other", 259 }; 260 261 struct __guc_capture_ads_cache { 262 bool is_valid; 263 void *ptr; 264 size_t size; 265 int status; 266 }; 267 268 struct xe_guc_state_capture { 269 const struct __guc_mmio_reg_descr_group *reglists; 270 /** 271 * NOTE: steered registers have multiple instances depending on the HW configuration 272 * (slices or dual-sub-slices) and thus depends on HW fuses discovered 273 */ 274 struct __guc_mmio_reg_descr_group *extlists; 275 struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX] 276 [GUC_STATE_CAPTURE_TYPE_MAX] 277 [GUC_CAPTURE_LIST_CLASS_MAX]; 278 void *ads_null_cache; 279 struct list_head cachelist; 280 #define PREALLOC_NODES_MAX_COUNT (3 * GUC_MAX_ENGINE_CLASSES * GUC_MAX_INSTANCES_PER_CLASS) 281 #define PREALLOC_NODES_DEFAULT_NUMREGS 64 282 283 int max_mmio_per_node; 284 struct list_head outlist; 285 }; 286 287 static void 288 guc_capture_remove_stale_matches_from_list(struct xe_guc_state_capture *gc, 289 struct __guc_capture_parsed_output *node); 290 291 static const struct __guc_mmio_reg_descr_group * 292 guc_capture_get_device_reglist(struct xe_device *xe) 293 { 294 if (GRAPHICS_VERx100(xe) >= 1255) 295 return xe_hpg_lists; 296 else 297 return xe_lp_lists; 298 } 299 300 static const struct __guc_mmio_reg_descr_group * 301 guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, 302 u32 owner, u32 type, enum guc_capture_list_class_type capture_class) 303 { 304 int i; 305 306 if (!reglists) 307 return NULL; 308 309 for (i = 0; reglists[i].list; ++i) { 310 if (reglists[i].owner == owner && reglists[i].type == type && 311 (reglists[i].engine == capture_class || 312 reglists[i].type == GUC_STATE_CAPTURE_TYPE_GLOBAL)) 313 return ®lists[i]; 314 } 315 316 return NULL; 317 } 318 319 const struct __guc_mmio_reg_descr_group * 320 xe_guc_capture_get_reg_desc_list(struct xe_gt *gt, u32 owner, u32 type, 321 enum guc_capture_list_class_type capture_class, bool is_ext) 322 { 323 const struct __guc_mmio_reg_descr_group *reglists; 324 325 if (is_ext) { 326 struct xe_guc *guc = >->uc.guc; 327 328 reglists = guc->capture->extlists; 329 } else { 330 reglists = guc_capture_get_device_reglist(gt_to_xe(gt)); 331 } 332 return guc_capture_get_one_list(reglists, owner, type, capture_class); 333 } 334 335 struct __ext_steer_reg { 336 const char *name; 337 struct xe_reg_mcr reg; 338 }; 339 340 static const struct __ext_steer_reg xe_extregs[] = { 341 {"SAMPLER_INSTDONE", SAMPLER_INSTDONE}, 342 {"ROW_INSTDONE", ROW_INSTDONE} 343 }; 344 345 static const struct __ext_steer_reg xehpg_extregs[] = { 346 {"SC_INSTDONE", XEHPG_SC_INSTDONE}, 347 {"SC_INSTDONE_EXTRA", XEHPG_SC_INSTDONE_EXTRA}, 348 {"SC_INSTDONE_EXTRA2", XEHPG_SC_INSTDONE_EXTRA2}, 349 {"INSTDONE_GEOM_SVGUNIT", XEHPG_INSTDONE_GEOM_SVGUNIT} 350 }; 351 352 static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext, 353 const struct __ext_steer_reg *extlist, 354 int slice_id, int subslice_id) 355 { 356 if (!ext || !extlist) 357 return; 358 359 ext->reg = XE_REG(extlist->reg.__reg.addr); 360 ext->flags = FIELD_PREP(GUC_REGSET_STEERING_NEEDED, 1); 361 ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id); 362 ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id); 363 ext->regname = extlist->name; 364 } 365 366 static int 367 __alloc_ext_regs(struct drm_device *drm, struct __guc_mmio_reg_descr_group *newlist, 368 const struct __guc_mmio_reg_descr_group *rootlist, int num_regs) 369 { 370 struct __guc_mmio_reg_descr *list; 371 372 list = drmm_kzalloc(drm, num_regs * sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL); 373 if (!list) 374 return -ENOMEM; 375 376 newlist->list = list; 377 newlist->num_regs = num_regs; 378 newlist->owner = rootlist->owner; 379 newlist->engine = rootlist->engine; 380 newlist->type = rootlist->type; 381 382 return 0; 383 } 384 385 static int guc_capture_get_steer_reg_num(struct xe_device *xe) 386 { 387 int num = ARRAY_SIZE(xe_extregs); 388 389 if (GRAPHICS_VERx100(xe) >= 1255) 390 num += ARRAY_SIZE(xehpg_extregs); 391 392 return num; 393 } 394 395 static void guc_capture_alloc_steered_lists(struct xe_guc *guc) 396 { 397 struct xe_gt *gt = guc_to_gt(guc); 398 u16 slice, subslice; 399 int iter, i, total = 0; 400 const struct __guc_mmio_reg_descr_group *lists = guc->capture->reglists; 401 const struct __guc_mmio_reg_descr_group *list; 402 struct __guc_mmio_reg_descr_group *extlists; 403 struct __guc_mmio_reg_descr *extarray; 404 bool has_xehpg_extregs = GRAPHICS_VERx100(gt_to_xe(gt)) >= 1255; 405 struct drm_device *drm = >_to_xe(gt)->drm; 406 bool has_rcs_ccs = false; 407 struct xe_hw_engine *hwe; 408 enum xe_hw_engine_id id; 409 410 /* 411 * If GT has no rcs/ccs, no need to alloc steered list. 412 * Currently, only rcs/ccs has steering register, if in the future, 413 * other engine types has steering register, this condition check need 414 * to be extended 415 */ 416 for_each_hw_engine(hwe, gt, id) { 417 if (xe_engine_class_to_guc_capture_class(hwe->class) == 418 GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) { 419 has_rcs_ccs = true; 420 break; 421 } 422 } 423 424 if (!has_rcs_ccs) 425 return; 426 427 /* steered registers currently only exist for the render-class */ 428 list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, 429 GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 430 GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE); 431 /* 432 * Skip if this platform has no engine class registers or if extlists 433 * was previously allocated 434 */ 435 if (!list || guc->capture->extlists) 436 return; 437 438 total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) * 439 guc_capture_get_steer_reg_num(guc_to_xe(guc)); 440 441 if (!total) 442 return; 443 444 /* allocate an extra for an end marker */ 445 extlists = drmm_kzalloc(drm, 2 * sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); 446 if (!extlists) 447 return; 448 449 if (__alloc_ext_regs(drm, &extlists[0], list, total)) { 450 drmm_kfree(drm, extlists); 451 return; 452 } 453 454 /* For steering registers, the list is generated at run-time */ 455 extarray = (struct __guc_mmio_reg_descr *)extlists[0].list; 456 for_each_dss_steering(iter, gt, slice, subslice) { 457 for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) { 458 __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); 459 ++extarray; 460 } 461 462 if (has_xehpg_extregs) 463 for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) { 464 __fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice); 465 ++extarray; 466 } 467 } 468 469 extlists[0].num_regs = total; 470 471 xe_gt_dbg(guc_to_gt(guc), "capture found %d ext-regs.\n", total); 472 guc->capture->extlists = extlists; 473 } 474 475 static int 476 guc_capture_list_init(struct xe_guc *guc, u32 owner, u32 type, 477 enum guc_capture_list_class_type capture_class, struct guc_mmio_reg *ptr, 478 u16 num_entries) 479 { 480 u32 ptr_idx = 0, list_idx = 0; 481 const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; 482 struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists; 483 const struct __guc_mmio_reg_descr_group *match; 484 u32 list_num; 485 486 if (!reglists) 487 return -ENODEV; 488 489 match = guc_capture_get_one_list(reglists, owner, type, capture_class); 490 if (!match) 491 return -ENODATA; 492 493 list_num = match->num_regs; 494 for (list_idx = 0; ptr_idx < num_entries && list_idx < list_num; ++list_idx, ++ptr_idx) { 495 ptr[ptr_idx].offset = match->list[list_idx].reg.addr; 496 ptr[ptr_idx].value = 0xDEADF00D; 497 ptr[ptr_idx].flags = match->list[list_idx].flags; 498 ptr[ptr_idx].mask = match->list[list_idx].mask; 499 } 500 501 match = guc_capture_get_one_list(extlists, owner, type, capture_class); 502 if (match) 503 for (ptr_idx = list_num, list_idx = 0; 504 ptr_idx < num_entries && list_idx < match->num_regs; 505 ++ptr_idx, ++list_idx) { 506 ptr[ptr_idx].offset = match->list[list_idx].reg.addr; 507 ptr[ptr_idx].value = 0xDEADF00D; 508 ptr[ptr_idx].flags = match->list[list_idx].flags; 509 ptr[ptr_idx].mask = match->list[list_idx].mask; 510 } 511 512 if (ptr_idx < num_entries) 513 xe_gt_dbg(guc_to_gt(guc), "Got short capture reglist init: %d out-of %d.\n", 514 ptr_idx, num_entries); 515 516 return 0; 517 } 518 519 static int 520 guc_cap_list_num_regs(struct xe_guc *guc, u32 owner, u32 type, 521 enum guc_capture_list_class_type capture_class) 522 { 523 const struct __guc_mmio_reg_descr_group *match; 524 int num_regs = 0; 525 526 match = guc_capture_get_one_list(guc->capture->reglists, owner, type, capture_class); 527 if (match) 528 num_regs = match->num_regs; 529 530 match = guc_capture_get_one_list(guc->capture->extlists, owner, type, capture_class); 531 if (match) 532 num_regs += match->num_regs; 533 else 534 /* 535 * If a caller wants the full register dump size but we have 536 * not yet got the hw-config, which is before max_mmio_per_node 537 * is initialized, then provide a worst-case number for 538 * extlists based on max dss fuse bits, but only ever for 539 * render/compute 540 */ 541 if (owner == GUC_CAPTURE_LIST_INDEX_PF && 542 type == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS && 543 capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE && 544 !guc->capture->max_mmio_per_node) 545 num_regs += guc_capture_get_steer_reg_num(guc_to_xe(guc)) * 546 XE_MAX_DSS_FUSE_BITS; 547 548 return num_regs; 549 } 550 551 static int 552 guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type, 553 enum guc_capture_list_class_type capture_class, 554 size_t *size, bool is_purpose_est) 555 { 556 struct xe_guc_state_capture *gc = guc->capture; 557 struct xe_gt *gt = guc_to_gt(guc); 558 struct __guc_capture_ads_cache *cache; 559 int num_regs; 560 561 xe_gt_assert(gt, type < GUC_STATE_CAPTURE_TYPE_MAX); 562 xe_gt_assert(gt, capture_class < GUC_CAPTURE_LIST_CLASS_MAX); 563 564 cache = &gc->ads_cache[owner][type][capture_class]; 565 if (!gc->reglists) { 566 xe_gt_warn(gt, "No capture reglist for this device\n"); 567 return -ENODEV; 568 } 569 570 if (cache->is_valid) { 571 *size = cache->size; 572 return cache->status; 573 } 574 575 if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF && 576 !guc_capture_get_one_list(gc->reglists, owner, type, capture_class)) { 577 if (type == GUC_STATE_CAPTURE_TYPE_GLOBAL) 578 xe_gt_warn(gt, "Missing capture reglist: global!\n"); 579 else 580 xe_gt_warn(gt, "Missing capture reglist: %s(%u):%s(%u)!\n", 581 capture_list_type_names[type], type, 582 capture_engine_class_names[capture_class], capture_class); 583 return -ENODEV; 584 } 585 586 num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class); 587 /* intentional empty lists can exist depending on hw config */ 588 if (!num_regs) 589 return -ENODATA; 590 591 if (size) 592 *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + 593 (num_regs * sizeof(struct guc_mmio_reg))); 594 595 return 0; 596 } 597 598 /** 599 * xe_guc_capture_getlistsize - Get list size for owner/type/class combination 600 * @guc: The GuC object 601 * @owner: PF/VF owner 602 * @type: GuC capture register type 603 * @capture_class: GuC capture engine class id 604 * @size: Point to the size 605 * 606 * This function will get the list for the owner/type/class combination, and 607 * return the page aligned list size. 608 * 609 * Returns: 0 on success or a negative error code on failure. 610 */ 611 int 612 xe_guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type, 613 enum guc_capture_list_class_type capture_class, size_t *size) 614 { 615 return guc_capture_getlistsize(guc, owner, type, capture_class, size, false); 616 } 617 618 /** 619 * xe_guc_capture_getlist - Get register capture list for owner/type/class 620 * combination 621 * @guc: The GuC object 622 * @owner: PF/VF owner 623 * @type: GuC capture register type 624 * @capture_class: GuC capture engine class id 625 * @outptr: Point to cached register capture list 626 * 627 * This function will get the register capture list for the owner/type/class 628 * combination. 629 * 630 * Returns: 0 on success or a negative error code on failure. 631 */ 632 int 633 xe_guc_capture_getlist(struct xe_guc *guc, u32 owner, u32 type, 634 enum guc_capture_list_class_type capture_class, void **outptr) 635 { 636 struct xe_guc_state_capture *gc = guc->capture; 637 struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][capture_class]; 638 struct guc_debug_capture_list *listnode; 639 int ret, num_regs; 640 u8 *caplist, *tmp; 641 size_t size = 0; 642 643 if (!gc->reglists) 644 return -ENODEV; 645 646 if (cache->is_valid) { 647 *outptr = cache->ptr; 648 return cache->status; 649 } 650 651 ret = xe_guc_capture_getlistsize(guc, owner, type, capture_class, &size); 652 if (ret) { 653 cache->is_valid = true; 654 cache->ptr = NULL; 655 cache->size = 0; 656 cache->status = ret; 657 return ret; 658 } 659 660 caplist = drmm_kzalloc(guc_to_drm(guc), size, GFP_KERNEL); 661 if (!caplist) 662 return -ENOMEM; 663 664 /* populate capture list header */ 665 tmp = caplist; 666 num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class); 667 listnode = (struct guc_debug_capture_list *)tmp; 668 listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs); 669 670 /* populate list of register descriptor */ 671 tmp += sizeof(struct guc_debug_capture_list); 672 guc_capture_list_init(guc, owner, type, capture_class, 673 (struct guc_mmio_reg *)tmp, num_regs); 674 675 /* cache this list */ 676 cache->is_valid = true; 677 cache->ptr = caplist; 678 cache->size = size; 679 cache->status = 0; 680 681 *outptr = caplist; 682 683 return 0; 684 } 685 686 /** 687 * xe_guc_capture_getnullheader - Get a null list for register capture 688 * @guc: The GuC object 689 * @outptr: Point to cached register capture list 690 * @size: Point to the size 691 * 692 * This function will alloc for a null list for register capture. 693 * 694 * Returns: 0 on success or a negative error code on failure. 695 */ 696 int 697 xe_guc_capture_getnullheader(struct xe_guc *guc, void **outptr, size_t *size) 698 { 699 struct xe_guc_state_capture *gc = guc->capture; 700 int tmp = sizeof(u32) * 4; 701 void *null_header; 702 703 if (gc->ads_null_cache) { 704 *outptr = gc->ads_null_cache; 705 *size = tmp; 706 return 0; 707 } 708 709 null_header = drmm_kzalloc(guc_to_drm(guc), tmp, GFP_KERNEL); 710 if (!null_header) 711 return -ENOMEM; 712 713 gc->ads_null_cache = null_header; 714 *outptr = null_header; 715 *size = tmp; 716 717 return 0; 718 } 719 720 /** 721 * xe_guc_capture_ads_input_worst_size - Calculate the worst size for GuC register capture 722 * @guc: point to xe_guc structure 723 * 724 * Calculate the worst size for GuC register capture by including all possible engines classes. 725 * 726 * Returns: Calculated size 727 */ 728 size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc) 729 { 730 size_t total_size, class_size, instance_size, global_size; 731 int i, j; 732 733 /* 734 * This function calculates the worst case register lists size by 735 * including all possible engines classes. It is called during the 736 * first of a two-phase GuC (and ADS-population) initialization 737 * sequence, that is, during the pre-hwconfig phase before we have 738 * the exact engine fusing info. 739 */ 740 total_size = PAGE_SIZE; /* Pad a page in front for empty lists */ 741 for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { 742 for (j = 0; j < GUC_CAPTURE_LIST_CLASS_MAX; j++) { 743 if (xe_guc_capture_getlistsize(guc, i, 744 GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 745 j, &class_size) < 0) 746 class_size = 0; 747 if (xe_guc_capture_getlistsize(guc, i, 748 GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE, 749 j, &instance_size) < 0) 750 instance_size = 0; 751 total_size += class_size + instance_size; 752 } 753 if (xe_guc_capture_getlistsize(guc, i, 754 GUC_STATE_CAPTURE_TYPE_GLOBAL, 755 0, &global_size) < 0) 756 global_size = 0; 757 total_size += global_size; 758 } 759 760 return PAGE_ALIGN(total_size); 761 } 762 763 static int guc_capture_output_size_est(struct xe_guc *guc) 764 { 765 struct xe_gt *gt = guc_to_gt(guc); 766 struct xe_hw_engine *hwe; 767 enum xe_hw_engine_id id; 768 769 int capture_size = 0; 770 size_t tmp = 0; 771 772 if (!guc->capture) 773 return -ENODEV; 774 775 /* 776 * If every single engine-instance suffered a failure in quick succession but 777 * were all unrelated, then a burst of multiple error-capture events would dump 778 * registers for every one engine instance, one at a time. In this case, GuC 779 * would even dump the global-registers repeatedly. 780 * 781 * For each engine instance, there would be 1 x guc_state_capture_group_t output 782 * followed by 3 x guc_state_capture_t lists. The latter is how the register 783 * dumps are split across different register types (where the '3' are global vs class 784 * vs instance). 785 */ 786 for_each_hw_engine(hwe, gt, id) { 787 enum guc_capture_list_class_type capture_class; 788 789 capture_class = xe_engine_class_to_guc_capture_class(hwe->class); 790 capture_size += sizeof(struct guc_state_capture_group_header_t) + 791 (3 * sizeof(struct guc_state_capture_header_t)); 792 793 if (!guc_capture_getlistsize(guc, 0, GUC_STATE_CAPTURE_TYPE_GLOBAL, 794 0, &tmp, true)) 795 capture_size += tmp; 796 if (!guc_capture_getlistsize(guc, 0, GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 797 capture_class, &tmp, true)) 798 capture_size += tmp; 799 if (!guc_capture_getlistsize(guc, 0, GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE, 800 capture_class, &tmp, true)) 801 capture_size += tmp; 802 } 803 804 return capture_size; 805 } 806 807 /* 808 * Add on a 3x multiplier to allow for multiple back-to-back captures occurring 809 * before the Xe can read the data out and process it 810 */ 811 #define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 812 813 static void check_guc_capture_size(struct xe_guc *guc) 814 { 815 int capture_size = guc_capture_output_size_est(guc); 816 int spare_size = capture_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER; 817 u32 buffer_size = xe_guc_log_section_size_capture(&guc->log); 818 819 /* 820 * NOTE: capture_size is much smaller than the capture region 821 * allocation (DG2: <80K vs 1MB). 822 * Additionally, its based on space needed to fit all engines getting 823 * reset at once within the same G2H handler task slot. This is very 824 * unlikely. However, if GuC really does run out of space for whatever 825 * reason, we will see an separate warning message when processing the 826 * G2H event capture-notification, search for: 827 * xe_guc_STATE_CAPTURE_EVENT_STATUS_NOSPACE. 828 */ 829 if (capture_size < 0) 830 xe_gt_dbg(guc_to_gt(guc), 831 "Failed to calculate error state capture buffer minimum size: %d!\n", 832 capture_size); 833 if (capture_size > buffer_size) 834 xe_gt_dbg(guc_to_gt(guc), "Error state capture buffer maybe small: %d < %d\n", 835 buffer_size, capture_size); 836 else if (spare_size > buffer_size) 837 xe_gt_dbg(guc_to_gt(guc), 838 "Error state capture buffer lacks spare size: %d < %d (min = %d)\n", 839 buffer_size, spare_size, capture_size); 840 } 841 842 static void 843 guc_capture_add_node_to_list(struct __guc_capture_parsed_output *node, 844 struct list_head *list) 845 { 846 list_add(&node->link, list); 847 } 848 849 static void 850 guc_capture_add_node_to_outlist(struct xe_guc_state_capture *gc, 851 struct __guc_capture_parsed_output *node) 852 { 853 guc_capture_remove_stale_matches_from_list(gc, node); 854 guc_capture_add_node_to_list(node, &gc->outlist); 855 } 856 857 static void 858 guc_capture_add_node_to_cachelist(struct xe_guc_state_capture *gc, 859 struct __guc_capture_parsed_output *node) 860 { 861 guc_capture_add_node_to_list(node, &gc->cachelist); 862 } 863 864 static void 865 guc_capture_free_outlist_node(struct xe_guc_state_capture *gc, 866 struct __guc_capture_parsed_output *n) 867 { 868 if (n) { 869 n->locked = 0; 870 list_del(&n->link); 871 /* put node back to cache list */ 872 guc_capture_add_node_to_cachelist(gc, n); 873 } 874 } 875 876 static void 877 guc_capture_remove_stale_matches_from_list(struct xe_guc_state_capture *gc, 878 struct __guc_capture_parsed_output *node) 879 { 880 struct __guc_capture_parsed_output *n, *ntmp; 881 int guc_id = node->guc_id; 882 883 list_for_each_entry_safe(n, ntmp, &gc->outlist, link) { 884 if (n != node && !n->locked && n->guc_id == guc_id) 885 guc_capture_free_outlist_node(gc, n); 886 } 887 } 888 889 static void 890 guc_capture_init_node(struct xe_guc *guc, struct __guc_capture_parsed_output *node) 891 { 892 struct guc_mmio_reg *tmp[GUC_STATE_CAPTURE_TYPE_MAX]; 893 int i; 894 895 for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) { 896 tmp[i] = node->reginfo[i].regs; 897 memset(tmp[i], 0, sizeof(struct guc_mmio_reg) * 898 guc->capture->max_mmio_per_node); 899 } 900 memset(node, 0, sizeof(*node)); 901 for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) 902 node->reginfo[i].regs = tmp[i]; 903 904 INIT_LIST_HEAD(&node->link); 905 } 906 907 /** 908 * DOC: Init, G2H-event and reporting flows for GuC-error-capture 909 * 910 * KMD Init time flows: 911 * -------------------- 912 * --> alloc A: GuC input capture regs lists (registered to GuC via ADS). 913 * xe_guc_ads acquires the register lists by calling 914 * xe_guc_capture_getlistsize and xe_guc_capture_getlist 'n' times, 915 * where n = 1 for global-reg-list + 916 * num_engine_classes for class-reg-list + 917 * num_engine_classes for instance-reg-list 918 * (since all instances of the same engine-class type 919 * have an identical engine-instance register-list). 920 * ADS module also calls separately for PF vs VF. 921 * 922 * --> alloc B: GuC output capture buf (registered via guc_init_params(log_param)) 923 * Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small) 924 * Note2: 'x 3' to hold multiple capture groups 925 * 926 * GUC Runtime notify capture: 927 * -------------------------- 928 * --> G2H STATE_CAPTURE_NOTIFICATION 929 * L--> xe_guc_capture_process 930 * L--> Loop through B (head..tail) and for each engine instance's 931 * err-state-captured register-list we find, we alloc 'C': 932 * --> alloc C: A capture-output-node structure that includes misc capture info along 933 * with 3 register list dumps (global, engine-class and engine-instance) 934 * This node is created from a pre-allocated list of blank nodes in 935 * guc->capture->cachelist and populated with the error-capture 936 * data from GuC and then it's added into guc->capture->outlist linked 937 * list. This list is used for matchup and printout by xe_devcoredump_read 938 * and xe_engine_snapshot_print, (when user invokes the devcoredump sysfs). 939 * 940 * GUC --> notify context reset: 941 * ----------------------------- 942 * --> guc_exec_queue_timedout_job 943 * L--> xe_devcoredump 944 * L--> devcoredump_snapshot 945 * --> xe_hw_engine_snapshot_capture 946 * --> xe_engine_manual_capture(For manual capture) 947 * 948 * User Sysfs / Debugfs 949 * -------------------- 950 * --> xe_devcoredump_read-> 951 * L--> xxx_snapshot_print 952 * L--> xe_engine_snapshot_print 953 * Print register lists values saved at 954 * guc->capture->outlist 955 * 956 */ 957 958 static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) 959 { 960 if (buf->wr >= buf->rd) 961 return (buf->wr - buf->rd); 962 return (buf->size - buf->rd) + buf->wr; 963 } 964 965 static int guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate *buf) 966 { 967 if (buf->rd > buf->wr) 968 return (buf->size - buf->rd); 969 return (buf->wr - buf->rd); 970 } 971 972 /* 973 * GuC's error-capture output is a ring buffer populated in a byte-stream fashion: 974 * 975 * The GuC Log buffer region for error-capture is managed like a ring buffer. 976 * The GuC firmware dumps error capture logs into this ring in a byte-stream flow. 977 * Additionally, as per the current and foreseeable future, all packed error- 978 * capture output structures are dword aligned. 979 * 980 * That said, if the GuC firmware is in the midst of writing a structure that is larger 981 * than one dword but the tail end of the err-capture buffer-region has lesser space left, 982 * we would need to extract that structure one dword at a time straddled across the end, 983 * onto the start of the ring. 984 * 985 * Below function, guc_capture_log_remove_bytes is a helper for that. All callers of this 986 * function would typically do a straight-up memcpy from the ring contents and will only 987 * call this helper if their structure-extraction is straddling across the end of the 988 * ring. GuC firmware does not add any padding. The reason for the no-padding is to ease 989 * scalability for future expansion of output data types without requiring a redesign 990 * of the flow controls. 991 */ 992 static int 993 guc_capture_log_remove_bytes(struct xe_guc *guc, struct __guc_capture_bufstate *buf, 994 void *out, int bytes_needed) 995 { 996 #define GUC_CAPTURE_LOG_BUF_COPY_RETRY_MAX 3 997 998 int fill_size = 0, tries = GUC_CAPTURE_LOG_BUF_COPY_RETRY_MAX; 999 int copy_size, avail; 1000 1001 xe_assert(guc_to_xe(guc), bytes_needed % sizeof(u32) == 0); 1002 1003 if (bytes_needed > guc_capture_buf_cnt(buf)) 1004 return -1; 1005 1006 while (bytes_needed > 0 && tries--) { 1007 int misaligned; 1008 1009 avail = guc_capture_buf_cnt_to_end(buf); 1010 misaligned = avail % sizeof(u32); 1011 /* wrap if at end */ 1012 if (!avail) { 1013 /* output stream clipped */ 1014 if (!buf->rd) 1015 return fill_size; 1016 buf->rd = 0; 1017 continue; 1018 } 1019 1020 /* Only copy to u32 aligned data */ 1021 copy_size = avail < bytes_needed ? avail - misaligned : bytes_needed; 1022 xe_map_memcpy_from(guc_to_xe(guc), out + fill_size, &guc->log.bo->vmap, 1023 buf->data_offset + buf->rd, copy_size); 1024 buf->rd += copy_size; 1025 fill_size += copy_size; 1026 bytes_needed -= copy_size; 1027 1028 if (misaligned) 1029 xe_gt_warn(guc_to_gt(guc), 1030 "Bytes extraction not dword aligned, clipping.\n"); 1031 } 1032 1033 return fill_size; 1034 } 1035 1036 static int 1037 guc_capture_log_get_group_hdr(struct xe_guc *guc, struct __guc_capture_bufstate *buf, 1038 struct guc_state_capture_group_header_t *ghdr) 1039 { 1040 int fullsize = sizeof(struct guc_state_capture_group_header_t); 1041 1042 if (guc_capture_log_remove_bytes(guc, buf, ghdr, fullsize) != fullsize) 1043 return -1; 1044 return 0; 1045 } 1046 1047 static int 1048 guc_capture_log_get_data_hdr(struct xe_guc *guc, struct __guc_capture_bufstate *buf, 1049 struct guc_state_capture_header_t *hdr) 1050 { 1051 int fullsize = sizeof(struct guc_state_capture_header_t); 1052 1053 if (guc_capture_log_remove_bytes(guc, buf, hdr, fullsize) != fullsize) 1054 return -1; 1055 return 0; 1056 } 1057 1058 static int 1059 guc_capture_log_get_register(struct xe_guc *guc, struct __guc_capture_bufstate *buf, 1060 struct guc_mmio_reg *reg) 1061 { 1062 int fullsize = sizeof(struct guc_mmio_reg); 1063 1064 if (guc_capture_log_remove_bytes(guc, buf, reg, fullsize) != fullsize) 1065 return -1; 1066 return 0; 1067 } 1068 1069 static struct __guc_capture_parsed_output * 1070 guc_capture_get_prealloc_node(struct xe_guc *guc) 1071 { 1072 struct __guc_capture_parsed_output *found = NULL; 1073 1074 if (!list_empty(&guc->capture->cachelist)) { 1075 struct __guc_capture_parsed_output *n, *ntmp; 1076 1077 /* get first avail node from the cache list */ 1078 list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) { 1079 found = n; 1080 break; 1081 } 1082 } else { 1083 struct __guc_capture_parsed_output *n, *ntmp; 1084 1085 /* 1086 * traverse reversed and steal back the oldest node already 1087 * allocated 1088 */ 1089 list_for_each_entry_safe_reverse(n, ntmp, &guc->capture->outlist, link) { 1090 if (!n->locked) 1091 found = n; 1092 } 1093 } 1094 if (found) { 1095 list_del(&found->link); 1096 guc_capture_init_node(guc, found); 1097 } 1098 1099 return found; 1100 } 1101 1102 static struct __guc_capture_parsed_output * 1103 guc_capture_clone_node(struct xe_guc *guc, struct __guc_capture_parsed_output *original, 1104 u32 keep_reglist_mask) 1105 { 1106 struct __guc_capture_parsed_output *new; 1107 int i; 1108 1109 new = guc_capture_get_prealloc_node(guc); 1110 if (!new) 1111 return NULL; 1112 if (!original) 1113 return new; 1114 1115 new->is_partial = original->is_partial; 1116 1117 /* copy reg-lists that we want to clone */ 1118 for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) { 1119 if (keep_reglist_mask & BIT(i)) { 1120 XE_WARN_ON(original->reginfo[i].num_regs > 1121 guc->capture->max_mmio_per_node); 1122 1123 memcpy(new->reginfo[i].regs, original->reginfo[i].regs, 1124 original->reginfo[i].num_regs * sizeof(struct guc_mmio_reg)); 1125 1126 new->reginfo[i].num_regs = original->reginfo[i].num_regs; 1127 new->reginfo[i].vfid = original->reginfo[i].vfid; 1128 1129 if (i == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS) { 1130 new->eng_class = original->eng_class; 1131 } else if (i == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE) { 1132 new->eng_inst = original->eng_inst; 1133 new->guc_id = original->guc_id; 1134 new->lrca = original->lrca; 1135 } 1136 } 1137 } 1138 1139 return new; 1140 } 1141 1142 static int 1143 guc_capture_extract_reglists(struct xe_guc *guc, struct __guc_capture_bufstate *buf) 1144 { 1145 struct xe_gt *gt = guc_to_gt(guc); 1146 struct guc_state_capture_group_header_t ghdr = {0}; 1147 struct guc_state_capture_header_t hdr = {0}; 1148 struct __guc_capture_parsed_output *node = NULL; 1149 struct guc_mmio_reg *regs = NULL; 1150 int i, numlists, numregs, ret = 0; 1151 enum guc_state_capture_type datatype; 1152 struct guc_mmio_reg tmp; 1153 bool is_partial = false; 1154 1155 i = guc_capture_buf_cnt(buf); 1156 if (!i) 1157 return -ENODATA; 1158 1159 if (i % sizeof(u32)) { 1160 xe_gt_warn(gt, "Got mis-aligned register capture entries\n"); 1161 ret = -EIO; 1162 goto bailout; 1163 } 1164 1165 /* first get the capture group header */ 1166 if (guc_capture_log_get_group_hdr(guc, buf, &ghdr)) { 1167 ret = -EIO; 1168 goto bailout; 1169 } 1170 /* 1171 * we would typically expect a layout as below where n would be expected to be 1172 * anywhere between 3 to n where n > 3 if we are seeing multiple dependent engine 1173 * instances being reset together. 1174 * ____________________________________________ 1175 * | Capture Group | 1176 * | ________________________________________ | 1177 * | | Capture Group Header: | | 1178 * | | - num_captures = 5 | | 1179 * | |______________________________________| | 1180 * | ________________________________________ | 1181 * | | Capture1: | | 1182 * | | Hdr: GLOBAL, numregs=a | | 1183 * | | ____________________________________ | | 1184 * | | | Reglist | | | 1185 * | | | - reg1, reg2, ... rega | | | 1186 * | | |__________________________________| | | 1187 * | |______________________________________| | 1188 * | ________________________________________ | 1189 * | | Capture2: | | 1190 * | | Hdr: CLASS=RENDER/COMPUTE, numregs=b| | 1191 * | | ____________________________________ | | 1192 * | | | Reglist | | | 1193 * | | | - reg1, reg2, ... regb | | | 1194 * | | |__________________________________| | | 1195 * | |______________________________________| | 1196 * | ________________________________________ | 1197 * | | Capture3: | | 1198 * | | Hdr: INSTANCE=RCS, numregs=c | | 1199 * | | ____________________________________ | | 1200 * | | | Reglist | | | 1201 * | | | - reg1, reg2, ... regc | | | 1202 * | | |__________________________________| | | 1203 * | |______________________________________| | 1204 * | ________________________________________ | 1205 * | | Capture4: | | 1206 * | | Hdr: CLASS=RENDER/COMPUTE, numregs=d| | 1207 * | | ____________________________________ | | 1208 * | | | Reglist | | | 1209 * | | | - reg1, reg2, ... regd | | | 1210 * | | |__________________________________| | | 1211 * | |______________________________________| | 1212 * | ________________________________________ | 1213 * | | Capture5: | | 1214 * | | Hdr: INSTANCE=CCS0, numregs=e | | 1215 * | | ____________________________________ | | 1216 * | | | Reglist | | | 1217 * | | | - reg1, reg2, ... rege | | | 1218 * | | |__________________________________| | | 1219 * | |______________________________________| | 1220 * |__________________________________________| 1221 */ 1222 is_partial = FIELD_GET(GUC_STATE_CAPTURE_GROUP_HEADER_CAPTURE_GROUP_TYPE, ghdr.info); 1223 numlists = FIELD_GET(GUC_STATE_CAPTURE_GROUP_HEADER_NUM_CAPTURES, ghdr.info); 1224 1225 while (numlists--) { 1226 if (guc_capture_log_get_data_hdr(guc, buf, &hdr)) { 1227 ret = -EIO; 1228 break; 1229 } 1230 1231 datatype = FIELD_GET(GUC_STATE_CAPTURE_HEADER_CAPTURE_TYPE, hdr.info); 1232 if (datatype > GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE) { 1233 /* unknown capture type - skip over to next capture set */ 1234 numregs = FIELD_GET(GUC_STATE_CAPTURE_HEADER_NUM_MMIO_ENTRIES, 1235 hdr.num_mmio_entries); 1236 while (numregs--) { 1237 if (guc_capture_log_get_register(guc, buf, &tmp)) { 1238 ret = -EIO; 1239 break; 1240 } 1241 } 1242 continue; 1243 } else if (node) { 1244 /* 1245 * Based on the current capture type and what we have so far, 1246 * decide if we should add the current node into the internal 1247 * linked list for match-up when xe_devcoredump calls later 1248 * (and alloc a blank node for the next set of reglists) 1249 * or continue with the same node or clone the current node 1250 * but only retain the global or class registers (such as the 1251 * case of dependent engine resets). 1252 */ 1253 if (datatype == GUC_STATE_CAPTURE_TYPE_GLOBAL) { 1254 guc_capture_add_node_to_outlist(guc->capture, node); 1255 node = NULL; 1256 } else if (datatype == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS && 1257 node->reginfo[GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS].num_regs) { 1258 /* Add to list, clone node and duplicate global list */ 1259 guc_capture_add_node_to_outlist(guc->capture, node); 1260 node = guc_capture_clone_node(guc, node, 1261 GCAP_PARSED_REGLIST_INDEX_GLOBAL); 1262 } else if (datatype == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE && 1263 node->reginfo[GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE].num_regs) { 1264 /* Add to list, clone node and duplicate global + class lists */ 1265 guc_capture_add_node_to_outlist(guc->capture, node); 1266 node = guc_capture_clone_node(guc, node, 1267 (GCAP_PARSED_REGLIST_INDEX_GLOBAL | 1268 GCAP_PARSED_REGLIST_INDEX_ENGCLASS)); 1269 } 1270 } 1271 1272 if (!node) { 1273 node = guc_capture_get_prealloc_node(guc); 1274 if (!node) { 1275 ret = -ENOMEM; 1276 break; 1277 } 1278 if (datatype != GUC_STATE_CAPTURE_TYPE_GLOBAL) 1279 xe_gt_dbg(gt, "Register capture missing global dump: %08x!\n", 1280 datatype); 1281 } 1282 node->is_partial = is_partial; 1283 node->reginfo[datatype].vfid = FIELD_GET(GUC_STATE_CAPTURE_HEADER_VFID, hdr.owner); 1284 node->source = XE_ENGINE_CAPTURE_SOURCE_GUC; 1285 node->type = datatype; 1286 1287 switch (datatype) { 1288 case GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE: 1289 node->eng_class = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_CLASS, 1290 hdr.info); 1291 node->eng_inst = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_INSTANCE, 1292 hdr.info); 1293 node->lrca = hdr.lrca; 1294 node->guc_id = hdr.guc_id; 1295 break; 1296 case GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS: 1297 node->eng_class = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_CLASS, 1298 hdr.info); 1299 break; 1300 default: 1301 break; 1302 } 1303 1304 numregs = FIELD_GET(GUC_STATE_CAPTURE_HEADER_NUM_MMIO_ENTRIES, 1305 hdr.num_mmio_entries); 1306 if (numregs > guc->capture->max_mmio_per_node) { 1307 xe_gt_dbg(gt, "Register capture list extraction clipped by prealloc!\n"); 1308 numregs = guc->capture->max_mmio_per_node; 1309 } 1310 node->reginfo[datatype].num_regs = numregs; 1311 regs = node->reginfo[datatype].regs; 1312 i = 0; 1313 while (numregs--) { 1314 if (guc_capture_log_get_register(guc, buf, ®s[i++])) { 1315 ret = -EIO; 1316 break; 1317 } 1318 } 1319 } 1320 1321 bailout: 1322 if (node) { 1323 /* If we have data, add to linked list for match-up when xe_devcoredump calls */ 1324 for (i = GUC_STATE_CAPTURE_TYPE_GLOBAL; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) { 1325 if (node->reginfo[i].regs) { 1326 guc_capture_add_node_to_outlist(guc->capture, node); 1327 node = NULL; 1328 break; 1329 } 1330 } 1331 if (node) /* else return it back to cache list */ 1332 guc_capture_add_node_to_cachelist(guc->capture, node); 1333 } 1334 return ret; 1335 } 1336 1337 static int __guc_capture_flushlog_complete(struct xe_guc *guc) 1338 { 1339 u32 action[] = { 1340 XE_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE, 1341 GUC_LOG_BUFFER_CAPTURE 1342 }; 1343 1344 return xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action)); 1345 } 1346 1347 static void __guc_capture_process_output(struct xe_guc *guc) 1348 { 1349 unsigned int buffer_size, read_offset, write_offset, full_count; 1350 struct xe_uc *uc = container_of(guc, typeof(*uc), guc); 1351 struct guc_log_buffer_state log_buf_state_local; 1352 struct __guc_capture_bufstate buf; 1353 bool new_overflow; 1354 int ret, tmp; 1355 u32 log_buf_state_offset; 1356 u32 src_data_offset; 1357 1358 log_buf_state_offset = sizeof(struct guc_log_buffer_state) * GUC_LOG_BUFFER_CAPTURE; 1359 src_data_offset = xe_guc_get_log_buffer_offset(&guc->log, GUC_LOG_BUFFER_CAPTURE); 1360 1361 /* 1362 * Make a copy of the state structure, inside GuC log buffer 1363 * (which is uncached mapped), on the stack to avoid reading 1364 * from it multiple times. 1365 */ 1366 xe_map_memcpy_from(guc_to_xe(guc), &log_buf_state_local, &guc->log.bo->vmap, 1367 log_buf_state_offset, sizeof(struct guc_log_buffer_state)); 1368 1369 buffer_size = xe_guc_get_log_buffer_size(&guc->log, GUC_LOG_BUFFER_CAPTURE); 1370 read_offset = log_buf_state_local.read_ptr; 1371 write_offset = log_buf_state_local.sampled_write_ptr; 1372 full_count = FIELD_GET(GUC_LOG_BUFFER_STATE_BUFFER_FULL_CNT, log_buf_state_local.flags); 1373 1374 /* Bookkeeping stuff */ 1375 tmp = FIELD_GET(GUC_LOG_BUFFER_STATE_FLUSH_TO_FILE, log_buf_state_local.flags); 1376 guc->log.stats[GUC_LOG_BUFFER_CAPTURE].flush += tmp; 1377 new_overflow = xe_guc_check_log_buf_overflow(&guc->log, GUC_LOG_BUFFER_CAPTURE, 1378 full_count); 1379 1380 /* Now copy the actual logs. */ 1381 if (unlikely(new_overflow)) { 1382 /* copy the whole buffer in case of overflow */ 1383 read_offset = 0; 1384 write_offset = buffer_size; 1385 } else if (unlikely((read_offset > buffer_size) || 1386 (write_offset > buffer_size))) { 1387 xe_gt_err(guc_to_gt(guc), 1388 "Register capture buffer in invalid state: read = 0x%X, size = 0x%X!\n", 1389 read_offset, buffer_size); 1390 /* copy whole buffer as offsets are unreliable */ 1391 read_offset = 0; 1392 write_offset = buffer_size; 1393 } 1394 1395 buf.size = buffer_size; 1396 buf.rd = read_offset; 1397 buf.wr = write_offset; 1398 buf.data_offset = src_data_offset; 1399 1400 if (!xe_guc_read_stopped(guc)) { 1401 do { 1402 ret = guc_capture_extract_reglists(guc, &buf); 1403 if (ret && ret != -ENODATA) 1404 xe_gt_dbg(guc_to_gt(guc), "Capture extraction failed:%d\n", ret); 1405 } while (ret >= 0); 1406 } 1407 1408 /* Update the state of log buffer err-cap state */ 1409 xe_map_wr(guc_to_xe(guc), &guc->log.bo->vmap, 1410 log_buf_state_offset + offsetof(struct guc_log_buffer_state, read_ptr), u32, 1411 write_offset); 1412 1413 /* 1414 * Clear the flush_to_file from local first, the local was loaded by above 1415 * xe_map_memcpy_from, then write out the "updated local" through 1416 * xe_map_wr() 1417 */ 1418 log_buf_state_local.flags &= ~GUC_LOG_BUFFER_STATE_FLUSH_TO_FILE; 1419 xe_map_wr(guc_to_xe(guc), &guc->log.bo->vmap, 1420 log_buf_state_offset + offsetof(struct guc_log_buffer_state, flags), u32, 1421 log_buf_state_local.flags); 1422 __guc_capture_flushlog_complete(guc); 1423 } 1424 1425 /* 1426 * xe_guc_capture_process - Process GuC register captured data 1427 * @guc: The GuC object 1428 * 1429 * When GuC captured data is ready, GuC will send message 1430 * XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION to host, this function will be 1431 * called to process the data comes with the message. 1432 * 1433 * Returns: None 1434 */ 1435 void xe_guc_capture_process(struct xe_guc *guc) 1436 { 1437 if (guc->capture) 1438 __guc_capture_process_output(guc); 1439 } 1440 1441 static struct __guc_capture_parsed_output * 1442 guc_capture_alloc_one_node(struct xe_guc *guc) 1443 { 1444 struct drm_device *drm = guc_to_drm(guc); 1445 struct __guc_capture_parsed_output *new; 1446 int i; 1447 1448 new = drmm_kzalloc(drm, sizeof(*new), GFP_KERNEL); 1449 if (!new) 1450 return NULL; 1451 1452 for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) { 1453 new->reginfo[i].regs = drmm_kzalloc(drm, guc->capture->max_mmio_per_node * 1454 sizeof(struct guc_mmio_reg), GFP_KERNEL); 1455 if (!new->reginfo[i].regs) { 1456 while (i) 1457 drmm_kfree(drm, new->reginfo[--i].regs); 1458 drmm_kfree(drm, new); 1459 return NULL; 1460 } 1461 } 1462 guc_capture_init_node(guc, new); 1463 1464 return new; 1465 } 1466 1467 static void 1468 __guc_capture_create_prealloc_nodes(struct xe_guc *guc) 1469 { 1470 struct __guc_capture_parsed_output *node = NULL; 1471 int i; 1472 1473 for (i = 0; i < PREALLOC_NODES_MAX_COUNT; ++i) { 1474 node = guc_capture_alloc_one_node(guc); 1475 if (!node) { 1476 xe_gt_warn(guc_to_gt(guc), "Register capture pre-alloc-cache failure\n"); 1477 /* dont free the priors, use what we got and cleanup at shutdown */ 1478 return; 1479 } 1480 guc_capture_add_node_to_cachelist(guc->capture, node); 1481 } 1482 } 1483 1484 static int 1485 guc_get_max_reglist_count(struct xe_guc *guc) 1486 { 1487 int i, j, k, tmp, maxregcount = 0; 1488 1489 for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) { 1490 for (j = 0; j < GUC_STATE_CAPTURE_TYPE_MAX; ++j) { 1491 for (k = 0; k < GUC_CAPTURE_LIST_CLASS_MAX; ++k) { 1492 const struct __guc_mmio_reg_descr_group *match; 1493 1494 if (j == GUC_STATE_CAPTURE_TYPE_GLOBAL && k > 0) 1495 continue; 1496 1497 tmp = 0; 1498 match = guc_capture_get_one_list(guc->capture->reglists, i, j, k); 1499 if (match) 1500 tmp = match->num_regs; 1501 1502 match = guc_capture_get_one_list(guc->capture->extlists, i, j, k); 1503 if (match) 1504 tmp += match->num_regs; 1505 1506 if (tmp > maxregcount) 1507 maxregcount = tmp; 1508 } 1509 } 1510 } 1511 if (!maxregcount) 1512 maxregcount = PREALLOC_NODES_DEFAULT_NUMREGS; 1513 1514 return maxregcount; 1515 } 1516 1517 static void 1518 guc_capture_create_prealloc_nodes(struct xe_guc *guc) 1519 { 1520 /* skip if we've already done the pre-alloc */ 1521 if (guc->capture->max_mmio_per_node) 1522 return; 1523 1524 guc->capture->max_mmio_per_node = guc_get_max_reglist_count(guc); 1525 __guc_capture_create_prealloc_nodes(guc); 1526 } 1527 1528 static void 1529 read_reg_to_node(struct xe_hw_engine *hwe, const struct __guc_mmio_reg_descr_group *list, 1530 struct guc_mmio_reg *regs) 1531 { 1532 int i; 1533 1534 if (!list || !list->list || list->num_regs == 0) 1535 return; 1536 1537 if (!regs) 1538 return; 1539 1540 for (i = 0; i < list->num_regs; i++) { 1541 struct __guc_mmio_reg_descr desc = list->list[i]; 1542 u32 value; 1543 1544 if (list->type == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE) { 1545 value = xe_hw_engine_mmio_read32(hwe, desc.reg); 1546 } else { 1547 if (list->type == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS && 1548 FIELD_GET(GUC_REGSET_STEERING_NEEDED, desc.flags)) { 1549 int group, instance; 1550 1551 group = FIELD_GET(GUC_REGSET_STEERING_GROUP, desc.flags); 1552 instance = FIELD_GET(GUC_REGSET_STEERING_INSTANCE, desc.flags); 1553 value = xe_gt_mcr_unicast_read(hwe->gt, XE_REG_MCR(desc.reg.addr), 1554 group, instance); 1555 } else { 1556 value = xe_mmio_read32(&hwe->gt->mmio, desc.reg); 1557 } 1558 } 1559 1560 regs[i].value = value; 1561 regs[i].offset = desc.reg.addr; 1562 regs[i].flags = desc.flags; 1563 regs[i].mask = desc.mask; 1564 } 1565 } 1566 1567 /** 1568 * xe_engine_manual_capture - Take a manual engine snapshot from engine. 1569 * @hwe: Xe HW Engine. 1570 * @snapshot: The engine snapshot 1571 * 1572 * Take engine snapshot from engine read. 1573 * 1574 * Returns: None 1575 */ 1576 void 1577 xe_engine_manual_capture(struct xe_hw_engine *hwe, struct xe_hw_engine_snapshot *snapshot) 1578 { 1579 struct xe_gt *gt = hwe->gt; 1580 struct xe_device *xe = gt_to_xe(gt); 1581 struct xe_guc *guc = >->uc.guc; 1582 struct xe_devcoredump *devcoredump = &xe->devcoredump; 1583 enum guc_capture_list_class_type capture_class; 1584 const struct __guc_mmio_reg_descr_group *list; 1585 struct __guc_capture_parsed_output *new; 1586 enum guc_state_capture_type type; 1587 u16 guc_id = 0; 1588 u32 lrca = 0; 1589 1590 if (IS_SRIOV_VF(xe)) 1591 return; 1592 1593 new = guc_capture_get_prealloc_node(guc); 1594 if (!new) 1595 return; 1596 1597 capture_class = xe_engine_class_to_guc_capture_class(hwe->class); 1598 for (type = GUC_STATE_CAPTURE_TYPE_GLOBAL; type < GUC_STATE_CAPTURE_TYPE_MAX; type++) { 1599 struct gcap_reg_list_info *reginfo = &new->reginfo[type]; 1600 /* 1601 * regsinfo->regs is allocated based on guc->capture->max_mmio_per_node 1602 * which is based on the descriptor list driving the population so 1603 * should not overflow 1604 */ 1605 1606 /* Get register list for the type/class */ 1607 list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF, type, 1608 capture_class, false); 1609 if (!list) { 1610 xe_gt_dbg(gt, "Empty GuC capture register descriptor for %s", 1611 hwe->name); 1612 continue; 1613 } 1614 1615 read_reg_to_node(hwe, list, reginfo->regs); 1616 reginfo->num_regs = list->num_regs; 1617 1618 /* Capture steering registers for rcs/ccs */ 1619 if (capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) { 1620 list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF, 1621 type, capture_class, true); 1622 if (list) { 1623 read_reg_to_node(hwe, list, ®info->regs[reginfo->num_regs]); 1624 reginfo->num_regs += list->num_regs; 1625 } 1626 } 1627 } 1628 1629 if (devcoredump && devcoredump->captured) { 1630 struct xe_guc_submit_exec_queue_snapshot *ge = devcoredump->snapshot.ge; 1631 1632 if (ge) { 1633 guc_id = ge->guc.id; 1634 if (ge->lrc[0]) 1635 lrca = ge->lrc[0]->context_desc; 1636 } 1637 } 1638 1639 new->eng_class = xe_engine_class_to_guc_class(hwe->class); 1640 new->eng_inst = hwe->instance; 1641 new->guc_id = guc_id; 1642 new->lrca = lrca; 1643 new->is_partial = 0; 1644 new->locked = 1; 1645 new->source = XE_ENGINE_CAPTURE_SOURCE_MANUAL; 1646 1647 guc_capture_add_node_to_outlist(guc->capture, new); 1648 devcoredump->snapshot.matched_node = new; 1649 } 1650 1651 static struct guc_mmio_reg * 1652 guc_capture_find_reg(struct gcap_reg_list_info *reginfo, u32 addr, u32 flags) 1653 { 1654 int i; 1655 1656 if (reginfo && reginfo->num_regs > 0) { 1657 struct guc_mmio_reg *regs = reginfo->regs; 1658 1659 if (regs) 1660 for (i = 0; i < reginfo->num_regs; i++) 1661 if (regs[i].offset == addr && regs[i].flags == flags) 1662 return ®s[i]; 1663 } 1664 1665 return NULL; 1666 } 1667 1668 static void 1669 snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_printer *p, 1670 u32 type, const struct __guc_mmio_reg_descr_group *list) 1671 { 1672 struct xe_gt *gt = snapshot->hwe->gt; 1673 struct xe_device *xe = gt_to_xe(gt); 1674 struct xe_guc *guc = >->uc.guc; 1675 struct xe_devcoredump *devcoredump = &xe->devcoredump; 1676 struct xe_devcoredump_snapshot *devcore_snapshot = &devcoredump->snapshot; 1677 struct gcap_reg_list_info *reginfo = NULL; 1678 u32 last_value, i; 1679 bool is_ext; 1680 1681 if (!list || list->num_regs == 0) 1682 return; 1683 XE_WARN_ON(!devcore_snapshot->matched_node); 1684 1685 is_ext = list == guc->capture->extlists; 1686 reginfo = &devcore_snapshot->matched_node->reginfo[type]; 1687 1688 /* 1689 * loop through descriptor first and find the register in the node 1690 * this is more scalable for developer maintenance as it will ensure 1691 * the printout matched the ordering of the static descriptor 1692 * table-of-lists 1693 */ 1694 for (i = 0; i < list->num_regs; i++) { 1695 const struct __guc_mmio_reg_descr *reg_desc = &list->list[i]; 1696 struct guc_mmio_reg *reg; 1697 u32 value; 1698 1699 reg = guc_capture_find_reg(reginfo, reg_desc->reg.addr, reg_desc->flags); 1700 if (!reg) 1701 continue; 1702 1703 value = reg->value; 1704 if (reg_desc->data_type == REG_64BIT_LOW_DW) { 1705 last_value = value; 1706 /* Low 32 bit dword saved, continue for high 32 bit */ 1707 continue; 1708 } else if (reg_desc->data_type == REG_64BIT_HI_DW) { 1709 u64 value_qw = ((u64)value << 32) | last_value; 1710 1711 drm_printf(p, "\t%s: 0x%016llx\n", reg_desc->regname, value_qw); 1712 continue; 1713 } 1714 1715 if (is_ext) { 1716 int dss, group, instance; 1717 1718 group = FIELD_GET(GUC_REGSET_STEERING_GROUP, reg_desc->flags); 1719 instance = FIELD_GET(GUC_REGSET_STEERING_INSTANCE, reg_desc->flags); 1720 dss = xe_gt_mcr_steering_info_to_dss_id(gt, group, instance); 1721 1722 drm_printf(p, "\t%s[%u]: 0x%08x\n", reg_desc->regname, dss, value); 1723 } else { 1724 drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value); 1725 } 1726 } 1727 } 1728 1729 /** 1730 * xe_engine_snapshot_print - Print out a given Xe HW Engine snapshot. 1731 * @snapshot: Xe HW Engine snapshot object. 1732 * @p: drm_printer where it will be printed out. 1733 * 1734 * This function prints out a given Xe HW Engine snapshot object. 1735 */ 1736 void xe_engine_snapshot_print(struct xe_hw_engine_snapshot *snapshot, struct drm_printer *p) 1737 { 1738 const char *grptype[GUC_STATE_CAPTURE_GROUP_TYPE_MAX] = { 1739 "full-capture", 1740 "partial-capture" 1741 }; 1742 int type; 1743 const struct __guc_mmio_reg_descr_group *list; 1744 enum guc_capture_list_class_type capture_class; 1745 1746 struct xe_gt *gt; 1747 struct xe_device *xe; 1748 struct xe_devcoredump *devcoredump; 1749 struct xe_devcoredump_snapshot *devcore_snapshot; 1750 1751 if (!snapshot) 1752 return; 1753 1754 gt = snapshot->hwe->gt; 1755 xe = gt_to_xe(gt); 1756 devcoredump = &xe->devcoredump; 1757 devcore_snapshot = &devcoredump->snapshot; 1758 1759 if (!devcore_snapshot->matched_node) 1760 return; 1761 1762 xe_gt_assert(gt, snapshot->source <= XE_ENGINE_CAPTURE_SOURCE_GUC); 1763 xe_gt_assert(gt, snapshot->hwe); 1764 1765 capture_class = xe_engine_class_to_guc_capture_class(snapshot->hwe->class); 1766 1767 drm_printf(p, "%s (physical), logical instance=%d\n", 1768 snapshot->name ? snapshot->name : "", 1769 snapshot->logical_instance); 1770 drm_printf(p, "\tCapture_source: %s\n", 1771 snapshot->source == XE_ENGINE_CAPTURE_SOURCE_GUC ? "GuC" : "Manual"); 1772 drm_printf(p, "\tCoverage: %s\n", grptype[devcore_snapshot->matched_node->is_partial]); 1773 drm_printf(p, "\tForcewake: domain 0x%x, ref %d\n", 1774 snapshot->forcewake.domain, snapshot->forcewake.ref); 1775 drm_printf(p, "\tReserved: %s\n", 1776 str_yes_no(snapshot->kernel_reserved)); 1777 1778 for (type = GUC_STATE_CAPTURE_TYPE_GLOBAL; type < GUC_STATE_CAPTURE_TYPE_MAX; type++) { 1779 list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF, type, 1780 capture_class, false); 1781 snapshot_print_by_list_order(snapshot, p, type, list); 1782 } 1783 1784 if (capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) { 1785 list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF, 1786 GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 1787 capture_class, true); 1788 snapshot_print_by_list_order(snapshot, p, GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS, 1789 list); 1790 } 1791 1792 drm_puts(p, "\n"); 1793 } 1794 1795 /** 1796 * xe_guc_capture_get_matching_and_lock - Matching GuC capture for the job. 1797 * @job: The job object. 1798 * 1799 * Search within the capture outlist for the job, could be used for check if 1800 * GuC capture is ready for the job. 1801 * If found, the locked boolean of the node will be flagged. 1802 * 1803 * Returns: found guc-capture node ptr else NULL 1804 */ 1805 struct __guc_capture_parsed_output * 1806 xe_guc_capture_get_matching_and_lock(struct xe_sched_job *job) 1807 { 1808 struct xe_hw_engine *hwe; 1809 enum xe_hw_engine_id id; 1810 struct xe_exec_queue *q; 1811 struct xe_device *xe; 1812 u16 guc_class = GUC_LAST_ENGINE_CLASS + 1; 1813 struct xe_devcoredump_snapshot *ss; 1814 1815 if (!job) 1816 return NULL; 1817 1818 q = job->q; 1819 if (!q || !q->gt) 1820 return NULL; 1821 1822 xe = gt_to_xe(q->gt); 1823 if (xe->wedged.mode >= 2 || !xe_device_uc_enabled(xe) || IS_SRIOV_VF(xe)) 1824 return NULL; 1825 1826 ss = &xe->devcoredump.snapshot; 1827 if (ss->matched_node && ss->matched_node->source == XE_ENGINE_CAPTURE_SOURCE_GUC) 1828 return ss->matched_node; 1829 1830 /* Find hwe for the job */ 1831 for_each_hw_engine(hwe, q->gt, id) { 1832 if (hwe != q->hwe) 1833 continue; 1834 guc_class = xe_engine_class_to_guc_class(hwe->class); 1835 break; 1836 } 1837 1838 if (guc_class <= GUC_LAST_ENGINE_CLASS) { 1839 struct __guc_capture_parsed_output *n, *ntmp; 1840 struct xe_guc *guc = &q->gt->uc.guc; 1841 u16 guc_id = q->guc->id; 1842 u32 lrca = xe_lrc_ggtt_addr(q->lrc[0]); 1843 1844 /* 1845 * Look for a matching GuC reported error capture node from 1846 * the internal output link-list based on engine, guc id and 1847 * lrca info. 1848 */ 1849 list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) { 1850 if (n->eng_class == guc_class && n->eng_inst == hwe->instance && 1851 n->guc_id == guc_id && n->lrca == lrca && 1852 n->source == XE_ENGINE_CAPTURE_SOURCE_GUC) { 1853 n->locked = 1; 1854 return n; 1855 } 1856 } 1857 } 1858 return NULL; 1859 } 1860 1861 /** 1862 * xe_engine_snapshot_capture_for_job - Take snapshot of associated engine 1863 * @job: The job object 1864 * 1865 * Take snapshot of associated HW Engine 1866 * 1867 * Returns: None. 1868 */ 1869 void 1870 xe_engine_snapshot_capture_for_job(struct xe_sched_job *job) 1871 { 1872 struct xe_exec_queue *q = job->q; 1873 struct xe_device *xe = gt_to_xe(q->gt); 1874 struct xe_devcoredump *coredump = &xe->devcoredump; 1875 struct xe_hw_engine *hwe; 1876 enum xe_hw_engine_id id; 1877 u32 adj_logical_mask = q->logical_mask; 1878 1879 if (IS_SRIOV_VF(xe)) 1880 return; 1881 1882 for_each_hw_engine(hwe, q->gt, id) { 1883 if (hwe->class != q->hwe->class || 1884 !(BIT(hwe->logical_instance) & adj_logical_mask)) { 1885 coredump->snapshot.hwe[id] = NULL; 1886 continue; 1887 } 1888 1889 if (!coredump->snapshot.hwe[id]) { 1890 coredump->snapshot.hwe[id] = xe_hw_engine_snapshot_capture(hwe, job); 1891 } else { 1892 struct __guc_capture_parsed_output *new; 1893 1894 new = xe_guc_capture_get_matching_and_lock(job); 1895 if (new) { 1896 struct xe_guc *guc = &q->gt->uc.guc; 1897 1898 /* 1899 * If we are in here, it means we found a fresh 1900 * GuC-err-capture node for this engine after 1901 * previously failing to find a match in the 1902 * early part of guc_exec_queue_timedout_job. 1903 * Thus we must free the manually captured node 1904 */ 1905 guc_capture_free_outlist_node(guc->capture, 1906 coredump->snapshot.matched_node); 1907 coredump->snapshot.matched_node = new; 1908 } 1909 } 1910 1911 break; 1912 } 1913 } 1914 1915 /* 1916 * xe_guc_capture_put_matched_nodes - Cleanup macthed nodes 1917 * @guc: The GuC object 1918 * 1919 * Free matched node and all nodes with the equal guc_id from 1920 * GuC captured outlist 1921 */ 1922 void xe_guc_capture_put_matched_nodes(struct xe_guc *guc) 1923 { 1924 struct xe_device *xe = guc_to_xe(guc); 1925 struct xe_devcoredump *devcoredump = &xe->devcoredump; 1926 struct __guc_capture_parsed_output *n = devcoredump->snapshot.matched_node; 1927 1928 if (n) { 1929 guc_capture_remove_stale_matches_from_list(guc->capture, n); 1930 guc_capture_free_outlist_node(guc->capture, n); 1931 devcoredump->snapshot.matched_node = NULL; 1932 } 1933 } 1934 1935 /* 1936 * xe_guc_capture_steered_list_init - Init steering register list 1937 * @guc: The GuC object 1938 * 1939 * Init steering register list for GuC register capture, create pre-alloc node 1940 */ 1941 void xe_guc_capture_steered_list_init(struct xe_guc *guc) 1942 { 1943 /* 1944 * For certain engine classes, there are slice and subslice 1945 * level registers requiring steering. We allocate and populate 1946 * these based on hw config and add it as an extension list at 1947 * the end of the pre-populated render list. 1948 */ 1949 guc_capture_alloc_steered_lists(guc); 1950 check_guc_capture_size(guc); 1951 guc_capture_create_prealloc_nodes(guc); 1952 } 1953 1954 /* 1955 * xe_guc_capture_init - Init for GuC register capture 1956 * @guc: The GuC object 1957 * 1958 * Init for GuC register capture, alloc memory for capture data structure. 1959 * 1960 * Returns: 0 if success. 1961 * -ENOMEM if out of memory 1962 */ 1963 int xe_guc_capture_init(struct xe_guc *guc) 1964 { 1965 guc->capture = drmm_kzalloc(guc_to_drm(guc), sizeof(*guc->capture), GFP_KERNEL); 1966 if (!guc->capture) 1967 return -ENOMEM; 1968 1969 guc->capture->reglists = guc_capture_get_device_reglist(guc_to_xe(guc)); 1970 1971 INIT_LIST_HEAD(&guc->capture->outlist); 1972 INIT_LIST_HEAD(&guc->capture->cachelist); 1973 1974 return 0; 1975 } 1976