1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const SYS = std.os.linux.SYS;
4
5pub const syscall_arg_t = u32;
6
7pub fn syscall0(
8 number: SYS,
9) u32 {
10 return asm volatile ("svc #0"
11 : [ret] "={r0}" (-> u32),
12 : [number] "{r7}" (@backingInt(number)),
13 : .{ .memory = true });
14}
15
16pub fn syscall1(
17 number: SYS,
18 arg1: syscall_arg_t,
19) u32 {
20 return asm volatile ("svc #0"
21 : [ret] "={r0}" (-> u32),
22 : [number] "{r7}" (@backingInt(number)),
23 [arg1] "{r0}" (arg1),
24 : .{ .memory = true });
25}
26
27pub fn syscall2(
28 number: SYS,
29 arg1: syscall_arg_t,
30 arg2: syscall_arg_t,
31) u32 {
32 return asm volatile ("svc #0"
33 : [ret] "={r0}" (-> u32),
34 : [number] "{r7}" (@backingInt(number)),
35 [arg1] "{r0}" (arg1),
36 [arg2] "{r1}" (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) u32 {
46 return asm volatile ("svc #0"
47 : [ret] "={r0}" (-> u32),
48 : [number] "{r7}" (@backingInt(number)),
49 [arg1] "{r0}" (arg1),
50 [arg2] "{r1}" (arg2),
51 [arg3] "{r2}" (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) u32 {
62 return asm volatile ("svc #0"
63 : [ret] "={r0}" (-> u32),
64 : [number] "{r7}" (@backingInt(number)),
65 [arg1] "{r0}" (arg1),
66 [arg2] "{r1}" (arg2),
67 [arg3] "{r2}" (arg3),
68 [arg4] "{r3}" (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) u32 {
80 return asm volatile ("svc #0"
81 : [ret] "={r0}" (-> u32),
82 : [number] "{r7}" (@backingInt(number)),
83 [arg1] "{r0}" (arg1),
84 [arg2] "{r1}" (arg2),
85 [arg3] "{r2}" (arg3),
86 [arg4] "{r3}" (arg4),
87 [arg5] "{r4}" (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) u32 {
100 return asm volatile ("svc #0"
101 : [ret] "={r0}" (-> u32),
102 : [number] "{r7}" (@backingInt(number)),
103 [arg1] "{r0}" (arg1),
104 [arg2] "{r1}" (arg2),
105 [arg3] "{r2}" (arg3),
106 [arg4] "{r3}" (arg4),
107 [arg5] "{r4}" (arg5),
108 [arg6] "{r5}" (arg6),
109 : .{ .memory = true });
110}
111
112pub fn clone() callconv(.naked) u32 {
113 // __clone(func, stack, flags, arg, ptid, tls, ctid)
114 // r0, r1, r2, r3, +0, +4, +8
115 //
116 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
117 // r7 r0, r1, r2, r3, r4
118 asm volatile (
119 \\ stmfd sp!,{r4,r5,r6,r7}
120 \\ mov r7,#120 // SYS_clone
121 \\ mov r6,r3
122 \\ mov r5,r0
123 \\ mov r0,r2
124 \\ and r1,r1,#-16
125 \\ ldr r2,[sp,#16]
126 \\ ldr r3,[sp,#20]
127 \\ ldr r4,[sp,#24]
128 \\ svc 0
129 \\ tst r0,r0
130 \\ beq 1f
131 \\ ldmfd sp!,{r4,r5,r6,r7}
132 \\ bx lr
133 \\
134 \\ // https://github.com/llvm/llvm-project/issues/115891
135 \\1:
136 \\ mov r7, #0
137 \\ mov r11, #0
138 \\ mov lr, #0
139 \\
140 \\ mov r0,r6
141 \\ bl 3f
142 \\ mov r7,#1 // SYS_exit
143 \\ svc 0
144 \\
145 \\3:
146 \\ bx r5
147 );
148}
149
150pub fn restore() callconv(.naked) noreturn {
151 asm volatile (
152 \\ mov r7, %[number]
153 \\ svc #0
154 :
155 : [number] "I" (@backingInt(SYS.sigreturn)),
156 );
157}
158
159pub fn restore_rt() callconv(.naked) noreturn {
160 asm volatile (
161 \\ mov r7, %[number]
162 \\ svc #0
163 :
164 : [number] "I" (@backingInt(SYS.rt_sigreturn)),
165 );
166}
167
168pub const VDSO = struct {
169 pub const CGT_SYM = "__vdso_clock_gettime";
170 pub const CGT_VER = "LINUX_2.6";
171};
172
173pub const time_t = i32;