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 ("syscall"
  7        : [ret] "={rax}" (-> u64),
  8        : [number] "{rax}" (@intFromEnum(number)),
  9        : .{ .rcx = true, .r11 = true, .memory = true });
 10}
 11
 12pub fn syscall1(number: SYS, arg1: u64) u64 {
 13    return asm volatile ("syscall"
 14        : [ret] "={rax}" (-> u64),
 15        : [number] "{rax}" (@intFromEnum(number)),
 16          [arg1] "{rdi}" (arg1),
 17        : .{ .rcx = true, .r11 = true, .memory = true });
 18}
 19
 20pub fn syscall2(number: SYS, arg1: u64, arg2: u64) u64 {
 21    return asm volatile ("syscall"
 22        : [ret] "={rax}" (-> u64),
 23        : [number] "{rax}" (@intFromEnum(number)),
 24          [arg1] "{rdi}" (arg1),
 25          [arg2] "{rsi}" (arg2),
 26        : .{ .rcx = true, .r11 = true, .memory = true });
 27}
 28
 29pub fn syscall3(number: SYS, arg1: u64, arg2: u64, arg3: u64) u64 {
 30    return asm volatile ("syscall"
 31        : [ret] "={rax}" (-> u64),
 32        : [number] "{rax}" (@intFromEnum(number)),
 33          [arg1] "{rdi}" (arg1),
 34          [arg2] "{rsi}" (arg2),
 35          [arg3] "{rdx}" (arg3),
 36        : .{ .rcx = true, .r11 = true, .memory = true });
 37}
 38
 39pub fn syscall4(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64) u64 {
 40    return asm volatile ("syscall"
 41        : [ret] "={rax}" (-> u64),
 42        : [number] "{rax}" (@intFromEnum(number)),
 43          [arg1] "{rdi}" (arg1),
 44          [arg2] "{rsi}" (arg2),
 45          [arg3] "{rdx}" (arg3),
 46          [arg4] "{r10}" (arg4),
 47        : .{ .rcx = true, .r11 = true, .memory = true });
 48}
 49
 50pub fn syscall5(number: SYS, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) u64 {
 51    return asm volatile ("syscall"
 52        : [ret] "={rax}" (-> u64),
 53        : [number] "{rax}" (@intFromEnum(number)),
 54          [arg1] "{rdi}" (arg1),
 55          [arg2] "{rsi}" (arg2),
 56          [arg3] "{rdx}" (arg3),
 57          [arg4] "{r10}" (arg4),
 58          [arg5] "{r8}" (arg5),
 59        : .{ .rcx = true, .r11 = true, .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 ("syscall"
 72        : [ret] "={rax}" (-> u64),
 73        : [number] "{rax}" (@intFromEnum(number)),
 74          [arg1] "{rdi}" (arg1),
 75          [arg2] "{rsi}" (arg2),
 76          [arg3] "{rdx}" (arg3),
 77          [arg4] "{r10}" (arg4),
 78          [arg5] "{r8}" (arg5),
 79          [arg6] "{r9}" (arg6),
 80        : .{ .rcx = true, .r11 = true, .memory = true });
 81}
 82
 83pub fn clone() callconv(.naked) u64 {
 84    asm volatile (
 85        \\      movl $56,%%eax // SYS_clone
 86        \\      movq %%rdi,%%r11
 87        \\      movq %%rdx,%%rdi
 88        \\      movq %%r8,%%rdx
 89        \\      movq %%r9,%%r8
 90        \\      movq 8(%%rsp),%%r10
 91        \\      movq %%r11,%%r9
 92        \\      andq $-16,%%rsi
 93        \\      subq $8,%%rsi
 94        \\      movq %%rcx,(%%rsi)
 95        \\      syscall
 96        \\      testq %%rax,%%rax
 97        \\      jz 1f
 98        \\      retq
 99        \\
100        \\1:
101    );
102    if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
103        \\      .cfi_undefined %%rip
104    );
105    asm volatile (
106        \\      xorl %%ebp,%%ebp
107        \\
108        \\      popq %%rdi
109        \\      callq *%%r9
110        \\      movl %%eax,%%edi
111        \\      movl $60,%%eax // SYS_exit
112        \\      syscall
113        \\
114    );
115}
116
117pub const restore = restore_rt;
118
119pub fn restore_rt() callconv(.naked) noreturn {
120    switch (builtin.zig_backend) {
121        .stage2_c => asm volatile (
122            \\ movl %[number], %%eax
123            \\ syscall
124            :
125            : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
126        ),
127        else => asm volatile (
128            \\ syscall
129            :
130            : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)),
131        ),
132    }
133}
134
135pub const mode_t = u64;
136pub const time_t = i64;
137pub const nlink_t = u64;
138pub const blksize_t = i64;
139pub const blkcnt_t = i64;
140pub const off_t = i64;
141pub const ino_t = u64;
142pub const dev_t = u64;
143
144pub const VDSO = struct {
145    pub const CGT_SYM = "__vdso_clock_gettime";
146    pub const CGT_VER = "LINUX_2.6";
147
148    pub const GETCPU_SYM = "__vdso_getcpu";
149    pub const GETCPU_VER = "LINUX_2.6";
150};
151
152pub const ARCH = struct {
153    pub const SET_GS = 0x1001;
154    pub const SET_FS = 0x1002;
155    pub const GET_FS = 0x1003;
156    pub const GET_GS = 0x1004;
157};
158
159// The `stat` definition used by the Linux kernel.
160pub const Stat = extern struct {
161    dev: dev_t,
162    ino: ino_t,
163    nlink: u64,
164
165    mode: u32,
166    uid: std.os.linux.uid_t,
167    gid: std.os.linux.gid_t,
168    __pad0: u32,
169    rdev: dev_t,
170    size: off_t,
171    blksize: i64,
172    blocks: i64,
173
174    atim: std.os.linux.timespec,
175    mtim: std.os.linux.timespec,
176    ctim: std.os.linux.timespec,
177    __unused: [3]i64,
178
179    pub fn atime(self: @This()) std.os.linux.timespec {
180        return self.atim;
181    }
182
183    pub fn mtime(self: @This()) std.os.linux.timespec {
184        return self.mtim;
185    }
186
187    pub fn ctime(self: @This()) std.os.linux.timespec {
188        return self.ctim;
189    }
190};