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 ("svc #0"
7 : [ret] "={r0}" (-> u32),
8 : [number] "{r7}" (@intFromEnum(number)),
9 : .{ .memory = true });
10}
11
12pub fn syscall1(number: SYS, arg1: u32) u32 {
13 return asm volatile ("svc #0"
14 : [ret] "={r0}" (-> u32),
15 : [number] "{r7}" (@intFromEnum(number)),
16 [arg1] "{r0}" (arg1),
17 : .{ .memory = true });
18}
19
20pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 {
21 return asm volatile ("svc #0"
22 : [ret] "={r0}" (-> u32),
23 : [number] "{r7}" (@intFromEnum(number)),
24 [arg1] "{r0}" (arg1),
25 [arg2] "{r1}" (arg2),
26 : .{ .memory = true });
27}
28
29pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 {
30 return asm volatile ("svc #0"
31 : [ret] "={r0}" (-> u32),
32 : [number] "{r7}" (@intFromEnum(number)),
33 [arg1] "{r0}" (arg1),
34 [arg2] "{r1}" (arg2),
35 [arg3] "{r2}" (arg3),
36 : .{ .memory = true });
37}
38
39pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
40 return asm volatile ("svc #0"
41 : [ret] "={r0}" (-> u32),
42 : [number] "{r7}" (@intFromEnum(number)),
43 [arg1] "{r0}" (arg1),
44 [arg2] "{r1}" (arg2),
45 [arg3] "{r2}" (arg3),
46 [arg4] "{r3}" (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 ("svc #0"
52 : [ret] "={r0}" (-> u32),
53 : [number] "{r7}" (@intFromEnum(number)),
54 [arg1] "{r0}" (arg1),
55 [arg2] "{r1}" (arg2),
56 [arg3] "{r2}" (arg3),
57 [arg4] "{r3}" (arg4),
58 [arg5] "{r4}" (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 ("svc #0"
72 : [ret] "={r0}" (-> u32),
73 : [number] "{r7}" (@intFromEnum(number)),
74 [arg1] "{r0}" (arg1),
75 [arg2] "{r1}" (arg2),
76 [arg3] "{r2}" (arg3),
77 [arg4] "{r3}" (arg4),
78 [arg5] "{r4}" (arg5),
79 [arg6] "{r5}" (arg6),
80 : .{ .memory = true });
81}
82
83pub fn clone() callconv(.naked) u32 {
84 // __clone(func, stack, flags, arg, ptid, tls, ctid)
85 // r0, r1, r2, r3, +0, +4, +8
86 //
87 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
88 // r7 r0, r1, r2, r3, r4
89 asm volatile (
90 \\ stmfd sp!,{r4,r5,r6,r7}
91 \\ mov r7,#120 // SYS_clone
92 \\ mov r6,r3
93 \\ mov r5,r0
94 \\ mov r0,r2
95 \\ and r1,r1,#-16
96 \\ ldr r2,[sp,#16]
97 \\ ldr r3,[sp,#20]
98 \\ ldr r4,[sp,#24]
99 \\ svc 0
100 \\ tst r0,r0
101 \\ beq 1f
102 \\ ldmfd sp!,{r4,r5,r6,r7}
103 \\ bx lr
104 \\
105 \\ // https://github.com/llvm/llvm-project/issues/115891
106 \\1: mov r7, #0
107 \\ mov r11, #0
108 \\ mov lr, #0
109 \\
110 \\ mov r0,r6
111 \\ bl 3f
112 \\ mov r7,#1 // SYS_exit
113 \\ svc 0
114 \\
115 \\3: bx r5
116 );
117}
118
119pub fn restore() callconv(.naked) noreturn {
120 switch (builtin.zig_backend) {
121 .stage2_c => asm volatile (
122 \\ mov r7, %[number]
123 \\ svc #0
124 :
125 : [number] "I" (@intFromEnum(SYS.sigreturn)),
126 ),
127 else => asm volatile (
128 \\ svc #0
129 :
130 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),
131 ),
132 }
133}
134
135pub fn restore_rt() callconv(.naked) noreturn {
136 switch (builtin.zig_backend) {
137 .stage2_c => asm volatile (
138 \\ mov r7, %[number]
139 \\ svc #0
140 :
141 : [number] "I" (@intFromEnum(SYS.rt_sigreturn)),
142 ),
143 else => asm volatile (
144 \\ svc #0
145 :
146 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),
147 ),
148 }
149}
150
151pub const VDSO = struct {
152 pub const CGT_SYM = "__vdso_clock_gettime";
153 pub const CGT_VER = "LINUX_2.6";
154};
155
156pub const HWCAP = struct {
157 pub const SWP = 1 << 0;
158 pub const HALF = 1 << 1;
159 pub const THUMB = 1 << 2;
160 pub const @"26BIT" = 1 << 3;
161 pub const FAST_MULT = 1 << 4;
162 pub const FPA = 1 << 5;
163 pub const VFP = 1 << 6;
164 pub const EDSP = 1 << 7;
165 pub const JAVA = 1 << 8;
166 pub const IWMMXT = 1 << 9;
167 pub const CRUNCH = 1 << 10;
168 pub const THUMBEE = 1 << 11;
169 pub const NEON = 1 << 12;
170 pub const VFPv3 = 1 << 13;
171 pub const VFPv3D16 = 1 << 14;
172 pub const TLS = 1 << 15;
173 pub const VFPv4 = 1 << 16;
174 pub const IDIVA = 1 << 17;
175 pub const IDIVT = 1 << 18;
176 pub const VFPD32 = 1 << 19;
177 pub const IDIV = IDIVA | IDIVT;
178 pub const LPAE = 1 << 20;
179 pub const EVTSTRM = 1 << 21;
180};
181
182pub const blksize_t = i32;
183pub const nlink_t = u32;
184pub const time_t = i32;
185pub const mode_t = u32;
186pub const off_t = i64;
187pub const ino_t = u64;
188pub const dev_t = u64;
189pub const blkcnt_t = i64;
190
191// The `stat` definition used by the Linux kernel.
192pub const Stat = extern struct {
193 dev: dev_t,
194 __dev_padding: u32,
195 __ino_truncated: u32,
196 mode: mode_t,
197 nlink: nlink_t,
198 uid: std.os.linux.uid_t,
199 gid: std.os.linux.gid_t,
200 rdev: dev_t,
201 __rdev_padding: u32,
202 size: off_t,
203 blksize: blksize_t,
204 blocks: blkcnt_t,
205 atim: std.os.linux.timespec,
206 mtim: std.os.linux.timespec,
207 ctim: std.os.linux.timespec,
208 ino: ino_t,
209
210 pub fn atime(self: @This()) std.os.linux.timespec {
211 return self.atim;
212 }
213
214 pub fn mtime(self: @This()) std.os.linux.timespec {
215 return self.mtim;
216 }
217
218 pub fn ctime(self: @This()) std.os.linux.timespec {
219 return self.ctim;
220 }
221};