b8be23d
From patchwork Thu Oct  6 09:52:07 2016
b8be23d
Content-Type: text/plain; charset="utf-8"
b8be23d
MIME-Version: 1.0
b8be23d
Content-Transfer-Encoding: 7bit
b8be23d
Subject: arm64: mm: Fix memmap to be initialized for the entire section
b8be23d
From: Robert Richter <rrichter@cavium.com>
b8be23d
X-Patchwork-Id: 9364537
b8be23d
Message-Id: <1475747527-32387-1-git-send-email-rrichter@cavium.com>
b8be23d
To: Catalin Marinas <catalin.marinas@arm.com>, Will Deacon
b8be23d
 <will.deacon@arm.com>
b8be23d
Cc: Mark Rutland <mark.rutland@arm.com>, linux-efi@vger.kernel.org,
b8be23d
 David Daney <david.daney@cavium.com>,
b8be23d
 Ard Biesheuvel <ard.biesheuvel@linaro.org>,
b8be23d
 linux-kernel@vger.kernel.org, Robert Richter <rrichter@cavium.com>,
b8be23d
 Hanjun Guo <hanjun.guo@linaro.org>, linux-arm-kernel@lists.infradead.org
b8be23d
Date: Thu, 6 Oct 2016 11:52:07 +0200
b8be23d
b8be23d
There is a memory setup problem on ThunderX systems with certain
b8be23d
memory configurations. The symptom is
b8be23d
b8be23d
 kernel BUG at mm/page_alloc.c:1848!
b8be23d
b8be23d
This happens for some configs with 64k page size enabled. The bug
b8be23d
triggers for page zones with some pages in the zone not assigned to
b8be23d
this particular zone. In my case some pages that are marked as nomap
b8be23d
were not reassigned to the new zone of node 1, so those are still
b8be23d
assigned to node 0.
b8be23d
b8be23d
The reason for the mis-configuration is a change in pfn_valid() which
b8be23d
reports pages marked nomap as invalid:
b8be23d
b8be23d
 68709f45385a arm64: only consider memblocks with NOMAP cleared for linear mapping
b8be23d
b8be23d
This causes pages marked as nomap being no long reassigned to the new
b8be23d
zone in memmap_init_zone() by calling __init_single_pfn().
b8be23d
b8be23d
Fixing this by restoring the old behavior of pfn_valid() to use
b8be23d
memblock_is_memory(). Also changing users of pfn_valid() in arm64 code
b8be23d
to use memblock_is_map_memory() where necessary. This only affects
b8be23d
code in ioremap.c. The code in mmu.c still can use the new version of
b8be23d
pfn_valid().
b8be23d
b8be23d
Should be marked stable v4.5..
b8be23d
b8be23d
Signed-off-by: Robert Richter <rrichter@cavium.com>
b8be23d
---
b8be23d
 arch/arm64/mm/init.c    | 2 +-
b8be23d
 arch/arm64/mm/ioremap.c | 5 +++--
b8be23d
 2 files changed, 4 insertions(+), 3 deletions(-)
b8be23d
b8be23d
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
b8be23d
index bbb7ee76e319..25b8659c2a9f 100644
b8be23d
--- a/arch/arm64/mm/init.c
b8be23d
+++ b/arch/arm64/mm/init.c
b8be23d
@@ -147,7 +147,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
b8be23d
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
b8be23d
 int pfn_valid(unsigned long pfn)
b8be23d
 {
b8be23d
-	return memblock_is_map_memory(pfn << PAGE_SHIFT);
b8be23d
+	return memblock_is_memory(pfn << PAGE_SHIFT);
b8be23d
 }
b8be23d
 EXPORT_SYMBOL(pfn_valid);
b8be23d
 #endif
b8be23d
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
b8be23d
index 01e88c8bcab0..c17c220b0c48 100644
b8be23d
--- a/arch/arm64/mm/ioremap.c
b8be23d
+++ b/arch/arm64/mm/ioremap.c
b8be23d
@@ -21,6 +21,7 @@
b8be23d
  */
b8be23d
 
b8be23d
 #include <linux/export.h>
b8be23d
+#include <linux/memblock.h>
b8be23d
 #include <linux/mm.h>
b8be23d
 #include <linux/vmalloc.h>
b8be23d
 #include <linux/io.h>
b8be23d
@@ -55,7 +56,7 @@ static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
b8be23d
 	/*
b8be23d
 	 * Don't allow RAM to be mapped.
b8be23d
 	 */
b8be23d
-	if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr))))
b8be23d
+	if (WARN_ON(memblock_is_map_memory(phys_addr)))
b8be23d
 		return NULL;
b8be23d
 
b8be23d
 	area = get_vm_area_caller(size, VM_IOREMAP, caller);
b8be23d
@@ -96,7 +97,7 @@ EXPORT_SYMBOL(__iounmap);
b8be23d
 void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
b8be23d
 {
b8be23d
 	/* For normal memory we already have a cacheable mapping. */
b8be23d
-	if (pfn_valid(__phys_to_pfn(phys_addr)))
b8be23d
+	if (memblock_is_map_memory(phys_addr))
b8be23d
 		return (void __iomem *)__phys_to_virt(phys_addr);
b8be23d
 
b8be23d
 	return __ioremap_caller(phys_addr, size, __pgprot(PROT_NORMAL),