xref: /openbmc/linux/arch/arm64/mm/mmap.c (revision 6e2edd6371a497a6350bb735534c9bda2a31f43d)
1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21d18c47cSCatalin Marinas /*
31d18c47cSCatalin Marinas  * Based on arch/arm/mm/mmap.c
41d18c47cSCatalin Marinas  *
51d18c47cSCatalin Marinas  * Copyright (C) 2012 ARM Ltd.
61d18c47cSCatalin Marinas  */
71d18c47cSCatalin Marinas 
8c7b9095eSWill Deacon #include <linux/io.h>
91151f838SArd Biesheuvel #include <linux/memblock.h>
10*6e2edd63SCatalin Marinas #include <linux/mm.h>
11507d6644SShaokun Zhang #include <linux/types.h>
121d18c47cSCatalin Marinas 
13*6e2edd63SCatalin Marinas #include <asm/cpufeature.h>
14507d6644SShaokun Zhang #include <asm/page.h>
151d18c47cSCatalin Marinas 
161d18c47cSCatalin Marinas /*
171d18c47cSCatalin Marinas  * You really shouldn't be using read() or write() on /dev/mem.  This might go
181d18c47cSCatalin Marinas  * away in the future.
191d18c47cSCatalin Marinas  */
20097cbd8dSMin-Hua Chen int valid_phys_addr_range(phys_addr_t addr, size_t size)
211d18c47cSCatalin Marinas {
221151f838SArd Biesheuvel 	/*
231151f838SArd Biesheuvel 	 * Check whether addr is covered by a memory region without the
241151f838SArd Biesheuvel 	 * MEMBLOCK_NOMAP attribute, and whether that region covers the
251151f838SArd Biesheuvel 	 * entire range. In theory, this could lead to false negatives
261151f838SArd Biesheuvel 	 * if the range is covered by distinct but adjacent memory regions
271151f838SArd Biesheuvel 	 * that only differ in other attributes. However, few of such
281151f838SArd Biesheuvel 	 * attributes have been defined, and it is debatable whether it
291151f838SArd Biesheuvel 	 * follows that /dev/mem read() calls should be able traverse
301151f838SArd Biesheuvel 	 * such boundaries.
311151f838SArd Biesheuvel 	 */
321151f838SArd Biesheuvel 	return memblock_is_region_memory(addr, size) &&
331151f838SArd Biesheuvel 	       memblock_is_map_memory(addr);
341d18c47cSCatalin Marinas }
351d18c47cSCatalin Marinas 
361d18c47cSCatalin Marinas /*
371d18c47cSCatalin Marinas  * Do not allow /dev/mem mappings beyond the supported physical range.
381d18c47cSCatalin Marinas  */
391d18c47cSCatalin Marinas int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
401d18c47cSCatalin Marinas {
411d18c47cSCatalin Marinas 	return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK);
421d18c47cSCatalin Marinas }
43*6e2edd63SCatalin Marinas 
44*6e2edd63SCatalin Marinas static int __init adjust_protection_map(void)
45*6e2edd63SCatalin Marinas {
46*6e2edd63SCatalin Marinas 	/*
47*6e2edd63SCatalin Marinas 	 * With Enhanced PAN we can honour the execute-only permissions as
48*6e2edd63SCatalin Marinas 	 * there is no PAN override with such mappings.
49*6e2edd63SCatalin Marinas 	 */
50*6e2edd63SCatalin Marinas 	if (cpus_have_const_cap(ARM64_HAS_EPAN)) {
51*6e2edd63SCatalin Marinas 		protection_map[VM_EXEC] = PAGE_EXECONLY;
52*6e2edd63SCatalin Marinas 		protection_map[VM_EXEC | VM_SHARED] = PAGE_EXECONLY;
53*6e2edd63SCatalin Marinas 	}
54*6e2edd63SCatalin Marinas 
55*6e2edd63SCatalin Marinas 	return 0;
56*6e2edd63SCatalin Marinas }
57*6e2edd63SCatalin Marinas arch_initcall(adjust_protection_map);
58