[PATCH] drm/xe: Set LRC addresses before guc load
Matthew Brost
matthew.brost at intel.com
Thu Apr 10 05:36:10 UTC 2025
On Wed, Apr 09, 2025 at 09:59:34PM -0700, Lucas De Marchi wrote:
> The metadata saved in the ADS is read by GuC when it's initialized.
> Saving the addresses to the LRCs when they are populated is too late as
> GuC will keep using the old ones.
>
> This was causing GuC to use the RCS LRC for any engine class. It's not a
> big problem on a Linux-only scenario since the they are used by GuC only
> on media engines when the watchdog is triggered. However, in a
> virtualization scenario with Windows as the VF, it causes the wrong LRCs
> to be loaded as the watchdog is used for all engines.
>
> Fix it by letting guc_golden_lrc_init() initialize the metadata, like
> other *_init() functions, and later guc_golden_lrc_populate() to copy
> the LRCs to the right places. The former is called before the second GuC
> load, while the latter is called after LRCs have been recorded.
>
> Cc: Chee Yin Wong <chee.yin.wong at intel.com>
> Cc: John Harrison <john.c.harrison at intel.com>
> Cc: Matt Roper <matthew.d.roper at intel.com>
> Cc: Matthew Brost <matthew.brost at intel.com>
Fixes tag? Anyways patch LGTM.
Reviewed-by: Matthew Brost <matthew.brost at intel.com>
> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
> ---
> drivers/gpu/drm/xe/xe_guc_ads.c | 75 ++++++++++++++++++++++++-----------------
> 1 file changed, 45 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c
> index 88400f249e614..2a227213c37ff 100644
> --- a/drivers/gpu/drm/xe/xe_guc_ads.c
> +++ b/drivers/gpu/drm/xe/xe_guc_ads.c
> @@ -491,24 +491,52 @@ static void fill_engine_enable_masks(struct xe_gt *gt,
> engine_enable_mask(gt, XE_ENGINE_CLASS_OTHER));
> }
>
> -static void guc_prep_golden_lrc_null(struct xe_guc_ads *ads)
> +/*
> + * Write the offsets corresponding to the golden LRCs. The actual data is
> + * populated later by guc_golden_lrc_populate()
> + */
> +static void guc_golden_lrc_init(struct xe_guc_ads *ads)
> {
> struct xe_device *xe = ads_to_xe(ads);
> + struct xe_gt *gt = ads_to_gt(ads);
> struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(ads_to_map(ads),
> offsetof(struct __guc_ads_blob, system_info));
> - u8 guc_class;
> + size_t alloc_size, real_size;
> + u32 addr_ggtt, offset;
> + int class;
> +
> + offset = guc_ads_golden_lrc_offset(ads);
> + addr_ggtt = xe_bo_ggtt_addr(ads->bo) + offset;
> +
> + for (class = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
> + u8 guc_class;
> +
> + guc_class = xe_engine_class_to_guc_class(class);
>
> - for (guc_class = 0; guc_class <= GUC_MAX_ENGINE_CLASSES; ++guc_class) {
> if (!info_map_read(xe, &info_map,
> engine_enabled_masks[guc_class]))
> continue;
>
> + real_size = xe_gt_lrc_size(gt, class);
> + alloc_size = PAGE_ALIGN(real_size);
> +
> + /*
> + * This interface is slightly confusing. We need to pass the
> + * base address of the full golden context and the size of just
> + * the engine state, which is the section of the context image
> + * that starts after the execlists LRC registers. This is
> + * required to allow the GuC to restore just the engine state
> + * when a watchdog reset occurs.
> + * We calculate the engine state size by removing the size of
> + * what comes before it in the context image (which is identical
> + * on all engines).
> + */
> ads_blob_write(ads, ads.eng_state_size[guc_class],
> - guc_ads_golden_lrc_size(ads) -
> - xe_lrc_skip_size(xe));
> + real_size - xe_lrc_skip_size(xe));
> ads_blob_write(ads, ads.golden_context_lrca[guc_class],
> - xe_bo_ggtt_addr(ads->bo) +
> - guc_ads_golden_lrc_offset(ads));
> + addr_ggtt);
> +
> + addr_ggtt += alloc_size;
> }
> }
>
> @@ -858,7 +886,7 @@ void xe_guc_ads_populate_minimal(struct xe_guc_ads *ads)
>
> xe_map_memset(ads_to_xe(ads), ads_to_map(ads), 0, 0, ads->bo->size);
> guc_policies_init(ads);
> - guc_prep_golden_lrc_null(ads);
> + guc_golden_lrc_init(ads);
> guc_mapping_table_init_invalid(gt, &info_map);
> guc_doorbell_init(ads);
>
> @@ -884,7 +912,7 @@ void xe_guc_ads_populate(struct xe_guc_ads *ads)
> guc_policies_init(ads);
> fill_engine_enable_masks(gt, &info_map);
> guc_mmio_reg_state_init(ads);
> - guc_prep_golden_lrc_null(ads);
> + guc_golden_lrc_init(ads);
> guc_mapping_table_init(gt, &info_map);
> guc_capture_prep_lists(ads);
> guc_doorbell_init(ads);
> @@ -904,18 +932,22 @@ void xe_guc_ads_populate(struct xe_guc_ads *ads)
> guc_ads_private_data_offset(ads));
> }
>
> -static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
> +/*
> + * After the golden LRC's are recorded for each engine class by the first
> + * submission, copy them to the ADS, as initialized earlier by
> + * guc_golden_lrc_init().
> + */
> +static void guc_golden_lrc_populate(struct xe_guc_ads *ads)
> {
> struct xe_device *xe = ads_to_xe(ads);
> struct xe_gt *gt = ads_to_gt(ads);
> struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(ads_to_map(ads),
> offsetof(struct __guc_ads_blob, system_info));
> size_t total_size = 0, alloc_size, real_size;
> - u32 addr_ggtt, offset;
> + u32 offset;
> int class;
>
> offset = guc_ads_golden_lrc_offset(ads);
> - addr_ggtt = xe_bo_ggtt_addr(ads->bo) + offset;
>
> for (class = 0; class < XE_ENGINE_CLASS_MAX; ++class) {
> u8 guc_class;
> @@ -932,26 +964,9 @@ static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
> alloc_size = PAGE_ALIGN(real_size);
> total_size += alloc_size;
>
> - /*
> - * This interface is slightly confusing. We need to pass the
> - * base address of the full golden context and the size of just
> - * the engine state, which is the section of the context image
> - * that starts after the execlists LRC registers. This is
> - * required to allow the GuC to restore just the engine state
> - * when a watchdog reset occurs.
> - * We calculate the engine state size by removing the size of
> - * what comes before it in the context image (which is identical
> - * on all engines).
> - */
> - ads_blob_write(ads, ads.eng_state_size[guc_class],
> - real_size - xe_lrc_skip_size(xe));
> - ads_blob_write(ads, ads.golden_context_lrca[guc_class],
> - addr_ggtt);
> -
> xe_map_memcpy_to(xe, ads_to_map(ads), offset,
> gt->default_lrc[class], real_size);
>
> - addr_ggtt += alloc_size;
> offset += alloc_size;
> }
>
> @@ -960,7 +975,7 @@ static void guc_populate_golden_lrc(struct xe_guc_ads *ads)
>
> void xe_guc_ads_populate_post_load(struct xe_guc_ads *ads)
> {
> - guc_populate_golden_lrc(ads);
> + guc_golden_lrc_populate(ads);
> }
>
> static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_offset)
>
>
>
More information about the Intel-xe
mailing list