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 ("trap #0"
7 : [ret] "={d0}" (-> u32),
8 : [number] "{d0}" (@intFromEnum(number)),
9 : .{ .memory = true });
10}
11
12pub fn syscall1(number: SYS, arg1: u32) u32 {
13 return asm volatile ("trap #0"
14 : [ret] "={d0}" (-> u32),
15 : [number] "{d0}" (@intFromEnum(number)),
16 [arg1] "{d1}" (arg1),
17 : .{ .memory = true });
18}
19
20pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 {
21 return asm volatile ("trap #0"
22 : [ret] "={d0}" (-> u32),
23 : [number] "{d0}" (@intFromEnum(number)),
24 [arg1] "{d1}" (arg1),
25 [arg2] "{d2}" (arg2),
26 : .{ .memory = true });
27}
28
29pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 {
30 return asm volatile ("trap #0"
31 : [ret] "={d0}" (-> u32),
32 : [number] "{d0}" (@intFromEnum(number)),
33 [arg1] "{d1}" (arg1),
34 [arg2] "{d2}" (arg2),
35 [arg3] "{d3}" (arg3),
36 : .{ .memory = true });
37}
38
39pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
40 return asm volatile ("trap #0"
41 : [ret] "={d0}" (-> u32),
42 : [number] "{d0}" (@intFromEnum(number)),
43 [arg1] "{d1}" (arg1),
44 [arg2] "{d2}" (arg2),
45 [arg3] "{d3}" (arg3),
46 [arg4] "{d4}" (arg4),
47 : .{ .memory = true });
48}
49
50pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 {
51 return asm volatile ("trap #0"
52 : [ret] "={d0}" (-> u32),
53 : [number] "{d0}" (@intFromEnum(number)),
54 [arg1] "{d1}" (arg1),
55 [arg2] "{d2}" (arg2),
56 [arg3] "{d3}" (arg3),
57 [arg4] "{d4}" (arg4),
58 [arg5] "{d5}" (arg5),
59 : .{ .memory = true });
60}
61
62pub fn syscall6(
63 number: SYS,
64 arg1: u32,
65 arg2: u32,
66 arg3: u32,
67 arg4: u32,
68 arg5: u32,
69 arg6: u32,
70) u32 {
71 return asm volatile ("trap #0"
72 : [ret] "={d0}" (-> u32),
73 : [number] "{d0}" (@intFromEnum(number)),
74 [arg1] "{d1}" (arg1),
75 [arg2] "{d2}" (arg2),
76 [arg3] "{d3}" (arg3),
77 [arg4] "{d4}" (arg4),
78 [arg5] "{d5}" (arg5),
79 [arg6] "{a0}" (arg6),
80 : .{ .memory = true });
81}
82
83pub fn clone() callconv(.naked) u32 {
84 // __clone(func, stack, flags, arg, ptid, tls, ctid)
85 // +4, +8, +12, +16, +20, +24, +28
86 //
87 // syscall(SYS_clone, flags, stack, ptid, ctid, tls)
88 // d0, d1, d2, d3, d4, d5
89 asm volatile (
90 \\ // Save callee-saved registers.
91 \\ movem.l %%d2-%%d5, -(%%sp) // sp -= 16
92 \\
93 \\ // Save func and arg.
94 \\ move.l 16+4(%%sp), %%a0
95 \\ move.l 16+16(%%sp), %%a1
96 \\
97 \\ // d0 = syscall(d0, d1, d2, d3, d4, d5)
98 \\ move.l #120, %%d0 // SYS_clone
99 \\ move.l 16+12(%%sp), %%d1
100 \\ move.l 16+8(%%sp), %%d2
101 \\ move.l 16+20(%%sp), %%d3
102 \\ move.l 16+28(%%sp), %%d4
103 \\ move.l 16+24(%%sp), %%d5
104 \\ and.l #-4, %%d2 // Align the child stack pointer.
105 \\ trap #0
106 \\
107 \\ // Are we in the parent or child?
108 \\ tst.l %%d0
109 \\ beq 1f
110 \\ // Parent:
111 \\
112 \\ // Restore callee-saved registers and return.
113 \\ movem.l (%%sp)+, %%d2-%%d5 // sp += 16
114 \\ rts
115 \\
116 \\ // Child:
117 \\1:
118 );
119 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
120 \\ .cfi_undefined %%pc
121 );
122 asm volatile (
123 \\ suba.l %%fp, %%fp
124 \\
125 \\ // d0 = func(a1)
126 \\ move.l %%a1, -(%%sp)
127 \\ jsr (%%a0)
128 \\
129 \\ // syscall(d0, d1)
130 \\ move.l %%d0, %%d1
131 \\ move.l #1, %%d0 // SYS_exit
132 \\ trap #0
133 );
134}
135
136pub const restore = restore_rt;
137
138pub fn restore_rt() callconv(.naked) noreturn {
139 asm volatile ("trap #0"
140 :
141 : [number] "{d0}" (@intFromEnum(SYS.rt_sigreturn)),
142 );
143}
144
145pub const blksize_t = i32;
146pub const nlink_t = u32;
147pub const time_t = i32;
148pub const mode_t = u32;
149pub const off_t = i64;
150pub const ino_t = u64;
151pub const dev_t = u64;
152pub const blkcnt_t = i64;
153
154pub const Stat = extern struct {
155 dev: dev_t,
156 __pad: i16,
157 __ino_truncated: i32,
158 mode: mode_t,
159 nlink: nlink_t,
160 uid: std.os.linux.uid_t,
161 gid: std.os.linux.gid_t,
162 rdev: dev_t,
163 __pad2: i16,
164 size: off_t,
165 blksize: blksize_t,
166 blocks: blkcnt_t,
167 atim: std.os.linux.timespec,
168 mtim: std.os.linux.timespec,
169 ctim: std.os.linux.timespec,
170 ino: ino_t,
171
172 pub fn atime(self: @This()) std.os.linux.timespec {
173 return self.atim;
174 }
175
176 pub fn mtime(self: @This()) std.os.linux.timespec {
177 return self.mtim;
178 }
179
180 pub fn ctime(self: @This()) std.os.linux.timespec {
181 return self.ctim;
182 }
183};
184
185// No VDSO used as of glibc 112a0ae18b831bf31f44d81b82666980312511d6.
186pub const VDSO = void;