Skip to contentSkip to conversation

Option to build big-endian with ELFv2 ABI

PATCH Applied Nicholas Piggin 3 participants 7 messages Nov 28, 2022 – Dec 8, 2022

Subsystems (3)
lore
Share & tools
lore

Nicholas Piggin

author reviewer
#0 lore raw

v6 cover Option to build big-endian with ELFv2 ABI

This is hopefully the final attempt. Luis was happy for the module patch to go via the powerpc tree, so I've put the the ELFv2 for big endian build patches into the series. Hopefully we can deprecate the ELFv1 ABI

Since v5, I cleaned up patch 2 as per Christophe's review. And patch 4 I removed the EXPERT depends so it's easier to test. It's marked as experimental, but we should soon make it default and try to deprecate the v1 ABI so we can eventually remove it.

Thanks,
Nick

Nicholas Piggin (4):
module: add module_elf_check_arch for module-specific checks powerpc/64: Add module check for ELF ABI version powerpc/64: Add big-endian ELFv2 flavour to crypto VMX asm generation powerpc/64: Option to build big-endian with ELFv2 ABI

 arch/powerpc/Kconfig                   | 21 +++++++++++++++++++++
 arch/powerpc/kernel/module_64.c        | 10 ++++++++++
 arch/powerpc/platforms/Kconfig.cputype |  4 ++--
 drivers/crypto/vmx/Makefile            | 12 +++++++++++-
 drivers/crypto/vmx/ppc-xlate.pl        | 10 ++++++----
 include/linux/moduleloader.h           |  3 +++
 kernel/module/main.c                   | 10 ++++++++++
 7 files changed, 63 insertions(+), 7 deletions(-)
Signature · 1 line
2.37.2
author reviewer
#1 lore raw

PATCH v6 1/4 module: add module_elf_check_arch for module-specific checks

The elf_check_arch() function is also used to test compatibility of usermode binaries. Kernel modules may have more specific requirements, for example powerpc would like to test for ABI version compatibility.

Add a weak module_elf_check_arch() that defaults to true, and call it from elf_validity_check().

Cc Michael Ellerman <[email protected]>
[np: added changelog, adjust name, rebase]
---
 include/linux/moduleloader.h |  3 +++
 kernel/module/main.c         | 10 ++++++++++
 2 files changed, 13 insertions(+)
include/linux/moduleloader.h +3 -0
index 9e09d11ffe5b..7b4587a19189 100644
@@ -13,6 +13,9 @@
  * must be implemented by each architecture.
  */
 
+/* arch may override to do additional checking of ELF header architecture */
+bool module_elf_check_arch(Elf_Ehdr *hdr);
+
 /* Adjust arch-specific sections.  Return 0 on success.  */
 int module_frob_arch_sections(Elf_Ehdr *hdr,
 			      Elf_Shdr *sechdrs,
kernel/module/main.c +10 -0
index d02d39c7174e..7b3f6fb0d428 100644
@@ -1674,6 +1674,11 @@ static int elf_validity_check(struct load_info *info)
 		       info->hdr->e_machine);
 		goto no_exec;
 	}
+	if (!module_elf_check_arch(info->hdr)) {
+		pr_err("Invalid module architecture in ELF header: %u\n",
+		       info->hdr->e_machine);
+		goto no_exec;
+	}
 	if (info->hdr->e_shentsize != sizeof(Elf_Shdr)) {
 		pr_err("Invalid ELF section header size\n");
 		goto no_exec;
@@ -2247,6 +2252,11 @@ static void flush_module_icache(const struct module *mod)
 			   (unsigned long)mod->core_layout.base + mod->core_layout.size);
 }
 
+bool __weak module_elf_check_arch(Elf_Ehdr *hdr)
+{
+	return true;
+}
+
 int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
 				     Elf_Shdr *sechdrs,
 				     char *secstrings,
Signature · 1 line
2.37.2
author reviewer
#2 lore raw

PATCH v6 2/4 powerpc/64: Add module check for ELF ABI version

In reply to Nicholas Piggin

Override the generic module ELF check to provide a check for the ELF ABI version. This becomes important if we allow big-endian ELF ABI V2 builds but it doesn't hurt to check now.

Cc Jessica Yu <[email protected]>
[np: split patch, added changelog, adjust to Jessica's proposal]
---
 arch/powerpc/kernel/module_64.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
arch/powerpc/kernel/module_64.c +10 -0
index 7e45dc98df8a..ff045644f13f 100644
@@ -31,6 +31,16 @@
    this, and makes other things simpler.  Anton?
    --RR.  */
 
+bool module_elf_check_arch(Elf_Ehdr *hdr)
+{
+	unsigned long abi_level = hdr->e_flags & 0x3;
+
+	if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2))
+		return abi_level == 2;
+	else
+		return abi_level < 2;
+}
+
 #ifdef CONFIG_PPC64_ELF_ABI_V2
 
 static func_desc_t func_desc(unsigned long addr)
Signature · 1 line
2.37.2
author reviewer
#3 lore raw

PATCH v6 3/4 powerpc/64: Add big-endian ELFv2 flavour to crypto VMX asm generation

In reply to Nicholas Piggin

This allows asm generation for big-endian ELFv2 builds.

---
 drivers/crypto/vmx/Makefile     | 12 +++++++++++-
 drivers/crypto/vmx/ppc-xlate.pl | 10 ++++++----
 2 files changed, 17 insertions(+), 5 deletions(-)
drivers/crypto/vmx/Makefile +11 -1
index 2560cfea1dec..e33c7238e7f8 100644
@@ -2,8 +2,18 @@
 obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o
 vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o
 
+ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
+override flavour := linux-ppc64le
+else
+ifdef CONFIG_PPC64_ELF_ABI_V2
+override flavour := linux-ppc64-elfv2
+else
+override flavour := linux-ppc64
+endif
+endif
+
 quiet_cmd_perl = PERL    $@
-      cmd_perl = $(PERL) $< $(if $(CONFIG_CPU_LITTLE_ENDIAN), linux-ppc64le, linux-ppc64) > $@
+      cmd_perl = $(PERL) $< $(flavour) > $@
 
 targets += aesp8-ppc.S ghashp8-ppc.S
 
drivers/crypto/vmx/ppc-xlate.pl +6 -4
index 36db2ef09e5b..b583898c11ae 100644
@@ -9,6 +9,8 @@ open STDOUT,">$output" || die "can't open $output: $!";
 
 my %GLOBALS;
 my $dotinlocallabels=($flavour=~/linux/)?1:0;
+my $elfv2abi=(($flavour =~ /linux-ppc64le/) or ($flavour =~ /linux-ppc64-elfv2/))?1:0;
+my $dotfunctions=($elfv2abi=~1)?0:1;
 
 ################################################################
 # directives which need special treatment on different platforms
@@ -40,7 +42,7 @@ my $globl = sub {
 };
 my $text = sub {
     my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text";
-    $ret = ".abiversion	2\n".$ret	if ($flavour =~ /linux.*64le/);
+    $ret = ".abiversion	2\n".$ret	if ($elfv2abi);
     $ret;
 };
 my $machine = sub {
@@ -56,8 +58,8 @@ my $size = sub {
     if ($flavour =~ /linux/)
     {	shift;
 	my $name = shift; $name =~ s|^[\.\_]||;
-	my $ret  = ".size	$name,.-".($flavour=~/64$/?".":"").$name;
-	$ret .= "\n.size	.$name,.-.$name" if ($flavour=~/64$/);
+	my $ret  = ".size	$name,.-".($dotfunctions?".":"").$name;
+	$ret .= "\n.size	.$name,.-.$name" if ($dotfunctions);
 	$ret;
     }
     else
@@ -142,7 +144,7 @@ my $vmr = sub {
 
 # Some ABIs specify vrsave, special-purpose register #256, as reserved
 # for system use.
-my $no_vrsave = ($flavour =~ /linux-ppc64le/);
+my $no_vrsave = ($elfv2abi);
 my $mtspr = sub {
     my ($f,$idx,$ra) = @_;
     if ($idx == 256 && $no_vrsave) {
Signature · 1 line
2.37.2
author reviewer
#4 lore raw

PATCH v6 4/4 powerpc/64: Option to build big-endian with ELFv2 ABI

In reply to Nicholas Piggin

Provide an option to build big-endian kernels using the ELFv2 ABI. This works on GCC only for now. Clang is rumored to support this, but core build files need updating first, at least.

This gives big-endian kernels useful advantages of the ELFv2 ABI, e.g., less stack usage, -mprofile-kernel support, better compatibility with eBPF tools.

BE+ELFv2 is not officially supported by the GNU toolchain, but it works fine in testing and has been used by some userspace for some time (e.g., Void Linux).

---
 arch/powerpc/Kconfig                   | 21 +++++++++++++++++++++
 arch/powerpc/platforms/Kconfig.cputype |  4 ++--
 2 files changed, 23 insertions(+), 2 deletions(-)
arch/powerpc/Kconfig +21 -0
index 2ca5418457ed..2d0d80bcc24a 100644
@@ -1,6 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 source "arch/powerpc/platforms/Kconfig.cputype"
 
+config CC_HAS_ELFV2
+	def_bool PPC64 && $(cc-option, -mabi=elfv2)
+
 config 32BIT
 	bool
 	default y if PPC32
@@ -583,6 +586,24 @@ config KEXEC_FILE
 config ARCH_HAS_KEXEC_PURGATORY
 	def_bool KEXEC_FILE
 
+config PPC64_BIG_ENDIAN_ELF_ABI_V2
+	bool "Build big-endian kernel using ELF ABI V2 (EXPERIMENTAL)"
+	depends on PPC64 && CPU_BIG_ENDIAN
+	depends on CC_HAS_ELFV2
+	depends on LD_IS_BFD && LD_VERSION >= 22400
+	default n
+	help
+	  This builds the kernel image using the "Power Architecture 64-Bit ELF
+	  V2 ABI Specification", which has a reduced stack overhead and faster
+	  function calls. This internal kernel ABI option does not affect
+          userspace compatibility.
+
+	  The V2 ABI is standard for 64-bit little-endian, but for big-endian
+	  it is less well tested by kernel and toolchain. However some distros
+	  build userspace this way, and it can produce a functioning kernel.
+
+	  This requires GCC and binutils 2.24 or newer.
+
 config RELOCATABLE
 	bool "Build a relocatable kernel"
 	depends on PPC64 || (FLATMEM && (44x || PPC_85xx))
arch/powerpc/platforms/Kconfig.cputype +2 -2
index 0c4eed9aea80..6e94d45f3baa 100644
@@ -575,10 +575,10 @@ config CPU_LITTLE_ENDIAN
 endchoice
 
 config PPC64_ELF_ABI_V1
-	def_bool PPC64 && CPU_BIG_ENDIAN
+	def_bool PPC64 && (CPU_BIG_ENDIAN && !PPC64_BIG_ENDIAN_ELF_ABI_V2)
 
 config PPC64_ELF_ABI_V2
-	def_bool PPC64 && CPU_LITTLE_ENDIAN
+	def_bool PPC64 && !PPC64_ELF_ABI_V1
 
 config PPC64_BOOT_WRAPPER
 	def_bool n
Signature · 1 line
2.37.2
Reviewed-by on the v6 series
#5 lore raw
In reply to Nicholas Piggin
Quoted 10 lines · Nicholas Piggin

This is hopefully the final attempt. Luis was happy for the module patch to go via the powerpc tree, so I've put the the ELFv2 for big endian build patches into the series. Hopefully we can deprecate the ELFv1 ABI

Since v5, I cleaned up patch 2 as per Christophe's review. And patch 4 I removed the EXPERT depends so it's easier to test. It's marked as experimental, but we should soon make it default and try to deprecate the v1 ABI so we can eventually remove it.

I did some builds and boot tested them in qemu fine.

Quoted 22 lines

Thanks,
Nick

Nicholas Piggin (4):
module: add module_elf_check_arch for module-specific checks powerpc/64: Add module check for ELF ABI version powerpc/64: Add big-endian ELFv2 flavour to crypto VMX asm generation powerpc/64: Option to build big-endian with ELFv2 ABI

 arch/powerpc/Kconfig                   | 21 +++++++++++++++++++++
 arch/powerpc/kernel/module_64.c        | 10 ++++++++++
 arch/powerpc/platforms/Kconfig.cputype |  4 ++--
 drivers/crypto/vmx/Makefile            | 12 +++++++++++-
 drivers/crypto/vmx/ppc-xlate.pl        | 10 ++++++----
 include/linux/moduleloader.h           |  3 +++
 kernel/module/main.c                   | 10 ++++++++++
 7 files changed, 63 insertions(+), 7 deletions(-)

--
2.37.2

#6 lore raw
In reply to Nicholas Piggin
Quoted 11 lines · Nicholas Piggin

This is hopefully the final attempt. Luis was happy for the module patch to go via the powerpc tree, so I've put the the ELFv2 for big endian build patches into the series. Hopefully we can deprecate the ELFv1 ABI

Since v5, I cleaned up patch 2 as per Christophe's review. And patch 4 I removed the EXPERT depends so it's easier to test. It's marked as experimental, but we should soon make it default and try to deprecate the v1 ABI so we can eventually remove it.

[...]

Applied to powerpc/next.

[1/4] module: add module_elf_check_arch for module-specific checks

      https://git.kernel.org/powerpc/c/f9231a996e229c13d23f907352c2cea84bd1c30a
[2/4] powerpc/64: Add module check for ELF ABI version
      https://git.kernel.org/powerpc/c/de3d098dd1fc635535e3689c5d4aa0684242adde
[3/4] powerpc/64: Add big-endian ELFv2 flavour to crypto VMX asm generation
      https://git.kernel.org/powerpc/c/505ea33089dcfc3ee3201b0fcb94751165805413
[4/4] powerpc/64: Option to build big-endian with ELFv2 ABI
      https://git.kernel.org/powerpc/c/5017b45946722bdd20ac255c9ae7273b78d1f12e

cheers