1const std = @import("../../std.zig");
2const maxInt = std.math.maxInt;
3const linux = std.os.linux;
4const socklen_t = linux.socklen_t;
5const sockaddr = linux.sockaddr;
6const iovec = linux.iovec;
7const iovec_const = linux.iovec_const;
8const uid_t = linux.uid_t;
9const gid_t = linux.gid_t;
10const pid_t = linux.pid_t;
11const stack_t = linux.stack_t;
12const sigset_t = linux.sigset_t;
13const timespec = std.os.linux.timespec;
14
15pub fn syscall0(number: SYS) usize {
16    return asm volatile ("svc #0"
17        : [ret] "={x0}" (-> usize),
18        : [number] "{x8}" (@enumToInt(number)),
19        : "memory", "cc"
20    );
21}
22
23pub fn syscall1(number: SYS, arg1: usize) usize {
24    return asm volatile ("svc #0"
25        : [ret] "={x0}" (-> usize),
26        : [number] "{x8}" (@enumToInt(number)),
27          [arg1] "{x0}" (arg1),
28        : "memory", "cc"
29    );
30}
31
32pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
33    return asm volatile ("svc #0"
34        : [ret] "={x0}" (-> usize),
35        : [number] "{x8}" (@enumToInt(number)),
36          [arg1] "{x0}" (arg1),
37          [arg2] "{x1}" (arg2),
38        : "memory", "cc"
39    );
40}
41
42pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
43    return asm volatile ("svc #0"
44        : [ret] "={x0}" (-> usize),
45        : [number] "{x8}" (@enumToInt(number)),
46          [arg1] "{x0}" (arg1),
47          [arg2] "{x1}" (arg2),
48          [arg3] "{x2}" (arg3),
49        : "memory", "cc"
50    );
51}
52
53pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
54    return asm volatile ("svc #0"
55        : [ret] "={x0}" (-> usize),
56        : [number] "{x8}" (@enumToInt(number)),
57          [arg1] "{x0}" (arg1),
58          [arg2] "{x1}" (arg2),
59          [arg3] "{x2}" (arg3),
60          [arg4] "{x3}" (arg4),
61        : "memory", "cc"
62    );
63}
64
65pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
66    return asm volatile ("svc #0"
67        : [ret] "={x0}" (-> usize),
68        : [number] "{x8}" (@enumToInt(number)),
69          [arg1] "{x0}" (arg1),
70          [arg2] "{x1}" (arg2),
71          [arg3] "{x2}" (arg3),
72          [arg4] "{x3}" (arg4),
73          [arg5] "{x4}" (arg5),
74        : "memory", "cc"
75    );
76}
77
78pub fn syscall6(
79    number: SYS,
80    arg1: usize,
81    arg2: usize,
82    arg3: usize,
83    arg4: usize,
84    arg5: usize,
85    arg6: usize,
86) usize {
87    return asm volatile ("svc #0"
88        : [ret] "={x0}" (-> usize),
89        : [number] "{x8}" (@enumToInt(number)),
90          [arg1] "{x0}" (arg1),
91          [arg2] "{x1}" (arg2),
92          [arg3] "{x2}" (arg3),
93          [arg4] "{x3}" (arg4),
94          [arg5] "{x4}" (arg5),
95          [arg6] "{x5}" (arg6),
96        : "memory", "cc"
97    );
98}
99
100/// This matches the libc clone function.
101pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
102
103pub const restore = restore_rt;
104
105pub fn restore_rt() callconv(.Naked) void {
106    return asm volatile ("svc #0"
107        :
108        : [number] "{x8}" (@enumToInt(SYS.rt_sigreturn)),
109        : "memory", "cc"
110    );
111}
112
113pub const SYS = enum(usize) {
114    io_setup = 0,
115    io_destroy = 1,
116    io_submit = 2,
117    io_cancel = 3,
118    io_getevents = 4,
119    setxattr = 5,
120    lsetxattr = 6,
121    fsetxattr = 7,
122    getxattr = 8,
123    lgetxattr = 9,
124    fgetxattr = 10,
125    listxattr = 11,
126    llistxattr = 12,
127    flistxattr = 13,
128    removexattr = 14,
129    lremovexattr = 15,
130    fremovexattr = 16,
131    getcwd = 17,
132    lookup_dcookie = 18,
133    eventfd2 = 19,
134    epoll_create1 = 20,
135    epoll_ctl = 21,
136    epoll_pwait = 22,
137    dup = 23,
138    dup3 = 24,
139    fcntl = 25,
140    inotify_init1 = 26,
141    inotify_add_watch = 27,
142    inotify_rm_watch = 28,
143    ioctl = 29,
144    ioprio_set = 30,
145    ioprio_get = 31,
146    flock = 32,
147    mknodat = 33,
148    mkdirat = 34,
149    unlinkat = 35,
150    symlinkat = 36,
151    linkat = 37,
152    renameat = 38,
153    umount2 = 39,
154    mount = 40,
155    pivot_root = 41,
156    nfsservctl = 42,
157    statfs = 43,
158    fstatfs = 44,
159    truncate = 45,
160    ftruncate = 46,
161    fallocate = 47,
162    faccessat = 48,
163    chdir = 49,
164    fchdir = 50,
165    chroot = 51,
166    fchmod = 52,
167    fchmodat = 53,
168    fchownat = 54,
169    fchown = 55,
170    openat = 56,
171    close = 57,
172    vhangup = 58,
173    pipe2 = 59,
174    quotactl = 60,
175    getdents64 = 61,
176    lseek = 62,
177    read = 63,
178    write = 64,
179    readv = 65,
180    writev = 66,
181    pread64 = 67,
182    pwrite64 = 68,
183    preadv = 69,
184    pwritev = 70,
185    sendfile = 71,
186    pselect6 = 72,
187    ppoll = 73,
188    signalfd4 = 74,
189    vmsplice = 75,
190    splice = 76,
191    tee = 77,
192    readlinkat = 78,
193    fstatat = 79,
194    fstat = 80,
195    sync = 81,
196    fsync = 82,
197    fdatasync = 83,
198    sync_file_range = 84,
199    timerfd_create = 85,
200    timerfd_settime = 86,
201    timerfd_gettime = 87,
202    utimensat = 88,
203    acct = 89,
204    capget = 90,
205    capset = 91,
206    personality = 92,
207    exit = 93,
208    exit_group = 94,
209    waitid = 95,
210    set_tid_address = 96,
211    unshare = 97,
212    futex = 98,
213    set_robust_list = 99,
214    get_robust_list = 100,
215    nanosleep = 101,
216    getitimer = 102,
217    setitimer = 103,
218    kexec_load = 104,
219    init_module = 105,
220    delete_module = 106,
221    timer_create = 107,
222    timer_gettime = 108,
223    timer_getoverrun = 109,
224    timer_settime = 110,
225    timer_delete = 111,
226    clock_settime = 112,
227    clock_gettime = 113,
228    clock_getres = 114,
229    clock_nanosleep = 115,
230    syslog = 116,
231    ptrace = 117,
232    sched_setparam = 118,
233    sched_setscheduler = 119,
234    sched_getscheduler = 120,
235    sched_getparam = 121,
236    sched_setaffinity = 122,
237    sched_getaffinity = 123,
238    sched_yield = 124,
239    sched_get_priority_max = 125,
240    sched_get_priority_min = 126,
241    sched_rr_get_interval = 127,
242    restart_syscall = 128,
243    kill = 129,
244    tkill = 130,
245    tgkill = 131,
246    sigaltstack = 132,
247    rt_sigsuspend = 133,
248    rt_sigaction = 134,
249    rt_sigprocmask = 135,
250    rt_sigpending = 136,
251    rt_sigtimedwait = 137,
252    rt_sigqueueinfo = 138,
253    rt_sigreturn = 139,
254    setpriority = 140,
255    getpriority = 141,
256    reboot = 142,
257    setregid = 143,
258    setgid = 144,
259    setreuid = 145,
260    setuid = 146,
261    setresuid = 147,
262    getresuid = 148,
263    setresgid = 149,
264    getresgid = 150,
265    setfsuid = 151,
266    setfsgid = 152,
267    times = 153,
268    setpgid = 154,
269    getpgid = 155,
270    getsid = 156,
271    setsid = 157,
272    getgroups = 158,
273    setgroups = 159,
274    uname = 160,
275    sethostname = 161,
276    setdomainname = 162,
277    getrlimit = 163,
278    setrlimit = 164,
279    getrusage = 165,
280    umask = 166,
281    prctl = 167,
282    getcpu = 168,
283    gettimeofday = 169,
284    settimeofday = 170,
285    adjtimex = 171,
286    getpid = 172,
287    getppid = 173,
288    getuid = 174,
289    geteuid = 175,
290    getgid = 176,
291    getegid = 177,
292    gettid = 178,
293    sysinfo = 179,
294    mq_open = 180,
295    mq_unlink = 181,
296    mq_timedsend = 182,
297    mq_timedreceive = 183,
298    mq_notify = 184,
299    mq_getsetattr = 185,
300    msgget = 186,
301    msgctl = 187,
302    msgrcv = 188,
303    msgsnd = 189,
304    semget = 190,
305    semctl = 191,
306    semtimedop = 192,
307    semop = 193,
308    shmget = 194,
309    shmctl = 195,
310    shmat = 196,
311    shmdt = 197,
312    socket = 198,
313    socketpair = 199,
314    bind = 200,
315    listen = 201,
316    accept = 202,
317    connect = 203,
318    getsockname = 204,
319    getpeername = 205,
320    sendto = 206,
321    recvfrom = 207,
322    setsockopt = 208,
323    getsockopt = 209,
324    shutdown = 210,
325    sendmsg = 211,
326    recvmsg = 212,
327    readahead = 213,
328    brk = 214,
329    munmap = 215,
330    mremap = 216,
331    add_key = 217,
332    request_key = 218,
333    keyctl = 219,
334    clone = 220,
335    execve = 221,
336    mmap = 222,
337    fadvise64 = 223,
338    swapon = 224,
339    swapoff = 225,
340    mprotect = 226,
341    msync = 227,
342    mlock = 228,
343    munlock = 229,
344    mlockall = 230,
345    munlockall = 231,
346    mincore = 232,
347    madvise = 233,
348    remap_file_pages = 234,
349    mbind = 235,
350    get_mempolicy = 236,
351    set_mempolicy = 237,
352    migrate_pages = 238,
353    move_pages = 239,
354    rt_tgsigqueueinfo = 240,
355    perf_event_open = 241,
356    accept4 = 242,
357    recvmmsg = 243,
358    arch_specific_syscall = 244,
359    wait4 = 260,
360    prlimit64 = 261,
361    fanotify_init = 262,
362    fanotify_mark = 263,
363    clock_adjtime = 266,
364    syncfs = 267,
365    setns = 268,
366    sendmmsg = 269,
367    process_vm_readv = 270,
368    process_vm_writev = 271,
369    kcmp = 272,
370    finit_module = 273,
371    sched_setattr = 274,
372    sched_getattr = 275,
373    renameat2 = 276,
374    seccomp = 277,
375    getrandom = 278,
376    memfd_create = 279,
377    bpf = 280,
378    execveat = 281,
379    userfaultfd = 282,
380    membarrier = 283,
381    mlock2 = 284,
382    copy_file_range = 285,
383    preadv2 = 286,
384    pwritev2 = 287,
385    pkey_mprotect = 288,
386    pkey_alloc = 289,
387    pkey_free = 290,
388    statx = 291,
389    io_pgetevents = 292,
390    rseq = 293,
391    kexec_file_load = 294,
392    pidfd_send_signal = 424,
393    io_uring_setup = 425,
394    io_uring_enter = 426,
395    io_uring_register = 427,
396    open_tree = 428,
397    move_mount = 429,
398    fsopen = 430,
399    fsconfig = 431,
400    fsmount = 432,
401    fspick = 433,
402    pidfd_open = 434,
403    clone3 = 435,
404    close_range = 436,
405    openat2 = 437,
406    pidfd_getfd = 438,
407    faccessat2 = 439,
408    process_madvise = 440,
409    epoll_pwait2 = 441,
410    mount_setattr = 442,
411    landlock_create_ruleset = 444,
412    landlock_add_rule = 445,
413    landlock_restrict_self = 446,
414
415    _,
416};
417
418pub const O = struct {
419    pub const CREAT = 0o100;
420    pub const EXCL = 0o200;
421    pub const NOCTTY = 0o400;
422    pub const TRUNC = 0o1000;
423    pub const APPEND = 0o2000;
424    pub const NONBLOCK = 0o4000;
425    pub const DSYNC = 0o10000;
426    pub const SYNC = 0o4010000;
427    pub const RSYNC = 0o4010000;
428    pub const DIRECTORY = 0o40000;
429    pub const NOFOLLOW = 0o100000;
430    pub const CLOEXEC = 0o2000000;
431
432    pub const ASYNC = 0o20000;
433    pub const DIRECT = 0o200000;
434    pub const LARGEFILE = 0o400000;
435    pub const NOATIME = 0o1000000;
436    pub const PATH = 0o10000000;
437    pub const TMPFILE = 0o20040000;
438    pub const NDELAY = NONBLOCK;
439};
440
441pub const F = struct {
442    pub const DUPFD = 0;
443    pub const GETFD = 1;
444    pub const SETFD = 2;
445    pub const GETFL = 3;
446    pub const SETFL = 4;
447
448    pub const SETOWN = 8;
449    pub const GETOWN = 9;
450    pub const SETSIG = 10;
451    pub const GETSIG = 11;
452
453    pub const GETLK = 5;
454    pub const SETLK = 6;
455    pub const SETLKW = 7;
456
457    pub const RDLCK = 0;
458    pub const WRLCK = 1;
459    pub const UNLCK = 2;
460
461    pub const SETOWN_EX = 15;
462    pub const GETOWN_EX = 16;
463
464    pub const GETOWNER_UIDS = 17;
465};
466
467pub const LOCK = struct {
468    pub const SH = 1;
469    pub const EX = 2;
470    pub const UN = 8;
471    pub const NB = 4;
472};
473
474pub const MAP = struct {
475    /// stack-like segment
476    pub const GROWSDOWN = 0x0100;
477    /// ETXTBSY
478    pub const DENYWRITE = 0x0800;
479    /// mark it as an executable
480    pub const EXECUTABLE = 0x1000;
481    /// pages are locked
482    pub const LOCKED = 0x2000;
483    /// don't check for reservations
484    pub const NORESERVE = 0x4000;
485};
486
487pub const VDSO = struct {
488    pub const CGT_SYM = "__kernel_clock_gettime";
489    pub const CGT_VER = "LINUX_2.6.39";
490};
491
492pub const Flock = extern struct {
493    l_type: i16,
494    l_whence: i16,
495    l_start: off_t,
496    l_len: off_t,
497    l_pid: pid_t,
498    __unused: [4]u8,
499};
500
501pub const msghdr = extern struct {
502    msg_name: ?*sockaddr,
503    msg_namelen: socklen_t,
504    msg_iov: [*]iovec,
505    msg_iovlen: i32,
506    __pad1: i32 = 0,
507    msg_control: ?*anyopaque,
508    msg_controllen: socklen_t,
509    __pad2: socklen_t = 0,
510    msg_flags: i32,
511};
512
513pub const msghdr_const = extern struct {
514    msg_name: ?*const sockaddr,
515    msg_namelen: socklen_t,
516    msg_iov: [*]iovec_const,
517    msg_iovlen: i32,
518    __pad1: i32 = 0,
519    msg_control: ?*anyopaque,
520    msg_controllen: socklen_t,
521    __pad2: socklen_t = 0,
522    msg_flags: i32,
523};
524
525pub const blksize_t = i32;
526pub const nlink_t = u32;
527pub const time_t = isize;
528pub const mode_t = u32;
529pub const off_t = isize;
530pub const ino_t = usize;
531pub const dev_t = usize;
532pub const blkcnt_t = isize;
533
534// The `stat` definition used by the Linux kernel.
535pub const Stat = extern struct {
536    dev: dev_t,
537    ino: ino_t,
538    mode: mode_t,
539    nlink: nlink_t,
540    uid: uid_t,
541    gid: gid_t,
542    rdev: dev_t,
543    __pad: usize,
544    size: off_t,
545    blksize: blksize_t,
546    __pad2: i32,
547    blocks: blkcnt_t,
548    atim: timespec,
549    mtim: timespec,
550    ctim: timespec,
551    __unused: [2]u32,
552
553    pub fn atime(self: @This()) timespec {
554        return self.atim;
555    }
556
557    pub fn mtime(self: @This()) timespec {
558        return self.mtim;
559    }
560
561    pub fn ctime(self: @This()) timespec {
562        return self.ctim;
563    }
564};
565
566pub const timeval = extern struct {
567    tv_sec: isize,
568    tv_usec: isize,
569};
570
571pub const timezone = extern struct {
572    tz_minuteswest: i32,
573    tz_dsttime: i32,
574};
575
576pub const mcontext_t = extern struct {
577    fault_address: usize,
578    regs: [31]usize,
579    sp: usize,
580    pc: usize,
581    pstate: usize,
582    // Make sure the field is correctly aligned since this area
583    // holds various FP/vector registers
584    reserved1: [256 * 16]u8 align(16),
585};
586
587pub const ucontext_t = extern struct {
588    flags: usize,
589    link: *ucontext_t,
590    stack: stack_t,
591    sigmask: sigset_t,
592    mcontext: mcontext_t,
593};
594
595pub const Elf_Symndx = u32;
596