return 0;
}
+/*
+ * Check the registers referenced on a save-restore list and report any
+ * save-restore entries that did not get applied.
+ */
+static int register_save_restore_check(struct xe_gt *gt, struct drm_printer *p)
+{
+ struct xe_hw_engine *hwe;
+ enum xe_hw_engine_id id;
+
+ CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
+ if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) {
+ drm_printf(p, "ERROR: Could not acquire forcewake\n");
+ return -ETIMEDOUT;
+ }
+
+ xe_reg_sr_readback_check(>->reg_sr, gt, p);
+ for_each_hw_engine(hwe, gt, id)
+ xe_reg_sr_readback_check(&hwe->reg_sr, gt, p);
+
+ /* TODO: Check hwe->reg_lrc against contents of default_lrc. */
+
+ return 0;
+}
+
static int rcs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
{
xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_RENDER);
{ "default_lrc_vecs", .show = xe_gt_debugfs_show_with_rpm, .data = vecs_default_lrc },
{ "hwconfig", .show = xe_gt_debugfs_show_with_rpm, .data = hwconfig },
{ "pat_sw_config", .show = xe_gt_debugfs_simple_show, .data = xe_pat_dump_sw_config },
+ { "register-save-restore-check",
+ .show = xe_gt_debugfs_show_with_rpm, .data = register_save_restore_check },
};
/* everything else should be added here */
str_yes_no(entry->reg.masked),
str_yes_no(entry->reg.mcr));
}
+
+static u32 readback_reg(struct xe_gt *gt, struct xe_reg reg)
+{
+ struct xe_reg_mcr mcr_reg = to_xe_reg_mcr(reg);
+
+ if (reg.mcr)
+ return xe_gt_mcr_unicast_read_any(gt, mcr_reg);
+ else
+ return xe_mmio_read32(>->mmio, reg);
+}
+
+/**
+ * xe_reg_sr_readback_check() - Readback registers referenced in save/restore
+ * entries and check whether the programming is in place.
+ * @sr: Save/restore entries
+ * @gt: GT to read register from
+ * @p: DRM printer to report discrepancies on
+ */
+void xe_reg_sr_readback_check(struct xe_reg_sr *sr,
+ struct xe_gt *gt,
+ struct drm_printer *p)
+{
+ struct xe_reg_sr_entry *entry;
+ unsigned long offset;
+
+ xa_for_each(&sr->xa, offset, entry) {
+ u32 val = readback_reg(gt, entry->reg);
+ u32 mask = entry->clr_bits | entry->set_bits;
+
+ if ((val & mask) != entry->set_bits)
+ drm_printf(p, "%#8lx & %#10x :: expected %#10x got %#10x\n",
+ offset, mask, entry->set_bits, val & mask);
+ }
+}
int xe_reg_sr_init(struct xe_reg_sr *sr, const char *name, struct xe_device *xe);
void xe_reg_sr_dump(struct xe_reg_sr *sr, struct drm_printer *p);
+void xe_reg_sr_readback_check(struct xe_reg_sr *sr,
+ struct xe_gt *gt,
+ struct drm_printer *p);
int xe_reg_sr_add(struct xe_reg_sr *sr, const struct xe_reg_sr_entry *e,
struct xe_gt *gt);