Commit ed6cbe6e authored by Harith G's avatar Harith G Committed by Russell King (Oracle)
Browse files

ARM: 9419/1: mm: Fix kernel memory mapping for xip kernels



The patchset introducing kernel_sec_start/end variables to separate the
kernel/lowmem memory mappings, broke the mapping of the kernel memory
for xipkernels.

kernel_sec_start/end variables are in RO area before the MMU is switched
on for xipkernels.
So these cannot be set early in boot in head.S. Fix this by setting these
after MMU is switched on.
xipkernels need two different mappings for kernel text (starting at
CONFIG_XIP_PHYS_ADDR) and data (starting at CONFIG_PHYS_OFFSET).
Also, move the kernel code mapping from devicemaps_init() to map_kernel().

Fixes: a91da545 ("ARM: 9089/1: Define kernel physical section start and end")
Signed-off-by: default avatarHarith George <harith.g@alifsemi.com>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
parent 9852d85e
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -252,11 +252,15 @@ __create_page_tables:
	 */
	add	r0, r4, #KERNEL_OFFSET >> (SECTION_SHIFT - PMD_ENTRY_ORDER)
	ldr	r6, =(_end - 1)

	/* For XIP, kernel_sec_start/kernel_sec_end are currently in RO memory */
#ifndef CONFIG_XIP_KERNEL
	adr_l	r5, kernel_sec_start		@ _pa(kernel_sec_start)
#if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32
	str	r8, [r5, #4]			@ Save physical start of kernel (BE)
#else
	str	r8, [r5]			@ Save physical start of kernel (LE)
#endif
#endif
	orr	r3, r8, r7			@ Add the MMU flags
	add	r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ENTRY_ORDER)
@@ -264,6 +268,7 @@ __create_page_tables:
	add	r3, r3, #1 << SECTION_SHIFT
	cmp	r0, r6
	bls	1b
#ifndef CONFIG_XIP_KERNEL
	eor	r3, r3, r7			@ Remove the MMU flags
	adr_l	r5, kernel_sec_end		@ _pa(kernel_sec_end)
#if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32
@@ -271,8 +276,7 @@ __create_page_tables:
#else
	str	r3, [r5]			@ Save physical end of kernel (LE)
#endif

#ifdef CONFIG_XIP_KERNEL
#else
	/*
	 * Map the kernel image separately as it is not located in RAM.
	 */
+21 −13
Original line number Diff line number Diff line
@@ -1402,18 +1402,6 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
		create_mapping(&map);
	}

	/*
	 * Map the kernel if it is XIP.
	 * It is always first in the modulearea.
	 */
#ifdef CONFIG_XIP_KERNEL
	map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
	map.virtual = MODULES_VADDR;
	map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
	map.type = MT_ROM;
	create_mapping(&map);
#endif

	/*
	 * Map the cache flushing regions.
	 */
@@ -1603,12 +1591,27 @@ static void __init map_kernel(void)
	 * This will only persist until we turn on proper memory management later on
	 * and we remap the whole kernel with page granularity.
	 */
#ifdef CONFIG_XIP_KERNEL
	phys_addr_t kernel_nx_start = kernel_sec_start;
#else
	phys_addr_t kernel_x_start = kernel_sec_start;
	phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
	phys_addr_t kernel_nx_start = kernel_x_end;
#endif
	phys_addr_t kernel_nx_end = kernel_sec_end;
	struct map_desc map;

	/*
	 * Map the kernel if it is XIP.
	 * It is always first in the modulearea.
	 */
#ifdef CONFIG_XIP_KERNEL
	map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
	map.virtual = MODULES_VADDR;
	map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
	map.type = MT_ROM;
	create_mapping(&map);
#else
	map.pfn = __phys_to_pfn(kernel_x_start);
	map.virtual = __phys_to_virt(kernel_x_start);
	map.length = kernel_x_end - kernel_x_start;
@@ -1618,7 +1621,7 @@ static void __init map_kernel(void)
	/* If the nx part is small it may end up covered by the tail of the RWX section */
	if (kernel_x_end == kernel_nx_end)
		return;

#endif
	map.pfn = __phys_to_pfn(kernel_nx_start);
	map.virtual = __phys_to_virt(kernel_nx_start);
	map.length = kernel_nx_end - kernel_nx_start;
@@ -1764,6 +1767,11 @@ void __init paging_init(const struct machine_desc *mdesc)
{
	void *zero_page;

#ifdef CONFIG_XIP_KERNEL
	/* Store the kernel RW RAM region start/end in these variables */
	kernel_sec_start = CONFIG_PHYS_OFFSET & SECTION_MASK;
	kernel_sec_end = round_up(__pa(_end), SECTION_SIZE);
#endif
	pr_debug("physical kernel sections: 0x%08llx-0x%08llx\n",
		 kernel_sec_start, kernel_sec_end);