Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 8518/1: Use correct symbols for XIP_KERNEL

For an XIP build, _etext does not represent the end of the
binary image that needs to stay mapped into the MODULES_VADDR area.
Years ago, data came before text in the memory map. However,
now that the order is text/init/data, an XIP_KERNEL needs to map
up to the data location in order to keep from cutting off
parts of the kernel that are needed.
We only map up to the beginning of data because data has already been
copied, so there's no reason to keep it around anymore.
A new symbol is created to make it clear what it is we are referring
to.

This fixes the bug where you might lose the end of your kernel area
after page table setup is complete.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Chris Brandt and committed by
Russell King
02afa9a8 31b96cae

+17 -4
-1
arch/arm/include/asm/Kbuild
··· 23 23 generic-y += resource.h 24 24 generic-y += rwsem.h 25 25 generic-y += seccomp.h 26 - generic-y += sections.h 27 26 generic-y += segment.h 28 27 generic-y += sembuf.h 29 28 generic-y += serial.h
+8
arch/arm/include/asm/sections.h
··· 1 + #ifndef _ASM_ARM_SECTIONS_H 2 + #define _ASM_ARM_SECTIONS_H 3 + 4 + #include <asm-generic/sections.h> 5 + 6 + extern char _exiprom[]; 7 + 8 + #endif /* _ASM_ARM_SECTIONS_H */
+1 -1
arch/arm/kernel/module.c
··· 34 34 * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. 35 35 */ 36 36 #undef MODULES_VADDR 37 - #define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK) 37 + #define MODULES_VADDR (((unsigned long)_exiprom + ~PMD_MASK) & PMD_MASK) 38 38 #endif 39 39 40 40 #ifdef CONFIG_MMU
+2
arch/arm/kernel/vmlinux-xip.lds.S
··· 85 85 } 86 86 87 87 . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); 88 + _xiprom = .; /* XIP ROM area to be mapped */ 88 89 89 90 .head.text : { 90 91 _text = .; ··· 211 210 PERCPU_SECTION(L1_CACHE_BYTES) 212 211 #endif 213 212 213 + _exiprom = .; /* End of XIP ROM area */ 214 214 __data_loc = ALIGN(4); /* location in binary */ 215 215 . = PAGE_OFFSET + TEXT_OFFSET; 216 216
+6 -2
arch/arm/mm/mmu.c
··· 1253 1253 1254 1254 #ifdef CONFIG_XIP_KERNEL 1255 1255 /* The XIP kernel is mapped in the module area -- skip over it */ 1256 - addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK; 1256 + addr = ((unsigned long)_exiprom + PMD_SIZE - 1) & PMD_MASK; 1257 1257 #endif 1258 1258 for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE) 1259 1259 pmd_clear(pmd_off_k(addr)); ··· 1335 1335 #ifdef CONFIG_XIP_KERNEL 1336 1336 map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); 1337 1337 map.virtual = MODULES_VADDR; 1338 - map.length = ((unsigned long)_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK; 1338 + map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK; 1339 1339 map.type = MT_ROM; 1340 1340 create_mapping(&map); 1341 1341 #endif ··· 1426 1426 static void __init map_lowmem(void) 1427 1427 { 1428 1428 struct memblock_region *reg; 1429 + #ifdef CONFIG_XIP_KERNEL 1430 + phys_addr_t kernel_x_start = round_down(__pa(_sdata), SECTION_SIZE); 1431 + #else 1429 1432 phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE); 1433 + #endif 1430 1434 phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE); 1431 1435 1432 1436 /* Map all the lowmem memory banks. */