Skip to content

Commit 1a6d80f

Browse files
committed
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fix from Will Deacon: "We received a report this week that the generic version of pfn_valid(), which we switched to this merge window in 16c9afc ("arm64/mm: drop HAVE_ARCH_PFN_VALID"), interacts badly with dma_map_resource() due to the following check: /* Don't allow RAM to be mapped */ if (WARN_ON_ONCE(pfn_valid(PHYS_PFN(phys_addr)))) return DMA_MAPPING_ERROR; Since the ongoing saga to determine the semantics of pfn_valid() is unlikely to be resolved this week (does it indicate valid memory, or just the presence of a struct page, or whether that struct page has been initialised?), just revert back to our old version of pfn_valid() for 5.14. Summary: - Fix dma_map_resource() by reverting back to old pfn_valid() code" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: Partially revert "arm64/mm: drop HAVE_ARCH_PFN_VALID"
2 parents 97d8cc2 + 3eb9cdf commit 1a6d80f

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

arch/arm64/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ config ARM64
156156
select HAVE_ARCH_KGDB
157157
select HAVE_ARCH_MMAP_RND_BITS
158158
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
159+
select HAVE_ARCH_PFN_VALID
159160
select HAVE_ARCH_PREL32_RELOCATIONS
160161
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
161162
select HAVE_ARCH_SECCOMP_FILTER

arch/arm64/include/asm/page.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ void tag_clear_highpage(struct page *to);
4141

4242
typedef struct page *pgtable_t;
4343

44+
int pfn_valid(unsigned long pfn);
4445
int pfn_is_map_memory(unsigned long pfn);
4546

4647
#include <asm/memory.h>

arch/arm64/mm/init.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,43 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
219219
free_area_init(max_zone_pfns);
220220
}
221221

222+
int pfn_valid(unsigned long pfn)
223+
{
224+
phys_addr_t addr = PFN_PHYS(pfn);
225+
struct mem_section *ms;
226+
227+
/*
228+
* Ensure the upper PAGE_SHIFT bits are clear in the
229+
* pfn. Else it might lead to false positives when
230+
* some of the upper bits are set, but the lower bits
231+
* match a valid pfn.
232+
*/
233+
if (PHYS_PFN(addr) != pfn)
234+
return 0;
235+
236+
if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
237+
return 0;
238+
239+
ms = __pfn_to_section(pfn);
240+
if (!valid_section(ms))
241+
return 0;
242+
243+
/*
244+
* ZONE_DEVICE memory does not have the memblock entries.
245+
* memblock_is_map_memory() check for ZONE_DEVICE based
246+
* addresses will always fail. Even the normal hotplugged
247+
* memory will never have MEMBLOCK_NOMAP flag set in their
248+
* memblock entries. Skip memblock search for all non early
249+
* memory sections covering all of hotplug memory including
250+
* both normal and ZONE_DEVICE based.
251+
*/
252+
if (!early_section(ms))
253+
return pfn_section_valid(ms, pfn);
254+
255+
return memblock_is_memory(addr);
256+
}
257+
EXPORT_SYMBOL(pfn_valid);
258+
222259
int pfn_is_map_memory(unsigned long pfn)
223260
{
224261
phys_addr_t addr = PFN_PHYS(pfn);

0 commit comments

Comments
 (0)