master
  1const builtin = @import("builtin");
  2const std = @import("../../std.zig");
  3const SYS = std.os.linux.SYS;
  4
  5pub fn syscall0(number: SYS) u64 {
  6    return asm volatile ("svc #0"
  7        : [ret] "={x0}" (-> u64),
  8        : [number] "{x8}" (@intFromEnum(number)),
  9        : .{ .memory = true });
 10}
 11
 12pub fn syscall1(number: SYS, arg1: u64) u64 {
 13    return asm volatile ("svc #0"
 14        : [ret] "={x0}" (-> u64),
 15        : [number] "{x8}" (@intFromEnum(number)),
 16          [arg1] "{x0}" (arg1),
 17        : .{ .memory = true });
 18}
 19
 20pub fn syscall2(number: SYS, arg1: u64, arg2: u64) u64 {
 21    return asm volatile ("svc #0"
 22        : [ret] "={x0}" (-> u64),
 23        : [number] "{x8}" (@intFromEnum(number)),
 24          [arg1] "{x0}" (arg1),
 25          [arg2] "{x1}" (arg2),
 26        : .{ .memory = true });
 27}
 28
 29pub fn syscall3(number: SYS, arg1: u64, arg2: u64, arg3: u64) u64 {
 30    return asm volatile ("svc #0"
 31        : [ret] "={x0}" (-> u64),
 32        : [number] "{x8}" (@intFromEnum(number)),
 33          [arg1] "{x0}" (arg1),
 34          [arg2] "{x1}" (arg2),
 35          [arg3] "{x2}" (arg3),
 36        : .{ .memory = true });
 37}
 38
 39pub fn syscall4(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64) u64 {
 40    return asm volatile ("svc #0"
 41        : [ret] "={x0}" (-> u64),
 42        : [number] "{x8}" (@intFromEnum(number)),
 43          [arg1] "{x0}" (arg1),
 44          [arg2] "{x1}" (arg2),
 45          [arg3] "{x2}" (arg3),
 46          [arg4] "{x3}" (arg4),
 47        : .{ .memory = true });
 48}
 49
 50pub fn syscall5(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) u64 {
 51    return asm volatile ("svc #0"
 52        : [ret] "={x0}" (-> u64),
 53        : [number] "{x8}" (@intFromEnum(number)),
 54          [arg1] "{x0}" (arg1),
 55          [arg2] "{x1}" (arg2),
 56          [arg3] "{x2}" (arg3),
 57          [arg4] "{x3}" (arg4),
 58          [arg5] "{x4}" (arg5),
 59        : .{ .memory = true });
 60}
 61
 62pub fn syscall6(
 63    number: SYS,
 64    arg1: u64,
 65    arg2: u64,
 66    arg3: u64,
 67    arg4: u64,
 68    arg5: u64,
 69    arg6: u64,
 70) u64 {
 71    return asm volatile ("svc #0"
 72        : [ret] "={x0}" (-> u64),
 73        : [number] "{x8}" (@intFromEnum(number)),
 74          [arg1] "{x0}" (arg1),
 75          [arg2] "{x1}" (arg2),
 76          [arg3] "{x2}" (arg3),
 77          [arg4] "{x3}" (arg4),
 78          [arg5] "{x4}" (arg5),
 79          [arg6] "{x5}" (arg6),
 80        : .{ .memory = true });
 81}
 82
 83pub fn clone() callconv(.naked) u64 {
 84    // __clone(func, stack, flags, arg, ptid, tls, ctid)
 85    //         x0,   x1,    w2,    x3,  x4,   x5,  x6
 86    //
 87    // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
 88    //         x8,        x0,    x1,    x2,   x3,  x4
 89    asm volatile (
 90        \\      // align stack and save func,arg
 91        \\      and x1,x1,#-16
 92        \\      stp x0,x3,[x1,#-16]!
 93        \\
 94        \\      // syscall
 95        \\      uxtw x0,w2
 96        \\      mov x2,x4
 97        \\      mov x3,x5
 98        \\      mov x4,x6
 99        \\      mov x8,#220 // SYS_clone
100        \\      svc #0
101        \\
102        \\      cbz x0,1f
103        \\      // parent
104        \\      ret
105        \\
106        \\      // child
107        \\1:
108    );
109    if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
110        \\     .cfi_undefined lr
111    );
112    asm volatile (
113        \\      mov fp, 0
114        \\      mov lr, 0
115        \\
116        \\      ldp x1,x0,[sp],#16
117        \\      blr x1
118        \\      mov x8,#93 // SYS_exit
119        \\      svc #0
120    );
121}
122
123pub const restore = restore_rt;
124
125pub fn restore_rt() callconv(.naked) noreturn {
126    switch (builtin.zig_backend) {
127        .stage2_c => asm volatile (
128            \\ mov x8, %[number]
129            \\ svc #0
130            :
131            : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
132        ),
133        else => asm volatile (
134            \\ svc #0
135            :
136            : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),
137        ),
138    }
139}
140
141pub const VDSO = struct {
142    pub const CGT_SYM = "__kernel_clock_gettime";
143    pub const CGT_VER = "LINUX_2.6.39";
144};
145
146pub const blksize_t = i32;
147pub const nlink_t = u32;
148pub const time_t = i64;
149pub const mode_t = u32;
150pub const off_t = i64;
151pub const ino_t = u64;
152pub const dev_t = u64;
153pub const blkcnt_t = i64;
154
155// The `stat` definition used by the Linux kernel.
156pub const Stat = extern struct {
157    dev: dev_t,
158    ino: ino_t,
159    mode: mode_t,
160    nlink: nlink_t,
161    uid: std.os.linux.uid_t,
162    gid: std.os.linux.gid_t,
163    rdev: dev_t,
164    __pad: u64,
165    size: off_t,
166    blksize: blksize_t,
167    __pad2: i32,
168    blocks: blkcnt_t,
169    atim: std.os.linux.timespec,
170    mtim: std.os.linux.timespec,
171    ctim: std.os.linux.timespec,
172    __unused: [2]u32,
173
174    pub fn atime(self: @This()) std.os.linux.timespec {
175        return self.atim;
176    }
177
178    pub fn mtime(self: @This()) std.os.linux.timespec {
179        return self.mtim;
180    }
181
182    pub fn ctime(self: @This()) std.os.linux.timespec {
183        return self.ctim;
184    }
185};