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.

Merge tag 'nolibc-20250724-for-6.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc

Pull nolibc updates from Thomas Weißschuh:
"Highlights:
- New supported architectures: SuperH, x32, MIPS n32/n64
- Adopt general kernel architectures names
- Integrate the nolibc selftests into the kselftests framework
- Various fixes and new syscall wrappers

Two non-nolibc changes:
- New arm64 selftest which depends on nolibc changes
- General tools/ cross-compilation bugfix for s390 clang"

* tag 'nolibc-20250724-for-6.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc: (30 commits)
selftests/nolibc: add x32 test configuration
tools/nolibc: define time_t in terms of __kernel_old_time_t
selftests/nolibc: show failed run if test process crashes
tools/nolibc: drop s390 clang target override
tools/build: Fix s390(x) cross-compilation with clang
tools/nolibc: avoid false-positive -Wmaybe-uninitialized through waitpid()
selftests/nolibc: correctly report errors from printf() and friends
selftests/nolibc: create /dev/full when running as PID 1
tools/nolibc: add support for clock_nanosleep() and nanosleep()
kselftest/arm64: Add a test for vfork() with GCS
selftests/nolibc: Add coverage of vfork()
tools/nolibc: Provide vfork()
tools/nolibc: Replace ifdef with if defined() in sys.h
tools/nolibc: add support for SuperH
selftests/nolibc: use file driver for QEMU serial
selftests/nolibc: fix EXTRACONFIG variables ordering
tools/nolibc: MIPS: add support for N64 and N32 ABIs
tools/nolibc: MIPS: drop noreorder option
tools/nolibc: MIPS: drop manual stack pointer alignment
tools/nolibc: MIPS: drop $gp setup
...

+1080 -601
+4 -14
tools/include/nolibc/Makefile
··· 23 23 Q=@ 24 24 endif 25 25 26 - nolibc_arch := $(patsubst arm64,aarch64,$(ARCH)) 27 - arch_file := arch-$(nolibc_arch).h 26 + arch_file := arch-$(ARCH).h 28 27 all_files := \ 29 28 compiler.h \ 30 29 crt.h \ ··· 90 91 @echo " OUTPUT = $(OUTPUT)" 91 92 @echo "" 92 93 93 - # Note: when ARCH is "x86" we concatenate both x86_64 and i386 94 94 headers: 95 95 $(Q)mkdir -p $(OUTPUT)sysroot 96 96 $(Q)mkdir -p $(OUTPUT)sysroot/include 97 97 $(Q)cp --parents $(all_files) $(OUTPUT)sysroot/include/ 98 - $(Q)if [ "$(ARCH)" = "x86" ]; then \ 99 - sed -e \ 100 - 's,^#ifndef _NOLIBC_ARCH_X86_64_H,#if !defined(_NOLIBC_ARCH_X86_64_H) \&\& defined(__x86_64__),' \ 101 - arch-x86_64.h; \ 102 - sed -e \ 103 - 's,^#ifndef _NOLIBC_ARCH_I386_H,#if !defined(_NOLIBC_ARCH_I386_H) \&\& !defined(__x86_64__),' \ 104 - arch-i386.h; \ 98 + $(Q)if [ "$(ARCH)" = "i386" -o "$(ARCH)" = "x86_64" ]; then \ 99 + cat arch-x86.h; \ 105 100 elif [ -e "$(arch_file)" ]; then \ 106 101 cat $(arch_file); \ 107 102 else \ ··· 107 114 $(Q)$(MAKE) -C $(srctree) headers 108 115 $(Q)$(MAKE) -C $(srctree) headers_install INSTALL_HDR_PATH=$(OUTPUT)sysroot 109 116 110 - # GCC uses "s390", clang "systemz" 111 - CLANG_CROSS_FLAGS := $(subst --target=s390-linux,--target=systemz-linux,$(CLANG_CROSS_FLAGS)) 112 - 113 117 headers_check: headers_standalone 114 - for header in $(filter-out crt.h std.h,$(all_files)); do \ 118 + $(Q)for header in $(filter-out crt.h std.h,$(all_files)); do \ 115 119 $(CC) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \ 116 120 -I$(or $(objtree),$(srctree))/usr/include -include $$header -include $$header || exit 1; \ 117 121 done
+5 -5
tools/include/nolibc/arch-aarch64.h tools/include/nolibc/arch-arm64.h
··· 1 1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 2 /* 3 - * AARCH64 specific definitions for NOLIBC 3 + * ARM64 specific definitions for NOLIBC 4 4 * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu> 5 5 */ 6 6 7 - #ifndef _NOLIBC_ARCH_AARCH64_H 8 - #define _NOLIBC_ARCH_AARCH64_H 7 + #ifndef _NOLIBC_ARCH_ARM64_H 8 + #define _NOLIBC_ARCH_ARM64_H 9 9 10 10 #include "compiler.h" 11 11 #include "crt.h" 12 12 13 - /* Syscalls for AARCH64 : 13 + /* Syscalls for ARM64 : 14 14 * - registers are 64-bit 15 15 * - stack is 16-byte aligned 16 16 * - syscall number is passed in x8 ··· 150 150 ); 151 151 __nolibc_entrypoint_epilogue(); 152 152 } 153 - #endif /* _NOLIBC_ARCH_AARCH64_H */ 153 + #endif /* _NOLIBC_ARCH_ARM64_H */
-178
tools/include/nolibc/arch-i386.h
··· 1 - /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 - /* 3 - * i386 specific definitions for NOLIBC 4 - * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu> 5 - */ 6 - 7 - #ifndef _NOLIBC_ARCH_I386_H 8 - #define _NOLIBC_ARCH_I386_H 9 - 10 - #include "compiler.h" 11 - #include "crt.h" 12 - 13 - /* Syscalls for i386 : 14 - * - mostly similar to x86_64 15 - * - registers are 32-bit 16 - * - syscall number is passed in eax 17 - * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively 18 - * - all registers are preserved (except eax of course) 19 - * - the system call is performed by calling int $0x80 20 - * - syscall return comes in eax 21 - * - the arguments are cast to long and assigned into the target registers 22 - * which are then simply passed as registers to the asm code, so that we 23 - * don't have to experience issues with register constraints. 24 - * - the syscall number is always specified last in order to allow to force 25 - * some registers before (gcc refuses a %-register at the last position). 26 - * 27 - * Also, i386 supports the old_select syscall if newselect is not available 28 - */ 29 - #define __ARCH_WANT_SYS_OLD_SELECT 30 - 31 - #define my_syscall0(num) \ 32 - ({ \ 33 - long _ret; \ 34 - register long _num __asm__ ("eax") = (num); \ 35 - \ 36 - __asm__ volatile ( \ 37 - "int $0x80\n" \ 38 - : "=a" (_ret) \ 39 - : "0"(_num) \ 40 - : "memory", "cc" \ 41 - ); \ 42 - _ret; \ 43 - }) 44 - 45 - #define my_syscall1(num, arg1) \ 46 - ({ \ 47 - long _ret; \ 48 - register long _num __asm__ ("eax") = (num); \ 49 - register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 50 - \ 51 - __asm__ volatile ( \ 52 - "int $0x80\n" \ 53 - : "=a" (_ret) \ 54 - : "r"(_arg1), \ 55 - "0"(_num) \ 56 - : "memory", "cc" \ 57 - ); \ 58 - _ret; \ 59 - }) 60 - 61 - #define my_syscall2(num, arg1, arg2) \ 62 - ({ \ 63 - long _ret; \ 64 - register long _num __asm__ ("eax") = (num); \ 65 - register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 66 - register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 67 - \ 68 - __asm__ volatile ( \ 69 - "int $0x80\n" \ 70 - : "=a" (_ret) \ 71 - : "r"(_arg1), "r"(_arg2), \ 72 - "0"(_num) \ 73 - : "memory", "cc" \ 74 - ); \ 75 - _ret; \ 76 - }) 77 - 78 - #define my_syscall3(num, arg1, arg2, arg3) \ 79 - ({ \ 80 - long _ret; \ 81 - register long _num __asm__ ("eax") = (num); \ 82 - register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 83 - register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 84 - register long _arg3 __asm__ ("edx") = (long)(arg3); \ 85 - \ 86 - __asm__ volatile ( \ 87 - "int $0x80\n" \ 88 - : "=a" (_ret) \ 89 - : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 90 - "0"(_num) \ 91 - : "memory", "cc" \ 92 - ); \ 93 - _ret; \ 94 - }) 95 - 96 - #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 97 - ({ \ 98 - long _ret; \ 99 - register long _num __asm__ ("eax") = (num); \ 100 - register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 101 - register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 102 - register long _arg3 __asm__ ("edx") = (long)(arg3); \ 103 - register long _arg4 __asm__ ("esi") = (long)(arg4); \ 104 - \ 105 - __asm__ volatile ( \ 106 - "int $0x80\n" \ 107 - : "=a" (_ret) \ 108 - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 109 - "0"(_num) \ 110 - : "memory", "cc" \ 111 - ); \ 112 - _ret; \ 113 - }) 114 - 115 - #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 116 - ({ \ 117 - long _ret; \ 118 - register long _num __asm__ ("eax") = (num); \ 119 - register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 120 - register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 121 - register long _arg3 __asm__ ("edx") = (long)(arg3); \ 122 - register long _arg4 __asm__ ("esi") = (long)(arg4); \ 123 - register long _arg5 __asm__ ("edi") = (long)(arg5); \ 124 - \ 125 - __asm__ volatile ( \ 126 - "int $0x80\n" \ 127 - : "=a" (_ret) \ 128 - : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 129 - "0"(_num) \ 130 - : "memory", "cc" \ 131 - ); \ 132 - _ret; \ 133 - }) 134 - 135 - #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 136 - ({ \ 137 - long _eax = (long)(num); \ 138 - long _arg6 = (long)(arg6); /* Always in memory */ \ 139 - __asm__ volatile ( \ 140 - "pushl %[_arg6]\n\t" \ 141 - "pushl %%ebp\n\t" \ 142 - "movl 4(%%esp),%%ebp\n\t" \ 143 - "int $0x80\n\t" \ 144 - "popl %%ebp\n\t" \ 145 - "addl $4,%%esp\n\t" \ 146 - : "+a"(_eax) /* %eax */ \ 147 - : "b"(arg1), /* %ebx */ \ 148 - "c"(arg2), /* %ecx */ \ 149 - "d"(arg3), /* %edx */ \ 150 - "S"(arg4), /* %esi */ \ 151 - "D"(arg5), /* %edi */ \ 152 - [_arg6]"m"(_arg6) /* memory */ \ 153 - : "memory", "cc" \ 154 - ); \ 155 - _eax; \ 156 - }) 157 - 158 - /* startup code */ 159 - /* 160 - * i386 System V ABI mandates: 161 - * 1) last pushed argument must be 16-byte aligned. 162 - * 2) The deepest stack frame should be set to zero 163 - * 164 - */ 165 - void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) 166 - { 167 - __asm__ volatile ( 168 - "xor %ebp, %ebp\n" /* zero the stack frame */ 169 - "mov %esp, %eax\n" /* save stack pointer to %eax, as arg1 of _start_c */ 170 - "sub $12, %esp\n" /* sub 12 to keep it aligned after the push %eax */ 171 - "push %eax\n" /* push arg1 on stack to support plain stack modes too */ 172 - "call _start_c\n" /* transfer to c runtime */ 173 - "hlt\n" /* ensure it does not return */ 174 - ); 175 - __nolibc_entrypoint_epilogue(); 176 - } 177 - 178 - #endif /* _NOLIBC_ARCH_I386_H */
+90 -27
tools/include/nolibc/arch-mips.h
··· 10 10 #include "compiler.h" 11 11 #include "crt.h" 12 12 13 - #if !defined(_ABIO32) 13 + #if !defined(_ABIO32) && !defined(_ABIN32) && !defined(_ABI64) 14 14 #error Unsupported MIPS ABI 15 15 #endif 16 16 ··· 32 32 * - the arguments are cast to long and assigned into the target registers 33 33 * which are then simply passed as registers to the asm code, so that we 34 34 * don't have to experience issues with register constraints. 35 + * 36 + * Syscalls for MIPS ABI N32, same as ABI O32 with the following differences : 37 + * - arguments are in a0, a1, a2, a3, t0, t1, t2, t3. 38 + * t0..t3 are also known as a4..a7. 39 + * - stack is 16-byte aligned 35 40 */ 41 + 42 + #if defined(_ABIO32) 36 43 37 44 #define _NOLIBC_SYSCALL_CLOBBERLIST \ 38 45 "memory", "cc", "at", "v1", "hi", "lo", \ 39 46 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" 47 + #define _NOLIBC_SYSCALL_STACK_RESERVE "addiu $sp, $sp, -32\n" 48 + #define _NOLIBC_SYSCALL_STACK_UNRESERVE "addiu $sp, $sp, 32\n" 49 + 50 + #else /* _ABIN32 || _ABI64 */ 51 + 52 + /* binutils, GCC and clang disagree about register aliases, use numbers instead. */ 53 + #define _NOLIBC_SYSCALL_CLOBBERLIST \ 54 + "memory", "cc", "at", "v1", \ 55 + "10", "11", "12", "13", "14", "15", "24", "25" 56 + 57 + #define _NOLIBC_SYSCALL_STACK_RESERVE 58 + #define _NOLIBC_SYSCALL_STACK_UNRESERVE 59 + 60 + #endif /* _ABIO32 */ 40 61 41 62 #define my_syscall0(num) \ 42 63 ({ \ ··· 65 44 register long _arg4 __asm__ ("a3"); \ 66 45 \ 67 46 __asm__ volatile ( \ 68 - "addiu $sp, $sp, -32\n" \ 47 + _NOLIBC_SYSCALL_STACK_RESERVE \ 69 48 "syscall\n" \ 70 - "addiu $sp, $sp, 32\n" \ 49 + _NOLIBC_SYSCALL_STACK_UNRESERVE \ 71 50 : "=r"(_num), "=r"(_arg4) \ 72 51 : "r"(_num) \ 73 52 : _NOLIBC_SYSCALL_CLOBBERLIST \ ··· 82 61 register long _arg4 __asm__ ("a3"); \ 83 62 \ 84 63 __asm__ volatile ( \ 85 - "addiu $sp, $sp, -32\n" \ 64 + _NOLIBC_SYSCALL_STACK_RESERVE \ 86 65 "syscall\n" \ 87 - "addiu $sp, $sp, 32\n" \ 66 + _NOLIBC_SYSCALL_STACK_UNRESERVE \ 88 67 : "=r"(_num), "=r"(_arg4) \ 89 68 : "0"(_num), \ 90 69 "r"(_arg1) \ ··· 101 80 register long _arg4 __asm__ ("a3"); \ 102 81 \ 103 82 __asm__ volatile ( \ 104 - "addiu $sp, $sp, -32\n" \ 83 + _NOLIBC_SYSCALL_STACK_RESERVE \ 105 84 "syscall\n" \ 106 - "addiu $sp, $sp, 32\n" \ 85 + _NOLIBC_SYSCALL_STACK_UNRESERVE \ 107 86 : "=r"(_num), "=r"(_arg4) \ 108 87 : "0"(_num), \ 109 88 "r"(_arg1), "r"(_arg2) \ ··· 121 100 register long _arg4 __asm__ ("a3"); \ 122 101 \ 123 102 __asm__ volatile ( \ 124 - "addiu $sp, $sp, -32\n" \ 103 + _NOLIBC_SYSCALL_STACK_RESERVE \ 125 104 "syscall\n" \ 126 - "addiu $sp, $sp, 32\n" \ 105 + _NOLIBC_SYSCALL_STACK_UNRESERVE \ 127 106 : "=r"(_num), "=r"(_arg4) \ 128 107 : "0"(_num), \ 129 108 "r"(_arg1), "r"(_arg2), "r"(_arg3) \ ··· 141 120 register long _arg4 __asm__ ("a3") = (long)(arg4); \ 142 121 \ 143 122 __asm__ volatile ( \ 144 - "addiu $sp, $sp, -32\n" \ 123 + _NOLIBC_SYSCALL_STACK_RESERVE \ 145 124 "syscall\n" \ 146 - "addiu $sp, $sp, 32\n" \ 125 + _NOLIBC_SYSCALL_STACK_UNRESERVE \ 147 126 : "=r" (_num), "=r"(_arg4) \ 148 127 : "0"(_num), \ 149 128 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ ··· 151 130 ); \ 152 131 _arg4 ? -_num : _num; \ 153 132 }) 133 + 134 + #if defined(_ABIO32) 154 135 155 136 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 156 137 ({ \ ··· 164 141 register long _arg5 = (long)(arg5); \ 165 142 \ 166 143 __asm__ volatile ( \ 167 - "addiu $sp, $sp, -32\n" \ 144 + _NOLIBC_SYSCALL_STACK_RESERVE \ 168 145 "sw %7, 16($sp)\n" \ 169 146 "syscall\n" \ 170 - "addiu $sp, $sp, 32\n" \ 147 + _NOLIBC_SYSCALL_STACK_UNRESERVE \ 171 148 : "=r" (_num), "=r"(_arg4) \ 172 149 : "0"(_num), \ 173 150 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ ··· 187 164 register long _arg6 = (long)(arg6); \ 188 165 \ 189 166 __asm__ volatile ( \ 190 - "addiu $sp, $sp, -32\n" \ 167 + _NOLIBC_SYSCALL_STACK_RESERVE \ 191 168 "sw %7, 16($sp)\n" \ 192 169 "sw %8, 20($sp)\n" \ 193 170 "syscall\n" \ 194 - "addiu $sp, $sp, 32\n" \ 171 + _NOLIBC_SYSCALL_STACK_UNRESERVE \ 195 172 : "=r" (_num), "=r"(_arg4) \ 196 173 : "0"(_num), \ 197 174 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ ··· 201 178 _arg4 ? -_num : _num; \ 202 179 }) 203 180 181 + #else /* _ABIN32 || _ABI64 */ 182 + 183 + #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 184 + ({ \ 185 + register long _num __asm__ ("v0") = (num); \ 186 + register long _arg1 __asm__ ("$4") = (long)(arg1); \ 187 + register long _arg2 __asm__ ("$5") = (long)(arg2); \ 188 + register long _arg3 __asm__ ("$6") = (long)(arg3); \ 189 + register long _arg4 __asm__ ("$7") = (long)(arg4); \ 190 + register long _arg5 __asm__ ("$8") = (long)(arg5); \ 191 + \ 192 + __asm__ volatile ( \ 193 + "syscall\n" \ 194 + : "=r" (_num), "=r"(_arg4) \ 195 + : "0"(_num), \ 196 + "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ 197 + : _NOLIBC_SYSCALL_CLOBBERLIST \ 198 + ); \ 199 + _arg4 ? -_num : _num; \ 200 + }) 201 + 202 + #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 203 + ({ \ 204 + register long _num __asm__ ("v0") = (num); \ 205 + register long _arg1 __asm__ ("$4") = (long)(arg1); \ 206 + register long _arg2 __asm__ ("$5") = (long)(arg2); \ 207 + register long _arg3 __asm__ ("$6") = (long)(arg3); \ 208 + register long _arg4 __asm__ ("$7") = (long)(arg4); \ 209 + register long _arg5 __asm__ ("$8") = (long)(arg5); \ 210 + register long _arg6 __asm__ ("$9") = (long)(arg6); \ 211 + \ 212 + __asm__ volatile ( \ 213 + "syscall\n" \ 214 + : "=r" (_num), "=r"(_arg4) \ 215 + : "0"(_num), \ 216 + "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 217 + "r"(_arg6) \ 218 + : _NOLIBC_SYSCALL_CLOBBERLIST \ 219 + ); \ 220 + _arg4 ? -_num : _num; \ 221 + }) 222 + 223 + #endif /* _ABIO32 */ 224 + 204 225 /* startup code, note that it's called __start on MIPS */ 205 226 void __start(void); 206 227 void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector __start(void) 207 228 { 208 229 __asm__ volatile ( 209 - ".set push\n" 210 - ".set noreorder\n" 211 - "bal 1f\n" /* prime $ra for .cpload */ 212 - "nop\n" 213 - "1:\n" 214 - ".cpload $ra\n" 215 230 "move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */ 216 - "addiu $sp, $sp, -4\n" /* space for .cprestore to store $gp */ 217 - ".cprestore 0\n" 218 - "li $t0, -8\n" 219 - "and $sp, $sp, $t0\n" /* $sp must be 8-byte aligned */ 231 + #if defined(_ABIO32) 220 232 "addiu $sp, $sp, -16\n" /* the callee expects to save a0..a3 there */ 233 + #endif /* _ABIO32 */ 221 234 "lui $t9, %hi(_start_c)\n" /* ABI requires current function address in $t9 */ 222 235 "ori $t9, %lo(_start_c)\n" 236 + #if defined(_ABI64) 237 + "lui $t0, %highest(_start_c)\n" 238 + "ori $t0, %higher(_start_c)\n" 239 + "dsll $t0, 0x20\n" 240 + "or $t9, $t0\n" 241 + #endif /* _ABI64 */ 223 242 "jalr $t9\n" /* transfer to c runtime */ 224 - " nop\n" /* delayed slot */ 225 - ".set pop\n" 226 243 ); 227 244 __nolibc_entrypoint_epilogue(); 228 245 }
+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 */
+16
tools/include/nolibc/arch-sparc.h
··· 188 188 } 189 189 #define sys_fork sys_fork 190 190 191 + static __attribute__((unused)) 192 + pid_t sys_vfork(void) 193 + { 194 + pid_t parent, ret; 195 + 196 + parent = getpid(); 197 + ret = my_syscall0(__NR_vfork); 198 + 199 + /* The syscall returns the parent pid in the child instead of 0 */ 200 + if (ret == parent) 201 + return 0; 202 + else 203 + return ret; 204 + } 205 + #define sys_vfork sys_vfork 206 + 191 207 #endif /* _NOLIBC_ARCH_SPARC_H */
+175 -5
tools/include/nolibc/arch-x86_64.h tools/include/nolibc/arch-x86.h
··· 1 1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 2 /* 3 - * x86_64 specific definitions for NOLIBC 4 - * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu> 3 + * x86 specific definitions for NOLIBC (both 32- and 64-bit) 4 + * Copyright (C) 2017-2025 Willy Tarreau <w@1wt.eu> 5 5 */ 6 6 7 - #ifndef _NOLIBC_ARCH_X86_64_H 8 - #define _NOLIBC_ARCH_X86_64_H 7 + #ifndef _NOLIBC_ARCH_X86_H 8 + #define _NOLIBC_ARCH_X86_H 9 9 10 10 #include "compiler.h" 11 11 #include "crt.h" 12 + 13 + #if !defined(__x86_64__) 14 + 15 + /* Syscalls for i386 : 16 + * - mostly similar to x86_64 17 + * - registers are 32-bit 18 + * - syscall number is passed in eax 19 + * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively 20 + * - all registers are preserved (except eax of course) 21 + * - the system call is performed by calling int $0x80 22 + * - syscall return comes in eax 23 + * - the arguments are cast to long and assigned into the target registers 24 + * which are then simply passed as registers to the asm code, so that we 25 + * don't have to experience issues with register constraints. 26 + * - the syscall number is always specified last in order to allow to force 27 + * some registers before (gcc refuses a %-register at the last position). 28 + * 29 + * Also, i386 supports the old_select syscall if newselect is not available 30 + */ 31 + #define __ARCH_WANT_SYS_OLD_SELECT 32 + 33 + #define my_syscall0(num) \ 34 + ({ \ 35 + long _ret; \ 36 + register long _num __asm__ ("eax") = (num); \ 37 + \ 38 + __asm__ volatile ( \ 39 + "int $0x80\n" \ 40 + : "=a" (_ret) \ 41 + : "0"(_num) \ 42 + : "memory", "cc" \ 43 + ); \ 44 + _ret; \ 45 + }) 46 + 47 + #define my_syscall1(num, arg1) \ 48 + ({ \ 49 + long _ret; \ 50 + register long _num __asm__ ("eax") = (num); \ 51 + register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 52 + \ 53 + __asm__ volatile ( \ 54 + "int $0x80\n" \ 55 + : "=a" (_ret) \ 56 + : "r"(_arg1), \ 57 + "0"(_num) \ 58 + : "memory", "cc" \ 59 + ); \ 60 + _ret; \ 61 + }) 62 + 63 + #define my_syscall2(num, arg1, arg2) \ 64 + ({ \ 65 + long _ret; \ 66 + register long _num __asm__ ("eax") = (num); \ 67 + register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 68 + register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 69 + \ 70 + __asm__ volatile ( \ 71 + "int $0x80\n" \ 72 + : "=a" (_ret) \ 73 + : "r"(_arg1), "r"(_arg2), \ 74 + "0"(_num) \ 75 + : "memory", "cc" \ 76 + ); \ 77 + _ret; \ 78 + }) 79 + 80 + #define my_syscall3(num, arg1, arg2, arg3) \ 81 + ({ \ 82 + long _ret; \ 83 + register long _num __asm__ ("eax") = (num); \ 84 + register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 85 + register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 86 + register long _arg3 __asm__ ("edx") = (long)(arg3); \ 87 + \ 88 + __asm__ volatile ( \ 89 + "int $0x80\n" \ 90 + : "=a" (_ret) \ 91 + : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 92 + "0"(_num) \ 93 + : "memory", "cc" \ 94 + ); \ 95 + _ret; \ 96 + }) 97 + 98 + #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 99 + ({ \ 100 + long _ret; \ 101 + register long _num __asm__ ("eax") = (num); \ 102 + register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 103 + register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 104 + register long _arg3 __asm__ ("edx") = (long)(arg3); \ 105 + register long _arg4 __asm__ ("esi") = (long)(arg4); \ 106 + \ 107 + __asm__ volatile ( \ 108 + "int $0x80\n" \ 109 + : "=a" (_ret) \ 110 + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 111 + "0"(_num) \ 112 + : "memory", "cc" \ 113 + ); \ 114 + _ret; \ 115 + }) 116 + 117 + #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 118 + ({ \ 119 + long _ret; \ 120 + register long _num __asm__ ("eax") = (num); \ 121 + register long _arg1 __asm__ ("ebx") = (long)(arg1); \ 122 + register long _arg2 __asm__ ("ecx") = (long)(arg2); \ 123 + register long _arg3 __asm__ ("edx") = (long)(arg3); \ 124 + register long _arg4 __asm__ ("esi") = (long)(arg4); \ 125 + register long _arg5 __asm__ ("edi") = (long)(arg5); \ 126 + \ 127 + __asm__ volatile ( \ 128 + "int $0x80\n" \ 129 + : "=a" (_ret) \ 130 + : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ 131 + "0"(_num) \ 132 + : "memory", "cc" \ 133 + ); \ 134 + _ret; \ 135 + }) 136 + 137 + #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 138 + ({ \ 139 + long _eax = (long)(num); \ 140 + long _arg6 = (long)(arg6); /* Always in memory */ \ 141 + __asm__ volatile ( \ 142 + "pushl %[_arg6]\n\t" \ 143 + "pushl %%ebp\n\t" \ 144 + "movl 4(%%esp),%%ebp\n\t" \ 145 + "int $0x80\n\t" \ 146 + "popl %%ebp\n\t" \ 147 + "addl $4,%%esp\n\t" \ 148 + : "+a"(_eax) /* %eax */ \ 149 + : "b"(arg1), /* %ebx */ \ 150 + "c"(arg2), /* %ecx */ \ 151 + "d"(arg3), /* %edx */ \ 152 + "S"(arg4), /* %esi */ \ 153 + "D"(arg5), /* %edi */ \ 154 + [_arg6]"m"(_arg6) /* memory */ \ 155 + : "memory", "cc" \ 156 + ); \ 157 + _eax; \ 158 + }) 159 + 160 + /* startup code */ 161 + /* 162 + * i386 System V ABI mandates: 163 + * 1) last pushed argument must be 16-byte aligned. 164 + * 2) The deepest stack frame should be set to zero 165 + * 166 + */ 167 + void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) 168 + { 169 + __asm__ volatile ( 170 + "xor %ebp, %ebp\n" /* zero the stack frame */ 171 + "mov %esp, %eax\n" /* save stack pointer to %eax, as arg1 of _start_c */ 172 + "sub $12, %esp\n" /* sub 12 to keep it aligned after the push %eax */ 173 + "push %eax\n" /* push arg1 on stack to support plain stack modes too */ 174 + "call _start_c\n" /* transfer to c runtime */ 175 + "hlt\n" /* ensure it does not return */ 176 + ); 177 + __nolibc_entrypoint_epilogue(); 178 + } 179 + 180 + #else /* !defined(__x86_64__) */ 12 181 13 182 /* Syscalls for x86_64 : 14 183 * - registers are 64-bit ··· 383 214 "retq\n" 384 215 ); 385 216 386 - #endif /* _NOLIBC_ARCH_X86_64_H */ 217 + #endif /* !defined(__x86_64__) */ 218 + #endif /* _NOLIBC_ARCH_X86_H */
+5 -5
tools/include/nolibc/arch.h
··· 15 15 #ifndef _NOLIBC_ARCH_H 16 16 #define _NOLIBC_ARCH_H 17 17 18 - #if defined(__x86_64__) 19 - #include "arch-x86_64.h" 20 - #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) 21 - #include "arch-i386.h" 18 + #if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) 19 + #include "arch-x86.h" 22 20 #elif defined(__ARM_EABI__) 23 21 #include "arch-arm.h" 24 22 #elif defined(__aarch64__) 25 - #include "arch-aarch64.h" 23 + #include "arch-arm64.h" 26 24 #elif defined(__mips__) 27 25 #include "arch-mips.h" 28 26 #elif defined(__powerpc__) ··· 35 37 #include "arch-sparc.h" 36 38 #elif defined(__m68k__) 37 39 #include "arch-m68k.h" 40 + #elif defined(__sh__) 41 + #include "arch-sh.h" 38 42 #else 39 43 #error Unsupported Architecture 40 44 #endif
+3 -1
tools/include/nolibc/std.h
··· 16 16 #include "stdint.h" 17 17 #include "stddef.h" 18 18 19 + #include <linux/types.h> 20 + 19 21 /* those are commonly provided by sys/types.h */ 20 22 typedef unsigned int dev_t; 21 23 typedef unsigned long ino_t; ··· 29 27 typedef signed long off_t; 30 28 typedef signed long blksize_t; 31 29 typedef signed long blkcnt_t; 32 - typedef signed long time_t; 30 + typedef __kernel_old_time_t time_t; 33 31 34 32 #endif /* _NOLIBC_STD_H */
+2 -2
tools/include/nolibc/stdio.h
··· 358 358 n -= w; 359 359 while (width-- > w) { 360 360 if (cb(state, " ", 1) != 0) 361 - break; 361 + return -1; 362 362 written += 1; 363 363 } 364 364 if (cb(state, outstr, w) != 0) 365 - break; 365 + return -1; 366 366 } 367 367 368 368 written += len;
+44 -15
tools/include/nolibc/sys.h
··· 22 22 #include <linux/time.h> 23 23 #include <linux/auxvec.h> 24 24 #include <linux/fcntl.h> /* for O_* and AT_* */ 25 + #include <linux/sched.h> /* for clone_args */ 25 26 #include <linux/stat.h> /* for statx() */ 26 27 27 28 #include "errno.h" ··· 140 139 static __attribute__((unused)) 141 140 int sys_chmod(const char *path, mode_t mode) 142 141 { 143 - #ifdef __NR_fchmodat 142 + #if defined(__NR_fchmodat) 144 143 return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 145 144 #elif defined(__NR_chmod) 146 145 return my_syscall2(__NR_chmod, path, mode); ··· 163 162 static __attribute__((unused)) 164 163 int sys_chown(const char *path, uid_t owner, gid_t group) 165 164 { 166 - #ifdef __NR_fchownat 165 + #if defined(__NR_fchownat) 167 166 return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 168 167 #elif defined(__NR_chown) 169 168 return my_syscall3(__NR_chown, path, owner, group); ··· 237 236 static __attribute__((unused)) 238 237 int sys_dup2(int old, int new) 239 238 { 240 - #ifdef __NR_dup3 239 + #if defined(__NR_dup3) 241 240 return my_syscall3(__NR_dup3, old, new, 0); 242 241 #elif defined(__NR_dup2) 243 242 return my_syscall2(__NR_dup2, old, new); ··· 257 256 * int dup3(int old, int new, int flags); 258 257 */ 259 258 260 - #ifdef __NR_dup3 259 + #if defined(__NR_dup3) 261 260 static __attribute__((unused)) 262 261 int sys_dup3(int old, int new, int flags) 263 262 { ··· 321 320 static __attribute__((unused)) 322 321 pid_t sys_fork(void) 323 322 { 324 - #ifdef __NR_clone 323 + #if defined(__NR_clone) 325 324 /* note: some archs only have clone() and not fork(). Different archs 326 325 * have a different API, but most archs have the flags on first arg and 327 326 * will not use the rest with no other flag. ··· 341 340 return __sysret(sys_fork()); 342 341 } 343 342 343 + #ifndef sys_vfork 344 + static __attribute__((unused)) 345 + pid_t sys_vfork(void) 346 + { 347 + #if defined(__NR_vfork) 348 + return my_syscall0(__NR_vfork); 349 + #elif defined(__NR_clone3) 350 + /* 351 + * clone() could be used but has different argument orders per 352 + * architecture. 353 + */ 354 + struct clone_args args = { 355 + .flags = CLONE_VM | CLONE_VFORK, 356 + .exit_signal = SIGCHLD, 357 + }; 358 + 359 + return my_syscall2(__NR_clone3, &args, sizeof(args)); 360 + #else 361 + return __nolibc_enosys(__func__); 362 + #endif 363 + } 364 + #endif 365 + 366 + static __attribute__((unused)) 367 + pid_t vfork(void) 368 + { 369 + return __sysret(sys_vfork()); 370 + } 344 371 345 372 /* 346 373 * int fsync(int fd); ··· 411 382 static __attribute__((unused)) 412 383 uid_t sys_geteuid(void) 413 384 { 414 - #ifdef __NR_geteuid32 385 + #if defined(__NR_geteuid32) 415 386 return my_syscall0(__NR_geteuid32); 416 387 #else 417 388 return my_syscall0(__NR_geteuid); ··· 529 500 static __attribute__((unused)) 530 501 uid_t sys_getuid(void) 531 502 { 532 - #ifdef __NR_getuid32 503 + #if defined(__NR_getuid32) 533 504 return my_syscall0(__NR_getuid32); 534 505 #else 535 506 return my_syscall0(__NR_getuid); ··· 567 538 static __attribute__((unused)) 568 539 int sys_link(const char *old, const char *new) 569 540 { 570 - #ifdef __NR_linkat 541 + #if defined(__NR_linkat) 571 542 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 572 543 #elif defined(__NR_link) 573 544 return my_syscall2(__NR_link, old, new); ··· 590 561 static __attribute__((unused)) 591 562 off_t sys_lseek(int fd, off_t offset, int whence) 592 563 { 593 - #ifdef __NR_lseek 564 + #if defined(__NR_lseek) 594 565 return my_syscall3(__NR_lseek, fd, offset, whence); 595 566 #else 596 567 return __nolibc_enosys(__func__, fd, offset, whence); ··· 601 572 int sys_llseek(int fd, unsigned long offset_high, unsigned long offset_low, 602 573 __kernel_loff_t *result, int whence) 603 574 { 604 - #ifdef __NR_llseek 575 + #if defined(__NR_llseek) 605 576 return my_syscall5(__NR_llseek, fd, offset_high, offset_low, result, whence); 606 577 #else 607 578 return __nolibc_enosys(__func__, fd, offset_high, offset_low, result, whence); ··· 638 609 static __attribute__((unused)) 639 610 int sys_mkdir(const char *path, mode_t mode) 640 611 { 641 - #ifdef __NR_mkdirat 612 + #if defined(__NR_mkdirat) 642 613 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 643 614 #elif defined(__NR_mkdir) 644 615 return my_syscall2(__NR_mkdir, path, mode); ··· 660 631 static __attribute__((unused)) 661 632 int sys_rmdir(const char *path) 662 633 { 663 - #ifdef __NR_rmdir 634 + #if defined(__NR_rmdir) 664 635 return my_syscall1(__NR_rmdir, path); 665 636 #elif defined(__NR_unlinkat) 666 637 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); ··· 683 654 static __attribute__((unused)) 684 655 long sys_mknod(const char *path, mode_t mode, dev_t dev) 685 656 { 686 - #ifdef __NR_mknodat 657 + #if defined(__NR_mknodat) 687 658 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 688 659 #elif defined(__NR_mknod) 689 660 return my_syscall3(__NR_mknod, path, mode, dev); ··· 872 843 static __attribute__((unused)) 873 844 int sys_symlink(const char *old, const char *new) 874 845 { 875 - #ifdef __NR_symlinkat 846 + #if defined(__NR_symlinkat) 876 847 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 877 848 #elif defined(__NR_symlink) 878 849 return my_syscall2(__NR_symlink, old, new); ··· 929 900 static __attribute__((unused)) 930 901 int sys_unlink(const char *path) 931 902 { 932 - #ifdef __NR_unlinkat 903 + #if defined(__NR_unlinkat) 933 904 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 934 905 #elif defined(__NR_unlink) 935 906 return my_syscall1(__NR_unlink, path);
+1 -1
tools/include/nolibc/sys/wait.h
··· 78 78 79 79 ret = waitid(idtype, id, &info, options); 80 80 if (ret) 81 - return ret; 81 + return -1; 82 82 83 83 switch (info.si_code) { 84 84 case 0:
+34
tools/include/nolibc/time.h
··· 36 36 * int clock_getres(clockid_t clockid, struct timespec *res); 37 37 * int clock_gettime(clockid_t clockid, struct timespec *tp); 38 38 * int clock_settime(clockid_t clockid, const struct timespec *tp); 39 + * int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, 40 + * struct timespec *rmtp) 39 41 */ 40 42 41 43 static __attribute__((unused)) ··· 109 107 return __sysret(sys_clock_settime(clockid, tp)); 110 108 } 111 109 110 + static __attribute__((unused)) 111 + int sys_clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, 112 + struct timespec *rmtp) 113 + { 114 + #if defined(__NR_clock_nanosleep) 115 + return my_syscall4(__NR_clock_nanosleep, clockid, flags, rqtp, rmtp); 116 + #elif defined(__NR_clock_nanosleep_time64) 117 + struct __kernel_timespec krqtp, krmtp; 118 + int ret; 119 + 120 + __nolibc_timespec_user_to_kernel(rqtp, &krqtp); 121 + ret = my_syscall4(__NR_clock_nanosleep_time64, clockid, flags, &krqtp, &krmtp); 122 + if (rmtp) 123 + __nolibc_timespec_kernel_to_user(&krmtp, rmtp); 124 + return ret; 125 + #else 126 + return __nolibc_enosys(__func__, clockid, flags, rqtp, rmtp); 127 + #endif 128 + } 129 + 130 + static __attribute__((unused)) 131 + int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, 132 + struct timespec *rmtp) 133 + { 134 + return __sysret(sys_clock_nanosleep(clockid, flags, rqtp, rmtp)); 135 + } 112 136 113 137 static __inline__ 114 138 double difftime(time_t time1, time_t time2) 115 139 { 116 140 return time1 - time2; 141 + } 142 + 143 + static __inline__ 144 + int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) 145 + { 146 + return clock_nanosleep(CLOCK_REALTIME, 0, rqtp, rmtp); 117 147 } 118 148 119 149
+2 -2
tools/include/nolibc/types.h
··· 128 128 int __fd = (fd); \ 129 129 if (__fd >= 0) \ 130 130 __set->fds[__fd / FD_SETIDXMASK] &= \ 131 - ~(1U << (__fd & FX_SETBITMASK)); \ 131 + ~(1U << (__fd & FD_SETBITMASK)); \ 132 132 } while (0) 133 133 134 134 #define FD_SET(fd, set) do { \ ··· 145 145 int __r = 0; \ 146 146 if (__fd >= 0) \ 147 147 __r = !!(__set->fds[__fd / FD_SETIDXMASK] & \ 148 - 1U << (__fd & FD_SET_BITMASK)); \ 148 + 1U << (__fd & FD_SETBITMASK)); \ 149 149 __r; \ 150 150 }) 151 151
+3 -1
tools/scripts/Makefile.include
··· 101 101 # Allow userspace to override CLANG_CROSS_FLAGS to specify their own 102 102 # sysroots and flags or to avoid the GCC call in pure Clang builds. 103 103 ifeq ($(CLANG_CROSS_FLAGS),) 104 - CLANG_CROSS_FLAGS := --target=$(notdir $(CROSS_COMPILE:%-=%)) 104 + CLANG_TARGET := $(notdir $(CROSS_COMPILE:%-=%)) 105 + CLANG_TARGET := $(subst s390-linux,s390x-linux,$(CLANG_TARGET)) 106 + CLANG_CROSS_FLAGS := --target=$(CLANG_TARGET) 105 107 GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)gcc 2>/dev/null)) 106 108 ifneq ($(GCC_TOOLCHAIN_DIR),) 107 109 CLANG_CROSS_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
+1
tools/testing/selftests/Makefile
··· 77 77 TARGETS += net/packetdrill 78 78 TARGETS += net/rds 79 79 TARGETS += net/tcp_ao 80 + TARGETS += nolibc 80 81 TARGETS += nsfs 81 82 TARGETS += pci_endpoint 82 83 TARGETS += pcie_bwctrl
+63
tools/testing/selftests/arm64/gcs/basic-gcs.c
··· 298 298 return pass; 299 299 } 300 300 301 + /* A vfork()ed process can run and exit */ 302 + static bool test_vfork(void) 303 + { 304 + unsigned long child_mode; 305 + int ret, status; 306 + pid_t pid; 307 + bool pass = true; 308 + 309 + pid = vfork(); 310 + if (pid == -1) { 311 + ksft_print_msg("vfork() failed: %d\n", errno); 312 + pass = false; 313 + goto out; 314 + } 315 + if (pid == 0) { 316 + /* 317 + * In child, make sure we can call a function, read 318 + * the GCS pointer and status and then exit. 319 + */ 320 + valid_gcs_function(); 321 + get_gcspr(); 322 + 323 + ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS, 324 + &child_mode, 0, 0, 0); 325 + if (ret == 0 && !(child_mode & PR_SHADOW_STACK_ENABLE)) { 326 + ksft_print_msg("GCS not enabled in child\n"); 327 + ret = EXIT_FAILURE; 328 + } 329 + 330 + _exit(ret); 331 + } 332 + 333 + /* 334 + * In parent, check we can still do function calls then check 335 + * on the child. 336 + */ 337 + valid_gcs_function(); 338 + 339 + ksft_print_msg("Waiting for child %d\n", pid); 340 + 341 + ret = waitpid(pid, &status, 0); 342 + if (ret == -1) { 343 + ksft_print_msg("Failed to wait for child: %d\n", 344 + errno); 345 + return false; 346 + } 347 + 348 + if (!WIFEXITED(status)) { 349 + ksft_print_msg("Child exited due to signal %d\n", 350 + WTERMSIG(status)); 351 + pass = false; 352 + } else if (WEXITSTATUS(status)) { 353 + ksft_print_msg("Child exited with status %d\n", 354 + WEXITSTATUS(status)); 355 + pass = false; 356 + } 357 + 358 + out: 359 + 360 + return pass; 361 + } 362 + 301 363 typedef bool (*gcs_test)(void); 302 364 303 365 static struct { ··· 376 314 { "enable_invalid", enable_invalid, true }, 377 315 { "map_guarded_stack", map_guarded_stack }, 378 316 { "fork", test_fork }, 317 + { "vfork", test_vfork }, 379 318 }; 380 319 381 320 int main(void)
+20 -335
tools/testing/selftests/nolibc/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - # Makefile for nolibc tests 3 - # we're in ".../tools/testing/selftests/nolibc" 4 - ifeq ($(srctree),) 5 - srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR))) 2 + 3 + TEST_GEN_PROGS := nolibc-test 4 + 5 + include ../lib.mk 6 + include $(top_srcdir)/scripts/Makefile.compiler 7 + 8 + cc-option = $(call __cc-option, $(CC),,$(1),$(2)) 9 + 10 + include Makefile.include 11 + 12 + CFLAGS = -nostdlib -nostdinc -static \ 13 + -isystem $(top_srcdir)/tools/include/nolibc -isystem $(top_srcdir)/usr/include \ 14 + $(CFLAGS_NOLIBC_TEST) 15 + 16 + ifeq ($(LLVM),) 17 + LDLIBS := -lgcc 6 18 endif 7 19 8 - include $(srctree)/tools/scripts/utilities.mak 9 - # We need this for the "__cc-option" macro. 10 - include $(srctree)/scripts/Makefile.compiler 11 - 12 - ifneq ($(O),) 13 - ifneq ($(call is-absolute,$(O)),y) 14 - $(error Only absolute O= parameters are supported) 15 - endif 16 - objtree := $(O) 17 - else 18 - objtree ?= $(srctree) 19 - endif 20 - 21 - ifeq ($(ARCH),) 22 - include $(srctree)/scripts/subarch.include 23 - ARCH = $(SUBARCH) 24 - endif 25 - 26 - cc-option = $(call __cc-option, $(CC),$(CLANG_CROSS_FLAGS),$(1),$(2)) 27 - 28 - # XARCH extends the kernel's ARCH with a few variants of the same 29 - # architecture that only differ by the configuration, the toolchain 30 - # and the Qemu program used. It is copied as-is into ARCH except for 31 - # a few specific values which are mapped like this: 32 - # 33 - # XARCH | ARCH | config 34 - # -------------|-----------|------------------------- 35 - # ppc | powerpc | 32 bits 36 - # ppc64 | powerpc | 64 bits big endian 37 - # ppc64le | powerpc | 64 bits little endian 38 - # 39 - # It is recommended to only use XARCH, though it does not harm if 40 - # ARCH is already set. For simplicity, ARCH is sufficient for all 41 - # architectures where both are equal. 42 - 43 - # configure default variants for target kernel supported architectures 44 - XARCH_powerpc = ppc 45 - XARCH_mips = mips32le 46 - XARCH_riscv = riscv64 47 - XARCH = $(or $(XARCH_$(ARCH)),$(ARCH)) 48 - 49 - # map from user input variants to their kernel supported architectures 50 - ARCH_armthumb = arm 51 - ARCH_ppc = powerpc 52 - ARCH_ppc64 = powerpc 53 - ARCH_ppc64le = powerpc 54 - ARCH_mips32le = mips 55 - ARCH_mips32be = mips 56 - ARCH_riscv32 = riscv 57 - ARCH_riscv64 = riscv 58 - ARCH_s390x = s390 59 - ARCH_sparc32 = sparc 60 - ARCH_sparc64 = sparc 61 - ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) 62 - 63 - # kernel image names by architecture 64 - IMAGE_i386 = arch/x86/boot/bzImage 65 - IMAGE_x86_64 = arch/x86/boot/bzImage 66 - IMAGE_x86 = arch/x86/boot/bzImage 67 - IMAGE_arm64 = arch/arm64/boot/Image 68 - IMAGE_arm = arch/arm/boot/zImage 69 - IMAGE_armthumb = arch/arm/boot/zImage 70 - IMAGE_mips32le = vmlinuz 71 - IMAGE_mips32be = vmlinuz 72 - IMAGE_ppc = vmlinux 73 - IMAGE_ppc64 = vmlinux 74 - IMAGE_ppc64le = arch/powerpc/boot/zImage 75 - IMAGE_riscv = arch/riscv/boot/Image 76 - IMAGE_riscv32 = arch/riscv/boot/Image 77 - IMAGE_riscv64 = arch/riscv/boot/Image 78 - IMAGE_s390x = arch/s390/boot/bzImage 79 - IMAGE_s390 = arch/s390/boot/bzImage 80 - IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi 81 - IMAGE_sparc32 = arch/sparc/boot/image 82 - IMAGE_sparc64 = arch/sparc/boot/image 83 - IMAGE_m68k = vmlinux 84 - IMAGE = $(objtree)/$(IMAGE_$(XARCH)) 85 - IMAGE_NAME = $(notdir $(IMAGE)) 86 - 87 - # default kernel configurations that appear to be usable 88 - DEFCONFIG_i386 = defconfig 89 - DEFCONFIG_x86_64 = defconfig 90 - DEFCONFIG_x86 = defconfig 91 - DEFCONFIG_arm64 = defconfig 92 - DEFCONFIG_arm = multi_v7_defconfig 93 - DEFCONFIG_armthumb = multi_v7_defconfig 94 - DEFCONFIG_mips32le = malta_defconfig 95 - DEFCONFIG_mips32be = malta_defconfig generic/eb.config 96 - DEFCONFIG_ppc = pmac32_defconfig 97 - DEFCONFIG_ppc64 = powernv_be_defconfig 98 - DEFCONFIG_ppc64le = powernv_defconfig 99 - DEFCONFIG_riscv = defconfig 100 - DEFCONFIG_riscv32 = rv32_defconfig 101 - DEFCONFIG_riscv64 = defconfig 102 - DEFCONFIG_s390x = defconfig 103 - DEFCONFIG_s390 = defconfig compat.config 104 - DEFCONFIG_loongarch = defconfig 105 - DEFCONFIG_sparc32 = sparc32_defconfig 106 - DEFCONFIG_sparc64 = sparc64_defconfig 107 - DEFCONFIG_m68k = virt_defconfig 108 - DEFCONFIG = $(DEFCONFIG_$(XARCH)) 109 - 110 - EXTRACONFIG_m68k = -e CONFIG_BLK_DEV_INITRD 111 - EXTRACONFIG = $(EXTRACONFIG_$(XARCH)) 112 - EXTRACONFIG_arm = -e CONFIG_NAMESPACES 113 - EXTRACONFIG_armthumb = -e CONFIG_NAMESPACES 114 - 115 - # optional tests to run (default = all) 116 - TEST = 117 - 118 - # QEMU_ARCH: arch names used by qemu 119 - QEMU_ARCH_i386 = i386 120 - QEMU_ARCH_x86_64 = x86_64 121 - QEMU_ARCH_x86 = x86_64 122 - QEMU_ARCH_arm64 = aarch64 123 - QEMU_ARCH_arm = arm 124 - QEMU_ARCH_armthumb = arm 125 - QEMU_ARCH_mips32le = mipsel # works with malta_defconfig 126 - QEMU_ARCH_mips32be = mips 127 - QEMU_ARCH_ppc = ppc 128 - QEMU_ARCH_ppc64 = ppc64 129 - QEMU_ARCH_ppc64le = ppc64 130 - QEMU_ARCH_riscv = riscv64 131 - QEMU_ARCH_riscv32 = riscv32 132 - QEMU_ARCH_riscv64 = riscv64 133 - QEMU_ARCH_s390x = s390x 134 - QEMU_ARCH_s390 = s390x 135 - QEMU_ARCH_loongarch = loongarch64 136 - QEMU_ARCH_sparc32 = sparc 137 - QEMU_ARCH_sparc64 = sparc64 138 - QEMU_ARCH_m68k = m68k 139 - QEMU_ARCH = $(QEMU_ARCH_$(XARCH)) 140 - 141 - QEMU_ARCH_USER_ppc64le = ppc64le 142 - QEMU_ARCH_USER = $(or $(QEMU_ARCH_USER_$(XARCH)),$(QEMU_ARCH_$(XARCH))) 143 - 144 - QEMU_BIOS_DIR = /usr/share/edk2/ 145 - QEMU_BIOS_loongarch = $(QEMU_BIOS_DIR)/loongarch64/OVMF_CODE.fd 146 - 147 - ifneq ($(QEMU_BIOS_$(XARCH)),) 148 - QEMU_ARGS_BIOS = -bios $(QEMU_BIOS_$(XARCH)) 149 - endif 150 - 151 - # QEMU_ARGS : some arch-specific args to pass to qemu 152 - QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 153 - QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 154 - QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 155 - QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 156 - QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 157 - QEMU_ARGS_armthumb = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 158 - QEMU_ARGS_mips32le = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 159 - QEMU_ARGS_mips32be = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 160 - QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 161 - QEMU_ARGS_ppc64 = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 162 - QEMU_ARGS_ppc64le = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 163 - QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 164 - QEMU_ARGS_riscv32 = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 165 - QEMU_ARGS_riscv64 = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 166 - QEMU_ARGS_s390x = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 167 - QEMU_ARGS_s390 = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 168 - QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 169 - QEMU_ARGS_sparc32 = -M SS-5 -m 256M -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 170 - QEMU_ARGS_sparc64 = -M sun4u -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 171 - QEMU_ARGS_m68k = -M virt -append "console=ttyGF0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 172 - QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA) 173 - 174 - # OUTPUT is only set when run from the main makefile, otherwise 175 - # it defaults to this nolibc directory. 176 - OUTPUT ?= $(CURDIR)/ 177 - 178 - ifeq ($(V),1) 179 - Q= 180 - else 181 - Q=@ 182 - endif 183 - 184 - CFLAGS_i386 = $(call cc-option,-m32) 185 - CFLAGS_arm = -marm 186 - CFLAGS_armthumb = -mthumb -march=armv6t2 187 - CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) 188 - CFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) 189 - CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2) 190 - CFLAGS_s390x = -m64 191 - CFLAGS_s390 = -m31 192 - CFLAGS_mips32le = -EL -mabi=32 -fPIC 193 - CFLAGS_mips32be = -EB -mabi=32 194 - CFLAGS_sparc32 = $(call cc-option,-m32) 195 - ifeq ($(origin XARCH),command line) 196 - CFLAGS_XARCH = $(CFLAGS_$(XARCH)) 197 - endif 198 - CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all)) 199 - CFLAGS_SANITIZER ?= $(call cc-option,-fsanitize=undefined -fsanitize-trap=all) 200 - CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \ 201 - $(call cc-option,-fno-stack-protector) $(call cc-option,-Wmissing-prototypes) \ 202 - $(CFLAGS_XARCH) $(CFLAGS_STACKPROTECTOR) $(CFLAGS_SANITIZER) $(CFLAGS_EXTRA) 203 - LDFLAGS := 204 - 205 - LIBGCC := -lgcc 206 - 207 - ifneq ($(LLVM),) 208 - # Not needed for clang 209 - LIBGCC := 210 - endif 211 - 212 - # Modify CFLAGS based on LLVM= 213 - include $(srctree)/tools/scripts/Makefile.include 214 - 215 - # GCC uses "s390", clang "systemz" 216 - CLANG_CROSS_FLAGS := $(subst --target=s390-linux,--target=systemz-linux,$(CLANG_CROSS_FLAGS)) 217 - 218 - REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \ 219 - END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \ 220 - if (f || !p) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \ 221 - printf("\nSee all results in %s\n", ARGV[1]); }' 20 + $(OUTPUT)/nolibc-test: nolibc-test.c nolibc-test-linkage.c | headers 222 21 223 22 help: 224 - @echo "Supported targets under selftests/nolibc:" 225 - @echo " all call the \"run\" target below" 226 - @echo " help this help" 227 - @echo " sysroot create the nolibc sysroot here (uses \$$ARCH)" 228 - @echo " nolibc-test build the executable (uses \$$CC and \$$CROSS_COMPILE)" 229 - @echo " libc-test build an executable using the compiler's default libc instead" 230 - @echo " run-user runs the executable under QEMU (uses \$$XARCH, \$$TEST)" 231 - @echo " initramfs.cpio prepare the initramfs archive with nolibc-test" 232 - @echo " initramfs prepare the initramfs tree with nolibc-test" 233 - @echo " defconfig create a fresh new default config (uses \$$XARCH)" 234 - @echo " kernel (re)build the kernel (uses \$$XARCH)" 235 - @echo " kernel-standalone (re)build the kernel with the initramfs (uses \$$XARCH)" 236 - @echo " run runs the kernel in QEMU after building it (uses \$$XARCH, \$$TEST)" 237 - @echo " rerun runs a previously prebuilt kernel in QEMU (uses \$$XARCH, \$$TEST)" 238 - @echo " clean clean the sysroot, initramfs, build and output files" 239 - @echo "" 240 - @echo "The output file is \"run.out\". Test ranges may be passed using \$$TEST." 241 - @echo "" 242 - @echo "Currently using the following variables:" 243 - @echo " ARCH = $(ARCH)" 244 - @echo " XARCH = $(XARCH)" 245 - @echo " CROSS_COMPILE = $(CROSS_COMPILE)" 246 - @echo " CC = $(CC)" 247 - @echo " OUTPUT = $(OUTPUT)" 248 - @echo " TEST = $(TEST)" 249 - @echo " QEMU_ARCH = $(if $(QEMU_ARCH),$(QEMU_ARCH),UNKNOWN_ARCH) [determined from \$$XARCH]" 250 - @echo " IMAGE_NAME = $(if $(IMAGE_NAME),$(IMAGE_NAME),UNKNOWN_ARCH) [determined from \$$XARCH]" 251 - @echo "" 23 + @echo "For the custom nolibc testsuite use '$(MAKE) -f Makefile.nolibc'; available targets:" 24 + @$(MAKE) -f Makefile.nolibc help 252 25 253 - all: run 254 - 255 - sysroot: sysroot/$(ARCH)/include 256 - 257 - sysroot/$(ARCH)/include: 258 - $(Q)rm -rf sysroot/$(ARCH) sysroot/sysroot 259 - $(QUIET_MKDIR)mkdir -p sysroot 260 - $(Q)$(MAKE) -C $(srctree) outputmakefile 261 - $(Q)$(MAKE) -C $(srctree)/tools/include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone headers_check 262 - $(Q)mv sysroot/sysroot sysroot/$(ARCH) 263 - 264 - ifneq ($(NOLIBC_SYSROOT),0) 265 - nolibc-test: nolibc-test.c nolibc-test-linkage.c sysroot/$(ARCH)/include 266 - $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ 267 - -nostdlib -nostdinc -static -Isysroot/$(ARCH)/include nolibc-test.c nolibc-test-linkage.c $(LIBGCC) 268 - else 269 - nolibc-test: nolibc-test.c nolibc-test-linkage.c 270 - $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ 271 - -nostdlib -static -include $(srctree)/tools/include/nolibc/nolibc.h nolibc-test.c nolibc-test-linkage.c $(LIBGCC) 272 - endif 273 - 274 - libc-test: nolibc-test.c nolibc-test-linkage.c 275 - $(QUIET_CC)$(HOSTCC) -o $@ nolibc-test.c nolibc-test-linkage.c 276 - 277 - # local libc-test 278 - run-libc-test: libc-test 279 - $(Q)./libc-test > "$(CURDIR)/run.out" || : 280 - $(Q)$(REPORT) $(CURDIR)/run.out 281 - 282 - # local nolibc-test 283 - run-nolibc-test: nolibc-test 284 - $(Q)./nolibc-test > "$(CURDIR)/run.out" || : 285 - $(Q)$(REPORT) $(CURDIR)/run.out 286 - 287 - # qemu user-land test 288 - run-user: nolibc-test 289 - $(Q)qemu-$(QEMU_ARCH_USER) ./nolibc-test > "$(CURDIR)/run.out" || : 290 - $(Q)$(REPORT) $(CURDIR)/run.out 291 - 292 - initramfs.cpio: kernel nolibc-test 293 - $(QUIET_GEN)echo 'file /init nolibc-test 755 0 0' | $(objtree)/usr/gen_init_cpio - > initramfs.cpio 294 - 295 - initramfs: nolibc-test 296 - $(QUIET_MKDIR)mkdir -p initramfs 297 - $(call QUIET_INSTALL, initramfs/init) 298 - $(Q)cp nolibc-test initramfs/init 299 - 300 - defconfig: 301 - $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(DEFCONFIG) 302 - $(Q)if [ -n "$(EXTRACONFIG)" ]; then \ 303 - $(srctree)/scripts/config --file $(objtree)/.config $(EXTRACONFIG); \ 304 - $(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) olddefconfig < /dev/null; \ 305 - fi 306 - 307 - kernel: | defconfig 308 - $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) < /dev/null 309 - 310 - kernel-standalone: initramfs | defconfig 311 - $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs < /dev/null 312 - 313 - # run the tests after building the kernel 314 - run: kernel initramfs.cpio 315 - $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(IMAGE)" -initrd initramfs.cpio -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out" 316 - $(Q)$(REPORT) $(CURDIR)/run.out 317 - 318 - # re-run the tests from an existing kernel 319 - rerun: 320 - $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(IMAGE)" -initrd initramfs.cpio -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out" 321 - $(Q)$(REPORT) $(CURDIR)/run.out 322 - 323 - # report with existing test log 324 - report: 325 - $(Q)$(REPORT) $(CURDIR)/run.out 326 - 327 - clean: 328 - $(call QUIET_CLEAN, sysroot) 329 - $(Q)rm -rf sysroot 330 - $(call QUIET_CLEAN, nolibc-test) 331 - $(Q)rm -f nolibc-test 332 - $(call QUIET_CLEAN, libc-test) 333 - $(Q)rm -f libc-test 334 - $(call QUIET_CLEAN, initramfs.cpio) 335 - $(Q)rm -rf initramfs.cpio 336 - $(call QUIET_CLEAN, initramfs) 337 - $(Q)rm -rf initramfs 338 - $(call QUIET_CLEAN, run.out) 339 - $(Q)rm -rf run.out 340 - 341 - .PHONY: sysroot/$(ARCH)/include 26 + .PHONY: help
+10
tools/testing/selftests/nolibc/Makefile.include
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + __CFLAGS_STACKPROTECTOR = $(call cc-option,-fstack-protector-all) $(call cc-option,-mstack-protector-guard=global) 4 + _CFLAGS_STACKPROTECTOR ?= $(call try-run, \ 5 + echo 'void foo(void) {}' | $(CC) -x c - -o - -S $(CLANG_CROSS_FLAGS) $(__CFLAGS_STACKPROTECTOR) | grep -q __stack_chk_guard, \ 6 + $(__CFLAGS_STACKPROTECTOR)) 7 + _CFLAGS_SANITIZER ?= $(call cc-option,-fsanitize=undefined -fsanitize-trap=all) 8 + CFLAGS_NOLIBC_TEST ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \ 9 + $(call cc-option,-fno-stack-protector) $(call cc-option,-Wmissing-prototypes) \ 10 + $(_CFLAGS_STACKPROTECTOR) $(_CFLAGS_SANITIZER)
+383
tools/testing/selftests/nolibc/Makefile.nolibc
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Makefile for nolibc tests 3 + # we're in ".../tools/testing/selftests/nolibc" 4 + ifeq ($(srctree),) 5 + srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR))) 6 + endif 7 + 8 + include $(srctree)/tools/scripts/utilities.mak 9 + # We need this for the "__cc-option" macro. 10 + include $(srctree)/scripts/Makefile.compiler 11 + 12 + ifneq ($(O),) 13 + ifneq ($(call is-absolute,$(O)),y) 14 + $(error Only absolute O= parameters are supported) 15 + endif 16 + objtree := $(O) 17 + else 18 + objtree ?= $(srctree) 19 + endif 20 + 21 + ifeq ($(ARCH),) 22 + include $(srctree)/scripts/subarch.include 23 + ARCH = $(SUBARCH) 24 + endif 25 + 26 + cc-option = $(call __cc-option, $(CC),$(CLANG_CROSS_FLAGS),$(1),$(2)) 27 + 28 + # XARCH extends the kernel's ARCH with a few variants of the same 29 + # architecture that only differ by the configuration, the toolchain 30 + # and the Qemu program used. It is copied as-is into ARCH except for 31 + # a few specific values which are mapped like this: 32 + # 33 + # XARCH | ARCH | config 34 + # -------------|-----------|------------------------- 35 + # ppc | powerpc | 32 bits 36 + # ppc64 | powerpc | 64 bits big endian 37 + # ppc64le | powerpc | 64 bits little endian 38 + # 39 + # It is recommended to only use XARCH, though it does not harm if 40 + # ARCH is already set. For simplicity, ARCH is sufficient for all 41 + # architectures where both are equal. 42 + 43 + # configure default variants for target kernel supported architectures 44 + XARCH_powerpc = ppc 45 + XARCH_mips = mips32le 46 + XARCH_riscv = riscv64 47 + XARCH = $(or $(XARCH_$(ARCH)),$(ARCH)) 48 + 49 + # map from user input variants to their kernel supported architectures 50 + ARCH_x32 = x86 51 + ARCH_armthumb = arm 52 + ARCH_ppc = powerpc 53 + ARCH_ppc64 = powerpc 54 + ARCH_ppc64le = powerpc 55 + ARCH_mips32le = mips 56 + ARCH_mips32be = mips 57 + ARCH_mipsn32le = mips 58 + ARCH_mipsn32be = mips 59 + ARCH_mips64le = mips 60 + ARCH_mips64be = mips 61 + ARCH_riscv32 = riscv 62 + ARCH_riscv64 = riscv 63 + ARCH_s390x = s390 64 + ARCH_sparc32 = sparc 65 + ARCH_sparc64 = sparc 66 + ARCH_sh4 = sh 67 + ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) 68 + 69 + # kernel image names by architecture 70 + IMAGE_i386 = arch/x86/boot/bzImage 71 + IMAGE_x86_64 = arch/x86/boot/bzImage 72 + IMAGE_x32 = arch/x86/boot/bzImage 73 + IMAGE_x86 = arch/x86/boot/bzImage 74 + IMAGE_arm64 = arch/arm64/boot/Image 75 + IMAGE_arm = arch/arm/boot/zImage 76 + IMAGE_armthumb = arch/arm/boot/zImage 77 + IMAGE_mips32le = vmlinuz 78 + IMAGE_mips32be = vmlinuz 79 + IMAGE_mipsn32le = vmlinuz 80 + IMAGE_mipsn32be = vmlinuz 81 + IMAGE_mips64le = vmlinuz 82 + IMAGE_mips64be = vmlinuz 83 + IMAGE_ppc = vmlinux 84 + IMAGE_ppc64 = vmlinux 85 + IMAGE_ppc64le = arch/powerpc/boot/zImage 86 + IMAGE_riscv = arch/riscv/boot/Image 87 + IMAGE_riscv32 = arch/riscv/boot/Image 88 + IMAGE_riscv64 = arch/riscv/boot/Image 89 + IMAGE_s390x = arch/s390/boot/bzImage 90 + IMAGE_s390 = arch/s390/boot/bzImage 91 + IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi 92 + IMAGE_sparc32 = arch/sparc/boot/image 93 + IMAGE_sparc64 = arch/sparc/boot/image 94 + IMAGE_m68k = vmlinux 95 + IMAGE_sh4 = arch/sh/boot/zImage 96 + IMAGE = $(objtree)/$(IMAGE_$(XARCH)) 97 + IMAGE_NAME = $(notdir $(IMAGE)) 98 + 99 + # default kernel configurations that appear to be usable 100 + DEFCONFIG_i386 = defconfig 101 + DEFCONFIG_x86_64 = defconfig 102 + DEFCONFIG_x32 = defconfig 103 + DEFCONFIG_x86 = defconfig 104 + DEFCONFIG_arm64 = defconfig 105 + DEFCONFIG_arm = multi_v7_defconfig 106 + DEFCONFIG_armthumb = multi_v7_defconfig 107 + DEFCONFIG_mips32le = malta_defconfig 108 + DEFCONFIG_mips32be = malta_defconfig generic/eb.config 109 + DEFCONFIG_mipsn32le = malta_defconfig generic/64r2.config 110 + DEFCONFIG_mipsn32be = malta_defconfig generic/64r6.config generic/eb.config 111 + DEFCONFIG_mips64le = malta_defconfig generic/64r6.config 112 + DEFCONFIG_mips64be = malta_defconfig generic/64r2.config generic/eb.config 113 + DEFCONFIG_ppc = pmac32_defconfig 114 + DEFCONFIG_ppc64 = powernv_be_defconfig 115 + DEFCONFIG_ppc64le = powernv_defconfig 116 + DEFCONFIG_riscv = defconfig 117 + DEFCONFIG_riscv32 = rv32_defconfig 118 + DEFCONFIG_riscv64 = defconfig 119 + DEFCONFIG_s390x = defconfig 120 + DEFCONFIG_s390 = defconfig compat.config 121 + DEFCONFIG_loongarch = defconfig 122 + DEFCONFIG_sparc32 = sparc32_defconfig 123 + DEFCONFIG_sparc64 = sparc64_defconfig 124 + DEFCONFIG_m68k = virt_defconfig 125 + DEFCONFIG_sh4 = rts7751r2dplus_defconfig 126 + DEFCONFIG = $(DEFCONFIG_$(XARCH)) 127 + 128 + EXTRACONFIG_x32 = -e CONFIG_X86_X32_ABI 129 + EXTRACONFIG_arm = -e CONFIG_NAMESPACES 130 + EXTRACONFIG_armthumb = -e CONFIG_NAMESPACES 131 + EXTRACONFIG_m68k = -e CONFIG_BLK_DEV_INITRD 132 + EXTRACONFIG_sh4 = -e CONFIG_BLK_DEV_INITRD -e CONFIG_CMDLINE_FROM_BOOTLOADER 133 + EXTRACONFIG = $(EXTRACONFIG_$(XARCH)) 134 + 135 + # optional tests to run (default = all) 136 + TEST = 137 + 138 + # QEMU_ARCH: arch names used by qemu 139 + QEMU_ARCH_i386 = i386 140 + QEMU_ARCH_x86_64 = x86_64 141 + QEMU_ARCH_x32 = x86_64 142 + QEMU_ARCH_x86 = x86_64 143 + QEMU_ARCH_arm64 = aarch64 144 + QEMU_ARCH_arm = arm 145 + QEMU_ARCH_armthumb = arm 146 + QEMU_ARCH_mips32le = mipsel # works with malta_defconfig 147 + QEMU_ARCH_mips32be = mips 148 + QEMU_ARCH_mipsn32le = mips64el 149 + QEMU_ARCH_mipsn32be = mips64 150 + QEMU_ARCH_mips64le = mips64el 151 + QEMU_ARCH_mips64be = mips64 152 + QEMU_ARCH_ppc = ppc 153 + QEMU_ARCH_ppc64 = ppc64 154 + QEMU_ARCH_ppc64le = ppc64 155 + QEMU_ARCH_riscv = riscv64 156 + QEMU_ARCH_riscv32 = riscv32 157 + QEMU_ARCH_riscv64 = riscv64 158 + QEMU_ARCH_s390x = s390x 159 + QEMU_ARCH_s390 = s390x 160 + QEMU_ARCH_loongarch = loongarch64 161 + QEMU_ARCH_sparc32 = sparc 162 + QEMU_ARCH_sparc64 = sparc64 163 + QEMU_ARCH_m68k = m68k 164 + QEMU_ARCH_sh4 = sh4 165 + QEMU_ARCH = $(QEMU_ARCH_$(XARCH)) 166 + 167 + QEMU_ARCH_USER_ppc64le = ppc64le 168 + QEMU_ARCH_USER_mipsn32le = mipsn32el 169 + QEMU_ARCH_USER_mipsn32be = mipsn32 170 + QEMU_ARCH_USER = $(or $(QEMU_ARCH_USER_$(XARCH)),$(QEMU_ARCH_$(XARCH))) 171 + 172 + QEMU_BIOS_DIR = /usr/share/edk2/ 173 + QEMU_BIOS_loongarch = $(QEMU_BIOS_DIR)/loongarch64/OVMF_CODE.fd 174 + 175 + ifneq ($(QEMU_BIOS_$(XARCH)),) 176 + QEMU_ARGS_BIOS = -bios $(QEMU_BIOS_$(XARCH)) 177 + endif 178 + 179 + # QEMU_ARGS : some arch-specific args to pass to qemu 180 + QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 181 + QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 182 + QEMU_ARGS_x32 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 183 + QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 184 + QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 185 + QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 186 + QEMU_ARGS_armthumb = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 187 + QEMU_ARGS_mips32le = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 188 + QEMU_ARGS_mips32be = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 189 + QEMU_ARGS_mipsn32le = -M malta -cpu 5KEc -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 190 + QEMU_ARGS_mipsn32be = -M malta -cpu I6400 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 191 + QEMU_ARGS_mips64le = -M malta -cpu I6400 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 192 + QEMU_ARGS_mips64be = -M malta -cpu 5KEc -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 193 + QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 194 + QEMU_ARGS_ppc64 = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 195 + QEMU_ARGS_ppc64le = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 196 + QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 197 + QEMU_ARGS_riscv32 = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 198 + QEMU_ARGS_riscv64 = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 199 + QEMU_ARGS_s390x = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 200 + QEMU_ARGS_s390 = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 201 + QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 202 + QEMU_ARGS_sparc32 = -M SS-5 -m 256M -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 203 + QEMU_ARGS_sparc64 = -M sun4u -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 204 + QEMU_ARGS_m68k = -M virt -append "console=ttyGF0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 205 + QEMU_ARGS_sh4 = -M r2d -serial file:/dev/stdout -append "console=ttySC1,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 206 + QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA) 207 + 208 + # OUTPUT is only set when run from the main makefile, otherwise 209 + # it defaults to this nolibc directory. 210 + OUTPUT ?= $(CURDIR)/ 211 + 212 + ifeq ($(V),1) 213 + Q= 214 + else 215 + Q=@ 216 + endif 217 + 218 + CFLAGS_i386 = $(call cc-option,-m32) 219 + CFLAGS_x32 = -mx32 220 + CFLAGS_arm = -marm 221 + CFLAGS_armthumb = -mthumb -march=armv6t2 222 + CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) 223 + CFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) 224 + CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2) 225 + CFLAGS_s390x = -m64 226 + CFLAGS_s390 = -m31 227 + CFLAGS_mips32le = -EL -mabi=32 -fPIC 228 + CFLAGS_mips32be = -EB -mabi=32 229 + CFLAGS_mipsn32le = -EL -mabi=n32 -fPIC -march=mips64r2 230 + CFLAGS_mipsn32be = -EB -mabi=n32 -march=mips64r6 231 + CFLAGS_mips64le = -EL -mabi=64 -march=mips64r6 232 + CFLAGS_mips64be = -EB -mabi=64 -march=mips64r2 233 + CFLAGS_sparc32 = $(call cc-option,-m32) 234 + CFLAGS_sh4 = -ml -m4 235 + ifeq ($(origin XARCH),command line) 236 + CFLAGS_XARCH = $(CFLAGS_$(XARCH)) 237 + endif 238 + 239 + include Makefile.include 240 + 241 + CFLAGS ?= $(CFLAGS_NOLIBC_TEST) $(CFLAGS_XARCH) $(CFLAGS_EXTRA) 242 + LDFLAGS := 243 + 244 + LIBGCC := -lgcc 245 + 246 + ifeq ($(ARCH),x86) 247 + # Not needed on x86, probably not present for x32 248 + LIBGCC := 249 + endif 250 + 251 + ifneq ($(LLVM),) 252 + # Not needed for clang 253 + LIBGCC := 254 + endif 255 + 256 + # Modify CFLAGS based on LLVM= 257 + include $(srctree)/tools/scripts/Makefile.include 258 + 259 + REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \ 260 + /^Total number of errors:/{done++} \ 261 + END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \ 262 + if (f || !p || !done) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \ 263 + printf("\nSee all results in %s\n", ARGV[1]); }' 264 + 265 + help: 266 + @echo "Supported targets under selftests/nolibc:" 267 + @echo " all call the \"run\" target below" 268 + @echo " help this help" 269 + @echo " sysroot create the nolibc sysroot here (uses \$$ARCH)" 270 + @echo " nolibc-test build the executable (uses \$$CC and \$$CROSS_COMPILE)" 271 + @echo " libc-test build an executable using the compiler's default libc instead" 272 + @echo " run-user runs the executable under QEMU (uses \$$XARCH, \$$TEST)" 273 + @echo " initramfs.cpio prepare the initramfs archive with nolibc-test" 274 + @echo " initramfs prepare the initramfs tree with nolibc-test" 275 + @echo " defconfig create a fresh new default config (uses \$$XARCH)" 276 + @echo " kernel (re)build the kernel (uses \$$XARCH)" 277 + @echo " kernel-standalone (re)build the kernel with the initramfs (uses \$$XARCH)" 278 + @echo " run runs the kernel in QEMU after building it (uses \$$XARCH, \$$TEST)" 279 + @echo " rerun runs a previously prebuilt kernel in QEMU (uses \$$XARCH, \$$TEST)" 280 + @echo " clean clean the sysroot, initramfs, build and output files" 281 + @echo "" 282 + @echo "The output file is \"run.out\". Test ranges may be passed using \$$TEST." 283 + @echo "" 284 + @echo "Currently using the following variables:" 285 + @echo " ARCH = $(ARCH)" 286 + @echo " XARCH = $(XARCH)" 287 + @echo " CROSS_COMPILE = $(CROSS_COMPILE)" 288 + @echo " CC = $(CC)" 289 + @echo " OUTPUT = $(OUTPUT)" 290 + @echo " TEST = $(TEST)" 291 + @echo " QEMU_ARCH = $(if $(QEMU_ARCH),$(QEMU_ARCH),UNKNOWN_ARCH) [determined from \$$XARCH]" 292 + @echo " IMAGE_NAME = $(if $(IMAGE_NAME),$(IMAGE_NAME),UNKNOWN_ARCH) [determined from \$$XARCH]" 293 + @echo "" 294 + 295 + all: run 296 + 297 + sysroot: sysroot/$(ARCH)/include 298 + 299 + sysroot/$(ARCH)/include: 300 + $(Q)rm -rf sysroot/$(ARCH) sysroot/sysroot 301 + $(QUIET_MKDIR)mkdir -p sysroot 302 + $(Q)$(MAKE) -C $(srctree) outputmakefile 303 + $(Q)$(MAKE) -C $(srctree)/tools/include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone headers_check 304 + $(Q)mv sysroot/sysroot sysroot/$(ARCH) 305 + 306 + ifneq ($(NOLIBC_SYSROOT),0) 307 + nolibc-test: nolibc-test.c nolibc-test-linkage.c sysroot/$(ARCH)/include 308 + $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ 309 + -nostdlib -nostdinc -static -Isysroot/$(ARCH)/include nolibc-test.c nolibc-test-linkage.c $(LIBGCC) 310 + else 311 + nolibc-test: nolibc-test.c nolibc-test-linkage.c 312 + $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ 313 + -nostdlib -static -include $(srctree)/tools/include/nolibc/nolibc.h nolibc-test.c nolibc-test-linkage.c $(LIBGCC) 314 + endif 315 + 316 + libc-test: nolibc-test.c nolibc-test-linkage.c 317 + $(QUIET_CC)$(HOSTCC) -o $@ nolibc-test.c nolibc-test-linkage.c 318 + 319 + # local libc-test 320 + run-libc-test: libc-test 321 + $(Q)./libc-test > "$(CURDIR)/run.out" || : 322 + $(Q)$(REPORT) $(CURDIR)/run.out 323 + 324 + # local nolibc-test 325 + run-nolibc-test: nolibc-test 326 + $(Q)./nolibc-test > "$(CURDIR)/run.out" || : 327 + $(Q)$(REPORT) $(CURDIR)/run.out 328 + 329 + # qemu user-land test 330 + run-user: nolibc-test 331 + $(Q)qemu-$(QEMU_ARCH_USER) ./nolibc-test > "$(CURDIR)/run.out" || : 332 + $(Q)$(REPORT) $(CURDIR)/run.out 333 + 334 + initramfs.cpio: kernel nolibc-test 335 + $(QUIET_GEN)echo 'file /init nolibc-test 755 0 0' | $(objtree)/usr/gen_init_cpio - > initramfs.cpio 336 + 337 + initramfs: nolibc-test 338 + $(QUIET_MKDIR)mkdir -p initramfs 339 + $(call QUIET_INSTALL, initramfs/init) 340 + $(Q)cp nolibc-test initramfs/init 341 + 342 + defconfig: 343 + $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(DEFCONFIG) 344 + $(Q)if [ -n "$(EXTRACONFIG)" ]; then \ 345 + $(srctree)/scripts/config --file $(objtree)/.config $(EXTRACONFIG); \ 346 + $(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) olddefconfig < /dev/null; \ 347 + fi 348 + 349 + kernel: 350 + $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) < /dev/null 351 + 352 + kernel-standalone: initramfs 353 + $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs < /dev/null 354 + 355 + # run the tests after building the kernel 356 + run: kernel initramfs.cpio 357 + $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(IMAGE)" -initrd initramfs.cpio -serial file:/dev/stdout $(QEMU_ARGS) > "$(CURDIR)/run.out" 358 + $(Q)$(REPORT) $(CURDIR)/run.out 359 + 360 + # re-run the tests from an existing kernel 361 + rerun: 362 + $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(IMAGE)" -initrd initramfs.cpio -serial file:/dev/stdout $(QEMU_ARGS) > "$(CURDIR)/run.out" 363 + $(Q)$(REPORT) $(CURDIR)/run.out 364 + 365 + # report with existing test log 366 + report: 367 + $(Q)$(REPORT) $(CURDIR)/run.out 368 + 369 + clean: 370 + $(call QUIET_CLEAN, sysroot) 371 + $(Q)rm -rf sysroot 372 + $(call QUIET_CLEAN, nolibc-test) 373 + $(Q)rm -f nolibc-test 374 + $(call QUIET_CLEAN, libc-test) 375 + $(Q)rm -f libc-test 376 + $(call QUIET_CLEAN, initramfs.cpio) 377 + $(Q)rm -rf initramfs.cpio 378 + $(call QUIET_CLEAN, initramfs) 379 + $(Q)rm -rf initramfs 380 + $(call QUIET_CLEAN, run.out) 381 + $(Q)rm -rf run.out 382 + 383 + .PHONY: sysroot/$(ARCH)/include
+47 -6
tools/testing/selftests/nolibc/nolibc-test.c
··· 877 877 return 0; 878 878 } 879 879 880 - int test_fork(void) 880 + enum fork_type { 881 + FORK_STANDARD, 882 + FORK_VFORK, 883 + }; 884 + 885 + int test_fork(enum fork_type type) 881 886 { 882 887 int status; 883 888 pid_t pid; ··· 891 886 fflush(stdout); 892 887 fflush(stderr); 893 888 894 - pid = fork(); 889 + switch (type) { 890 + case FORK_STANDARD: 891 + pid = fork(); 892 + break; 893 + case FORK_VFORK: 894 + pid = vfork(); 895 + break; 896 + default: 897 + return 1; 898 + } 895 899 896 900 switch (pid) { 897 901 case -1: 898 902 return 1; 899 903 900 904 case 0: 901 - exit(123); 905 + _exit(123); 902 906 903 907 default: 904 908 pid = waitpid(pid, &status, 0); ··· 1344 1330 CASE_TEST(dup3_m1); tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; 1345 1331 CASE_TEST(execve_root); EXPECT_SYSER(1, execve("/", (char*[]){ [0] = "/", [1] = NULL }, NULL), -1, EACCES); break; 1346 1332 CASE_TEST(file_stream); EXPECT_SYSZR(1, test_file_stream()); break; 1347 - CASE_TEST(fork); EXPECT_SYSZR(1, test_fork()); break; 1333 + CASE_TEST(fork); EXPECT_SYSZR(1, test_fork(FORK_STANDARD)); break; 1348 1334 CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/"), -1); break; 1349 1335 CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break; 1350 1336 CASE_TEST(directories); EXPECT_SYSZR(proc, test_dirent()); break; ··· 1363 1349 CASE_TEST(mmap_bad); EXPECT_PTRER(1, mmap(NULL, 0, PROT_READ, MAP_PRIVATE, 0, 0), MAP_FAILED, EINVAL); break; 1364 1350 CASE_TEST(munmap_bad); EXPECT_SYSER(1, munmap(NULL, 0), -1, EINVAL); break; 1365 1351 CASE_TEST(mmap_munmap_good); EXPECT_SYSZR(1, test_mmap_munmap()); break; 1352 + CASE_TEST(nanosleep); ts.tv_nsec = -1; EXPECT_SYSER(1, nanosleep(&ts, NULL), -1, EINVAL); break; 1366 1353 CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", O_RDONLY), -1); if (tmp != -1) close(tmp); break; 1367 1354 CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", O_RDONLY), -1, ENOENT); if (tmp != -1) close(tmp); break; 1368 1355 CASE_TEST(openat_dir); EXPECT_SYSZR(1, test_openat()); break; ··· 1389 1374 CASE_TEST(uname_fault); EXPECT_SYSER(1, uname(NULL), -1, EFAULT); break; 1390 1375 CASE_TEST(unlink_root); EXPECT_SYSER(1, unlink("/"), -1, EISDIR); break; 1391 1376 CASE_TEST(unlink_blah); EXPECT_SYSER(1, unlink("/proc/self/blah"), -1, ENOENT); break; 1377 + CASE_TEST(vfork); EXPECT_SYSZR(1, test_fork(FORK_VFORK)); break; 1392 1378 CASE_TEST(wait_child); EXPECT_SYSER(1, wait(&tmp), -1, ECHILD); break; 1393 1379 CASE_TEST(waitpid_min); EXPECT_SYSER(1, waitpid(INT_MIN, &tmp, WNOHANG), -1, ESRCH); break; 1394 1380 CASE_TEST(waitpid_child); EXPECT_SYSER(1, waitpid(getpid(), &tmp, WNOHANG), -1, ECHILD); break; ··· 1429 1413 * Add some more chars after the \0, to test functions that overwrite the buffer set 1430 1414 * the \0 at the exact right position. 1431 1415 */ 1432 - char buf[10] = "test123456"; 1416 + char buf[11] = "test123456"; 1433 1417 buf[4] = '\0'; 1434 1418 1435 1419 ··· 1662 1646 return 0; 1663 1647 } 1664 1648 1649 + static int test_printf_error(void) 1650 + { 1651 + int fd, ret, saved_errno; 1652 + 1653 + fd = open("/dev/full", O_RDWR); 1654 + if (fd == -1) 1655 + return 1; 1656 + 1657 + errno = 0; 1658 + ret = dprintf(fd, "foo"); 1659 + saved_errno = errno; 1660 + close(fd); 1661 + 1662 + if (ret != -1) 1663 + return 2; 1664 + 1665 + if (saved_errno != ENOSPC) 1666 + return 3; 1667 + 1668 + return 0; 1669 + } 1670 + 1665 1671 static int run_printf(int min, int max) 1666 1672 { 1667 1673 int test; ··· 1713 1675 CASE_TEST(width_trunc); EXPECT_VFPRINTF(25, " ", "%25d", 1); break; 1714 1676 CASE_TEST(scanf); EXPECT_ZR(1, test_scanf()); break; 1715 1677 CASE_TEST(strerror); EXPECT_ZR(1, test_strerror()); break; 1678 + CASE_TEST(printf_error); EXPECT_ZR(1, test_printf_error()); break; 1716 1679 case __LINE__: 1717 1680 return ret; /* must be last */ 1718 1681 /* note: do not set any defaults so as to permit holes above */ ··· 1801 1762 if (stat("/dev/.", &stat_buf) == 0 || mkdir("/dev", 0755) == 0) { 1802 1763 if (stat("/dev/console", &stat_buf) != 0 || 1803 1764 stat("/dev/null", &stat_buf) != 0 || 1804 - stat("/dev/zero", &stat_buf) != 0) { 1765 + stat("/dev/zero", &stat_buf) != 0 || 1766 + stat("/dev/full", &stat_buf) != 0) { 1805 1767 /* try devtmpfs first, otherwise fall back to manual creation */ 1806 1768 if (mount("/dev", "/dev", "devtmpfs", 0, 0) != 0) { 1807 1769 mknod("/dev/console", 0600 | S_IFCHR, makedev(5, 1)); 1808 1770 mknod("/dev/null", 0666 | S_IFCHR, makedev(1, 3)); 1809 1771 mknod("/dev/zero", 0666 | S_IFCHR, makedev(1, 5)); 1772 + mknod("/dev/full", 0666 | S_IFCHR, makedev(1, 7)); 1810 1773 } 1811 1774 } 1812 1775 }
+10 -4
tools/testing/selftests/nolibc/run-tests.sh
··· 18 18 werror=1 19 19 llvm= 20 20 all_archs=( 21 - i386 x86_64 21 + i386 x86_64 x32 22 22 arm64 arm armthumb 23 - mips32le mips32be 23 + mips32le mips32be mipsn32le mipsn32be mips64le mips64be 24 24 ppc ppc64 ppc64le 25 25 riscv32 riscv64 26 26 s390x s390 27 27 loongarch 28 28 sparc32 sparc64 29 29 m68k 30 + sh4 30 31 ) 31 32 archs="${all_archs[@]}" 32 33 ··· 115 114 mips*) echo mips;; 116 115 s390*) echo s390;; 117 116 sparc*) echo sparc64;; 117 + x32*) echo x86_64;; 118 118 *) echo "$1";; 119 119 esac 120 120 } ··· 171 169 if [ "$werror" -ne 0 ]; then 172 170 CFLAGS_EXTRA="$CFLAGS_EXTRA -Werror" 173 171 fi 174 - MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" LLVM="${llvm}" O="${build_dir}") 172 + MAKE=(make -f Makefile.nolibc -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" LLVM="${llvm}" O="${build_dir}") 175 173 176 174 case "$test_mode" in 177 175 'system') ··· 189 187 echo "Unsupported configuration" 190 188 return 191 189 fi 192 - if [ "$arch" = "m68k" ] && [ "$llvm" = "1" ]; then 190 + if [ "$arch" = "m68k" -o "$arch" = "sh4" ] && [ "$llvm" = "1" ]; then 191 + echo "Unsupported configuration" 192 + return 193 + fi 194 + if [ "$arch" = "x32" ] && [ "$test_mode" = "user" ]; then 193 195 echo "Unsupported configuration" 194 196 return 195 197 fi