[Intel-gfx] [PATCH 1/2] intel_gpu_top: Skip head/tail reads on HSW
Ben Widawsky
ben at bwidawsk.net
Mon Feb 22 02:23:57 UTC 2016
Haswell has a known issue when doing concurrent reads of MMIO (see reference for
details). This issue results in a system wide unrecoverable hang. As this tool
is shipped by default in the IGT package, this is a very mean behavior to
accidentally impose on the user.
This patch shuts this behavior down by default on HSW, and prints a warning. An
upcoming patch will provide an override for the insane.
References: https://lists.freedesktop.org/archives/mesa-dev/2013-July/041692.html
Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
man/intel_gpu_top.man | 2 ++
tools/intel_gpu_top.c | 28 +++++++++++++++++++++++-----
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/man/intel_gpu_top.man b/man/intel_gpu_top.man
index b307a23..d90a7ee 100644
--- a/man/intel_gpu_top.man
+++ b/man/intel_gpu_top.man
@@ -39,3 +39,5 @@ header.
.SH BUGS
Some GPUs report some units as busy when they aren't, such that even when
idle and not hung, it will show up as 100% busy.
+.TP
+Haswell GPU may hang when trying to determine ring busyness, and so it is disabled by default.
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 4f327c6..33a8e0c 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -316,6 +316,7 @@ struct ring {
int head, tail, size;
uint64_t full;
int idle;
+ bool skip_ring_reads;
};
static uint32_t ring_read(struct ring *ring, uint32_t reg)
@@ -323,9 +324,14 @@ static uint32_t ring_read(struct ring *ring, uint32_t reg)
return INREG(ring->mmio + reg);
}
-static void ring_init(struct ring *ring)
+static void ring_init(struct ring *ring, uint32_t devid)
{
ring->size = (((ring_read(ring, RING_LEN) & RING_NR_PAGES) >> 12) + 1) * 4096;
+
+ if (IS_HASWELL(devid)) {
+ fprintf(stderr, "Skipping reads of head, and tail registers to avoid hangs\n");
+ ring->skip_ring_reads = true;
+ }
}
static void ring_reset(struct ring *ring)
@@ -340,6 +346,9 @@ static void ring_sample(struct ring *ring)
if (!ring->size)
return;
+ if (ring->skip_ring_reads)
+ return;
+
ring->head = ring_read(ring, RING_HEAD) & HEAD_ADDR;
ring->tail = ring_read(ring, RING_TAIL) & TAIL_ADDR;
@@ -366,6 +375,15 @@ static void ring_print(struct ring *ring, unsigned long samples_per_sec)
if (!ring->size)
return;
+ if (ring->skip_ring_reads) {
+ len = printf("%25s busy: ??%%: ", ring->name);
+ print_percentage_bar(0, len);
+ printf("%24s space: ??\?/%d\n",
+ ring->name,
+ ring->size);
+ return;
+ }
+
percent_busy = 100 - 100 * ring->idle / samples_per_sec;
len = printf("%25s busy: %3d%%: ", ring->name, percent_busy);
@@ -513,12 +531,12 @@ int main(int argc, char **argv)
/* Grab access to the registers */
intel_register_access_init(pci_dev, 0);
- ring_init(&render_ring);
+ ring_init(&render_ring, devid);
if (IS_GEN4(devid) || IS_GEN5(devid))
- ring_init(&bsd_ring);
+ ring_init(&bsd_ring, devid);
if (IS_GEN6(devid) || IS_GEN7(devid)) {
- ring_init(&bsd6_ring);
- ring_init(&blt_ring);
+ ring_init(&bsd6_ring, devid);
+ ring_init(&blt_ring, devid);
}
/* Initialize GPU stats */
--
2.7.1
More information about the Intel-gfx
mailing list