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