[Intel-xe] [PATCH 6/7] drm/xe/pat: Add debugfs node to dump PAT

Lucas De Marchi lucas.demarchi at intel.com
Mon Oct 2 20:03:19 UTC 2023


On Fri, Sep 29, 2023 at 01:44:35PM -0700, Matt Roper wrote:
>On Thu, Sep 28, 2023 at 10:02:52PM -0700, Lucas De Marchi wrote:
>> This is useful to debug cache issues, to double check if the PAT
>> indexes match what they were supposed to be set to from spec.
>>
>> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
>> ---
>>  drivers/gpu/drm/xe/xe_gt_debugfs.c | 12 ++++
>>  drivers/gpu/drm/xe/xe_pat.c        | 96 ++++++++++++++++++++++++++++++
>>  drivers/gpu/drm/xe/xe_pat.h        |  8 +++
>>  3 files changed, 116 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c
>> index ec1ae00f6bfc..cd6d28c7b923 100644
>> --- a/drivers/gpu/drm/xe/xe_gt_debugfs.c
>> +++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c
>> @@ -16,6 +16,7 @@
>>  #include "xe_gt_topology.h"
>>  #include "xe_hw_engine.h"
>>  #include "xe_macros.h"
>> +#include "xe_pat.h"
>>  #include "xe_reg_sr.h"
>>  #include "xe_reg_whitelist.h"
>>  #include "xe_uc_debugfs.h"
>> @@ -138,6 +139,16 @@ static int workarounds(struct seq_file *m, void *data)
>>  	return 0;
>>  }
>>
>> +static int pat(struct seq_file *m, void *data)
>> +{
>> +	struct xe_gt *gt = node_to_gt(m->private);
>> +	struct drm_printer p = drm_seq_file_printer(m);
>> +
>> +	xe_pat_dump(gt, &p);
>> +
>> +	return 0;
>> +}
>> +
>>  static const struct drm_info_list debugfs_list[] = {
>>  	{"hw_engines", hw_engines, 0},
>>  	{"force_reset", force_reset, 0},
>> @@ -147,6 +158,7 @@ static const struct drm_info_list debugfs_list[] = {
>>  	{"ggtt", ggtt, 0},
>>  	{"register-save-restore", register_save_restore, 0},
>>  	{"workarounds", workarounds, 0},
>> +	{"pat", pat, 0},
>>  };
>>
>>  void xe_gt_debugfs_register(struct xe_gt *gt)
>> diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c
>> index 296763594370..20714888a5fa 100644
>> --- a/drivers/gpu/drm/xe/xe_pat.c
>> +++ b/drivers/gpu/drm/xe/xe_pat.c
>> @@ -6,6 +6,8 @@
>>  #include "xe_pat.h"
>>
>>  #include "regs/xe_reg_defs.h"
>> +#include "xe_assert.h"
>> +#include "xe_device.h"
>>  #include "xe_gt.h"
>>  #include "xe_gt_mcr.h"
>>  #include "xe_mmio.h"
>> @@ -14,6 +16,7 @@
>>  #define _PAT_INDEX(index)			_PICK_EVEN_2RANGES(index, 8, \
>>  								   0x4800, 0x4804, \
>>  								   0x4848, 0x484c)
>> +#define _PAT_PTA				0x4820
>>
>>  #define XE2_NO_PROMOTE				REG_BIT(10)
>>  #define XE2_COMP_EN				REG_BIT(9)
>> @@ -43,6 +46,7 @@
>>  struct xe_pat_ops {
>>  	void (*program_graphics)(struct xe_gt *gt, const u32 table[], int n_entries);
>>  	void (*program_media)(struct xe_gt *gt, const u32 table[], int n_entries);
>> +	void (*dump)(struct xe_gt *gt, struct drm_printer *p);
>>  };
>>
>>  static const u32 xelp_pat_table[] = {
>> @@ -151,12 +155,38 @@ static void program_pat_mcr(struct xe_gt *gt, const u32 table[], int n_entries)
>>  	}
>>  }
>>
>> +void xelp_dump(struct xe_gt *gt, struct drm_printer *p)
>> +{
>> +	struct xe_device *xe = gt_to_xe(gt);
>> +	int i, err;
>> +
>> +	xe_device_mem_access_get(xe);
>> +	err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
>> +	if (err)
>> +		goto err_fw;
>> +
>> +	drm_printf(p, "PAT table:\n");
>> +
>> +	for (i = 0; i < xe->pat.n_entries; i++) {
>> +		u32 pat = xe_mmio_read32(gt, XE_REG(_PAT_INDEX(i)));
>> +
>> +		drm_printf(p, "PAT[%2d] = %#8x\n", i, pat);
>> +	}
>> +
>> +	err = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
>> +err_fw:
>> +	xe_assert(xe, !err);
>> +	xe_device_mem_access_put(xe);
>> +}
>> +
>>  static const struct xe_pat_ops xelp_pat_ops = {
>>  	.program_graphics = program_pat,
>> +	.dump = xelp_dump,
>>  };
>>
>>  static const struct xe_pat_ops xehp_pat_ops = {
>>  	.program_graphics = program_pat_mcr,
>> +	.dump = xelp_dump,
>
>If we use the unicast xelp dumper, some of our reads might happen while
>another thread is steering us to a group/instance that corresponds to a
>fused-off mslice, resulting in 0's instead of the correct values.  We
>probably need an xehp-specific variant that does MCR reads.

ugh... I added the additional dump function while coding this, but
decided to remove since I thought it was the media gt that did the MCR
read. Since we don't have a separate media GT in PVC and DG2 then we
wouldn't need the check. I will add that back

>
>It might also be nice to have an xehpc-specific dumping function that
>does field-based printout ( CLOS, MEM_TYPE ).

ok

>>  };
>>
>>  /*
>> @@ -166,6 +196,7 @@ static const struct xe_pat_ops xehp_pat_ops = {
>>  static const struct xe_pat_ops xelpg_pat_ops = {
>>  	.program_graphics = program_pat,
>>  	.program_media = program_pat_mcr,
>> +	.dump = xelp_dump,
>
>Xe_LPG / Xe_LPM+ need to choose MCR vs non-MCR based on GT type as
>you've done with Xe2 below.  It would also be nice to have field-based
>dump output that presents ( L4_POLICY, COH_MODE ) separately.


ok

thanks
Lucas De Marchi

>
>
>Matt
>
>>  };
>>
>>  static void xe2lpg_program_pat(struct xe_gt *gt, const u32 table[], int n_entries)
>> @@ -180,9 +211,64 @@ static void xe2lpm_program_pat(struct xe_gt *gt, const u32 table[], int n_entrie
>>  	xe_mmio_write32(gt, XE_REG(_PAT_ATS), XE2_PAT_ATS);
>>  }
>>
>> +void xe2_dump(struct xe_gt *gt, struct drm_printer *p)
>> +{
>> +	struct xe_device *xe = gt_to_xe(gt);
>> +	int i, err;
>> +	u32 pat;
>> +
>> +	xe_device_mem_access_get(xe);
>> +	err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
>> +	if (err)
>> +		goto err_fw;
>> +
>> +	drm_printf(p, "PAT table:\n");
>> +
>> +	for (i = 0; i < xe->pat.n_entries; i++) {
>> +		if (xe_gt_is_media_type(gt))
>> +			pat = xe_mmio_read32(gt, XE_REG(_PAT_INDEX(i)));
>> +		else
>> +			pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i)));
>> +
>> +		drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u, %u ]  (%#8x)\n", i,
>> +			   !!(pat & XE2_NO_PROMOTE),
>> +			   !!(pat & XE2_COMP_EN),
>> +			   REG_FIELD_GET(XE2_L3_CLOS, pat),
>> +			   REG_FIELD_GET(XE2_L3_POLICY, pat),
>> +			   REG_FIELD_GET(XE2_L4_POLICY, pat),
>> +			   REG_FIELD_GET(XE2_COH_MODE, pat),
>> +			   pat);
>> +	}
>> +
>> +	/*
>> +	 * Also print PTA_MODE, which describes how the hardware accesses
>> +	 * PPGTT entries.
>> +	 */
>> +	if (xe_gt_is_media_type(gt))
>> +		pat = xe_mmio_read32(gt, XE_REG(_PAT_PTA));
>> +	else
>> +		pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_PTA));
>> +
>> +	drm_printf(p, "Page Table Access:\n");
>> +	drm_printf(p, "PTA_MODE= [ %u, %u, %u, %u, %u, %u ]  (%#8x)\n",
>> +		   !!(pat & XE2_NO_PROMOTE),
>> +		   !!(pat & XE2_COMP_EN),
>> +		   REG_FIELD_GET(XE2_L3_CLOS, pat),
>> +		   REG_FIELD_GET(XE2_L3_POLICY, pat),
>> +		   REG_FIELD_GET(XE2_L4_POLICY, pat),
>> +		   REG_FIELD_GET(XE2_COH_MODE, pat),
>> +		   pat);
>> +
>> +	err = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
>> +err_fw:
>> +	xe_assert(xe, !err);
>> +	xe_device_mem_access_put(xe);
>> +}
>> +
>>  static const struct xe_pat_ops xe2_pat_ops = {
>>  	.program_graphics = xe2lpg_program_pat,
>>  	.program_media = xe2lpm_program_pat,
>> +	.dump = xe2_dump,
>>  };
>>
>>  void xe_pat_init_early(struct xe_device *xe)
>> @@ -252,3 +338,13 @@ void xe_pat_init(struct xe_gt *gt)
>>  	else
>>  		xe->pat.ops->program_graphics(gt, xe->pat.table, xe->pat.n_entries);
>>  }
>> +
>> +void xe_pat_dump(struct xe_gt *gt, struct drm_printer *p)
>> +{
>> +	struct xe_device *xe = gt_to_xe(gt);
>> +
>> +	if (!xe->pat.ops->dump)
>> +		return;
>> +
>> +	xe->pat.ops->dump(gt, p);
>> +}
>> diff --git a/drivers/gpu/drm/xe/xe_pat.h b/drivers/gpu/drm/xe/xe_pat.h
>> index 168e80e63809..09c491ab9f15 100644
>> --- a/drivers/gpu/drm/xe/xe_pat.h
>> +++ b/drivers/gpu/drm/xe/xe_pat.h
>> @@ -6,6 +6,7 @@
>>  #ifndef _XE_PAT_H_
>>  #define _XE_PAT_H_
>>
>> +struct drm_printer;
>>  struct xe_gt;
>>  struct xe_device;
>>
>> @@ -21,4 +22,11 @@ void xe_pat_init_early(struct xe_device *xe);
>>   */
>>  void xe_pat_init(struct xe_gt *gt);
>>
>> +/**
>> + * xe_pat_dump - Dump PAT table
>> + * @gt: GT structure
>> + * @p: Printer to dump info to
>> + */
>> +void xe_pat_dump(struct xe_gt *gt, struct drm_printer *p);
>> +
>>  #endif
>> --
>> 2.40.1
>>
>
>-- 
>Matt Roper
>Graphics Software Engineer
>Linux GPU Platform Enablement
>Intel Corporation


More information about the Intel-xe mailing list