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};