* [PATCH] tools/nolibc: add support for OpenRISC / or1k
@ 2026-04-28 15:48 Thomas Weißschuh
2026-04-28 17:04 ` Stafford Horne
0 siblings, 1 reply; 3+ messages in thread
From: Thomas Weißschuh @ 2026-04-28 15:48 UTC (permalink / raw)
To: Willy Tarreau, Jonas Bonn, Stefan Kristiansson, Stafford Horne
Cc: linux-openrisc, linux-kernel, Thomas Weißschuh
Add support for OpenRISC / or1k to nolibc.
_start() uses the same wrapper construct as in arch-sh.h.
libgcc is necessary as OpenRISC is missing 64-bit multiplication.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
tools/include/nolibc/Makefile | 2 +-
tools/include/nolibc/arch-openrisc.h | 176 +++++++++++++++++++++++++
tools/include/nolibc/arch.h | 2 +
tools/testing/selftests/nolibc/Makefile.nolibc | 5 +
tools/testing/selftests/nolibc/run-tests.sh | 4 +-
5 files changed, 187 insertions(+), 2 deletions(-)
diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile
index 872c318f50d4..2cb4d610fe53 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 openrisc powerpc riscv s390 sh sparc x86
arch_files := arch.h $(addsuffix .h, $(addprefix arch-, $(architectures)))
all_files := \
alloca.h \
diff --git a/tools/include/nolibc/arch-openrisc.h b/tools/include/nolibc/arch-openrisc.h
new file mode 100644
index 000000000000..de2df1715504
--- /dev/null
+++ b/tools/include/nolibc/arch-openrisc.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * openrisc specific definitions for NOLIBC
+ * Copyright (C) 2026 Thomas Weißschuh <linux@weissschuh.net>
+ */
+
+#ifndef _NOLIBC_ARCH_OPENRISC_H
+#define _NOLIBC_ARCH_OPENRISC_H
+
+#include "compiler.h"
+#include "crt.h"
+
+/*
+ * Syscalls for SuperH:
+ * - syscall number is passed in r11
+ * - arguments are in r3, r4, r5, r6, r7, r8
+ * - the system call is performed by calling l.sys 1
+ * - syscall return value is in r11
+ */
+
+#define _NOLIBC_SYSCALL_CLOBBERLIST \
+ "r12", "r13", "r15", "r17", "r19", "r21", "r23", "r25", "r27", "r29", "r31", "memory"
+
+#define __nolibc_syscall0(num) \
+({ \
+ register long _num __asm__ ("r11") = (num); \
+ register long _ret __asm__ ("r11"); \
+ \
+ __asm__ volatile ( \
+ "l.sys 1\n" \
+ "l.nop\n" \
+ : "=r"(_ret) \
+ : "r"(_num) \
+ : "r3", "r4", "r5", "r6", "r7", "r8", \
+ _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall1(num, arg1) \
+({ \
+ register long _num __asm__ ("r11") = (num); \
+ register long _ret __asm__ ("r11"); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ \
+ __asm__ volatile ( \
+ "l.sys 1\n" \
+ "l.nop\n" \
+ : "=r"(_ret) \
+ : "r"(_num), "r"(_arg1) \
+ : "r4", "r5", "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall2(num, arg1, arg2) \
+({ \
+ register long _num __asm__ ("r11") = (num); \
+ register long _ret __asm__ ("r11"); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ \
+ __asm__ volatile ( \
+ "l.sys 1\n" \
+ "l.nop\n" \
+ : "=r"(_ret) \
+ : "r"(_num), "r"(_arg1), "r"(_arg2) \
+ : "r5", "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall3(num, arg1, arg2, arg3) \
+({ \
+ register long _num __asm__ ("r11") = (num); \
+ register long _ret __asm__ ("r11"); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ \
+ __asm__ volatile ( \
+ "l.sys 1\n" \
+ "l.nop\n" \
+ : "=r"(_ret) \
+ : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3) \
+ : "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall4(num, arg1, arg2, arg3, arg4) \
+({ \
+ register long _num __asm__ ("r11") = (num); \
+ register long _ret __asm__ ("r11"); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ register long _arg4 __asm__ ("r6") = (long)(arg4); \
+ \
+ __asm__ volatile ( \
+ "l.sys 1\n" \
+ "l.nop\n" \
+ : "=r"(_ret) \
+ : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
+ : "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+({ \
+ register long _num __asm__ ("r11") = (num); \
+ register long _ret __asm__ ("r11"); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ register long _arg4 __asm__ ("r6") = (long)(arg4); \
+ register long _arg5 __asm__ ("r7") = (long)(arg5); \
+ \
+ __asm__ volatile ( \
+ "l.sys 1\n" \
+ "l.nop\n" \
+ : "=r"(_ret) \
+ : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+ "r"(_arg5) \
+ : "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+({ \
+ register long _num __asm__ ("r11") = (num); \
+ register long _ret __asm__ ("r11"); \
+ register long _arg1 __asm__ ("r3") = (long)(arg1); \
+ register long _arg2 __asm__ ("r4") = (long)(arg2); \
+ register long _arg3 __asm__ ("r5") = (long)(arg3); \
+ register long _arg4 __asm__ ("r6") = (long)(arg4); \
+ register long _arg5 __asm__ ("r7") = (long)(arg5); \
+ register long _arg6 __asm__ ("r8") = (long)(arg6); \
+ \
+ __asm__ volatile ( \
+ "l.sys 1\n" \
+ "l.nop\n" \
+ : "=r"(_ret) \
+ : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+ "r"(_arg5), "r"(_arg6) \
+ : _NOLIBC_SYSCALL_CLOBBERLIST \
+ ); \
+ _ret; \
+})
+
+#ifndef NOLIBC_NO_RUNTIME
+/* startup code */
+void _start_wrapper(void);
+void __attribute__((weak,noreturn))
+__nolibc_entrypoint __nolibc_no_stack_protector
+_start_wrapper(void)
+{
+ __asm__ volatile (
+ ".global _start\n" /* The C function will have a prologue, */
+ ".type _start, @function\n" /* corrupting "sp" */
+ ".weak _start\n"
+ "_start:\n"
+
+ "l.or r3,sp,sp\n" /* save stack pointer to 3, as arg1 of _start_c */
+ "l.jal _start_c\n" /* transfer to c runtime */
+ "l.nop\n"
+
+ ".size _start, .-_start\n"
+ );
+ __nolibc_entrypoint_epilogue();
+}
+#endif /* NOLIBC_NO_RUNTIME */
+
+#endif /* _NOLIBC_ARCH_OPENRISC_H */
diff --git a/tools/include/nolibc/arch.h b/tools/include/nolibc/arch.h
index a3adaf433f2c..55009dcafe9e 100644
--- a/tools/include/nolibc/arch.h
+++ b/tools/include/nolibc/arch.h
@@ -28,6 +28,8 @@
#include "arch-m68k.h"
#elif defined(__sh__)
#include "arch-sh.h"
+#elif defined(__or1k__)
+#include "arch-openrisc.h"
#else
#error Unsupported Architecture
#endif
diff --git a/tools/testing/selftests/nolibc/Makefile.nolibc b/tools/testing/selftests/nolibc/Makefile.nolibc
index f30bc68470cc..91f5a284f4e6 100644
--- a/tools/testing/selftests/nolibc/Makefile.nolibc
+++ b/tools/testing/selftests/nolibc/Makefile.nolibc
@@ -92,6 +92,7 @@ IMAGE_sparc32 = arch/sparc/boot/image
IMAGE_sparc64 = arch/sparc/boot/image
IMAGE_m68k = vmlinux
IMAGE_sh4 = arch/sh/boot/zImage
+IMAGE_openrisc = vmlinux
IMAGE = $(objtree)/$(IMAGE_$(XARCH))
IMAGE_NAME = $(notdir $(IMAGE))
@@ -121,6 +122,7 @@ DEFCONFIG_sparc32 = sparc32_defconfig
DEFCONFIG_sparc64 = sparc64_defconfig
DEFCONFIG_m68k = virt_defconfig
DEFCONFIG_sh4 = rts7751r2dplus_defconfig
+DEFCONFIG_openrisc = virt_defconfig
DEFCONFIG = $(DEFCONFIG_$(XARCH))
EXTRACONFIG_x32 = -e CONFIG_X86_X32_ABI
@@ -159,6 +161,7 @@ QEMU_ARCH_sparc32 = sparc
QEMU_ARCH_sparc64 = sparc64
QEMU_ARCH_m68k = m68k
QEMU_ARCH_sh4 = sh4
+QEMU_ARCH_openrisc = or1k
QEMU_ARCH = $(QEMU_ARCH_$(XARCH))
QEMU_ARCH_USER_ppc64le = ppc64le
@@ -199,6 +202,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_openrisc = -M virt -m 512M -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA)
# OUTPUT is only set when run from the main makefile, otherwise
@@ -233,6 +237,7 @@ CFLAGS_XARCH = $(CFLAGS_$(XARCH))
endif
LDLIBS_ppc = $(if $(LLVM),,-lgcc)
+LDLIBS_openrisc = $(if $(LLVM),,-lgcc)
LDLIBS = $(LDLIBS_$(XARCH))
include Makefile.include
diff --git a/tools/testing/selftests/nolibc/run-tests.sh b/tools/testing/selftests/nolibc/run-tests.sh
index cd439096fdf3..c25ee4be2df4 100755
--- a/tools/testing/selftests/nolibc/run-tests.sh
+++ b/tools/testing/selftests/nolibc/run-tests.sh
@@ -21,6 +21,7 @@ all_archs=(
i386 x86_64 x32
arm64 arm armthumb
mips32le mips32be mipsn32le mipsn32be mips64le mips64be
+ openrisc
ppc ppc64 ppc64le
riscv32 riscv64
s390x
@@ -107,6 +108,7 @@ crosstool_arch() {
case "$1" in
arm64) echo aarch64;;
armthumb) echo arm;;
+ openrisc) echo or1k;;
ppc) echo powerpc;;
ppc64) echo powerpc64;;
ppc64le) echo powerpc64;;
@@ -185,7 +187,7 @@ test_arch() {
exit 1
esac
printf '%-15s' "$arch:"
- if [ "$arch" = "m68k" -o "$arch" = "sh4" ] && [ "$llvm" = "1" ]; then
+ if [ "$arch" = "m68k" -o "$arch" = "sh4" -o "$arch" = "openrisc" ] && [ "$llvm" = "1" ]; then
echo "Unsupported configuration"
return
fi
---
base-commit: 8bf37d924968cf26ab95f644c981a28086e372af
change-id: 20260415-nolibc-openrisc-a1ab91c41fe5
Best regards,
--
Thomas Weißschuh <linux@weissschuh.net>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] tools/nolibc: add support for OpenRISC / or1k
2026-04-28 15:48 [PATCH] tools/nolibc: add support for OpenRISC / or1k Thomas Weißschuh
@ 2026-04-28 17:04 ` Stafford Horne
2026-04-28 17:33 ` Thomas Weißschuh
0 siblings, 1 reply; 3+ messages in thread
From: Stafford Horne @ 2026-04-28 17:04 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Willy Tarreau, Jonas Bonn, Stefan Kristiansson, linux-openrisc,
linux-kernel
On Tue, Apr 28, 2026 at 05:48:51PM +0200, Thomas Weißschuh wrote:
> Add support for OpenRISC / or1k to nolibc.
>
> _start() uses the same wrapper construct as in arch-sh.h.
> libgcc is necessary as OpenRISC is missing 64-bit multiplication.
There are a few minor issues with this patch. Could you give any background
for this? What are you working on? Just getting more coverage in the test
suite? Do you have any results for or1k, considering one of the issues I
highlighted before I am not sure this will compile as is.
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> tools/include/nolibc/Makefile | 2 +-
> tools/include/nolibc/arch-openrisc.h | 176 +++++++++++++++++++++++++
> tools/include/nolibc/arch.h | 2 +
> tools/testing/selftests/nolibc/Makefile.nolibc | 5 +
> tools/testing/selftests/nolibc/run-tests.sh | 4 +-
> 5 files changed, 187 insertions(+), 2 deletions(-)
>
> diff --git a/tools/include/nolibc/Makefile b/tools/include/nolibc/Makefile
> index 872c318f50d4..2cb4d610fe53 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 openrisc powerpc riscv s390 sh sparc x86
> arch_files := arch.h $(addsuffix .h, $(addprefix arch-, $(architectures)))
> all_files := \
> alloca.h \
> diff --git a/tools/include/nolibc/arch-openrisc.h b/tools/include/nolibc/arch-openrisc.h
> new file mode 100644
> index 000000000000..de2df1715504
> --- /dev/null
> +++ b/tools/include/nolibc/arch-openrisc.h
> @@ -0,0 +1,176 @@
> +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
> +/*
> + * openrisc specific definitions for NOLIBC
> + * Copyright (C) 2026 Thomas Weißschuh <linux@weissschuh.net>
> + */
> +
> +#ifndef _NOLIBC_ARCH_OPENRISC_H
> +#define _NOLIBC_ARCH_OPENRISC_H
> +
> +#include "compiler.h"
> +#include "crt.h"
> +
> +/*
> + * Syscalls for SuperH:
> + * - syscall number is passed in r11
> + * - arguments are in r3, r4, r5, r6, r7, r8
> + * - the system call is performed by calling l.sys 1
> + * - syscall return value is in r11
> + */
> +
> +#define _NOLIBC_SYSCALL_CLOBBERLIST \
> + "r12", "r13", "r15", "r17", "r19", "r21", "r23", "r25", "r27", "r29", "r31", "memory"
> +
> +#define __nolibc_syscall0(num) \
> +({ \
> + register long _num __asm__ ("r11") = (num); \
> + register long _ret __asm__ ("r11"); \
> + \
> + __asm__ volatile ( \
> + "l.sys 1\n" \
> + "l.nop\n" \
We do not need l.nop for l.sys instructions. They do not have a delay-slot line
branches.
> + : "=r"(_ret) \
> + : "r"(_num) \
> + : "r3", "r4", "r5", "r6", "r7", "r8", \
> + _NOLIBC_SYSCALL_CLOBBERLIST \
> + ); \
> + _ret; \
> +})
> +
> +#define __nolibc_syscall1(num, arg1) \
> +({ \
> + register long _num __asm__ ("r11") = (num); \
> + register long _ret __asm__ ("r11"); \
> + register long _arg1 __asm__ ("r3") = (long)(arg1); \
> + \
> + __asm__ volatile ( \
> + "l.sys 1\n" \
> + "l.nop\n" \
> + : "=r"(_ret) \
> + : "r"(_num), "r"(_arg1) \
> + : "r4", "r5", "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
> + ); \
> + _ret; \
> +})
> +
> +#define __nolibc_syscall2(num, arg1, arg2) \
> +({ \
> + register long _num __asm__ ("r11") = (num); \
> + register long _ret __asm__ ("r11"); \
> + register long _arg1 __asm__ ("r3") = (long)(arg1); \
> + register long _arg2 __asm__ ("r4") = (long)(arg2); \
> + \
> + __asm__ volatile ( \
> + "l.sys 1\n" \
> + "l.nop\n" \
> + : "=r"(_ret) \
> + : "r"(_num), "r"(_arg1), "r"(_arg2) \
> + : "r5", "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
> + ); \
> + _ret; \
> +})
> +
> +#define __nolibc_syscall3(num, arg1, arg2, arg3) \
> +({ \
> + register long _num __asm__ ("r11") = (num); \
> + register long _ret __asm__ ("r11"); \
> + register long _arg1 __asm__ ("r3") = (long)(arg1); \
> + register long _arg2 __asm__ ("r4") = (long)(arg2); \
> + register long _arg3 __asm__ ("r5") = (long)(arg3); \
> + \
> + __asm__ volatile ( \
> + "l.sys 1\n" \
> + "l.nop\n" \
> + : "=r"(_ret) \
> + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3) \
> + : "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
> + ); \
> + _ret; \
> +})
> +
> +#define __nolibc_syscall4(num, arg1, arg2, arg3, arg4) \
> +({ \
> + register long _num __asm__ ("r11") = (num); \
> + register long _ret __asm__ ("r11"); \
> + register long _arg1 __asm__ ("r3") = (long)(arg1); \
> + register long _arg2 __asm__ ("r4") = (long)(arg2); \
> + register long _arg3 __asm__ ("r5") = (long)(arg3); \
> + register long _arg4 __asm__ ("r6") = (long)(arg4); \
> + \
> + __asm__ volatile ( \
> + "l.sys 1\n" \
> + "l.nop\n" \
> + : "=r"(_ret) \
> + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
> + : "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
> + ); \
> + _ret; \
> +})
> +
> +#define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
> +({ \
> + register long _num __asm__ ("r11") = (num); \
> + register long _ret __asm__ ("r11"); \
> + register long _arg1 __asm__ ("r3") = (long)(arg1); \
> + register long _arg2 __asm__ ("r4") = (long)(arg2); \
> + register long _arg3 __asm__ ("r5") = (long)(arg3); \
> + register long _arg4 __asm__ ("r6") = (long)(arg4); \
> + register long _arg5 __asm__ ("r7") = (long)(arg5); \
> + \
> + __asm__ volatile ( \
> + "l.sys 1\n" \
> + "l.nop\n" \
> + : "=r"(_ret) \
> + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
> + "r"(_arg5) \
> + : "r8", _NOLIBC_SYSCALL_CLOBBERLIST \
> + ); \
> + _ret; \
> +})
> +
> +#define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
> +({ \
> + register long _num __asm__ ("r11") = (num); \
> + register long _ret __asm__ ("r11"); \
> + register long _arg1 __asm__ ("r3") = (long)(arg1); \
> + register long _arg2 __asm__ ("r4") = (long)(arg2); \
> + register long _arg3 __asm__ ("r5") = (long)(arg3); \
> + register long _arg4 __asm__ ("r6") = (long)(arg4); \
> + register long _arg5 __asm__ ("r7") = (long)(arg5); \
> + register long _arg6 __asm__ ("r8") = (long)(arg6); \
> + \
> + __asm__ volatile ( \
> + "l.sys 1\n" \
> + "l.nop\n" \
> + : "=r"(_ret) \
> + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
> + "r"(_arg5), "r"(_arg6) \
> + : _NOLIBC_SYSCALL_CLOBBERLIST \
> + ); \
> + _ret; \
> +})
> +
> +#ifndef NOLIBC_NO_RUNTIME
> +/* startup code */
> +void _start_wrapper(void);
> +void __attribute__((weak,noreturn))
> +__nolibc_entrypoint __nolibc_no_stack_protector
> +_start_wrapper(void)
> +{
> + __asm__ volatile (
> + ".global _start\n" /* The C function will have a prologue, */
> + ".type _start, @function\n" /* corrupting "sp" */
> + ".weak _start\n"
> + "_start:\n"
> +
> + "l.or r3,sp,sp\n" /* save stack pointer to 3, as arg1 of _start_c */
What is sp here? There is no sp alias in OpenRISC, should it be r1? Does this
compile?
> + "l.jal _start_c\n" /* transfer to c runtime */
> + "l.nop\n"
The l.or can go in the delay slot.
Also, preferrably we use spaces between args, and a space to indicate a delay
slot e.g.
"l.jal _start_c\n"
"l.or r3, r1, r1\n"
> +
> + ".size _start, .-_start\n"
> + );
> + __nolibc_entrypoint_epilogue();
> +}
> +#endif /* NOLIBC_NO_RUNTIME */
> +
> +#endif /* _NOLIBC_ARCH_OPENRISC_H */
> diff --git a/tools/include/nolibc/arch.h b/tools/include/nolibc/arch.h
> index a3adaf433f2c..55009dcafe9e 100644
> --- a/tools/include/nolibc/arch.h
> +++ b/tools/include/nolibc/arch.h
> @@ -28,6 +28,8 @@
> #include "arch-m68k.h"
> #elif defined(__sh__)
> #include "arch-sh.h"
> +#elif defined(__or1k__)
> +#include "arch-openrisc.h"
> #else
> #error Unsupported Architecture
> #endif
> diff --git a/tools/testing/selftests/nolibc/Makefile.nolibc b/tools/testing/selftests/nolibc/Makefile.nolibc
> index f30bc68470cc..91f5a284f4e6 100644
> --- a/tools/testing/selftests/nolibc/Makefile.nolibc
> +++ b/tools/testing/selftests/nolibc/Makefile.nolibc
> @@ -92,6 +92,7 @@ IMAGE_sparc32 = arch/sparc/boot/image
> IMAGE_sparc64 = arch/sparc/boot/image
> IMAGE_m68k = vmlinux
> IMAGE_sh4 = arch/sh/boot/zImage
> +IMAGE_openrisc = vmlinux
> IMAGE = $(objtree)/$(IMAGE_$(XARCH))
> IMAGE_NAME = $(notdir $(IMAGE))
>
> @@ -121,6 +122,7 @@ DEFCONFIG_sparc32 = sparc32_defconfig
> DEFCONFIG_sparc64 = sparc64_defconfig
> DEFCONFIG_m68k = virt_defconfig
> DEFCONFIG_sh4 = rts7751r2dplus_defconfig
> +DEFCONFIG_openrisc = virt_defconfig
> DEFCONFIG = $(DEFCONFIG_$(XARCH))
>
> EXTRACONFIG_x32 = -e CONFIG_X86_X32_ABI
> @@ -159,6 +161,7 @@ QEMU_ARCH_sparc32 = sparc
> QEMU_ARCH_sparc64 = sparc64
> QEMU_ARCH_m68k = m68k
> QEMU_ARCH_sh4 = sh4
> +QEMU_ARCH_openrisc = or1k
> QEMU_ARCH = $(QEMU_ARCH_$(XARCH))
>
> QEMU_ARCH_USER_ppc64le = ppc64le
> @@ -199,6 +202,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_openrisc = -M virt -m 512M -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
> QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA)
>
> # OUTPUT is only set when run from the main makefile, otherwise
> @@ -233,6 +237,7 @@ CFLAGS_XARCH = $(CFLAGS_$(XARCH))
> endif
>
> LDLIBS_ppc = $(if $(LLVM),,-lgcc)
> +LDLIBS_openrisc = $(if $(LLVM),,-lgcc)
> LDLIBS = $(LDLIBS_$(XARCH))
>
> include Makefile.include
> diff --git a/tools/testing/selftests/nolibc/run-tests.sh b/tools/testing/selftests/nolibc/run-tests.sh
> index cd439096fdf3..c25ee4be2df4 100755
> --- a/tools/testing/selftests/nolibc/run-tests.sh
> +++ b/tools/testing/selftests/nolibc/run-tests.sh
> @@ -21,6 +21,7 @@ all_archs=(
> i386 x86_64 x32
> arm64 arm armthumb
> mips32le mips32be mipsn32le mipsn32be mips64le mips64be
> + openrisc
> ppc ppc64 ppc64le
> riscv32 riscv64
> s390x
> @@ -107,6 +108,7 @@ crosstool_arch() {
> case "$1" in
> arm64) echo aarch64;;
> armthumb) echo arm;;
> + openrisc) echo or1k;;
> ppc) echo powerpc;;
> ppc64) echo powerpc64;;
> ppc64le) echo powerpc64;;
> @@ -185,7 +187,7 @@ test_arch() {
> exit 1
> esac
> printf '%-15s' "$arch:"
> - if [ "$arch" = "m68k" -o "$arch" = "sh4" ] && [ "$llvm" = "1" ]; then
> + if [ "$arch" = "m68k" -o "$arch" = "sh4" -o "$arch" = "openrisc" ] && [ "$llvm" = "1" ]; then
> echo "Unsupported configuration"
> return
> fi
The rest looks ok to me.
Thanks,
-Stafford
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] tools/nolibc: add support for OpenRISC / or1k
2026-04-28 17:04 ` Stafford Horne
@ 2026-04-28 17:33 ` Thomas Weißschuh
0 siblings, 0 replies; 3+ messages in thread
From: Thomas Weißschuh @ 2026-04-28 17:33 UTC (permalink / raw)
To: Stafford Horne
Cc: Willy Tarreau, Jonas Bonn, Stefan Kristiansson, linux-openrisc,
linux-kernel
On 2026-04-28 18:04:47+0100, Stafford Horne wrote:
> On Tue, Apr 28, 2026 at 05:48:51PM +0200, Thomas Weißschuh wrote:
> > Add support for OpenRISC / or1k to nolibc.
> >
> > _start() uses the same wrapper construct as in arch-sh.h.
> > libgcc is necessary as OpenRISC is missing 64-bit multiplication.
>
> There are a few minor issues with this patch.
Thanks for taking a look!
> Could you give any background for this? What are you working on?
> Just getting more coverage in the test suite?
I have no specific goal. In general I'd like for nolibc to support all
architectures which are supported by Linux.
> Do you have any results for or1k, considering one of the issues I
> highlighted before I am not sure this will compile as is.
This compiled fine for me and ran the full nolibc testsuite.
More details below.
With "highlighted before", do you mean "below"?
> > Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> > ---
> > tools/include/nolibc/Makefile | 2 +-
> > tools/include/nolibc/arch-openrisc.h | 176 +++++++++++++++++++++++++
> > tools/include/nolibc/arch.h | 2 +
> > tools/testing/selftests/nolibc/Makefile.nolibc | 5 +
> > tools/testing/selftests/nolibc/run-tests.sh | 4 +-
> > 5 files changed, 187 insertions(+), 2 deletions(-)
(...)
> > +#define __nolibc_syscall0(num) \
> > +({ \
> > + register long _num __asm__ ("r11") = (num); \
> > + register long _ret __asm__ ("r11"); \
> > + \
> > + __asm__ volatile ( \
> > + "l.sys 1\n" \
> > + "l.nop\n" \
>
> We do not need l.nop for l.sys instructions. They do not have a delay-slot line
> branches.
Ack, I'll remove them.
> > + : "=r"(_ret) \
> > + : "r"(_num) \
> > + : "r3", "r4", "r5", "r6", "r7", "r8", \
> > + _NOLIBC_SYSCALL_CLOBBERLIST \
> > + ); \
> > + _ret; \
> > +})
(...)
> > +#ifndef NOLIBC_NO_RUNTIME
> > +/* startup code */
> > +void _start_wrapper(void);
> > +void __attribute__((weak,noreturn))
> > +__nolibc_entrypoint __nolibc_no_stack_protector
> > +_start_wrapper(void)
> > +{
> > + __asm__ volatile (
> > + ".global _start\n" /* The C function will have a prologue, */
> > + ".type _start, @function\n" /* corrupting "sp" */
> > + ".weak _start\n"
> > + "_start:\n"
> > +
> > + "l.or r3,sp,sp\n" /* save stack pointer to 3, as arg1 of _start_c */
>
> What is sp here? There is no sp alias in OpenRISC, should it be r1? Does this
> compile?
It compiles and works with my fairly modern GCC.
It is translated to 'r1'. If it is not idiomatic, I'll change it to r1.
>
> > + "l.jal _start_c\n" /* transfer to c runtime */
> > + "l.nop\n"
>
> The l.or can go in the delay slot.
Ack.
> Also, preferrably we use spaces between args, and a space to indicate a delay
> slot e.g.
>
> "l.jal _start_c\n"
> "l.or r3, r1, r1\n"
I'd prefer to keep this aligned with the rest of nolibc instead of
aligning it with the arch/openrisc/ code.
> > +
> > + ".size _start, .-_start\n"
> > + );
> > + __nolibc_entrypoint_epilogue();
> > +}
> > +#endif /* NOLIBC_NO_RUNTIME */
(...)
> The rest looks ok to me.
Thanks!
Thomas
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-04-28 17:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 15:48 [PATCH] tools/nolibc: add support for OpenRISC / or1k Thomas Weißschuh
2026-04-28 17:04 ` Stafford Horne
2026-04-28 17:33 ` Thomas Weißschuh
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.