summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Holland <samuel.holland@sifive.com>2024-10-26 10:13:57 -0700
committerPalmer Dabbelt <palmer@rivosinc.com>2025-03-26 15:56:45 -0700
commitea2bde36a46d5724c1b44d80cc9fafbd73c2ecf9 (patch)
tree9c181df489c20b76c583d8b4ce6ef08b589867e8
parentd073a571e68f42414f8f06f01b59f52224538a83 (diff)
riscv: Support CONFIG_RELOCATABLE on riscv32
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>
-rw-r--r--arch/riscv/Kconfig2
-rw-r--r--arch/riscv/mm/init.c17
2 files changed, 9 insertions, 10 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 62fb6d9560e5..7d3d457045ee 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -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),
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 82d14f94c996..d1494d48a70d 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -20,15 +20,13 @@
#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