]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
riscv: Support CONFIG_RELOCATABLE on riscv32
authorSamuel Holland <samuel.holland@sifive.com>
Sat, 26 Oct 2024 17:13:57 +0000 (10:13 -0700)
committerPalmer Dabbelt <palmer@rivosinc.com>
Wed, 26 Mar 2025 22:56:45 +0000 (15:56 -0700)
When adjusted to use the correctly-sized ELF types, relocate_kernel()
works on riscv32 as well. The caveat about crossing an intermediate page
table boundary does not apply to riscv32, since for Sv32 the early
kernel mapping uses only PGD entries. Since KASLR is not yet supported
on riscv32, this option is mostly useful for NOMMU.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20241026171441.3047904-6-samuel.holland@sifive.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/Kconfig
arch/riscv/mm/init.c

index 62fb6d9560e5dd59726ec49c713cd7735dcb78e7..7d3d457045eec597b263b0f16c508f14fba4c94f 100644 (file)
@@ -1075,7 +1075,7 @@ config PARAVIRT_TIME_ACCOUNTING
 
 config RELOCATABLE
        bool "Build a relocatable kernel"
-       depends on 64BIT && !XIP_KERNEL
+       depends on !XIP_KERNEL
        select MODULE_SECTIONS if MODULES
        help
           This builds a kernel as a Position Independent Executable (PIE),
index 82d14f94c996c9c99eaa5bbc6130555b147bf48d..d1494d48a70d6028f36615ce8f5adf97de2f3716 100644 (file)
 #include <linux/dma-map-ops.h>
 #include <linux/crash_dump.h>
 #include <linux/hugetlb.h>
-#ifdef CONFIG_RELOCATABLE
-#include <linux/elf.h>
-#endif
 #include <linux/kfence.h>
 #include <linux/execmem.h>
 
 #include <asm/fixmap.h>
 #include <asm/io.h>
 #include <asm/kasan.h>
+#include <asm/module.h>
 #include <asm/numa.h>
 #include <asm/pgtable.h>
 #include <asm/sections.h>
@@ -328,7 +326,7 @@ extern unsigned long __rela_dyn_start, __rela_dyn_end;
 
 static void __init relocate_kernel(void)
 {
-       Elf64_Rela *rela = (Elf64_Rela *)&__rela_dyn_start;
+       Elf_Rela *rela = (Elf_Rela *)&__rela_dyn_start;
        /*
         * This holds the offset between the linked virtual address and the
         * relocated virtual address.
@@ -340,9 +338,9 @@ static void __init relocate_kernel(void)
         */
        uintptr_t va_kernel_link_pa_offset = KERNEL_LINK_ADDR - kernel_map.phys_addr;
 
-       for ( ; rela < (Elf64_Rela *)&__rela_dyn_end; rela++) {
-               Elf64_Addr addr = (rela->r_offset - va_kernel_link_pa_offset);
-               Elf64_Addr relocated_addr = rela->r_addend;
+       for ( ; rela < (Elf_Rela *)&__rela_dyn_end; rela++) {
+               Elf_Addr addr = (rela->r_offset - va_kernel_link_pa_offset);
+               Elf_Addr relocated_addr = rela->r_addend;
 
                if (rela->r_info != R_RISCV_RELATIVE)
                        continue;
@@ -356,7 +354,7 @@ static void __init relocate_kernel(void)
                if (relocated_addr >= KERNEL_LINK_ADDR)
                        relocated_addr += reloc_offset;
 
-               *(Elf64_Addr *)addr = relocated_addr;
+               *(Elf_Addr *)addr = relocated_addr;
        }
 }
 #endif /* CONFIG_RELOCATABLE */
@@ -1174,7 +1172,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
         * makes the kernel cross over a PUD_SIZE boundary, raise a bug
         * since a part of the kernel would not get mapped.
         */
-       BUG_ON(PUD_SIZE - (kernel_map.virt_addr & (PUD_SIZE - 1)) < kernel_map.size);
+       if (IS_ENABLED(CONFIG_64BIT))
+               BUG_ON(PUD_SIZE - (kernel_map.virt_addr & (PUD_SIZE - 1)) < kernel_map.size);
        relocate_kernel();
 #endif