aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/include/linux/kernel.h2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh8
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/mkinitrd.sh136
-rw-r--r--tools/testing/selftests/rcutorture/bin/nolibc.h2197
-rw-r--r--tools/testing/selftests/rcutorture/doc/initrd.txt99
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h4
6 files changed, 2356 insertions, 90 deletions
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 6935ef94e77a..857d9e22826e 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -116,6 +116,6 @@ int scnprintf(char * buf, size_t size, const char * fmt, ...);
116#define round_down(x, y) ((x) & ~__round_mask(x, y)) 116#define round_down(x, y) ((x) & ~__round_mask(x, y))
117 117
118#define current_gfp_context(k) 0 118#define current_gfp_context(k) 0
119#define synchronize_sched() 119#define synchronize_rcu()
120 120
121#endif 121#endif
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 5a7a62d76a50..19864f1cb27a 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -194,6 +194,14 @@ do
194 shift 194 shift
195done 195done
196 196
197if test -z "$TORTURE_INITRD" || tools/testing/selftests/rcutorture/bin/mkinitrd.sh
198then
199 :
200else
201 echo No initrd and unable to create one, aborting test >&2
202 exit 1
203fi
204
197CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG 205CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG
198 206
199if test -z "$configs" 207if test -z "$configs"
diff --git a/tools/testing/selftests/rcutorture/bin/mkinitrd.sh b/tools/testing/selftests/rcutorture/bin/mkinitrd.sh
new file mode 100755
index 000000000000..da298394daa2
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/mkinitrd.sh
@@ -0,0 +1,136 @@
1#!/bin/bash
2#
3# Create an initrd directory if one does not already exist.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2013
20#
21# Author: Connor Shu <Connor.Shu@ibm.com>
22
23D=tools/testing/selftests/rcutorture
24
25# Prerequisite checks
26[ -z "$D" ] && echo >&2 "No argument supplied" && exit 1
27if [ ! -d "$D" ]; then
28 echo >&2 "$D does not exist: Malformed kernel source tree?"
29 exit 1
30fi
31if [ -s "$D/initrd/init" ]; then
32 echo "$D/initrd/init already exists, no need to create it"
33 exit 0
34fi
35
36T=${TMPDIR-/tmp}/mkinitrd.sh.$$
37trap 'rm -rf $T' 0 2
38mkdir $T
39
40cat > $T/init << '__EOF___'
41#!/bin/sh
42# Run in userspace a few milliseconds every second. This helps to
43# exercise the NO_HZ_FULL portions of RCU.
44while :
45do
46 q=
47 for i in \
48 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
49 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
50 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
51 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
52 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
53 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
54 do
55 q="$q $i"
56 done
57 sleep 1
58done
59__EOF___
60
61# Try using dracut to create initrd
62if command -v dracut >/dev/null 2>&1
63then
64 echo Creating $D/initrd using dracut.
65 # Filesystem creation
66 dracut --force --no-hostonly --no-hostonly-cmdline --module "base" $T/initramfs.img
67 cd $D
68 mkdir -p initrd
69 cd initrd
70 zcat $T/initramfs.img | cpio -id
71 cp $T/init init
72 chmod +x init
73 echo Done creating $D/initrd using dracut
74 exit 0
75fi
76
77# No dracut, so create a C-language initrd/init program and statically
78# link it. This results in a very small initrd, but might be a bit less
79# future-proof than dracut.
80echo "Could not find dracut, attempting C initrd"
81cd $D
82mkdir -p initrd
83cd initrd
84cat > init.c << '___EOF___'
85#ifndef NOLIBC
86#include <unistd.h>
87#include <sys/time.h>
88#endif
89
90volatile unsigned long delaycount;
91
92int main(int argc, int argv[])
93{
94 int i;
95 struct timeval tv;
96 struct timeval tvb;
97
98 for (;;) {
99 sleep(1);
100 /* Need some userspace time. */
101 if (gettimeofday(&tvb, NULL))
102 continue;
103 do {
104 for (i = 0; i < 1000 * 100; i++)
105 delaycount = i * i;
106 if (gettimeofday(&tv, NULL))
107 break;
108 tv.tv_sec -= tvb.tv_sec;
109 if (tv.tv_sec > 1)
110 break;
111 tv.tv_usec += tv.tv_sec * 1000 * 1000;
112 tv.tv_usec -= tvb.tv_usec;
113 } while (tv.tv_usec < 1000);
114 }
115 return 0;
116}
117___EOF___
118
119# build using nolibc on supported archs (smaller executable) and fall
120# back to regular glibc on other ones.
121if echo -e "#if __x86_64__||__i386__||__i486__||__i586__||__i686__" \
122 "||__ARM_EABI__||__aarch64__\nyes\n#endif" \
123 | ${CROSS_COMPILE}gcc -E -nostdlib -xc - \
124 | grep -q '^yes'; then
125 # architecture supported by nolibc
126 ${CROSS_COMPILE}gcc -fno-asynchronous-unwind-tables -fno-ident \
127 -nostdlib -include ../bin/nolibc.h -lgcc -s -static -Os \
128 -o init init.c
129else
130 ${CROSS_COMPILE}gcc -s -static -Os -o init init.c
131fi
132
133rm init.c
134echo "Done creating a statically linked C-language initrd"
135
136exit 0
diff --git a/tools/testing/selftests/rcutorture/bin/nolibc.h b/tools/testing/selftests/rcutorture/bin/nolibc.h
new file mode 100644
index 000000000000..f98f5b92d3eb
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/nolibc.h
@@ -0,0 +1,2197 @@
1/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2/* nolibc.h
3 * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu>
4 */
5
6/* some archs (at least aarch64) don't expose the regular syscalls anymore by
7 * default, either because they have an "_at" replacement, or because there are
8 * more modern alternatives. For now we'd rather still use them.
9 */
10#define __ARCH_WANT_SYSCALL_NO_AT
11#define __ARCH_WANT_SYSCALL_NO_FLAGS
12#define __ARCH_WANT_SYSCALL_DEPRECATED
13
14#include <asm/unistd.h>
15#include <asm/ioctls.h>
16#include <asm/errno.h>
17#include <linux/fs.h>
18#include <linux/loop.h>
19
20#define NOLIBC
21
22/* Build a static executable this way :
23 * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \
24 * -static -include nolibc.h -lgcc -o hello hello.c
25 *
26 * Useful calling convention table found here :
27 * http://man7.org/linux/man-pages/man2/syscall.2.html
28 *
29 * This doc is even better :
30 * https://w3challs.com/syscalls/
31 */
32
33
34/* this way it will be removed if unused */
35static int errno;
36
37#ifndef NOLIBC_IGNORE_ERRNO
38#define SET_ERRNO(v) do { errno = (v); } while (0)
39#else
40#define SET_ERRNO(v) do { } while (0)
41#endif
42
43/* errno codes all ensure that they will not conflict with a valid pointer
44 * because they all correspond to the highest addressable memry page.
45 */
46#define MAX_ERRNO 4095
47
48/* Declare a few quite common macros and types that usually are in stdlib.h,
49 * stdint.h, ctype.h, unistd.h and a few other common locations.
50 */
51
52#define NULL ((void *)0)
53
54/* stdint types */
55typedef unsigned char uint8_t;
56typedef signed char int8_t;
57typedef unsigned short uint16_t;
58typedef signed short int16_t;
59typedef unsigned int uint32_t;
60typedef signed int int32_t;
61typedef unsigned long long uint64_t;
62typedef signed long long int64_t;
63typedef unsigned long size_t;
64typedef signed long ssize_t;
65typedef unsigned long uintptr_t;
66typedef signed long intptr_t;
67typedef signed long ptrdiff_t;
68
69/* for stat() */
70typedef unsigned int dev_t;
71typedef unsigned long ino_t;
72typedef unsigned int mode_t;
73typedef signed int pid_t;
74typedef unsigned int uid_t;
75typedef unsigned int gid_t;
76typedef unsigned long nlink_t;
77typedef signed long off_t;
78typedef signed long blksize_t;
79typedef signed long blkcnt_t;
80typedef signed long time_t;
81
82/* for poll() */
83struct pollfd {
84 int fd;
85 short int events;
86 short int revents;
87};
88
89/* for select() */
90struct timeval {
91 long tv_sec;
92 long tv_usec;
93};
94
95/* for pselect() */
96struct timespec {
97 long tv_sec;
98 long tv_nsec;
99};
100
101/* for gettimeofday() */
102struct timezone {
103 int tz_minuteswest;
104 int tz_dsttime;
105};
106
107/* for getdents64() */
108struct linux_dirent64 {
109 uint64_t d_ino;
110 int64_t d_off;
111 unsigned short d_reclen;
112 unsigned char d_type;
113 char d_name[];
114};
115
116/* commonly an fd_set represents 256 FDs */
117#define FD_SETSIZE 256
118typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set;
119
120/* needed by wait4() */
121struct rusage {
122 struct timeval ru_utime;
123 struct timeval ru_stime;
124 long ru_maxrss;
125 long ru_ixrss;
126 long ru_idrss;
127 long ru_isrss;
128 long ru_minflt;
129 long ru_majflt;
130 long ru_nswap;
131 long ru_inblock;
132 long ru_oublock;
133 long ru_msgsnd;
134 long ru_msgrcv;
135 long ru_nsignals;
136 long ru_nvcsw;
137 long ru_nivcsw;
138};
139
140/* stat flags (WARNING, octal here) */
141#define S_IFDIR 0040000
142#define S_IFCHR 0020000
143#define S_IFBLK 0060000
144#define S_IFREG 0100000
145#define S_IFIFO 0010000
146#define S_IFLNK 0120000
147#define S_IFSOCK 0140000
148#define S_IFMT 0170000
149
150#define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR)
151#define S_ISCHR(mode) (((mode) & S_IFCHR) == S_IFCHR)
152#define S_ISBLK(mode) (((mode) & S_IFBLK) == S_IFBLK)
153#define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
154#define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
155#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
156#define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
157
158#define DT_UNKNOWN 0
159#define DT_FIFO 1
160#define DT_CHR 2
161#define DT_DIR 4
162#define DT_BLK 6
163#define DT_REG 8
164#define DT_LNK 10
165#define DT_SOCK 12
166
167/* all the *at functions */
168#ifndef AT_FDWCD
169#define AT_FDCWD -100
170#endif
171
172/* lseek */
173#define SEEK_SET 0
174#define SEEK_CUR 1
175#define SEEK_END 2
176
177/* reboot */
178#define LINUX_REBOOT_MAGIC1 0xfee1dead
179#define LINUX_REBOOT_MAGIC2 0x28121969
180#define LINUX_REBOOT_CMD_HALT 0xcdef0123
181#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc
182#define LINUX_REBOOT_CMD_RESTART 0x01234567
183#define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2
184
185
186/* The format of the struct as returned by the libc to the application, which
187 * significantly differs from the format returned by the stat() syscall flavours.
188 */
189struct stat {
190 dev_t st_dev; /* ID of device containing file */
191 ino_t st_ino; /* inode number */
192 mode_t st_mode; /* protection */
193 nlink_t st_nlink; /* number of hard links */
194 uid_t st_uid; /* user ID of owner */
195 gid_t st_gid; /* group ID of owner */
196 dev_t st_rdev; /* device ID (if special file) */
197 off_t st_size; /* total size, in bytes */
198 blksize_t st_blksize; /* blocksize for file system I/O */
199 blkcnt_t st_blocks; /* number of 512B blocks allocated */
200 time_t st_atime; /* time of last access */
201 time_t st_mtime; /* time of last modification */
202 time_t st_ctime; /* time of last status change */
203};
204
205#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
206#define WIFEXITED(status) (((status) & 0x7f) == 0)
207
208
209/* Below comes the architecture-specific code. For each architecture, we have
210 * the syscall declarations and the _start code definition. This is the only
211 * global part. On all architectures the kernel puts everything in the stack
212 * before jumping to _start just above us, without any return address (_start
213 * is not a function but an entry pint). So at the stack pointer we find argc.
214 * Then argv[] begins, and ends at the first NULL. Then we have envp which
215 * starts and ends with a NULL as well. So envp=argv+argc+1.
216 */
217
218#if defined(__x86_64__)
219/* Syscalls for x86_64 :
220 * - registers are 64-bit
221 * - syscall number is passed in rax
222 * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively
223 * - the system call is performed by calling the syscall instruction
224 * - syscall return comes in rax
225 * - rcx and r8..r11 may be clobbered, others are preserved.
226 * - the arguments are cast to long and assigned into the target registers
227 * which are then simply passed as registers to the asm code, so that we
228 * don't have to experience issues with register constraints.
229 * - the syscall number is always specified last in order to allow to force
230 * some registers before (gcc refuses a %-register at the last position).
231 */
232
233#define my_syscall0(num) \
234({ \
235 long _ret; \
236 register long _num asm("rax") = (num); \
237 \
238 asm volatile ( \
239 "syscall\n" \
240 : "=a" (_ret) \
241 : "0"(_num) \
242 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
243 ); \
244 _ret; \
245})
246
247#define my_syscall1(num, arg1) \
248({ \
249 long _ret; \
250 register long _num asm("rax") = (num); \
251 register long _arg1 asm("rdi") = (long)(arg1); \
252 \
253 asm volatile ( \
254 "syscall\n" \
255 : "=a" (_ret) \
256 : "r"(_arg1), \
257 "0"(_num) \
258 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
259 ); \
260 _ret; \
261})
262
263#define my_syscall2(num, arg1, arg2) \
264({ \
265 long _ret; \
266 register long _num asm("rax") = (num); \
267 register long _arg1 asm("rdi") = (long)(arg1); \
268 register long _arg2 asm("rsi") = (long)(arg2); \
269 \
270 asm volatile ( \
271 "syscall\n" \
272 : "=a" (_ret) \
273 : "r"(_arg1), "r"(_arg2), \
274 "0"(_num) \
275 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
276 ); \
277 _ret; \
278})
279
280#define my_syscall3(num, arg1, arg2, arg3) \
281({ \
282 long _ret; \
283 register long _num asm("rax") = (num); \
284 register long _arg1 asm("rdi") = (long)(arg1); \
285 register long _arg2 asm("rsi") = (long)(arg2); \
286 register long _arg3 asm("rdx") = (long)(arg3); \
287 \
288 asm volatile ( \
289 "syscall\n" \
290 : "=a" (_ret) \
291 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
292 "0"(_num) \
293 : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
294 ); \
295 _ret; \
296})
297
298#define my_syscall4(num, arg1, arg2, arg3, arg4) \
299({ \
300 long _ret; \
301 register long _num asm("rax") = (num); \
302 register long _arg1 asm("rdi") = (long)(arg1); \
303 register long _arg2 asm("rsi") = (long)(arg2); \
304 register long _arg3 asm("rdx") = (long)(arg3); \
305 register long _arg4 asm("r10") = (long)(arg4); \
306 \
307 asm volatile ( \
308 "syscall\n" \
309 : "=a" (_ret), "=r"(_arg4) \
310 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
311 "0"(_num) \
312 : "rcx", "r8", "r9", "r11", "memory", "cc" \
313 ); \
314 _ret; \
315})
316
317#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
318({ \
319 long _ret; \
320 register long _num asm("rax") = (num); \
321 register long _arg1 asm("rdi") = (long)(arg1); \
322 register long _arg2 asm("rsi") = (long)(arg2); \
323 register long _arg3 asm("rdx") = (long)(arg3); \
324 register long _arg4 asm("r10") = (long)(arg4); \
325 register long _arg5 asm("r8") = (long)(arg5); \
326 \
327 asm volatile ( \
328 "syscall\n" \
329 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \
330 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
331 "0"(_num) \
332 : "rcx", "r9", "r11", "memory", "cc" \
333 ); \
334 _ret; \
335})
336
337#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
338({ \
339 long _ret; \
340 register long _num asm("rax") = (num); \
341 register long _arg1 asm("rdi") = (long)(arg1); \
342 register long _arg2 asm("rsi") = (long)(arg2); \
343 register long _arg3 asm("rdx") = (long)(arg3); \
344 register long _arg4 asm("r10") = (long)(arg4); \
345 register long _arg5 asm("r8") = (long)(arg5); \
346 register long _arg6 asm("r9") = (long)(arg6); \
347 \
348 asm volatile ( \
349 "syscall\n" \
350 : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \
351 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
352 "r"(_arg6), "0"(_num) \
353 : "rcx", "r11", "memory", "cc" \
354 ); \
355 _ret; \
356})
357
358/* startup code */
359asm(".section .text\n"
360 ".global _start\n"
361 "_start:\n"
362 "pop %rdi\n" // argc (first arg, %rdi)
363 "mov %rsp, %rsi\n" // argv[] (second arg, %rsi)
364 "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
365 "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned when
366 "sub $8, %rsp\n" // entering the callee
367 "call main\n" // main() returns the status code, we'll exit with it.
368 "movzb %al, %rdi\n" // retrieve exit code from 8 lower bits
369 "mov $60, %rax\n" // NR_exit == 60
370 "syscall\n" // really exit
371 "hlt\n" // ensure it does not return
372 "");
373
374/* fcntl / open */
375#define O_RDONLY 0
376#define O_WRONLY 1
377#define O_RDWR 2
378#define O_CREAT 0x40
379#define O_EXCL 0x80
380#define O_NOCTTY 0x100
381#define O_TRUNC 0x200
382#define O_APPEND 0x400
383#define O_NONBLOCK 0x800
384#define O_DIRECTORY 0x10000
385
386/* The struct returned by the stat() syscall, equivalent to stat64(). The
387 * syscall returns 116 bytes and stops in the middle of __unused.
388 */
389struct sys_stat_struct {
390 unsigned long st_dev;
391 unsigned long st_ino;
392 unsigned long st_nlink;
393 unsigned int st_mode;
394 unsigned int st_uid;
395
396 unsigned int st_gid;
397 unsigned int __pad0;
398 unsigned long st_rdev;
399 long st_size;
400 long st_blksize;
401
402 long st_blocks;
403 unsigned long st_atime;
404 unsigned long st_atime_nsec;
405 unsigned long st_mtime;
406
407 unsigned long st_mtime_nsec;
408 unsigned long st_ctime;
409 unsigned long st_ctime_nsec;
410 long __unused[3];
411};
412
413#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
414/* Syscalls for i386 :
415 * - mostly similar to x86_64
416 * - registers are 32-bit
417 * - syscall number is passed in eax
418 * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
419 * - all registers are preserved (except eax of course)
420 * - the system call is performed by calling int $0x80
421 * - syscall return comes in eax
422 * - the arguments are cast to long and assigned into the target registers
423 * which are then simply passed as registers to the asm code, so that we
424 * don't have to experience issues with register constraints.
425 * - the syscall number is always specified last in order to allow to force
426 * some registers before (gcc refuses a %-register at the last position).
427 *
428 * Also, i386 supports the old_select syscall if newselect is not available
429 */
430#define __ARCH_WANT_SYS_OLD_SELECT
431
432#define my_syscall0(num) \
433({ \
434 long _ret; \
435 register long _num asm("eax") = (num); \
436 \
437 asm volatile ( \
438 "int $0x80\n" \
439 : "=a" (_ret) \
440 : "0"(_num) \
441 : "memory", "cc" \
442 ); \
443 _ret; \
444})
445
446#define my_syscall1(num, arg1) \
447({ \
448 long _ret; \
449 register long _num asm("eax") = (num); \
450 register long _arg1 asm("ebx") = (long)(arg1); \
451 \
452 asm volatile ( \
453 "int $0x80\n" \
454 : "=a" (_ret) \
455 : "r"(_arg1), \
456 "0"(_num) \
457 : "memory", "cc" \
458 ); \
459 _ret; \
460})
461
462#define my_syscall2(num, arg1, arg2) \
463({ \
464 long _ret; \
465 register long _num asm("eax") = (num); \
466 register long _arg1 asm("ebx") = (long)(arg1); \
467 register long _arg2 asm("ecx") = (long)(arg2); \
468 \
469 asm volatile ( \
470 "int $0x80\n" \
471 : "=a" (_ret) \
472 : "r"(_arg1), "r"(_arg2), \
473 "0"(_num) \
474 : "memory", "cc" \
475 ); \
476 _ret; \
477})
478
479#define my_syscall3(num, arg1, arg2, arg3) \
480({ \
481 long _ret; \
482 register long _num asm("eax") = (num); \
483 register long _arg1 asm("ebx") = (long)(arg1); \
484 register long _arg2 asm("ecx") = (long)(arg2); \
485 register long _arg3 asm("edx") = (long)(arg3); \
486 \
487 asm volatile ( \
488 "int $0x80\n" \
489 : "=a" (_ret) \
490 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
491 "0"(_num) \
492 : "memory", "cc" \
493 ); \
494 _ret; \
495})
496
497#define my_syscall4(num, arg1, arg2, arg3, arg4) \
498({ \
499 long _ret; \
500 register long _num asm("eax") = (num); \
501 register long _arg1 asm("ebx") = (long)(arg1); \
502 register long _arg2 asm("ecx") = (long)(arg2); \
503 register long _arg3 asm("edx") = (long)(arg3); \
504 register long _arg4 asm("esi") = (long)(arg4); \
505 \
506 asm volatile ( \
507 "int $0x80\n" \
508 : "=a" (_ret) \
509 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
510 "0"(_num) \
511 : "memory", "cc" \
512 ); \
513 _ret; \
514})
515
516#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
517({ \
518 long _ret; \
519 register long _num asm("eax") = (num); \
520 register long _arg1 asm("ebx") = (long)(arg1); \
521 register long _arg2 asm("ecx") = (long)(arg2); \
522 register long _arg3 asm("edx") = (long)(arg3); \
523 register long _arg4 asm("esi") = (long)(arg4); \
524 register long _arg5 asm("edi") = (long)(arg5); \
525 \
526 asm volatile ( \
527 "int $0x80\n" \
528 : "=a" (_ret) \
529 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
530 "0"(_num) \
531 : "memory", "cc" \
532 ); \
533 _ret; \
534})
535
536/* startup code */
537asm(".section .text\n"
538 ".global _start\n"
539 "_start:\n"
540 "pop %eax\n" // argc (first arg, %eax)
541 "mov %esp, %ebx\n" // argv[] (second arg, %ebx)
542 "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
543 "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned when
544 "push %ecx\n" // push all registers on the stack so that we
545 "push %ebx\n" // support both regparm and plain stack modes
546 "push %eax\n"
547 "call main\n" // main() returns the status code in %eax
548 "movzbl %al, %ebx\n" // retrieve exit code from lower 8 bits
549 "movl $1, %eax\n" // NR_exit == 1
550 "int $0x80\n" // exit now
551 "hlt\n" // ensure it does not
552 "");
553
554/* fcntl / open */
555#define O_RDONLY 0
556#define O_WRONLY 1
557#define O_RDWR 2
558#define O_CREAT 0x40
559#define O_EXCL 0x80
560#define O_NOCTTY 0x100
561#define O_TRUNC 0x200
562#define O_APPEND 0x400
563#define O_NONBLOCK 0x800
564#define O_DIRECTORY 0x10000
565
566/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
567 * exactly 56 bytes (stops before the unused array).
568 */
569struct sys_stat_struct {
570 unsigned long st_dev;
571 unsigned long st_ino;
572 unsigned short st_mode;
573 unsigned short st_nlink;
574 unsigned short st_uid;
575 unsigned short st_gid;
576
577 unsigned long st_rdev;
578 unsigned long st_size;
579 unsigned long st_blksize;
580 unsigned long st_blocks;
581
582 unsigned long st_atime;
583 unsigned long st_atime_nsec;
584 unsigned long st_mtime;
585 unsigned long st_mtime_nsec;
586
587 unsigned long st_ctime;
588 unsigned long st_ctime_nsec;
589 unsigned long __unused[2];
590};
591
592#elif defined(__ARM_EABI__)
593/* Syscalls for ARM in ARM or Thumb modes :
594 * - registers are 32-bit
595 * - stack is 8-byte aligned
596 * ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html)
597 * - syscall number is passed in r7
598 * - arguments are in r0, r1, r2, r3, r4, r5
599 * - the system call is performed by calling svc #0
600 * - syscall return comes in r0.
601 * - only lr is clobbered.
602 * - the arguments are cast to long and assigned into the target registers
603 * which are then simply passed as registers to the asm code, so that we
604 * don't have to experience issues with register constraints.
605 * - the syscall number is always specified last in order to allow to force
606 * some registers before (gcc refuses a %-register at the last position).
607 *
608 * Also, ARM supports the old_select syscall if newselect is not available
609 */
610#define __ARCH_WANT_SYS_OLD_SELECT
611
612#define my_syscall0(num) \
613({ \
614 register long _num asm("r7") = (num); \
615 register long _arg1 asm("r0"); \
616 \
617 asm volatile ( \
618 "svc #0\n" \
619 : "=r"(_arg1) \
620 : "r"(_num) \
621 : "memory", "cc", "lr" \
622 ); \
623 _arg1; \
624})
625
626#define my_syscall1(num, arg1) \
627({ \
628 register long _num asm("r7") = (num); \
629 register long _arg1 asm("r0") = (long)(arg1); \
630 \
631 asm volatile ( \
632 "svc #0\n" \
633 : "=r"(_arg1) \
634 : "r"(_arg1), \
635 "r"(_num) \
636 : "memory", "cc", "lr" \
637 ); \
638 _arg1; \
639})
640
641#define my_syscall2(num, arg1, arg2) \
642({ \
643 register long _num asm("r7") = (num); \
644 register long _arg1 asm("r0") = (long)(arg1); \
645 register long _arg2 asm("r1") = (long)(arg2); \
646 \
647 asm volatile ( \
648 "svc #0\n" \
649 : "=r"(_arg1) \
650 : "r"(_arg1), "r"(_arg2), \
651 "r"(_num) \
652 : "memory", "cc", "lr" \
653 ); \
654 _arg1; \
655})
656
657#define my_syscall3(num, arg1, arg2, arg3) \
658({ \
659 register long _num asm("r7") = (num); \
660 register long _arg1 asm("r0") = (long)(arg1); \
661 register long _arg2 asm("r1") = (long)(arg2); \
662 register long _arg3 asm("r2") = (long)(arg3); \
663 \
664 asm volatile ( \
665 "svc #0\n" \
666 : "=r"(_arg1) \
667 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
668 "r"(_num) \
669 : "memory", "cc", "lr" \
670 ); \
671 _arg1; \
672})
673
674#define my_syscall4(num, arg1, arg2, arg3, arg4) \
675({ \
676 register long _num asm("r7") = (num); \
677 register long _arg1 asm("r0") = (long)(arg1); \
678 register long _arg2 asm("r1") = (long)(arg2); \
679 register long _arg3 asm("r2") = (long)(arg3); \
680 register long _arg4 asm("r3") = (long)(arg4); \
681 \
682 asm volatile ( \
683 "svc #0\n" \
684 : "=r"(_arg1) \
685 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
686 "r"(_num) \
687 : "memory", "cc", "lr" \
688 ); \
689 _arg1; \
690})
691
692#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
693({ \
694 register long _num asm("r7") = (num); \
695 register long _arg1 asm("r0") = (long)(arg1); \
696 register long _arg2 asm("r1") = (long)(arg2); \
697 register long _arg3 asm("r2") = (long)(arg3); \
698 register long _arg4 asm("r3") = (long)(arg4); \
699 register long _arg5 asm("r4") = (long)(arg5); \
700 \
701 asm volatile ( \
702 "svc #0\n" \
703 : "=r" (_arg1) \
704 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
705 "r"(_num) \
706 : "memory", "cc", "lr" \
707 ); \
708 _arg1; \
709})
710
711/* startup code */
712asm(".section .text\n"
713 ".global _start\n"
714 "_start:\n"
715#if defined(__THUMBEB__) || defined(__THUMBEL__)
716 /* We enter here in 32-bit mode but if some previous functions were in
717 * 16-bit mode, the assembler cannot know, so we need to tell it we're in
718 * 32-bit now, then switch to 16-bit (is there a better way to do it than
719 * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that
720 * it generates correct instructions. Note that we do not support thumb1.
721 */
722 ".code 32\n"
723 "add r0, pc, #1\n"
724 "bx r0\n"
725 ".code 16\n"
726#endif
727 "pop {%r0}\n" // argc was in the stack
728 "mov %r1, %sp\n" // argv = sp
729 "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ...
730 "add %r2, %r2, $4\n" // ... + 4
731 "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the
732 "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc)
733 "bl main\n" // main() returns the status code, we'll exit with it.
734 "and %r0, %r0, $0xff\n" // limit exit code to 8 bits
735 "movs r7, $1\n" // NR_exit == 1
736 "svc $0x00\n"
737 "");
738
739/* fcntl / open */
740#define O_RDONLY 0
741#define O_WRONLY 1
742#define O_RDWR 2
743#define O_CREAT 0x40
744#define O_EXCL 0x80
745#define O_NOCTTY 0x100
746#define O_TRUNC 0x200
747#define O_APPEND 0x400
748#define O_NONBLOCK 0x800
749#define O_DIRECTORY 0x4000
750
751/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
752 * exactly 56 bytes (stops before the unused array). In big endian, the format
753 * differs as devices are returned as short only.
754 */
755struct sys_stat_struct {
756#if defined(__ARMEB__)
757 unsigned short st_dev;
758 unsigned short __pad1;
759#else
760 unsigned long st_dev;
761#endif
762 unsigned long st_ino;
763 unsigned short st_mode;
764 unsigned short st_nlink;
765 unsigned short st_uid;
766 unsigned short st_gid;
767#if defined(__ARMEB__)
768 unsigned short st_rdev;
769 unsigned short __pad2;
770#else
771 unsigned long st_rdev;
772#endif
773 unsigned long st_size;
774 unsigned long st_blksize;
775 unsigned long st_blocks;
776 unsigned long st_atime;
777 unsigned long st_atime_nsec;
778 unsigned long st_mtime;
779 unsigned long st_mtime_nsec;
780 unsigned long st_ctime;
781 unsigned long st_ctime_nsec;
782 unsigned long __unused[2];
783};
784
785#elif defined(__aarch64__)
786/* Syscalls for AARCH64 :
787 * - registers are 64-bit
788 * - stack is 16-byte aligned
789 * - syscall number is passed in x8
790 * - arguments are in x0, x1, x2, x3, x4, x5
791 * - the system call is performed by calling svc 0
792 * - syscall return comes in x0.
793 * - the arguments are cast to long and assigned into the target registers
794 * which are then simply passed as registers to the asm code, so that we
795 * don't have to experience issues with register constraints.
796 *
797 * On aarch64, select() is not implemented so we have to use pselect6().
798 */
799#define __ARCH_WANT_SYS_PSELECT6
800
801#define my_syscall0(num) \
802({ \
803 register long _num asm("x8") = (num); \
804 register long _arg1 asm("x0"); \
805 \
806 asm volatile ( \
807 "svc #0\n" \
808 : "=r"(_arg1) \
809 : "r"(_num) \
810 : "memory", "cc" \
811 ); \
812 _arg1; \
813})
814
815#define my_syscall1(num, arg1) \
816({ \
817 register long _num asm("x8") = (num); \
818 register long _arg1 asm("x0") = (long)(arg1); \
819 \
820 asm volatile ( \
821 "svc #0\n" \
822 : "=r"(_arg1) \
823 : "r"(_arg1), \
824 "r"(_num) \
825 : "memory", "cc" \
826 ); \
827 _arg1; \
828})
829
830#define my_syscall2(num, arg1, arg2) \
831({ \
832 register long _num asm("x8") = (num); \
833 register long _arg1 asm("x0") = (long)(arg1); \
834 register long _arg2 asm("x1") = (long)(arg2); \
835 \
836 asm volatile ( \
837 "svc #0\n" \
838 : "=r"(_arg1) \
839 : "r"(_arg1), "r"(_arg2), \
840 "r"(_num) \
841 : "memory", "cc" \
842 ); \
843 _arg1; \
844})
845
846#define my_syscall3(num, arg1, arg2, arg3) \
847({ \
848 register long _num asm("x8") = (num); \
849 register long _arg1 asm("x0") = (long)(arg1); \
850 register long _arg2 asm("x1") = (long)(arg2); \
851 register long _arg3 asm("x2") = (long)(arg3); \
852 \
853 asm volatile ( \
854 "svc #0\n" \
855 : "=r"(_arg1) \
856 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
857 "r"(_num) \
858 : "memory", "cc" \
859 ); \
860 _arg1; \
861})
862
863#define my_syscall4(num, arg1, arg2, arg3, arg4) \
864({ \
865 register long _num asm("x8") = (num); \
866 register long _arg1 asm("x0") = (long)(arg1); \
867 register long _arg2 asm("x1") = (long)(arg2); \
868 register long _arg3 asm("x2") = (long)(arg3); \
869 register long _arg4 asm("x3") = (long)(arg4); \
870 \
871 asm volatile ( \
872 "svc #0\n" \
873 : "=r"(_arg1) \
874 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
875 "r"(_num) \
876 : "memory", "cc" \
877 ); \
878 _arg1; \
879})
880
881#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
882({ \
883 register long _num asm("x8") = (num); \
884 register long _arg1 asm("x0") = (long)(arg1); \
885 register long _arg2 asm("x1") = (long)(arg2); \
886 register long _arg3 asm("x2") = (long)(arg3); \
887 register long _arg4 asm("x3") = (long)(arg4); \
888 register long _arg5 asm("x4") = (long)(arg5); \
889 \
890 asm volatile ( \
891 "svc #0\n" \
892 : "=r" (_arg1) \
893 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
894 "r"(_num) \
895 : "memory", "cc" \
896 ); \
897 _arg1; \
898})
899
900#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
901({ \
902 register long _num asm("x8") = (num); \
903 register long _arg1 asm("x0") = (long)(arg1); \
904 register long _arg2 asm("x1") = (long)(arg2); \
905 register long _arg3 asm("x2") = (long)(arg3); \
906 register long _arg4 asm("x3") = (long)(arg4); \
907 register long _arg5 asm("x4") = (long)(arg5); \
908 register long _arg6 asm("x5") = (long)(arg6); \
909 \
910 asm volatile ( \
911 "svc #0\n" \
912 : "=r" (_arg1) \
913 : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
914 "r"(_arg6), "r"(_num) \
915 : "memory", "cc" \
916 ); \
917 _arg1; \
918})
919
920/* startup code */
921asm(".section .text\n"
922 ".global _start\n"
923 "_start:\n"
924 "ldr x0, [sp]\n" // argc (x0) was in the stack
925 "add x1, sp, 8\n" // argv (x1) = sp
926 "lsl x2, x0, 3\n" // envp (x2) = 8*argc ...
927 "add x2, x2, 8\n" // + 8 (skip null)
928 "add x2, x2, x1\n" // + argv
929 "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee
930 "bl main\n" // main() returns the status code, we'll exit with it.
931 "and x0, x0, 0xff\n" // limit exit code to 8 bits
932 "mov x8, 93\n" // NR_exit == 93
933 "svc #0\n"
934 "");
935
936/* fcntl / open */
937#define O_RDONLY 0
938#define O_WRONLY 1
939#define O_RDWR 2
940#define O_CREAT 0x40
941#define O_EXCL 0x80
942#define O_NOCTTY 0x100
943#define O_TRUNC 0x200
944#define O_APPEND 0x400
945#define O_NONBLOCK 0x800
946#define O_DIRECTORY 0x4000
947
948/* The struct returned by the newfstatat() syscall. Differs slightly from the
949 * x86_64's stat one by field ordering, so be careful.
950 */
951struct sys_stat_struct {
952 unsigned long st_dev;
953 unsigned long st_ino;
954 unsigned int st_mode;
955 unsigned int st_nlink;
956 unsigned int st_uid;
957 unsigned int st_gid;
958
959 unsigned long st_rdev;
960 unsigned long __pad1;
961 long st_size;
962 int st_blksize;
963 int __pad2;
964
965 long st_blocks;
966 long st_atime;
967 unsigned long st_atime_nsec;
968 long st_mtime;
969
970 unsigned long st_mtime_nsec;
971 long st_ctime;
972 unsigned long st_ctime_nsec;
973 unsigned int __unused[2];
974};
975
976#elif defined(__mips__) && defined(_ABIO32)
977/* Syscalls for MIPS ABI O32 :
978 * - WARNING! there's always a delayed slot!
979 * - WARNING again, the syntax is different, registers take a '$' and numbers
980 * do not.
981 * - registers are 32-bit
982 * - stack is 8-byte aligned
983 * - syscall number is passed in v0 (starts at 0xfa0).
984 * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
985 * leave some room in the stack for the callee to save a0..a3 if needed.
986 * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
987 * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
988 * scall32-o32.S in the kernel sources.
989 * - the system call is performed by calling "syscall"
990 * - syscall return comes in v0, and register a3 needs to be checked to know
991 * if an error occured, in which case errno is in v0.
992 * - the arguments are cast to long and assigned into the target registers
993 * which are then simply passed as registers to the asm code, so that we
994 * don't have to experience issues with register constraints.
995 */
996
997#define my_syscall0(num) \
998({ \
999 register long _num asm("v0") = (num); \
1000 register long _arg4 asm("a3"); \
1001 \
1002 asm volatile ( \
1003 "addiu $sp, $sp, -32\n" \
1004 "syscall\n" \
1005 "addiu $sp, $sp, 32\n" \
1006 : "=r"(_num), "=r"(_arg4) \
1007 : "r"(_num) \
1008 : "memory", "cc", "at", "v1", "hi", "lo", \
1009 \
1010 ); \
1011 _arg4 ? -_num : _num; \
1012})
1013
1014#define my_syscall1(num, arg1) \
1015({ \
1016 register long _num asm("v0") = (num); \
1017 register long _arg1 asm("a0") = (long)(arg1); \
1018 register long _arg4 asm("a3"); \
1019 \
1020 asm volatile ( \
1021 "addiu $sp, $sp, -32\n" \
1022 "syscall\n" \
1023 "addiu $sp, $sp, 32\n" \
1024 : "=r"(_num), "=r"(_arg4) \
1025 : "0"(_num), \
1026 "r"(_arg1) \
1027 : "memory", "cc", "at", "v1", "hi", "lo", \
1028 \
1029 ); \
1030 _arg4 ? -_num : _num; \
1031})
1032
1033#define my_syscall2(num, arg1, arg2) \
1034({ \
1035 register long _num asm("v0") = (num); \
1036 register long _arg1 asm("a0") = (long)(arg1); \
1037 register long _arg2 asm("a1") = (long)(arg2); \
1038 register long _arg4 asm("a3"); \
1039 \
1040 asm volatile ( \
1041 "addiu $sp, $sp, -32\n" \
1042 "syscall\n" \
1043 "addiu $sp, $sp, 32\n" \
1044 : "=r"(_num), "=r"(_arg4) \
1045 : "0"(_num), \
1046 "r"(_arg1), "r"(_arg2) \
1047 : "memory", "cc", "at", "v1", "hi", "lo", \
1048 \
1049 ); \
1050 _arg4 ? -_num : _num; \
1051})
1052
1053#define my_syscall3(num, arg1, arg2, arg3) \
1054({ \
1055 register long _num asm("v0") = (num); \
1056 register long _arg1 asm("a0") = (long)(arg1); \
1057 register long _arg2 asm("a1") = (long)(arg2); \
1058 register long _arg3 asm("a2") = (long)(arg3); \
1059 register long _arg4 asm("a3"); \
1060 \
1061 asm volatile ( \
1062 "addiu $sp, $sp, -32\n" \
1063 "syscall\n" \
1064 "addiu $sp, $sp, 32\n" \
1065 : "=r"(_num), "=r"(_arg4) \
1066 : "0"(_num), \
1067 "r"(_arg1), "r"(_arg2), "r"(_arg3) \
1068 : "memory", "cc", "at", "v1", "hi", "lo", \
1069 \
1070 ); \
1071 _arg4 ? -_num : _num; \
1072})
1073
1074#define my_syscall4(num, arg1, arg2, arg3, arg4) \
1075({ \
1076 register long _num asm("v0") = (num); \
1077 register long _arg1 asm("a0") = (long)(arg1); \
1078 register long _arg2 asm("a1") = (long)(arg2); \
1079 register long _arg3 asm("a2") = (long)(arg3); \
1080 register long _arg4 asm("a3") = (long)(arg4); \
1081 \
1082 asm volatile ( \
1083 "addiu $sp, $sp, -32\n" \
1084 "syscall\n" \
1085 "addiu $sp, $sp, 32\n" \
1086 : "=r" (_num), "=r"(_arg4) \
1087 : "0"(_num), \
1088 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
1089 : "memory", "cc", "at", "v1", "hi", "lo", \
1090 \
1091 ); \
1092 _arg4 ? -_num : _num; \
1093})
1094
1095#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
1096({ \
1097 register long _num asm("v0") = (num); \
1098 register long _arg1 asm("a0") = (long)(arg1); \
1099 register long _arg2 asm("a1") = (long)(arg2); \
1100 register long _arg3 asm("a2") = (long)(arg3); \
1101 register long _arg4 asm("a3") = (long)(arg4); \
1102 register long _arg5 = (long)(arg5); \
1103 \
1104 asm volatile ( \
1105 "addiu $sp, $sp, -32\n" \
1106 "sw %7, 16($sp)\n" \
1107 "syscall\n " \
1108 "addiu $sp, $sp, 32\n" \
1109 : "=r" (_num), "=r"(_arg4) \
1110 : "0"(_num), \
1111 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
1112 : "memory", "cc", "at", "v1", "hi", "lo", \
1113 \
1114 ); \
1115 _arg4 ? -_num : _num; \
1116})
1117
1118/* startup code, note that it's called __start on MIPS */
1119asm(".section .text\n"
1120 ".set nomips16\n"
1121 ".global __start\n"
1122 ".set noreorder\n"
1123 ".option pic0\n"
1124 ".ent __start\n"
1125 "__start:\n"
1126 "lw $a0,($sp)\n" // argc was in the stack
1127 "addiu $a1, $sp, 4\n" // argv = sp + 4
1128 "sll $a2, $a0, 2\n" // a2 = argc * 4
1129 "add $a2, $a2, $a1\n" // envp = argv + 4*argc ...
1130 "addiu $a2, $a2, 4\n" // ... + 4
1131 "li $t0, -8\n"
1132 "and $sp, $sp, $t0\n" // sp must be 8-byte aligned
1133 "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there!
1134 "jal main\n" // main() returns the status code, we'll exit with it.
1135 "nop\n" // delayed slot
1136 "and $a0, $v0, 0xff\n" // limit exit code to 8 bits
1137 "li $v0, 4001\n" // NR_exit == 4001
1138 "syscall\n"
1139 ".end __start\n"
1140 "");
1141
1142/* fcntl / open */
1143#define O_RDONLY 0
1144#define O_WRONLY 1
1145#define O_RDWR 2
1146#define O_APPEND 0x0008
1147#define O_NONBLOCK 0x0080
1148#define O_CREAT 0x0100
1149#define O_TRUNC 0x0200
1150#define O_EXCL 0x0400
1151#define O_NOCTTY 0x0800
1152#define O_DIRECTORY 0x10000
1153
1154/* The struct returned by the stat() syscall. 88 bytes are returned by the
1155 * syscall.
1156 */
1157struct sys_stat_struct {
1158 unsigned int st_dev;
1159 long st_pad1[3];
1160 unsigned long st_ino;
1161 unsigned int st_mode;
1162 unsigned int st_nlink;
1163 unsigned int st_uid;
1164 unsigned int st_gid;
1165 unsigned int st_rdev;
1166 long st_pad2[2];
1167 long st_size;
1168 long st_pad3;
1169 long st_atime;
1170 long st_atime_nsec;
1171 long st_mtime;
1172 long st_mtime_nsec;
1173 long st_ctime;
1174 long st_ctime_nsec;
1175 long st_blksize;
1176 long st_blocks;
1177 long st_pad4[14];
1178};
1179
1180#endif
1181
1182
1183/* Below are the C functions used to declare the raw syscalls. They try to be
1184 * architecture-agnostic, and return either a success or -errno. Declaring them
1185 * static will lead to them being inlined in most cases, but it's still possible
1186 * to reference them by a pointer if needed.
1187 */
1188static __attribute__((unused))
1189void *sys_brk(void *addr)
1190{
1191 return (void *)my_syscall1(__NR_brk, addr);
1192}
1193
1194static __attribute__((noreturn,unused))
1195void sys_exit(int status)
1196{
1197 my_syscall1(__NR_exit, status & 255);
1198 while(1); // shut the "noreturn" warnings.
1199}
1200
1201static __attribute__((unused))
1202int sys_chdir(const char *path)
1203{
1204 return my_syscall1(__NR_chdir, path);
1205}
1206
1207static __attribute__((unused))
1208int sys_chmod(const char *path, mode_t mode)
1209{
1210#ifdef __NR_fchmodat
1211 return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0);
1212#else
1213 return my_syscall2(__NR_chmod, path, mode);
1214#endif
1215}
1216
1217static __attribute__((unused))
1218int sys_chown(const char *path, uid_t owner, gid_t group)
1219{
1220#ifdef __NR_fchownat
1221 return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0);
1222#else
1223 return my_syscall3(__NR_chown, path, owner, group);
1224#endif
1225}
1226
1227static __attribute__((unused))
1228int sys_chroot(const char *path)
1229{
1230 return my_syscall1(__NR_chroot, path);
1231}
1232
1233static __attribute__((unused))
1234int sys_close(int fd)
1235{
1236 return my_syscall1(__NR_close, fd);
1237}
1238
1239static __attribute__((unused))
1240int sys_dup(int fd)
1241{
1242 return my_syscall1(__NR_dup, fd);
1243}
1244
1245static __attribute__((unused))
1246int sys_dup2(int old, int new)
1247{
1248 return my_syscall2(__NR_dup2, old, new);
1249}
1250
1251static __attribute__((unused))
1252int sys_execve(const char *filename, char *const argv[], char *const envp[])
1253{
1254 return my_syscall3(__NR_execve, filename, argv, envp);
1255}
1256
1257static __attribute__((unused))
1258pid_t sys_fork(void)
1259{
1260 return my_syscall0(__NR_fork);
1261}
1262
1263static __attribute__((unused))
1264int sys_fsync(int fd)
1265{
1266 return my_syscall1(__NR_fsync, fd);
1267}
1268
1269static __attribute__((unused))
1270int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
1271{
1272 return my_syscall3(__NR_getdents64, fd, dirp, count);
1273}
1274
1275static __attribute__((unused))
1276pid_t sys_getpgrp(void)
1277{
1278 return my_syscall0(__NR_getpgrp);
1279}
1280
1281static __attribute__((unused))
1282pid_t sys_getpid(void)
1283{
1284 return my_syscall0(__NR_getpid);
1285}
1286
1287static __attribute__((unused))
1288int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
1289{
1290 return my_syscall2(__NR_gettimeofday, tv, tz);
1291}
1292
1293static __attribute__((unused))
1294int sys_ioctl(int fd, unsigned long req, void *value)
1295{
1296 return my_syscall3(__NR_ioctl, fd, req, value);
1297}
1298
1299static __attribute__((unused))
1300int sys_kill(pid_t pid, int signal)
1301{
1302 return my_syscall2(__NR_kill, pid, signal);
1303}
1304
1305static __attribute__((unused))
1306int sys_link(const char *old, const char *new)
1307{
1308#ifdef __NR_linkat
1309 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0);
1310#else
1311 return my_syscall2(__NR_link, old, new);
1312#endif
1313}
1314
1315static __attribute__((unused))
1316off_t sys_lseek(int fd, off_t offset, int whence)
1317{
1318 return my_syscall3(__NR_lseek, fd, offset, whence);
1319}
1320
1321static __attribute__((unused))
1322int sys_mkdir(const char *path, mode_t mode)
1323{
1324#ifdef __NR_mkdirat
1325 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode);
1326#else
1327 return my_syscall2(__NR_mkdir, path, mode);
1328#endif
1329}
1330
1331static __attribute__((unused))
1332long sys_mknod(const char *path, mode_t mode, dev_t dev)
1333{
1334#ifdef __NR_mknodat
1335 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev);
1336#else
1337 return my_syscall3(__NR_mknod, path, mode, dev);
1338#endif
1339}
1340
1341static __attribute__((unused))
1342int sys_mount(const char *src, const char *tgt, const char *fst,
1343 unsigned long flags, const void *data)
1344{
1345 return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
1346}
1347
1348static __attribute__((unused))
1349int sys_open(const char *path, int flags, mode_t mode)
1350{
1351#ifdef __NR_openat
1352 return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
1353#else
1354 return my_syscall3(__NR_open, path, flags, mode);
1355#endif
1356}
1357
1358static __attribute__((unused))
1359int sys_pivot_root(const char *new, const char *old)
1360{
1361 return my_syscall2(__NR_pivot_root, new, old);
1362}
1363
1364static __attribute__((unused))
1365int sys_poll(struct pollfd *fds, int nfds, int timeout)
1366{
1367 return my_syscall3(__NR_poll, fds, nfds, timeout);
1368}
1369
1370static __attribute__((unused))
1371ssize_t sys_read(int fd, void *buf, size_t count)
1372{
1373 return my_syscall3(__NR_read, fd, buf, count);
1374}
1375
1376static __attribute__((unused))
1377ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
1378{
1379 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
1380}
1381
1382static __attribute__((unused))
1383int sys_sched_yield(void)
1384{
1385 return my_syscall0(__NR_sched_yield);
1386}
1387
1388static __attribute__((unused))
1389int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
1390{
1391#if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
1392 struct sel_arg_struct {
1393 unsigned long n;
1394 fd_set *r, *w, *e;
1395 struct timeval *t;
1396 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
1397 return my_syscall1(__NR_select, &arg);
1398#elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6)
1399 struct timespec t;
1400
1401 if (timeout) {
1402 t.tv_sec = timeout->tv_sec;
1403 t.tv_nsec = timeout->tv_usec * 1000;
1404 }
1405 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
1406#else
1407#ifndef __NR__newselect
1408#define __NR__newselect __NR_select
1409#endif
1410 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
1411#endif
1412}
1413
1414static __attribute__((unused))
1415int sys_setpgid(pid_t pid, pid_t pgid)
1416{
1417 return my_syscall2(__NR_setpgid, pid, pgid);
1418}
1419
1420static __attribute__((unused))
1421pid_t sys_setsid(void)
1422{
1423 return my_syscall0(__NR_setsid);
1424}
1425
1426static __attribute__((unused))
1427int sys_stat(const char *path, struct stat *buf)
1428{
1429 struct sys_stat_struct stat;
1430 long ret;
1431
1432#ifdef __NR_newfstatat
1433 /* only solution for arm64 */
1434 ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0);
1435#else
1436 ret = my_syscall2(__NR_stat, path, &stat);
1437#endif
1438 buf->st_dev = stat.st_dev;
1439 buf->st_ino = stat.st_ino;
1440 buf->st_mode = stat.st_mode;
1441 buf->st_nlink = stat.st_nlink;
1442 buf->st_uid = stat.st_uid;
1443 buf->st_gid = stat.st_gid;
1444 buf->st_rdev = stat.st_rdev;
1445 buf->st_size = stat.st_size;
1446 buf->st_blksize = stat.st_blksize;
1447 buf->st_blocks = stat.st_blocks;
1448 buf->st_atime = stat.st_atime;
1449 buf->st_mtime = stat.st_mtime;
1450 buf->st_ctime = stat.st_ctime;
1451 return ret;
1452}
1453
1454
1455static __attribute__((unused))
1456int sys_symlink(const char *old, const char *new)
1457{
1458#ifdef __NR_symlinkat
1459 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new);
1460#else
1461 return my_syscall2(__NR_symlink, old, new);
1462#endif
1463}
1464
1465static __attribute__((unused))
1466mode_t sys_umask(mode_t mode)
1467{
1468 return my_syscall1(__NR_umask, mode);
1469}
1470
1471static __attribute__((unused))
1472int sys_umount2(const char *path, int flags)
1473{
1474 return my_syscall2(__NR_umount2, path, flags);
1475}
1476
1477static __attribute__((unused))
1478int sys_unlink(const char *path)
1479{
1480#ifdef __NR_unlinkat
1481 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0);
1482#else
1483 return my_syscall1(__NR_unlink, path);
1484#endif
1485}
1486
1487static __attribute__((unused))
1488pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1489{
1490 return my_syscall4(__NR_wait4, pid, status, options, rusage);
1491}
1492
1493static __attribute__((unused))
1494pid_t sys_waitpid(pid_t pid, int *status, int options)
1495{
1496 return sys_wait4(pid, status, options, 0);
1497}
1498
1499static __attribute__((unused))
1500pid_t sys_wait(int *status)
1501{
1502 return sys_waitpid(-1, status, 0);
1503}
1504
1505static __attribute__((unused))
1506ssize_t sys_write(int fd, const void *buf, size_t count)
1507{
1508 return my_syscall3(__NR_write, fd, buf, count);
1509}
1510
1511
1512/* Below are the libc-compatible syscalls which return x or -1 and set errno.
1513 * They rely on the functions above. Similarly they're marked static so that it
1514 * is possible to assign pointers to them if needed.
1515 */
1516
1517static __attribute__((unused))
1518int brk(void *addr)
1519{
1520 void *ret = sys_brk(addr);
1521
1522 if (!ret) {
1523 SET_ERRNO(ENOMEM);
1524 return -1;
1525 }
1526 return 0;
1527}
1528
1529static __attribute__((noreturn,unused))
1530void exit(int status)
1531{
1532 sys_exit(status);
1533}
1534
1535static __attribute__((unused))
1536int chdir(const char *path)
1537{
1538 int ret = sys_chdir(path);
1539
1540 if (ret < 0) {
1541 SET_ERRNO(-ret);
1542 ret = -1;
1543 }
1544 return ret;
1545}
1546
1547static __attribute__((unused))
1548int chmod(const char *path, mode_t mode)
1549{
1550 int ret = sys_chmod(path, mode);
1551
1552 if (ret < 0) {
1553 SET_ERRNO(-ret);
1554 ret = -1;
1555 }
1556 return ret;
1557}
1558
1559static __attribute__((unused))
1560int chown(const char *path, uid_t owner, gid_t group)
1561{
1562 int ret = sys_chown(path, owner, group);
1563
1564 if (ret < 0) {
1565 SET_ERRNO(-ret);
1566 ret = -1;
1567 }
1568 return ret;
1569}
1570
1571static __attribute__((unused))
1572int chroot(const char *path)
1573{
1574 int ret = sys_chroot(path);
1575
1576 if (ret < 0) {
1577 SET_ERRNO(-ret);
1578 ret = -1;
1579 }
1580 return ret;
1581}
1582
1583static __attribute__((unused))
1584int close(int fd)
1585{
1586 int ret = sys_close(fd);
1587
1588 if (ret < 0) {
1589 SET_ERRNO(-ret);
1590 ret = -1;
1591 }
1592 return ret;
1593}
1594
1595static __attribute__((unused))
1596int dup2(int old, int new)
1597{
1598 int ret = sys_dup2(old, new);
1599
1600 if (ret < 0) {
1601 SET_ERRNO(-ret);
1602 ret = -1;
1603 }
1604 return ret;
1605}
1606
1607static __attribute__((unused))
1608int execve(const char *filename, char *const argv[], char *const envp[])
1609{
1610 int ret = sys_execve(filename, argv, envp);
1611
1612 if (ret < 0) {
1613 SET_ERRNO(-ret);
1614 ret = -1;
1615 }
1616 return ret;
1617}
1618
1619static __attribute__((unused))
1620pid_t fork(void)
1621{
1622 pid_t ret = sys_fork();
1623
1624 if (ret < 0) {
1625 SET_ERRNO(-ret);
1626 ret = -1;
1627 }
1628 return ret;
1629}
1630
1631static __attribute__((unused))
1632int fsync(int fd)
1633{
1634 int ret = sys_fsync(fd);
1635
1636 if (ret < 0) {
1637 SET_ERRNO(-ret);
1638 ret = -1;
1639 }
1640 return ret;
1641}
1642
1643static __attribute__((unused))
1644int getdents64(int fd, struct linux_dirent64 *dirp, int count)
1645{
1646 int ret = sys_getdents64(fd, dirp, count);
1647
1648 if (ret < 0) {
1649 SET_ERRNO(-ret);
1650 ret = -1;
1651 }
1652 return ret;
1653}
1654
1655static __attribute__((unused))
1656pid_t getpgrp(void)
1657{
1658 pid_t ret = sys_getpgrp();
1659
1660 if (ret < 0) {
1661 SET_ERRNO(-ret);
1662 ret = -1;
1663 }
1664 return ret;
1665}
1666
1667static __attribute__((unused))
1668pid_t getpid(void)
1669{
1670 pid_t ret = sys_getpid();
1671
1672 if (ret < 0) {
1673 SET_ERRNO(-ret);
1674 ret = -1;
1675 }
1676 return ret;
1677}
1678
1679static __attribute__((unused))
1680int gettimeofday(struct timeval *tv, struct timezone *tz)
1681{
1682 int ret = sys_gettimeofday(tv, tz);
1683
1684 if (ret < 0) {
1685 SET_ERRNO(-ret);
1686 ret = -1;
1687 }
1688 return ret;
1689}
1690
1691static __attribute__((unused))
1692int ioctl(int fd, unsigned long req, void *value)
1693{
1694 int ret = sys_ioctl(fd, req, value);
1695
1696 if (ret < 0) {
1697 SET_ERRNO(-ret);
1698 ret = -1;
1699 }
1700 return ret;
1701}
1702
1703static __attribute__((unused))
1704int kill(pid_t pid, int signal)
1705{
1706 int ret = sys_kill(pid, signal);
1707
1708 if (ret < 0) {
1709 SET_ERRNO(-ret);
1710 ret = -1;
1711 }
1712 return ret;
1713}
1714
1715static __attribute__((unused))
1716int link(const char *old, const char *new)
1717{
1718 int ret = sys_link(old, new);
1719
1720 if (ret < 0) {
1721 SET_ERRNO(-ret);
1722 ret = -1;
1723 }
1724 return ret;
1725}
1726
1727static __attribute__((unused))
1728off_t lseek(int fd, off_t offset, int whence)
1729{
1730 off_t ret = sys_lseek(fd, offset, whence);
1731
1732 if (ret < 0) {
1733 SET_ERRNO(-ret);
1734 ret = -1;
1735 }
1736 return ret;
1737}
1738
1739static __attribute__((unused))
1740int mkdir(const char *path, mode_t mode)
1741{
1742 int ret = sys_mkdir(path, mode);
1743
1744 if (ret < 0) {
1745 SET_ERRNO(-ret);
1746 ret = -1;
1747 }
1748 return ret;
1749}
1750
1751static __attribute__((unused))
1752int mknod(const char *path, mode_t mode, dev_t dev)
1753{
1754 int ret = sys_mknod(path, mode, dev);
1755
1756 if (ret < 0) {
1757 SET_ERRNO(-ret);
1758 ret = -1;
1759 }
1760 return ret;
1761}
1762
1763static __attribute__((unused))
1764int mount(const char *src, const char *tgt,
1765 const char *fst, unsigned long flags,
1766 const void *data)
1767{
1768 int ret = sys_mount(src, tgt, fst, flags, data);
1769
1770 if (ret < 0) {
1771 SET_ERRNO(-ret);
1772 ret = -1;
1773 }
1774 return ret;
1775}
1776
1777static __attribute__((unused))
1778int open(const char *path, int flags, mode_t mode)
1779{
1780 int ret = sys_open(path, flags, mode);
1781
1782 if (ret < 0) {
1783 SET_ERRNO(-ret);
1784 ret = -1;
1785 }
1786 return ret;
1787}
1788
1789static __attribute__((unused))
1790int pivot_root(const char *new, const char *old)
1791{
1792 int ret = sys_pivot_root(new, old);
1793
1794 if (ret < 0) {
1795 SET_ERRNO(-ret);
1796 ret = -1;
1797 }
1798 return ret;
1799}
1800
1801static __attribute__((unused))
1802int poll(struct pollfd *fds, int nfds, int timeout)
1803{
1804 int ret = sys_poll(fds, nfds, timeout);
1805
1806 if (ret < 0) {
1807 SET_ERRNO(-ret);
1808 ret = -1;
1809 }
1810 return ret;
1811}
1812
1813static __attribute__((unused))
1814ssize_t read(int fd, void *buf, size_t count)
1815{
1816 ssize_t ret = sys_read(fd, buf, count);
1817
1818 if (ret < 0) {
1819 SET_ERRNO(-ret);
1820 ret = -1;
1821 }
1822 return ret;
1823}
1824
1825static __attribute__((unused))
1826int reboot(int cmd)
1827{
1828 int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0);
1829
1830 if (ret < 0) {
1831 SET_ERRNO(-ret);
1832 ret = -1;
1833 }
1834 return ret;
1835}
1836
1837static __attribute__((unused))
1838void *sbrk(intptr_t inc)
1839{
1840 void *ret;
1841
1842 /* first call to find current end */
1843 if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc))
1844 return ret + inc;
1845
1846 SET_ERRNO(ENOMEM);
1847 return (void *)-1;
1848}
1849
1850static __attribute__((unused))
1851int sched_yield(void)
1852{
1853 int ret = sys_sched_yield();
1854
1855 if (ret < 0) {
1856 SET_ERRNO(-ret);
1857 ret = -1;
1858 }
1859 return ret;
1860}
1861
1862static __attribute__((unused))
1863int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
1864{
1865 int ret = sys_select(nfds, rfds, wfds, efds, timeout);
1866
1867 if (ret < 0) {
1868 SET_ERRNO(-ret);
1869 ret = -1;
1870 }
1871 return ret;
1872}
1873
1874static __attribute__((unused))
1875int setpgid(pid_t pid, pid_t pgid)
1876{
1877 int ret = sys_setpgid(pid, pgid);
1878
1879 if (ret < 0) {
1880 SET_ERRNO(-ret);
1881 ret = -1;
1882 }
1883 return ret;
1884}
1885
1886static __attribute__((unused))
1887pid_t setsid(void)
1888{
1889 pid_t ret = sys_setsid();
1890
1891 if (ret < 0) {
1892 SET_ERRNO(-ret);
1893 ret = -1;
1894 }
1895 return ret;
1896}
1897
1898static __attribute__((unused))
1899unsigned int sleep(unsigned int seconds)
1900{
1901 struct timeval my_timeval = { seconds, 0 };
1902
1903 if (sys_select(0, 0, 0, 0, &my_timeval) < 0)
1904 return my_timeval.tv_sec + !!my_timeval.tv_usec;
1905 else
1906 return 0;
1907}
1908
1909static __attribute__((unused))
1910int stat(const char *path, struct stat *buf)
1911{
1912 int ret = sys_stat(path, buf);
1913
1914 if (ret < 0) {
1915 SET_ERRNO(-ret);
1916 ret = -1;
1917 }
1918 return ret;
1919}
1920
1921static __attribute__((unused))
1922int symlink(const char *old, const char *new)
1923{
1924 int ret = sys_symlink(old, new);
1925
1926 if (ret < 0) {
1927 SET_ERRNO(-ret);
1928 ret = -1;
1929 }
1930 return ret;
1931}
1932
1933static __attribute__((unused))
1934int tcsetpgrp(int fd, pid_t pid)
1935{
1936 return ioctl(fd, TIOCSPGRP, &pid);
1937}
1938
1939static __attribute__((unused))
1940mode_t umask(mode_t mode)
1941{
1942 return sys_umask(mode);
1943}
1944
1945static __attribute__((unused))
1946int umount2(const char *path, int flags)
1947{
1948 int ret = sys_umount2(path, flags);
1949
1950 if (ret < 0) {
1951 SET_ERRNO(-ret);
1952 ret = -1;
1953 }
1954 return ret;
1955}
1956
1957static __attribute__((unused))
1958int unlink(const char *path)
1959{
1960 int ret = sys_unlink(path);
1961
1962 if (ret < 0) {
1963 SET_ERRNO(-ret);
1964 ret = -1;
1965 }
1966 return ret;
1967}
1968
1969static __attribute__((unused))
1970pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1971{
1972 pid_t ret = sys_wait4(pid, status, options, rusage);
1973
1974 if (ret < 0) {
1975 SET_ERRNO(-ret);
1976 ret = -1;
1977 }
1978 return ret;
1979}
1980
1981static __attribute__((unused))
1982pid_t waitpid(pid_t pid, int *status, int options)
1983{
1984 pid_t ret = sys_waitpid(pid, status, options);
1985
1986 if (ret < 0) {
1987 SET_ERRNO(-ret);
1988 ret = -1;
1989 }
1990 return ret;
1991}
1992
1993static __attribute__((unused))
1994pid_t wait(int *status)
1995{
1996 pid_t ret = sys_wait(status);
1997
1998 if (ret < 0) {
1999 SET_ERRNO(-ret);
2000 ret = -1;
2001 }
2002 return ret;
2003}
2004
2005static __attribute__((unused))
2006ssize_t write(int fd, const void *buf, size_t count)
2007{
2008 ssize_t ret = sys_write(fd, buf, count);
2009
2010 if (ret < 0) {
2011 SET_ERRNO(-ret);
2012 ret = -1;
2013 }
2014 return ret;
2015}
2016
2017/* some size-optimized reimplementations of a few common str* and mem*
2018 * functions. They're marked static, except memcpy() and raise() which are used
2019 * by libgcc on ARM, so they are marked weak instead in order not to cause an
2020 * error when building a program made of multiple files (not recommended).
2021 */
2022
2023static __attribute__((unused))
2024void *memmove(void *dst, const void *src, size_t len)
2025{
2026 ssize_t pos = (dst <= src) ? -1 : (long)len;
2027 void *ret = dst;
2028
2029 while (len--) {
2030 pos += (dst <= src) ? 1 : -1;
2031 ((char *)dst)[pos] = ((char *)src)[pos];
2032 }
2033 return ret;
2034}
2035
2036static __attribute__((unused))
2037void *memset(void *dst, int b, size_t len)
2038{
2039 char *p = dst;
2040
2041 while (len--)
2042 *(p++) = b;
2043 return dst;
2044}
2045
2046static __attribute__((unused))
2047int memcmp(const void *s1, const void *s2, size_t n)
2048{
2049 size_t ofs = 0;
2050 char c1 = 0;
2051
2052 while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) {
2053 ofs++;
2054 }
2055 return c1;
2056}
2057
2058static __attribute__((unused))
2059char *strcpy(char *dst, const char *src)
2060{
2061 char *ret = dst;
2062
2063 while ((*dst++ = *src++));
2064 return ret;
2065}
2066
2067static __attribute__((unused))
2068char *strchr(const char *s, int c)
2069{
2070 while (*s) {
2071 if (*s == (char)c)
2072 return (char *)s;
2073 s++;
2074 }
2075 return NULL;
2076}
2077
2078static __attribute__((unused))
2079char *strrchr(const char *s, int c)
2080{
2081 const char *ret = NULL;
2082
2083 while (*s) {
2084 if (*s == (char)c)
2085 ret = s;
2086 s++;
2087 }
2088 return (char *)ret;
2089}
2090
2091static __attribute__((unused))
2092size_t nolibc_strlen(const char *str)
2093{
2094 size_t len;
2095
2096 for (len = 0; str[len]; len++);
2097 return len;
2098}
2099
2100#define strlen(str) ({ \
2101 __builtin_constant_p((str)) ? \
2102 __builtin_strlen((str)) : \
2103 nolibc_strlen((str)); \
2104})
2105
2106static __attribute__((unused))
2107int isdigit(int c)
2108{
2109 return (unsigned int)(c - '0') <= 9;
2110}
2111
2112static __attribute__((unused))
2113long atol(const char *s)
2114{
2115 unsigned long ret = 0;
2116 unsigned long d;
2117 int neg = 0;
2118
2119 if (*s == '-') {
2120 neg = 1;
2121 s++;
2122 }
2123
2124 while (1) {
2125 d = (*s++) - '0';
2126 if (d > 9)
2127 break;
2128 ret *= 10;
2129 ret += d;
2130 }
2131
2132 return neg ? -ret : ret;
2133}
2134
2135static __attribute__((unused))
2136int atoi(const char *s)
2137{
2138 return atol(s);
2139}
2140
2141static __attribute__((unused))
2142const char *ltoa(long in)
2143{
2144 /* large enough for -9223372036854775808 */
2145 static char buffer[21];
2146 char *pos = buffer + sizeof(buffer) - 1;
2147 int neg = in < 0;
2148 unsigned long n = neg ? -in : in;
2149
2150 *pos-- = '\0';
2151 do {
2152 *pos-- = '0' + n % 10;
2153 n /= 10;
2154 if (pos < buffer)
2155 return pos + 1;
2156 } while (n);
2157
2158 if (neg)
2159 *pos-- = '-';
2160 return pos + 1;
2161}
2162
2163__attribute__((weak,unused))
2164void *memcpy(void *dst, const void *src, size_t len)
2165{
2166 return memmove(dst, src, len);
2167}
2168
2169/* needed by libgcc for divide by zero */
2170__attribute__((weak,unused))
2171int raise(int signal)
2172{
2173 return kill(getpid(), signal);
2174}
2175
2176/* Here come a few helper functions */
2177
2178static __attribute__((unused))
2179void FD_ZERO(fd_set *set)
2180{
2181 memset(set, 0, sizeof(*set));
2182}
2183
2184static __attribute__((unused))
2185void FD_SET(int fd, fd_set *set)
2186{
2187 if (fd < 0 || fd >= FD_SETSIZE)
2188 return;
2189 set->fd32[fd / 32] |= 1 << (fd & 31);
2190}
2191
2192/* WARNING, it only deals with the 4096 first majors and 256 first minors */
2193static __attribute__((unused))
2194dev_t makedev(unsigned int major, unsigned int minor)
2195{
2196 return ((major & 0xfff) << 8) | (minor & 0xff);
2197}
diff --git a/tools/testing/selftests/rcutorture/doc/initrd.txt b/tools/testing/selftests/rcutorture/doc/initrd.txt
index 833f826d6ec2..933b4fd12327 100644
--- a/tools/testing/selftests/rcutorture/doc/initrd.txt
+++ b/tools/testing/selftests/rcutorture/doc/initrd.txt
@@ -1,9 +1,12 @@
1This document describes one way to create the initrd directory hierarchy 1The rcutorture scripting tools automatically create the needed initrd
2in order to allow an initrd to be built into your kernel. The trick 2directory using dracut. Failing that, this tool will create an initrd
3here is to steal the initrd file used on your Linux laptop, Ubuntu in 3containing a single statically linked binary named "init" that loops
4this case. There are probably much better ways of doing this. 4over a very long sleep() call. In both cases, this creation is done
5by tools/testing/selftests/rcutorture/bin/mkinitrd.sh.
5 6
6That said, here are the commands: 7However, if you are attempting to run rcutorture on a system that does
8not have dracut installed, and if you don't like the notion of static
9linking, you might wish to press an existing initrd into service:
7 10
8------------------------------------------------------------------------ 11------------------------------------------------------------------------
9cd tools/testing/selftests/rcutorture 12cd tools/testing/selftests/rcutorture
@@ -11,22 +14,7 @@ zcat /initrd.img > /tmp/initrd.img.zcat
11mkdir initrd 14mkdir initrd
12cd initrd 15cd initrd
13cpio -id < /tmp/initrd.img.zcat 16cpio -id < /tmp/initrd.img.zcat
14------------------------------------------------------------------------ 17# Manually verify that initrd contains needed binaries and libraries.
15
16Another way to create an initramfs image is using "dracut"[1], which is
17available on many distros, however the initramfs dracut generates is a cpio
18archive with another cpio archive in it, so an extra step is needed to create
19the initrd directory hierarchy.
20
21Here are the commands to create a initrd directory for rcutorture using
22dracut:
23
24------------------------------------------------------------------------
25dracut --no-hostonly --no-hostonly-cmdline --module "base bash shutdown" /tmp/initramfs.img
26cd tools/testing/selftests/rcutorture
27mkdir initrd
28cd initrd
29/usr/lib/dracut/skipcpio /tmp/initramfs.img | zcat | cpio -id < /tmp/initramfs.img
30------------------------------------------------------------------------ 18------------------------------------------------------------------------
31 19
32Interestingly enough, if you are running rcutorture, you don't really 20Interestingly enough, if you are running rcutorture, you don't really
@@ -39,75 +27,12 @@ with 0755 mode.
39------------------------------------------------------------------------ 27------------------------------------------------------------------------
40#!/bin/sh 28#!/bin/sh
41 29
42[ -d /dev ] || mkdir -m 0755 /dev
43[ -d /root ] || mkdir -m 0700 /root
44[ -d /sys ] || mkdir /sys
45[ -d /proc ] || mkdir /proc
46[ -d /tmp ] || mkdir /tmp
47mkdir -p /var/lock
48mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
49mount -t proc -o nodev,noexec,nosuid proc /proc
50# Some things don't work properly without /etc/mtab.
51ln -sf /proc/mounts /etc/mtab
52
53# Note that this only becomes /dev on the real filesystem if udev's scripts
54# are used; which they will be, but it's worth pointing out
55if ! mount -t devtmpfs -o mode=0755 udev /dev; then
56 echo "W: devtmpfs not available, falling back to tmpfs for /dev"
57 mount -t tmpfs -o mode=0755 udev /dev
58 [ -e /dev/console ] || mknod --mode=600 /dev/console c 5 1
59 [ -e /dev/kmsg ] || mknod --mode=644 /dev/kmsg c 1 11
60 [ -e /dev/null ] || mknod --mode=666 /dev/null c 1 3
61fi
62
63mkdir /dev/pts
64mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
65mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run
66mkdir /run/initramfs
67# compatibility symlink for the pre-oneiric locations
68ln -s /run/initramfs /dev/.initramfs
69
70# Export relevant variables
71export ROOT=
72export ROOTDELAY=
73export ROOTFLAGS=
74export ROOTFSTYPE=
75export IP=
76export BOOT=
77export BOOTIF=
78export UBIMTD=
79export break=
80export init=/sbin/init
81export quiet=n
82export readonly=y
83export rootmnt=/root
84export debug=
85export panic=
86export blacklist=
87export resume=
88export resume_offset=
89export recovery=
90
91for i in /sys/devices/system/cpu/cpu*/online
92do
93 case $i in
94 '/sys/devices/system/cpu/cpu0/online')
95 ;;
96 '/sys/devices/system/cpu/cpu*/online')
97 ;;
98 *)
99 echo 1 > $i
100 ;;
101 esac
102done
103
104while : 30while :
105do 31do
106 sleep 10 32 sleep 10
107done 33done
108------------------------------------------------------------------------ 34------------------------------------------------------------------------
109 35
110References: 36This approach also allows most of the binaries and libraries in the
111[1]: https://dracut.wiki.kernel.org/index.php/Main_Page 37initrd filesystem to be dispensed with, which can save significant
112[2]: http://blog.elastocloud.org/2015/06/rapid-linux-kernel-devtest-with-qemu.html 38space in rcutorture's "res" directory.
113[3]: https://www.centos.org/forums/viewtopic.php?t=51621
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
index 891ad13e95b2..d27285f8ee82 100644
--- a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
@@ -131,8 +131,8 @@ struct hlist_node {
131 * weird ABI and we need to ask it explicitly. 131 * weird ABI and we need to ask it explicitly.
132 * 132 *
133 * The alignment is required to guarantee that bits 0 and 1 of @next will be 133 * The alignment is required to guarantee that bits 0 and 1 of @next will be
134 * clear under normal conditions -- as long as we use call_rcu(), 134 * clear under normal conditions -- as long as we use call_rcu() or
135 * call_rcu_bh(), call_rcu_sched(), or call_srcu() to queue callback. 135 * call_srcu() to queue callback.
136 * 136 *
137 * This guarantee is important for few reasons: 137 * This guarantee is important for few reasons:
138 * - future call_rcu_lazy() will make use of lower bits in the pointer; 138 * - future call_rcu_lazy() will make use of lower bits in the pointer;