cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_guc_capture.c (50789B)


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