riscv: remove .text section size limitation for XIP
authorVitaly Wool <vitaly.wool@konsulko.com>
Mon, 11 Oct 2021 09:14:14 +0000 (11:14 +0200)
committerPalmer Dabbelt <palmerdabbelt@google.com>
Tue, 26 Oct 2021 21:31:15 +0000 (14:31 -0700)
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@konsulko.com>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
arch/riscv/include/asm/pgtable.h
arch/riscv/kernel/head.S
arch/riscv/kernel/vmlinux-xip.lds.S
arch/riscv/mm/init.c

index 39b550310ec6456358021816144e0a4bb3d08b68..bf204e7c1f7425b7a43cd004fd4fb1ff5bcd71e6 100644 (file)
@@ -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;                                                            \
        })
index fce5184b22c3458e6013f28740a2956739a83ae3..ed316d02cd7ef7b459a1c010301ca42b3baa11ee 100644 (file)
        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 */
index 9c9f35091ef04bb7637c285f21d10368f4819390..f5ed08262139f3bd5f16e652d855852545f8e2af 100644 (file)
@@ -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*)
        }
index c0cddf0fc22db67f2c741d9280338d9e157c8e4b..24b2b80446020fe684454c4c6c09b8489da39d60 100644 (file)
@@ -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);
 }