From patchwork Wed Jan 26 10:48:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724933 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5ABA7C2BA4C for ; Wed, 26 Jan 2022 10:46:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 37FEC10E834; Wed, 26 Jan 2022 10:46:24 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id B3F3B10E794 for ; Wed, 26 Jan 2022 10:46:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193982; x=1674729982; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=231/M3RM16rDPN8YK4D6cC62oCBiYKgIlVe8jVKbLmA=; b=cI1DMGsrQWt95H/f3n1A48lrbSLG/k46plAbr/tW62N0fXhUvzjwvaRp Nniw6cyYCVLZRPlxmIy1+KCHD9l7w3sSNYMb/pMkMzk4VlixYc5iGLbVU NN/9XDIew+HnExGyOo4gmv/Bn1g9RIP4RbFdv8TmjsZ+PkCxlseKE8FXf YlDNULaAyA/UpXYIQptZ+VdvVxIdQ3nIkZGcZwWm7Rp95POax+xXxZSUm kwrYPEH6fVcGt6BLYam5RqqR8PPZbpVSJMTj9JicUdE0nbpnG9OvwZGZt CBz7tOI/HCynJ9jMHSRYFJPtzG/t7U9Vi7ACPXG2u5SxAmL+s8HhtnUUa A==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301873" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301873" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445960" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:21 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:13 -0800 Message-Id: <20220126104822.3653079-2-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 01/10] drm/i915/guc: Update GuC ADS size for error capture lists X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Update GuC ADS size allocation to include space for the lists of error state capture register descriptors. Also, populate the lists of registers we want GuC to report back to Host on engine reset events. This list should include global, engine-class and engine-instance registers for every engine-class type on the current hardware. NOTE: Start with a sample table of register lists to layout the framework before adding real registers in subsequent patch. Signed-off-by: Alan Previn --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 36 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c | 13 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 11 +- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 36 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 450 ++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 20 + drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 17 + 8 files changed, 555 insertions(+), 29 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index a26e6736bebb..236bcd6cd8ea 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -183,6 +183,7 @@ i915-y += gt/uc/intel_uc.o \ gt/uc/intel_uc_fw.o \ gt/uc/intel_guc.o \ gt/uc/intel_guc_ads.o \ + gt/uc/intel_guc_capture.o \ gt/uc/intel_guc_ct.o \ gt/uc/intel_guc_debugfs.o \ gt/uc/intel_guc_fw.o \ diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h new file mode 100644 index 000000000000..15b8c02b8a76 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021-2021 Intel Corporation + */ + +#ifndef _INTEL_GUC_CAPTURE_FWIF_H +#define _INTEL_GUC_CAPTURE_FWIF_H + +#include +#include "intel_guc_fwif.h" + +struct intel_guc; + +struct __guc_mmio_reg_descr { + i915_reg_t reg; + u32 flags; + u32 mask; + const char *regname; +}; + +struct __guc_mmio_reg_descr_group { + struct __guc_mmio_reg_descr *list; + u32 num_regs; + u32 owner; /* see enum guc_capture_owner */ + u32 type; /* see enum guc_capture_type */ + u32 engine; /* as per MAX_ENGINE_CLASS */ +}; + +struct __guc_state_capture_priv { + struct __guc_mmio_reg_descr_group *reglists; + u16 num_instance_regs[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES]; + u16 num_class_regs[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES]; + u16 num_global_regs[GUC_CAPTURE_LIST_INDEX_MAX]; +}; + +#endif /* _INTEL_GUC_CAPTURE_FWIF_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index ba2a67f9e500..d035a3ba8700 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -8,8 +8,9 @@ #include "gt/intel_gt_irq.h" #include "gt/intel_gt_pm_irq.h" #include "intel_guc.h" -#include "intel_guc_slpc.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" +#include "intel_guc_slpc.h" #include "intel_guc_submission.h" #include "i915_drv.h" #include "i915_irq.h" @@ -361,9 +362,14 @@ int intel_guc_init(struct intel_guc *guc) if (ret) goto err_fw; - ret = intel_guc_ads_create(guc); + ret = intel_guc_capture_init(guc); if (ret) goto err_log; + + ret = intel_guc_ads_create(guc); + if (ret) + goto err_capture; + GEM_BUG_ON(!guc->ads_vma); ret = intel_guc_ct_init(&guc->ct); @@ -402,6 +408,8 @@ int intel_guc_init(struct intel_guc *guc) intel_guc_ct_fini(&guc->ct); err_ads: intel_guc_ads_destroy(guc); +err_capture: + intel_guc_capture_destroy(guc); err_log: intel_guc_log_destroy(&guc->log); err_fw: @@ -429,6 +437,7 @@ void intel_guc_fini(struct intel_guc *guc) intel_guc_ct_fini(&guc->ct); intel_guc_ads_destroy(guc); + intel_guc_capture_destroy(guc); intel_guc_log_destroy(&guc->log); intel_uc_fw_fini(&guc->fw); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 697d9d66acef..4e819853ec2e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -9,18 +9,19 @@ #include #include -#include "intel_uncore.h" +#include "intel_guc_ct.h" #include "intel_guc_fw.h" #include "intel_guc_fwif.h" -#include "intel_guc_ct.h" #include "intel_guc_log.h" #include "intel_guc_reg.h" #include "intel_guc_slpc_types.h" #include "intel_uc_fw.h" +#include "intel_uncore.h" #include "i915_utils.h" #include "i915_vma.h" struct __guc_ads_blob; +struct __guc_state_capture_priv; /** * struct intel_guc - Top level structure of GuC. @@ -37,6 +38,10 @@ struct intel_guc { struct intel_guc_ct ct; /** @slpc: sub-structure containing SLPC related data and objects */ struct intel_guc_slpc slpc; + /** @capture: the error-state-capture module's data and objects */ + struct intel_guc_state_capture { + struct __guc_state_capture_priv *priv; + } capture; /** @sched_engine: Global engine used to submit requests to GuC */ struct i915_sched_engine *sched_engine; @@ -152,6 +157,8 @@ struct intel_guc { u32 ads_regset_size; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_capture_size: size of register lists in the ADS used for error capture */ + u32 ads_capture_size; /** @ads_engine_usage_size: size of engine usage in the ADS */ u32 ads_engine_usage_size; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 668bf4ac9b0c..4597ba0a4177 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -10,6 +10,7 @@ #include "gt/intel_lrc.h" #include "gt/shmem_utils.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" #include "intel_guc_fwif.h" #include "intel_uc.h" #include "i915_drv.h" @@ -72,8 +73,7 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) static u32 guc_ads_capture_size(struct intel_guc *guc) { - /* FIXME: Allocate a proper capture list */ - return PAGE_ALIGN(PAGE_SIZE); + return PAGE_ALIGN(guc->ads_capture_size); } static u32 guc_ads_private_data_size(struct intel_guc *guc) @@ -520,26 +520,6 @@ static void guc_init_golden_context(struct intel_guc *guc) GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size); } -static void guc_capture_list_init(struct intel_guc *guc, struct __guc_ads_blob *blob) -{ - int i, j; - u32 addr_ggtt, offset; - - offset = guc_ads_capture_offset(guc); - addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; - - /* FIXME: Populate a proper capture list */ - - for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { - for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) { - blob->ads.capture_instance[i][j] = addr_ggtt; - blob->ads.capture_class[i][j] = addr_ggtt; - } - - blob->ads.capture_global[i] = addr_ggtt; - } -} - static void __guc_ads_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -573,9 +553,9 @@ static void __guc_ads_init(struct intel_guc *guc) base = intel_guc_ggtt_offset(guc, guc->ads_vma); - /* Capture list for hang debug */ - guc_capture_list_init(guc, blob); - + /* Lists for error capture debug */ + intel_guc_capture_prep_lists(guc, (struct guc_ads *)blob, base, + guc_ads_capture_offset(guc), &blob->system_info); /* ADS */ blob->ads.scheduler_policies = base + ptr_offset(blob, policies); blob->ads.gt_system_info = base + ptr_offset(blob, system_info); @@ -615,6 +595,12 @@ int intel_guc_ads_create(struct intel_guc *guc) return ret; guc->ads_golden_ctxt_size = ret; + /* Likewise the capture lists: */ + ret = intel_guc_capture_prep_lists(guc, NULL, 0, 0, NULL); + if (ret < 0) + return ret; + guc->ads_capture_size = ret; + /* Now the total size can be determined: */ size = guc_ads_blob_size(guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c new file mode 100644 index 000000000000..06873d617b8b --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021-2021 Intel Corporation + */ + +#include + +#include + +#include "gt/intel_engine_regs.h" +#include "gt/intel_gt.h" +#include "guc_capture_fwif.h" +#include "intel_guc_fwif.h" +#include "i915_drv.h" +#include "i915_memcpy.h" + +/* + * Define all device tables of GuC error capture register lists + * NOTE: For engine-registers, GuC only needs the register offsets + * from the engine-mmio-base + */ +/* XE_LPD - Global */ +static struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { + {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"} +}; + +/* XE_LPD - Render / Compute Per-Class */ +static struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { + {EIR, 0, 0, "EIR"} +}; + +/* XE_LPD - Render / Compute Per-Engine-Instance */ +static struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { + {RING_HEAD(0), 0, 0, "RING_HEAD"}, + {RING_TAIL(0), 0, 0, "RING_TAIL"}, +}; + +/* XE_LPD - Media Decode/Encode Per-Class */ +static struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { +}; + +/* XE_LPD - Media Decode/Encode Per-Engine-Instance */ +static struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { + {RING_HEAD(0), 0, 0, "RING_HEAD"}, + {RING_TAIL(0), 0, 0, "RING_TAIL"}, +}; + +/* XE_LPD - Video Enhancement Per-Class */ +static struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { +}; + +/* XE_LPD - Video Enhancement Per-Engine-Instance */ +static struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { + {RING_HEAD(0), 0, 0, "RING_HEAD"}, + {RING_TAIL(0), 0, 0, "RING_TAIL"}, +}; + +#define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) +#define TO_GCAP_DEF_TYPE(x) (GUC_CAPTURE_LIST_TYPE_##x) +#define MAKE_REGLIST(regslist, regsowner, regstype, class) \ + { \ + .list = regslist, \ + .num_regs = ARRAY_SIZE(regslist), \ + .owner = TO_GCAP_DEF_OWNER(regsowner), \ + .type = TO_GCAP_DEF_TYPE(regstype), \ + .engine = class, \ + } + +/* List of lists */ +static struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { + MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_vd_class_regs, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + {} +}; + +static struct __guc_mmio_reg_descr_group * +guc_capture_get_device_reglist(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + + if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || + IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { + /* + * For certain engine classes, there are slice and subslice + * level registers requiring steering. We allocate and populate + * these at init time based on hw config add it as an extension + * list at the end of the pre-populated render list. + */ + return xe_lpd_lists; + } + + return NULL; +} + +static struct __guc_mmio_reg_descr_group * +guc_capture_get_one_list(struct __guc_mmio_reg_descr_group *reglists, u32 owner, u32 type, u32 id) +{ + int i; + + if (!reglists) + return NULL; + + for (i = 0; reglists[i].list; i++) { + if (reglists[i].owner == owner && reglists[i].type == type && + (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) + return ®lists[i]; + } + + return NULL; +} + +static const char * +guc_capture_stringify_owner(u32 owner) +{ + switch (owner) { + case GUC_CAPTURE_LIST_INDEX_PF: + return "PF"; + case GUC_CAPTURE_LIST_INDEX_VF: + return "VF"; + default: + return "unknown"; + } + + return ""; +} + +static const char * +guc_capture_stringify_type(u32 type) +{ + switch (type) { + case GUC_CAPTURE_LIST_TYPE_GLOBAL: + return "Global"; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + return "Class"; + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + return "Instance"; + default: + return "unknown"; + } + + return ""; +} + +static const char * +guc_capture_stringify_engclass(u32 class) +{ + switch (class) { + case GUC_RENDER_CLASS: + return "Render"; + case GUC_VIDEO_CLASS: + return "Video"; + case GUC_VIDEOENHANCE_CLASS: + return "VideoEnhance"; + case GUC_BLITTER_CLASS: + return "Blitter"; + case GUC_RESERVED_CLASS: + return "Reserved"; + default: + return "unknown"; + } + + return ""; +} + +static void +guc_capture_warn_with_list_info(struct drm_i915_private *i915, char *msg, + u32 owner, u32 type, u32 classid) +{ + if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL) + drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers.\n", msg, + guc_capture_stringify_owner(owner), guc_capture_stringify_type(type)); + else + drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers on %s-Engine\n", msg, + guc_capture_stringify_owner(owner), guc_capture_stringify_type(type), + guc_capture_stringify_engclass(classid)); +} + +static int +guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + struct guc_mmio_reg *ptr, u16 num_entries) +{ + u32 j = 0; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct __guc_mmio_reg_descr_group *reglists = guc->capture.priv->reglists; + struct __guc_mmio_reg_descr_group *match; + + if (!reglists) + return -ENODEV; + + match = guc_capture_get_one_list(reglists, owner, type, classid); + if (match) { + for (j = 0; j < num_entries && j < match->num_regs; ++j) { + ptr[j].offset = match->list[j].reg.reg; + ptr[j].value = 0xDEADF00D; + ptr[j].flags = match->list[j].flags; + ptr[j].mask = match->list[j].mask; + } + return 0; + } + + guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type, + classid); + + return -ENODATA; +} + +static int +guc_capture_fill_reglist(struct intel_guc *guc, struct guc_ads *ads, + u32 owner, int type, int classid, u16 numregs, + u8 **p_virt, u32 *p_ggtt, u32 null_ggtt) +{ + struct guc_debug_capture_list *listnode; + u32 *p_capturelist_ggtt; + int size = 0; + + /* + * For enabled capture lists, we not only need to call capture module to help + * populate the list-descriptor into the correct ads capture structures, but + * we also need to increment the virtual pointers and ggtt offsets so that + * caller has the subsequent gfx memory location. + */ + size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + + (numregs * sizeof(struct guc_mmio_reg))); + /* if caller hasn't allocated ADS blob, return size and counts, we're done */ + if (!ads) + return size; + + /* + * If caller allocated ADS blob, populate the capture register descriptors into + * the designated ADS location based on list-owner, list-type and engine-classid + */ + if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL) + p_capturelist_ggtt = &ads->capture_global[owner]; + else if (type == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) + p_capturelist_ggtt = &ads->capture_class[owner][classid]; + else /*GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE*/ + p_capturelist_ggtt = &ads->capture_instance[owner][classid]; + + if (!numregs) { + *p_capturelist_ggtt = null_ggtt; + } else { + /* get ptr and populate header info: */ + *p_capturelist_ggtt = *p_ggtt; + listnode = (struct guc_debug_capture_list *)*p_virt; + *p_ggtt += sizeof(struct guc_debug_capture_list); + *p_virt += sizeof(struct guc_debug_capture_list); + listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, numregs); + + /* get ptr and populate register descriptor list: */ + guc_capture_list_init(guc, owner, type, classid, + (struct guc_mmio_reg *)*p_virt, + numregs); + + /* increment ptrs for that header: */ + *p_ggtt += size - sizeof(struct guc_debug_capture_list); + *p_virt += size - sizeof(struct guc_debug_capture_list); + } + + return size; +} + +static int +guc_capture_list_count(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + u16 *num_entries) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct __guc_mmio_reg_descr_group *reglists = guc->capture.priv->reglists; + struct __guc_mmio_reg_descr_group *match; + + if (!reglists) + return -ENODEV; + + match = guc_capture_get_one_list(reglists, owner, type, classid); + if (!match) { + guc_capture_warn_with_list_info(i915, "Missing register list size", + owner, type, classid); + return -ENODATA; + } + + *num_entries = match->num_regs; + return 0; +} + +static void +guc_capture_fill_engine_enable_masks(struct intel_gt *gt, + struct guc_gt_system_info *info) +{ + info->engine_enabled_masks[GUC_RENDER_CLASS] = 1; + info->engine_enabled_masks[GUC_BLITTER_CLASS] = 1; + info->engine_enabled_masks[GUC_VIDEO_CLASS] = VDBOX_MASK(gt); + info->engine_enabled_masks[GUC_VIDEOENHANCE_CLASS] = VEBOX_MASK(gt); +} + +int intel_guc_capture_prep_lists(struct intel_guc *guc, struct guc_ads *blob, u32 blob_ggtt, + u32 capture_offset, struct guc_gt_system_info *sysinfo) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct guc_gt_system_info *info, local_info; + struct guc_debug_capture_list *listnode; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct __guc_state_capture_priv *gc = guc->capture.priv; + int i, j, size; + u32 ggtt, null_ggtt, alloc_size = 0; + u16 tmpnumreg = 0; + u8 *ptr = NULL; + + GEM_BUG_ON(!gc); + + if (blob) { + ptr = ((u8 *)blob) + capture_offset; + ggtt = blob_ggtt + capture_offset; + GEM_BUG_ON(!sysinfo); + info = sysinfo; + } else { + memset(&local_info, 0, sizeof(local_info)); + info = &local_info; + guc_capture_fill_engine_enable_masks(gt, info); + } + + /* first, set aside the first page for a capture_list with zero descriptors */ + alloc_size = PAGE_SIZE; + if (blob) { + listnode = (struct guc_debug_capture_list *)ptr; + listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, 0); + null_ggtt = ggtt; + ggtt += PAGE_SIZE; + ptr += PAGE_SIZE; + } + +#define COUNT_REGS guc_capture_list_count +#define FILL_REGS guc_capture_fill_reglist +#define TYPE_GLOBAL GUC_CAPTURE_LIST_TYPE_GLOBAL +#define TYPE_CLASS GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS +#define TYPE_INSTANCE GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE +#define OWNER2STR guc_capture_stringify_owner +#define ENGCLS2STR guc_capture_stringify_engclass +#define TYPE2STR guc_capture_stringify_type + + for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { + for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) { + if (!info->engine_enabled_masks[j]) { + if (gc->num_class_regs[i][j]) + drm_warn(&i915->drm, "GuC-Cap %s's %s class-" + "list enable mismatch was=%d now off\n", + OWNER2STR(i), ENGCLS2STR(j), + gc->num_class_regs[i][j]); + if (gc->num_instance_regs[i][j]) + drm_warn(&i915->drm, "GuC-Cap %s's %s inst-" + "list enable mismatch was=%d now off!\n", + OWNER2STR(i), ENGCLS2STR(j), + gc->num_instance_regs[i][j]); + gc->num_class_regs[i][j] = 0; + gc->num_instance_regs[i][j] = 0; + if (blob) { + blob->capture_class[i][j] = null_ggtt; + blob->capture_instance[i][j] = null_ggtt; + } + } else { + if (!COUNT_REGS(guc, i, TYPE_CLASS, j, &tmpnumreg)) { + if (blob && tmpnumreg > gc->num_class_regs[i][j]) { + drm_warn(&i915->drm, "GuC-Cap %s's %s-%s-list " + "count overflow cap from %d to %d", + OWNER2STR(i), ENGCLS2STR(j), + TYPE2STR(TYPE_CLASS), + gc->num_class_regs[i][j], tmpnumreg); + tmpnumreg = gc->num_class_regs[i][j]; + } + size = FILL_REGS(guc, blob, i, TYPE_CLASS, j, + tmpnumreg, &ptr, &ggtt, null_ggtt); + alloc_size += size; + gc->num_class_regs[i][j] = tmpnumreg; + } else { + gc->num_class_regs[i][j] = 0; + if (blob) + blob->capture_class[i][j] = null_ggtt; + } + if (!COUNT_REGS(guc, i, TYPE_INSTANCE, j, &tmpnumreg)) { + if (blob && tmpnumreg > gc->num_instance_regs[i][j]) { + drm_warn(&i915->drm, "GuC-Cap %s's %s-%s-list " + "count overflow cap from %d to %d", + OWNER2STR(i), ENGCLS2STR(j), + TYPE2STR(TYPE_INSTANCE), + gc->num_instance_regs[i][j], tmpnumreg); + tmpnumreg = gc->num_instance_regs[i][j]; + } + size = FILL_REGS(guc, blob, i, TYPE_INSTANCE, j, + tmpnumreg, &ptr, &ggtt, null_ggtt); + alloc_size += size; + gc->num_instance_regs[i][j] = tmpnumreg; + } else { + gc->num_instance_regs[i][j] = 0; + if (blob) + blob->capture_instance[i][j] = null_ggtt; + } + } + } + if (!COUNT_REGS(guc, i, TYPE_GLOBAL, 0, &tmpnumreg)) { + if (blob && tmpnumreg > gc->num_global_regs[i]) { + drm_warn(&i915->drm, "GuC-Cap %s's %s-list count increased from %d to %d", + OWNER2STR(i), TYPE2STR(TYPE_GLOBAL), + gc->num_global_regs[i], tmpnumreg); + tmpnumreg = gc->num_global_regs[i]; + } + size = FILL_REGS(guc, blob, i, TYPE_GLOBAL, 0, tmpnumreg, + &ptr, &ggtt, null_ggtt); + alloc_size += size; + gc->num_global_regs[i] = tmpnumreg; + } else { + gc->num_global_regs[i] = 0; + if (blob) + blob->capture_global[i] = null_ggtt; + } + } + +#undef COUNT_REGS +#undef FILL_REGS +#undef TYPE_GLOBAL +#undef TYPE_CLASS +#undef TYPE_INSTANCE +#undef OWNER2STR +#undef ENGCLS2STR +#undef TYPE2STR + + if (guc->ads_capture_size && guc->ads_capture_size != PAGE_ALIGN(alloc_size)) + drm_warn(&i915->drm, "GuC->ADS->Capture alloc size changed from %d to %d\n", + guc->ads_capture_size, PAGE_ALIGN(alloc_size)); + + return PAGE_ALIGN(alloc_size); +} + +void intel_guc_capture_destroy(struct intel_guc *guc) +{ + kfree(guc->capture.priv); + guc->capture.priv = NULL; +} + +int intel_guc_capture_init(struct intel_guc *guc) +{ + guc->capture.priv = kzalloc(sizeof(*guc->capture.priv), GFP_KERNEL); + if (!guc->capture.priv) + return -ENOMEM; + guc->capture.priv->reglists = guc_capture_get_device_reglist(guc); + + return 0; +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h new file mode 100644 index 000000000000..6b5594ca529d --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021-2021 Intel Corporation + */ + +#ifndef _INTEL_GUC_CAPTURE_H +#define _INTEL_GUC_CAPTURE_H + +#include + +struct intel_guc; +struct guc_ads; +struct guc_gt_system_info; + +int intel_guc_capture_prep_lists(struct intel_guc *guc, struct guc_ads *blob, u32 blob_ggtt, + u32 capture_offset, struct guc_gt_system_info *sysinfo); +void intel_guc_capture_destroy(struct intel_guc *guc); +int intel_guc_capture_init(struct intel_guc *guc); + +#endif /* _INTEL_GUC_CAPTURE_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 6a4612a852e2..92bfe25a5e85 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -297,6 +297,23 @@ enum { GUC_CAPTURE_LIST_INDEX_MAX = 2, }; +/*Register-types of GuC capture register lists */ +enum guc_capture_type { + GUC_CAPTURE_LIST_TYPE_GLOBAL = 0, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + GUC_CAPTURE_LIST_TYPE_MAX, +}; + +struct guc_debug_capture_list_header { + u32 info; + #define GUC_CAPTURELISTHDR_NUMDESCR GENMASK(15, 0) +} __packed; + +struct guc_debug_capture_list { + struct guc_debug_capture_list_header header; +} __packed; + /* GuC Additional Data Struct */ struct guc_ads { struct guc_mmio_reg_set reg_state_list[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS]; From patchwork Wed Jan 26 10:48:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724934 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 867A7C63682 for ; Wed, 26 Jan 2022 10:46:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 45DB210E881; Wed, 26 Jan 2022 10:46:24 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id EDBB910E722 for ; Wed, 26 Jan 2022 10:46:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0saAOuIogbcjAFAzGkYRyYbA5V3EH0H3jbhNbjsnue8=; b=ZxdEPPgbn+n40NhIlP8BG9uez3qqK92nhQwOufQRdApIUI8cI4LUzpy1 yywieez6CRV6PyLhPa2CZ/AYQ97BegYjehtyT2l0fjQDMYp4iar2zLm98 /U2dS7z+sNn1GgcxWSeTFv24fSnFcDQyGRLOX5BZWEo1f5uNqScolK2li rkcy+cGlRv2mUQePRZWc+j2TCbG4ytBoo62frAmFhnIDb0LUsEQY+upDA +zbT5cCTy8sRsLQfD+XhVYkh9LssT0gLt0iET9L1NAUHNysv5l2QZevr2 9vMeHtKfR9p6zWWs1F4sxgkBxyZorsafoRyhmPO+MPI1OdUEXFQqfc42+ w==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301874" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301874" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445965" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:14 -0800 Message-Id: <20220126104822.3653079-3-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 02/10] drm/i915/guc: Add XE_LP registers for GuC error state capture. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add device specific tables and register lists to cover different engines class types for GuC error state capture for XE_LP products. Also, add runtime allocation and freeing of extended register lists for registers that need steering identifiers that depend on the detected HW config. Signed-off-by: Alan Previn --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 2 + .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 207 +++++++++++++++--- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 4 +- 3 files changed, 180 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 15b8c02b8a76..a2f97d04ff18 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -24,6 +24,8 @@ struct __guc_mmio_reg_descr_group { u32 owner; /* see enum guc_capture_owner */ u32 type; /* see enum guc_capture_type */ u32 engine; /* as per MAX_ENGINE_CLASS */ + int num_ext; + struct __guc_mmio_reg_descr *ext; }; struct __guc_state_capture_priv { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 06873d617b8b..b6882074fc8d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -19,40 +19,101 @@ * NOTE: For engine-registers, GuC only needs the register offsets * from the engine-mmio-base */ +#define COMMON_GEN12BASE_GLOBAL() \ + {GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0"}, \ + {GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1"}, \ + {FORCEWAKE_MT, 0, 0, "FORCEWAKE_MT"}, \ + {GEN12_AUX_ERR_DBG, 0, 0, "GEN12_AUX_ERR_DBG"}, \ + {GEN12_GAM_DONE, 0, 0, "GEN12_GAM_DONE"}, \ + {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"} + +#define COMMON_GEN12BASE_ENGINE_INSTANCE() \ + {RING_PSMI_CTL(0), 0, 0, "RING_PSMI_CTL"}, \ + {RING_ESR(0), 0, 0, "RING_ESR"}, \ + {RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LOW32"}, \ + {RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UP32"}, \ + {RING_IPEIR(0), 0, 0, "RING_IPEIR"}, \ + {RING_IPEHR(0), 0, 0, "RING_IPEHR"}, \ + {RING_INSTPS(0), 0, 0, "RING_INSTPS"}, \ + {RING_BBADDR(0), 0, 0, "RING_BBADDR_LOW32"}, \ + {RING_BBADDR_UDW(0), 0, 0, "RING_BBADDR_UP32"}, \ + {RING_BBSTATE(0), 0, 0, "RING_BBSTATE"}, \ + {CCID(0), 0, 0, "CCID"}, \ + {RING_ACTHD(0), 0, 0, "RING_ACTHD_LOW32"}, \ + {RING_ACTHD_UDW(0), 0, 0, "RING_ACTHD_UP32"}, \ + {RING_INSTPM(0), 0, 0, "RING_INSTPM"}, \ + {RING_NOPID(0), 0, 0, "RING_NOPID"}, \ + {RING_START(0), 0, 0, "RING_START"}, \ + {RING_HEAD(0), 0, 0, "RING_HEAD"}, \ + {RING_TAIL(0), 0, 0, "RING_TAIL"}, \ + {RING_CTL(0), 0, 0, "RING_CTL"}, \ + {RING_MI_MODE(0), 0, 0, "RING_MI_MODE"}, \ + {RING_CONTEXT_CONTROL(0), 0, 0, "RING_CONTEXT_CONTROL"}, \ + {RING_INSTDONE(0), 0, 0, "RING_INSTDONE"}, \ + {RING_HWS_PGA(0), 0, 0, "RING_HWS_PGA"}, \ + {RING_MODE_GEN7(0), 0, 0, "RING_MODE_GEN7"}, \ + {GEN8_RING_PDP_LDW(0, 0), 0, 0, "GEN8_RING_PDP0_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 0), 0, 0, "GEN8_RING_PDP0_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 1), 0, 0, "GEN8_RING_PDP1_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 1), 0, 0, "GEN8_RING_PDP1_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 2), 0, 0, "GEN8_RING_PDP2_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 2), 0, 0, "GEN8_RING_PDP2_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 3), 0, 0, "GEN8_RING_PDP3_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 3), 0, 0, "GEN8_RING_PDP3_UDW"} + +#define COMMON_GEN12BASE_HAS_EU() \ + {EIR, 0, 0, "EIR"} + +#define COMMON_GEN12BASE_RENDER() \ + {GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE"}, \ + {GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA"}, \ + {GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2"} + +#define COMMON_GEN12BASE_VEC() \ + {GEN12_SFC_DONE(0), 0, 0, "GEN12_SFC_DONE0"}, \ + {GEN12_SFC_DONE(1), 0, 0, "GEN12_SFC_DONE1"}, \ + {GEN12_SFC_DONE(2), 0, 0, "GEN12_SFC_DONE2"}, \ + {GEN12_SFC_DONE(3), 0, 0, "GEN12_SFC_DONE3"} + /* XE_LPD - Global */ static struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { - {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"} + COMMON_GEN12BASE_GLOBAL(), }; /* XE_LPD - Render / Compute Per-Class */ static struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { - {EIR, 0, 0, "EIR"} + COMMON_GEN12BASE_HAS_EU(), + COMMON_GEN12BASE_RENDER(), }; /* XE_LPD - Render / Compute Per-Engine-Instance */ static struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { - {RING_HEAD(0), 0, 0, "RING_HEAD"}, - {RING_TAIL(0), 0, 0, "RING_TAIL"}, -}; - -/* XE_LPD - Media Decode/Encode Per-Class */ -static struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { + COMMON_GEN12BASE_ENGINE_INSTANCE(), }; /* XE_LPD - Media Decode/Encode Per-Engine-Instance */ static struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { - {RING_HEAD(0), 0, 0, "RING_HEAD"}, - {RING_TAIL(0), 0, 0, "RING_TAIL"}, + COMMON_GEN12BASE_ENGINE_INSTANCE(), }; /* XE_LPD - Video Enhancement Per-Class */ static struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { + COMMON_GEN12BASE_VEC(), }; /* XE_LPD - Video Enhancement Per-Engine-Instance */ static struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { - {RING_HEAD(0), 0, 0, "RING_HEAD"}, - {RING_TAIL(0), 0, 0, "RING_TAIL"}, + COMMON_GEN12BASE_ENGINE_INSTANCE(), +}; + +/* XE_LPD - Blitter Per-Engine-Instance */ +static struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = { + COMMON_GEN12BASE_ENGINE_INSTANCE(), +}; + +/* XE_LPD - Blitter Per-Class */ +/* XE_LPD - Media Decode/Encode Per-Class */ +static struct __guc_mmio_reg_descr empty_regs_list[] = { }; #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) @@ -64,6 +125,8 @@ static struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { .owner = TO_GCAP_DEF_OWNER(regsowner), \ .type = TO_GCAP_DEF_TYPE(regstype), \ .engine = class, \ + .num_ext = 0, \ + .ext = NULL, \ } /* List of lists */ @@ -71,13 +134,96 @@ static struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), - MAKE_REGLIST(xe_lpd_vd_class_regs, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), + MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), {} }; +static struct __guc_mmio_reg_descr_group * +guc_capture_get_one_list(struct __guc_mmio_reg_descr_group *reglists, u32 owner, u32 type, u32 id) +{ + int i; + + if (!reglists) + return NULL; + + for (i = 0; reglists[i].list; i++) { + if (reglists[i].owner == owner && reglists[i].type == type && + (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) + return ®lists[i]; + } + + return NULL; +} + +static void guc_capture_clear_ext_regs(struct __guc_mmio_reg_descr_group *lists) +{ + while (lists->list) { + kfree(lists->ext); + lists->ext = NULL; + ++lists; + } +} + +struct __ext_steer_reg { + const char *name; + i915_reg_t reg; +}; + +static struct __ext_steer_reg xelpd_extregs[] = { + {"GEN7_SAMPLER_INSTDONE", GEN7_SAMPLER_INSTDONE}, + {"GEN7_ROW_INSTDONE", GEN7_ROW_INSTDONE} +}; + +static void +guc_capture_alloc_steered_list_xelpd(struct intel_guc *guc, + struct __guc_mmio_reg_descr_group *lists) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct sseu_dev_info *sseu; + int slice, subslice, i, num_tot_regs = 0; + struct __guc_mmio_reg_descr_group *list; + struct __guc_mmio_reg_descr *extarray; + int num_steer_regs = ARRAY_SIZE(xelpd_extregs); + + /* In XE_LP we only care about render-class steering registers during error-capture */ + list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); + if (!list) + return; + + if (list->ext) + return; /* already populated */ + + sseu = >->info.sseu; + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { + num_tot_regs += num_steer_regs; + } + if (!num_tot_regs) + return; + + list->ext = kcalloc(num_tot_regs, sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL); + if (!list->ext) + return; + + extarray = list->ext; + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { + for (i = 0; i < num_steer_regs; i++) { + extarray->reg = xelpd_extregs[i].reg; + extarray->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice); + extarray->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice); + extarray->regname = xelpd_extregs[i].name; + ++extarray; + } + } + list->num_ext = num_tot_regs; +} + static struct __guc_mmio_reg_descr_group * guc_capture_get_device_reglist(struct intel_guc *guc) { @@ -91,29 +237,13 @@ guc_capture_get_device_reglist(struct intel_guc *guc) * these at init time based on hw config add it as an extension * list at the end of the pre-populated render list. */ + guc_capture_alloc_steered_list_xelpd(guc, xe_lpd_lists); return xe_lpd_lists; } return NULL; } -static struct __guc_mmio_reg_descr_group * -guc_capture_get_one_list(struct __guc_mmio_reg_descr_group *reglists, u32 owner, u32 type, u32 id) -{ - int i; - - if (!reglists) - return NULL; - - for (i = 0; reglists[i].list; i++) { - if (reglists[i].owner == owner && reglists[i].type == type && - (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) - return ®lists[i]; - } - - return NULL; -} - static const char * guc_capture_stringify_owner(u32 owner) { @@ -184,7 +314,7 @@ static int guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, struct guc_mmio_reg *ptr, u16 num_entries) { - u32 j = 0; + u32 j = 0, k = 0; struct drm_i915_private *i915 = guc_to_gt(guc)->i915; struct __guc_mmio_reg_descr_group *reglists = guc->capture.priv->reglists; struct __guc_mmio_reg_descr_group *match; @@ -200,6 +330,18 @@ guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, ptr[j].flags = match->list[j].flags; ptr[j].mask = match->list[j].mask; } + if (match->ext) { + for (j = match->num_regs, k = 0; j < num_entries && + j < (match->num_regs + match->num_ext); ++j, ++k) { + ptr[j].offset = match->ext[k].reg.reg; + ptr[j].value = 0xDEADF00D; + ptr[j].flags = match->ext[k].flags; + ptr[j].mask = match->ext[k].mask; + } + } + if (j < num_entries) + drm_dbg(&i915->drm, "GuC-capture: Init reglist short %d out %d.\n", + (int)j, (int)num_entries); return 0; } @@ -282,7 +424,7 @@ guc_capture_list_count(struct intel_guc *guc, u32 owner, u32 type, u32 classid, return -ENODATA; } - *num_entries = match->num_regs; + *num_entries = match->num_regs + match->num_ext; return 0; } @@ -435,6 +577,7 @@ int intel_guc_capture_prep_lists(struct intel_guc *guc, struct guc_ads *blob, u3 void intel_guc_capture_destroy(struct intel_guc *guc) { + guc_capture_clear_ext_regs(guc->capture.priv->reglists); kfree(guc->capture.priv); guc->capture.priv = NULL; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 92bfe25a5e85..50fcd987f2a2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -271,10 +271,12 @@ struct guc_mmio_reg { u32 offset; u32 value; u32 flags; - u32 mask; #define GUC_REGSET_MASKED BIT(0) #define GUC_REGSET_MASKED_WITH_VALUE BIT(2) #define GUC_REGSET_RESTORE_ONLY BIT(3) +#define GUC_REGSET_STEERING_GROUP GENMASK(15, 12) +#define GUC_REGSET_STEERING_INSTANCE GENMASK(23, 20) + u32 mask; } __packed; /* GuC register sets */ From patchwork Wed Jan 26 10:48:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724932 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1D06CC28CF5 for ; Wed, 26 Jan 2022 10:46:29 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2139110E863; Wed, 26 Jan 2022 10:46:24 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2FE9910E794 for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eicmfpyCiIqIPAf2EL+ZbNd7M5FRgeHz6LGhGBzqhN4=; b=MHWcY5E3+a5cKT06Niadq8WITTwq8o2QLZm9Gw99M8JkS3PuASqPaS+4 9ppuH74ZTH66N1OFdqPHWf+1XipHRPdK66yng3XzRLZvNSeCwkVbA8VlC WVM7yNRPlKC+6FakWW9lW606a+yr0nOiRczHutPi7+0gaERAeFTwtwMBA xEpLwSQufxS07NV9R5tZ6GKERqnlkquBP7eRGq7/tNARKZDYl9LLTj/M8 9ofBOz7BsPBI/Hts59I9hWg1zjZaf+5NOYDv31lsKqhDqSHcT351PnZV9 FsSKe0N4fHS78T/4s4u9FX1e6GuuClzwB2r6eDo1q90OuzJw9Au0Qba4K Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301875" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301875" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445969" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:15 -0800 Message-Id: <20220126104822.3653079-4-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 03/10] drm/i915/guc: Add DG2 registers for GuC error state capture. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add additional DG2 registers for GuC error state capture. Signed-off-by: Alan Previn --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 64 ++++++++++++++----- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index b6882074fc8d..19719daffed4 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -179,19 +179,23 @@ static struct __ext_steer_reg xelpd_extregs[] = { {"GEN7_ROW_INSTDONE", GEN7_ROW_INSTDONE} }; +static struct __ext_steer_reg xehpg_extregs[] = { + {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG} +}; + static void -guc_capture_alloc_steered_list_xelpd(struct intel_guc *guc, - struct __guc_mmio_reg_descr_group *lists) +guc_capture_alloc_steered_list_xe_lpd_hpg(struct intel_guc *guc, + struct __guc_mmio_reg_descr_group *lists, + u32 ipver) { struct intel_gt *gt = guc_to_gt(guc); struct drm_i915_private *i915 = guc_to_gt(guc)->i915; struct sseu_dev_info *sseu; - int slice, subslice, i, num_tot_regs = 0; + int slice, subslice, i, iter, num_steer_regs, num_tot_regs = 0; struct __guc_mmio_reg_descr_group *list; struct __guc_mmio_reg_descr *extarray; - int num_steer_regs = ARRAY_SIZE(xelpd_extregs); - /* In XE_LP we only care about render-class steering registers during error-capture */ + /* In XE_LP / HPG we only have render-class steering registers during error-capture */ list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); if (!list) @@ -200,10 +204,21 @@ guc_capture_alloc_steered_list_xelpd(struct intel_guc *guc, if (list->ext) return; /* already populated */ + num_steer_regs = ARRAY_SIZE(xelpd_extregs); + if (ipver >= IP_VER(12, 55)) + num_steer_regs += ARRAY_SIZE(xehpg_extregs); + sseu = >->info.sseu; - for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { - num_tot_regs += num_steer_regs; + if (ipver >= IP_VER(12, 50)) { + for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + num_tot_regs += num_steer_regs; + } + } else { + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { + num_tot_regs += num_steer_regs; + } } + if (!num_tot_regs) return; @@ -212,15 +227,31 @@ guc_capture_alloc_steered_list_xelpd(struct intel_guc *guc, return; extarray = list->ext; - for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { - for (i = 0; i < num_steer_regs; i++) { - extarray->reg = xelpd_extregs[i].reg; - extarray->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice); - extarray->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice); - extarray->regname = xelpd_extregs[i].name; - ++extarray; + +#define POPULATE_NEXT_EXTREG(ext, list, idx, slicenum, subslicenum) \ + { \ + (ext)->reg = list[idx].reg; \ + (ext)->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slicenum); \ + (ext)->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslicenum); \ + (ext)->regname = xelpd_extregs[i].name; \ + ++(ext); \ + } + if (ipver >= IP_VER(12, 50)) { + for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + for (i = 0; i < ARRAY_SIZE(xelpd_extregs); i++) + POPULATE_NEXT_EXTREG(extarray, xelpd_extregs, i, slice, subslice) + for (i = 0; i < ARRAY_SIZE(xehpg_extregs) && ipver >= IP_VER(12, 55); + i++) + POPULATE_NEXT_EXTREG(extarray, xehpg_extregs, i, slice, subslice) + } + } else { + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { + for (i = 0; i < num_steer_regs; i++) + POPULATE_NEXT_EXTREG(extarray, xelpd_extregs, i, slice, subslice) } } +#undef POPULATE_NEXT_EXTREG + list->num_ext = num_tot_regs; } @@ -237,7 +268,10 @@ guc_capture_get_device_reglist(struct intel_guc *guc) * these at init time based on hw config add it as an extension * list at the end of the pre-populated render list. */ - guc_capture_alloc_steered_list_xelpd(guc, xe_lpd_lists); + guc_capture_alloc_steered_list_xe_lpd_hpg(guc, xe_lpd_lists, IP_VER(12, 0)); + return xe_lpd_lists; + } else if (IS_DG2(i915)) { + guc_capture_alloc_steered_list_xe_lpd_hpg(guc, xe_lpd_lists, IP_VER(12, 55)); return xe_lpd_lists; } From patchwork Wed Jan 26 10:48:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724941 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EA864C63682 for ; Wed, 26 Jan 2022 10:46:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DA77310E8AB; Wed, 26 Jan 2022 10:46:26 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5F43210E722 for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7VjKlC9GTz2hfByUux3TKscpOT01dI2mkjsSuQTLMFQ=; b=VEVL4bNWH3ghPlONMqI8bsG5SBb2a6htdSdxHhjdcJHXkPm7B/AGzN/W //Y7tegLi7PeRNnXkZ1nwXY8p9/l8gCYtvFDMLyA5iYQX8T+p0ItehExg lnSwiQGFyBUwM+Y+a+gXbLMBqFh3LjAcEXgSFwiFBV8W7FDDBhTEkcyJH cF/G10w8dnBSqXhY1YY8G+0hGWTUJrO8FTog0bFkmj9XByO/zl3Y1CodM HsiV8u2c5jvqWkl+1ADCnJhJ+NqhNDtLJQ0a7rDTCmoWWHaPhn3hVEyBn Ej7VCTwZQXGoWtWo6N5v1y+zNgxXCBUGROJ6xm617RjEq5ax0F889xxXp w==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301877" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301877" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445972" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:16 -0800 Message-Id: <20220126104822.3653079-5-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 04/10] drm/i915/guc: Add Gen9 registers for GuC error state capture. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Abstract out a Gen9 register list as the default for all other platforms we don't yet formally support GuC submission on. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 74 +++++++++++++++---- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 19719daffed4..70d2ee841289 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -19,15 +19,24 @@ * NOTE: For engine-registers, GuC only needs the register offsets * from the engine-mmio-base */ +#define COMMON_BASE_GLOBAL() \ + {FORCEWAKE_MT, 0, 0, "FORCEWAKE_MT"} + +#define COMMON_GEN9BASE_GLOBAL() \ + {GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0"}, \ + {GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1"}, \ + {ERROR_GEN6, 0, 0, "ERROR_GEN6"}, \ + {DONE_REG, 0, 0, "DONE_REG"}, \ + {HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN"} + #define COMMON_GEN12BASE_GLOBAL() \ {GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0"}, \ {GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1"}, \ - {FORCEWAKE_MT, 0, 0, "FORCEWAKE_MT"}, \ {GEN12_AUX_ERR_DBG, 0, 0, "GEN12_AUX_ERR_DBG"}, \ {GEN12_GAM_DONE, 0, 0, "GEN12_GAM_DONE"}, \ {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"} -#define COMMON_GEN12BASE_ENGINE_INSTANCE() \ +#define COMMON_BASE_ENGINE_INSTANCE() \ {RING_PSMI_CTL(0), 0, 0, "RING_PSMI_CTL"}, \ {RING_ESR(0), 0, 0, "RING_ESR"}, \ {RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LOW32"}, \ @@ -61,11 +70,13 @@ {GEN8_RING_PDP_LDW(0, 3), 0, 0, "GEN8_RING_PDP3_LDW"}, \ {GEN8_RING_PDP_UDW(0, 3), 0, 0, "GEN8_RING_PDP3_UDW"} -#define COMMON_GEN12BASE_HAS_EU() \ +#define COMMON_BASE_HAS_EU() \ {EIR, 0, 0, "EIR"} +#define COMMON_BASE_RENDER() \ + {GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE"} + #define COMMON_GEN12BASE_RENDER() \ - {GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE"}, \ {GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA"}, \ {GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2"} @@ -77,23 +88,26 @@ /* XE_LPD - Global */ static struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { + COMMON_BASE_GLOBAL(), + COMMON_GEN9BASE_GLOBAL(), COMMON_GEN12BASE_GLOBAL(), }; /* XE_LPD - Render / Compute Per-Class */ static struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { - COMMON_GEN12BASE_HAS_EU(), + COMMON_BASE_HAS_EU(), + COMMON_BASE_RENDER(), COMMON_GEN12BASE_RENDER(), }; -/* XE_LPD - Render / Compute Per-Engine-Instance */ +/* GEN9/XE_LPD - Render / Compute Per-Engine-Instance */ static struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), }; -/* XE_LPD - Media Decode/Encode Per-Engine-Instance */ +/* GEN9/XE_LPD - Media Decode/Encode Per-Engine-Instance */ static struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), }; /* XE_LPD - Video Enhancement Per-Class */ @@ -101,18 +115,33 @@ static struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { COMMON_GEN12BASE_VEC(), }; -/* XE_LPD - Video Enhancement Per-Engine-Instance */ +/* GEN9/XE_LPD - Video Enhancement Per-Engine-Instance */ static struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), }; -/* XE_LPD - Blitter Per-Engine-Instance */ +/* GEN9/XE_LPD - Blitter Per-Engine-Instance */ static struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE(), + COMMON_BASE_ENGINE_INSTANCE(), +}; + +/* GEN9 - Global */ +static struct __guc_mmio_reg_descr default_global_regs[] = { + COMMON_BASE_GLOBAL(), + COMMON_GEN9BASE_GLOBAL(), }; -/* XE_LPD - Blitter Per-Class */ -/* XE_LPD - Media Decode/Encode Per-Class */ +static struct __guc_mmio_reg_descr default_rc_class_regs[] = { + COMMON_BASE_HAS_EU(), + COMMON_BASE_RENDER(), +}; + +/* + * Empty lists: + * GEN9/XE_LPD - Blitter-Class + * GEN9/XE_LPD - Media Class + * GEN9 - VEC Class + */ static struct __guc_mmio_reg_descr empty_regs_list[] = { }; @@ -130,6 +159,18 @@ static struct __guc_mmio_reg_descr empty_regs_list[] = { } /* List of lists */ +static struct __guc_mmio_reg_descr_group default_lists[] = { + MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), + MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), + {} +}; static struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), @@ -275,7 +316,8 @@ guc_capture_get_device_reglist(struct intel_guc *guc) return xe_lpd_lists; } - return NULL; + /* if GuC submission is enabled on a non-POR platform, just use a common baseline */ + return default_lists; } static const char * From patchwork Wed Jan 26 10:48:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724937 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 17746C2BA4C for ; Wed, 26 Jan 2022 10:46:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3A17110E808; Wed, 26 Jan 2022 10:46:26 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6DAB410E808 for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=L0KyIszebexoO5irrh3Mjt+/Tqs03dsOzt13PTJDg9c=; b=CUbqscMo7vMuvj+eYkbu+JzW6BHSQWkvSgQmnpvrGtmnrgE2Z4FbcjyV ugOlYv4bikYLfmBF2lIgv1TNCViiYEren7+d/Orv6grdkA88kLn019Xpc +ea12jN7JgvSW8fji2cOr7swOpfq1A/vSWy62BgaW0MjGsGVJw9gHS5sq 2OAs976jMPH+uT6uAWJG5fy9AGjU/JrRQ25D4ud1LwxVXjg2Ot6ciVWUy EFbdQQhWYtg8Rnn2j7BnErz87jXI5fEzsCd//yEzWJop28S05WTviEMXO AVzmL5siuRunHhW6TApD/Yt0LzxGW+6Gkak89Uk9Cjg39HXaOY1V5JLuJ A==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301878" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301878" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445975" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:17 -0800 Message-Id: <20220126104822.3653079-6-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 05/10] drm/i915/guc: Add GuC's error state capture output structures. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add GuC's error capture output structures and definitions as how they would appear in GuC log buffer's error capture subregion after an error state capture G2H event notification. Signed-off-by: Alan Previn Reviewed-by: Matthew Brost --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index a2f97d04ff18..495cdb0228c6 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -28,6 +28,41 @@ struct __guc_mmio_reg_descr_group { struct __guc_mmio_reg_descr *ext; }; +struct guc_state_capture_header_t { + u32 reserved1; + u32 info; + #define CAP_HDR_CAPTURE_TYPE GENMASK(3, 0) /* see enum guc_capture_type */ + #define CAP_HDR_ENGINE_CLASS GENMASK(7, 4) /* see GUC_MAX_ENGINE_CLASSES */ + #define CAP_HDR_ENGINE_INSTANCE GENMASK(11, 8) + u32 lrca; /* if type-instance, LRCA (address) that hung, else set to ~0 */ + u32 guc_id; /* if type-instance, context index of hung context, else set to ~0 */ + u32 num_mmios; + #define CAP_HDR_NUM_MMIOS GENMASK(9, 0) +} __packed; + +struct guc_state_capture_t { + struct guc_state_capture_header_t header; + struct guc_mmio_reg mmio_entries[0]; +} __packed; + +enum guc_capture_group_types { + GUC_STATE_CAPTURE_GROUP_TYPE_FULL, + GUC_STATE_CAPTURE_GROUP_TYPE_PARTIAL, + GUC_STATE_CAPTURE_GROUP_TYPE_MAX, +}; + +struct guc_state_capture_group_header_t { + u32 reserved1; + u32 info; + #define CAP_GRP_HDR_NUM_CAPTURES GENMASK(7, 0) + #define CAP_GRP_HDR_CAPTURE_TYPE GENMASK(15, 8) /* guc_capture_group_types */ +} __packed; + +struct guc_state_capture_group_t { + struct guc_state_capture_group_header_t grp_header; + struct guc_state_capture_t capture_entries[0]; +} __packed; + struct __guc_state_capture_priv { struct __guc_mmio_reg_descr_group *reglists; u16 num_instance_regs[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES]; From patchwork Wed Jan 26 10:48:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724940 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DF50FC63684 for ; Wed, 26 Jan 2022 10:46:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E91CB10E8C2; Wed, 26 Jan 2022 10:46:26 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id 888CC10E794 for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=G9g4lFYN3Z7uFUxPxe4jra1nCZNpg9JbHzxRnX0s6sM=; b=ESfr05kmXA3ItEyLIF6TNwXiMBDzFff3KWrzZYApq3x9dcR2J5Aayn2N HRjGGzBaCvdPo5LewcKWxMZL/O2YsEdNkuXs5VZkgpzWgi2SNaju4/zpV l9cvgWWZ89240YtUiajNr0Xup6gMx/W2s7o6ymhqAFdkaa4TsgucGYhCI 2KfgdDqLBcg1kyd+7IAGM1IwlcZM1ca03vPtTBJ7dVlqafRlDYGlU7g2G eEa4ekU/cwAyXEdNt4exbBjhWUGPQEDD8bZG/yz/eWpEd6HQxDDfWa1PD rN3aJymS7i/kIqnxPPbERIpglqHSeIvAuabnixzM9A6k7OocvLKwFZ8Gz Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301882" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301882" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445979" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:18 -0800 Message-Id: <20220126104822.3653079-7-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 06/10] drm/i915/guc: Update GuC's log-buffer-state access for error capture. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" GuC log buffer regions for debug-log-events, crash-dumps and error-state-capture are all a single bo allocation that includes the guc_log_buffer_state structures. Since the error-capture region is accessed with high priority at non- deterministic times (as part of gpu coredump) while the debug-log-event region is populated and accessed with different priorities, timings and consumers, let's split out separate locks for buffer-state accesses of each region. Also, ensure a global mapping is made up front for the entire bo throughout GuC operation so that dynamic mapping and unmapping isn't required for error capture log access if relay-logging isn't running. Additionally, while here, make some readibility improvements: 1. change previous function names with "capture_logs" to "copy_debug_logs" to help make the distinction clearer. 2. Update the guc log region mapping comments to order them according to the enum definition as per the GuC interface. Signed-off-by: Alan Previn --- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 + .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 47 ++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 135 +++++++++++------- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h | 16 ++- 5 files changed, 141 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 4e819853ec2e..be1ad7fa2bf8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -34,6 +34,8 @@ struct intel_guc { struct intel_uc_fw fw; /** @log: sub-structure containing GuC log related data and objects */ struct intel_guc_log log; + /** @log_state: states and locks for each subregion of GuC's log buffer */ + struct intel_guc_log_stats log_state[GUC_MAX_LOG_BUFFER]; /** @ct: the command transport communication channel */ struct intel_guc_ct ct; /** @slpc: sub-structure containing SLPC related data and objects */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 70d2ee841289..e7f99d051636 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -651,6 +651,53 @@ int intel_guc_capture_prep_lists(struct intel_guc *guc, struct guc_ads *blob, u3 return PAGE_ALIGN(alloc_size); } +#define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 +int intel_guc_capture_output_min_size_est(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct intel_engine_cs *engine; + enum intel_engine_id id; + int worst_min_size = 0, num_regs = 0; + u16 tmp = 0; + + /* + * If every single engine-instance suffered a failure in quick succession but + * were all unrelated, then a burst of multiple error-capture events would dump + * registers for every one engine instance, one at a time. In this case, GuC + * would even dump the global-registers repeatedly. + * + * For each engine instance, there would be 1 x guc_state_capture_group_t output + * followed by 3 x guc_state_capture_t lists. The latter is how the register + * dumps are split across different register types (where the '3' are global vs class + * vs instance). Finally, let's multiply the whole thing by 3x (just so we are + * not limited to just 1 round of data in a worst case full register dump log) + * + * NOTE: intel_guc_log that allocates the log buffer would round this size up to + * a power of two. + */ + + for_each_engine(engine, gt, id) { + worst_min_size += sizeof(struct guc_state_capture_group_header_t) + + (3 * sizeof(struct guc_state_capture_header_t)); + + if (!guc_capture_list_count(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp)) + num_regs += tmp; + + if (!guc_capture_list_count(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + engine->class, &tmp)) { + num_regs += tmp; + } + if (!guc_capture_list_count(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + engine->class, &tmp)) { + num_regs += tmp; + } + } + + worst_min_size += (num_regs * sizeof(struct guc_mmio_reg)); + + return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); +} + void intel_guc_capture_destroy(struct intel_guc *guc) { guc_capture_clear_ext_regs(guc->capture.priv->reglists); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index 6b5594ca529d..4d3e5221128c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -14,6 +14,7 @@ struct guc_gt_system_info; int intel_guc_capture_prep_lists(struct intel_guc *guc, struct guc_ads *blob, u32 blob_ggtt, u32 capture_offset, struct guc_gt_system_info *sysinfo); +int intel_guc_capture_output_min_size_est(struct intel_guc *guc); void intel_guc_capture_destroy(struct intel_guc *guc); int intel_guc_capture_init(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index b53f61f3101f..d6b1a3c0fb15 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -6,12 +6,13 @@ #include #include "gt/intel_gt.h" +#include "intel_guc_capture.h" +#include "intel_guc_log.h" #include "i915_drv.h" #include "i915_irq.h" #include "i915_memcpy.h" -#include "intel_guc_log.h" -static void guc_log_capture_logs(struct intel_guc_log *log); +static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); /** * DOC: GuC firmware log @@ -136,7 +137,7 @@ static void guc_move_to_next_buf(struct intel_guc_log *log) smp_wmb(); /* All data has been written, so now move the offset of sub buffer. */ - relay_reserve(log->relay.channel, log->vma->obj->base.size); + relay_reserve(log->relay.channel, log->vma->obj->base.size - CAPTURE_BUFFER_SIZE); /* Switch to the next sub buffer */ relay_flush(log->relay.channel); @@ -156,25 +157,25 @@ static void *guc_get_write_buffer(struct intel_guc_log *log) return relay_reserve(log->relay.channel, 0); } -static bool guc_check_log_buf_overflow(struct intel_guc_log *log, - enum guc_log_buffer_type type, +static bool guc_check_log_buf_overflow(struct intel_guc *guc, + struct intel_guc_log_stats *log_state, unsigned int full_cnt) { - unsigned int prev_full_cnt = log->stats[type].sampled_overflow; + unsigned int prev_full_cnt = log_state->sampled_overflow; bool overflow = false; if (full_cnt != prev_full_cnt) { overflow = true; - log->stats[type].overflow = full_cnt; - log->stats[type].sampled_overflow += full_cnt - prev_full_cnt; + log_state->overflow = full_cnt; + log_state->sampled_overflow += full_cnt - prev_full_cnt; if (full_cnt < prev_full_cnt) { /* buffer_full_cnt is a 4 bit counter */ - log->stats[type].sampled_overflow += 16; + log_state->sampled_overflow += 16; } - dev_notice_ratelimited(guc_to_gt(log_to_guc(log))->i915->drm.dev, + dev_notice_ratelimited(guc_to_gt(guc)->i915->drm.dev, "GuC log buffer overflow\n"); } @@ -197,8 +198,10 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) return 0; } -static void guc_read_update_log_buffer(struct intel_guc_log *log) +static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { + struct intel_guc *guc = log_to_guc(log); + struct intel_guc_log_stats *logstate; unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; struct guc_log_buffer_state log_buf_state_local; @@ -212,7 +215,7 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) goto out_unlock; /* Get the pointer to shared GuC log buffer */ - log_buf_state = src_data = log->relay.buf_addr; + log_buf_state = src_data = log->buf_addr; /* Get the pointer to local buffer to store the logs */ log_buf_snapshot_state = dst_data = guc_get_write_buffer(log); @@ -222,7 +225,7 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) * Used rate limited to avoid deluge of messages, logs might be * getting consumed by User at a slow rate. */ - DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); + DRM_ERROR_RATELIMITED("no sub-buffer to copy general logs\n"); log->relay.full_count++; goto out_unlock; @@ -232,12 +235,16 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) src_data += PAGE_SIZE; dst_data += PAGE_SIZE; - for (type = GUC_DEBUG_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) { + /* For relay logging, we exclude error state capture */ + for (type = GUC_DEBUG_LOG_BUFFER; type <= GUC_CRASH_DUMP_LOG_BUFFER; type++) { /* + * Get a lock to the buffer_state we want to read and update. * Make a copy of the state structure, inside GuC log buffer * (which is uncached mapped), on the stack to avoid reading * from it multiple times. */ + logstate = &guc->log_state[type]; + mutex_lock(&logstate->lock); memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); buffer_size = guc_get_log_buffer_size(type); @@ -246,13 +253,14 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) full_cnt = log_buf_state_local.buffer_full_cnt; /* Bookkeeping stuff */ - log->stats[type].flush += log_buf_state_local.flush_to_file; - new_overflow = guc_check_log_buf_overflow(log, type, full_cnt); + logstate->flush += log_buf_state_local.flush_to_file; + new_overflow = guc_check_log_buf_overflow(guc, logstate, full_cnt); /* Update the state of shared log buffer */ log_buf_state->read_ptr = write_offset; log_buf_state->flush_to_file = 0; log_buf_state++; + mutex_unlock(&logstate->lock); /* First copy the state structure in snapshot buffer */ memcpy(log_buf_snapshot_state, &log_buf_state_local, @@ -300,49 +308,49 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) mutex_unlock(&log->relay.lock); } -static void capture_logs_work(struct work_struct *work) +static void copy_debug_logs_work(struct work_struct *work) { struct intel_guc_log *log = container_of(work, struct intel_guc_log, relay.flush_work); - guc_log_capture_logs(log); + guc_log_copy_debuglogs_for_relay(log); } -static int guc_log_map(struct intel_guc_log *log) +static int guc_log_relay_map(struct intel_guc_log *log) { - void *vaddr; - lockdep_assert_held(&log->relay.lock); - if (!log->vma) + if (!log->vma || !log->buf_addr) return -ENODEV; /* - * Create a WC (Uncached for read) vmalloc mapping of log - * buffer pages, so that we can directly get the data - * (up-to-date) from memory. + * WC vmalloc mapping of log buffer pages was done at + * GuC Init time, but lets keep a ref for book-keeping */ - vaddr = i915_gem_object_pin_map_unlocked(log->vma->obj, I915_MAP_WC); - if (IS_ERR(vaddr)) - return PTR_ERR(vaddr); - - log->relay.buf_addr = vaddr; + i915_gem_object_get(log->vma->obj); + log->relay.buf_in_use = true; return 0; } -static void guc_log_unmap(struct intel_guc_log *log) +static void guc_log_relay_unmap(struct intel_guc_log *log) { lockdep_assert_held(&log->relay.lock); - i915_gem_object_unpin_map(log->vma->obj); - log->relay.buf_addr = NULL; + i915_gem_object_put(log->vma->obj); + log->relay.buf_in_use = false; } void intel_guc_log_init_early(struct intel_guc_log *log) { + struct intel_guc *guc = log_to_guc(log); + int n; + + for (n = GUC_DEBUG_LOG_BUFFER; n < GUC_MAX_LOG_BUFFER; n++) + mutex_init(&guc->log_state[n].lock); + mutex_init(&log->relay.lock); - INIT_WORK(&log->relay.flush_work, capture_logs_work); + INIT_WORK(&log->relay.flush_work, copy_debug_logs_work); log->relay.started = false; } @@ -357,8 +365,11 @@ static int guc_log_relay_create(struct intel_guc_log *log) lockdep_assert_held(&log->relay.lock); GEM_BUG_ON(!log->vma); - /* Keep the size of sub buffers same as shared log buffer */ - subbuf_size = log->vma->size; + /* + * Keep the size of sub buffers same as shared log buffer + * but GuC log-events excludes the error-state-capture logs + */ + subbuf_size = log->vma->size - CAPTURE_BUFFER_SIZE; /* * Store up to 8 snapshots, which is large enough to buffer sufficient @@ -393,13 +404,13 @@ static void guc_log_relay_destroy(struct intel_guc_log *log) log->relay.channel = NULL; } -static void guc_log_capture_logs(struct intel_guc_log *log) +static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915; intel_wakeref_t wakeref; - guc_read_update_log_buffer(log); + _guc_log_copy_debuglogs_for_relay(log); /* * Generally device is expected to be active only at this @@ -439,6 +450,7 @@ int intel_guc_log_create(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); struct i915_vma *vma; + void *vaddr; u32 guc_log_size; int ret; @@ -446,25 +458,29 @@ int intel_guc_log_create(struct intel_guc_log *log) /* * GuC Log buffer Layout + * (this ordering must follow "enum guc_log_buffer_type" definition) * * +===============================+ 00B - * | Crash dump state header | - * +-------------------------------+ 32B * | Debug state header | + * +-------------------------------+ 32B + * | Crash dump state header | * +-------------------------------+ 64B * | Capture state header | * +-------------------------------+ 96B * | | * +===============================+ PAGE_SIZE (4KB) - * | Crash Dump logs | - * +===============================+ + CRASH_SIZE * | Debug logs | * +===============================+ + DEBUG_SIZE + * | Crash Dump logs | + * +===============================+ + CRASH_SIZE * | Capture logs | * +===============================+ + CAPTURE_SIZE */ - guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + - CAPTURE_BUFFER_SIZE; + if (intel_guc_capture_output_min_size_est(guc) > CAPTURE_BUFFER_SIZE) + DRM_WARN("GuC log buffer for state_capture maybe too small. %d < %d\n", + CAPTURE_BUFFER_SIZE, intel_guc_capture_output_min_size_est(guc)); + + guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + CAPTURE_BUFFER_SIZE; vma = intel_guc_allocate_vma(guc, guc_log_size); if (IS_ERR(vma)) { @@ -473,6 +489,17 @@ int intel_guc_log_create(struct intel_guc_log *log) } log->vma = vma; + /* + * Create a WC (Uncached for read) vmalloc mapping up front immediate access to + * data from memory during critical events such as error capture + */ + vaddr = i915_gem_object_pin_map_unlocked(log->vma->obj, I915_MAP_WC); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + i915_vma_unpin_and_release(&log->vma, 0); + goto err; + } + log->buf_addr = vaddr; log->level = __get_default_log_level(log); DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n", @@ -483,13 +510,14 @@ int intel_guc_log_create(struct intel_guc_log *log) return 0; err: - DRM_ERROR("Failed to allocate GuC log buffer. %d\n", ret); + DRM_ERROR("Failed to allocate or map GuC log buffer. %d\n", ret); return ret; } void intel_guc_log_destroy(struct intel_guc_log *log) { - i915_vma_unpin_and_release(&log->vma, 0); + log->buf_addr = NULL; + i915_vma_unpin_and_release(&log->vma, I915_VMA_RELEASE_MAP); } int intel_guc_log_set_level(struct intel_guc_log *log, u32 level) @@ -534,7 +562,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level) bool intel_guc_log_relay_created(const struct intel_guc_log *log) { - return log->relay.buf_addr; + return log->buf_addr; } int intel_guc_log_relay_open(struct intel_guc_log *log) @@ -565,7 +593,7 @@ int intel_guc_log_relay_open(struct intel_guc_log *log) if (ret) goto out_unlock; - ret = guc_log_map(log); + ret = guc_log_relay_map(log); if (ret) goto out_relay; @@ -615,8 +643,8 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log) with_intel_runtime_pm(guc_to_gt(guc)->uncore->rpm, wakeref) guc_action_flush_log(guc); - /* GuC would have updated log buffer by now, so capture it */ - guc_log_capture_logs(log); + /* GuC would have updated log buffer by now, so copy it */ + guc_log_copy_debuglogs_for_relay(log); } /* @@ -645,7 +673,7 @@ void intel_guc_log_relay_close(struct intel_guc_log *log) mutex_lock(&log->relay.lock); GEM_BUG_ON(!intel_guc_log_relay_created(log)); - guc_log_unmap(log); + guc_log_relay_unmap(log); guc_log_relay_destroy(log); mutex_unlock(&log->relay.lock); } @@ -682,6 +710,7 @@ stringify_guc_log_type(enum guc_log_buffer_type type) */ void intel_guc_log_info(struct intel_guc_log *log, struct drm_printer *p) { + struct intel_guc *guc = log_to_guc(log); enum guc_log_buffer_type type; if (!intel_guc_log_relay_created(log)) { @@ -696,8 +725,8 @@ void intel_guc_log_info(struct intel_guc_log *log, struct drm_printer *p) for (type = GUC_DEBUG_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) { drm_printf(p, "\t%s:\tflush count %10u, overflow count %10u\n", stringify_guc_log_type(type), - log->stats[type].flush, - log->stats[type].sampled_overflow); + guc->log_state[type].flush, + guc->log_state[type].sampled_overflow); } } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h index d7e1b6471fed..b6e8e9ee37b7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h @@ -46,23 +46,25 @@ struct intel_guc; #define GUC_VERBOSITY_TO_LOG_LEVEL(x) ((x) + 2) #define GUC_LOG_LEVEL_MAX GUC_VERBOSITY_TO_LOG_LEVEL(GUC_LOG_VERBOSITY_MAX) +struct intel_guc_log_stats { + struct mutex lock; /* protects below and guc_log_buffer_state's read-ptr */ + u32 sampled_overflow; + u32 overflow; + u32 flush; +}; + struct intel_guc_log { u32 level; struct i915_vma *vma; + void *buf_addr; struct { - void *buf_addr; + bool buf_in_use; bool started; struct work_struct flush_work; struct rchan *channel; struct mutex lock; u32 full_count; } relay; - /* logging related stats */ - struct { - u32 sampled_overflow; - u32 overflow; - u32 flush; - } stats[GUC_MAX_LOG_BUFFER]; }; void intel_guc_log_init_early(struct intel_guc_log *log); From patchwork Wed Jan 26 10:48:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724938 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D7F62C28CF5 for ; Wed, 26 Jan 2022 10:46:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3CBE410E80E; Wed, 26 Jan 2022 10:46:26 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9E1AB10E722 for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ESfWBCesOI3zSPhdyzohcDuq1beBcRNt8LlqufMspvA=; b=Z7SF3fg2H3BwtUh4duXUlzrpgSsGgut0zkr15B3Ql9zBkBzG3DTr28Ch /2JMJ28byRIKhx68jmz1upo9IwyGJyATMK7NFWv3hsJMShf/sTUdJlDYO M/OAKQ57/lW5IMURXjHtakf2QNUomrGMZ3D31kLgY0vdCblRL5XiH7ntf cwjA+8G/1TWbqcIM2UZUyJnFVB6Pb0CEt/mmNtyq2+X4p3J2Fivo9FZ1u soKGNgkgYiRzpBAJ/8OJ4ZTprszZsp2MiPLxuQHAQBGK6+9BwL5jk4JZq uziyj2AbYQVh/OM3sz4c7ZQ0PiZ7LcV3xegLSRw2Nff3MwZoWWuGJ4Fo6 A==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301883" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301883" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445983" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:19 -0800 Message-Id: <20220126104822.3653079-8-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 07/10] drm/i915/guc: Extract GuC error capture lists on G2H notification. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" - Upon the G2H Notify-Err-Capture event, parse through the GuC Log Buffer (error-capture-region) and dynamically allocate capture-nodes, A single node represents a single "engine- instance-capture-dump" and contains at least 3 register lists: global, engine-class and engine-instance. An internal link list is maintained to store one or more nodes. - The G2G error-capture notification event happens before the corresponding G2H context-reset that triggers the i915_gpu_coredump (where we want to avoid memory allocation moving forward). - Because the link-list node allocations happen before the call to i915_gpu_codedump, duplicate global and engine-class register lists for each engine-instance register dump if we find dependent-engine resets in a engine-capture-group. - Later when i915_gpu_coredump calls into capture_engine, (in the subsequent patch) we dettach the matching node (guc-id, LRCA, etc) from the link list above and attach it to i915_gpu_coredump's intel_engine_coredump structure when have matching LRCA/guc-id/engine-instance. - Finally, when we reset GuC submission lets also parse all outstanding capture data here too. Signed-off-by: Alan Previn --- .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 7 + drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 52 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 517 +++++++++++++++++- .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 26 +- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h | 4 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 14 +- 7 files changed, 608 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h index 7afdadc7656f..82a69f54cddb 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h @@ -173,4 +173,11 @@ enum intel_guc_sleep_state_status { #define GUC_LOG_CONTROL_VERBOSITY_MASK (0xF << GUC_LOG_CONTROL_VERBOSITY_SHIFT) #define GUC_LOG_CONTROL_DEFAULT_LOGGING (1 << 8) +enum intel_guc_state_capture_event_status { + INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_SUCCESS = 0x0, + INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE = 0x1, +}; + +#define INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK 0x1 + #endif /* _ABI_GUC_ACTIONS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 495cdb0228c6..14c497f12621 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -29,7 +29,8 @@ struct __guc_mmio_reg_descr_group { }; struct guc_state_capture_header_t { - u32 reserved1; + u32 owner; + #define CAP_HDR_CAPTURE_VFID GENMASK(7, 0) u32 info; #define CAP_HDR_CAPTURE_TYPE GENMASK(3, 0) /* see enum guc_capture_type */ #define CAP_HDR_ENGINE_CLASS GENMASK(7, 4) /* see GUC_MAX_ENGINE_CLASSES */ @@ -52,7 +53,8 @@ enum guc_capture_group_types { }; struct guc_state_capture_group_header_t { - u32 reserved1; + u32 owner; + #define CAP_GRP_HDR_CAPTURE_VFID GENMASK(7, 0) u32 info; #define CAP_GRP_HDR_NUM_CAPTURES GENMASK(7, 0) #define CAP_GRP_HDR_CAPTURE_TYPE GENMASK(15, 8) /* guc_capture_group_types */ @@ -63,11 +65,57 @@ struct guc_state_capture_group_t { struct guc_state_capture_t capture_entries[0]; } __packed; +struct __guc_capture_parsed_output { + /* + * a single set of 3 capture lists: a global-list + * an engine-class-list and an engine-instance list. + * outlist in __guc_capture_parsed_output will keep + * a linked list of these nodes that will eventually + * be detached from outlist and attached into to + * i915_gpu_codedump in response to a context reset + */ + struct list_head link; + bool is_partial; + u32 eng_class; + u32 eng_inst; + u32 guc_id; + u32 lrca; + struct gcap_reg_list_info { + u32 vfid; + u32 num; + struct guc_mmio_reg *regs; + } reginfo[GUC_CAPTURE_LIST_TYPE_MAX]; + #define GCAP_PARSED_REGLIST_INDEX_GLOBAL BIT(GUC_CAPTURE_LIST_TYPE_GLOBAL) + #define GCAP_PARSED_REGLIST_INDEX_ENGCLASS BIT(GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) + #define GCAP_PARSED_REGLIST_INDEX_ENGINST BIT(GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) +}; + +#define MAX_NODE_LINKLIST_THRESHOLD 24 + /* The maximum number of allocated __guc_capture_parsed_output nodes + * that we shall keep in outlist. If we receive an error-capture + * notification and need to allocate another node but have hit this + * threshold, we shall free the oldest entry and add a new one (FIFO). + */ + +struct __guc_capture_bufstate { + unsigned int size; + void *data; + unsigned int rd; + unsigned int wr; +}; + struct __guc_state_capture_priv { struct __guc_mmio_reg_descr_group *reglists; u16 num_instance_regs[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES]; u16 num_class_regs[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES]; u16 num_global_regs[GUC_CAPTURE_LIST_INDEX_MAX]; + /* An interim linked list of parsed GuC error-capture-output before + * reporting with formatting. Each node in this linked list shall + * contain a single engine-capture including global, engine-class and + * engine-instance register dumps as per guc_capture_parsed_output_node + */ + struct list_head outlist; + int listcount; /* see MAX_NODE_LINKLIST_THRESHOLD */ }; #endif /* _INTEL_GUC_CAPTURE_FWIF_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index e7f99d051636..0b6d743712a6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -12,6 +12,8 @@ #include "guc_capture_fwif.h" #include "intel_guc_fwif.h" #include "i915_drv.h" +#include "i915_gpu_error.h" +#include "i915_irq.h" #include "i915_memcpy.h" /* @@ -660,6 +662,9 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) int worst_min_size = 0, num_regs = 0; u16 tmp = 0; + if (!guc->capture.priv) + return -ENODEV; + /* * If every single engine-instance suffered a failure in quick succession but * were all unrelated, then a burst of multiple error-capture events would dump @@ -698,8 +703,518 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); } +/* + * KMD Init time flows: + * -------------------- + * --> alloc A: GuC input capture regs lists (registered via ADS) + * List acquired via intel_guc_capture_list_count + intel_guc_capture_list_init + * Size = global-reg-list + (class-reg-list) + (num-instances x instance-reg-list) + * Device tables carry: 1x global, 1x per-class, 1x per-instance) + * Caller needs to call per-class and per-instance multiplie times + * + * --> alloc B: GuC output capture buf (registered via guc_init_params(log_param)) + * Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small) + * Note2: 'x 3' to hold multiple capture groups + * + * + * GUC Runtime notify capture: + * -------------------------- + * --> G2H STATE_CAPTURE_NOTIFICATION + * L--> intel_guc_capture_store_snapshot + * L--> Loop through B (head..tail) and for each engine instance + * register we find: + * --> alloc C: A capture-output-node structure that includes misc capture info along + * with 3 register list dumps (global, engine-class and engine- + * instance). This node id added to a linked list stored in + * guc->capture->priv for matchup and printout when triggered by + * i915_gpu_coredump and err_print_gt (via error capture sysfs) later. + */ + +static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) +{ + if (buf->rd == buf->wr) + return 0; + if (buf->wr > buf->rd) + return (buf->wr - buf->rd); + return (buf->size - buf->rd) + buf->wr; +} + +static int guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate *buf) +{ + if (buf->rd > buf->wr) + return (buf->size - buf->rd); + return (buf->wr - buf->rd); +} + +static int +guc_capture_log_remove_dw(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + u32 *dw) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int tries = 2; + int avail = 0; + u32 *src_data; + + if (!guc_capture_buf_cnt(buf)) + return 0; + + while (tries--) { + avail = guc_capture_buf_cnt_to_end(buf); + if (avail >= sizeof(u32)) { + src_data = (u32 *)(buf->data + buf->rd); + *dw = *src_data; + buf->rd += 4; + return 4; + } + if (avail) + drm_warn(&i915->drm, "GuC-Cap-Logs not dword aligned, skipping.\n"); + buf->rd = 0; + } + + return 0; +} + +static bool +guc_capture_data_extracted(struct __guc_capture_bufstate *b, + int s, void *p) +{ + if (guc_capture_buf_cnt_to_end(b) >= s) { + memcpy(p, (b->data + b->rd), s); + b->rd += s; + return true; + } + return false; +} + +static int +guc_capture_log_get_group_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_state_capture_group_header_t *ghdr) +{ + int read = 0; + int fullsize = sizeof(struct guc_state_capture_group_header_t); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)ghdr)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, &ghdr->owner); + read += guc_capture_log_remove_dw(guc, buf, &ghdr->info); + if (read != fullsize) + return -1; + + return 0; +} + +static int +guc_capture_log_get_data_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_state_capture_header_t *hdr) +{ + int read = 0; + int fullsize = sizeof(struct guc_state_capture_header_t); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)hdr)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, &hdr->owner); + read += guc_capture_log_remove_dw(guc, buf, &hdr->info); + read += guc_capture_log_remove_dw(guc, buf, &hdr->lrca); + read += guc_capture_log_remove_dw(guc, buf, &hdr->guc_id); + read += guc_capture_log_remove_dw(guc, buf, &hdr->num_mmios); + if (read != fullsize) + return -1; + + return 0; +} + +static int +guc_capture_log_get_register(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_mmio_reg *reg) +{ + int read = 0; + int fullsize = sizeof(struct guc_mmio_reg); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)reg)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, ®->offset); + read += guc_capture_log_remove_dw(guc, buf, ®->value); + read += guc_capture_log_remove_dw(guc, buf, ®->flags); + read += guc_capture_log_remove_dw(guc, buf, ®->mask); + if (read != fullsize) + return -1; + + return 0; +} + +static void +guc_capture_del_all_nodes(struct intel_guc *guc) +{ + int i; + + if (!list_empty(&guc->capture.priv->outlist)) { + struct __guc_capture_parsed_output *n, *ntmp; + + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) { + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (n->reginfo[i].regs) + kfree(n->reginfo[i].regs); + } + list_del(&n->link); + kfree(n); + } + } + guc->capture.priv->listcount = 0; +} + +static void +guc_capture_del_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) +{ + int i; + struct __guc_capture_parsed_output *found = NULL; + + if (!list_empty(&guc->capture.priv->outlist)) { + struct __guc_capture_parsed_output *n, *ntmp; + + if (node) { + found = node; + } else { + /* traverse down and get the oldest entry */ + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) + found = n; + } + if (found) { + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (found->reginfo[i].regs) + kfree(found->reginfo[i].regs); + } + list_del(&found->link); + kfree(found); + --guc->capture.priv->listcount; + } + } +} + +static void +guc_capture_add_node_to_list(struct intel_guc *guc, struct __guc_capture_parsed_output *node) +{ + GEM_BUG_ON(guc->capture.priv->listcount > MAX_NODE_LINKLIST_THRESHOLD); + + if (guc->capture.priv->listcount == MAX_NODE_LINKLIST_THRESHOLD) { + /* discard oldest node */ + guc_capture_del_node(guc, NULL); + } + + ++guc->capture.priv->listcount; + list_add_tail(&node->link, &guc->capture.priv->outlist); +} + +static struct __guc_capture_parsed_output * +guc_capture_create_node(struct intel_guc *guc, struct __guc_capture_parsed_output *ori, + u32 keep_reglist_mask) +{ + struct __guc_capture_parsed_output *new; + int i; + + new = kzalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return NULL; + INIT_LIST_HEAD(&new->link); + if (!ori) + return new; + memcpy(new, ori, sizeof(*new)); + + /* reallocate individual reg-list pointers */ + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + new->reginfo[i].regs = NULL; + new->reginfo[i].num = 0; + } + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (keep_reglist_mask & BIT(i)) { + new->reginfo[i].regs = kcalloc(ori->reginfo[i].num, + sizeof(struct guc_mmio_reg), GFP_KERNEL); + if (!new->reginfo[i].regs) + goto bail_clone; + memcpy(new->reginfo[i].regs, ori->reginfo[i].regs, ori->reginfo[i].num * + sizeof(struct guc_mmio_reg)); + new->reginfo[i].num = ori->reginfo[i].num; + } + } + + return new; + +bail_clone: + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (new->reginfo[i].regs) + kfree(new->reginfo[i].regs); + } + kfree(new); + return NULL; +} + +static int +guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstate *buf) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct guc_state_capture_group_header_t ghdr = {0}; + struct guc_state_capture_header_t hdr = {0}; + struct __guc_capture_parsed_output *node = NULL; + struct guc_mmio_reg *regs = NULL; + int i, numlists, numreg, ret = 0; + bool is_partial = false; + enum guc_capture_type datatype; + + i = guc_capture_buf_cnt(buf); + if (!i) + return -ENODATA; + if (i % sizeof(u32)) { + drm_warn(&i915->drm, "GuC Capture new entries unaligned\n"); + ret = -EIO; + goto bailout; + } + + /* first get the capture group header */ + if (guc_capture_log_get_group_hdr(guc, buf, &ghdr)) { + ret = -EIO; + goto bailout; + } + /* + * we would typically expect a layout as below where n would be expected to be + * anywhere between 3 to n where n > 3 if we are seeing multiple dependent engine + * instances being reset together. + * ____________________________________________ + * | Capture Group | + * | ________________________________________ | + * | | Capture Group Header: | | + * | | - num_captures = 5 | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture1: | | + * | | Hdr: GLOBAL, numregs=a | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... rega | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture2: | | + * | | Hdr: CLASS=RENDER/COMPUTE, numregs=b| | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regb | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture3: | | + * | | Hdr: INSTANCE=RCS, numregs=c | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regc | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture4: | | + * | | Hdr: CLASS=RENDER/COMPUTE, numregs=d| | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regd | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture5: | | + * | | Hdr: INSTANCE=CCS0, numregs=e | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... rege | | | + * | | |__________________________________| | | + * | |______________________________________| | + * |__________________________________________| + */ + is_partial = FIELD_GET(CAP_GRP_HDR_CAPTURE_TYPE, ghdr.info); + if (is_partial) + drm_warn(&i915->drm, "GuC Capture group is partial\n"); + numlists = FIELD_GET(CAP_GRP_HDR_NUM_CAPTURES, ghdr.info); + while (numlists--) { + + numreg = 0; + regs = NULL; + if (guc_capture_log_get_data_hdr(guc, buf, &hdr)) { + ret = -EIO; + break; + } + + datatype = FIELD_GET(CAP_HDR_CAPTURE_TYPE, hdr.info); + if (node) { + /* Based on the current capture type and what we have so far, + * decide if we should add the current node into the internal + * linked list for match-up when i915_gpu_coredump calls later + * (and alloc a blank node for the next set of reglists) + * or continue with the same node or clone the current node + * but only retain the global or class registers (such as the + * case of dependent engine resets). + */ + if (datatype == GUC_CAPTURE_LIST_TYPE_GLOBAL) { + guc_capture_add_node_to_list(guc, node); + node = NULL; + } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS && + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].regs) { + /* Add to list, clone node and duplicate global list */ + guc_capture_add_node_to_list(guc, node); + node = guc_capture_create_node(guc, node, + GCAP_PARSED_REGLIST_INDEX_GLOBAL); + } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE && + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].regs) { + /* Add to list, clone node and duplicate global + class lists */ + guc_capture_add_node_to_list(guc, node); + node = guc_capture_create_node(guc, node, + (GCAP_PARSED_REGLIST_INDEX_GLOBAL | + GCAP_PARSED_REGLIST_INDEX_ENGCLASS)); + } + } + + if (!node) { + node = guc_capture_create_node(guc, NULL, 0); + if (!node) { + ret = -ENOMEM; + break; + } + if (datatype != GUC_CAPTURE_LIST_TYPE_GLOBAL) + drm_dbg(&i915->drm, "GuC Capture missing global dump: %08x!\n", + datatype); + } + node->is_partial = is_partial; + switch (datatype) { + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + node->eng_inst = FIELD_GET(CAP_HDR_ENGINE_INSTANCE, hdr.info); + node->lrca = hdr.lrca; + node->guc_id = hdr.guc_id; + node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); + break; + default: + break; + } + regs = NULL; + numreg = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); + if (numreg) { + regs = kcalloc(numreg, sizeof(*regs), GFP_KERNEL); + if (!regs) { + ret = -ENOMEM; + break; + } + } + node->reginfo[datatype].num = numreg; + node->reginfo[datatype].regs = regs; + node->reginfo[datatype].vfid = FIELD_GET(CAP_HDR_CAPTURE_VFID, hdr.info); + i = 0; + while (numreg--) { + if (guc_capture_log_get_register(guc, buf, ®s[i++])) { + ret = -EIO; + break; + } + } + } + +bailout: + if (node) { + /* If we have data, add to linked list for match-up when i915_gpu_coredump calls */ + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (node->reginfo[i].regs) { + guc_capture_add_node_to_list(guc, node); + node = NULL; + break; + } + } + if (node) + kfree(node); + } + return ret; +} + +static void __guc_capture_store_snapshot_work(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + unsigned int buffer_size, read_offset, write_offset, full_count; + struct guc_log_buffer_state *log_buf_state; + struct guc_log_buffer_state log_buf_state_local; + void *src_data = NULL; + bool new_overflow; + struct __guc_capture_bufstate buf; + int ret; + + /* Lock to get the pointer to GuC capture-log-buffer-state */ + mutex_lock(&guc->log_state[GUC_CAPTURE_LOG_BUFFER].lock); + log_buf_state = guc->log.buf_addr + + (sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER); + src_data = guc->log.buf_addr + intel_guc_get_log_buffer_offset(GUC_CAPTURE_LOG_BUFFER); + + /* + * Make a copy of the state structure, inside GuC log buffer + * (which is uncached mapped), on the stack to avoid reading + * from it multiple times. + */ + memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); + buffer_size = intel_guc_get_log_buffer_size(GUC_CAPTURE_LOG_BUFFER); + read_offset = log_buf_state_local.read_ptr; + write_offset = log_buf_state_local.sampled_write_ptr; + full_count = log_buf_state_local.buffer_full_cnt; + + /* Bookkeeping stuff */ + guc->log_state[GUC_CAPTURE_LOG_BUFFER].flush += log_buf_state_local.flush_to_file; + new_overflow = intel_guc_check_log_buf_overflow(guc, + &guc->log_state[GUC_CAPTURE_LOG_BUFFER], + full_count); + + /* Now copy the actual logs. */ + if (unlikely(new_overflow)) { + /* copy the whole buffer in case of overflow */ + read_offset = 0; + write_offset = buffer_size; + } else if (unlikely((read_offset > buffer_size) || + (write_offset > buffer_size))) { + drm_err(&i915->drm, "invalid GuC log capture buffer state!\n"); + /* copy whole buffer as offsets are unreliable */ + read_offset = 0; + write_offset = buffer_size; + } + + buf.size = buffer_size; + buf.rd = read_offset; + buf.wr = write_offset; + buf.data = src_data; + /* */ + do { + ret = guc_capture_extract_reglists(guc, &buf); + } while (ret >= 0); + + /* Update the state of shared log buffer */ + log_buf_state->read_ptr = write_offset; + log_buf_state->flush_to_file = 0; + + mutex_unlock(&guc->log_state[GUC_CAPTURE_LOG_BUFFER].lock); +} + +void intel_guc_capture_store_snapshot(struct intel_guc *guc) +{ + if (guc->capture.priv) + __guc_capture_store_snapshot_work(guc); +} + void intel_guc_capture_destroy(struct intel_guc *guc) { + if (!guc->capture.priv) + return; + + guc_capture_del_all_nodes(guc); guc_capture_clear_ext_regs(guc->capture.priv->reglists); kfree(guc->capture.priv); guc->capture.priv = NULL; @@ -710,7 +1225,7 @@ int intel_guc_capture_init(struct intel_guc *guc) guc->capture.priv = kzalloc(sizeof(*guc->capture.priv), GFP_KERNEL); if (!guc->capture.priv) return -ENOMEM; + INIT_LIST_HEAD(&guc->capture.priv->outlist); guc->capture.priv->reglists = guc_capture_get_device_reglist(guc); - return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index 4d3e5221128c..c240a4cc046b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -14,6 +14,7 @@ struct guc_gt_system_info; int intel_guc_capture_prep_lists(struct intel_guc *guc, struct guc_ads *blob, u32 blob_ggtt, u32 capture_offset, struct guc_gt_system_info *sysinfo); +void intel_guc_capture_store_snapshot(struct intel_guc *guc); int intel_guc_capture_output_min_size_est(struct intel_guc *guc); void intel_guc_capture_destroy(struct intel_guc *guc); int intel_guc_capture_init(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index d6b1a3c0fb15..194b17e8c2ae 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -157,9 +157,9 @@ static void *guc_get_write_buffer(struct intel_guc_log *log) return relay_reserve(log->relay.channel, 0); } -static bool guc_check_log_buf_overflow(struct intel_guc *guc, - struct intel_guc_log_stats *log_state, - unsigned int full_cnt) +bool intel_guc_check_log_buf_overflow(struct intel_guc *guc, + struct intel_guc_log_stats *log_state, + unsigned int full_cnt) { unsigned int prev_full_cnt = log_state->sampled_overflow; bool overflow = false; @@ -182,7 +182,7 @@ static bool guc_check_log_buf_overflow(struct intel_guc *guc, return overflow; } -static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) +unsigned int intel_guc_get_log_buffer_size(enum guc_log_buffer_type type) { switch (type) { case GUC_DEBUG_LOG_BUFFER: @@ -198,6 +198,20 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) return 0; } +size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type) +{ + enum guc_log_buffer_type i; + size_t offset = PAGE_SIZE;/* for the log_buffer_states */ + + for (i = GUC_DEBUG_LOG_BUFFER; i < GUC_MAX_LOG_BUFFER; i++) { + if (i == type) + break; + offset += intel_guc_get_log_buffer_size(i); + } + + return offset; +} + static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); @@ -247,14 +261,14 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) mutex_lock(&logstate->lock); memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); - buffer_size = guc_get_log_buffer_size(type); + buffer_size = intel_guc_get_log_buffer_size(type); read_offset = log_buf_state_local.read_ptr; write_offset = log_buf_state_local.sampled_write_ptr; full_cnt = log_buf_state_local.buffer_full_cnt; /* Bookkeeping stuff */ logstate->flush += log_buf_state_local.flush_to_file; - new_overflow = guc_check_log_buf_overflow(guc, logstate, full_cnt); + new_overflow = intel_guc_check_log_buf_overflow(guc, logstate, full_cnt); /* Update the state of shared log buffer */ log_buf_state->read_ptr = write_offset; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h index b6e8e9ee37b7..f16de816447d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h @@ -68,6 +68,10 @@ struct intel_guc_log { }; void intel_guc_log_init_early(struct intel_guc_log *log); +bool intel_guc_check_log_buf_overflow(struct intel_guc *guc, struct intel_guc_log_stats *state, + unsigned int full_cnt); +unsigned int intel_guc_get_log_buffer_size(enum guc_log_buffer_type type); +size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type); int intel_guc_log_create(struct intel_guc_log *log); void intel_guc_log_destroy(struct intel_guc_log *log); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index db9615dcb0ec..c19d6d682394 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -24,6 +24,7 @@ #include "gt/intel_ring.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" #include "intel_guc_submission.h" #include "i915_drv.h" @@ -1444,6 +1445,8 @@ void intel_guc_submission_reset_prepare(struct intel_guc *guc) flush_work(&guc->ct.requests.worker); scrub_guc_desc_for_outstanding_g2h(guc); + + intel_guc_capture_store_snapshot(guc); } static struct intel_engine_cs * @@ -4016,17 +4019,20 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, int intel_guc_error_capture_process_msg(struct intel_guc *guc, const u32 *msg, u32 len) { - int status; + u32 status; if (unlikely(len != 1)) { drm_dbg(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); return -EPROTO; } - status = msg[0]; - drm_info(&guc_to_gt(guc)->i915->drm, "Got error capture: status = %d", status); + status = msg[0] & INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK; + if (status == INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE) + drm_warn(&guc_to_gt(guc)->i915->drm, "G2H-Error capture no space"); + else + drm_info(&guc_to_gt(guc)->i915->drm, "G2H-Received error capture"); - /* FIXME: Do something with the capture */ + intel_guc_capture_store_snapshot(guc); return 0; } From patchwork Wed Jan 26 10:48:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724942 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DFE1DC28CF5 for ; Wed, 26 Jan 2022 10:46:38 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6D53A10E8D7; Wed, 26 Jan 2022 10:46:27 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id BD6CE10E834 for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Pr6hbdSwzMLYhpSeEg+hnwgYxhvvhPpGZZqW7NOJCAY=; b=DZSDKytFr4OIEsa7Ofo7HfiRF0UMd2s3Lyuo8FCSm908Uao7FxafLJjC +kJPe78cbQfd0Tt9HZU1w+FhiNygOyyHpDRJM1S4+HL3x3Z8mHQXYNujl YvpxC7BYfQkq3P7gvIpfy0+ZtROuirW4R9ju6GD8DjgILkOCZCl+S7A+N zH5SmYGoIotFQ+jI20nZqw0CurvtSpAobIfhACEbkokopdcluivFsS50T f+5BQkwESqP118NFvecqLEDmCOwzSeqBBqTy1DW7dnyFv5bQ23uwADC2P W1+KGgyr3s+/er2ez4HpFyajHd21gqL4s9B/wwefbh1J/w3GcaQ1azKML w==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301885" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301885" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445988" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:20 -0800 Message-Id: <20220126104822.3653079-9-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 08/10] drm/i915/guc: Plumb GuC-capture into gpu_coredump X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Add a flags parameter through all of the coredump creation functions. Add a bitmask flag to indicate if the top level gpu_coredump event is triggered in response to a GuC context reset notification. Using that flag, ensure all coredump functions that read or print mmio-register values related to work submission or command-streamer engines are skipped and replaced with a calls guc-capture module equivalent functions to retrieve or print the register dump. While here, split out display related register reading and printing into its own function that is called agnostic to whether GuC had triggered the reset. For now, introduce an empty printing function that can filled in on a subsequent patch just to handle formatting. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa --- .../drm/i915/gt/intel_execlists_submission.c | 4 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 78 ++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 11 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 263 ++++++++++++------ drivers/gpu/drm/i915/i915_gpu_error.h | 31 ++- 8 files changed, 295 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 960a9aaf4f3a..c8bb43863461 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2230,11 +2230,11 @@ static struct execlists_capture *capture_regs(struct intel_engine_cs *engine) if (!cap->error) goto err_cap; - cap->error->gt = intel_gt_coredump_alloc(engine->gt, gfp); + cap->error->gt = intel_gt_coredump_alloc(engine->gt, gfp, CORE_DUMP_FLAG_NONE); if (!cap->error->gt) goto err_gpu; - cap->error->gt->engine = intel_engine_coredump_alloc(engine, gfp); + cap->error->gt->engine = intel_engine_coredump_alloc(engine, gfp, CORE_DUMP_FLAG_NONE); if (!cap->error->gt->engine) goto err_gt; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 6f2821cca409..c1dc3f8b1108 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1305,7 +1305,7 @@ void intel_gt_handle_error(struct intel_gt *gt, engine_mask &= gt->info.engine_mask; if (flags & I915_ERROR_CAPTURE) { - i915_capture_error_state(gt, engine_mask); + i915_capture_error_state(gt, engine_mask, CORE_DUMP_FLAG_NONE); intel_gt_clear_error_registers(gt, engine_mask); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 0b6d743712a6..2f5dc413dddc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -728,6 +728,17 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) * instance). This node id added to a linked list stored in * guc->capture->priv for matchup and printout when triggered by * i915_gpu_coredump and err_print_gt (via error capture sysfs) later. + * + * GUC --> notify context reset: + * ----------------------------- + * --> G2H CONTEXT RESET + * L--> guc_handle_context_reset --> i915_capture_error_state + * L--> i915_gpu_coredump(..IS_GUC_CAPTURE) --> gt_record_engines + * --> capture_engine(..IS_GUC_CAPTURE) + * L--> detach C from internal linked list and add into + * intel_engine_coredump struct (if the context and + * engine of the event notification matches a node + * in the link list) */ static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) @@ -1203,6 +1214,73 @@ static void __guc_capture_store_snapshot_work(struct intel_guc *guc) mutex_unlock(&guc->log_state[GUC_CAPTURE_LOG_BUFFER].lock); } +#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) + +int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, + const struct intel_engine_coredump *ee) +{ + return 0; +} + +#endif //CONFIG_DRM_I915_DEBUG_GUC + +void intel_guc_capture_free_node(struct intel_engine_coredump *ee) +{ + int i; + + if (!ee) + return; + if (!ee->guc_capture_node) + return; + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (ee->guc_capture_node->reginfo[i].regs) + kfree(ee->guc_capture_node->reginfo[i].regs); + } + kfree(ee->guc_capture_node); + ee->guc_capture_node = NULL; +} + +void intel_guc_capture_get_matching_node(struct intel_gt *gt, + struct intel_engine_coredump *ee, + struct intel_context *ce) +{ + struct intel_guc *guc; + struct drm_i915_private *i915; + + if (!gt || !ee || !ce) + return; + + i915 = gt->i915; + guc = >->uc.guc; + if (!guc->capture.priv) + return; + + GEM_BUG_ON(ee->guc_capture_node); + /* + * Look for a matching GuC reported error capture node from + * the internal output link-list based on lrca, guc-id and engine + * identification. + */ + if (!list_empty(&guc->capture.priv->outlist)) { + struct __guc_capture_parsed_output *n, *ntmp; + + list_for_each_entry_safe(n, ntmp, &guc->capture.priv->outlist, link) { + if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(ee->engine->guc_id) && + n->eng_class == GUC_ID_TO_ENGINE_CLASS(ee->engine->guc_id) && + n->guc_id == ce->guc_id.id && + (n->lrca & CTX_GTT_ADDRESS_MASK) == + (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) { + list_del(&n->link); + --guc->capture.priv->listcount; + ee->guc_capture_node = n; + ee->capture = &guc->capture; + return; + } + } + } + drm_warn(&i915->drm, "GuC capture can't match ee to node\n"); +} + void intel_guc_capture_store_snapshot(struct intel_guc *guc) { if (guc->capture.priv) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index c240a4cc046b..9a2037638e64 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -8,12 +8,21 @@ #include -struct intel_guc; +struct drm_i915_error_state_buf; struct guc_ads; struct guc_gt_system_info; +struct intel_context; +struct intel_engine_coredump; +struct intel_gt; +struct intel_guc; int intel_guc_capture_prep_lists(struct intel_guc *guc, struct guc_ads *blob, u32 blob_ggtt, u32 capture_offset, struct guc_gt_system_info *sysinfo); +int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *m, + const struct intel_engine_coredump *ee); +void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee, + struct intel_context *ce); +void intel_guc_capture_free_node(struct intel_engine_coredump *ee); void intel_guc_capture_store_snapshot(struct intel_guc *guc); int intel_guc_capture_output_min_size_est(struct intel_guc *guc); void intel_guc_capture_destroy(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index c19d6d682394..45ec7db3a85f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3953,7 +3953,7 @@ static void capture_error_state(struct intel_guc *guc, intel_engine_set_hung_context(engine, ce); with_intel_runtime_pm(&i915->runtime_pm, wakeref) - i915_capture_error_state(gt, engine->mask); + i915_capture_error_state(gt, engine->mask, CORE_DUMP_FLAG_IS_GUC_CAPTURE); atomic_inc(&i915->gpu_error.reset_engine_count[engine->uabi_class]); } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f3141b58d912..d2af0d1f3a3e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -294,7 +294,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file) gpu = NULL; with_intel_runtime_pm(&i915->runtime_pm, wakeref) - gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES); + gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); if (IS_ERR(gpu)) return PTR_ERR(gpu); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index aee42eae4729..d8c82589d86e 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -590,15 +590,11 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, ee->vm_info.pp_dir_base); } } - err_printf(m, " hung: %u\n", ee->hung); - err_printf(m, " engine reset count: %u\n", ee->reset_count); for (n = 0; n < ee->num_ports; n++) { err_printf(m, " ELSP[%d]:", n); error_print_request(m, " ", &ee->execlist[n]); } - - error_print_context(m, " Active context: ", &ee->context); } void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) @@ -710,23 +706,30 @@ static void err_print_gt_info(struct drm_i915_error_state_buf *m, intel_sseu_print_topology(>->info.sseu, &p); } -static void err_print_gt(struct drm_i915_error_state_buf *m, - struct intel_gt_coredump *gt) +static void err_print_gt_display(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + err_printf(m, "IER: 0x%08x\n", gt->ier); + err_printf(m, "DERRMR: 0x%08x\n", gt->derrmr); +} + +static void err_print_gt_global_nonguc(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) { - const struct intel_engine_coredump *ee; int i; err_printf(m, "GT awake: %s\n", yesno(gt->awake)); err_printf(m, "EIR: 0x%08x\n", gt->eir); - err_printf(m, "IER: 0x%08x\n", gt->ier); + err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); + for (i = 0; i < gt->ngtier; i++) err_printf(m, "GTIER[%d]: 0x%08x\n", i, gt->gtier[i]); - err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); - err_printf(m, "FORCEWAKE: 0x%08x\n", gt->forcewake); - err_printf(m, "DERRMR: 0x%08x\n", gt->derrmr); +} - for (i = 0; i < gt->nfence; i++) - err_printf(m, " fence[%d] = %08llx\n", i, gt->fence[i]); +static void err_print_gt_global(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + err_printf(m, "FORCEWAKE: 0x%08x\n", gt->forcewake); if (IS_GRAPHICS_VER(m->i915, 6, 11)) { err_printf(m, "ERROR: 0x%08x\n", gt->error); @@ -765,19 +768,38 @@ static void err_print_gt(struct drm_i915_error_state_buf *m, err_printf(m, " GAM_DONE: 0x%08x\n", gt->gam_done); } +} + +static void err_print_gt_fences(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + int i; + + for (i = 0; i < gt->nfence; i++) + err_printf(m, " fence[%d] = %08llx\n", i, gt->fence[i]); +} + +static void err_print_gt_engines(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + const struct intel_engine_coredump *ee; for (ee = gt->engine; ee; ee = ee->next) { const struct i915_vma_coredump *vma; - error_print_engine(m, ee); + if (ee->guc_capture_node) + intel_guc_capture_print_engine_node(m, ee); + else + error_print_engine(m, ee); + + err_printf(m, " hung: %u\n", ee->hung); + err_printf(m, " engine reset count: %u\n", ee->reset_count); + error_print_context(m, " Active context: ", &ee->context); + for (vma = ee->vma; vma; vma = vma->next) print_error_vma(m, ee->engine, vma); } - if (gt->uc) - err_print_uc(m, gt->uc); - - err_print_gt_info(m, gt); } static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, @@ -833,8 +855,30 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock)); err_printf(m, "PM suspended: %s\n", yesno(error->suspended)); - if (error->gt) - err_print_gt(m, error->gt); + if (error->gt) { + bool print_guc_capture = false; + + if (error->gt->uc && error->gt->uc->is_guc_capture) + print_guc_capture = true; + + err_print_gt_display(m, error->gt); + err_print_gt_global_nonguc(m, error->gt); + err_print_gt_fences(m, error->gt); + + /* + * GuC dumped global, eng-class and eng-instance registers together + * as part of engine state dump so we print in err_print_gt_engines + */ + if (!print_guc_capture) + err_print_gt_global(m, error->gt); + + err_print_gt_engines(m, error->gt); + + if (error->gt->uc) + err_print_uc(m, error->gt->uc); + + err_print_gt_info(m, error->gt); + } if (error->overlay) intel_overlay_print_error_state(m, error->overlay); @@ -982,6 +1026,7 @@ static void cleanup_gt(struct intel_gt_coredump *gt) gt->engine = ee->next; i915_vma_coredump_free(ee->vma); + intel_guc_capture_free_node(ee); kfree(ee); } @@ -1433,7 +1478,7 @@ static void add_vma_coredump(struct intel_engine_coredump *ee, } struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags) { struct intel_engine_coredump *ee; @@ -1443,8 +1488,10 @@ intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) ee->engine = engine; - engine_record_registers(ee); - engine_record_execlists(ee); + if (!(dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)) { + engine_record_registers(ee); + engine_record_execlists(ee); + } return ee; } @@ -1508,7 +1555,8 @@ intel_engine_coredump_add_vma(struct intel_engine_coredump *ee, static struct intel_engine_coredump * capture_engine(struct intel_engine_cs *engine, - struct i915_vma_compress *compress) + struct i915_vma_compress *compress, + u32 dump_flags) { struct intel_engine_capture_vma *capture = NULL; struct intel_engine_coredump *ee; @@ -1516,7 +1564,7 @@ capture_engine(struct intel_engine_cs *engine, struct i915_request *rq = NULL; unsigned long flags; - ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL); + ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); if (!ee) return NULL; @@ -1549,6 +1597,8 @@ capture_engine(struct intel_engine_cs *engine, i915_request_put(rq); goto no_request_capture; } + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + intel_guc_capture_get_matching_node(engine->gt, ee, ce); intel_engine_coredump_add_vma(ee, capture, compress); i915_request_put(rq); @@ -1563,7 +1613,8 @@ capture_engine(struct intel_engine_cs *engine, static void gt_record_engines(struct intel_gt_coredump *gt, intel_engine_mask_t engine_mask, - struct i915_vma_compress *compress) + struct i915_vma_compress *compress, + u32 dump_flags) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -1574,7 +1625,7 @@ gt_record_engines(struct intel_gt_coredump *gt, /* Refill our page pool before entering atomic section */ pool_refill(&compress->pool, ALLOW_FAIL); - ee = capture_engine(engine, compress); + ee = capture_engine(engine, compress, dump_flags); if (!ee) continue; @@ -1617,8 +1668,74 @@ gt_record_uc(struct intel_gt_coredump *gt, return error_uc; } -/* Capture all registers which don't fit into another category. */ -static void gt_record_regs(struct intel_gt_coredump *gt) +/* Capture display registers. */ +static void gt_record_display_regs(struct intel_gt_coredump *gt) +{ + struct intel_uncore *uncore = gt->_gt->uncore; + struct drm_i915_private *i915 = uncore->i915; + + if (GRAPHICS_VER(i915) >= 6) + gt->derrmr = intel_uncore_read(uncore, DERRMR); + + if (GRAPHICS_VER(i915) >= 8) + gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); + else if (IS_VALLEYVIEW(i915)) + gt->ier = intel_uncore_read(uncore, VLV_IER); + else if (HAS_PCH_SPLIT(i915)) + gt->ier = intel_uncore_read(uncore, DEIER); + else if (GRAPHICS_VER(i915) == 2) + gt->ier = intel_uncore_read16(uncore, GEN2_IER); + else + gt->ier = intel_uncore_read(uncore, GEN2_IER); +} + +/* Capture all other registers that GuC doesn't capture. */ +static void gt_record_global_nonguc_regs(struct intel_gt_coredump *gt) +{ + struct intel_uncore *uncore = gt->_gt->uncore; + struct drm_i915_private *i915 = uncore->i915; + int i; + + if (IS_VALLEYVIEW(i915)) { + gt->gtier[0] = intel_uncore_read(uncore, GTIER); + gt->ngtier = 1; + } else if (GRAPHICS_VER(i915) >= 11) { + gt->gtier[0] = + intel_uncore_read(uncore, + GEN11_RENDER_COPY_INTR_ENABLE); + gt->gtier[1] = + intel_uncore_read(uncore, GEN11_VCS_VECS_INTR_ENABLE); + gt->gtier[2] = + intel_uncore_read(uncore, GEN11_GUC_SG_INTR_ENABLE); + gt->gtier[3] = + intel_uncore_read(uncore, + GEN11_GPM_WGBOXPERF_INTR_ENABLE); + gt->gtier[4] = + intel_uncore_read(uncore, + GEN11_CRYPTO_RSVD_INTR_ENABLE); + gt->gtier[5] = + intel_uncore_read(uncore, + GEN11_GUNIT_CSME_INTR_ENABLE); + gt->ngtier = 6; + } else if (GRAPHICS_VER(i915) >= 8) { + for (i = 0; i < 4; i++) + gt->gtier[i] = + intel_uncore_read(uncore, GEN8_GT_IER(i)); + gt->ngtier = 4; + } else if (HAS_PCH_SPLIT(i915)) { + gt->gtier[0] = intel_uncore_read(uncore, GTIER); + gt->ngtier = 1; + } + + gt->eir = intel_uncore_read(uncore, EIR); + gt->pgtbl_er = intel_uncore_read(uncore, PGTBL_ER); +} + +/* + * Capture all registers that relate to workload submission. + * NOTE: In GuC submission, when GuC resets an engine, it can dump these for us + */ +static void gt_record_global_regs(struct intel_gt_coredump *gt) { struct intel_uncore *uncore = gt->_gt->uncore; struct drm_i915_private *i915 = uncore->i915; @@ -1634,11 +1751,8 @@ static void gt_record_regs(struct intel_gt_coredump *gt) */ /* 1: Registers specific to a single generation */ - if (IS_VALLEYVIEW(i915)) { - gt->gtier[0] = intel_uncore_read(uncore, GTIER); - gt->ier = intel_uncore_read(uncore, VLV_IER); + if (IS_VALLEYVIEW(i915)) gt->forcewake = intel_uncore_read_fw(uncore, FORCEWAKE_VLV); - } if (GRAPHICS_VER(i915) == 7) gt->err_int = intel_uncore_read(uncore, GEN7_ERR_INT); @@ -1666,7 +1780,6 @@ static void gt_record_regs(struct intel_gt_coredump *gt) gt->forcewake = intel_uncore_read_fw(uncore, FORCEWAKE_MT); if (GRAPHICS_VER(i915) >= 6) { - gt->derrmr = intel_uncore_read(uncore, DERRMR); if (GRAPHICS_VER(i915) < 12) { gt->error = intel_uncore_read(uncore, ERROR_GEN6); gt->done_reg = intel_uncore_read(uncore, DONE_REG); @@ -1702,44 +1815,6 @@ static void gt_record_regs(struct intel_gt_coredump *gt) gt->gam_done = intel_uncore_read(uncore, GEN12_GAM_DONE); } - - /* 4: Everything else */ - if (GRAPHICS_VER(i915) >= 11) { - gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); - gt->gtier[0] = - intel_uncore_read(uncore, - GEN11_RENDER_COPY_INTR_ENABLE); - gt->gtier[1] = - intel_uncore_read(uncore, GEN11_VCS_VECS_INTR_ENABLE); - gt->gtier[2] = - intel_uncore_read(uncore, GEN11_GUC_SG_INTR_ENABLE); - gt->gtier[3] = - intel_uncore_read(uncore, - GEN11_GPM_WGBOXPERF_INTR_ENABLE); - gt->gtier[4] = - intel_uncore_read(uncore, - GEN11_CRYPTO_RSVD_INTR_ENABLE); - gt->gtier[5] = - intel_uncore_read(uncore, - GEN11_GUNIT_CSME_INTR_ENABLE); - gt->ngtier = 6; - } else if (GRAPHICS_VER(i915) >= 8) { - gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); - for (i = 0; i < 4; i++) - gt->gtier[i] = - intel_uncore_read(uncore, GEN8_GT_IER(i)); - gt->ngtier = 4; - } else if (HAS_PCH_SPLIT(i915)) { - gt->ier = intel_uncore_read(uncore, DEIER); - gt->gtier[0] = intel_uncore_read(uncore, GTIER); - gt->ngtier = 1; - } else if (GRAPHICS_VER(i915) == 2) { - gt->ier = intel_uncore_read16(uncore, GEN2_IER); - } else if (!IS_VALLEYVIEW(i915)) { - gt->ier = intel_uncore_read(uncore, GEN2_IER); - } - gt->eir = intel_uncore_read(uncore, EIR); - gt->pgtbl_er = intel_uncore_read(uncore, PGTBL_ER); } static void gt_record_info(struct intel_gt_coredump *gt) @@ -1851,7 +1926,7 @@ i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp) #define DAY_AS_SECONDS(x) (24 * 60 * 60 * (x)) struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags) { struct intel_gt_coredump *gc; @@ -1862,7 +1937,21 @@ intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) gc->_gt = gt; gc->awake = intel_gt_pm_is_awake(gt); - gt_record_regs(gc); + gt_record_display_regs(gc); + gt_record_global_nonguc_regs(gc); + + /* + * GuC dumps global, eng-class and eng-instance registers + * (that can change as part of engine state during execution) + * before an engine is reset due to a hung context. + * GuC captures and reports all three groups of registers + * together as a single set before the engine is reset. + * Thus, if GuC triggered the context reset we retrieve + * the register values as part of gt_record_engines. + */ + if (!(dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)) + gt_record_global_regs(gc); + gt_record_fences(gc); return gc; @@ -1896,7 +1985,7 @@ void i915_vma_capture_finish(struct intel_gt_coredump *gt, } static struct i915_gpu_coredump * -__i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) +__i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { struct drm_i915_private *i915 = gt->i915; struct i915_gpu_coredump *error; @@ -1910,7 +1999,7 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) if (!error) return ERR_PTR(-ENOMEM); - error->gt = intel_gt_coredump_alloc(gt, ALLOW_FAIL); + error->gt = intel_gt_coredump_alloc(gt, ALLOW_FAIL, dump_flags); if (error->gt) { struct i915_vma_compress *compress; @@ -1921,11 +2010,19 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) return ERR_PTR(-ENOMEM); } + if (INTEL_INFO(i915)->has_gt_uc) { + error->gt->uc = gt_record_uc(error->gt, compress); + if (error->gt->uc) { + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + error->gt->uc->is_guc_capture = true; + else + GEM_BUG_ON(error->gt->uc->is_guc_capture); + } + } + gt_record_info(error->gt); - gt_record_engines(error->gt, engine_mask, compress); + gt_record_engines(error->gt, engine_mask, compress, dump_flags); - if (INTEL_INFO(i915)->has_gt_uc) - error->gt->uc = gt_record_uc(error->gt, compress); i915_vma_capture_finish(error->gt, compress); @@ -1938,7 +2035,7 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) } struct i915_gpu_coredump * -i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) +i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { static DEFINE_MUTEX(capture_mutex); int ret = mutex_lock_interruptible(&capture_mutex); @@ -1947,7 +2044,7 @@ i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) if (ret) return ERR_PTR(ret); - dump = __i915_gpu_coredump(gt, engine_mask); + dump = __i915_gpu_coredump(gt, engine_mask, dump_flags); mutex_unlock(&capture_mutex); return dump; @@ -1994,11 +2091,11 @@ void i915_error_state_store(struct i915_gpu_coredump *error) * to pick up. */ void i915_capture_error_state(struct intel_gt *gt, - intel_engine_mask_t engine_mask) + intel_engine_mask_t engine_mask, u32 dump_flags) { struct i915_gpu_coredump *error; - error = i915_gpu_coredump(gt, engine_mask); + error = i915_gpu_coredump(gt, engine_mask, dump_flags); if (IS_ERR(error)) { cmpxchg(>->i915->gpu_error.first_error, NULL, error); return; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index 5aedf5129814..d20a1779ea51 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -17,6 +17,7 @@ #include "gt/intel_engine.h" #include "gt/intel_gt_types.h" #include "gt/uc/intel_uc_fw.h" +#include "gt/uc/intel_guc_capture.h" #include "intel_device_info.h" @@ -53,6 +54,8 @@ struct i915_request_coredump { struct i915_sched_attr sched_attr; }; +struct __guc_capture_parsed_output; + struct intel_engine_coredump { const struct intel_engine_cs *engine; @@ -84,6 +87,10 @@ struct intel_engine_coredump { u32 rc_psmi; /* sleep state */ struct intel_instdone instdone; + /* GuC matched capture-lists info */ + struct intel_guc_state_capture *capture; + struct __guc_capture_parsed_output *guc_capture_node; + struct i915_gem_context_coredump { char comm[TASK_COMM_LEN]; @@ -124,7 +131,6 @@ struct intel_gt_coredump { u32 pgtbl_er; u32 ier; u32 gtier[6], ngtier; - u32 derrmr; u32 forcewake; u32 error; /* gen6+ */ u32 err_int; /* gen7 */ @@ -137,9 +143,12 @@ struct intel_gt_coredump { u32 gfx_mode; u32 gtt_cache; u32 aux_err; /* gen12 */ - u32 sfc_done[GEN12_SFC_DONE_MAX]; /* gen12 */ u32 gam_done; /* gen12 */ + /* Display related */ + u32 derrmr; + u32 sfc_done[GEN12_SFC_DONE_MAX]; /* gen12 */ + u32 nfence; u64 fence[I915_MAX_NUM_FENCES]; @@ -149,6 +158,7 @@ struct intel_gt_coredump { struct intel_uc_fw guc_fw; struct intel_uc_fw huc_fw; struct i915_vma_coredump *guc_log; + bool is_guc_capture; } *uc; struct intel_gt_coredump *next; @@ -210,24 +220,27 @@ struct drm_i915_error_state_buf { int err; }; +#define CORE_DUMP_FLAG_NONE 0x0 +#define CORE_DUMP_FLAG_IS_GUC_CAPTURE BIT(0) + #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) __printf(2, 3) void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); struct i915_gpu_coredump *i915_gpu_coredump(struct intel_gt *gt, - intel_engine_mask_t engine_mask); + intel_engine_mask_t engine_mask, u32 dump_flags); void i915_capture_error_state(struct intel_gt *gt, - intel_engine_mask_t engine_mask); + intel_engine_mask_t engine_mask, u32 dump_flags); struct i915_gpu_coredump * i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp); struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp); +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags); struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp); +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags); struct intel_engine_capture_vma * intel_engine_coredump_add_request(struct intel_engine_coredump *ee, @@ -271,7 +284,7 @@ void i915_disable_error_state(struct drm_i915_private *i915, int err); #else static inline void -i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask) +i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { } @@ -282,13 +295,13 @@ i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp) } static inline struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags) { return NULL; } static inline struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags) { return NULL; } From patchwork Wed Jan 26 10:48:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724935 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EA481C2BA4C for ; Wed, 26 Jan 2022 10:46:31 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EED8510E722; Wed, 26 Jan 2022 10:46:24 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id E433C10E808 for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wFSyKtHFunA1xqqRQX3rKiZs/QZD+tUlaRysPWFpQR8=; b=BMAHBNAl7/6xblpr28nOLQfqrMQb1DW0tEMO8solgLIjumR6Pumv+iy2 qJo/XsPkXI4aDnfqYWxl9G1A4ChZEdTNvrr9uT8jdggrPuAJDk5LuT7kN zc6VQzI2vA2BEw/T0HKD7U4+z8js5BKradYRfKtcDPfBoBaBk+pSVcyLJ bkC+ohPIwFVaGcuVLHU0A/KbLfbb3B0SwQ6OGFtV2CkXr2Z2jWlPNYkeD B3kFPUJxUxvNuATeOawBnIHyrtb19nvt/V0Bf/vALhhD04HstUICsuYik GmNcHIXg177oQPDco1N25njDPMrDuvwjljMfpmAzGlB2oNRnyBVdTD1Zq g==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301886" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301886" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:23 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445991" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:22 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:21 -0800 Message-Id: <20220126104822.3653079-10-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 09/10] drm/i915/guc: Follow legacy register names X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Before we print the GuC provided register dumps, modify the register tables to use string names as per the legacy error capture execlist codes. Signed-off-by: Alan Previn --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 2f5dc413dddc..506496058daf 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -22,7 +22,7 @@ * from the engine-mmio-base */ #define COMMON_BASE_GLOBAL() \ - {FORCEWAKE_MT, 0, 0, "FORCEWAKE_MT"} + {FORCEWAKE_MT, 0, 0, "FORCEWAKE"} #define COMMON_GEN9BASE_GLOBAL() \ {GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0"}, \ @@ -34,43 +34,43 @@ #define COMMON_GEN12BASE_GLOBAL() \ {GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0"}, \ {GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1"}, \ - {GEN12_AUX_ERR_DBG, 0, 0, "GEN12_AUX_ERR_DBG"}, \ - {GEN12_GAM_DONE, 0, 0, "GEN12_GAM_DONE"}, \ - {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"} + {GEN12_AUX_ERR_DBG, 0, 0, "AUX_ERR_DBG"}, \ + {GEN12_GAM_DONE, 0, 0, "GAM_DONE"}, \ + {GEN12_RING_FAULT_REG, 0, 0, "FAULT_REG"} #define COMMON_BASE_ENGINE_INSTANCE() \ - {RING_PSMI_CTL(0), 0, 0, "RING_PSMI_CTL"}, \ - {RING_ESR(0), 0, 0, "RING_ESR"}, \ - {RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LOW32"}, \ - {RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UP32"}, \ - {RING_IPEIR(0), 0, 0, "RING_IPEIR"}, \ - {RING_IPEHR(0), 0, 0, "RING_IPEHR"}, \ - {RING_INSTPS(0), 0, 0, "RING_INSTPS"}, \ + {RING_PSMI_CTL(0), 0, 0, "RC PSMI"}, \ + {RING_ESR(0), 0, 0, "ESR"}, \ + {RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW"}, \ + {RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UDW"}, \ + {RING_IPEIR(0), 0, 0, "IPEIR"}, \ + {RING_IPEHR(0), 0, 0, "IPEHR"}, \ + {RING_INSTPS(0), 0, 0, "INSTPS"}, \ {RING_BBADDR(0), 0, 0, "RING_BBADDR_LOW32"}, \ {RING_BBADDR_UDW(0), 0, 0, "RING_BBADDR_UP32"}, \ - {RING_BBSTATE(0), 0, 0, "RING_BBSTATE"}, \ + {RING_BBSTATE(0), 0, 0, "BB_STATE"}, \ {CCID(0), 0, 0, "CCID"}, \ - {RING_ACTHD(0), 0, 0, "RING_ACTHD_LOW32"}, \ - {RING_ACTHD_UDW(0), 0, 0, "RING_ACTHD_UP32"}, \ - {RING_INSTPM(0), 0, 0, "RING_INSTPM"}, \ + {RING_ACTHD(0), 0, 0, "ACTHD_LDW"}, \ + {RING_ACTHD_UDW(0), 0, 0, "ACTHD_UDW"}, \ + {RING_INSTPM(0), 0, 0, "INSTPM"}, \ + {RING_INSTDONE(0), 0, 0, "INSTDONE"}, \ {RING_NOPID(0), 0, 0, "RING_NOPID"}, \ - {RING_START(0), 0, 0, "RING_START"}, \ - {RING_HEAD(0), 0, 0, "RING_HEAD"}, \ - {RING_TAIL(0), 0, 0, "RING_TAIL"}, \ - {RING_CTL(0), 0, 0, "RING_CTL"}, \ - {RING_MI_MODE(0), 0, 0, "RING_MI_MODE"}, \ + {RING_START(0), 0, 0, "START"}, \ + {RING_HEAD(0), 0, 0, "HEAD"}, \ + {RING_TAIL(0), 0, 0, "TAIL"}, \ + {RING_CTL(0), 0, 0, "CTL"}, \ + {RING_MI_MODE(0), 0, 0, "MODE"}, \ {RING_CONTEXT_CONTROL(0), 0, 0, "RING_CONTEXT_CONTROL"}, \ - {RING_INSTDONE(0), 0, 0, "RING_INSTDONE"}, \ - {RING_HWS_PGA(0), 0, 0, "RING_HWS_PGA"}, \ - {RING_MODE_GEN7(0), 0, 0, "RING_MODE_GEN7"}, \ - {GEN8_RING_PDP_LDW(0, 0), 0, 0, "GEN8_RING_PDP0_LDW"}, \ - {GEN8_RING_PDP_UDW(0, 0), 0, 0, "GEN8_RING_PDP0_UDW"}, \ - {GEN8_RING_PDP_LDW(0, 1), 0, 0, "GEN8_RING_PDP1_LDW"}, \ - {GEN8_RING_PDP_UDW(0, 1), 0, 0, "GEN8_RING_PDP1_UDW"}, \ - {GEN8_RING_PDP_LDW(0, 2), 0, 0, "GEN8_RING_PDP2_LDW"}, \ - {GEN8_RING_PDP_UDW(0, 2), 0, 0, "GEN8_RING_PDP2_UDW"}, \ - {GEN8_RING_PDP_LDW(0, 3), 0, 0, "GEN8_RING_PDP3_LDW"}, \ - {GEN8_RING_PDP_UDW(0, 3), 0, 0, "GEN8_RING_PDP3_UDW"} + {RING_HWS_PGA(0), 0, 0, "HWS"}, \ + {RING_MODE_GEN7(0), 0, 0, "GFX_MODE"}, \ + {GEN8_RING_PDP_LDW(0, 0), 0, 0, "PDP0_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 0), 0, 0, "PDP0_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 1), 0, 0, "PDP1_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 1), 0, 0, "PDP1_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 2), 0, 0, "PDP2_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 2), 0, 0, "PDP2_UDW"}, \ + {GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW"}, \ + {GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW"} #define COMMON_BASE_HAS_EU() \ {EIR, 0, 0, "EIR"} @@ -83,10 +83,10 @@ {GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2"} #define COMMON_GEN12BASE_VEC() \ - {GEN12_SFC_DONE(0), 0, 0, "GEN12_SFC_DONE0"}, \ - {GEN12_SFC_DONE(1), 0, 0, "GEN12_SFC_DONE1"}, \ - {GEN12_SFC_DONE(2), 0, 0, "GEN12_SFC_DONE2"}, \ - {GEN12_SFC_DONE(3), 0, 0, "GEN12_SFC_DONE3"} + {GEN12_SFC_DONE(0), 0, 0, "SFC_DONE[0]"}, \ + {GEN12_SFC_DONE(1), 0, 0, "SFC_DONE[1]"}, \ + {GEN12_SFC_DONE(2), 0, 0, "SFC_DONE[2]"}, \ + {GEN12_SFC_DONE(3), 0, 0, "SFC_DONE[3]"} /* XE_LPD - Global */ static struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { From patchwork Wed Jan 26 10:48:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Teres Alexis, Alan Previn" X-Patchwork-Id: 12724939 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E017EC2BA4C for ; Wed, 26 Jan 2022 10:46:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D196010E882; Wed, 26 Jan 2022 10:46:25 +0000 (UTC) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id EABD310E80E for ; Wed, 26 Jan 2022 10:46:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643193983; x=1674729983; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SP2RD0p9tu7ttQZepBmmfhMhGZ1iqYnLyQPUM4LWg0o=; b=goPtHHWPOcqejDbGOdlDRsloIjG8Nj0UvZ9ibPCr9ygz3jR73xSFrggH hG+1PwsSiPMSF5hM/bmtUzIOnr8pWEP1/ebGkRTUQGWIqWArNBKzN4HOc /c1yjnUJDYnxsQgmghqScPCIHHFa0Kt8VoPdICmQgre4LohtXxjrHveer 4I08rdz2kCS4FoK61W5ws3Y1EA5FOaKU/9CiIKbHNAK1Zln68wYv9DgFT toZUM1UzOAUqnfHV18tVSJYnv0bqdOdBXndpAo7vDf0idrCvQL94ZxHcB l4SPTshZz5C5crKdAmSHJGQSDkIGNHTDp63pOFz1TiYYoEXm3HowRpNyS g==; X-IronPort-AV: E=McAfee;i="6200,9189,10238"; a="246301888" X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="246301888" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jan 2022 02:46:23 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,317,1635231600"; d="scan'208";a="477445995" Received: from aalteres-desk.fm.intel.com ([10.80.57.53]) by orsmga003.jf.intel.com with ESMTP; 26 Jan 2022 02:46:23 -0800 From: Alan Previn To: intel-gfx@lists.freedesktop.org Date: Wed, 26 Jan 2022 02:48:22 -0800 Message-Id: <20220126104822.3653079-11-alan.previn.teres.alexis@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> References: <20220126104822.3653079-1-alan.previn.teres.alexis@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 10/10] drm/i915/guc: Print the GuC error capture output register list. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alan Previn Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Print the GuC captured error state register list (string names and values) when gpu_coredump_state printout is invoked via the i915 debugfs for flushing the gpu error-state that was captured prior. Since GuC could have reported multiple engine register dumps in a single notification event, parse the captured data (appearing as a stream of structures) to identify each dump as a different 'engine-capture-group-output'. Finally, for each 'engine-capture-group-output' that is found, verify if the engine register dump corresponds to the engine_coredump content that was previously populated by the i915_gpu_coredump function. That function would have copied the context's vma's including the bacth buffer during the G2H-context-reset notification that occurred earlier. Perform this verification check by comparing guc_id, lrca and engine- instance obtained from the 'engine-capture-group-output' vs a copy of that same info taken during i915_gpu_coredump. If they match, then print those vma's as well (such as the batch buffers). Signed-off-by: Alan Previn --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 4 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 169 ++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 16 +- drivers/gpu/drm/i915/i915_gpu_error.h | 5 + 6 files changed, 185 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 4317ae5e525b..47c0c32d9b86 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1628,9 +1628,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine, drm_printf(m, "\tIPEHR: 0x%08x\n", ENGINE_READ(engine, IPEHR)); } - if (intel_engine_uses_guc(engine)) { - /* nothing to print yet */ - } else if (HAS_EXECLISTS(dev_priv)) { + if (HAS_EXECLISTS(dev_priv) && !intel_engine_uses_guc(engine)) { struct i915_request * const *port, *rq; const u32 *hws = &engine->status_page.addr[I915_HWS_CSB_BUF0_INDEX]; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 506496058daf..5cb24098747e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -739,6 +739,15 @@ int intel_guc_capture_output_min_size_est(struct intel_guc *guc) * intel_engine_coredump struct (if the context and * engine of the event notification matches a node * in the link list) + * + * User Sysfs / Debugfs + * -------------------- + * --> i915_gpu_coredump_copy_to_buffer-> + * L--> err_print_to_sgl --> err_print_gt + * L--> error_print_guc_captures + * L--> intel_guc_capture_print_node prints the + * register lists values of the attached node + * on the error-engine-dump being reported. */ static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) @@ -1216,12 +1225,172 @@ static void __guc_capture_store_snapshot_work(struct intel_guc *guc) #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) +static const char * +guc_capture_reg_to_str(const struct intel_guc *guc, u32 owner, u32 type, + u32 class, u32 id, u32 offset, u32 *is_ext) +{ + struct __guc_mmio_reg_descr_group *reglists = guc->capture.priv->reglists; + struct __guc_mmio_reg_descr_group *match; + int num_regs, j; + + *is_ext = 0; + if (!reglists) + return NULL; + + match = guc_capture_get_one_list(reglists, owner, type, id); + + if (match) { + for (num_regs = match->num_regs, j = 0; j < num_regs; ++j) { + if (offset == match->list[j].reg.reg) + return match->list[j].regname; + } + } + if (match->ext) { + for (num_regs = match->num_ext, j = 0; j < num_regs; ++j) { + if (offset == match->ext[j].reg.reg) { + *is_ext = 1; + return match->ext[j].regname; + } + } + } + + return NULL; +} + +#ifdef CONFIG_DRM_I915_DEBUG_GUC +#define guc_capt_err_print(a, b, ...) \ + do { \ + drm_warn(a, __VA_ARGS__); \ + if (b) \ + i915_error_printf(b, __VA_ARGS__); \ + } while (0) +#else +#define guc_capt_err_print(a, b, ...) \ + do { \ + if (b) \ + i915_error_printf(b, __VA_ARGS__); \ + } while (0) +#endif + +static struct intel_engine_cs * +guc_capture_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance) +{ + struct intel_gt *gt = guc_to_gt(guc); + u8 engine_class = guc_class_to_engine_class(guc_class); + + /* Class index is checked in class converter */ + GEM_BUG_ON(instance > MAX_ENGINE_INSTANCE); + + return gt->engine_class[engine_class][instance]; +} + +#define GCAP_PRINT_INTEL_ENG_INFO(i915, ebuf, eng) \ + do { \ + PRINT(&(i915)->drm, (ebuf), " i915-Eng-Name: %s command stream\n", \ + (eng)->name); \ + PRINT(&(i915)->drm, (ebuf), " i915-Eng-Inst-Class: 0x%02x\n", (eng)->class); \ + PRINT(&(i915)->drm, (ebuf), " i915-Eng-Inst-Id: 0x%02x\n", (eng)->instance); \ + PRINT(&(i915)->drm, (ebuf), " i915-Eng-LogicalMask: 0x%08x\n", \ + (eng)->logical_mask); \ + } while (0) + +#define GCAP_PRINT_GUC_INST_INFO(i915, ebuf, node) \ + do { \ + PRINT(&(i915)->drm, (ebuf), " GuC-Engine-Inst-Id: 0x%08x\n", \ + (node)->eng_inst); \ + PRINT(&(i915)->drm, (ebuf), " GuC-Context-Id: 0x%08x\n", (node)->guc_id); \ + PRINT(&(i915)->drm, (ebuf), " LRCA: 0x%08x\n", (node)->lrca); \ + } while (0) + +#define PRINT guc_capt_err_print + int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, const struct intel_engine_coredump *ee) { + struct intel_guc_state_capture *cap; + struct intel_guc *guc; + struct drm_i915_private *i915; + struct __guc_capture_parsed_output *node; + struct guc_mmio_reg *regs; + const char *grptypestr[GUC_STATE_CAPTURE_GROUP_TYPE_MAX] = {"full-capture", + "partial-capture"}; + const char *datatypestr[GUC_CAPTURE_LIST_TYPE_MAX] = {"Global", "Engine-Class", + "Engine-Instance"}; + struct intel_engine_cs *eng; + int numregs, i, j; + u32 is_ext; + const char *str; + char noname[16]; + + if (!ebuf || !ee) + return -EINVAL; + cap = ee->capture; + if (!cap->priv || !ee->engine) + return -ENODEV; + + guc = container_of(cap, struct intel_guc, capture); + i915 = (container_of(guc, struct intel_gt, uc.guc))->i915; + PRINT(&i915->drm, ebuf, "global --- GuC Error Capture on %s command stream:\n", + ee->engine->name); + + node = ee->guc_capture_node; + if (!node) { + PRINT(&i915->drm, ebuf, " No matching ee-node\n"); + return 0; + } + + PRINT(&i915->drm, ebuf, "Coverage: %s\n", grptypestr[node->is_partial]); + + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + PRINT(&i915->drm, ebuf, " RegListType: %s\n", + datatypestr[i % GUC_CAPTURE_LIST_TYPE_MAX]); + PRINT(&i915->drm, ebuf, " Owner-Id: %d\n", node->reginfo[i].vfid); + + switch (i) { + case GUC_CAPTURE_LIST_TYPE_GLOBAL: + default: + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + PRINT(&i915->drm, ebuf, " GuC-Eng-Class: %d\n", node->eng_class); + PRINT(&i915->drm, ebuf, " i915-Eng-Class: %d\n", + guc_class_to_engine_class(node->eng_class)); + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + eng = guc_capture_lookup_engine(guc, node->eng_class, node->eng_inst); + if (eng) + GCAP_PRINT_INTEL_ENG_INFO(i915, ebuf, eng); + else + PRINT(&i915->drm, ebuf, " i915-Eng-Lookup Fail!\n"); + GCAP_PRINT_GUC_INST_INFO(i915, ebuf, node); + break; + } + + numregs = node->reginfo[i].num; + PRINT(&i915->drm, ebuf, " NumRegs: %d\n", numregs); + j = 0; + while (numregs--) { + regs = node->reginfo[i].regs; + str = guc_capture_reg_to_str(guc, GUC_CAPTURE_LIST_INDEX_PF, i, + node->eng_class, 0, regs[j].offset, &is_ext); + if (!str) { + snprintf(noname, sizeof(noname), "REG-0x%08x", regs[j].offset); + PRINT(&i915->drm, ebuf, " %s", noname); + } else { + PRINT(&i915->drm, ebuf, " %s", str); + } + if (is_ext) + PRINT(&i915->drm, ebuf, "[%ld][%ld]", + FIELD_GET(GUC_REGSET_STEERING_GROUP, regs[j].flags), + FIELD_GET(GUC_REGSET_STEERING_INSTANCE, regs[j].flags)); + PRINT(&i915->drm, ebuf, ": 0x%08x\n", regs[j].value); + ++j; + } + } return 0; } +#undef PRINT + #endif //CONFIG_DRM_I915_DEBUG_GUC void intel_guc_capture_free_node(struct intel_engine_coredump *ee) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index 9a2037638e64..3ed33f14ac7d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -11,8 +11,8 @@ struct drm_i915_error_state_buf; struct guc_ads; struct guc_gt_system_info; -struct intel_context; struct intel_engine_coredump; +struct intel_context; struct intel_gt; struct intel_guc; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d2af0d1f3a3e..35faba20d406 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -295,6 +295,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file) gpu = NULL; with_intel_runtime_pm(&i915->runtime_pm, wakeref) gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); + if (IS_ERR(gpu)) return PTR_ERR(gpu); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index d8c82589d86e..67d39226155e 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -526,8 +526,8 @@ __find_vma(struct i915_vma_coredump *vma, const char *name) return NULL; } -static struct i915_vma_coredump * -find_batch(const struct intel_engine_coredump *ee) +struct i915_vma_coredump * +intel_gpu_error_find_batch(const struct intel_engine_coredump *ee) { return __find_vma(ee->vma, "batch"); } @@ -555,7 +555,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, error_print_instdone(m, ee); - batch = find_batch(ee); + batch = intel_gpu_error_find_batch(ee); if (batch) { u64 start = batch->gtt_offset; u64 end = start + batch->gtt_size; @@ -606,9 +606,9 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) va_end(args); } -static void print_error_vma(struct drm_i915_error_state_buf *m, - const struct intel_engine_cs *engine, - const struct i915_vma_coredump *vma) +void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, + const struct intel_engine_cs *engine, + const struct i915_vma_coredump *vma) { char out[ASCII85_BUFSZ]; struct page *page; @@ -677,7 +677,7 @@ static void err_print_uc(struct drm_i915_error_state_buf *m, intel_uc_fw_dump(&error_uc->guc_fw, &p); intel_uc_fw_dump(&error_uc->huc_fw, &p); - print_error_vma(m, NULL, error_uc->guc_log); + intel_gpu_error_print_vma(m, NULL, error_uc->guc_log); } static void err_free_sgl(struct scatterlist *sgl) @@ -797,7 +797,7 @@ static void err_print_gt_engines(struct drm_i915_error_state_buf *m, error_print_context(m, " Active context: ", &ee->context); for (vma = ee->vma; vma; vma = vma->next) - print_error_vma(m, ee->engine, vma); + intel_gpu_error_print_vma(m, ee->engine, vma); } } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index d20a1779ea51..5f52dda67ef8 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -227,6 +227,11 @@ struct drm_i915_error_state_buf { __printf(2, 3) void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); +void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, + const struct intel_engine_cs *engine, + const struct i915_vma_coredump *vma); +struct i915_vma_coredump * +intel_gpu_error_find_batch(const struct intel_engine_coredump *ee); struct i915_gpu_coredump *i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags);