Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe: Apply whitelist to engine save-restore

Instead of handling the whitelist directly in the GuC ADS
initialization, make it follow the same logic as other engine registers
that are save-restored. Main benefit is that then the SW tracking then
shows it in debugfs and there's no risk of an engine workaround to write
to the same nopriv register that is being passed directly to GuC.

This means that xe_reg_whitelist_process_engine() only has to process
the RTP and convert them to entries for the hwe. With that all the
registers should be covered by xe_reg_sr_apply_mmio() to write to the HW
and there's no special handling in GuC ADS to also add these registers
to the list of registers that is passed to GuC.

Example for DG2:

# cat /sys/kernel/debug/dri/0000\:03\:00.0/gt0/register-save-restore
...
Engine
rcs0
...
REG[0x24d0] clr=0xffffffff set=0x1000dafc masked=no mcr=no
REG[0x24d4] clr=0xffffffff set=0x1000db01 masked=no mcr=no
REG[0x24d8] clr=0xffffffff set=0x0000db1c masked=no mcr=no
...
Whitelist
rcs0
REG[0xdafc-0xdaff]: allow read access
REG[0xdb00-0xdb1f]: allow read access
REG[0xdb1c-0xdb1f]: allow rw access

v2:
- Use ~0u for clr bits so it's just a write (Matt Roper)
- Simplify helpers now that unused slots are not written

Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241209232739.147417-6-lucas.demarchi@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>

+38 -56
+1 -3
drivers/gpu/drm/xe/xe_gt.c
··· 748 748 if (err) 749 749 return err; 750 750 751 - for_each_hw_engine(hwe, gt, id) { 751 + for_each_hw_engine(hwe, gt, id) 752 752 xe_reg_sr_apply_mmio(&hwe->reg_sr, gt); 753 - xe_reg_sr_apply_whitelist(hwe); 754 - } 755 753 756 754 /* Get CCS mode in sync between sw/hw */ 757 755 xe_gt_apply_ccs_mode(gt);
-7
drivers/gpu/drm/xe/xe_guc_ads.c
··· 243 243 xa_for_each(&hwe->reg_sr.xa, sr_idx, sr_entry) 244 244 count++; 245 245 246 - count += RING_MAX_NONPRIV_SLOTS * XE_NUM_HW_ENGINES; 247 - 248 246 count += ADS_REGSET_EXTRA_MAX * XE_NUM_HW_ENGINES; 249 247 250 248 if (XE_WA(gt, 1607983814)) ··· 726 728 727 729 xa_for_each(&hwe->reg_sr.xa, idx, entry) 728 730 guc_mmio_regset_write_one(ads, regset_map, entry->reg, count++); 729 - 730 - for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) 731 - guc_mmio_regset_write_one(ads, regset_map, 732 - RING_FORCE_TO_NONPRIV(hwe->mmio_base, i), 733 - count++); 734 731 735 732 for (e = extra_regs; e < extra_regs + ARRAY_SIZE(extra_regs); e++) { 736 733 if (e->skip)
-1
drivers/gpu/drm/xe/xe_hw_engine.c
··· 574 574 xe_gt_assert(gt, gt->info.engine_mask & BIT(id)); 575 575 576 576 xe_reg_sr_apply_mmio(&hwe->reg_sr, gt); 577 - xe_reg_sr_apply_whitelist(hwe); 578 577 579 578 hwe->hwsp = xe_managed_bo_create_pin_map(xe, tile, SZ_4K, 580 579 XE_BO_FLAG_VRAM_IF_DGFX(tile) |
-45
drivers/gpu/drm/xe/xe_reg_sr.c
··· 24 24 #include "xe_hw_engine_types.h" 25 25 #include "xe_macros.h" 26 26 #include "xe_mmio.h" 27 - #include "xe_reg_whitelist.h" 28 27 #include "xe_rtp_types.h" 29 28 30 29 static void reg_sr_fini(struct drm_device *drm, void *arg) ··· 181 182 182 183 xa_for_each(&sr->xa, reg, entry) 183 184 apply_one_mmio(gt, entry); 184 - 185 - xe_force_wake_put(gt_to_fw(gt), fw_ref); 186 - 187 - return; 188 - 189 - err_force_wake: 190 - xe_force_wake_put(gt_to_fw(gt), fw_ref); 191 - xe_gt_err(gt, "Failed to apply, err=-ETIMEDOUT\n"); 192 - } 193 - 194 - void xe_reg_sr_apply_whitelist(struct xe_hw_engine *hwe) 195 - { 196 - struct xe_reg_sr *sr = &hwe->reg_whitelist; 197 - struct xe_gt *gt = hwe->gt; 198 - struct xe_reg_sr_entry *entry; 199 - struct drm_printer p; 200 - u32 mmio_base = hwe->mmio_base; 201 - unsigned long reg; 202 - unsigned int slot = 0; 203 - unsigned int fw_ref; 204 - 205 - if (xa_empty(&sr->xa)) 206 - return; 207 - 208 - xe_gt_dbg(gt, "Whitelisting %s registers\n", sr->name); 209 - 210 - fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 211 - if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) 212 - goto err_force_wake; 213 - 214 - p = xe_gt_dbg_printer(gt); 215 - xa_for_each(&sr->xa, reg, entry) { 216 - if (slot == RING_MAX_NONPRIV_SLOTS) { 217 - xe_gt_err(gt, 218 - "hwe %s: maximum register whitelist slots (%d) reached, refusing to add more\n", 219 - hwe->name, RING_MAX_NONPRIV_SLOTS); 220 - break; 221 - } 222 - 223 - xe_reg_whitelist_print_entry(&p, 0, reg, entry); 224 - xe_mmio_write32(&gt->mmio, RING_FORCE_TO_NONPRIV(mmio_base, slot), 225 - reg | entry->set_bits); 226 - slot++; 227 - } 228 185 229 186 xe_force_wake_put(gt_to_fw(gt), fw_ref); 230 187
+37
drivers/gpu/drm/xe/xe_reg_whitelist.c
··· 10 10 #include "regs/xe_oa_regs.h" 11 11 #include "regs/xe_regs.h" 12 12 #include "xe_gt_types.h" 13 + #include "xe_gt_printk.h" 13 14 #include "xe_platform_types.h" 15 + #include "xe_reg_sr.h" 14 16 #include "xe_rtp.h" 15 17 #include "xe_step.h" 16 18 ··· 91 89 {} 92 90 }; 93 91 92 + static void whitelist_apply_to_hwe(struct xe_hw_engine *hwe) 93 + { 94 + struct xe_reg_sr *sr = &hwe->reg_whitelist; 95 + struct xe_reg_sr_entry *entry; 96 + struct drm_printer p; 97 + unsigned long reg; 98 + unsigned int slot; 99 + 100 + xe_gt_dbg(hwe->gt, "Add %s whitelist to engine\n", sr->name); 101 + p = xe_gt_dbg_printer(hwe->gt); 102 + 103 + slot = 0; 104 + xa_for_each(&sr->xa, reg, entry) { 105 + struct xe_reg_sr_entry hwe_entry = { 106 + .reg = RING_FORCE_TO_NONPRIV(hwe->mmio_base, slot), 107 + .set_bits = entry->reg.addr | entry->set_bits, 108 + .clr_bits = ~0u, 109 + .read_mask = entry->read_mask, 110 + }; 111 + 112 + if (slot == RING_MAX_NONPRIV_SLOTS) { 113 + xe_gt_err(hwe->gt, 114 + "hwe %s: maximum register whitelist slots (%d) reached, refusing to add more\n", 115 + hwe->name, RING_MAX_NONPRIV_SLOTS); 116 + break; 117 + } 118 + 119 + xe_reg_whitelist_print_entry(&p, 0, reg, entry); 120 + xe_reg_sr_add(&hwe->reg_sr, &hwe_entry, hwe->gt); 121 + 122 + slot++; 123 + } 124 + } 125 + 94 126 /** 95 127 * xe_reg_whitelist_process_engine - process table of registers to whitelist 96 128 * @hwe: engine instance to process whitelist for ··· 138 102 struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe); 139 103 140 104 xe_rtp_process_to_sr(&ctx, register_whitelist, &hwe->reg_whitelist); 105 + whitelist_apply_to_hwe(hwe); 141 106 } 142 107 143 108 /**