[PATCH] tools/nolibc: add 64-bit parisc support

Thomas Weißschuh <[email protected]>
Newsgroups org.kernel.vger.linux-parisc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest
Message-ID <[email protected]>
Extend the existing parisc support to also handle 64-bit mode.

Some peculiarities:
* The nonstandard ftruncate64 system call requires a workaround.
* The linker defaults to main() as entry point, which needs to be
  switched to _start() explicitly.
* The linker defaults to dynamic linking, which needs to be disabled
  explicitly.
* With the default -Os, gcc does not use 64-bit multiplication
  instructions, requiring libgcc. Use -O2 instead.
* There is no qemu-user available.
* CONFIG_COMPAT needs to be disabled to avoid build errors due to a
  missing 32-bit vDSO compiler.

Signed-off-by: Thomas Weißschuh <[email protected]>
---
 tools/include/nolibc/arch-parisc.h             | 26 +++++++++++++++++++++++---
 tools/include/nolibc/stdlib.h                  |  2 +-
 tools/testing/selftests/nolibc/Makefile.nolibc |  5 +++++
 tools/testing/selftests/nolibc/run-tests.sh    |  7 ++++---
 4 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/tools/include/nolibc/arch-parisc.h b/tools/include/nolibc/arch-parisc.h
index 417043ecbc53..fd0d1dccabf3 100644
--- a/tools/include/nolibc/arch-parisc.h
+++ b/tools/include/nolibc/arch-parisc.h
@@ -7,9 +7,7 @@
 #ifndef _NOLIBC_ARCH_PARISC_H
 #define _NOLIBC_ARCH_PARISC_H
 
-#if defined(__LP64__)
-#error 64-bit not supported
-#endif
+#include <linux/unistd.h>
 
 #include "compiler.h"
 #include "crt.h"
@@ -167,9 +165,15 @@
 void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_protector _start(void)
 {
 	__asm__ volatile (
+#ifdef __LP64__
+		".import __gp\n"               /* Set up the dp register */
+		"ldil L%__gp, %dp\n"
+		"ldo R%__gp(%r27), %dp\n"
+#else
 		".import $global$\n"           /* Set up the dp register */
 		"ldil L%$global$, %dp\n"
 		"ldo R%$global$(%r27), %dp\n"
+#endif
 
 		"b _start_c\n"                 /* Call _start_c, the load below is executed first */
 
@@ -182,4 +186,20 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_prote
 }
 #endif /* NOLIBC_NO_RUNTIME */
 
+#ifdef __LP64__
+/*
+ * This override is normally only meant for 32-bit architectures.
+ * Put parisc 64-bit has __NR_ftruncate64, so this path is taken.
+ * Add an unused second argument to satisfy the calling convention.
+ */
+static __attribute__((unused))
+int _sys_ftruncate64(int fd, uint64_t length, uint64_t unused)
+{
+	(void)unused;
+
+	return __nolibc_syscall2(__NR_ftruncate64, fd, length);
+}
+#define _sys_ftruncate64 _sys_ftruncate64
+#endif
+
 #endif /* _NOLIBC_ARCH_PARISC_H */
diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h
index 1816c2368b68..6c3c620a04cf 100644
--- a/tools/include/nolibc/stdlib.h
+++ b/tools/include/nolibc/stdlib.h
@@ -230,7 +230,7 @@ int _nolibc_u64toa_base(uint64_t in, char *buffer, unsigned int base, uint64_t r
 
 	/* Generate least significant digit first */
 	do {
-#if defined(__SIZEOF_INT128__) && !defined(__mips__) && !defined(__sparc__)
+#if defined(__SIZEOF_INT128__) && !defined(__mips__) && !defined(__sparc__) && !defined(__hppa__)
 		q = ((unsigned __int128)in * recip) >> 64;
 #else
 		uint64_t p = (uint32_t)in * (recip >> 32);
diff --git a/tools/testing/selftests/nolibc/Makefile.nolibc b/tools/testing/selftests/nolibc/Makefile.nolibc
index d8b71cbfc173..3ca473ec35ef 100644
--- a/tools/testing/selftests/nolibc/Makefile.nolibc
+++ b/tools/testing/selftests/nolibc/Makefile.nolibc
@@ -65,6 +65,7 @@ ARCH_sparc32     = sparc
 ARCH_sparc64     = sparc
 ARCH_sh4         = sh
 ARCH_parisc32    = parisc
+ARCH_parisc64    = parisc64
 ARCH            := $(or $(ARCH_$(XARCH)),$(XARCH))
 
 # kernel image names by architecture
@@ -113,6 +114,7 @@ EXTRACONFIG_sparc32   = -e CONFIG_TMPFS
 EXTRACONFIG_m68k      = -e CONFIG_BLK_DEV_INITRD
 EXTRACONFIG_sh4       = -e CONFIG_BLK_DEV_INITRD -e CONFIG_CMDLINE_FROM_BOOTLOADER
 EXTRACONFIG_alpha     = -e CONFIG_BLK_DEV_INITRD
+EXTRACONFIG_parisc64  = -d CONFIG_COMPAT
 EXTRACONFIG           = $(EXTRACONFIG_$(XARCH))
 
 # optional tests to run (default = all)
@@ -134,6 +136,7 @@ QEMU_ARCH_loongarch  = loongarch64
 QEMU_ARCH_sparc32    = sparc
 QEMU_ARCH_openrisc   = or1k
 QEMU_ARCH_parisc32   = hppa
+QEMU_ARCH_parisc64   = hppa
 QEMU_ARCH            = $(or $(QEMU_ARCH_$(XARCH)),$(XARCH))
 
 QEMU_ARCH_USER_ppc64le = ppc64le
@@ -175,6 +178,7 @@ QEMU_ARGS_m68k       = -M virt -append "console=ttyGF0,115200 panic=-1 $(TEST:%=
 QEMU_ARGS_sh4        = -M r2d -serial file:/dev/stdout -append "console=ttySC1,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
 QEMU_ARGS_openrisc   = -M virt -m 512M -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
 QEMU_ARGS_parisc32   = -M B160L -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_parisc64   = -M C3700 -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
 QEMU_ARGS_alpha      = -M clipper -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
 QEMU_ARGS            = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA)
 
@@ -193,6 +197,7 @@ CFLAGS_x32 = -mx32
 CFLAGS_arm = -marm
 CFLAGS_armthumb = -mthumb -march=armv6t2
 CFLAGS_parisc32 = -mfast-indirect-calls
+CFLAGS_parisc64 = -Wl,--no-dynamic-linker -Wl,--entry=_start -O2
 CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
 CFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
 CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2)
diff --git a/tools/testing/selftests/nolibc/run-tests.sh b/tools/testing/selftests/nolibc/run-tests.sh
index 3da806e2b302..a50a47d9df2c 100755
--- a/tools/testing/selftests/nolibc/run-tests.sh
+++ b/tools/testing/selftests/nolibc/run-tests.sh
@@ -29,7 +29,7 @@ all_archs=(
 	sparc32 sparc64
 	m68k
 	sh4
-	parisc32
+	parisc32 parisc64
 	alpha
 	hexagon
 )
@@ -122,6 +122,7 @@ crosstool_arch() {
 	sparc*) echo sparc64;;
 	x32*) echo x86_64;;
 	parisc32) echo hppa;;
+	parisc64) echo hppa64;;
 	*) echo "$1";;
 	esac
 }
@@ -206,11 +207,11 @@ test_arch() {
 			exit 1
 	esac
 	printf '%-15s' "$arch:"
-	if [ "$arch" = "m68k" -o "$arch" = "sh4" -o "$arch" = "openrisc" -o "$arch" = "parisc32" -o "$arch" = "alpha" ] && [ "$llvm" = "1" ]; then
+	if [ "$arch" = "m68k" -o "$arch" = "sh4" -o "$arch" = "openrisc" -o "$arch" = "parisc*" -o "$arch" = "alpha" ] && [ "$llvm" = "1" ]; then
 		echo "Unsupported configuration"
 		return
 	fi
-	if [ "$arch" = "x32" ] && [ "$test_mode" = "user" ]; then
+	if [ "$arch" = "x32" -o "$arch" = "parisc64" ] && [ "$test_mode" = "user" ]; then
 		echo "Unsupported configuration"
 		return
 	fi

---
base-commit: 7f4233794df172ab1d286dc0fbd70da2cc837654
change-id: 20260407-nolibc-parisc64-3ca0547c2af9

Best regards,
--  
Thomas Weißschuh <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.