[PATCH 5/6] drm/i915/guc: Check the locking status of GuC WOPCM registers

Jackie Li yaodong.li at intel.com
Fri Dec 15 23:38:56 UTC 2017


GuC WOPCM registers are write-once registers. Current driver code
accesses these registers without checking the accessibility to these
registers, this will lead unpredictable driver behaviors if these
registers were touch by other components (such as faulty BIOS code).

This patch moves the GuC WOPCM register updating operations into
intel_guc_wopcm.c and adds checks before and after the write to GuC
WOPCM registers to make sure the driver is in a known state before
and after writing to these write-once registers.

Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
Signed-off-by: Jackie Li <yaodong.li at intel.com>
---
 drivers/gpu/drm/i915/intel_guc_reg.h   |  2 ++
 drivers/gpu/drm/i915/intel_guc_wopcm.c | 45 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_uc.c        |  5 ----
 3 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h
index 1f52fb8..3bb5566 100644
--- a/drivers/gpu/drm/i915/intel_guc_reg.h
+++ b/drivers/gpu/drm/i915/intel_guc_reg.h
@@ -75,6 +75,8 @@
 
 /* Defines WOPCM space available to GuC firmware */
 #define GUC_WOPCM_SIZE			_MMIO(0xc050)
+#define GUC_WOPCM_REG_LOCKED		(1<<0)
+
 
 /* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
 #define GUC_GGTT_TOP			0xFEE00000
diff --git a/drivers/gpu/drm/i915/intel_guc_wopcm.c b/drivers/gpu/drm/i915/intel_guc_wopcm.c
index e23d7a4..4ec4931 100644
--- a/drivers/gpu/drm/i915/intel_guc_wopcm.c
+++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
@@ -89,6 +89,37 @@ static inline int guc_wopcm_size_check(struct intel_guc *guc)
 	return 0;
 }
 
+static inline bool __reg_locked(struct drm_i915_private *dev_priv,
+				 i915_reg_t reg)
+{
+	return !!(I915_READ(reg) & GUC_WOPCM_REG_LOCKED);
+}
+
+static inline bool guc_wopcm_locked(struct intel_guc *guc)
+{
+	struct drm_i915_private *i915 = guc_to_i915(guc);
+	bool size_reg_locked = __reg_locked(i915, GUC_WOPCM_SIZE);
+	bool offset_reg_locked = __reg_locked(i915, DMA_GUC_WOPCM_OFFSET);
+
+	return size_reg_locked && offset_reg_locked;
+}
+
+static inline void guc_wopcm_hw_setup(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+
+	/* GuC WOPCM registers should be unlocked at this point. */
+	GEM_BUG_ON(__reg_locked(dev_priv, GUC_WOPCM_SIZE));
+	GEM_BUG_ON(__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
+
+	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
+	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
+		   guc->wopcm.offset | HUC_LOADING_AGENT_GUC);
+
+	GEM_BUG_ON(!__reg_locked(dev_priv, GUC_WOPCM_SIZE));
+	GEM_BUG_ON(!__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
+}
+
 /*
  * intel_guc_wopcm_init() - Initialize the GuC WOPCM partition.
  * @guc: intel guc.
@@ -104,11 +135,21 @@ int intel_guc_init_wopcm(struct intel_guc *guc, u32 guc_fw_size,
 			 u32 huc_fw_size)
 {
 	u32 reserved = guc_reserved_wopcm_size(guc);
+	u32 locked = guc_wopcm_locked(guc);
 	u32 offset, size, top;
 	int err;
 
-	if (guc->wopcm.valid)
+	if (locked) {
+		/* It's a bug if Locked without a valid GuC WOPCM setting. */
+		GEM_BUG_ON(!guc->wopcm.valid);
+		return 0;
+	}
+
+	/* WOPCM is unlocked, need setup the GuC WOPCM again */
+	if (guc->wopcm.valid) {
+		guc_wopcm_hw_setup(guc);
 		return 0;
+	}
 
 	if (!guc_fw_size)
 		return -EINVAL;
@@ -144,6 +185,8 @@ int intel_guc_init_wopcm(struct intel_guc *guc, u32 guc_fw_size,
 	if (err)
 		return err;
 
+	guc_wopcm_hw_setup(guc);
+
 	guc->wopcm.valid = true;
 
 	DRM_DEBUG_DRIVER("GuC WOPCM offset %dKB, size %dKB, top %dKB\n",
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index f6745f3..8eab01a 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -279,11 +279,6 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv)
 	guc_disable_communication(guc);
 	gen9_reset_guc_interrupts(dev_priv);
 
-	/* init WOPCM */
-	I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
-	I915_WRITE(DMA_GUC_WOPCM_OFFSET,
-		   guc->wopcm.offset | HUC_LOADING_AGENT_GUC);
-
 	/* WaEnableuKernelHeaderValidFix:skl */
 	/* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
 	if (IS_GEN9(dev_priv))
-- 
2.7.4



More information about the Intel-gfx-trybot mailing list