Skip to content

Commit 310c33d

Browse files
Merge patch series "Introduce 64b relocatable kernel"
Alexandre Ghiti <alexghiti@rivosinc.com> says: After multiple attempts, this patchset is now based on the fact that the 64b kernel mapping was moved outside the linear mapping. The first patch allows to build relocatable kernels but is not selected by default. That patch is a requirement for KASLR. The second and third patches take advantage of an already existing powerpc script that checks relocations at compile-time, and uses it for riscv. * b4-shazam-merge: riscv: Use --emit-relocs in order to move .rela.dyn in init riscv: Check relocations at compile time powerpc: Move script to check relocations at compile time in scripts/ riscv: Introduce CONFIG_RELOCATABLE riscv: Move .rela.dyn outside of init to avoid empty relocations riscv: Prepare EFI header for relocatable kernels Link: https://lore.kernel.org/r/20230329045329.64565-1-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2 parents 2667e36 + 559d1e4 commit 310c33d

13 files changed

Lines changed: 221 additions & 31 deletions

File tree

arch/powerpc/tools/relocs_check.sh

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,8 @@ if [ $# -lt 3 ]; then
1515
exit 1
1616
fi
1717

18-
# Have Kbuild supply the path to objdump and nm so we handle cross compilation.
19-
objdump="$1"
20-
nm="$2"
21-
vmlinux="$3"
22-
23-
# Remove from the bad relocations those that match an undefined weak symbol
24-
# which will result in an absolute relocation to 0.
25-
# Weak unresolved symbols are of that form in nm output:
26-
# " w _binary__btf_vmlinux_bin_end"
27-
undef_weak_symbols=$($nm "$vmlinux" | awk '$1 ~ /w/ { print $2 }')
28-
2918
bad_relocs=$(
30-
$objdump -R "$vmlinux" |
31-
# Only look at relocation lines.
32-
grep -E '\<R_' |
19+
${srctree}/scripts/relocs_check.sh "$@" |
3320
# These relocations are okay
3421
# On PPC64:
3522
# R_PPC64_RELATIVE, R_PPC64_NONE
@@ -44,8 +31,7 @@ R_PPC_ADDR16_LO
4431
R_PPC_ADDR16_HI
4532
R_PPC_ADDR16_HA
4633
R_PPC_RELATIVE
47-
R_PPC_NONE' |
48-
([ "$undef_weak_symbols" ] && grep -F -w -v "$undef_weak_symbols" || cat)
34+
R_PPC_NONE'
4935
)
5036

5137
if [ -z "$bad_relocs" ]; then

arch/riscv/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,20 @@ config COMPAT
603603

604604
If you want to execute 32-bit userspace applications, say Y.
605605

606+
config RELOCATABLE
607+
bool "Build a relocatable kernel"
608+
depends on MMU && 64BIT && !XIP_KERNEL
609+
help
610+
This builds a kernel as a Position Independent Executable (PIE),
611+
which retains all relocation metadata required to relocate the
612+
kernel binary at runtime to a different virtual address than the
613+
address it was linked at.
614+
Since RISCV uses the RELA relocation format, this requires a
615+
relocation pass at runtime even if the kernel is loaded at the
616+
same address it was linked at.
617+
618+
If unsure, say N.
619+
606620
endmenu # "Kernel features"
607621

608622
menu "Boot options"

arch/riscv/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
#
88

99
OBJCOPYFLAGS := -O binary
10-
LDFLAGS_vmlinux :=
10+
ifeq ($(CONFIG_RELOCATABLE),y)
11+
LDFLAGS_vmlinux += -shared -Bsymbolic -z notext -z norelro --emit-relocs
12+
KBUILD_CFLAGS += -fPIE
13+
endif
1114
ifeq ($(CONFIG_DYNAMIC_FTRACE),y)
12-
LDFLAGS_vmlinux := --no-relax
15+
LDFLAGS_vmlinux += --no-relax
1316
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
1417
ifeq ($(CONFIG_RISCV_ISA_C),y)
1518
CC_FLAGS_FTRACE := -fpatchable-function-entry=4

arch/riscv/Makefile.postlink

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
# ===========================================================================
3+
# Post-link riscv pass
4+
# ===========================================================================
5+
#
6+
# Check that vmlinux relocations look sane
7+
8+
PHONY := __archpost
9+
__archpost:
10+
11+
-include include/config/auto.conf
12+
include $(srctree)/scripts/Kbuild.include
13+
14+
quiet_cmd_relocs_check = CHKREL $@
15+
cmd_relocs_check = \
16+
$(CONFIG_SHELL) $(srctree)/arch/riscv/tools/relocs_check.sh "$(OBJDUMP)" "$(NM)" "$@"
17+
18+
ifdef CONFIG_RELOCATABLE
19+
quiet_cmd_cp_vmlinux_relocs = CPREL vmlinux.relocs
20+
cmd_cp_vmlinux_relocs = cp vmlinux vmlinux.relocs
21+
22+
quiet_cmd_relocs_strip = STRIPREL $@
23+
cmd_relocs_strip = $(OBJCOPY) --remove-section='.rel.*' \
24+
--remove-section='.rel__*' \
25+
--remove-section='.rela.*' \
26+
--remove-section='.rela__*' $@
27+
endif
28+
29+
# `@true` prevents complaint when there is nothing to be done
30+
31+
vmlinux: FORCE
32+
@true
33+
ifdef CONFIG_RELOCATABLE
34+
$(call if_changed,relocs_check)
35+
$(call if_changed,cp_vmlinux_relocs)
36+
$(call if_changed,relocs_strip)
37+
endif
38+
39+
%.ko: FORCE
40+
@true
41+
42+
clean:
43+
@true
44+
45+
PHONY += FORCE clean
46+
47+
FORCE:
48+
49+
.PHONY: $(PHONY)

arch/riscv/boot/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@ $(obj)/xipImage: vmlinux FORCE
3333

3434
endif
3535

36+
ifdef CONFIG_RELOCATABLE
37+
vmlinux.relocs: vmlinux
38+
@ (! [ -f vmlinux.relocs ] && echo "vmlinux.relocs can't be found, please remove vmlinux and try again") || true
39+
40+
$(obj)/Image: vmlinux.relocs FORCE
41+
else
3642
$(obj)/Image: vmlinux FORCE
43+
endif
3744
$(call if_changed,objcopy)
3845

3946
$(obj)/Image.gz: $(obj)/Image FORCE

arch/riscv/include/asm/set_memory.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,7 @@ bool kernel_page_present(struct page *page);
5656
#define SECTION_ALIGN L1_CACHE_BYTES
5757
#endif /* CONFIG_STRICT_KERNEL_RWX */
5858

59+
#define PECOFF_SECTION_ALIGNMENT 0x1000
60+
#define PECOFF_FILE_ALIGNMENT 0x200
61+
5962
#endif /* _ASM_RISCV_SET_MEMORY_H */

arch/riscv/include/asm/topology.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#include <linux/arch_topology.h>
66

77
/* Replace task scheduler's default frequency-invariant accounting */
8-
#define arch_scale_freq_tick topology_scale_freq_tick
9-
#define arch_set_freq_scale topology_set_freq_scale
8+
#define arch_scale_freq_tick topology_scale_freq_tick
9+
#define arch_set_freq_scale topology_set_freq_scale
1010
#define arch_scale_freq_capacity topology_get_freq_scale
1111
#define arch_scale_freq_invariant topology_scale_freq_invariant
1212

@@ -17,4 +17,5 @@
1717
#define arch_update_cpu_topology topology_update_cpu_topology
1818

1919
#include <asm-generic/topology.h>
20+
2021
#endif /* _ASM_RISCV_TOPOLOGY_H */

arch/riscv/kernel/efi-header.S

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <linux/pe.h>
88
#include <linux/sizes.h>
9+
#include <asm/set_memory.h>
910

1011
.macro __EFI_PE_HEADER
1112
.long PE_MAGIC
@@ -33,7 +34,11 @@ optional_header:
3334
.byte 0x02 // MajorLinkerVersion
3435
.byte 0x14 // MinorLinkerVersion
3536
.long __pecoff_text_end - efi_header_end // SizeOfCode
36-
.long __pecoff_data_virt_size // SizeOfInitializedData
37+
#ifdef __clang__
38+
.long __pecoff_data_virt_size // SizeOfInitializedData
39+
#else
40+
.long __pecoff_data_virt_end - __pecoff_text_end // SizeOfInitializedData
41+
#endif
3742
.long 0 // SizeOfUninitializedData
3843
.long __efistub_efi_pe_entry - _start // AddressOfEntryPoint
3944
.long efi_header_end - _start // BaseOfCode
@@ -91,9 +96,17 @@ section_table:
9196
IMAGE_SCN_MEM_EXECUTE // Characteristics
9297

9398
.ascii ".data\0\0\0"
94-
.long __pecoff_data_virt_size // VirtualSize
99+
#ifdef __clang__
100+
.long __pecoff_data_virt_size // VirtualSize
101+
#else
102+
.long __pecoff_data_virt_end - __pecoff_text_end // VirtualSize
103+
#endif
95104
.long __pecoff_text_end - _start // VirtualAddress
96-
.long __pecoff_data_raw_size // SizeOfRawData
105+
#ifdef __clang__
106+
.long __pecoff_data_raw_size // SizeOfRawData
107+
#else
108+
.long __pecoff_data_raw_end - __pecoff_text_end // SizeOfRawData
109+
#endif
97110
.long __pecoff_text_end - _start // PointerToRawData
98111

99112
.long 0 // PointerToRelocations

arch/riscv/kernel/vmlinux.lds.S

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ ENTRY(_start)
2727

2828
jiffies = jiffies_64;
2929

30-
PECOFF_SECTION_ALIGNMENT = 0x1000;
31-
PECOFF_FILE_ALIGNMENT = 0x200;
32-
3330
SECTIONS
3431
{
3532
/* Beginning of code and text segment */
@@ -99,10 +96,6 @@ SECTIONS
9996
*(.rel.dyn*)
10097
}
10198

102-
.rela.dyn : {
103-
*(.rela*)
104-
}
105-
10699
__init_data_end = .;
107100

108101
. = ALIGN(8);
@@ -129,9 +122,27 @@ SECTIONS
129122
*(.sdata*)
130123
}
131124

125+
.rela.dyn : ALIGN(8) {
126+
__rela_dyn_start = .;
127+
*(.rela .rela*)
128+
__rela_dyn_end = .;
129+
}
130+
131+
#ifdef CONFIG_RELOCATABLE
132+
.data.rel : { *(.data.rel*) }
133+
.got : { *(.got*) }
134+
.plt : { *(.plt) }
135+
.dynamic : { *(.dynamic) }
136+
.dynsym : { *(.dynsym) }
137+
.dynstr : { *(.dynstr) }
138+
.hash : { *(.hash) }
139+
.gnu.hash : { *(.gnu.hash) }
140+
#endif
141+
132142
#ifdef CONFIG_EFI
133143
.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
134144
__pecoff_data_raw_size = ABSOLUTE(. - __pecoff_text_end);
145+
__pecoff_data_raw_end = ABSOLUTE(.);
135146
#endif
136147

137148
/* End of data section */
@@ -142,6 +153,7 @@ SECTIONS
142153
#ifdef CONFIG_EFI
143154
. = ALIGN(PECOFF_SECTION_ALIGNMENT);
144155
__pecoff_data_virt_size = ABSOLUTE(. - __pecoff_text_end);
156+
__pecoff_data_virt_end = ABSOLUTE(.);
145157
#endif
146158
_end = .;
147159

arch/riscv/mm/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22

33
CFLAGS_init.o := -mcmodel=medany
4+
ifdef CONFIG_RELOCATABLE
5+
CFLAGS_init.o += -fno-pie
6+
endif
7+
48
ifdef CONFIG_FTRACE
59
CFLAGS_REMOVE_init.o = $(CC_FLAGS_FTRACE)
610
CFLAGS_REMOVE_cacheflush.o = $(CC_FLAGS_FTRACE)

0 commit comments

Comments
 (0)