Re: [PATCH v3 2/2] tools/nolibc: add support for 32-bit parisc
Helge Deller <[email protected]>
| Newsgroups | org.kernel.vger.linux-parisc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 4/9/26 10:38, Thomas Weißschuh wrote: > On 2026-04-09 00:15:54+0200, Helge Deller wrote: >> * Thomas Weißschuh <[email protected]>: >>> Extend nolibc to target the 32-bit parisc architecture. >>> 64-bit is not yet supported. >>> >>> Signed-off-by: Thomas Weißschuh <[email protected]> >>> --- >>> tools/include/nolibc/Makefile | 2 +- >>> tools/include/nolibc/arch-parisc.h | 178 +++++++++++++++++++++++++ >>> tools/include/nolibc/arch.h | 2 + >>> tools/testing/selftests/nolibc/Makefile.nolibc | 6 + >>> tools/testing/selftests/nolibc/run-tests.sh | 8 +- >>> 5 files changed, 194 insertions(+), 2 deletions(-) >>> >>> diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile >>> index 7455097cff69..81187126bf93 100644 >>> --- a/tools/include/nolibc/Makefile >>> +++ b/tools/include/nolibc/Makefile >>> @@ -17,7 +17,7 @@ endif >>> # it defaults to this nolibc directory. >>> OUTPUT ?= $(CURDIR)/ >>> >>> -architectures := arm arm64 loongarch m68k mips powerpc riscv s390 sh sparc x86 >>> +architectures := arm arm64 loongarch m68k mips parisc powerpc riscv s390 sh sparc x86 >>> arch_files := arch.h $(addsuffix .h, $(addprefix arch-, $(architectures))) >>> all_files := \ >>> byteswap.h \ >>> diff --git a/tools/include/nolibc/arch-parisc.h b/tools/include/nolibc/arch-parisc.h >>> new file mode 100644 >>> index 000000000000..8580be5c9c58 >>> --- /dev/null >>> +++ b/tools/include/nolibc/arch-parisc.h >>> @@ -0,0 +1,178 @@ >>> +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ >>> +/* >>> + * parisc/hppa (32-bit) specific definitions for NOLIBC >>> + * Copyright (C) 2026 Thomas Weißschuh <[email protected]> >>> + */ >>> + >>> +#ifndef _NOLIBC_ARCH_PARISC_H >>> +#define _NOLIBC_ARCH_PARISC_H >>> + >>> +#if defined(__LP64__) >>> +#error 64-bit not supported >>> +#endif >>> + >>> +#include "compiler.h" >>> +#include "crt.h" >>> + >>> +/* Syscalls for parisc : >>> + * - syscall number is passed in r20 >>> + * - arguments are in r26 to r21 >>> + * - the system call is performed by calling "ble 0x100(%sr2, %r0)", >>> + * the instruction after that is executed first, use it to load the number >> better: >> the instruction after that is in the delay slot and executed before the jump >> to 0x100 actually happens. > > Ack. > >>> + * - syscall return comes in r28 >>> + * - the arguments are cast to long and assigned into the target >>> + * registers which are then simply passed as registers to the asm code, >>> + * so that we don't have to experience issues with register constraints. >> >> side-note: >> this is actually really tricky. >> I've seen cases, where the syscalls were not using the given registers, >> because the callers were too complicated and the compiler could not guarantee >> to actually use the given register. > > This is weird. We are using the same pattern for all other > architectures, too and so far that worked fine. > Was it a compiler bug? No, it can happen if too many registers are in use and if you e.g. hand over arg0 = a+x-z, arg1 = 100-z/3, .... (I mean if you put in multiple calculations). For now I would ignore it. > (...) > >>> +#ifndef NOLIBC_NO_RUNTIME >>> +/* startup code */ >>> +void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) >>> +{ >>> + __asm__ volatile ( >>> + ".import $global$\n" /* Set up the dp register */ >>> + "ldil L%$global$, %dp\n" >>> + "ldo R%$global$(%r27), %dp\n" >>> + >>> + "ldo -4(%r24), %r26\n" /* The sp register is special on parisc. >>> + * r24 points to argv. Subtract 4 to get &argc. >>> + * Pass that as first argument to _start_c. >>> + */ >>> + >>> + "b,n _start_c\n" >> >> you can change that to "b _start_c\" (without ",n") and move it >> one line up before the "ldo -4..." instruction. It's a little bit faster". >> The ldo is then in the delay slot. > > Ack. > >>> + ); >>> + __nolibc_entrypoint_epilogue(); >>> +} >>> +#endif /* NOLIBC_NO_RUNTIME */ > > (...) > >>> QEMU_ARCH_USER_ppc64le = ppc64le >>> @@ -199,6 +203,7 @@ QEMU_ARGS_sparc32 = -M SS-5 -m 256M -append "console=ttyS0,115200 panic=-1 $( >>> QEMU_ARGS_sparc64 = -M sun4u -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" >>> QEMU_ARGS_m68k = -M virt -append "console=ttyGF0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" >>> QEMU_ARGS_sh4 = -M r2d -serial file:/dev/stdout -append "console=ttySC1,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" >>> +QEMU_ARGS_parisc32 = -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" >> >> You could change that to (untested): >> QEMU_ARGS_parisc32 = -M B160L -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" -nographic > > Will try. I tried. You are using "-display none" which is nearly the same. The difference is: With "-display none", you will see the output starting when the kernel switches to serial port". With "-nographics" you will see everything from the start of the virtual computer, e.g. BIOS messages, boot loader and initial kernel messages. For your usecase either is OK. >>> QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA) >>> >>> # OUTPUT is only set when run from the main makefile, otherwise >>> @@ -215,6 +220,7 @@ CFLAGS_i386 = $(call cc-option,-m32) >>> CFLAGS_x32 = -mx32 >>> CFLAGS_arm = -marm >>> CFLAGS_armthumb = -mthumb -march=armv6t2 >>> +CFLAGS_parisc32 = -mfast-indirect-calls >> >> would be good if we could go without this... >> But for the beginning it's ok. > > Why? As nolibc is compiled again for each application, any users which > don't want this don't get it. For nolibc-test it avoids a dependency on > libgcc. Yeah, but I think we can avoid libgcc other ways too. I will try once it's upstreamed.. Helge