diff --git a/overlay/Makefile.am b/overlay/Makefile.am
index 1c722434..294181e0 100644
--- a/overlay/Makefile.am
+++ b/overlay/Makefile.am
@@ -12,6 +12,8 @@ intel_gpu_overlay_SOURCES = \
 	overlay.c \
 	chart.h \
 	chart.c \
+	cpu-top.h \
+	cpu-top.c \
 	gem-objects.h \
 	gem-objects.c \
 	gpu-top.h \
diff --git a/overlay/cpu-top.c b/overlay/cpu-top.c
new file mode 100644
index 00000000..ccfc9a6b
--- /dev/null
+++ b/overlay/cpu-top.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "cpu-top.h"
+
+int cpu_top_update(struct cpu_top *cpu)
+{
+	struct cpu_stat *s = &cpu->stat[cpu->count++&1];
+	struct cpu_stat *d = &cpu->stat[cpu->count&1];
+	uint64_t d_total, d_idle;
+	char buf[4096];
+	int fd, len = -1;
+
+	fd = open("/proc/stat", 0);
+	if (fd < 0)
+		return errno;
+
+	len = read(fd, buf, sizeof(buf)-1);
+	close(fd);
+
+	if (len < 0)
+		return EIO;
+	buf[len] = '\0';
+
+#ifdef __x86_64__
+	sscanf(buf, "cpu %lu %lu %lu %lu",
+	       &s->user, &s->nice, &s->sys, &s->idle);
+#else
+	sscanf(buf, "cpu %llu %llu %llu %llu",
+	       &s->user, &s->nice, &s->sys, &s->idle);
+#endif
+
+	s->total = s->user + s->nice + s->sys + s->idle;
+	if (cpu->count == 1)
+		return EAGAIN;
+
+	d_total = s->total - d->total;
+	d_idle = s->idle - d->idle;
+	cpu->busy = 100 - 100 * d_idle / d_total;
+
+	return 0;
+}
diff --git a/overlay/cpu-top.h b/overlay/cpu-top.h
new file mode 100644
index 00000000..4687f902
--- /dev/null
+++ b/overlay/cpu-top.h
@@ -0,0 +1,13 @@
+#include <stdint.h>
+
+struct cpu_top {
+	uint8_t busy;
+
+	int count;
+	struct cpu_stat {
+		uint64_t user, nice, sys, idle;
+		uint64_t total;
+	} stat[2];
+};
+
+int cpu_top_update(struct cpu_top *cpu);
diff --git a/overlay/overlay.c b/overlay/overlay.c
index 2ff9e9ca..71d20b0f 100644
--- a/overlay/overlay.c
+++ b/overlay/overlay.c
@@ -10,6 +10,7 @@
 #include <errno.h>
 
 #include "overlay.h"
+#include "cpu-top.h"
 #include "gpu-top.h"
 #include "gpu-perf.h"
 #include "gem-objects.h"
@@ -59,8 +60,10 @@ struct overlay_context {
 
 struct overlay_gpu_top {
 	struct gpu_top gpu_top;
+	struct cpu_top cpu_top;
 	struct chart busy[MAX_RINGS];
 	struct chart wait[MAX_RINGS];
+	struct chart cpu;
 };
 
 static void init_gpu_top(struct overlay_gpu_top *gt,
@@ -75,6 +78,16 @@ static void init_gpu_top(struct overlay_gpu_top *gt,
 	int n;
 
 	gpu_top_init(&gt->gpu_top);
+	memset(&gt->cpu, 0, sizeof(gt->cpu));
+
+	chart_init(&gt->cpu, "CPU", 120);
+	chart_set_position(&gt->cpu, 12, 12);
+	chart_set_size(&gt->cpu,
+		       cairo_image_surface_get_width(surface)-24,
+		       100);
+	chart_set_stroke_rgba(&gt->cpu, 0.75, 0.25, 0.75, 1.);
+	chart_set_mode(&gt->cpu, CHART_STROKE);
+	chart_set_range(&gt->cpu, 0, 100);
 
 	for (n = 0; n < gt->gpu_top.num_rings; n++) {
 		chart_init(&gt->busy[n],
@@ -107,9 +120,15 @@ static void init_gpu_top(struct overlay_gpu_top *gt,
 
 static void show_gpu_top(struct overlay_context *ctx, struct overlay_gpu_top *gt)
 {
-	int y, n, update;
+	int y, n, update, len;
+	char txt[160];
 
 	update = gpu_top_update(&gt->gpu_top);
+
+	if (update && cpu_top_update(&gt->cpu_top) == 0)
+		chart_add_sample(&gt->cpu, gt->cpu_top.busy);
+	chart_draw(&gt->cpu, ctx->cr);
+
 	for (n = 0; n < gt->gpu_top.num_rings; n++) {
 		if (update)
 			chart_add_sample(&gt->wait[n],
@@ -126,10 +145,14 @@ static void show_gpu_top(struct overlay_context *ctx, struct overlay_gpu_top *gt
 	cairo_set_source_rgb(ctx->cr, 1, 1, 1);
 
 	y = 12;
+	cairo_set_source_rgba(ctx->cr, 0.75, 0.25, 0.75, 1.);
+	cairo_move_to(ctx->cr, 12, y);
+	sprintf(txt, "CPU: %d%% busy", gt->cpu_top.busy);
+	cairo_show_text(ctx->cr, txt);
+	y += 14;
+
 	for (n = 0; n < gt->gpu_top.num_rings; n++) {
 		struct chart *c =&gt->busy[n];
-		char txt[160];
-		int len;
 
 		len = sprintf(txt, "%s: %d%% busy",
 			      gt->gpu_top.ring[n].name,