diff --git a/arch/x86/purgatory/.gitignore b/arch/x86/purgatory/.gitignore index d2be1500671de4..71bd99d98906c8 100644 --- a/arch/x86/purgatory/.gitignore +++ b/arch/x86/purgatory/.gitignore @@ -1 +1,2 @@ purgatory.chk +purgatory.lds diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile index bc31863c5ee638..dfc030a4cca917 100644 --- a/arch/x86/purgatory/Makefile +++ b/arch/x86/purgatory/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 OBJECT_FILES_NON_STANDARD := y -purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o +purgatory-y := purgatory.o purgatory.lds stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o targets += $(purgatory-y) PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) @@ -14,20 +14,11 @@ $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE CFLAGS_sha256.o := -D__DISABLE_EXPORTS -D__NO_FORTIFY -# When profile-guided optimization is enabled, llvm emits two different -# overlapping text sections, which is not supported by kexec. Remove profile -# optimization flags. -KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%,$(KBUILD_CFLAGS)) - -# When LTO is enabled, llvm emits many text sections, which is not supported -# by kexec. Remove -flto=* flags. -KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) - # When linking purgatory.ro with -r unresolved symbols are not checked, # also link a purgatory.chk binary without -r to check for unresolved symbols. -PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib -LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS) -LDFLAGS_purgatory.chk := $(PURGATORY_LDFLAGS) +PURGATORY_LDFLAGS := -z nodefaultlib +LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS) -T +LDFLAGS_purgatory.chk := -e purgatory_start $(PURGATORY_LDFLAGS) targets += purgatory.ro purgatory.chk # Sanitizer, etc. runtimes are unavailable and cannot be linked here. @@ -80,7 +71,7 @@ CFLAGS_string.o += $(PURGATORY_CFLAGS) asflags-remove-y += $(foreach x, -g -gdwarf-4 -gdwarf-5, $(x) -Wa,$(x)) -$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE +$(obj)/purgatory.ro: $(obj)/purgatory.lds $(PURGATORY_OBJS) FORCE $(call if_changed,ld) $(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE diff --git a/arch/x86/purgatory/purgatory.lds.S b/arch/x86/purgatory/purgatory.lds.S new file mode 100644 index 00000000000000..4fb15594264227 --- /dev/null +++ b/arch/x86/purgatory/purgatory.lds.S @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include +#include + +OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT) + +#undef i386 + +#ifdef CONFIG_X86_64 +OUTPUT_ARCH(i386:x86-64) +#else +OUTPUT_ARCH(i386) +#endif + +ENTRY(purgatory_start) + +SECTIONS +{ + . = 0; + + .kexec-purgatory : { + *(.kexec-purgatory) + } + + .text : { + _text = .; + *(.text .text.*) + *(.ltext .ltext.*) + _etext = .; + } + + .rodata : { + _rodata = .; + *(.rodata .rodata.*) + *(.lrodata .lrodata.*) + _erodata = .; + } + + .data : { + _data = .; + *(.data .data.*) + _edata = .; + } + + . = ALIGN(L1_CACHE_BYTES); + .bss : { + _bss = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(8); /* For convenience during zeroing */ + _ebss = .; + } + _end = .; + + ELF_DETAILS + + DISCARDS + /DISCARD/ : { + *(.note.GNU-stack .note.gnu.property) + *(.llvm_addrsig) + } +}