1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const SYS = std.os.linux.SYS;
4
5pub const syscall_arg_t = u64;
6
7pub fn syscall0(
8 number: SYS,
9) u64 {
10 return asm volatile ("svc 0"
11 : [ret] "={r2}" (-> u64),
12 : [number] "{r1}" (@backingInt(number)),
13 : .{ .memory = true });
14}
15
16pub fn syscall1(
17 number: SYS,
18 arg1: syscall_arg_t,
19) u64 {
20 return asm volatile ("svc 0"
21 : [ret] "={r2}" (-> u64),
22 : [number] "{r1}" (@backingInt(number)),
23 [arg1] "{r2}" (arg1),
24 : .{ .memory = true });
25}
26
27pub fn syscall2(
28 number: SYS,
29 arg1: syscall_arg_t,
30 arg2: syscall_arg_t,
31) u64 {
32 return asm volatile ("svc 0"
33 : [ret] "={r2}" (-> u64),
34 : [number] "{r1}" (@backingInt(number)),
35 [arg1] "{r2}" (arg1),
36 [arg2] "{r3}" (arg2),
37 : .{ .memory = true });
38}
39
40pub fn syscall3(
41 number: SYS,
42 arg1: syscall_arg_t,
43 arg2: syscall_arg_t,
44 arg3: syscall_arg_t,
45) u64 {
46 return asm volatile ("svc 0"
47 : [ret] "={r2}" (-> u64),
48 : [number] "{r1}" (@backingInt(number)),
49 [arg1] "{r2}" (arg1),
50 [arg2] "{r3}" (arg2),
51 [arg3] "{r4}" (arg3),
52 : .{ .memory = true });
53}
54
55pub fn syscall4(
56 number: SYS,
57 arg1: syscall_arg_t,
58 arg2: syscall_arg_t,
59 arg3: syscall_arg_t,
60 arg4: syscall_arg_t,
61) u64 {
62 return asm volatile ("svc 0"
63 : [ret] "={r2}" (-> u64),
64 : [number] "{r1}" (@backingInt(number)),
65 [arg1] "{r2}" (arg1),
66 [arg2] "{r3}" (arg2),
67 [arg3] "{r4}" (arg3),
68 [arg4] "{r5}" (arg4),
69 : .{ .memory = true });
70}
71
72pub fn syscall5(
73 number: SYS,
74 arg1: syscall_arg_t,
75 arg2: syscall_arg_t,
76 arg3: syscall_arg_t,
77 arg4: syscall_arg_t,
78 arg5: syscall_arg_t,
79) u64 {
80 return asm volatile ("svc 0"
81 : [ret] "={r2}" (-> u64),
82 : [number] "{r1}" (@backingInt(number)),
83 [arg1] "{r2}" (arg1),
84 [arg2] "{r3}" (arg2),
85 [arg3] "{r4}" (arg3),
86 [arg4] "{r5}" (arg4),
87 [arg5] "{r6}" (arg5),
88 : .{ .memory = true });
89}
90
91pub fn syscall6(
92 number: SYS,
93 arg1: syscall_arg_t,
94 arg2: syscall_arg_t,
95 arg3: syscall_arg_t,
96 arg4: syscall_arg_t,
97 arg5: syscall_arg_t,
98 arg6: syscall_arg_t,
99) u64 {
100 return asm volatile ("svc 0"
101 : [ret] "={r2}" (-> u64),
102 : [number] "{r1}" (@backingInt(number)),
103 [arg1] "{r2}" (arg1),
104 [arg2] "{r3}" (arg2),
105 [arg3] "{r4}" (arg3),
106 [arg4] "{r5}" (arg4),
107 [arg5] "{r6}" (arg5),
108 [arg6] "{r7}" (arg6),
109 : .{ .memory = true });
110}
111
112pub fn clone() callconv(.naked) u64 {
113 asm volatile (
114 \\ # int clone(
115 \\ # fn, a = r2
116 \\ # stack, b = r3
117 \\ # flags, c = r4
118 \\ # arg, d = r5
119 \\ # ptid, e = r6
120 \\ # tls, f = *(r15+160)
121 \\ # ctid) g = *(r15+168)
122 \\ #
123 \\ # pseudo C code:
124 \\ # tid = syscall(SYS_clone,b,c,e,g,f);
125 \\ # if (!tid) syscall(SYS_exit, a(d));
126 \\ # return tid;
127 \\
128 \\ # preserve call-saved register used as syscall arg
129 \\ stg %%r6, 48(%%r15)
130 \\
131 \\ # create initial stack frame for new thread
132 \\ nill %%r3, 0xfff8
133 \\ aghi %%r3, -160
134 \\ lghi %%r0, 0
135 \\ stg %%r0, 0(%%r3)
136 \\
137 \\ # save fn and arg to child stack
138 \\ stg %%r2, 8(%%r3)
139 \\ stg %%r5, 16(%%r3)
140 \\
141 \\ # shuffle args into correct registers and call SYS_clone
142 \\ lgr %%r2, %%r3
143 \\ lgr %%r3, %%r4
144 \\ lgr %%r4, %%r6
145 \\ lg %%r5, 168(%%r15)
146 \\ lg %%r6, 160(%%r15)
147 \\ svc 120
148 \\
149 \\ # restore call-saved register
150 \\ lg %%r6, 48(%%r15)
151 \\
152 \\ # if error or if we're the parent, return
153 \\ ltgr %%r2, %%r2
154 \\ bnzr %%r14
155 \\
156 \\ # we're the child
157 );
158 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
159 \\ .cfi_undefined %%r14
160 );
161 asm volatile (
162 \\ lghi %%r11, 0
163 \\ lghi %%r14, 0
164 \\
165 \\ # call fn(arg)
166 \\ lg %%r1, 8(%%r15)
167 \\ lg %%r2, 16(%%r15)
168 \\ basr %%r14, %%r1
169 \\
170 \\ # call SYS_exit. exit code is already in r2 from fn return value
171 \\ svc 1
172 );
173}
174
175pub fn restore() callconv(.naked) noreturn {
176 asm volatile (
177 \\ lghi %%r1, %[number]
178 \\ svc 0
179 :
180 : [number] "K" (@backingInt(SYS.sigreturn)),
181 );
182}
183
184pub fn restore_rt() callconv(.naked) noreturn {
185 asm volatile (
186 \\ lghi %%r1, %[number]
187 \\ svc 0
188 :
189 : [number] "K" (@backingInt(SYS.rt_sigreturn)),
190 );
191}
192
193pub const time_t = i64;
194
195pub const VDSO = struct {
196 pub const CGT_SYM = "__kernel_clock_gettime";
197 pub const CGT_VER = "LINUX_2.6.29";
198};