[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20120103223321.582682324@clark.kroah.org>
Date: Tue, 03 Jan 2012 14:32:40 -0800
From: Greg KH <gregkh@...e.de>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
Cc: torvalds@...ux-foundation.org, akpm@...ux-foundation.org,
alan@...rguk.ukuu.org.uk, Jesse Barnes <jbarnes@...tuousgeek.org>,
Keith Packard <keithp@...thp.com>,
Eugeni Dodonov <eugeni.dodonov@...el.com>
Subject: [07/75] drm/i915: prevent division by zero when asking for chipset power
3.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugeni Dodonov <eugeni.dodonov@...el.com>
commit 4ed0b577457eb6aeb7cdc7e7316576e63d15abb2 upstream.
This prevents an in-kernel division by zero which happens when we are
asking for i915_chipset_val too quickly, or within a race condition
between the power monitoring thread and userspace accesses via debugfs.
The issue can be reproduced easily via the following command:
while ``; do cat /sys/kernel/debug/dri/0/i915_emon_status; done
This is particularly dangerous because it can be triggered by
a non-privileged user by just reading the debugfs entry.
This issue was also found independently by Konstantin Belousov
<kostikbel@...il.com>, who proposed a similar patch.
Reported-by: Konstantin Belousov <kostikbel@...il.com>
Acked-by: Jesse Barnes <jbarnes@...tuousgeek.org>
Acked-by: Keith Packard <keithp@...thp.com>
Reviewed-by: Chris Wilson <chris@...is-wilson.co.uk>
Signed-off-by: Eugeni Dodonov <eugeni.dodonov@...el.com>
Signed-off-by: Keith Packard <keithp@...thp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de>
---
drivers/gpu/drm/i915/i915_dma.c | 10 ++++++++++
drivers/gpu/drm/i915/i915_drv.h | 1 +
2 files changed, 11 insertions(+)
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1453,6 +1453,14 @@ unsigned long i915_chipset_val(struct dr
diff1 = now - dev_priv->last_time1;
+ /* Prevent division-by-zero if we are asking too fast.
+ * Also, we don't get interesting results if we are polling
+ * faster than once in 10ms, so just return the saved value
+ * in such cases.
+ */
+ if (diff1 <= 10)
+ return dev_priv->chipset_power;
+
count1 = I915_READ(DMIEC);
count2 = I915_READ(DDREC);
count3 = I915_READ(CSIEC);
@@ -1483,6 +1491,8 @@ unsigned long i915_chipset_val(struct dr
dev_priv->last_count1 = total_count;
dev_priv->last_time1 = now;
+ dev_priv->chipset_power = ret;
+
return ret;
}
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -707,6 +707,7 @@ typedef struct drm_i915_private {
u64 last_count1;
unsigned long last_time1;
+ unsigned long chipset_power;
u64 last_count2;
struct timespec last_time2;
unsigned long gfx_power;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists