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-20250308-for-6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu

Pull nolibc updates from Paul McKenney:
- 32bit s390 support
- opendir() and friends
- openat() support
- sscanf() support
- various cleanups

[ Paul has just forwarded the pull request from Thomas Weißschuh, so
the tag signature is from Thomas, not Paul - Linus ]

* tag 'nolibc-20250308-for-6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: (26 commits)
tools/nolibc: don't use asm/ UAPI headers
selftests/nolibc: stop testing constructor order
selftests/nolibc: use O_RDONLY flag instead of 0
tools/nolibc: drop outdated example from overview comment
tools/nolibc: process open() vararg as mode_t
tools/nolibc: always use openat(2) instead of open(2)
tools/nolibc: add support for openat(2)
selftests/nolibc: add armthumb configuration
selftests/nolibc: explicitly enable ARM mode
Revert "selftests: kselftest: Fix build failure with NOLIBC"
tools/nolibc: add support for [v]sscanf()
tools/nolibc: add support for 32-bit s390
selftests/nolibc: rename s390 to s390x
selftests/nolibc: only run constructor tests on nolibc
selftests/nolibc: split up architecture list in run-tests.sh
tools/nolibc: add support for directory access
tools/nolibc: add support for sys_llseek()
selftests/nolibc: always keep test kernel configuration up to date
selftests/nolibc: execute defconfig before other targets
selftests/nolibc: drop call to mrproper target
...

+457 -56
+1
tools/include/nolibc/Makefile
··· 29 29 compiler.h \ 30 30 crt.h \ 31 31 ctype.h \ 32 + dirent.h \ 32 33 errno.h \ 33 34 nolibc.h \ 34 35 signal.h \
+1
tools/include/nolibc/arch-mips.h
··· 179 179 }) 180 180 181 181 /* startup code, note that it's called __start on MIPS */ 182 + void __start(void); 182 183 void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector __start(void) 183 184 { 184 185 __asm__ volatile (
+7 -2
tools/include/nolibc/arch-s390.h
··· 5 5 6 6 #ifndef _NOLIBC_ARCH_S390_H 7 7 #define _NOLIBC_ARCH_S390_H 8 - #include <asm/signal.h> 9 - #include <asm/unistd.h> 8 + #include <linux/signal.h> 9 + #include <linux/unistd.h> 10 10 11 11 #include "compiler.h" 12 12 #include "crt.h" ··· 143 143 void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void) 144 144 { 145 145 __asm__ volatile ( 146 + #ifdef __s390x__ 146 147 "lgr %r2, %r15\n" /* save stack pointer to %r2, as arg1 of _start_c */ 147 148 "aghi %r15, -160\n" /* allocate new stackframe */ 149 + #else 150 + "lr %r2, %r15\n" 151 + "ahi %r15, -96\n" 152 + #endif 148 153 "xc 0(8,%r15), 0(%r15)\n" /* clear backchain */ 149 154 "brasl %r14, _start_c\n" /* transfer to c runtime */ 150 155 );
+1 -1
tools/include/nolibc/arch.h
··· 29 29 #include "arch-powerpc.h" 30 30 #elif defined(__riscv) 31 31 #include "arch-riscv.h" 32 - #elif defined(__s390x__) 32 + #elif defined(__s390x__) || defined(__s390__) 33 33 #include "arch-s390.h" 34 34 #elif defined(__loongarch__) 35 35 #include "arch-loongarch.h"
+2
tools/include/nolibc/crt.h
··· 10 10 char **environ __attribute__((weak)); 11 11 const unsigned long *_auxv __attribute__((weak)); 12 12 13 + void _start(void); 13 14 static void __stack_chk_init(void); 14 15 static void exit(int); 15 16 ··· 23 22 extern void (*const __fini_array_start[])(void) __attribute__((weak)); 24 23 extern void (*const __fini_array_end[])(void) __attribute__((weak)); 25 24 25 + void _start_c(long *sp); 26 26 __attribute__((weak,used)) 27 27 void _start_c(long *sp) 28 28 {
+98
tools/include/nolibc/dirent.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + /* 3 + * Directory access for NOLIBC 4 + * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net> 5 + */ 6 + 7 + #ifndef _NOLIBC_DIRENT_H 8 + #define _NOLIBC_DIRENT_H 9 + 10 + #include "stdint.h" 11 + #include "types.h" 12 + 13 + #include <linux/limits.h> 14 + 15 + struct dirent { 16 + ino_t d_ino; 17 + char d_name[NAME_MAX + 1]; 18 + }; 19 + 20 + /* See comment of FILE in stdio.h */ 21 + typedef struct { 22 + char dummy[1]; 23 + } DIR; 24 + 25 + static __attribute__((unused)) 26 + DIR *fdopendir(int fd) 27 + { 28 + if (fd < 0) { 29 + SET_ERRNO(EBADF); 30 + return NULL; 31 + } 32 + return (DIR *)(intptr_t)~fd; 33 + } 34 + 35 + static __attribute__((unused)) 36 + DIR *opendir(const char *name) 37 + { 38 + int fd; 39 + 40 + fd = open(name, O_RDONLY); 41 + if (fd == -1) 42 + return NULL; 43 + return fdopendir(fd); 44 + } 45 + 46 + static __attribute__((unused)) 47 + int closedir(DIR *dirp) 48 + { 49 + intptr_t i = (intptr_t)dirp; 50 + 51 + if (i >= 0) { 52 + SET_ERRNO(EBADF); 53 + return -1; 54 + } 55 + return close(~i); 56 + } 57 + 58 + static __attribute__((unused)) 59 + int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) 60 + { 61 + char buf[sizeof(struct linux_dirent64) + NAME_MAX + 1]; 62 + struct linux_dirent64 *ldir = (void *)buf; 63 + intptr_t i = (intptr_t)dirp; 64 + int fd, ret; 65 + 66 + if (i >= 0) 67 + return EBADF; 68 + 69 + fd = ~i; 70 + 71 + ret = sys_getdents64(fd, ldir, sizeof(buf)); 72 + if (ret < 0) 73 + return -ret; 74 + if (ret == 0) { 75 + *result = NULL; 76 + return 0; 77 + } 78 + 79 + /* 80 + * getdents64() returns as many entries as fit the buffer. 81 + * readdir() can only return one entry at a time. 82 + * Make sure the non-returned ones are not skipped. 83 + */ 84 + ret = lseek(fd, ldir->d_off, SEEK_SET); 85 + if (ret == -1) 86 + return errno; 87 + 88 + entry->d_ino = ldir->d_ino; 89 + /* the destination should always be big enough */ 90 + strlcpy(entry->d_name, ldir->d_name, sizeof(entry->d_name)); 91 + *result = entry; 92 + return 0; 93 + } 94 + 95 + /* make sure to include all global symbols */ 96 + #include "nolibc.h" 97 + 98 + #endif /* _NOLIBC_DIRENT_H */
+1 -1
tools/include/nolibc/errno.h
··· 7 7 #ifndef _NOLIBC_ERRNO_H 8 8 #define _NOLIBC_ERRNO_H 9 9 10 - #include <asm/errno.h> 10 + #include <linux/errno.h> 11 11 12 12 #ifndef NOLIBC_IGNORE_ERRNO 13 13 #define SET_ERRNO(v) do { errno = (v); } while (0)
+2 -2
tools/include/nolibc/nolibc.h
··· 31 31 * - The third level is the libc call definition. It exposes the lower raw 32 32 * sys_<name>() calls in a way that looks like what a libc usually does, 33 33 * takes care of specific input values, and of setting errno upon error. 34 - * There can be minor variations compared to standard libc calls. For 35 - * example the open() call always takes 3 args here. 34 + * There can be minor variations compared to standard libc calls. 36 35 * 37 36 * The errno variable is declared static and unused. This way it can be 38 37 * optimized away if not used. However this means that a program made of ··· 104 105 #include "string.h" 105 106 #include "time.h" 106 107 #include "stackprotector.h" 108 + #include "dirent.h" 107 109 108 110 /* Used by programs to avoid std includes */ 109 111 #define NOLIBC
+1
tools/include/nolibc/signal.h
··· 13 13 #include "sys.h" 14 14 15 15 /* This one is not marked static as it's needed by libgcc for divide by zero */ 16 + int raise(int signal); 16 17 __attribute__((weak,unused,section(".text.nolibc_raise"))) 17 18 int raise(int signal) 18 19 {
+2
tools/include/nolibc/stackprotector.h
··· 18 18 * triggering stack protector errors themselves 19 19 */ 20 20 21 + void __stack_chk_fail(void); 21 22 __attribute__((weak,used,noreturn,section(".text.nolibc_stack_chk"))) 22 23 void __stack_chk_fail(void) 23 24 { ··· 29 28 for (;;); 30 29 } 31 30 31 + void __stack_chk_fail_local(void); 32 32 __attribute__((weak,noreturn,section(".text.nolibc_stack_chk"))) 33 33 void __stack_chk_fail_local(void) 34 34 {
+98
tools/include/nolibc/stdio.h
··· 350 350 } 351 351 352 352 static __attribute__((unused)) 353 + int vsscanf(const char *str, const char *format, va_list args) 354 + { 355 + uintmax_t uval; 356 + intmax_t ival; 357 + int base; 358 + char *endptr; 359 + int matches; 360 + int lpref; 361 + 362 + matches = 0; 363 + 364 + while (1) { 365 + if (*format == '%') { 366 + /* start of pattern */ 367 + lpref = 0; 368 + format++; 369 + 370 + if (*format == 'l') { 371 + /* same as in printf() */ 372 + lpref = 1; 373 + format++; 374 + if (*format == 'l') { 375 + lpref = 2; 376 + format++; 377 + } 378 + } 379 + 380 + if (*format == '%') { 381 + /* literal % */ 382 + if ('%' != *str) 383 + goto done; 384 + str++; 385 + format++; 386 + continue; 387 + } else if (*format == 'd') { 388 + ival = strtoll(str, &endptr, 10); 389 + if (lpref == 0) 390 + *va_arg(args, int *) = ival; 391 + else if (lpref == 1) 392 + *va_arg(args, long *) = ival; 393 + else if (lpref == 2) 394 + *va_arg(args, long long *) = ival; 395 + } else if (*format == 'u' || *format == 'x' || *format == 'X') { 396 + base = *format == 'u' ? 10 : 16; 397 + uval = strtoull(str, &endptr, base); 398 + if (lpref == 0) 399 + *va_arg(args, unsigned int *) = uval; 400 + else if (lpref == 1) 401 + *va_arg(args, unsigned long *) = uval; 402 + else if (lpref == 2) 403 + *va_arg(args, unsigned long long *) = uval; 404 + } else if (*format == 'p') { 405 + *va_arg(args, void **) = (void *)strtoul(str, &endptr, 16); 406 + } else { 407 + SET_ERRNO(EILSEQ); 408 + goto done; 409 + } 410 + 411 + format++; 412 + str = endptr; 413 + matches++; 414 + 415 + } else if (*format == '\0') { 416 + goto done; 417 + } else if (isspace(*format)) { 418 + /* skip spaces in format and str */ 419 + while (isspace(*format)) 420 + format++; 421 + while (isspace(*str)) 422 + str++; 423 + } else if (*format == *str) { 424 + /* literal match */ 425 + format++; 426 + str++; 427 + } else { 428 + if (!matches) 429 + matches = EOF; 430 + goto done; 431 + } 432 + } 433 + 434 + done: 435 + return matches; 436 + } 437 + 438 + static __attribute__((unused, format(scanf, 2, 3))) 439 + int sscanf(const char *str, const char *format, ...) 440 + { 441 + va_list args; 442 + int ret; 443 + 444 + va_start(args, format); 445 + ret = vsscanf(str, format, args); 446 + va_end(args); 447 + return ret; 448 + } 449 + 450 + static __attribute__((unused)) 353 451 void perror(const char *msg) 354 452 { 355 453 fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno);
+1
tools/include/nolibc/stdlib.h
··· 30 30 */ 31 31 32 32 /* must be exported, as it's used by libgcc for various divide functions */ 33 + void abort(void); 33 34 __attribute__((weak,unused,noreturn,section(".text.nolibc_abort"))) 34 35 void abort(void) 35 36 {
+4
tools/include/nolibc/string.h
··· 32 32 /* might be ignored by the compiler without -ffreestanding, then found as 33 33 * missing. 34 34 */ 35 + void *memmove(void *dst, const void *src, size_t len); 35 36 __attribute__((weak,unused,section(".text.nolibc_memmove"))) 36 37 void *memmove(void *dst, const void *src, size_t len) 37 38 { ··· 57 56 58 57 #ifndef NOLIBC_ARCH_HAS_MEMCPY 59 58 /* must be exported, as it's used by libgcc on ARM */ 59 + void *memcpy(void *dst, const void *src, size_t len); 60 60 __attribute__((weak,unused,section(".text.nolibc_memcpy"))) 61 61 void *memcpy(void *dst, const void *src, size_t len) 62 62 { ··· 75 73 /* might be ignored by the compiler without -ffreestanding, then found as 76 74 * missing. 77 75 */ 76 + void *memset(void *dst, int b, size_t len); 78 77 __attribute__((weak,unused,section(".text.nolibc_memset"))) 79 78 void *memset(void *dst, int b, size_t len) 80 79 { ··· 127 124 * thus itself, hence the asm() statement below that's meant to disable this 128 125 * confusing practice. 129 126 */ 127 + size_t strlen(const char *str); 130 128 __attribute__((weak,unused,section(".text.nolibc_strlen"))) 131 129 size_t strlen(const char *str) 132 130 {
+62 -21
tools/include/nolibc/sys.h
··· 10 10 #include "std.h" 11 11 12 12 /* system includes */ 13 - #include <asm/unistd.h> 14 - #include <asm/signal.h> /* for SIGCHLD */ 15 - #include <asm/ioctls.h> 16 - #include <asm/mman.h> 13 + #include <linux/unistd.h> 14 + #include <linux/signal.h> /* for SIGCHLD */ 15 + #include <linux/termios.h> 16 + #include <linux/mman.h> 17 17 #include <linux/fs.h> 18 18 #include <linux/loop.h> 19 19 #include <linux/time.h> ··· 23 23 #include <linux/prctl.h> 24 24 #include <linux/resource.h> 25 25 #include <linux/utsname.h> 26 - #include <linux/signal.h> 27 26 28 27 #include "arch.h" 29 28 #include "errno.h" ··· 531 532 532 533 533 534 /* 534 - * int ioctl(int fd, unsigned long req, void *value); 535 + * int ioctl(int fd, unsigned long cmd, ... arg); 535 536 */ 536 537 537 538 static __attribute__((unused)) 538 - int sys_ioctl(int fd, unsigned long req, void *value) 539 + long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) 539 540 { 540 - return my_syscall3(__NR_ioctl, fd, req, value); 541 + return my_syscall3(__NR_ioctl, fd, cmd, arg); 541 542 } 542 543 543 - static __attribute__((unused)) 544 - int ioctl(int fd, unsigned long req, void *value) 545 - { 546 - return __sysret(sys_ioctl(fd, req, value)); 547 - } 544 + #define ioctl(fd, cmd, arg) __sysret(sys_ioctl(fd, cmd, (unsigned long)(arg))) 548 545 549 546 /* 550 547 * int kill(pid_t pid, int signal); ··· 597 602 } 598 603 599 604 static __attribute__((unused)) 605 + int sys_llseek(int fd, unsigned long offset_high, unsigned long offset_low, 606 + __kernel_loff_t *result, int whence) 607 + { 608 + #ifdef __NR_llseek 609 + return my_syscall5(__NR_llseek, fd, offset_high, offset_low, result, whence); 610 + #else 611 + return __nolibc_enosys(__func__, fd, offset_high, offset_low, result, whence); 612 + #endif 613 + } 614 + 615 + static __attribute__((unused)) 600 616 off_t lseek(int fd, off_t offset, int whence) 601 617 { 602 - return __sysret(sys_lseek(fd, offset, whence)); 618 + __kernel_loff_t loff = 0; 619 + off_t result; 620 + int ret; 621 + 622 + result = sys_lseek(fd, offset, whence); 623 + if (result == -ENOSYS) { 624 + /* Only exists on 32bit where nolibc off_t is also 32bit */ 625 + ret = sys_llseek(fd, 0, offset, &loff, whence); 626 + if (ret < 0) 627 + result = ret; 628 + else if (loff != (off_t)loff) 629 + result = -EOVERFLOW; 630 + else 631 + result = loff; 632 + } 633 + 634 + return __sysret(result); 603 635 } 604 636 605 637 ··· 764 742 return __sysret(sys_mount(src, tgt, fst, flags, data)); 765 743 } 766 744 745 + /* 746 + * int openat(int dirfd, const char *path, int flags[, mode_t mode]); 747 + */ 748 + 749 + static __attribute__((unused)) 750 + int sys_openat(int dirfd, const char *path, int flags, mode_t mode) 751 + { 752 + return my_syscall4(__NR_openat, dirfd, path, flags, mode); 753 + } 754 + 755 + static __attribute__((unused)) 756 + int openat(int dirfd, const char *path, int flags, ...) 757 + { 758 + mode_t mode = 0; 759 + 760 + if (flags & O_CREAT) { 761 + va_list args; 762 + 763 + va_start(args, flags); 764 + mode = va_arg(args, mode_t); 765 + va_end(args); 766 + } 767 + 768 + return __sysret(sys_openat(dirfd, path, flags, mode)); 769 + } 767 770 768 771 /* 769 772 * int open(const char *path, int flags[, mode_t mode]); ··· 797 750 static __attribute__((unused)) 798 751 int sys_open(const char *path, int flags, mode_t mode) 799 752 { 800 - #ifdef __NR_openat 801 753 return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 802 - #elif defined(__NR_open) 803 - return my_syscall3(__NR_open, path, flags, mode); 804 - #else 805 - return __nolibc_enosys(__func__, path, flags, mode); 806 - #endif 807 754 } 808 755 809 756 static __attribute__((unused)) ··· 809 768 va_list args; 810 769 811 770 va_start(args, flags); 812 - mode = va_arg(args, int); 771 + mode = va_arg(args, mode_t); 813 772 va_end(args); 814 773 } 815 774
-5
tools/testing/selftests/kselftest.h
··· 444 444 static inline int ksft_min_kernel_version(unsigned int min_major, 445 445 unsigned int min_minor) 446 446 { 447 - #ifdef NOLIBC 448 - ksft_print_msg("NOLIBC: Can't check kernel version: Function not implemented\n"); 449 - return 0; 450 - #else 451 447 unsigned int major, minor; 452 448 struct utsname info; 453 449 ··· 451 455 ksft_exit_fail_msg("Can't parse kernel version\n"); 452 456 453 457 return major > min_major || (major == min_major && minor >= min_minor); 454 - #endif 455 458 } 456 459 457 460 #endif /* __KSELFTEST_H */
+21 -9
tools/testing/selftests/nolibc/Makefile
··· 47 47 XARCH = $(or $(XARCH_$(ARCH)),$(ARCH)) 48 48 49 49 # map from user input variants to their kernel supported architectures 50 + ARCH_armthumb = arm 50 51 ARCH_ppc = powerpc 51 52 ARCH_ppc64 = powerpc 52 53 ARCH_ppc64le = powerpc ··· 55 54 ARCH_mips32be = mips 56 55 ARCH_riscv32 = riscv 57 56 ARCH_riscv64 = riscv 57 + ARCH_s390x = s390 58 58 ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) 59 59 60 60 # kernel image names by architecture ··· 64 62 IMAGE_x86 = arch/x86/boot/bzImage 65 63 IMAGE_arm64 = arch/arm64/boot/Image 66 64 IMAGE_arm = arch/arm/boot/zImage 65 + IMAGE_armthumb = arch/arm/boot/zImage 67 66 IMAGE_mips32le = vmlinuz 68 67 IMAGE_mips32be = vmlinuz 69 68 IMAGE_ppc = vmlinux ··· 73 70 IMAGE_riscv = arch/riscv/boot/Image 74 71 IMAGE_riscv32 = arch/riscv/boot/Image 75 72 IMAGE_riscv64 = arch/riscv/boot/Image 73 + IMAGE_s390x = arch/s390/boot/bzImage 76 74 IMAGE_s390 = arch/s390/boot/bzImage 77 75 IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi 78 76 IMAGE = $(objtree)/$(IMAGE_$(XARCH)) ··· 85 81 DEFCONFIG_x86 = defconfig 86 82 DEFCONFIG_arm64 = defconfig 87 83 DEFCONFIG_arm = multi_v7_defconfig 84 + DEFCONFIG_armthumb = multi_v7_defconfig 88 85 DEFCONFIG_mips32le = malta_defconfig 89 - DEFCONFIG_mips32be = malta_defconfig 86 + DEFCONFIG_mips32be = malta_defconfig generic/eb.config 90 87 DEFCONFIG_ppc = pmac32_defconfig 91 88 DEFCONFIG_ppc64 = powernv_be_defconfig 92 89 DEFCONFIG_ppc64le = powernv_defconfig 93 90 DEFCONFIG_riscv = defconfig 94 91 DEFCONFIG_riscv32 = rv32_defconfig 95 92 DEFCONFIG_riscv64 = defconfig 96 - DEFCONFIG_s390 = defconfig 93 + DEFCONFIG_s390x = defconfig 94 + DEFCONFIG_s390 = defconfig compat.config 97 95 DEFCONFIG_loongarch = defconfig 98 96 DEFCONFIG = $(DEFCONFIG_$(XARCH)) 99 97 100 - EXTRACONFIG_mips32be = -d CONFIG_CPU_LITTLE_ENDIAN -e CONFIG_CPU_BIG_ENDIAN 101 98 EXTRACONFIG = $(EXTRACONFIG_$(XARCH)) 102 99 103 100 # optional tests to run (default = all) ··· 110 105 QEMU_ARCH_x86 = x86_64 111 106 QEMU_ARCH_arm64 = aarch64 112 107 QEMU_ARCH_arm = arm 108 + QEMU_ARCH_armthumb = arm 113 109 QEMU_ARCH_mips32le = mipsel # works with malta_defconfig 114 110 QEMU_ARCH_mips32be = mips 115 111 QEMU_ARCH_ppc = ppc ··· 119 113 QEMU_ARCH_riscv = riscv64 120 114 QEMU_ARCH_riscv32 = riscv32 121 115 QEMU_ARCH_riscv64 = riscv64 116 + QEMU_ARCH_s390x = s390x 122 117 QEMU_ARCH_s390 = s390x 123 118 QEMU_ARCH_loongarch = loongarch64 124 119 QEMU_ARCH = $(QEMU_ARCH_$(XARCH)) ··· 140 133 QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" 141 134 QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 142 135 QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 136 + QEMU_ARGS_armthumb = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 143 137 QEMU_ARGS_mips32le = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 144 138 QEMU_ARGS_mips32be = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" 145 139 QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" ··· 149 141 QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 150 142 QEMU_ARGS_riscv32 = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 151 143 QEMU_ARGS_riscv64 = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 144 + QEMU_ARGS_s390x = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 152 145 QEMU_ARGS_s390 = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 153 146 QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" 154 147 QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA) ··· 165 156 endif 166 157 167 158 CFLAGS_i386 = $(call cc-option,-m32) 159 + CFLAGS_arm = -marm 160 + CFLAGS_armthumb = -mthumb -march=armv6t2 168 161 CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) 169 162 CFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) 170 163 CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2) 171 - CFLAGS_s390 = -m64 164 + CFLAGS_s390x = -m64 165 + CFLAGS_s390 = -m31 172 166 CFLAGS_mips32le = -EL -mabi=32 -fPIC 173 167 CFLAGS_mips32be = -EB -mabi=32 174 168 CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all)) 175 169 CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \ 176 - $(call cc-option,-fno-stack-protector) \ 170 + $(call cc-option,-fno-stack-protector) $(call cc-option,-Wmissing-prototypes) \ 177 171 $(CFLAGS_$(XARCH)) $(CFLAGS_STACKPROTECTOR) $(CFLAGS_EXTRA) 178 172 LDFLAGS := 179 173 ··· 232 220 233 221 sysroot: sysroot/$(ARCH)/include 234 222 235 - sysroot/$(ARCH)/include: 223 + sysroot/$(ARCH)/include: | defconfig 236 224 $(Q)rm -rf sysroot/$(ARCH) sysroot/sysroot 237 225 $(QUIET_MKDIR)mkdir -p sysroot 238 226 $(Q)$(MAKE) -C $(srctree) outputmakefile ··· 276 264 $(Q)cp nolibc-test initramfs/init 277 265 278 266 defconfig: 279 - $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) mrproper $(DEFCONFIG) prepare 267 + $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(DEFCONFIG) 280 268 $(Q)if [ -n "$(EXTRACONFIG)" ]; then \ 281 269 $(srctree)/scripts/config --file $(objtree)/.config $(EXTRACONFIG); \ 282 270 $(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) olddefconfig < /dev/null; \ 283 271 fi 284 272 285 - kernel: 273 + kernel: | defconfig 286 274 $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) < /dev/null 287 275 288 - kernel-standalone: initramfs 276 + kernel-standalone: initramfs | defconfig 289 277 $(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs < /dev/null 290 278 291 279 # run the tests after building the kernel
+3 -3
tools/testing/selftests/nolibc/nolibc-test-linkage.c
··· 11 11 return &errno; 12 12 } 13 13 14 - int linkage_test_constructor_test_value; 14 + int linkage_test_constructor_test_value = 0; 15 15 16 16 __attribute__((constructor)) 17 17 static void constructor1(void) 18 18 { 19 - linkage_test_constructor_test_value = 2; 19 + linkage_test_constructor_test_value |= 1 << 0; 20 20 } 21 21 22 22 __attribute__((constructor)) 23 23 static void constructor2(void) 24 24 { 25 - linkage_test_constructor_test_value *= 3; 25 + linkage_test_constructor_test_value |= 1 << 1; 26 26 }
+132 -6
tools/testing/selftests/nolibc/nolibc-test.c
··· 43 43 #endif 44 44 #endif 45 45 46 + #pragma GCC diagnostic ignored "-Wmissing-prototypes" 47 + 46 48 #include "nolibc-test-linkage.h" 47 49 48 50 /* for the type of int_fast16_t and int_fast32_t, musl differs from glibc and nolibc */ ··· 692 690 __attribute__((constructor)) 693 691 static void constructor1(void) 694 692 { 695 - constructor_test_value = 1; 693 + constructor_test_value |= 1 << 0; 696 694 } 697 695 698 696 __attribute__((constructor)) 699 697 static void constructor2(int argc, char **argv, char **envp) 700 698 { 701 699 if (argc && argv && envp) 702 - constructor_test_value *= 2; 700 + constructor_test_value |= 1 << 1; 703 701 } 704 702 705 703 int run_startup(int min, int max) ··· 738 736 CASE_TEST(environ_HOME); EXPECT_PTRNZ(1, getenv("HOME")); break; 739 737 CASE_TEST(auxv_addr); EXPECT_PTRGT(test_auxv != (void *)-1, test_auxv, brk); break; 740 738 CASE_TEST(auxv_AT_UID); EXPECT_EQ(1, getauxval(AT_UID), getuid()); break; 741 - CASE_TEST(constructor); EXPECT_EQ(1, constructor_test_value, 2); break; 739 + CASE_TEST(constructor); EXPECT_EQ(is_nolibc, constructor_test_value, 0x3); break; 742 740 CASE_TEST(linkage_errno); EXPECT_PTREQ(1, linkage_test_errno_addr(), &errno); break; 743 - CASE_TEST(linkage_constr); EXPECT_EQ(1, linkage_test_constructor_test_value, 6); break; 741 + CASE_TEST(linkage_constr); EXPECT_EQ(1, linkage_test_constructor_test_value, 0x3); break; 744 742 case __LINE__: 745 743 return ret; /* must be last */ 746 744 /* note: do not set any defaults so as to permit holes above */ ··· 767 765 768 766 errno = err; 769 767 return ret; 768 + } 769 + 770 + static int test_dirent(void) 771 + { 772 + int comm = 0, cmdline = 0; 773 + struct dirent dirent, *result; 774 + DIR *dir; 775 + int ret; 776 + 777 + dir = opendir("/proc/self"); 778 + if (!dir) 779 + return 1; 780 + 781 + while (1) { 782 + errno = 0; 783 + ret = readdir_r(dir, &dirent, &result); 784 + if (ret != 0) 785 + return 1; 786 + if (!result) 787 + break; 788 + 789 + if (strcmp(dirent.d_name, "comm") == 0) 790 + comm++; 791 + else if (strcmp(dirent.d_name, "cmdline") == 0) 792 + cmdline++; 793 + } 794 + 795 + if (errno) 796 + return 1; 797 + 798 + ret = closedir(dir); 799 + if (ret) 800 + return 1; 801 + 802 + if (comm != 1 || cmdline != 1) 803 + return 1; 804 + 805 + return 0; 770 806 } 771 807 772 808 int test_getpagesize(void) ··· 1028 988 return 0; 1029 989 } 1030 990 991 + int test_openat(void) 992 + { 993 + int dev, null; 994 + 995 + dev = openat(AT_FDCWD, "/dev", O_DIRECTORY); 996 + if (dev < 0) 997 + return -1; 998 + 999 + null = openat(dev, "null", O_RDONLY); 1000 + close(dev); 1001 + if (null < 0) 1002 + return -1; 1003 + 1004 + close(null); 1005 + return 0; 1006 + } 1031 1007 1032 1008 /* Run syscall tests between IDs <min> and <max>. 1033 1009 * Return 0 on success, non-zero on failure. ··· 1115 1059 CASE_TEST(fork); EXPECT_SYSZR(1, test_fork()); break; 1116 1060 CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/"), -1); break; 1117 1061 CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break; 1062 + CASE_TEST(directories); EXPECT_SYSZR(proc, test_dirent()); break; 1118 1063 CASE_TEST(gettimeofday_tv); EXPECT_SYSZR(1, gettimeofday(&tv, NULL)); break; 1119 1064 CASE_TEST(gettimeofday_tv_tz);EXPECT_SYSZR(1, gettimeofday(&tv, &tz)); break; 1120 1065 CASE_TEST(getpagesize); EXPECT_SYSZR(1, test_getpagesize()); break; ··· 1130 1073 CASE_TEST(mmap_bad); EXPECT_PTRER(1, mmap(NULL, 0, PROT_READ, MAP_PRIVATE, 0, 0), MAP_FAILED, EINVAL); break; 1131 1074 CASE_TEST(munmap_bad); EXPECT_SYSER(1, munmap(NULL, 0), -1, EINVAL); break; 1132 1075 CASE_TEST(mmap_munmap_good); EXPECT_SYSZR(1, test_mmap_munmap()); break; 1133 - CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break; 1134 - CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break; 1076 + CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", O_RDONLY), -1); if (tmp != -1) close(tmp); break; 1077 + CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", O_RDONLY), -1, ENOENT); if (tmp != -1) close(tmp); break; 1078 + CASE_TEST(openat_dir); EXPECT_SYSZR(1, test_openat()); break; 1135 1079 CASE_TEST(pipe); EXPECT_SYSZR(1, test_pipe()); break; 1136 1080 CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break; 1137 1081 CASE_TEST(poll_stdout); EXPECT_SYSNE(1, ({ struct pollfd fds = { 1, POLLOUT, 0}; poll(&fds, 1, 0); }), -1); break; ··· 1342 1284 return ret; 1343 1285 } 1344 1286 1287 + static int test_scanf(void) 1288 + { 1289 + unsigned long long ull; 1290 + unsigned long ul; 1291 + unsigned int u; 1292 + long long ll; 1293 + long l; 1294 + void *p; 1295 + int i; 1296 + 1297 + /* return __LINE__ to point to the specific failure */ 1298 + 1299 + /* test EOF */ 1300 + if (sscanf("", "foo") != EOF) 1301 + return __LINE__; 1302 + 1303 + /* test simple literal without placeholder */ 1304 + if (sscanf("foo", "foo") != 0) 1305 + return __LINE__; 1306 + 1307 + /* test single placeholder */ 1308 + if (sscanf("123", "%d", &i) != 1) 1309 + return __LINE__; 1310 + 1311 + if (i != 123) 1312 + return __LINE__; 1313 + 1314 + /* test multiple place holders and separators */ 1315 + if (sscanf("a123b456c0x90", "a%db%uc%p", &i, &u, &p) != 3) 1316 + return __LINE__; 1317 + 1318 + if (i != 123) 1319 + return __LINE__; 1320 + 1321 + if (u != 456) 1322 + return __LINE__; 1323 + 1324 + if (p != (void *)0x90) 1325 + return __LINE__; 1326 + 1327 + /* test space handling */ 1328 + if (sscanf("a b1", "a b%d", &i) != 1) 1329 + return __LINE__; 1330 + 1331 + if (i != 1) 1332 + return __LINE__; 1333 + 1334 + /* test literal percent */ 1335 + if (sscanf("a%1", "a%%%d", &i) != 1) 1336 + return __LINE__; 1337 + 1338 + if (i != 1) 1339 + return __LINE__; 1340 + 1341 + /* test stdint.h types */ 1342 + if (sscanf("1|2|3|4|5|6", 1343 + "%d|%ld|%lld|%u|%lu|%llu", 1344 + &i, &l, &ll, &u, &ul, &ull) != 6) 1345 + return __LINE__; 1346 + 1347 + if (i != 1 || l != 2 || ll != 3 || 1348 + u != 4 || ul != 5 || ull != 6) 1349 + return __LINE__; 1350 + 1351 + return 0; 1352 + } 1353 + 1345 1354 static int run_vfprintf(int min, int max) 1346 1355 { 1347 1356 int test; ··· 1430 1305 CASE_TEST(char); EXPECT_VFPRINTF(1, "c", "%c", 'c'); break; 1431 1306 CASE_TEST(hex); EXPECT_VFPRINTF(1, "f", "%x", 0xf); break; 1432 1307 CASE_TEST(pointer); EXPECT_VFPRINTF(3, "0x1", "%p", (void *) 0x1); break; 1308 + CASE_TEST(scanf); EXPECT_ZR(1, test_scanf()); break; 1433 1309 case __LINE__: 1434 1310 return ret; /* must be last */ 1435 1311 /* note: do not set any defaults so as to permit holes above */
+20 -6
tools/testing/selftests/nolibc/run-tests.sh
··· 17 17 test_mode=system 18 18 werror=1 19 19 llvm= 20 - archs="i386 x86_64 arm64 arm mips32le mips32be ppc ppc64 ppc64le riscv32 riscv64 s390 loongarch" 20 + all_archs=( 21 + i386 x86_64 22 + arm64 arm armthumb 23 + mips32le mips32be 24 + ppc ppc64 ppc64le 25 + riscv32 riscv64 26 + s390x s390 27 + loongarch 28 + ) 29 + archs="${all_archs[@]}" 21 30 22 31 TEMP=$(getopt -o 'j:d:c:b:a:m:pelh' -n "$0" -- "$@") 23 32 ··· 103 94 crosstool_arch() { 104 95 case "$1" in 105 96 arm64) echo aarch64;; 97 + armthumb) echo arm;; 106 98 ppc) echo powerpc;; 107 99 ppc64) echo powerpc64;; 108 100 ppc64le) echo powerpc64;; 109 101 riscv) echo riscv64;; 110 102 loongarch) echo loongarch64;; 111 103 mips*) echo mips;; 104 + s390*) echo s390;; 112 105 *) echo "$1";; 113 106 esac 114 107 } 115 108 116 109 crosstool_abi() { 117 110 case "$1" in 118 - arm) echo linux-gnueabi;; 111 + arm | armthumb) echo linux-gnueabi;; 119 112 *) echo linux;; 120 113 esac 121 114 } ··· 168 157 fi 169 158 MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" LLVM="${llvm}" O="${build_dir}") 170 159 171 - mkdir -p "$build_dir" 172 - if [ "$test_mode" = "system" ] && [ ! -f "${build_dir}/.config" ]; then 173 - swallow_output "${MAKE[@]}" defconfig 174 - fi 175 160 case "$test_mode" in 176 161 'system') 177 162 test_target=run ··· 180 173 exit 1 181 174 esac 182 175 printf '%-15s' "$arch:" 176 + if [ "$arch" = "s390" ] && ([ "$llvm" = "1" ] || [ "$test_mode" = "user" ]); then 177 + echo "Unsupported configuration" 178 + return 179 + fi 180 + 181 + mkdir -p "$build_dir" 182 + swallow_output "${MAKE[@]}" defconfig 183 183 swallow_output "${MAKE[@]}" CFLAGS_EXTRA="$CFLAGS_EXTRA" "$test_target" V=1 184 184 cp run.out run.out."${arch}" 185 185 "${MAKE[@]}" report | grep passed