Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2019-09-17 16:30:03 +0200
committerTakashi Iwai <tiwai@suse.de>2019-11-07 17:25:21 +0100
commitaf0d6049fe64ffb47b0863b3d3ec168b4982fa92 (patch)
tree92046a3c05c5223341b7d0f60426cf6d39b2aead
parentf4e587a2743d29b431d4e5a1a68ffebf7ffbbef2 (diff)
drm/i915/gen8+: Add RC6 CTX corruption WA (bsc#1135967)
-rw-r--r--patches.suse/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch285
-rw-r--r--series.conf1
2 files changed, 286 insertions, 0 deletions
diff --git a/patches.suse/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch b/patches.suse/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch
new file mode 100644
index 0000000000..69c4d42b82
--- /dev/null
+++ b/patches.suse/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch
@@ -0,0 +1,285 @@
+From 723b01a21a3f37002013f452780ea9f0490c593b Mon Sep 17 00:00:00 2001
+From: Imre Deak <imre.deak@intel.com>
+Date: Mon, 9 Jul 2018 18:24:27 +0300
+Subject: [PATCH 12/12] drm/i915/gen8+: Add RC6 CTX corruption WA
+References: CVE-2019-0154,bsc#1135966,CVE-2019-0155,bsc#1135967
+Patch-mainline: Not yet, embargoed
+
+In some circumstances the RC6 context can get corrupted. We can detect
+this and take the required action, that is disable RC6 and runtime PM.
+The HW recovers from the corrupted state after a system suspend/resume
+cycle, so detect the recovery and re-enable RC6 and runtime PM.
+
+V2: rebase (Mika)
+V3:
+- Move intel_suspend_gt_powersave() to the end of the GEM suspend
+ sequence.
+- Add commit message.
+V4:
+- Rebased on intel_uncore_forcewake_put(i915->uncore, ...) API
+ change.
+V5:
+- Rebased on latest upstream gt_pm refactoring.
+
+Signed-off-by: Imre Deak <imre.deak@intel.com>
+Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_drv.c | 3 +
+ drivers/gpu/drm/i915/i915_drv.h | 7 +-
+ drivers/gpu/drm/i915/i915_gem.c | 8 ++
+ drivers/gpu/drm/i915/i915_reg.h | 2
+ drivers/gpu/drm/i915/intel_drv.h | 3 +
+ drivers/gpu/drm/i915/intel_pm.c | 107 ++++++++++++++++++++++++++++++++++++++-
+ 6 files changed, 126 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
+@@ -1658,6 +1658,7 @@ static int i915_drm_suspend_late(struct
+ i915_gem_suspend_late(dev_priv);
+
+ intel_display_set_init_power(dev_priv, false);
++ i915_rc6_ctx_wa_suspend(dev_priv);
+ intel_uncore_suspend(dev_priv);
+
+ /*
+@@ -1884,6 +1885,8 @@ static int i915_drm_resume_early(struct
+ else
+ intel_display_set_init_power(dev_priv, true);
+
++ i915_rc6_ctx_wa_resume(dev_priv);
++
+ intel_engines_sanitize(dev_priv);
+
+ enable_rpm_wakeref_asserts(dev_priv);
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -801,6 +801,7 @@ struct intel_rps {
+
+ struct intel_rc6 {
+ bool enabled;
++ bool ctx_corrupted;
+ u64 prev_hw_residency[4];
+ u64 cur_residency[4];
+ };
+@@ -2648,10 +2649,12 @@ IS_SUBPLATFORM(const struct drm_i915_pri
+ /* Early gen2 have a totally busted CS tlb and require pinned batches. */
+ #define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv))
+
++#define NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv) \
++ (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) == 9)
++
+ /* WaRsDisableCoarsePowerGating:skl,cnl */
+ #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
+- (IS_CANNONLAKE(dev_priv) || \
+- IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
++ (IS_CANNONLAKE(dev_priv) || INTEL_GEN(dev_priv) == 9)
+
+ #define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4)
+ #define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \
+--- a/drivers/gpu/drm/i915/i915_gem.c
++++ b/drivers/gpu/drm/i915/i915_gem.c
+@@ -174,6 +174,11 @@ static u32 __i915_gem_park(struct drm_i9
+ if (INTEL_GEN(i915) >= 6)
+ gen6_rps_idle(i915);
+
++ if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) {
++ i915_rc6_ctx_wa_check(i915);
++ intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
++ }
++
+ intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
+
+ intel_runtime_pm_put(i915);
+@@ -220,6 +225,9 @@ void i915_gem_unpark(struct drm_i915_pri
+ */
+ intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
+
++ if (NEEDS_RC6_CTX_CORRUPTION_WA(i915))
++ intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
++
+ i915->gt.awake = true;
+ if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
+ i915->gt.epoch = 1;
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -389,6 +389,8 @@ static inline bool i915_mmio_reg_valid(i
+ #define ECOCHK_PPGTT_WT_HSW (0x2 << 3)
+ #define ECOCHK_PPGTT_WB_HSW (0x3 << 3)
+
++#define GEN8_RC6_CTX_INFO _MMIO(0x8504)
++
+ #define GAC_ECO_BITS _MMIO(0x14090)
+ #define ECOBITS_SNB_BIT (1 << 13)
+ #define ECOBITS_PPGTT_CACHE64B (3 << 8)
+--- a/drivers/gpu/drm/i915/intel_drv.h
++++ b/drivers/gpu/drm/i915/intel_drv.h
+@@ -2075,6 +2075,9 @@ void intel_sanitize_gt_powersave(struct
+ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv);
+ void intel_disable_gt_powersave(struct drm_i915_private *dev_priv);
+ void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv);
++bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915);
++void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915);
++void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915);
+ void gen6_rps_busy(struct drm_i915_private *dev_priv);
+ void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
+ void gen6_rps_idle(struct drm_i915_private *dev_priv);
+--- a/drivers/gpu/drm/i915/intel_pm.c
++++ b/drivers/gpu/drm/i915/intel_pm.c
+@@ -8202,6 +8202,95 @@ static void intel_init_emon(struct drm_i
+ dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK);
+ }
+
++static bool i915_rc6_ctx_corrupted(struct drm_i915_private *dev_priv)
++{
++ return !I915_READ(GEN8_RC6_CTX_INFO);
++}
++
++static void i915_rc6_ctx_wa_init(struct drm_i915_private *i915)
++{
++ if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
++ return;
++
++ if (i915_rc6_ctx_corrupted(i915)) {
++ DRM_INFO("RC6 context corrupted, disabling runtime power management\n");
++ i915->gt_pm.rc6.ctx_corrupted = true;
++ intel_runtime_pm_get(i915);
++ }
++}
++
++static void i915_rc6_ctx_wa_cleanup(struct drm_i915_private *i915)
++{
++ if (i915->gt_pm.rc6.ctx_corrupted) {
++ intel_runtime_pm_put(i915);
++ i915->gt_pm.rc6.ctx_corrupted = false;
++ }
++}
++
++/**
++ * i915_rc6_ctx_wa_suspend - system suspend sequence for the RC6 CTX WA
++ * @i915: i915 device
++ *
++ * Perform any steps needed to clean up the RC6 CTX WA before system suspend.
++ */
++void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915)
++{
++ if (i915->gt_pm.rc6.ctx_corrupted)
++ intel_runtime_pm_put(i915);
++}
++
++/**
++ * i915_rc6_ctx_wa_resume - system resume sequence for the RC6 CTX WA
++ * @i915: i915 device
++ *
++ * Perform any steps needed to re-init the RC6 CTX WA after system resume.
++ */
++void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915)
++{
++ if (!i915->gt_pm.rc6.ctx_corrupted)
++ return;
++
++ if (i915_rc6_ctx_corrupted(i915)) {
++ intel_runtime_pm_get(i915);
++ return;
++ }
++
++ DRM_INFO("RC6 context restored, re-enabling runtime power management\n");
++ i915->gt_pm.rc6.ctx_corrupted = false;
++}
++
++static void intel_disable_rc6(struct drm_i915_private *dev_priv);
++
++/**
++ * i915_rc6_ctx_wa_check - check for a new RC6 CTX corruption
++ * @i915: i915 device
++ *
++ * Check if an RC6 CTX corruption has happened since the last check and if so
++ * disable RC6 and runtime power management.
++ *
++ * Return false if no context corruption has happened since the last call of
++ * this function, true otherwise.
++*/
++bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915)
++{
++ if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
++ return false;
++
++ if (i915->gt_pm.rc6.ctx_corrupted)
++ return false;
++
++ if (!i915_rc6_ctx_corrupted(i915))
++ return false;
++
++ DRM_NOTE("RC6 context corruption, disabling runtime power management\n");
++
++ intel_disable_rc6(i915);
++ i915->gt_pm.rc6.ctx_corrupted = true;
++ intel_runtime_pm_get_noresume(i915);
++
++ return true;
++}
++
+ void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
+ {
+ struct intel_rps *rps = &dev_priv->gt_pm.rps;
+@@ -8217,6 +8306,8 @@ void intel_init_gt_powersave(struct drm_
+
+ mutex_lock(&dev_priv->pcu_lock);
+
++ i915_rc6_ctx_wa_init(dev_priv);
++
+ /* Initialize RPS limits (for userspace) */
+ if (IS_CHERRYVIEW(dev_priv))
+ cherryview_init_gt_powersave(dev_priv);
+@@ -8263,6 +8354,8 @@ void intel_cleanup_gt_powersave(struct d
+ if (IS_VALLEYVIEW(dev_priv))
+ valleyview_cleanup_gt_powersave(dev_priv);
+
++ i915_rc6_ctx_wa_cleanup(dev_priv);
++
+ if (!HAS_RC6(dev_priv))
+ intel_runtime_pm_put(dev_priv);
+ }
+@@ -8307,7 +8400,7 @@ static inline void intel_disable_llc_pst
+ i915->gt_pm.llc_pstate.enabled = false;
+ }
+
+-static void intel_disable_rc6(struct drm_i915_private *dev_priv)
++static void __intel_disable_rc6(struct drm_i915_private *dev_priv)
+ {
+ lockdep_assert_held(&dev_priv->pcu_lock);
+
+@@ -8326,6 +8419,13 @@ static void intel_disable_rc6(struct drm
+ dev_priv->gt_pm.rc6.enabled = false;
+ }
+
++static void intel_disable_rc6(struct drm_i915_private *dev_priv)
++{
++ mutex_lock(&dev_priv->pcu_lock);
++ __intel_disable_rc6(dev_priv);
++ mutex_unlock(&dev_priv->pcu_lock);
++}
++
+ static void intel_disable_rps(struct drm_i915_private *dev_priv)
+ {
+ lockdep_assert_held(&dev_priv->pcu_lock);
+@@ -8351,7 +8451,7 @@ void intel_disable_gt_powersave(struct d
+ {
+ mutex_lock(&dev_priv->pcu_lock);
+
+- intel_disable_rc6(dev_priv);
++ __intel_disable_rc6(dev_priv);
+ intel_disable_rps(dev_priv);
+ if (HAS_LLC(dev_priv))
+ intel_disable_llc_pstate(dev_priv);
+@@ -8378,6 +8478,9 @@ static void intel_enable_rc6(struct drm_
+ if (dev_priv->gt_pm.rc6.enabled)
+ return;
+
++ if (dev_priv->gt_pm.rc6.ctx_corrupted)
++ return;
++
+ if (IS_CHERRYVIEW(dev_priv))
+ cherryview_enable_rc6(dev_priv);
+ else if (IS_VALLEYVIEW(dev_priv))
diff --git a/series.conf b/series.conf
index ec047f37ab..ba9b984bf6 100644
--- a/series.conf
+++ b/series.conf
@@ -49951,6 +49951,7 @@
patches.suse/0009-drm-i915-cmdparser-Add-support-for-backward-jumps.patch
patches.suse/0010-drm-i915-cmdparser-Ignore-Length-operands-during-com.patch
patches.suse/0011-drm-i915-Lower-RM-timeout-to-avoid-DSI-hard-hangs.patch
+ patches.suse/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch
########################################################
# end of sorted patches