--- /dev/null
+From 498c2280212327858e521e9d21345d4cc2637f54 Mon Sep 17 00:00:00 2001
+From: Will Deacon <will.deacon@arm.com>
+Date: Fri, 16 Nov 2012 14:15:00 -0800
+Subject: mm: highmem: don't treat PKMAP_ADDR(LAST_PKMAP) as a highmem address
+
+From: Will Deacon <will.deacon@arm.com>
+
+commit 498c2280212327858e521e9d21345d4cc2637f54 upstream.
+
+kmap_to_page returns the corresponding struct page for a virtual address
+of an arbitrary mapping. This works by checking whether the address
+falls in the pkmap region and using the pkmap page tables instead of the
+linear mapping if appropriate.
+
+Unfortunately, the bounds checking means that PKMAP_ADDR(LAST_PKMAP) is
+incorrectly treated as a highmem address and we can end up walking off
+the end of pkmap_page_table and subsequently passing junk to pte_page.
+
+This patch fixes the bound check to stay within the pkmap tables.
+
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Cc: Mel Gorman <mgorman@suse.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Yijing Wang <wangyijing@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/highmem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/highmem.c
++++ b/mm/highmem.c
+@@ -98,7 +98,7 @@ struct page *kmap_to_page(void *vaddr)
+ {
+ unsigned long addr = (unsigned long)vaddr;
+
+- if (addr >= PKMAP_ADDR(0) && addr <= PKMAP_ADDR(LAST_PKMAP)) {
++ if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) {
+ int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT;
+ return pte_page(pkmap_page_table[i]);
+ }