Unverified Commit ea2bde36 authored by Samuel Holland's avatar Samuel Holland Committed by Palmer Dabbelt
Browse files

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: default avatarSamuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20241026171441.3047904-6-samuel.holland@sifive.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parent d073a571
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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),
+8 −9
Original line number Diff line number Diff line
@@ -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,6 +1172,7 @@ 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.
	 */
	if (IS_ENABLED(CONFIG_64BIT))
		BUG_ON(PUD_SIZE - (kernel_map.virt_addr & (PUD_SIZE - 1)) < kernel_map.size);
	relocate_kernel();
#endif