diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9c4dc30cdc13bba5ed018be4ddaed077cadd4e1a..a9281cca411412be75e12a867b1224af37cbfa45 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -416,6 +416,7 @@ LIB_H += util/thread.h
 LIB_H += util/trace-event.h
 LIB_H += util/probe-finder.h
 LIB_H += util/probe-event.h
+LIB_H += util/pstack.h
 LIB_H += util/cpumap.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
@@ -451,6 +452,7 @@ LIB_OBJS += $(OUTPUT)util/callchain.o
 LIB_OBJS += $(OUTPUT)util/values.o
 LIB_OBJS += $(OUTPUT)util/debug.o
 LIB_OBJS += $(OUTPUT)util/map.o
+LIB_OBJS += $(OUTPUT)util/pstack.o
 LIB_OBJS += $(OUTPUT)util/session.o
 LIB_OBJS += $(OUTPUT)util/thread.o
 LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 3402453812b3a509fb34d3d99e30da72c332352f..e74df1240ef64c0525d532e2fadb48890d412095 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -9,6 +9,7 @@
 
 #include "cache.h"
 #include "hist.h"
+#include "pstack.h"
 #include "session.h"
 #include "sort.h"
 #include "symbol.h"
@@ -750,6 +751,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
 	newtFormAddHotKey(self->form, 'A');
 	newtFormAddHotKey(self->form, 'a');
 	newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
+	newtFormAddHotKey(self->form, NEWT_KEY_LEFT);
 	newtFormAddComponents(self->form, self->tree, NULL);
 	self->selection = newt__symbol_tree_get_current(self->tree);
 
@@ -801,6 +803,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
 int hists__browse(struct hists *self, const char *helpline, const char *input_name)
 {
 	struct hist_browser *browser = hist_browser__new();
+	struct pstack *fstack = pstack__new(2);
 	const struct thread *thread_filter = NULL;
 	const struct dso *dso_filter = NULL;
 	struct newtExitStruct es;
@@ -810,12 +813,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
 	if (browser == NULL)
 		return -1;
 
+	fstack = pstack__new(2);
+	if (fstack == NULL)
+		goto out;
+
 	ui_helpline__push(helpline);
 
 	hist_browser__title(msg, sizeof(msg), input_name,
 			    dso_filter, thread_filter);
 	if (hist_browser__populate(browser, self, msg) < 0)
-		goto out;
+		goto out_free_stack;
 
 	while (1) {
 		const struct thread *thread;
@@ -836,6 +843,19 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
 				else
 					continue;
 			}
+
+			if (es.u.key == NEWT_KEY_LEFT) {
+				const void *top;
+
+				if (pstack__empty(fstack))
+					continue;
+				top = pstack__pop(fstack);
+				if (top == &dso_filter)
+					goto zoom_out_dso;
+				if (top == &thread_filter)
+					goto zoom_out_thread;
+				continue;
+			}
 		}
 
 		if (browser->selection->sym != NULL &&
@@ -888,12 +908,15 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
 			hist_entry__annotate_browser(he);
 		} else if (choice == zoom_dso) {
 			if (dso_filter) {
+				pstack__remove(fstack, &dso_filter);
+zoom_out_dso:
 				ui_helpline__pop();
 				dso_filter = NULL;
 			} else {
-				ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s DSO\"",
+				ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
 						   dso->kernel ? "the Kernel" : dso->short_name);
 				dso_filter = dso;
+				pstack__push(fstack, &dso_filter);
 			}
 			hists__filter_by_dso(self, dso_filter);
 			hist_browser__title(msg, sizeof(msg), input_name,
@@ -902,13 +925,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
 				goto out;
 		} else if (choice == zoom_thread) {
 			if (thread_filter) {
+				pstack__remove(fstack, &thread_filter);
+zoom_out_thread:
 				ui_helpline__pop();
 				thread_filter = NULL;
 			} else {
-				ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s(%d) thread\"",
+				ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
 						   thread->comm_set ? thread->comm : "",
 						   thread->pid);
 				thread_filter = thread;
+				pstack__push(fstack, &thread_filter);
 			}
 			hists__filter_by_thread(self, thread_filter);
 			hist_browser__title(msg, sizeof(msg), input_name,
@@ -918,6 +944,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
 		}
 	}
 	err = 0;
+out_free_stack:
+	pstack__delete(fstack);
 out:
 	hist_browser__delete(browser);
 	return err;
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
new file mode 100644
index 0000000000000000000000000000000000000000..13d36faf64eb4da3e2bed21813f0d791550f5053
--- /dev/null
+++ b/tools/perf/util/pstack.c
@@ -0,0 +1,75 @@
+/*
+ * Simple pointer stack
+ *
+ * (c) 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
+ */
+
+#include "util.h"
+#include "pstack.h"
+#include <linux/kernel.h>
+#include <stdlib.h>
+
+struct pstack {
+	unsigned short	top;
+	unsigned short	max_nr_entries;
+	void		*entries[0];
+};
+
+struct pstack *pstack__new(unsigned short max_nr_entries)
+{
+	struct pstack *self = zalloc((sizeof(*self) +
+				     max_nr_entries * sizeof(void *)));
+	if (self != NULL)
+		self->max_nr_entries = max_nr_entries;
+	return self;
+}
+
+void pstack__delete(struct pstack *self)
+{
+	free(self);
+}
+
+bool pstack__empty(const struct pstack *self)
+{
+	return self->top == 0;
+}
+
+void pstack__remove(struct pstack *self, void *key)
+{
+	unsigned short i = self->top, last_index = self->top - 1;
+
+	while (i-- != 0) {
+		if (self->entries[i] == key) {
+			if (i < last_index)
+				memmove(self->entries + i,
+					self->entries + i + 1,
+					(last_index - i) * sizeof(void *));
+			--self->top;
+			return;
+		}
+	}
+	pr_err("%s: %p not on the pstack!\n", __func__, key);
+}
+
+void pstack__push(struct pstack *self, void *key)
+{
+	if (self->top == self->max_nr_entries) {
+		pr_err("%s: top=%d, overflow!\n", __func__, self->top);
+		return;
+	}
+	self->entries[self->top++] = key;
+}
+
+void *pstack__pop(struct pstack *self)
+{
+	void *ret;
+
+	if (self->top == 0) {
+		pr_err("%s: underflow!\n", __func__);
+		return NULL;
+	}
+
+	ret = self->entries[--self->top];
+	self->entries[self->top] = NULL;
+	return ret;
+}
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ad07023504bb834e6334bbc5628e269faaa21ce
--- /dev/null
+++ b/tools/perf/util/pstack.h
@@ -0,0 +1,12 @@
+#ifndef _PERF_PSTACK_
+#define _PERF_PSTACK_
+
+struct pstack;
+struct pstack *pstack__new(unsigned short max_nr_entries);
+void pstack__delete(struct pstack *self);
+bool pstack__empty(const struct pstack *self);
+void pstack__remove(struct pstack *self, void *key);
+void pstack__push(struct pstack *self, void *key);
+void *pstack__pop(struct pstack *self);
+
+#endif /* _PERF_PSTACK_ */