Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tools/nolibc: add support for SuperH

Add support for SuperH/"sh" to nolibc.
Only sh4 is tested for now.

The startup code is special:

__nolibc_entrypoint_epilogue() calls __builtin_unreachable() which emits
a call to abort(). To make this work a function prologue is generated to
set up a GOT pointer which corrupts "sp".
__builtin_unreachable() is necessary for __attribute__((noreturn)).
Also depending on compiler flags (for example -fPIC) even more prologue
is generated.

Work around this by defining a nested function in asm.

Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70216
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Acked-by: Rob Landley <rob@landley.net>
Acked-by: D. Jeff Dionne <jeff@coresemi.io>
Tested-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Link: https://lore.kernel.org/r/20250623-nolibc-sh-v2-3-0f5b4b303025@weissschuh.net

+173 -1
+162
tools/include/nolibc/arch-sh.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + /* 3 + * SuperH specific definitions for NOLIBC 4 + * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net> 5 + */ 6 + 7 + #ifndef _NOLIBC_ARCH_SH_H 8 + #define _NOLIBC_ARCH_SH_H 9 + 10 + #include "compiler.h" 11 + #include "crt.h" 12 + 13 + /* 14 + * Syscalls for SuperH: 15 + * - registers are 32bit wide 16 + * - syscall number is passed in r3 17 + * - arguments are in r4, r5, r6, r7, r0, r1, r2 18 + * - the system call is performed by calling trapa #31 19 + * - syscall return value is in r0 20 + */ 21 + 22 + #define my_syscall0(num) \ 23 + ({ \ 24 + register long _num __asm__ ("r3") = (num); \ 25 + register long _ret __asm__ ("r0"); \ 26 + \ 27 + __asm__ volatile ( \ 28 + "trapa #31" \ 29 + : "=r"(_ret) \ 30 + : "r"(_num) \ 31 + : "memory", "cc" \ 32 + ); \ 33 + _ret; \ 34 + }) 35 + 36 + #define my_syscall1(num, arg1) \ 37 + ({ \ 38 + register long _num __asm__ ("r3") = (num); \ 39 + register long _ret __asm__ ("r0"); \ 40 + register long _arg1 __asm__ ("r4") = (long)(arg1); \ 41 + \ 42 + __asm__ volatile ( \ 43 + "trapa #31" \ 44 + : "=r"(_ret) \ 45 + : "r"(_num), "r"(_arg1) \ 46 + : "memory", "cc" \ 47 + ); \ 48 + _ret; \ 49 + }) 50 + 51 + #define my_syscall2(num, arg1, arg2) \ 52 + ({ \ 53 + register long _num __asm__ ("r3") = (num); \ 54 + register long _ret __asm__ ("r0"); \ 55 + register long _arg1 __asm__ ("r4") = (long)(arg1); \ 56 + register long _arg2 __asm__ ("r5") = (long)(arg2); \ 57 + \ 58 + __asm__ volatile ( \ 59 + "trapa #31" \ 60 + : "=r"(_ret) \ 61 + : "r"(_num), "r"(_arg1), "r"(_arg2) \ 62 + : "memory", "cc" \ 63 + ); \ 64 + _ret; \ 65 + }) 66 + 67 + #define my_syscall3(num, arg1, arg2, arg3) \ 68 + ({ \ 69 + register long _num __asm__ ("r3") = (num); \ 70 + register long _ret __asm__ ("r0"); \ 71 + register long _arg1 __asm__ ("r4") = (long)(arg1); \ 72 + register long _arg2 __asm__ ("r5") = (long)(arg2); \ 73 + register long _arg3 __asm__ ("r6") = (long)(arg3); \ 74 + \ 75 + __asm__ volatile ( \ 76 + "trapa #31" \ 77 + : "=r"(_ret) \ 78 + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3) \ 79 + : "memory", "cc" \ 80 + ); \ 81 + _ret; \ 82 + }) 83 + 84 + #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 85 + ({ \ 86 + register long _num __asm__ ("r3") = (num); \ 87 + register long _ret __asm__ ("r0"); \ 88 + register long _arg1 __asm__ ("r4") = (long)(arg1); \ 89 + register long _arg2 __asm__ ("r5") = (long)(arg2); \ 90 + register long _arg3 __asm__ ("r6") = (long)(arg3); \ 91 + register long _arg4 __asm__ ("r7") = (long)(arg4); \ 92 + \ 93 + __asm__ volatile ( \ 94 + "trapa #31" \ 95 + : "=r"(_ret) \ 96 + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ 97 + : "memory", "cc" \ 98 + ); \ 99 + _ret; \ 100 + }) 101 + 102 + #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 103 + ({ \ 104 + register long _num __asm__ ("r3") = (num); \ 105 + register long _ret __asm__ ("r0"); \ 106 + register long _arg1 __asm__ ("r4") = (long)(arg1); \ 107 + register long _arg2 __asm__ ("r5") = (long)(arg2); \ 108 + register long _arg3 __asm__ ("r6") = (long)(arg3); \ 109 + register long _arg4 __asm__ ("r7") = (long)(arg4); \ 110 + register long _arg5 __asm__ ("r0") = (long)(arg5); \ 111 + \ 112 + __asm__ volatile ( \ 113 + "trapa #31" \ 114 + : "=r"(_ret) \ 115 + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 116 + "r"(_arg5) \ 117 + : "memory", "cc" \ 118 + ); \ 119 + _ret; \ 120 + }) 121 + 122 + #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 123 + ({ \ 124 + register long _num __asm__ ("r3") = (num); \ 125 + register long _ret __asm__ ("r0"); \ 126 + register long _arg1 __asm__ ("r4") = (long)(arg1); \ 127 + register long _arg2 __asm__ ("r5") = (long)(arg2); \ 128 + register long _arg3 __asm__ ("r6") = (long)(arg3); \ 129 + register long _arg4 __asm__ ("r7") = (long)(arg4); \ 130 + register long _arg5 __asm__ ("r0") = (long)(arg5); \ 131 + register long _arg6 __asm__ ("r1") = (long)(arg6); \ 132 + \ 133 + __asm__ volatile ( \ 134 + "trapa #31" \ 135 + : "=r"(_ret) \ 136 + : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 137 + "r"(_arg5), "r"(_arg6) \ 138 + : "memory", "cc" \ 139 + ); \ 140 + _ret; \ 141 + }) 142 + 143 + /* startup code */ 144 + void _start_wrapper(void); 145 + void __attribute__((weak,noreturn)) __nolibc_entrypoint __no_stack_protector _start_wrapper(void) 146 + { 147 + __asm__ volatile ( 148 + ".global _start\n" /* The C function will have a prologue, */ 149 + ".type _start, @function\n" /* corrupting "sp" */ 150 + ".weak _start\n" 151 + "_start:\n" 152 + 153 + "mov sp, r4\n" /* save argc pointer to r4, as arg1 of _start_c */ 154 + "bsr _start_c\n" /* transfer to c runtime */ 155 + "nop\n" /* delay slot */ 156 + 157 + ".size _start, .-_start\n" 158 + ); 159 + __nolibc_entrypoint_epilogue(); 160 + } 161 + 162 + #endif /* _NOLIBC_ARCH_SH_H */
+2
tools/include/nolibc/arch.h
··· 35 35 #include "arch-sparc.h" 36 36 #elif defined(__m68k__) 37 37 #include "arch-m68k.h" 38 + #elif defined(__sh__) 39 + #include "arch-sh.h" 38 40 #else 39 41 #error Unsupported Architecture 40 42 #endif
+7
tools/testing/selftests/nolibc/Makefile.nolibc
··· 62 62 ARCH_s390x = s390 63 63 ARCH_sparc32 = sparc 64 64 ARCH_sparc64 = sparc 65 + ARCH_sh4 = sh 65 66 ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) 66 67 67 68 # kernel image names by architecture ··· 90 89 IMAGE_sparc32 = arch/sparc/boot/image 91 90 IMAGE_sparc64 = arch/sparc/boot/image 92 91 IMAGE_m68k = vmlinux 92 + IMAGE_sh4 = arch/sh/boot/zImage 93 93 IMAGE = $(objtree)/$(IMAGE_$(XARCH)) 94 94 IMAGE_NAME = $(notdir $(IMAGE)) 95 95 ··· 119 117 DEFCONFIG_sparc32 = sparc32_defconfig 120 118 DEFCONFIG_sparc64 = sparc64_defconfig 121 119 DEFCONFIG_m68k = virt_defconfig 120 + DEFCONFIG_sh4 = rts7751r2dplus_defconfig 122 121 DEFCONFIG = $(DEFCONFIG_$(XARCH)) 123 122 124 123 EXTRACONFIG_arm = -e CONFIG_NAMESPACES 125 124 EXTRACONFIG_armthumb = -e CONFIG_NAMESPACES 126 125 EXTRACONFIG_m68k = -e CONFIG_BLK_DEV_INITRD 126 + EXTRACONFIG_sh4 = -e CONFIG_BLK_DEV_INITRD -e CONFIG_CMDLINE_FROM_BOOTLOADER 127 127 EXTRACONFIG = $(EXTRACONFIG_$(XARCH)) 128 128 129 129 # optional tests to run (default = all) ··· 156 152 QEMU_ARCH_sparc32 = sparc 157 153 QEMU_ARCH_sparc64 = sparc64 158 154 QEMU_ARCH_m68k = m68k 155 + QEMU_ARCH_sh4 = sh4 159 156 QEMU_ARCH = $(QEMU_ARCH_$(XARCH)) 160 157 161 158 QEMU_ARCH_USER_ppc64le = ppc64le ··· 196 191 QEMU_ARGS_sparc32 = -M SS-5 -m 256M -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 197 192 QEMU_ARGS_sparc64 = -M sun4u -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 198 193 QEMU_ARGS_m68k = -M virt -append "console=ttyGF0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 194 + QEMU_ARGS_sh4 = -M r2d -serial file:/dev/stdout -append "console=ttySC1,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 199 195 QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA) 200 196 201 197 # OUTPUT is only set when run from the main makefile, otherwise ··· 224 218 CFLAGS_mips64le = -EL -mabi=64 -march=mips64r6 225 219 CFLAGS_mips64be = -EB -mabi=64 -march=mips64r2 226 220 CFLAGS_sparc32 = $(call cc-option,-m32) 221 + CFLAGS_sh4 = -ml -m4 227 222 ifeq ($(origin XARCH),command line) 228 223 CFLAGS_XARCH = $(CFLAGS_$(XARCH)) 229 224 endif
+2 -1
tools/testing/selftests/nolibc/run-tests.sh
··· 27 27 loongarch 28 28 sparc32 sparc64 29 29 m68k 30 + sh4 30 31 ) 31 32 archs="${all_archs[@]}" 32 33 ··· 188 187 echo "Unsupported configuration" 189 188 return 190 189 fi 191 - if [ "$arch" = "m68k" ] && [ "$llvm" = "1" ]; then 190 + if [ "$arch" = "m68k" -o "$arch" = "sh4" ] && [ "$llvm" = "1" ]; then 192 191 echo "Unsupported configuration" 193 192 return 194 193 fi