Skip to content

Commit 9bf8515

Browse files
HarithGeorge-AlifSemismb49
authored andcommitted
ARM: 9419/1: mm: Fix kernel memory mapping for xip kernels
BugLink: https://bugs.launchpad.net/bugs/2101042 [ 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: a91da54 ("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> Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 3be799d commit 9bf8515

File tree

2 files changed

+27
-15
lines changed

2 files changed

+27
-15
lines changed

arch/arm/kernel/head.S

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,27 +252,31 @@ __create_page_tables:
252252
*/
253253
add r0, r4, #KERNEL_OFFSET >> (SECTION_SHIFT - PMD_ENTRY_ORDER)
254254
ldr r6, =(_end - 1)
255+
256+
/* For XIP, kernel_sec_start/kernel_sec_end are currently in RO memory */
257+
#ifndef CONFIG_XIP_KERNEL
255258
adr_l r5, kernel_sec_start @ _pa(kernel_sec_start)
256259
#if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32
257260
str r8, [r5, #4] @ Save physical start of kernel (BE)
258261
#else
259262
str r8, [r5] @ Save physical start of kernel (LE)
263+
#endif
260264
#endif
261265
orr r3, r8, r7 @ Add the MMU flags
262266
add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ENTRY_ORDER)
263267
1: str r3, [r0], #1 << PMD_ENTRY_ORDER
264268
add r3, r3, #1 << SECTION_SHIFT
265269
cmp r0, r6
266270
bls 1b
271+
#ifndef CONFIG_XIP_KERNEL
267272
eor r3, r3, r7 @ Remove the MMU flags
268273
adr_l r5, kernel_sec_end @ _pa(kernel_sec_end)
269274
#if defined CONFIG_CPU_ENDIAN_BE8 || defined CONFIG_CPU_ENDIAN_BE32
270275
str r3, [r5, #4] @ Save physical end of kernel (BE)
271276
#else
272277
str r3, [r5] @ Save physical end of kernel (LE)
273278
#endif
274-
275-
#ifdef CONFIG_XIP_KERNEL
279+
#else
276280
/*
277281
* Map the kernel image separately as it is not located in RAM.
278282
*/

arch/arm/mm/mmu.c

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,18 +1402,6 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
14021402
create_mapping(&map);
14031403
}
14041404

1405-
/*
1406-
* Map the kernel if it is XIP.
1407-
* It is always first in the modulearea.
1408-
*/
1409-
#ifdef CONFIG_XIP_KERNEL
1410-
map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
1411-
map.virtual = MODULES_VADDR;
1412-
map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
1413-
map.type = MT_ROM;
1414-
create_mapping(&map);
1415-
#endif
1416-
14171405
/*
14181406
* Map the cache flushing regions.
14191407
*/
@@ -1603,12 +1591,27 @@ static void __init map_kernel(void)
16031591
* This will only persist until we turn on proper memory management later on
16041592
* and we remap the whole kernel with page granularity.
16051593
*/
1594+
#ifdef CONFIG_XIP_KERNEL
1595+
phys_addr_t kernel_nx_start = kernel_sec_start;
1596+
#else
16061597
phys_addr_t kernel_x_start = kernel_sec_start;
16071598
phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
16081599
phys_addr_t kernel_nx_start = kernel_x_end;
1600+
#endif
16091601
phys_addr_t kernel_nx_end = kernel_sec_end;
16101602
struct map_desc map;
16111603

1604+
/*
1605+
* Map the kernel if it is XIP.
1606+
* It is always first in the modulearea.
1607+
*/
1608+
#ifdef CONFIG_XIP_KERNEL
1609+
map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
1610+
map.virtual = MODULES_VADDR;
1611+
map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
1612+
map.type = MT_ROM;
1613+
create_mapping(&map);
1614+
#else
16121615
map.pfn = __phys_to_pfn(kernel_x_start);
16131616
map.virtual = __phys_to_virt(kernel_x_start);
16141617
map.length = kernel_x_end - kernel_x_start;
@@ -1618,7 +1621,7 @@ static void __init map_kernel(void)
16181621
/* If the nx part is small it may end up covered by the tail of the RWX section */
16191622
if (kernel_x_end == kernel_nx_end)
16201623
return;
1621-
1624+
#endif
16221625
map.pfn = __phys_to_pfn(kernel_nx_start);
16231626
map.virtual = __phys_to_virt(kernel_nx_start);
16241627
map.length = kernel_nx_end - kernel_nx_start;
@@ -1763,6 +1766,11 @@ void __init paging_init(const struct machine_desc *mdesc)
17631766
{
17641767
void *zero_page;
17651768

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

0 commit comments

Comments
 (0)