master
1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const SYS = std.os.linux.SYS;
4
5pub fn syscall0(number: SYS) u32 {
6 return asm volatile (
7 \\ syscall
8 \\ beq $a3, $zero, 1f
9 \\ blez $v0, 1f
10 \\ subu $v0, $zero, $v0
11 \\1:
12 : [ret] "={$2}" (-> u32),
13 : [number] "{$2}" (@intFromEnum(number)),
14 : .{ .r1 = true, .r3 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
15}
16
17pub fn syscall_pipe(fd: *[2]i32) u32 {
18 return asm volatile (
19 \\ syscall
20 \\ beq $a3, $zero, 1f
21 \\ blez $v0, 2f
22 \\ subu $v0, $zero, $v0
23 \\ b 2f
24 \\1:
25 \\ sw $v0, 0($a0)
26 \\ sw $v1, 4($a0)
27 \\2:
28 : [ret] "={$2}" (-> u32),
29 : [number] "{$2}" (@intFromEnum(SYS.pipe)),
30 [fd] "{$4}" (fd),
31 : .{ .r1 = true, .r3 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
32}
33
34pub fn syscall1(number: SYS, arg1: u32) u32 {
35 return asm volatile (
36 \\ syscall
37 \\ beq $a3, $zero, 1f
38 \\ blez $v0, 1f
39 \\ subu $v0, $zero, $v0
40 \\1:
41 : [ret] "={$2}" (-> u32),
42 : [number] "{$2}" (@intFromEnum(number)),
43 [arg1] "{$4}" (arg1),
44 : .{ .r1 = true, .r3 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
45}
46
47pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 {
48 return asm volatile (
49 \\ syscall
50 \\ beq $a3, $zero, 1f
51 \\ blez $v0, 1f
52 \\ subu $v0, $zero, $v0
53 \\1:
54 : [ret] "={$2}" (-> u32),
55 : [number] "{$2}" (@intFromEnum(number)),
56 [arg1] "{$4}" (arg1),
57 [arg2] "{$5}" (arg2),
58 : .{ .r1 = true, .r3 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
59}
60
61pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 {
62 return asm volatile (
63 \\ syscall
64 \\ beq $a3, $zero, 1f
65 \\ blez $v0, 1f
66 \\ subu $v0, $zero, $v0
67 \\1:
68 : [ret] "={$2}" (-> u32),
69 : [number] "{$2}" (@intFromEnum(number)),
70 [arg1] "{$4}" (arg1),
71 [arg2] "{$5}" (arg2),
72 [arg3] "{$6}" (arg3),
73 : .{ .r1 = true, .r3 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
74}
75
76pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
77 return asm volatile (
78 \\ syscall
79 \\ beq $a3, $zero, 1f
80 \\ blez $v0, 1f
81 \\ subu $v0, $zero, $v0
82 \\1:
83 : [ret] "={$2}" (-> u32),
84 : [number] "{$2}" (@intFromEnum(number)),
85 [arg1] "{$4}" (arg1),
86 [arg2] "{$5}" (arg2),
87 [arg3] "{$6}" (arg3),
88 [arg4] "{$7}" (arg4),
89 : .{ .r1 = true, .r3 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
90}
91
92pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 {
93 return asm volatile (
94 \\ syscall
95 \\ beq $a3, $zero, 1f
96 \\ blez $v0, 1f
97 \\ subu $v0, $zero, $v0
98 \\1:
99 : [ret] "={$2}" (-> u32),
100 : [number] "{$2}" (@intFromEnum(number)),
101 [arg1] "{$4}" (arg1),
102 [arg2] "{$5}" (arg2),
103 [arg3] "{$6}" (arg3),
104 [arg4] "{$7}" (arg4),
105 [arg5] "{$8}" (arg5),
106 : .{ .r1 = true, .r3 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
107}
108
109pub fn syscall6(
110 number: SYS,
111 arg1: u32,
112 arg2: u32,
113 arg3: u32,
114 arg4: u32,
115 arg5: u32,
116 arg6: u32,
117) u32 {
118 return asm volatile (
119 \\ syscall
120 \\ beq $a3, $zero, 1f
121 \\ blez $v0, 1f
122 \\ subu $v0, $zero, $v0
123 \\1:
124 : [ret] "={$2}" (-> u32),
125 : [number] "{$2}" (@intFromEnum(number)),
126 [arg1] "{$4}" (arg1),
127 [arg2] "{$5}" (arg2),
128 [arg3] "{$6}" (arg3),
129 [arg4] "{$7}" (arg4),
130 [arg5] "{$8}" (arg5),
131 [arg6] "{$9}" (arg6),
132 : .{ .r1 = true, .r3 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
133}
134
135pub fn clone() callconv(.naked) u32 {
136 // __clone(func, stack, flags, arg, ptid, tls, ctid)
137 // a0, a1, a2, a3, a4, a5, a6
138 //
139 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
140 // v0 a0, a1, a2, a3, a4
141 asm volatile (
142 \\ # Save function pointer and argument pointer on new thread stack
143 \\ and $a1, $a1, -16
144 \\ subu $a1, $a1, 16
145 \\ sw $a0, 0($a1)
146 \\ sw $a3, 4($a1)
147 \\
148 \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid)
149 \\ move $a0, $a2
150 \\ move $a2, $a4
151 \\ move $a3, $a5
152 \\ move $a4, $a6
153 \\ li $v0, 6055 # SYS_clone
154 \\ syscall
155 \\ beq $a3, $zero, 1f
156 \\ blez $v0, 2f
157 \\ subu $v0, $zero, $v0
158 \\ b 2f
159 \\1:
160 \\ beq $v0, $zero, 3f
161 \\2:
162 \\ jr $ra
163 \\3:
164 );
165 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
166 \\ .cfi_undefined $ra
167 );
168 asm volatile (
169 \\ move $fp, $zero
170 \\ move $ra, $zero
171 \\
172 \\ ld $t9, 0($sp)
173 \\ ld $a0, 4($sp)
174 \\ jalr $t9
175 \\
176 \\ move $a0, $v0
177 \\ li $v0, 6058 # SYS_exit
178 \\ syscall
179 );
180}
181
182pub const VDSO = struct {
183 pub const CGT_SYM = "__vdso_clock_gettime";
184 pub const CGT_VER = "LINUX_2.6";
185};
186
187pub const blksize_t = u32;
188pub const nlink_t = u32;
189pub const time_t = i32;
190pub const mode_t = u32;
191pub const off_t = i64;
192pub const ino_t = u64;
193pub const dev_t = u64;
194pub const blkcnt_t = i64;
195
196// The `stat` definition used by the Linux kernel.
197pub const Stat = extern struct {
198 dev: dev_t,
199 __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32).
200 ino: ino_t,
201 mode: mode_t,
202 nlink: nlink_t,
203 uid: std.os.linux.uid_t,
204 gid: std.os.linux.gid_t,
205 rdev: dev_t,
206 __pad1: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32).
207 size: off_t,
208 atim: u32,
209 atim_nsec: u32,
210 mtim: u32,
211 mtim_nsec: u32,
212 ctim: u32,
213 ctim_nsec: u32,
214 blksize: blksize_t,
215 __pad3: u32,
216 blocks: blkcnt_t,
217
218 pub fn atime(self: @This()) std.os.linux.timespec {
219 return .{
220 .sec = self.atim,
221 .nsec = self.atim_nsec,
222 };
223 }
224
225 pub fn mtime(self: @This()) std.os.linux.timespec {
226 return .{
227 .sec = self.mtim,
228 .nsec = self.mtim_nsec,
229 };
230 }
231
232 pub fn ctime(self: @This()) std.os.linux.timespec {
233 return .{
234 .sec = self.ctim,
235 .nsec = self.ctim_nsec,
236 };
237 }
238};