]> git.hungrycats.org Git - linux/commitdiff
ARM: 9419/1: mm: Fix kernel memory mapping for xip kernels
authorHarith G <harith.g@alifsemi.com>
Wed, 18 Sep 2024 05:57:11 +0000 (06:57 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 Nov 2024 14:37:30 +0000 (15:37 +0100)
[ Upstream commit ed6cbe6e5563452f305e89c15846820f2874e431 ]

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: a91da5457085 ("ARM: 9089/1: Define kernel physical section start and end")
Signed-off-by: Harith George <harith.g@alifsemi.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/arm/kernel/head.S
arch/arm/mm/mmu.c

index 29e2900178a1f4c70888fc9e8164924b59a8821c..b97da9e069a06b0594cfcffd59aa338d2a87989b 100644 (file)
@@ -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.
         */
index 463fc2a8448f0a28725f3f26bf098fa8c504de0b..a39a7043f18967144229b1973cf136721cad7586 100644 (file)
@@ -1401,18 +1401,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.
         */
@@ -1602,12 +1590,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;
@@ -1617,7 +1620,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;
@@ -1762,6 +1765,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);