mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-11-01 09:13:37 +00:00 
			
		
		
		
	Certain portions of code always need to be position-independent regardless of CONFIG_RELOCATABLE, including code which is executed in an idmap or which is executed before relocations are applied. In some kernel configurations the LLD linker generates position-dependent veneers for such code, and when executed these result in early boot-time failures. Marc Zyngier encountered a boot failure resulting from this when building a (particularly cursed) configuration with LLVM, as he reported to the list: https://lore.kernel.org/linux-arm-kernel/86wmjwvatn.wl-maz@kernel.org/ In Marc's kernel configuration, the .head.text and .rodata.text sections end up more than 128MiB apart, requiring a veneer to branch between the two: | [mark@lakrids:~/src/linux]% usekorg 14.1.0 aarch64-linux-objdump -t vmlinux | grep -w _text | ffff800080000000 g .head.text 0000000000000000 _text | [mark@lakrids:~/src/linux]% usekorg 14.1.0 aarch64-linux-objdump -t vmlinux | grep -w primary_entry | ffff8000889df0e0 g .rodata.text 000000000000006c primary_entry, ... consequently, LLD inserts a position-dependent veneer for the branch from _stext (in .head.text) to primary_entry (in .rodata.text): | ffff800080000000 <_text>: | ffff800080000000: fa405a4d ccmp x18, #0x0, #0xd, pl // pl = nfrst | ffff800080000004: 14003fff b ffff800080010000 <__AArch64AbsLongThunk_primary_entry> ... | ffff800080010000 <__AArch64AbsLongThunk_primary_entry>: | ffff800080010000: 58000050 ldr x16, ffff800080010008 <__AArch64AbsLongThunk_primary_entry+0x8> | ffff800080010004: d61f0200 br x16 | ffff800080010008: 889df0e0 .word 0x889df0e0 | ffff80008001000c: ffff8000 .word 0xffff8000 ... and as this is executed early in boot before the kernel is mapped in TTBR1 this results in a silent boot failure. Fix this by passing '--pic-veneer' to the linker, which will cause the linker to use position-independent veneers, e.g. | ffff800080000000 <_text>: | ffff800080000000: fa405a4d ccmp x18, #0x0, #0xd, pl // pl = nfrst | ffff800080000004: 14003fff b ffff800080010000 <__AArch64ADRPThunk_primary_entry> ... | ffff800080010000 <__AArch64ADRPThunk_primary_entry>: | ffff800080010000: f004e3f0 adrp x16, ffff800089c8f000 <__idmap_text_start> | ffff800080010004: 91038210 add x16, x16, #0xe0 | ffff800080010008: d61f0200 br x16 I've opted to pass '--pic-veneer' unconditionally, as: * In addition to solving the boot failure, these sequences are generally nicer as they require fewer instructions and don't need to perform data accesses. * While the position-independent veneer sequences have a limited +/-2GiB range, this is not a new restriction. Even kernels built with CONFIG_RELOCATABLE=n are limited to 2GiB in size as we have several structues using 32-bit relative offsets and PPREL32 relocations, which are similarly limited to +/-2GiB in range. These include extable entries, jump table entries, and alt_instr entries. * GNU LD defaults to using position-independent veneers, and supports the same '--pic-veneer' option, so this change is not expected to adversely affect GNU LD. I've tested with GNU LD 2.30 to 2.42 inclusive and LLVM 13.0.1 to 19.1.0 inclusive, using the kernel.org binaries from: * https://mirrors.edge.kernel.org/pub/tools/crosstool/ * https://mirrors.edge.kernel.org/pub/tools/llvm/ Signed-off-by: Mark Rutland <mark.rutland@arm.com> Reported-by: Marc Zyngier <maz@kernel.org> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Nathan Chancellor <nathan@kernel.org> Cc: Nick Desaulniers <ndesaulniers@google.com> Cc: Will Deacon <will@kernel.org> Acked-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Nathan Chancellor <nathan@kernel.org> Link: https://lore.kernel.org/r/20240927101838.3061054-1-mark.rutland@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
		
			
				
	
	
		
			246 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			Makefile
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			Makefile
		
	
	
	
	
	
#
 | 
						|
# arch/arm64/Makefile
 | 
						|
#
 | 
						|
# This file is included by the global makefile so that you can add your own
 | 
						|
# architecture-specific flags and dependencies.
 | 
						|
#
 | 
						|
# This file is subject to the terms and conditions of the GNU General Public
 | 
						|
# License.  See the file "COPYING" in the main directory of this archive
 | 
						|
# for more details.
 | 
						|
#
 | 
						|
# Copyright (C) 1995-2001 by Russell King
 | 
						|
 | 
						|
LDFLAGS_vmlinux	:=--no-undefined -X --pic-veneer
 | 
						|
 | 
						|
ifeq ($(CONFIG_RELOCATABLE), y)
 | 
						|
# Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
 | 
						|
# for relative relocs, since this leads to better Image compression
 | 
						|
# with the relocation offsets always being zero.
 | 
						|
LDFLAGS_vmlinux		+= -shared -Bsymbolic -z notext \
 | 
						|
			$(call ld-option, --no-apply-dynamic-relocs)
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
 | 
						|
  ifeq ($(CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419),y)
 | 
						|
LDFLAGS_vmlinux	+= --fix-cortex-a53-843419
 | 
						|
  endif
 | 
						|
endif
 | 
						|
 | 
						|
cc_has_k_constraint := $(call try-run,echo				\
 | 
						|
	'int main(void) {						\
 | 
						|
		asm volatile("and w0, w0, %w0" :: "K" (4294967295));	\
 | 
						|
		return 0;						\
 | 
						|
	}' | $(CC) -S -x c -o "$$TMP" -,,-DCONFIG_CC_HAS_K_CONSTRAINT=1)
 | 
						|
 | 
						|
ifeq ($(CONFIG_BROKEN_GAS_INST),y)
 | 
						|
$(warning Detected assembler with broken .inst; disassembly will be unreliable)
 | 
						|
endif
 | 
						|
 | 
						|
# The GCC option -ffreestanding is required in order to compile code containing
 | 
						|
# ARM/NEON intrinsics in a non C99-compliant environment (such as the kernel)
 | 
						|
CC_FLAGS_FPU	:= -ffreestanding
 | 
						|
# Enable <arm_neon.h>
 | 
						|
CC_FLAGS_FPU	+= -isystem $(shell $(CC) -print-file-name=include)
 | 
						|
CC_FLAGS_NO_FPU	:= -mgeneral-regs-only
 | 
						|
 | 
						|
KBUILD_CFLAGS	+= $(CC_FLAGS_NO_FPU) \
 | 
						|
		   $(compat_vdso) $(cc_has_k_constraint)
 | 
						|
KBUILD_CFLAGS	+= $(call cc-disable-warning, psabi)
 | 
						|
KBUILD_AFLAGS	+= $(compat_vdso)
 | 
						|
 | 
						|
KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon"
 | 
						|
 | 
						|
KBUILD_CFLAGS	+= $(call cc-option,-mabi=lp64)
 | 
						|
KBUILD_AFLAGS	+= $(call cc-option,-mabi=lp64)
 | 
						|
 | 
						|
# Avoid generating .eh_frame* sections.
 | 
						|
ifneq ($(CONFIG_UNWIND_TABLES),y)
 | 
						|
KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables -fno-unwind-tables
 | 
						|
KBUILD_AFLAGS	+= -fno-asynchronous-unwind-tables -fno-unwind-tables
 | 
						|
KBUILD_RUSTFLAGS += -Cforce-unwind-tables=n
 | 
						|
else
 | 
						|
KBUILD_CFLAGS	+= -fasynchronous-unwind-tables
 | 
						|
KBUILD_AFLAGS	+= -fasynchronous-unwind-tables
 | 
						|
KBUILD_RUSTFLAGS += -Cforce-unwind-tables=y -Zuse-sync-unwind=n
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
 | 
						|
prepare: stack_protector_prepare
 | 
						|
stack_protector_prepare: prepare0
 | 
						|
	$(eval KBUILD_CFLAGS += -mstack-protector-guard=sysreg		  \
 | 
						|
				-mstack-protector-guard-reg=sp_el0	  \
 | 
						|
				-mstack-protector-guard-offset=$(shell	  \
 | 
						|
			awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \
 | 
						|
					include/generated/asm-offsets.h))
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
 | 
						|
  KBUILD_CFLAGS += -mbranch-protection=pac-ret+bti
 | 
						|
  KBUILD_RUSTFLAGS += -Zbranch-protection=bti,pac-ret
 | 
						|
else ifeq ($(CONFIG_ARM64_PTR_AUTH_KERNEL),y)
 | 
						|
  KBUILD_RUSTFLAGS += -Zbranch-protection=pac-ret
 | 
						|
  ifeq ($(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET),y)
 | 
						|
    KBUILD_CFLAGS += -mbranch-protection=pac-ret
 | 
						|
  else
 | 
						|
    KBUILD_CFLAGS += -msign-return-address=non-leaf
 | 
						|
  endif
 | 
						|
else
 | 
						|
  KBUILD_CFLAGS += $(call cc-option,-mbranch-protection=none)
 | 
						|
endif
 | 
						|
 | 
						|
# Tell the assembler to support instructions from the latest target
 | 
						|
# architecture.
 | 
						|
#
 | 
						|
# For non-integrated assemblers we'll pass this on the command line, and for
 | 
						|
# integrated assemblers we'll define ARM64_ASM_ARCH and ARM64_ASM_PREAMBLE for
 | 
						|
# inline usage.
 | 
						|
#
 | 
						|
# We cannot pass the same arch flag to the compiler as this would allow it to
 | 
						|
# freely generate instructions which are not supported by earlier architecture
 | 
						|
# versions, which would prevent a single kernel image from working on earlier
 | 
						|
# hardware.
 | 
						|
ifeq ($(CONFIG_AS_HAS_ARMV8_5), y)
 | 
						|
  asm-arch := armv8.5-a
 | 
						|
else ifeq ($(CONFIG_AS_HAS_ARMV8_4), y)
 | 
						|
  asm-arch := armv8.4-a
 | 
						|
else ifeq ($(CONFIG_AS_HAS_ARMV8_3), y)
 | 
						|
  asm-arch := armv8.3-a
 | 
						|
else ifeq ($(CONFIG_AS_HAS_ARMV8_2), y)
 | 
						|
  asm-arch := armv8.2-a
 | 
						|
endif
 | 
						|
 | 
						|
ifdef asm-arch
 | 
						|
KBUILD_CFLAGS	+= -Wa,-march=$(asm-arch) \
 | 
						|
		   -DARM64_ASM_ARCH='"$(asm-arch)"'
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(CONFIG_SHADOW_CALL_STACK), y)
 | 
						|
KBUILD_CFLAGS	+= -ffixed-x18
 | 
						|
KBUILD_RUSTFLAGS += -Zfixed-x18
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
 | 
						|
KBUILD_CPPFLAGS	+= -mbig-endian
 | 
						|
CHECKFLAGS	+= -D__AARCH64EB__
 | 
						|
# Prefer the baremetal ELF build target, but not all toolchains include
 | 
						|
# it so fall back to the standard linux version if needed.
 | 
						|
KBUILD_LDFLAGS	+= -EB $(call ld-option, -maarch64elfb, -maarch64linuxb -z norelro)
 | 
						|
UTS_MACHINE	:= aarch64_be
 | 
						|
else
 | 
						|
KBUILD_CPPFLAGS	+= -mlittle-endian
 | 
						|
CHECKFLAGS	+= -D__AARCH64EL__
 | 
						|
# Same as above, prefer ELF but fall back to linux target if needed.
 | 
						|
KBUILD_LDFLAGS	+= -EL $(call ld-option, -maarch64elf, -maarch64linux -z norelro)
 | 
						|
UTS_MACHINE	:= aarch64
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(CONFIG_LD_IS_LLD), y)
 | 
						|
KBUILD_LDFLAGS	+= -z norelro
 | 
						|
endif
 | 
						|
 | 
						|
CHECKFLAGS	+= -D__aarch64__
 | 
						|
 | 
						|
ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS),y)
 | 
						|
  KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
 | 
						|
  CC_FLAGS_FTRACE := -fpatchable-function-entry=4,2
 | 
						|
else ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_ARGS),y)
 | 
						|
  KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
 | 
						|
  CC_FLAGS_FTRACE := -fpatchable-function-entry=2
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(CONFIG_KASAN_SW_TAGS), y)
 | 
						|
KASAN_SHADOW_SCALE_SHIFT := 4
 | 
						|
else ifeq ($(CONFIG_KASAN_GENERIC), y)
 | 
						|
KASAN_SHADOW_SCALE_SHIFT := 3
 | 
						|
endif
 | 
						|
 | 
						|
KBUILD_CFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
 | 
						|
KBUILD_CPPFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
 | 
						|
KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
 | 
						|
 | 
						|
libs-y		:= arch/arm64/lib/ $(libs-y)
 | 
						|
libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 | 
						|
 | 
						|
# Default target when executing plain make
 | 
						|
boot		:= arch/arm64/boot
 | 
						|
 | 
						|
BOOT_TARGETS	:= Image vmlinuz.efi image.fit
 | 
						|
 | 
						|
PHONY += $(BOOT_TARGETS)
 | 
						|
 | 
						|
ifeq ($(CONFIG_EFI_ZBOOT),)
 | 
						|
KBUILD_IMAGE	:= $(boot)/Image.gz
 | 
						|
else
 | 
						|
KBUILD_IMAGE	:= $(boot)/vmlinuz.efi
 | 
						|
endif
 | 
						|
 | 
						|
all:	$(notdir $(KBUILD_IMAGE))
 | 
						|
 | 
						|
image.fit: dtbs
 | 
						|
 | 
						|
vmlinuz.efi image.fit: Image
 | 
						|
$(BOOT_TARGETS): vmlinux
 | 
						|
	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 | 
						|
 | 
						|
Image.%: Image
 | 
						|
	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 | 
						|
 | 
						|
ifeq ($(CONFIG_COMPRESSED_INSTALL),y)
 | 
						|
 DEFAULT_KBUILD_IMAGE = $(KBUILD_IMAGE)
 | 
						|
else
 | 
						|
 DEFAULT_KBUILD_IMAGE = $(boot)/Image
 | 
						|
endif
 | 
						|
 | 
						|
install: KBUILD_IMAGE := $(DEFAULT_KBUILD_IMAGE)
 | 
						|
install zinstall:
 | 
						|
	$(call cmd,install)
 | 
						|
 | 
						|
archprepare:
 | 
						|
	$(Q)$(MAKE) $(build)=arch/arm64/tools kapi
 | 
						|
ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
 | 
						|
  ifneq ($(CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419),y)
 | 
						|
	@echo "warning: ld does not support --fix-cortex-a53-843419; kernel may be susceptible to erratum" >&2
 | 
						|
  endif
 | 
						|
endif
 | 
						|
ifeq ($(CONFIG_ARM64_USE_LSE_ATOMICS),y)
 | 
						|
  ifneq ($(CONFIG_ARM64_LSE_ATOMICS),y)
 | 
						|
	@echo "warning: LSE atomics not supported by binutils" >&2
 | 
						|
  endif
 | 
						|
endif
 | 
						|
 | 
						|
ifeq ($(KBUILD_EXTMOD),)
 | 
						|
# We need to generate vdso-offsets.h before compiling certain files in kernel/.
 | 
						|
# In order to do that, we should use the archprepare target, but we can't since
 | 
						|
# asm-offsets.h is included in some files used to generate vdso-offsets.h, and
 | 
						|
# asm-offsets.h is built in prepare0, for which archprepare is a dependency.
 | 
						|
# Therefore we need to generate the header after prepare0 has been made, hence
 | 
						|
# this hack.
 | 
						|
prepare: vdso_prepare
 | 
						|
vdso_prepare: prepare0
 | 
						|
	$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso \
 | 
						|
	include/generated/vdso-offsets.h arch/arm64/kernel/vdso/vdso.so
 | 
						|
ifdef CONFIG_COMPAT_VDSO
 | 
						|
	$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 \
 | 
						|
	arch/arm64/kernel/vdso32/vdso.so
 | 
						|
endif
 | 
						|
endif
 | 
						|
 | 
						|
vdso-install-y				+= arch/arm64/kernel/vdso/vdso.so.dbg
 | 
						|
vdso-install-$(CONFIG_COMPAT_VDSO)	+= arch/arm64/kernel/vdso32/vdso32.so.dbg
 | 
						|
 | 
						|
include $(srctree)/scripts/Makefile.defconf
 | 
						|
 | 
						|
PHONY += virtconfig
 | 
						|
virtconfig:
 | 
						|
	$(call merge_into_defconfig_override,defconfig,virt)
 | 
						|
 | 
						|
define archhelp
 | 
						|
  echo  '* Image.gz      - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
 | 
						|
  echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
 | 
						|
  echo  '  image.fit     - Flat Image Tree (arch/$(ARCH)/boot/image.fit)'
 | 
						|
  echo  '  install       - Install kernel (compressed if COMPRESSED_INSTALL set)'
 | 
						|
  echo  '  zinstall      - Install compressed kernel'
 | 
						|
  echo  '                  Install using (your) ~/bin/installkernel or'
 | 
						|
  echo  '                  (distribution) /sbin/installkernel or'
 | 
						|
  echo  '                  install to $$(INSTALL_PATH) and run lilo'
 | 
						|
endef
 |