[PATCH] riscv: remove .text section size limitation for XIP

Palmer Dabbelt palmer at dabbelt.com
Tue Oct 26 15:46:12 PDT 2021


On Mon, 11 Oct 2021 02:14:14 PDT (-0700), vitaly.wool at konsulko.com wrote:
> Currently there's a limit of 8MB for the .text section of a RISC-V
> image in the XIP case. This breaks compilation of many automatic
> builds and is generally inconvenient. This patch removes that
> limitation and optimizes XIP image file size at the same time.
>
> Signed-off-by: Vitaly Wool <vitaly.wool at konsulko.com>
> ---
>  arch/riscv/include/asm/pgtable.h    |  6 ++++--
>  arch/riscv/kernel/head.S            | 12 ++++++++++++
>  arch/riscv/kernel/vmlinux-xip.lds.S | 10 +++++++---
>  arch/riscv/mm/init.c                |  7 +++----
>  4 files changed, 26 insertions(+), 9 deletions(-)
>
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index 39b550310ec6..bf204e7c1f74 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -75,7 +75,8 @@
>  #endif
>
>  #ifdef CONFIG_XIP_KERNEL
> -#define XIP_OFFSET		SZ_8M
> +#define XIP_OFFSET		SZ_32M
> +#define XIP_OFFSET_MASK		(SZ_32M - 1)
>  #else
>  #define XIP_OFFSET		0
>  #endif
> @@ -97,7 +98,8 @@
>  #ifdef CONFIG_XIP_KERNEL
>  #define XIP_FIXUP(addr) ({							\
>  	uintptr_t __a = (uintptr_t)(addr);					\
> -	(__a >= CONFIG_XIP_PHYS_ADDR && __a < CONFIG_XIP_PHYS_ADDR + SZ_16M) ?	\
> +	(__a >= CONFIG_XIP_PHYS_ADDR && \
> +	 __a < CONFIG_XIP_PHYS_ADDR + XIP_OFFSET * 2) ?	\
>  		__a - CONFIG_XIP_PHYS_ADDR + CONFIG_PHYS_RAM_BASE - XIP_OFFSET :\
>  		__a;								\
>  	})
> diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
> index fce5184b22c3..ed316d02cd7e 100644
> --- a/arch/riscv/kernel/head.S
> +++ b/arch/riscv/kernel/head.S
> @@ -20,10 +20,20 @@
>  	REG_L t0, _xip_fixup
>  	add \reg, \reg, t0
>  .endm
> +.macro XIP_FIXUP_FLASH_OFFSET reg
> +	la t1, __data_loc
> +	li t0, XIP_OFFSET_MASK
> +	and t1, t1, t0
> +	li t1, XIP_OFFSET
> +	sub t0, t0, t1
> +	sub \reg, \reg, t0
> +.endm
>  _xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET
>  #else
>  .macro XIP_FIXUP_OFFSET reg
>  .endm
> +.macro XIP_FIXUP_FLASH_OFFSET reg
> +.endm
>  #endif /* CONFIG_XIP_KERNEL */
>
>  __HEAD
> @@ -266,6 +276,7 @@ pmp_done:
>  	la a3, hart_lottery
>  	mv a2, a3
>  	XIP_FIXUP_OFFSET a2
> +	XIP_FIXUP_FLASH_OFFSET a3
>  	lw t1, (a3)
>  	amoswap.w t0, t1, (a2)
>  	/* first time here if hart_lottery in RAM is not set */
> @@ -304,6 +315,7 @@ clear_bss_done:
>  	XIP_FIXUP_OFFSET sp
>  #ifdef CONFIG_BUILTIN_DTB
>  	la a0, __dtb_start
> +	XIP_FIXUP_OFFSET a0
>  #else
>  	mv a0, s1
>  #endif /* CONFIG_BUILTIN_DTB */
> diff --git a/arch/riscv/kernel/vmlinux-xip.lds.S b/arch/riscv/kernel/vmlinux-xip.lds.S
> index 9c9f35091ef0..f5ed08262139 100644
> --- a/arch/riscv/kernel/vmlinux-xip.lds.S
> +++ b/arch/riscv/kernel/vmlinux-xip.lds.S
> @@ -64,8 +64,11 @@ SECTIONS
>  /*
>   * From this point, stuff is considered writable and will be copied to RAM
>   */
> -	__data_loc = ALIGN(16);		/* location in file */
> -	. = LOAD_OFFSET + XIP_OFFSET;	/* location in memory */
> +	__data_loc = ALIGN(PAGE_SIZE);		/* location in file */
> +	. = KERNEL_LINK_ADDR + XIP_OFFSET;	/* location in memory */
> +
> +#undef LOAD_OFFSET
> +#define LOAD_OFFSET (KERNEL_LINK_ADDR + XIP_OFFSET - (__data_loc & XIP_OFFSET_MASK))
>
>  	_sdata = .;			/* Start of data section */
>  	_data = .;
> @@ -96,7 +99,6 @@ SECTIONS
>  		KEEP(*(__soc_builtin_dtb_table))
>  		__soc_builtin_dtb_table_end = .;
>  	}
> -	PERCPU_SECTION(L1_CACHE_BYTES)
>
>  	. = ALIGN(8);
>  	.alternative : {
> @@ -122,6 +124,8 @@ SECTIONS
>
>  	BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
>
> +	PERCPU_SECTION(L1_CACHE_BYTES)
> +
>  	.rel.dyn : AT(ADDR(.rel.dyn) - LOAD_OFFSET) {
>  		*(.rel.dyn*)
>  	}
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index c0cddf0fc22d..24b2b8044602 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -41,7 +41,7 @@ phys_addr_t phys_ram_base __ro_after_init;
>  EXPORT_SYMBOL(phys_ram_base);
>
>  #ifdef CONFIG_XIP_KERNEL
> -extern char _xiprom[], _exiprom[];
> +extern char _xiprom[], _exiprom[], __data_loc;
>  #endif
>
>  unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
> @@ -454,10 +454,9 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
>  /* called from head.S with MMU off */
>  asmlinkage void __init __copy_data(void)
>  {
> -	void *from = (void *)(&_sdata);
> -	void *end = (void *)(&_end);
> +	void *from = (void *)(&__data_loc);
>  	void *to = (void *)CONFIG_PHYS_RAM_BASE;
> -	size_t sz = (size_t)(end - from + 1);
> +	size_t sz = (size_t)((uintptr_t)(&_end) - (uintptr_t)(&_sdata));
>
>  	memcpy(to, from, sz);
>  }

Thanks, this is on for-next.



More information about the linux-riscv mailing list