Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] arm64: Force position-independent veneers
@ 2024-09-27 10:18 Mark Rutland
  2024-09-27 10:42 ` Ard Biesheuvel
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Mark Rutland @ 2024-09-27 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: ardb, catalin.marinas, mark.rutland, maz, nathan, ndesaulniers,
	will

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: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Will Deacon <will@kernel.org>
---
 arch/arm64/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index f6bc3da1ef110..c8e237b20ef29 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -10,7 +10,7 @@
 #
 # Copyright (C) 1995-2001 by Russell King
 
-LDFLAGS_vmlinux	:=--no-undefined -X
+LDFLAGS_vmlinux	:=--no-undefined -X --pic-veneer
 
 ifeq ($(CONFIG_RELOCATABLE), y)
 # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] arm64: Force position-independent veneers
  2024-09-27 10:18 [PATCH] arm64: Force position-independent veneers Mark Rutland
@ 2024-09-27 10:42 ` Ard Biesheuvel
  2024-09-27 13:49 ` Nathan Chancellor
  2024-10-01 13:03 ` Catalin Marinas
  2 siblings, 0 replies; 4+ messages in thread
From: Ard Biesheuvel @ 2024-09-27 10:42 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, catalin.marinas, maz, nathan, ndesaulniers,
	will

On Fri, 27 Sept 2024 at 12:18, Mark Rutland <mark.rutland@arm.com> wrote:
>
> 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.
>
...
>
> 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.
>

Yeah, and accessing literal pools interspersed with the code. I find
it rather bizarre that --pic-veneer is not the default when using the
small code model.

...
>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Reported-by: Marc Zyngier <maz@kernel.org>
> Cc: Ard Biesheuvel <ardb@kernel.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Nick Desaulniers <ndesaulniers@google.com>
> Cc: Will Deacon <will@kernel.org>
> ---
>  arch/arm64/Makefile | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

Acked-by: Ard Biesheuvel <ardb@kernel.org>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] arm64: Force position-independent veneers
  2024-09-27 10:18 [PATCH] arm64: Force position-independent veneers Mark Rutland
  2024-09-27 10:42 ` Ard Biesheuvel
@ 2024-09-27 13:49 ` Nathan Chancellor
  2024-10-01 13:03 ` Catalin Marinas
  2 siblings, 0 replies; 4+ messages in thread
From: Nathan Chancellor @ 2024-09-27 13:49 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, ardb, catalin.marinas, maz, ndesaulniers, will

On Fri, Sep 27, 2024 at 11:18:38AM +0100, Mark Rutland wrote:
> 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:

Heh, I admire the "particularly cursed" bit.

> 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: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Nick Desaulniers <ndesaulniers@google.com>
> Cc: Will Deacon <will@kernel.org>

Thanks for the patch!

Reviewed-by: Nathan Chancellor <nathan@kernel.org>

> ---
>  arch/arm64/Makefile | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index f6bc3da1ef110..c8e237b20ef29 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -10,7 +10,7 @@
>  #
>  # Copyright (C) 1995-2001 by Russell King
>  
> -LDFLAGS_vmlinux	:=--no-undefined -X
> +LDFLAGS_vmlinux	:=--no-undefined -X --pic-veneer
>  
>  ifeq ($(CONFIG_RELOCATABLE), y)
>  # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
> -- 
> 2.30.2
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] arm64: Force position-independent veneers
  2024-09-27 10:18 [PATCH] arm64: Force position-independent veneers Mark Rutland
  2024-09-27 10:42 ` Ard Biesheuvel
  2024-09-27 13:49 ` Nathan Chancellor
@ 2024-10-01 13:03 ` Catalin Marinas
  2 siblings, 0 replies; 4+ messages in thread
From: Catalin Marinas @ 2024-10-01 13:03 UTC (permalink / raw)
  To: linux-arm-kernel, Mark Rutland
  Cc: Will Deacon, ardb, maz, nathan, ndesaulniers

On Fri, 27 Sep 2024 11:18:38 +0100, Mark Rutland wrote:
> 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.
> 
> [...]

Applied to arm64 (for-next/fixes), thanks!

[1/1] arm64: Force position-independent veneers
      https://git.kernel.org/arm64/c/9abe390e689f

-- 
Catalin



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-10-01 13:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-27 10:18 [PATCH] arm64: Force position-independent veneers Mark Rutland
2024-09-27 10:42 ` Ard Biesheuvel
2024-09-27 13:49 ` Nathan Chancellor
2024-10-01 13:03 ` Catalin Marinas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox