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 ("ecall"
  7        : [ret] "={x10}" (-> u64),
  8        : [number] "{x17}" (@intFromEnum(number)),
  9        : .{ .memory = true });
 10}
 11
 12pub fn syscall1(number: SYS, arg1: u64) u64 {
 13    return asm volatile ("ecall"
 14        : [ret] "={x10}" (-> u64),
 15        : [number] "{x17}" (@intFromEnum(number)),
 16          [arg1] "{x10}" (arg1),
 17        : .{ .memory = true });
 18}
 19
 20pub fn syscall2(number: SYS, arg1: u64, arg2: u64) u64 {
 21    return asm volatile ("ecall"
 22        : [ret] "={x10}" (-> u64),
 23        : [number] "{x17}" (@intFromEnum(number)),
 24          [arg1] "{x10}" (arg1),
 25          [arg2] "{x11}" (arg2),
 26        : .{ .memory = true });
 27}
 28
 29pub fn syscall3(number: SYS, arg1: u64, arg2: u64, arg3: u64) u64 {
 30    return asm volatile ("ecall"
 31        : [ret] "={x10}" (-> u64),
 32        : [number] "{x17}" (@intFromEnum(number)),
 33          [arg1] "{x10}" (arg1),
 34          [arg2] "{x11}" (arg2),
 35          [arg3] "{x12}" (arg3),
 36        : .{ .memory = true });
 37}
 38
 39pub fn syscall4(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64) u64 {
 40    return asm volatile ("ecall"
 41        : [ret] "={x10}" (-> u64),
 42        : [number] "{x17}" (@intFromEnum(number)),
 43          [arg1] "{x10}" (arg1),
 44          [arg2] "{x11}" (arg2),
 45          [arg3] "{x12}" (arg3),
 46          [arg4] "{x13}" (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 ("ecall"
 52        : [ret] "={x10}" (-> u64),
 53        : [number] "{x17}" (@intFromEnum(number)),
 54          [arg1] "{x10}" (arg1),
 55          [arg2] "{x11}" (arg2),
 56          [arg3] "{x12}" (arg3),
 57          [arg4] "{x13}" (arg4),
 58          [arg5] "{x14}" (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 ("ecall"
 72        : [ret] "={x10}" (-> u64),
 73        : [number] "{x17}" (@intFromEnum(number)),
 74          [arg1] "{x10}" (arg1),
 75          [arg2] "{x11}" (arg2),
 76          [arg3] "{x12}" (arg3),
 77          [arg4] "{x13}" (arg4),
 78          [arg5] "{x14}" (arg5),
 79          [arg6] "{x15}" (arg6),
 80        : .{ .memory = true });
 81}
 82
 83pub fn clone() callconv(.naked) u64 {
 84    // __clone(func, stack, flags, arg, ptid, tls, ctid)
 85    //         a0,   a1,    a2,    a3,  a4,   a5,  a6
 86    //
 87    // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
 88    //         a7         a0,    a1,    a2,   a3,  a4
 89    asm volatile (
 90        \\    # Save func and arg to stack
 91        \\    addi a1, a1, -16
 92        \\    sd a0, 0(a1)
 93        \\    sd a3, 8(a1)
 94        \\
 95        \\    # Call SYS_clone
 96        \\    mv a0, a2
 97        \\    mv a2, a4
 98        \\    mv a3, a5
 99        \\    mv a4, a6
100        \\    li a7, 220 # SYS_clone
101        \\    ecall
102        \\
103        \\    beqz a0, 1f
104        \\    # Parent
105        \\    ret
106        \\
107        \\    # Child
108        \\1:
109    );
110    if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
111        \\    .cfi_undefined ra
112    );
113    asm volatile (
114        \\    mv fp, zero
115        \\    mv ra, zero
116        \\
117        \\    ld a1, 0(sp)
118        \\    ld a0, 8(sp)
119        \\    jalr a1
120        \\
121        \\    # Exit
122        \\    li a7, 93 # SYS_exit
123        \\    ecall
124    );
125}
126
127pub const blksize_t = i32;
128pub const nlink_t = u32;
129pub const time_t = i64;
130pub const mode_t = u32;
131pub const off_t = i64;
132pub const ino_t = u64;
133pub const dev_t = u64;
134pub const blkcnt_t = i64;
135
136// The `stat` definition used by the Linux kernel.
137pub const Stat = extern struct {
138    dev: dev_t,
139    ino: ino_t,
140    mode: mode_t,
141    nlink: nlink_t,
142    uid: std.os.linux.uid_t,
143    gid: std.os.linux.gid_t,
144    rdev: dev_t,
145    __pad: u64,
146    size: off_t,
147    blksize: blksize_t,
148    __pad2: i32,
149    blocks: blkcnt_t,
150    atim: std.os.linux.timespec,
151    mtim: std.os.linux.timespec,
152    ctim: std.os.linux.timespec,
153    __unused: [2]u32,
154
155    pub fn atime(self: @This()) std.os.linux.timespec {
156        return self.atim;
157    }
158
159    pub fn mtime(self: @This()) std.os.linux.timespec {
160        return self.mtim;
161    }
162
163    pub fn ctime(self: @This()) std.os.linux.timespec {
164        return self.ctim;
165    }
166};
167
168pub const VDSO = struct {
169    pub const CGT_SYM = "__vdso_clock_gettime";
170    pub const CGT_VER = "LINUX_4.15";
171};