Skip to content

Commit 9ad3df7

Browse files
nathanchanceintel-lab-lkp
authored andcommitted
x86/purgatory: Add a linker script
Commit 8652d44 ("kexec: support purgatories with .text.hot sections") added a warning when the purgatory has more than one .text section, which is unsupported. A couple of changes have been made to the x86 purgatory's Makefile to prevent the compiler from splitting the .text section as a result: 97b6b9c ("x86/purgatory: remove PGO flags") 75b2f7e ("x86/purgatory: Remove LTO flags") Unfortunately, there may be compiler optimizations that add other text sections that cannot be disabled. For example, starting with LLVM 18, large text is emitted in '.ltext', which happens for the purgatory due to commit e16c298 ("x86/purgatory: Change compiler flags from -mcmodel=kernel to -mcmodel=large to fix kexec relocation errors"), but there are out of line assembly files that use '.text'. $ llvm-readelf -S arch/x86/purgatory/purgatory.ro | rg ' .[a-z]?text' [ 1] .text PROGBITS 0000000000000000 000040 0000d0 00 AX 0 0 16 [ 2] .ltext PROGBITS 0000000000000000 000110 0015a6 00 AXl 0 0 16 To avoid the runtime warning when the purgatory has been built with LLVM 18, add a linker script that explicitly describes the sections of the purgatory.ro and use it to merge '.ltext' and '.lrodata' back into '.text' and '.rodata' to match the behavior of GCC and LLVM prior to the optimization, as the distinction between small and large text is not important in this case. This results in no warnings with '--orphan-handling=warn' with either GNU or LLVM toolchains and the resulting kernels can properly kexec other kernels. This linker script is based on arch/s390/purgatory/purgatory.lds.S and Ricardo Ribalda's prior attempt to add one for arch/x86 [1]. As a consequence of this change, the aforementioned flag changes can be reverted because the '.text.*' sections generated by those options will be combined properly by the linker script, which avoids the only reason they were added in the first place. kexec continues to work with LTO enabled. [1]: https://lore.kernel.org/[email protected]/ Reported-by: ns <[email protected]> Closes: ClangBuiltLinux#2016 Signed-off-by: Nathan Chancellor <[email protected]>
1 parent 0bbac3f commit 9ad3df7

File tree

3 files changed

+69
-14
lines changed

3 files changed

+69
-14
lines changed

arch/x86/purgatory/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
purgatory.chk
2+
purgatory.lds

arch/x86/purgatory/Makefile

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
OBJECT_FILES_NON_STANDARD := y
33

4-
purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
4+
purgatory-y := purgatory.o purgatory.lds stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
55

66
targets += $(purgatory-y)
77
PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
@@ -14,20 +14,11 @@ $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE
1414

1515
CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY
1616

17-
# When profile-guided optimization is enabled, llvm emits two different
18-
# overlapping text sections, which is not supported by kexec. Remove profile
19-
# optimization flags.
20-
KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%,$(KBUILD_CFLAGS))
21-
22-
# When LTO is enabled, llvm emits many text sections, which is not supported
23-
# by kexec. Remove -flto=* flags.
24-
KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS))
25-
2617
# When linking purgatory.ro with -r unresolved symbols are not checked,
2718
# also link a purgatory.chk binary without -r to check for unresolved symbols.
28-
PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib
29-
LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS)
30-
LDFLAGS_purgatory.chk := $(PURGATORY_LDFLAGS)
19+
PURGATORY_LDFLAGS := -z nodefaultlib
20+
LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS) -T
21+
LDFLAGS_purgatory.chk := -e purgatory_start $(PURGATORY_LDFLAGS)
3122
targets += purgatory.ro purgatory.chk
3223

3324
# Sanitizer, etc. runtimes are unavailable and cannot be linked here.
@@ -80,7 +71,7 @@ CFLAGS_string.o += $(PURGATORY_CFLAGS)
8071

8172
asflags-remove-y += $(foreach x, -g -gdwarf-4 -gdwarf-5, $(x) -Wa,$(x))
8273

83-
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
74+
$(obj)/purgatory.ro: $(obj)/purgatory.lds $(PURGATORY_OBJS) FORCE
8475
$(call if_changed,ld)
8576

8677
$(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE

arch/x86/purgatory/purgatory.lds.S

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#include <asm-generic/vmlinux.lds.h>
4+
#include <asm/cache.h>
5+
6+
OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT)
7+
8+
#undef i386
9+
10+
#ifdef CONFIG_X86_64
11+
OUTPUT_ARCH(i386:x86-64)
12+
#else
13+
OUTPUT_ARCH(i386)
14+
#endif
15+
16+
ENTRY(purgatory_start)
17+
18+
SECTIONS
19+
{
20+
. = 0;
21+
22+
.kexec-purgatory : {
23+
*(.kexec-purgatory)
24+
}
25+
26+
.text : {
27+
_text = .;
28+
*(.text .text.*)
29+
*(.ltext .ltext.*)
30+
_etext = .;
31+
}
32+
33+
.rodata : {
34+
_rodata = .;
35+
*(.rodata .rodata.*)
36+
*(.lrodata .lrodata.*)
37+
_erodata = .;
38+
}
39+
40+
.data : {
41+
_data = .;
42+
*(.data .data.*)
43+
_edata = .;
44+
}
45+
46+
. = ALIGN(L1_CACHE_BYTES);
47+
.bss : {
48+
_bss = .;
49+
*(.bss .bss.*)
50+
*(COMMON)
51+
. = ALIGN(8); /* For convenience during zeroing */
52+
_ebss = .;
53+
}
54+
_end = .;
55+
56+
ELF_DETAILS
57+
58+
DISCARDS
59+
/DISCARD/ : {
60+
*(.note.GNU-stack .note.gnu.property)
61+
*(.llvm_addrsig)
62+
}
63+
}

0 commit comments

Comments
 (0)