[PATCH v5] ARM: xip: Use correct symbol for end of ROM marker

Nicolas Pitre nicolas.pitre at linaro.org
Tue Feb 2 09:35:46 PST 2016


On Tue, 2 Feb 2016, Chris Brandt wrote:

> 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.
> 
> 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 at renesas.com>

Acked-by: Nicolas Pitre <nico at linaro.org>


> ---
> v5:
> * Switched from using __data_loc to _exiprom (new symbol)
> v4:
> * Switched from using _edata_loc __data_loc.
> * Made commit text more accurate.
> v3:
> * Removed sections.h from Kbuild
> v2:
> * Added change for MODULES_VADDR
> * Moved extern to new file asm/sections.h
> ---
>  arch/arm/include/asm/Kbuild     | 1 -
>  arch/arm/include/asm/sections.h | 8 ++++++++
>  arch/arm/kernel/module.c        | 2 +-
>  arch/arm/kernel/vmlinux.lds.S   | 2 ++
>  arch/arm/mm/mmu.c               | 8 ++++++--
>  5 files changed, 17 insertions(+), 4 deletions(-)
>  create mode 100644 arch/arm/include/asm/sections.h
> 
> diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
> index 16da638..3f6616b 100644
> --- a/arch/arm/include/asm/Kbuild
> +++ b/arch/arm/include/asm/Kbuild
> @@ -23,7 +23,6 @@ generic-y += preempt.h
>  generic-y += resource.h
>  generic-y += rwsem.h
>  generic-y += seccomp.h
> -generic-y += sections.h
>  generic-y += segment.h
>  generic-y += sembuf.h
>  generic-y += serial.h
> diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h
> new file mode 100644
> index 0000000..803bbf2
> --- /dev/null
> +++ b/arch/arm/include/asm/sections.h
> @@ -0,0 +1,8 @@
> +#ifndef _ASM_ARM_SECTIONS_H
> +#define _ASM_ARM_SECTIONS_H
> +
> +#include <asm-generic/sections.h>
> +
> +extern char _exiprom[];
> +
> +#endif	/* _ASM_ARM_SECTIONS_H */
> diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
> index efdddcb..4f14b5c 100644
> --- a/arch/arm/kernel/module.c
> +++ b/arch/arm/kernel/module.c
> @@ -34,7 +34,7 @@
>   * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.
>   */
>  #undef MODULES_VADDR
> -#define MODULES_VADDR	(((unsigned long)_etext + ~PMD_MASK) & PMD_MASK)
> +#define MODULES_VADDR	(((unsigned long)_exiprom + ~PMD_MASK) & PMD_MASK)
>  #endif
>  
>  #ifdef CONFIG_MMU
> diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
> index 8b60fde..d18e4e5 100644
> --- a/arch/arm/kernel/vmlinux.lds.S
> +++ b/arch/arm/kernel/vmlinux.lds.S
> @@ -86,6 +86,7 @@ SECTIONS
>  
>  #ifdef CONFIG_XIP_KERNEL
>  	. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
> +	_xiprom = .;			/* XIP ROM area to be mapped */
>  #else
>  	. = PAGE_OFFSET + TEXT_OFFSET;
>  #endif
> @@ -228,6 +229,7 @@ SECTIONS
>  #endif
>  
>  #ifdef CONFIG_XIP_KERNEL
> +	_exiprom = .;			/* End of XIP ROM area */
>  	__data_loc = ALIGN(4);		/* location in binary */
>  	. = PAGE_OFFSET + TEXT_OFFSET;
>  #else
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 434d76f..e4b681a 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -1253,7 +1253,7 @@ static inline void prepare_page_table(void)
>  
>  #ifdef CONFIG_XIP_KERNEL
>  	/* The XIP kernel is mapped in the module area -- skip over it */
> -	addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK;
> +	addr = ((unsigned long)_exiprom + PMD_SIZE - 1) & PMD_MASK;
>  #endif
>  	for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
>  		pmd_clear(pmd_off_k(addr));
> @@ -1335,7 +1335,7 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
>  #ifdef CONFIG_XIP_KERNEL
>  	map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
>  	map.virtual = MODULES_VADDR;
> -	map.length = ((unsigned long)_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK;
> +	map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
>  	map.type = MT_ROM;
>  	create_mapping(&map);
>  #endif
> @@ -1426,7 +1426,11 @@ static void __init kmap_init(void)
>  static void __init map_lowmem(void)
>  {
>  	struct memblock_region *reg;
> +#ifdef CONFIG_XIP_KERNEL
> +	phys_addr_t kernel_x_start = round_down(__pa(_sdata), SECTION_SIZE);
> +#else
>  	phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
> +#endif
>  	phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
>  
>  	/* Map all the lowmem memory banks. */
> -- 
> 1.9.1
> 
> 
> 



More information about the linux-arm-kernel mailing list