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