Mian Yousaf Kaukab 9a3b5b
From: Anshuman Khandual <anshuman.khandual@arm.com>
Mian Yousaf Kaukab 9a3b5b
Date: Fri, 5 Mar 2021 10:54:57 +0530
Mian Yousaf Kaukab 9a3b5b
Subject: arm64/mm: Fix pfn_valid() for ZONE_DEVICE based memory
Mian Yousaf Kaukab 9a3b5b
Mian Yousaf Kaukab 9a3b5b
Git-commit: eeb0753ba27b26f609e61f9950b14f1b934fe429
Mian Yousaf Kaukab 9a3b5b
Patch-mainline: v5.12-rc3
Mian Yousaf Kaukab 9a3b5b
References: git-fixes
Mian Yousaf Kaukab 9a3b5b
Mian Yousaf Kaukab 9a3b5b
pfn_valid() validates a pfn but basically it checks for a valid struct page
Mian Yousaf Kaukab 9a3b5b
backing for that pfn. It should always return positive for memory ranges
Mian Yousaf Kaukab 9a3b5b
backed with struct page mapping. But currently pfn_valid() fails for all
Mian Yousaf Kaukab 9a3b5b
ZONE_DEVICE based memory types even though they have struct page mapping.
Mian Yousaf Kaukab 9a3b5b
Mian Yousaf Kaukab 9a3b5b
pfn_valid() asserts that there is a memblock entry for a given pfn without
Mian Yousaf Kaukab 9a3b5b
MEMBLOCK_NOMAP flag being set. The problem with ZONE_DEVICE based memory is
Mian Yousaf Kaukab 9a3b5b
that they do not have memblock entries. Hence memblock_is_map_memory() will
Mian Yousaf Kaukab 9a3b5b
invariably fail via memblock_search() for a ZONE_DEVICE based address. This
Mian Yousaf Kaukab 9a3b5b
eventually fails pfn_valid() which is wrong. memblock_is_map_memory() needs
Mian Yousaf Kaukab 9a3b5b
to be skipped for such memory ranges. As ZONE_DEVICE memory gets hotplugged
Mian Yousaf Kaukab 9a3b5b
into the system via memremap_pages() called from a driver, their respective
Mian Yousaf Kaukab 9a3b5b
memory sections will not have SECTION_IS_EARLY set.
Mian Yousaf Kaukab 9a3b5b
Mian Yousaf Kaukab 9a3b5b
Normal hotplug memory will never have MEMBLOCK_NOMAP set in their memblock
Mian Yousaf Kaukab 9a3b5b
regions. Because the flag MEMBLOCK_NOMAP was specifically designed and set
Mian Yousaf Kaukab 9a3b5b
for firmware reserved memory regions. memblock_is_map_memory() can just be
Mian Yousaf Kaukab 9a3b5b
skipped as its always going to be positive and that will be an optimization
Mian Yousaf Kaukab 9a3b5b
for the normal hotplug memory. Like ZONE_DEVICE based memory, all normal
Mian Yousaf Kaukab 9a3b5b
hotplugged memory too will not have SECTION_IS_EARLY set for their sections
Mian Yousaf Kaukab 9a3b5b
Mian Yousaf Kaukab 9a3b5b
Skipping memblock_is_map_memory() for all non early memory sections would
Mian Yousaf Kaukab 9a3b5b
fix pfn_valid() problem for ZONE_DEVICE based memory and also improve its
Mian Yousaf Kaukab 9a3b5b
performance for normal hotplug memory as well.
Mian Yousaf Kaukab 9a3b5b
Mian Yousaf Kaukab 9a3b5b
Cc: Catalin Marinas <catalin.marinas@arm.com>
Mian Yousaf Kaukab 9a3b5b
Cc: Will Deacon <will@kernel.org>
Mian Yousaf Kaukab 9a3b5b
Cc: Ard Biesheuvel <ardb@kernel.org>
Mian Yousaf Kaukab 9a3b5b
Cc: Robin Murphy <robin.murphy@arm.com>
Mian Yousaf Kaukab 9a3b5b
Cc: linux-arm-kernel@lists.infradead.org
Mian Yousaf Kaukab 9a3b5b
Cc: linux-kernel@vger.kernel.org
Mian Yousaf Kaukab 9a3b5b
Acked-by: David Hildenbrand <david@redhat.com>
Mian Yousaf Kaukab 9a3b5b
Fixes: 73b20c84d42d ("arm64: mm: implement pte_devmap support")
Mian Yousaf Kaukab 9a3b5b
Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Mian Yousaf Kaukab 9a3b5b
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Mian Yousaf Kaukab 9a3b5b
Link: https://lore.kernel.org/r/1614921898-4099-2-git-send-email-anshuman.khandual@arm.com
Mian Yousaf Kaukab 9a3b5b
Signed-off-by: Will Deacon <will@kernel.org>
Mian Yousaf Kaukab 9a3b5b
Signed-off-by: Mian Yousaf Kaukab <ykaukab@suse.de>
Mian Yousaf Kaukab 9a3b5b
---
Mian Yousaf Kaukab 9a3b5b
 arch/arm64/mm/init.c | 12 ++++++++++++
Mian Yousaf Kaukab 9a3b5b
 1 file changed, 12 insertions(+)
Mian Yousaf Kaukab 9a3b5b
Mian Yousaf Kaukab 9a3b5b
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
Mian Yousaf Kaukab 9a3b5b
index 0ace5e68efba..5920c527845a 100644
Mian Yousaf Kaukab 9a3b5b
--- a/arch/arm64/mm/init.c
Mian Yousaf Kaukab 9a3b5b
+++ b/arch/arm64/mm/init.c
Mian Yousaf Kaukab 9a3b5b
@@ -230,6 +230,18 @@ int pfn_valid(unsigned long pfn)
Mian Yousaf Kaukab 9a3b5b
 
Mian Yousaf Kaukab 9a3b5b
 	if (!valid_section(__pfn_to_section(pfn)))
Mian Yousaf Kaukab 9a3b5b
 		return 0;
Mian Yousaf Kaukab 9a3b5b
+
Mian Yousaf Kaukab 9a3b5b
+	/*
Mian Yousaf Kaukab 9a3b5b
+	 * ZONE_DEVICE memory does not have the memblock entries.
Mian Yousaf Kaukab 9a3b5b
+	 * memblock_is_map_memory() check for ZONE_DEVICE based
Mian Yousaf Kaukab 9a3b5b
+	 * addresses will always fail. Even the normal hotplugged
Mian Yousaf Kaukab 9a3b5b
+	 * memory will never have MEMBLOCK_NOMAP flag set in their
Mian Yousaf Kaukab 9a3b5b
+	 * memblock entries. Skip memblock search for all non early
Mian Yousaf Kaukab 9a3b5b
+	 * memory sections covering all of hotplug memory including
Mian Yousaf Kaukab 9a3b5b
+	 * both normal and ZONE_DEVICE based.
Mian Yousaf Kaukab 9a3b5b
+	 */
Mian Yousaf Kaukab 9a3b5b
+	if (!early_section(__pfn_to_section(pfn)))
Mian Yousaf Kaukab 9a3b5b
+		return pfn_section_valid(__pfn_to_section(pfn), pfn);
Mian Yousaf Kaukab 9a3b5b
 #endif
Mian Yousaf Kaukab 9a3b5b
 	return memblock_is_map_memory(addr);
Mian Yousaf Kaukab 9a3b5b
 }
Mian Yousaf Kaukab 9a3b5b
-- 
Mian Yousaf Kaukab 9a3b5b
2.26.2
Mian Yousaf Kaukab 9a3b5b