diff options
author | Linus Torvalds | 2023-02-23 09:33:01 -0800 |
---|---|---|
committer | Linus Torvalds | 2023-02-23 09:33:01 -0800 |
commit | f01d4c8a22908956f4018ed334bb6713e41b37c1 (patch) | |
tree | a0144706cc6b09de5ae26d1f148b549d7a0778a4 /tools | |
parent | 525445efacdfeed71329ce8bc5f558859a894b8b (diff) | |
parent | c54ba4178159e440bea3826d22d43a9d0d94b071 (diff) |
Merge tag 'nolibc.2023.02.06a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu
Pull nolibc updates from Paul McKenney:
- Add s390 support
- Add support for the ARM Thumb1 instruction set
- Fix O_* flags definitions for open() and fcntl()
- Make errno a weak symbol instead of a static variable
- Export environ as a weak symbol
- Export _auxv as a weak symbol for auxilliary vector retrieval
- Implement getauxval() and getpagesize()
- Further improve self tests, including permitting userland testing of
the nolibc library
* tag 'nolibc.2023.02.06a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: (28 commits)
selftests/nolibc: Add a "run-user" target to test the program in user land
selftests/nolibc: Support "x86_64" for arch name
selftests/nolibc: Add `getpagesize(2)` selftest
nolibc/sys: Implement `getpagesize(2)` function
nolibc/stdlib: Implement `getauxval(3)` function
tools/nolibc: add auxiliary vector retrieval for s390
tools/nolibc: add auxiliary vector retrieval for mips
tools/nolibc: add auxiliary vector retrieval for riscv
tools/nolibc: add auxiliary vector retrieval for arm
tools/nolibc: add auxiliary vector retrieval for arm64
tools/nolibc: add auxiliary vector retrieval for x86_64
tools/nolibc: add auxiliary vector retrieval for i386
tools/nolibc: export environ as a weak symbol on s390
tools/nolibc: export environ as a weak symbol on riscv
tools/nolibc: export environ as a weak symbol on mips
tools/nolibc: export environ as a weak symbol on arm
tools/nolibc: export environ as a weak symbol on arm64
tools/nolibc: export environ as a weak symbol on i386
tools/nolibc: export environ as a weak symbol on x86_64
tools/nolibc: make errno a weak symbol instead of a static one
...
Diffstat (limited to 'tools')
-rw-r--r-- | tools/include/nolibc/arch-aarch64.h | 52 | ||||
-rw-r--r-- | tools/include/nolibc/arch-arm.h | 138 | ||||
-rw-r--r-- | tools/include/nolibc/arch-i386.h | 60 | ||||
-rw-r--r-- | tools/include/nolibc/arch-mips.h | 79 | ||||
-rw-r--r-- | tools/include/nolibc/arch-riscv.h | 62 | ||||
-rw-r--r-- | tools/include/nolibc/arch-s390.h | 226 | ||||
-rw-r--r-- | tools/include/nolibc/arch-x86_64.h | 52 | ||||
-rw-r--r-- | tools/include/nolibc/arch.h | 2 | ||||
-rw-r--r-- | tools/include/nolibc/errno.h | 4 | ||||
-rw-r--r-- | tools/include/nolibc/stdlib.h | 27 | ||||
-rw-r--r-- | tools/include/nolibc/sys.h | 24 | ||||
-rw-r--r-- | tools/testing/selftests/nolibc/Makefile | 17 | ||||
-rw-r--r-- | tools/testing/selftests/nolibc/nolibc-test.c | 30 | ||||
-rw-r--r-- | tools/testing/selftests/rcutorture/bin/functions.sh | 6 | ||||
-rwxr-xr-x | tools/testing/selftests/rcutorture/bin/mkinitrd.sh | 2 |
15 files changed, 579 insertions, 202 deletions
diff --git a/tools/include/nolibc/arch-aarch64.h b/tools/include/nolibc/arch-aarch64.h index f68baf8f395f..383baddef701 100644 --- a/tools/include/nolibc/arch-aarch64.h +++ b/tools/include/nolibc/arch-aarch64.h @@ -7,18 +7,6 @@ #ifndef _NOLIBC_ARCH_AARCH64_H #define _NOLIBC_ARCH_AARCH64_H -/* O_* macros for fcntl/open are architecture-specific */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x4000 - /* The struct returned by the newfstatat() syscall. Differs slightly from the * x86_64's stat one by field ordering, so be careful. */ @@ -181,19 +169,31 @@ struct sys_stat_struct { _arg1; \ }) -/* startup code */ -__asm__ (".section .text\n" - ".weak _start\n" - "_start:\n" - "ldr x0, [sp]\n" // argc (x0) was in the stack - "add x1, sp, 8\n" // argv (x1) = sp - "lsl x2, x0, 3\n" // envp (x2) = 8*argc ... - "add x2, x2, 8\n" // + 8 (skip null) - "add x2, x2, x1\n" // + argv - "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee - "bl main\n" // main() returns the status code, we'll exit with it. - "mov x8, 93\n" // NR_exit == 93 - "svc #0\n" - ""); +char **environ __attribute__((weak)); +const unsigned long *_auxv __attribute__((weak)); +/* startup code */ +void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) +{ + __asm__ volatile ( + "ldr x0, [sp]\n" // argc (x0) was in the stack + "add x1, sp, 8\n" // argv (x1) = sp + "lsl x2, x0, 3\n" // envp (x2) = 8*argc ... + "add x2, x2, 8\n" // + 8 (skip null) + "add x2, x2, x1\n" // + argv + "adrp x3, environ\n" // x3 = &environ (high bits) + "str x2, [x3, #:lo12:environ]\n" // store envp into environ + "mov x4, x2\n" // search for auxv (follows NULL after last env) + "0:\n" + "ldr x5, [x4], 8\n" // x5 = *x4; x4 += 8 + "cbnz x5, 0b\n" // and stop at NULL after last env + "adrp x3, _auxv\n" // x3 = &_auxv (high bits) + "str x4, [x3, #:lo12:_auxv]\n" // store x4 into _auxv + "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee + "bl main\n" // main() returns the status code, we'll exit with it. + "mov x8, 93\n" // NR_exit == 93 + "svc #0\n" + ); + __builtin_unreachable(); +} #endif // _NOLIBC_ARCH_AARCH64_H diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h index f31be8e967d6..42499f23e73c 100644 --- a/tools/include/nolibc/arch-arm.h +++ b/tools/include/nolibc/arch-arm.h @@ -7,18 +7,6 @@ #ifndef _NOLIBC_ARCH_ARM_H #define _NOLIBC_ARCH_ARM_H -/* O_* macros for fcntl/open are architecture-specific */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x4000 - /* The struct returned by the stat() syscall, 32-bit only, the syscall returns * exactly 56 bytes (stops before the unused array). In big endian, the format * differs as devices are returned as short only. @@ -70,20 +58,44 @@ struct sys_stat_struct { * don't have to experience issues with register constraints. * - the syscall number is always specified last in order to allow to force * some registers before (gcc refuses a %-register at the last position). + * - in thumb mode without -fomit-frame-pointer, r7 is also used to store the + * frame pointer, and we cannot directly assign it as a register variable, + * nor can we clobber it. Instead we assign the r6 register and swap it + * with r7 before calling svc, and r6 is marked as clobbered. + * We're just using any regular register which we assign to r7 after saving + * it. * * Also, ARM supports the old_select syscall if newselect is not available */ #define __ARCH_WANT_SYS_OLD_SELECT +#if (defined(__THUMBEB__) || defined(__THUMBEL__)) && \ + !defined(NOLIBC_OMIT_FRAME_POINTER) +/* swap r6,r7 needed in Thumb mode since we can't use nor clobber r7 */ +#define _NOLIBC_SYSCALL_REG "r6" +#define _NOLIBC_THUMB_SET_R7 "eor r7, r6\neor r6, r7\neor r7, r6\n" +#define _NOLIBC_THUMB_RESTORE_R7 "mov r7, r6\n" + +#else /* we're in ARM mode */ +/* in Arm mode we can directly use r7 */ +#define _NOLIBC_SYSCALL_REG "r7" +#define _NOLIBC_THUMB_SET_R7 "" +#define _NOLIBC_THUMB_RESTORE_R7 "" + +#endif /* end THUMB */ + #define my_syscall0(num) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0"); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ - : "r"(_num) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r"(_num) \ + : "r"(_arg1), \ + "r"(_num) \ : "memory", "cc", "lr" \ ); \ _arg1; \ @@ -91,12 +103,14 @@ struct sys_stat_struct { #define my_syscall1(num, arg1) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -106,13 +120,15 @@ struct sys_stat_struct { #define my_syscall2(num, arg1, arg2) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -122,14 +138,16 @@ struct sys_stat_struct { #define my_syscall3(num, arg1, arg2, arg3) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ register long _arg3 __asm__ ("r2") = (long)(arg3); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -139,15 +157,17 @@ struct sys_stat_struct { #define my_syscall4(num, arg1, arg2, arg3, arg4) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ register long _arg3 __asm__ ("r2") = (long)(arg3); \ register long _arg4 __asm__ ("r3") = (long)(arg4); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r"(_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -157,7 +177,7 @@ struct sys_stat_struct { #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ ({ \ - register long _num __asm__ ("r7") = (num); \ + register long _num __asm__(_NOLIBC_SYSCALL_REG) = (num); \ register long _arg1 __asm__ ("r0") = (long)(arg1); \ register long _arg2 __asm__ ("r1") = (long)(arg2); \ register long _arg3 __asm__ ("r2") = (long)(arg3); \ @@ -165,8 +185,10 @@ struct sys_stat_struct { register long _arg5 __asm__ ("r4") = (long)(arg5); \ \ __asm__ volatile ( \ + _NOLIBC_THUMB_SET_R7 \ "svc #0\n" \ - : "=r" (_arg1) \ + _NOLIBC_THUMB_RESTORE_R7 \ + : "=r"(_arg1), "=r" (_num) \ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \ "r"(_num) \ : "memory", "cc", "lr" \ @@ -174,31 +196,47 @@ struct sys_stat_struct { _arg1; \ }) +char **environ __attribute__((weak)); +const unsigned long *_auxv __attribute__((weak)); + /* startup code */ -__asm__ (".section .text\n" - ".weak _start\n" - "_start:\n" -#if defined(__THUMBEB__) || defined(__THUMBEL__) - /* We enter here in 32-bit mode but if some previous functions were in - * 16-bit mode, the assembler cannot know, so we need to tell it we're in - * 32-bit now, then switch to 16-bit (is there a better way to do it than - * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that - * it generates correct instructions. Note that we do not support thumb1. - */ - ".code 32\n" - "add r0, pc, #1\n" - "bx r0\n" - ".code 16\n" -#endif - "pop {%r0}\n" // argc was in the stack - "mov %r1, %sp\n" // argv = sp - "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ... - "add %r2, %r2, $4\n" // ... + 4 - "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the - "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc) - "bl main\n" // main() returns the status code, we'll exit with it. - "movs r7, $1\n" // NR_exit == 1 - "svc $0x00\n" - ""); +void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) +{ + __asm__ volatile ( + "pop {%r0}\n" // argc was in the stack + "mov %r1, %sp\n" // argv = sp + + "add %r2, %r0, $1\n" // envp = (argc + 1) ... + "lsl %r2, %r2, $2\n" // * 4 ... + "add %r2, %r2, %r1\n" // + argv + "ldr %r3, 1f\n" // r3 = &environ (see below) + "str %r2, [r3]\n" // store envp into environ + + "mov r4, r2\n" // search for auxv (follows NULL after last env) + "0:\n" + "mov r5, r4\n" // r5 = r4 + "add r4, r4, #4\n" // r4 += 4 + "ldr r5,[r5]\n" // r5 = *r5 = *(r4-4) + "cmp r5, #0\n" // and stop at NULL after last env + "bne 0b\n" + "ldr %r3, 2f\n" // r3 = &_auxv (low bits) + "str r4, [r3]\n" // store r4 into _auxv + + "mov %r3, $8\n" // AAPCS : sp must be 8-byte aligned in the + "neg %r3, %r3\n" // callee, and bl doesn't push (lr=pc) + "and %r3, %r3, %r1\n" // so we do sp = r1(=sp) & r3(=-8); + "mov %sp, %r3\n" // + + "bl main\n" // main() returns the status code, we'll exit with it. + "movs r7, $1\n" // NR_exit == 1 + "svc $0x00\n" + ".align 2\n" // below are the pointers to a few variables + "1:\n" + ".word environ\n" + "2:\n" + ".word _auxv\n" + ); + __builtin_unreachable(); +} #endif // _NOLIBC_ARCH_ARM_H diff --git a/tools/include/nolibc/arch-i386.h b/tools/include/nolibc/arch-i386.h index d7e7212346e2..e8d0cf545bf1 100644 --- a/tools/include/nolibc/arch-i386.h +++ b/tools/include/nolibc/arch-i386.h @@ -7,18 +7,6 @@ #ifndef _NOLIBC_ARCH_I386_H #define _NOLIBC_ARCH_I386_H -/* O_* macros for fcntl/open are architecture-specific */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x10000 - /* The struct returned by the stat() syscall, 32-bit only, the syscall returns * exactly 56 bytes (stops before the unused array). */ @@ -190,6 +178,9 @@ struct sys_stat_struct { _eax; \ }) +char **environ __attribute__((weak)); +const unsigned long *_auxv __attribute__((weak)); + /* startup code */ /* * i386 System V ABI mandates: @@ -197,23 +188,32 @@ struct sys_stat_struct { * 2) The deepest stack frame should be set to zero * */ -__asm__ (".section .text\n" - ".weak _start\n" - "_start:\n" - "pop %eax\n" // argc (first arg, %eax) - "mov %esp, %ebx\n" // argv[] (second arg, %ebx) - "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) - "xor %ebp, %ebp\n" // zero the stack frame - "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned before - "sub $4, %esp\n" // the call instruction (args are aligned) - "push %ecx\n" // push all registers on the stack so that we - "push %ebx\n" // support both regparm and plain stack modes - "push %eax\n" - "call main\n" // main() returns the status code in %eax - "mov %eax, %ebx\n" // retrieve exit code (32-bit int) - "movl $1, %eax\n" // NR_exit == 1 - "int $0x80\n" // exit now - "hlt\n" // ensure it does not - ""); +void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) +{ + __asm__ volatile ( + "pop %eax\n" // argc (first arg, %eax) + "mov %esp, %ebx\n" // argv[] (second arg, %ebx) + "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx) + "mov %ecx, environ\n" // save environ + "xor %ebp, %ebp\n" // zero the stack frame + "mov %ecx, %edx\n" // search for auxv (follows NULL after last env) + "0:\n" + "add $4, %edx\n" // search for auxv using edx, it follows the + "cmp -4(%edx), %ebp\n" // ... NULL after last env (ebp is zero here) + "jnz 0b\n" + "mov %edx, _auxv\n" // save it into _auxv + "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned before + "sub $4, %esp\n" // the call instruction (args are aligned) + "push %ecx\n" // push all registers on the stack so that we + "push %ebx\n" // support both regparm and plain stack modes + "push %eax\n" + "call main\n" // main() returns the status code in %eax + "mov %eax, %ebx\n" // retrieve exit code (32-bit int) + "movl $1, %eax\n" // NR_exit == 1 + "int $0x80\n" // exit now + "hlt\n" // ensure it does not + ); + __builtin_unreachable(); +} #endif // _NOLIBC_ARCH_I386_H diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h index 7380093ba9e7..bf83432d23ed 100644 --- a/tools/include/nolibc/arch-mips.h +++ b/tools/include/nolibc/arch-mips.h @@ -7,18 +7,6 @@ #ifndef _NOLIBC_ARCH_MIPS_H #define _NOLIBC_ARCH_MIPS_H -/* O_* macros for fcntl/open are architecture-specific */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_APPEND 0x0008 -#define O_NONBLOCK 0x0080 -#define O_CREAT 0x0100 -#define O_TRUNC 0x0200 -#define O_EXCL 0x0400 -#define O_NOCTTY 0x0800 -#define O_DIRECTORY 0x10000 - /* The struct returned by the stat() syscall. 88 bytes are returned by the * syscall. */ @@ -188,30 +176,49 @@ struct sys_stat_struct { _arg4 ? -_num : _num; \ }) +char **environ __attribute__((weak)); +const unsigned long *_auxv __attribute__((weak)); + /* startup code, note that it's called __start on MIPS */ -__asm__ (".section .text\n" - ".weak __start\n" - ".set nomips16\n" - ".set push\n" - ".set noreorder\n" - ".option pic0\n" - ".ent __start\n" - "__start:\n" - "lw $a0,($sp)\n" // argc was in the stack - "addiu $a1, $sp, 4\n" // argv = sp + 4 - "sll $a2, $a0, 2\n" // a2 = argc * 4 - "add $a2, $a2, $a1\n" // envp = argv + 4*argc ... - "addiu $a2, $a2, 4\n" // ... + 4 - "li $t0, -8\n" - "and $sp, $sp, $t0\n" // sp must be 8-byte aligned - "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there! - "jal main\n" // main() returns the status code, we'll exit with it. - "nop\n" // delayed slot - "move $a0, $v0\n" // retrieve 32-bit exit code from v0 - "li $v0, 4001\n" // NR_exit == 4001 - "syscall\n" - ".end __start\n" - ".set pop\n" - ""); +void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) __start(void) +{ + __asm__ volatile ( + //".set nomips16\n" + ".set push\n" + ".set noreorder\n" + ".option pic0\n" + //".ent __start\n" + //"__start:\n" + "lw $a0,($sp)\n" // argc was in the stack + "addiu $a1, $sp, 4\n" // argv = sp + 4 + "sll $a2, $a0, 2\n" // a2 = argc * 4 + "add $a2, $a2, $a1\n" // envp = argv + 4*argc ... + "addiu $a2, $a2, 4\n" // ... + 4 + "lui $a3, %hi(environ)\n" // load environ into a3 (hi) + "addiu $a3, %lo(environ)\n" // load environ into a3 (lo) + "sw $a2,($a3)\n" // store envp(a2) into environ + + "move $t0, $a2\n" // iterate t0 over envp, look for NULL + "0:" // do { + "lw $a3, ($t0)\n" // a3=*(t0); + "bne $a3, $0, 0b\n" // } while (a3); + "addiu $t0, $t0, 4\n" // delayed slot: t0+=4; + "lui $a3, %hi(_auxv)\n" // load _auxv into a3 (hi) + "addiu $a3, %lo(_auxv)\n" // load _auxv into a3 (lo) + "sw $t0, ($a3)\n" // store t0 into _auxv + + "li $t0, -8\n" + "and $sp, $sp, $t0\n" // sp must be 8-byte aligned + "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there! + "jal main\n" // main() returns the status code, we'll exit with it. + "nop\n" // delayed slot + "move $a0, $v0\n" // retrieve 32-bit exit code from v0 + "li $v0, 4001\n" // NR_exit == 4001 + "syscall\n" + //".end __start\n" + ".set pop\n" + ); + __builtin_unreachable(); +} #endif // _NOLIBC_ARCH_MIPS_H diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-riscv.h index a3bdd9803f8c..e197fcb10ac0 100644 --- a/tools/include/nolibc/arch-riscv.h +++ b/tools/include/nolibc/arch-riscv.h @@ -7,18 +7,6 @@ #ifndef _NOLIBC_ARCH_RISCV_H #define _NOLIBC_ARCH_RISCV_H -/* O_* macros for fcntl/open are architecture-specific */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x10000 - struct sys_stat_struct { unsigned long st_dev; /* Device. */ unsigned long st_ino; /* File serial number. */ @@ -182,23 +170,39 @@ struct sys_stat_struct { _arg1; \ }) +char **environ __attribute__((weak)); +const unsigned long *_auxv __attribute__((weak)); + /* startup code */ -__asm__ (".section .text\n" - ".weak _start\n" - "_start:\n" - ".option push\n" - ".option norelax\n" - "lla gp, __global_pointer$\n" - ".option pop\n" - "lw a0, 0(sp)\n" // argc (a0) was in the stack - "add a1, sp, "SZREG"\n" // argv (a1) = sp - "slli a2, a0, "PTRLOG"\n" // envp (a2) = SZREG*argc ... - "add a2, a2, "SZREG"\n" // + SZREG (skip null) - "add a2,a2,a1\n" // + argv - "andi sp,a1,-16\n" // sp must be 16-byte aligned - "call main\n" // main() returns the status code, we'll exit with it. - "li a7, 93\n" // NR_exit == 93 - "ecall\n" - ""); +void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) +{ + __asm__ volatile ( + ".option push\n" + ".option norelax\n" + "lla gp, __global_pointer$\n" + ".option pop\n" + "lw a0, 0(sp)\n" // argc (a0) was in the stack + "add a1, sp, "SZREG"\n" // argv (a1) = sp + "slli a2, a0, "PTRLOG"\n" // envp (a2) = SZREG*argc ... + "add a2, a2, "SZREG"\n" // + SZREG (skip null) + "add a2,a2,a1\n" // + argv + + "add a3, a2, zero\n" // iterate a3 over envp to find auxv (after NULL) + "0:\n" // do { + "ld a4, 0(a3)\n" // a4 = *a3; + "add a3, a3, "SZREG"\n" // a3 += sizeof(void*); + "bne a4, zero, 0b\n" // } while (a4); + "lui a4, %hi(_auxv)\n" // a4 = &_auxv (high bits) + "sd a3, %lo(_auxv)(a4)\n" // store a3 into _auxv + + "lui a3, %hi(environ)\n" // a3 = &environ (high bits) + "sd a2,%lo(environ)(a3)\n" // store envp(a2) into environ + "andi sp,a1,-16\n" // sp must be 16-byte aligned + "call main\n" // main() returns the status code, we'll exit with it. + "li a7, 93\n" // NR_exit == 93 + "ecall\n" + ); + __builtin_unreachable(); +} #endif // _NOLIBC_ARCH_RISCV_H diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h new file mode 100644 index 000000000000..6b0e54ed543d --- /dev/null +++ b/tools/include/nolibc/arch-s390.h @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ +/* + * s390 specific definitions for NOLIBC + */ + +#ifndef _NOLIBC_ARCH_S390_H +#define _NOLIBC_ARCH_S390_H +#include <asm/unistd.h> + +/* The struct returned by the stat() syscall, equivalent to stat64(). The + * syscall returns 116 bytes and stops in the middle of __unused. + */ + +struct sys_stat_struct { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad1; + unsigned long st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long st_blksize; + long st_blocks; + unsigned long __unused[3]; +}; + +/* Syscalls for s390: + * - registers are 64-bit + * - syscall number is passed in r1 + * - arguments are in r2-r7 + * - the system call is performed by calling the svc instruction + * - syscall return value is in r2 + * - r1 and r2 are clobbered, others are preserved. + * + * Link s390 ABI: https://github.com/IBM/s390x-abi + * + */ + +#define my_syscall0(num) \ +({ \ + register long _num __asm__ ("1") = (num); \ + register long _rc __asm__ ("2"); \ + \ + __asm__ volatile ( \ + "svc 0\n" \ + : "=d"(_rc) \ + : "d"(_num) \ + : "memory", "cc" \ + ); \ + _rc; \ +}) + +#define my_syscall1(num, arg1) \ +({ \ + register long _num __asm__ ("1") = (num); \ + register long _arg1 __asm__ ("2") = (long)(arg1); \ + \ + __asm__ volatile ( \ + "svc 0\n" \ + : "+d"(_arg1) \ + : "d"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall2(num, arg1, arg2) \ +({ \ + register long _num __asm__ ("1") = (num); \ + register long _arg1 __asm__ ("2") = (long)(arg1); \ + register long _arg2 __asm__ ("3") = (long)(arg2); \ + \ + __asm__ volatile ( \ + "svc 0\n" \ + : "+d"(_arg1) \ + : "d"(_arg2), "d"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall3(num, arg1, arg2, arg3) \ +({ \ + register long _num __asm__ ("1") = (num); \ + register long _arg1 __asm__ ("2") = (long)(arg1); \ + register long _arg2 __asm__ ("3") = (long)(arg2); \ + register long _arg3 __asm__ ("4") = (long)(arg3); \ + \ + __asm__ volatile ( \ + "svc 0\n" \ + : "+d"(_arg1) \ + : "d"(_arg2), "d"(_arg3), "d"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall4(num, arg1, arg2, arg3, arg4) \ +({ \ + register long _num __asm__ ("1") = (num); \ + register long _arg1 __asm__ ("2") = (long)(arg1); \ + register long _arg2 __asm__ ("3") = (long)(arg2); \ + register long _arg3 __asm__ ("4") = (long)(arg3); \ + register long _arg4 __asm__ ("5") = (long)(arg4); \ + \ + __asm__ volatile ( \ + "svc 0\n" \ + : "+d"(_arg1) \ + : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ +({ \ + register long _num __asm__ ("1") = (num); \ + register long _arg1 __asm__ ("2") = (long)(arg1); \ + register long _arg2 __asm__ ("3") = (long)(arg2); \ + register long _arg3 __asm__ ("4") = (long)(arg3); \ + register long _arg4 __asm__ ("5") = (long)(arg4); \ + register long _arg5 __asm__ ("6") = (long)(arg5); \ + \ + __asm__ volatile ( \ + "svc 0\n" \ + : "+d"(_arg1) \ + : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \ + "d"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + register long _num __asm__ ("1") = (num); \ + register long _arg1 __asm__ ("2") = (long)(arg1); \ + register long _arg2 __asm__ ("3") = (long)(arg2); \ + register long _arg3 __asm__ ("4") = (long)(arg3); \ + register long _arg4 __asm__ ("5") = (long)(arg4); \ + register long _arg5 __asm__ ("6") = (long)(arg5); \ + register long _arg6 __asm__ ("7") = (long)(arg6); \ + \ + __asm__ volatile ( \ + "svc 0\n" \ + : "+d"(_arg1) \ + : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \ + "d"(_arg6), "d"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +char **environ __attribute__((weak)); +const unsigned long *_auxv __attribute__((weak)); + +/* startup code */ +void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) +{ + __asm__ volatile ( + "lg %r2,0(%r15)\n" /* argument count */ + "la %r3,8(%r15)\n" /* argument pointers */ + + "xgr %r0,%r0\n" /* r0 will be our NULL value */ + /* search for envp */ + "lgr %r4,%r3\n" /* start at argv */ + "0:\n" + "clg %r0,0(%r4)\n" /* entry zero? */ + "la %r4,8(%r4)\n" /* advance pointer */ + "jnz 0b\n" /* no -> test next pointer */ + /* yes -> r4 now contains start of envp */ + "larl %r1,environ\n" + "stg %r4,0(%r1)\n" + + /* search for auxv */ + "lgr %r5,%r4\n" /* start at envp */ + "1:\n" + "clg %r0,0(%r5)\n" /* entry zero? */ + "la %r5,8(%r5)\n" /* advance pointer */ + "jnz 1b\n" /* no -> test next pointer */ + "larl %r1,_auxv\n" /* yes -> store value in _auxv */ + "stg %r5,0(%r1)\n" + + "aghi %r15,-160\n" /* allocate new stackframe */ + "xc 0(8,%r15),0(%r15)\n" /* clear backchain */ + "brasl %r14,main\n" /* ret value of main is arg to exit */ + "lghi %r1,1\n" /* __NR_exit */ + "svc 0\n" + ); + __builtin_unreachable(); +} + +struct s390_mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +static __attribute__((unused)) +void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, + off_t offset) +{ + struct s390_mmap_arg_struct args = { + .addr = (unsigned long)addr, + .len = (unsigned long)length, + .prot = prot, + .flags = flags, + .fd = fd, + .offset = (unsigned long)offset + }; + + return (void *)my_syscall1(__NR_mmap, &args); +} +#define sys_mmap sys_mmap +#endif // _NOLIBC_ARCH_S390_H diff --git a/tools/include/nolibc/arch-x86_64.h b/tools/include/nolibc/arch-x86_64.h index 0e1e9eb8545d..17f6751208e7 100644 --- a/tools/include/nolibc/arch-x86_64.h +++ b/tools/include/nolibc/arch-x86_64.h @@ -7,18 +7,6 @@ #ifndef _NOLIBC_ARCH_X86_64_H #define _NOLIBC_ARCH_X86_64_H -/* O_* macros for fcntl/open are architecture-specific */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 -#define O_CREAT 0x40 -#define O_EXCL 0x80 -#define O_NOCTTY 0x100 -#define O_TRUNC 0x200 -#define O_APPEND 0x400 -#define O_NONBLOCK 0x800 -#define O_DIRECTORY 0x10000 - /* The struct returned by the stat() syscall, equivalent to stat64(). The * syscall returns 116 bytes and stops in the middle of __unused. */ @@ -190,6 +178,9 @@ struct sys_stat_struct { _ret; \ }) +char **environ __attribute__((weak)); +const unsigned long *_auxv __attribute__((weak)); + /* startup code */ /* * x86-64 System V ABI mandates: @@ -197,19 +188,28 @@ struct sys_stat_struct { * 2) The deepest stack frame should be zero (the %rbp). * */ -__asm__ (".section .text\n" - ".weak _start\n" - "_start:\n" - "pop %rdi\n" // argc (first arg, %rdi) - "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) - "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx) - "xor %ebp, %ebp\n" // zero the stack frame - "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned before call - "call main\n" // main() returns the status code, we'll exit with it. - "mov %eax, %edi\n" // retrieve exit code (32 bit) - "mov $60, %eax\n" // NR_exit == 60 - "syscall\n" // really exit - "hlt\n" // ensure it does not return - ""); +void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) +{ + __asm__ volatile ( + "pop %rdi\n" // argc (first arg, %rdi) + "mov %rsp, %rsi\n" // argv[] (second arg, %rsi) + "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx) + "mov %rdx, environ\n" // save environ + "xor %ebp, %ebp\n" // zero the stack frame + "mov %rdx, %rax\n" // search for auxv (follows NULL after last env) + "0:\n" + "add $8, %rax\n" // search for auxv using rax, it follows the + "cmp -8(%rax), %rbp\n" // ... NULL after last env (rbp is zero here) + "jnz 0b\n" + "mov %rax, _auxv\n" // save it into _auxv + "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned before call + "call main\n" // main() returns the status code, we'll exit with it. + "mov %eax, %edi\n" // retrieve exit code (32 bit) + "mov $60, %eax\n" // NR_exit == 60 + "syscall\n" // really exit + "hlt\n" // ensure it does not return + ); + __builtin_unreachable(); +} #endif // _NOLIBC_ARCH_X86_64_H diff --git a/tools/include/nolibc/arch.h b/tools/include/nolibc/arch.h index 4c6992321b0d..78b067a4fa47 100644 --- a/tools/include/nolibc/arch.h +++ b/tools/include/nolibc/arch.h @@ -27,6 +27,8 @@ #include "arch-mips.h" #elif defined(__riscv) #include "arch-riscv.h" +#elif defined(__s390x__) +#include "arch-s390.h" #endif #endif /* _NOLIBC_ARCH_H */ diff --git a/tools/include/nolibc/errno.h b/tools/include/nolibc/errno.h index 9dc4919c769b..a44486ff0477 100644 --- a/tools/include/nolibc/errno.h +++ b/tools/include/nolibc/errno.h @@ -9,11 +9,9 @@ #include <asm/errno.h> -/* this way it will be removed if unused */ -static int errno; - #ifndef NOLIBC_IGNORE_ERRNO #define SET_ERRNO(v) do { errno = (v); } while (0) +int errno __attribute__((weak)); #else #define SET_ERRNO(v) do { } while (0) #endif diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index a24000d1e822..894c955d027e 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -12,6 +12,7 @@ #include "types.h" #include "sys.h" #include "string.h" +#include <linux/auxvec.h> struct nolibc_heap { size_t len; @@ -109,6 +110,32 @@ char *getenv(const char *name) } static __attribute__((unused)) +unsigned long getauxval(unsigned long type) +{ + const unsigned long *auxv = _auxv; + unsigned long ret; + + if (!auxv) + return 0; + + while (1) { + if (!auxv[0] && !auxv[1]) { + ret = 0; + break; + } + + if (auxv[0] == type) { + ret = auxv[1]; + break; + } + + auxv += 2; + } + + return ret; +} + +static __attribute__((unused)) void *malloc(size_t len) { struct nolibc_heap *heap; diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index 78473d34e27c..b5f8cd35c03b 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -11,6 +11,7 @@ #include "std.h" /* system includes */ +#include <asm/fcntl.h> // for O_* #include <asm/unistd.h> #include <asm/signal.h> // for SIGCHLD #include <asm/ioctls.h> @@ -18,6 +19,7 @@ #include <linux/fs.h> #include <linux/loop.h> #include <linux/time.h> +#include <linux/auxvec.h> #include "arch.h" #include "errno.h" @@ -498,6 +500,26 @@ pid_t gettid(void) return sys_gettid(); } +static unsigned long getauxval(unsigned long key); + +/* + * long getpagesize(void); + */ + +static __attribute__((unused)) +long getpagesize(void) +{ + long ret; + + ret = getauxval(AT_PAGESZ); + if (!ret) { + SET_ERRNO(ENOENT); + return -1; + } + + return ret; +} + /* * int gettimeofday(struct timeval *tv, struct timezone *tz); @@ -686,6 +708,7 @@ int mknod(const char *path, mode_t mode, dev_t dev) #define MAP_FAILED ((void *)-1) #endif +#ifndef sys_mmap static __attribute__((unused)) void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) @@ -707,6 +730,7 @@ void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset); #endif } +#endif static __attribute__((unused)) void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 22f1e1d73fa8..8fe61d3e3cce 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -14,21 +14,25 @@ endif # kernel image names by architecture IMAGE_i386 = arch/x86/boot/bzImage +IMAGE_x86_64 = arch/x86/boot/bzImage IMAGE_x86 = arch/x86/boot/bzImage IMAGE_arm64 = arch/arm64/boot/Image IMAGE_arm = arch/arm/boot/zImage IMAGE_mips = vmlinuz IMAGE_riscv = arch/riscv/boot/Image +IMAGE_s390 = arch/s390/boot/bzImage IMAGE = $(IMAGE_$(ARCH)) IMAGE_NAME = $(notdir $(IMAGE)) # default kernel configurations that appear to be usable DEFCONFIG_i386 = defconfig +DEFCONFIG_x86_64 = defconfig DEFCONFIG_x86 = defconfig DEFCONFIG_arm64 = defconfig DEFCONFIG_arm = multi_v7_defconfig DEFCONFIG_mips = malta_defconfig DEFCONFIG_riscv = defconfig +DEFCONFIG_s390 = defconfig DEFCONFIG = $(DEFCONFIG_$(ARCH)) # optional tests to run (default = all) @@ -36,20 +40,24 @@ TEST = # QEMU_ARCH: arch names used by qemu QEMU_ARCH_i386 = i386 +QEMU_ARCH_x86_64 = x86_64 QEMU_ARCH_x86 = x86_64 QEMU_ARCH_arm64 = aarch64 QEMU_ARCH_arm = arm QEMU_ARCH_mips = mipsel # works with malta_defconfig QEMU_ARCH_riscv = riscv64 +QEMU_ARCH_s390 = s390x QEMU_ARCH = $(QEMU_ARCH_$(ARCH)) # QEMU_ARGS : some arch-specific args to pass to qemu QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" +QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" +QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS = $(QEMU_ARGS_$(ARCH)) # OUTPUT is only set when run from the main makefile, otherwise @@ -62,7 +70,8 @@ else Q=@ endif -CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables +CFLAGS_s390 = -m64 +CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables $(CFLAGS_$(ARCH)) LDFLAGS := -s help: @@ -71,6 +80,7 @@ help: @echo " help this help" @echo " sysroot create the nolibc sysroot here (uses \$$ARCH)" @echo " nolibc-test build the executable (uses \$$CC and \$$CROSS_COMPILE)" + @echo " run-user runs the executable under QEMU (uses \$$ARCH, \$$TEST)" @echo " initramfs prepare the initramfs with nolibc-test" @echo " defconfig create a fresh new default config (uses \$$ARCH)" @echo " kernel (re)build the kernel with the initramfs (uses \$$ARCH)" @@ -104,6 +114,11 @@ nolibc-test: nolibc-test.c sysroot/$(ARCH)/include $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ -nostdlib -static -Isysroot/$(ARCH)/include $< -lgcc +# qemu user-land test +run-user: nolibc-test + $(Q)qemu-$(QEMU_ARCH) ./nolibc-test > "$(CURDIR)/run.out" || : + $(Q)grep -w FAIL "$(CURDIR)/run.out" && echo "See all results in $(CURDIR)/run.out" || echo "$$(grep -c ^[0-9].*OK $(CURDIR)/run.out) test(s) passed." + initramfs: nolibc-test $(QUIET_MKDIR)mkdir -p initramfs $(call QUIET_INSTALL, initramfs/init) diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index f14f5076fb6d..c4a0c915139c 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -442,6 +442,35 @@ int test_getdents64(const char *dir) return ret; } +static int test_getpagesize(void) +{ + long x = getpagesize(); + int c; + + if (x < 0) + return x; + +#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) + /* + * x86 family is always 4K page. + */ + c = (x == 4096); +#elif defined(__aarch64__) + /* + * Linux aarch64 supports three values of page size: 4K, 16K, and 64K + * which are selected at kernel compilation time. + */ + c = (x == 4096 || x == (16 * 1024) || x == (64 * 1024)); +#else + /* + * Assuming other architectures must have at least 4K page. + */ + c = (x >= 4096); +#endif + + return !c; +} + /* Run syscall tests between IDs <min> and <max>. * Return 0 on success, non-zero on failure. */ @@ -502,6 +531,7 @@ int run_syscall(int min, int max) CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break; CASE_TEST(gettimeofday_bad2); EXPECT_SYSER(1, gettimeofday(NULL, (void *)1), -1, EFAULT); break; #endif + CASE_TEST(getpagesize); EXPECT_SYSZR(1, test_getpagesize()); break; CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break; CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break; diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh index 66d0414d8e4b..b52d5069563c 100644 --- a/tools/testing/selftests/rcutorture/bin/functions.sh +++ b/tools/testing/selftests/rcutorture/bin/functions.sh @@ -159,6 +159,9 @@ identify_boot_image () { qemu-system-aarch64) echo arch/arm64/boot/Image ;; + qemu-system-s390x) + echo arch/s390/boot/bzImage + ;; *) echo vmlinux ;; @@ -184,6 +187,9 @@ identify_qemu () { elif echo $u | grep -q aarch64 then echo qemu-system-aarch64 + elif echo $u | grep -q 'IBM S/390' + then + echo qemu-system-s390x elif uname -a | grep -q ppc64 then echo qemu-system-ppc64 diff --git a/tools/testing/selftests/rcutorture/bin/mkinitrd.sh b/tools/testing/selftests/rcutorture/bin/mkinitrd.sh index 70d62fd0d31d..71f0dfbb2a6d 100755 --- a/tools/testing/selftests/rcutorture/bin/mkinitrd.sh +++ b/tools/testing/selftests/rcutorture/bin/mkinitrd.sh @@ -64,7 +64,7 @@ ___EOF___ # build using nolibc on supported archs (smaller executable) and fall # back to regular glibc on other ones. if echo -e "#if __x86_64__||__i386__||__i486__||__i586__||__i686__" \ - "||__ARM_EABI__||__aarch64__\nyes\n#endif" \ + "||__ARM_EABI__||__aarch64__||__s390x__\nyes\n#endif" \ | ${CROSS_COMPILE}gcc -E -nostdlib -xc - \ | grep -q '^yes'; then # architecture supported by nolibc |