diff mbox

[10/10] drm/i915: Disable use of stolen area by User when Intel RST is present

Message ID 1453751016-8713-11-git-send-email-ankitprasad.r.sharma@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

ankitprasad.r.sharma@intel.com Jan. 25, 2016, 7:43 p.m. UTC
From: Ankitprasad Sharma <ankitprasad.r.sharma@intel.com>

The BIOS RapidStartTechnology may corrupt the stolen memory across S3
suspend due to unalarmed hibernation, in which case we will not be able
to preserve the User data stored in the stolen region. Hence this patch
tries to identify presence of the RST device on the ACPI bus, and
disables use of stolen memory (for persistent data) if found.

v2: Updated comment, updated/corrected new functions private to driver
(Chris/Tvrtko)

v3: Disabling stolen by default, wait till required acpi changes to
detect device presence are pulled in (Ankit)

Signed-off-by: Ankitprasad Sharma <ankitprasad.r.sharma@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h        | 11 +++++++++++
 drivers/gpu/drm/i915/i915_gem.c        |  8 ++++++++
 drivers/gpu/drm/i915/i915_gem_stolen.c | 14 ++++++++++++++
 drivers/gpu/drm/i915/intel_acpi.c      | 10 ++++++++++
 4 files changed, 43 insertions(+)

Comments

Chris Wilson Jan. 26, 2016, 11:36 a.m. UTC | #1
On Tue, Jan 26, 2016 at 01:13:36AM +0530, ankitprasad.r.sharma@intel.com wrote:
> From: Ankitprasad Sharma <ankitprasad.r.sharma@intel.com>
> 
> The BIOS RapidStartTechnology may corrupt the stolen memory across S3
> suspend due to unalarmed hibernation, in which case we will not be able
> to preserve the User data stored in the stolen region. Hence this patch
> tries to identify presence of the RST device on the ACPI bus, and
> disables use of stolen memory (for persistent data) if found.
> 
> v2: Updated comment, updated/corrected new functions private to driver
> (Chris/Tvrtko)
> 
> v3: Disabling stolen by default, wait till required acpi changes to
> detect device presence are pulled in (Ankit)
> 
> Signed-off-by: Ankitprasad Sharma <ankitprasad.r.sharma@intel.com>

Ideally this would be earlier in the sequence so that we don't introduce
the new API will a known problem.


> ---
>  drivers/gpu/drm/i915/i915_drv.h        | 11 +++++++++++
>  drivers/gpu/drm/i915/i915_gem.c        |  8 ++++++++
>  drivers/gpu/drm/i915/i915_gem_stolen.c | 14 ++++++++++++++
>  drivers/gpu/drm/i915/intel_acpi.c      | 10 ++++++++++
>  4 files changed, 43 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index d77d2ed..8037609 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1311,6 +1311,16 @@ struct i915_gem_mm {
>  	 */
>  	bool busy;
>  
> +	/**
> +	 * Stolen will be lost upon hibernate (as the memory is unpowered).
> +	 * Across resume, we expect stolen to be intact - however, it may
> +	 * also be utililised by third parties (e.g. Intel RapidStart
> +	 * Technology) and if so we have to assume that any data stored in
> +	 * stolen across resume is lost and we set this flag to indicate that
> +	 * the stolen memory is volatile.
> +	 */
> +	bool nonvolatile_stolen;
> +
>  	/* the indicator for dispatch video commands on two BSD rings */
>  	unsigned int bsd_ring_dispatch_index;
>  
> @@ -3418,6 +3428,7 @@ intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
>  #endif
>  
>  /* intel_acpi.c */
> +bool intel_detect_acpi_rst(void);
>  #ifdef CONFIG_ACPI
>  extern void intel_register_dsm_handler(void);
>  extern void intel_unregister_dsm_handler(void);
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 9dcefb1..f7c9420 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -396,8 +396,16 @@ static struct drm_i915_gem_object *
>  i915_gem_alloc_object_stolen(struct drm_device *dev, size_t size)
>  {
>  	struct drm_i915_gem_object *obj;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;
>  
> +	if (!dev_priv->mm.nonvolatile_stolen) {
> +		/* Stolen may be overwritten by external parties
> +		 * so unsuitable for persistent user data.
> +		 */
> +		return ERR_PTR(-ENODEV);
> +	}
> +
>  	mutex_lock(&dev->struct_mutex);
>  	obj = i915_gem_object_create_stolen(dev, size);
>  	if (IS_ERR(obj))
> diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
> index 335a1ef..4f44531 100644
> --- a/drivers/gpu/drm/i915/i915_gem_stolen.c
> +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
> @@ -482,6 +482,20 @@ int i915_gem_init_stolen(struct drm_device *dev)
>  	 */
>  	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size);
>  
> +	/* If the stolen region can be modified behind our backs upon suspend,
> +	 * then we cannot use it to store nonvolatile contents (i.e user data)
> +	 * as it will be corrupted upon resume.
> +	 */
> +	dev_priv->mm.nonvolatile_stolen = true;
> +#ifdef CONFIG_SUSPEND
> +	if (intel_detect_acpi_rst()) {
> +		/* BIOSes using RapidStart Technology have been reported
> +		 * to overwrite stolen across S3, not just S4.
> +		 */
> +		dev_priv->mm.nonvolatile_stolen = false;
> +	}
> +#endif
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
> index eb638a1..8add47d 100644
> --- a/drivers/gpu/drm/i915/intel_acpi.c
> +++ b/drivers/gpu/drm/i915/intel_acpi.c
> @@ -23,6 +23,11 @@ static const u8 intel_dsm_guid[] = {
>  	0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c
>  };
>  
> +static const struct acpi_device_id irst_ids[] = {
> +	{"INT3392", 0},
> +	{"", 0}
> +};

Dead code (atm).

> +
>  static char *intel_dsm_port_name(u8 id)
>  {
>  	switch (id) {
> @@ -162,3 +167,8 @@ void intel_register_dsm_handler(void)
>  void intel_unregister_dsm_handler(void)
>  {
>  }
> +
> +bool intel_detect_acpi_rst(void)
> +{

/* Explain why this code is dead or else we will remove it! */
> +	return true;
> +}
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d77d2ed..8037609 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1311,6 +1311,16 @@  struct i915_gem_mm {
 	 */
 	bool busy;
 
+	/**
+	 * Stolen will be lost upon hibernate (as the memory is unpowered).
+	 * Across resume, we expect stolen to be intact - however, it may
+	 * also be utililised by third parties (e.g. Intel RapidStart
+	 * Technology) and if so we have to assume that any data stored in
+	 * stolen across resume is lost and we set this flag to indicate that
+	 * the stolen memory is volatile.
+	 */
+	bool nonvolatile_stolen;
+
 	/* the indicator for dispatch video commands on two BSD rings */
 	unsigned int bsd_ring_dispatch_index;
 
@@ -3418,6 +3428,7 @@  intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
 #endif
 
 /* intel_acpi.c */
+bool intel_detect_acpi_rst(void);
 #ifdef CONFIG_ACPI
 extern void intel_register_dsm_handler(void);
 extern void intel_unregister_dsm_handler(void);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9dcefb1..f7c9420 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -396,8 +396,16 @@  static struct drm_i915_gem_object *
 i915_gem_alloc_object_stolen(struct drm_device *dev, size_t size)
 {
 	struct drm_i915_gem_object *obj;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	if (!dev_priv->mm.nonvolatile_stolen) {
+		/* Stolen may be overwritten by external parties
+		 * so unsuitable for persistent user data.
+		 */
+		return ERR_PTR(-ENODEV);
+	}
+
 	mutex_lock(&dev->struct_mutex);
 	obj = i915_gem_object_create_stolen(dev, size);
 	if (IS_ERR(obj))
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 335a1ef..4f44531 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -482,6 +482,20 @@  int i915_gem_init_stolen(struct drm_device *dev)
 	 */
 	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size);
 
+	/* If the stolen region can be modified behind our backs upon suspend,
+	 * then we cannot use it to store nonvolatile contents (i.e user data)
+	 * as it will be corrupted upon resume.
+	 */
+	dev_priv->mm.nonvolatile_stolen = true;
+#ifdef CONFIG_SUSPEND
+	if (intel_detect_acpi_rst()) {
+		/* BIOSes using RapidStart Technology have been reported
+		 * to overwrite stolen across S3, not just S4.
+		 */
+		dev_priv->mm.nonvolatile_stolen = false;
+	}
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index eb638a1..8add47d 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -23,6 +23,11 @@  static const u8 intel_dsm_guid[] = {
 	0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c
 };
 
+static const struct acpi_device_id irst_ids[] = {
+	{"INT3392", 0},
+	{"", 0}
+};
+
 static char *intel_dsm_port_name(u8 id)
 {
 	switch (id) {
@@ -162,3 +167,8 @@  void intel_register_dsm_handler(void)
 void intel_unregister_dsm_handler(void)
 {
 }
+
+bool intel_detect_acpi_rst(void)
+{
+	return true;
+}