master
1//! The syscall interface is identical to the ARM one but we're facing an extra
2//! challenge: r7, the register where the syscall number is stored, may be
3//! reserved for the frame pointer.
4//! Save and restore r7 around the syscall without touching the stack pointer not
5//! to break the frame chain.
6const std = @import("../../std.zig");
7const SYS = std.os.linux.SYS;
8
9pub fn syscall0(number: SYS) u32 {
10 var buf: [2]u32 = .{ @intFromEnum(number), undefined };
11 return asm volatile (
12 \\ str r7, [%[tmp], #4]
13 \\ ldr r7, [%[tmp]]
14 \\ svc #0
15 \\ ldr r7, [%[tmp], #4]
16 : [ret] "={r0}" (-> u32),
17 : [tmp] "{r1}" (&buf),
18 : .{ .memory = true });
19}
20
21pub fn syscall1(number: SYS, arg1: u32) u32 {
22 var buf: [2]u32 = .{ @intFromEnum(number), undefined };
23 return asm volatile (
24 \\ str r7, [%[tmp], #4]
25 \\ ldr r7, [%[tmp]]
26 \\ svc #0
27 \\ ldr r7, [%[tmp], #4]
28 : [ret] "={r0}" (-> u32),
29 : [tmp] "{r1}" (&buf),
30 [arg1] "{r0}" (arg1),
31 : .{ .memory = true });
32}
33
34pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 {
35 var buf: [2]u32 = .{ @intFromEnum(number), undefined };
36 return asm volatile (
37 \\ str r7, [%[tmp], #4]
38 \\ ldr r7, [%[tmp]]
39 \\ svc #0
40 \\ ldr r7, [%[tmp], #4]
41 : [ret] "={r0}" (-> u32),
42 : [tmp] "{r2}" (&buf),
43 [arg1] "{r0}" (arg1),
44 [arg2] "{r1}" (arg2),
45 : .{ .memory = true });
46}
47
48pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 {
49 var buf: [2]u32 = .{ @intFromEnum(number), undefined };
50 return asm volatile (
51 \\ str r7, [%[tmp], #4]
52 \\ ldr r7, [%[tmp]]
53 \\ svc #0
54 \\ ldr r7, [%[tmp], #4]
55 : [ret] "={r0}" (-> u32),
56 : [tmp] "{r3}" (&buf),
57 [arg1] "{r0}" (arg1),
58 [arg2] "{r1}" (arg2),
59 [arg3] "{r2}" (arg3),
60 : .{ .memory = true });
61}
62
63pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
64 var buf: [2]u32 = .{ @intFromEnum(number), undefined };
65 return asm volatile (
66 \\ str r7, [%[tmp], #4]
67 \\ ldr r7, [%[tmp]]
68 \\ svc #0
69 \\ ldr r7, [%[tmp], #4]
70 : [ret] "={r0}" (-> u32),
71 : [tmp] "{r4}" (&buf),
72 [arg1] "{r0}" (arg1),
73 [arg2] "{r1}" (arg2),
74 [arg3] "{r2}" (arg3),
75 [arg4] "{r3}" (arg4),
76 : .{ .memory = true });
77}
78
79pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 {
80 var buf: [2]u32 = .{ @intFromEnum(number), undefined };
81 return asm volatile (
82 \\ str r7, [%[tmp], #4]
83 \\ ldr r7, [%[tmp]]
84 \\ svc #0
85 \\ ldr r7, [%[tmp], #4]
86 : [ret] "={r0}" (-> u32),
87 : [tmp] "{r5}" (&buf),
88 [arg1] "{r0}" (arg1),
89 [arg2] "{r1}" (arg2),
90 [arg3] "{r2}" (arg3),
91 [arg4] "{r3}" (arg4),
92 [arg5] "{r4}" (arg5),
93 : .{ .memory = true });
94}
95
96pub fn syscall6(
97 number: SYS,
98 arg1: u32,
99 arg2: u32,
100 arg3: u32,
101 arg4: u32,
102 arg5: u32,
103 arg6: u32,
104) u32 {
105 var buf: [2]u32 = .{ @intFromEnum(number), undefined };
106 return asm volatile (
107 \\ str r7, [%[tmp], #4]
108 \\ ldr r7, [%[tmp]]
109 \\ svc #0
110 \\ ldr r7, [%[tmp], #4]
111 : [ret] "={r0}" (-> u32),
112 : [tmp] "{r6}" (&buf),
113 [arg1] "{r0}" (arg1),
114 [arg2] "{r1}" (arg2),
115 [arg3] "{r2}" (arg3),
116 [arg4] "{r3}" (arg4),
117 [arg5] "{r4}" (arg5),
118 [arg6] "{r5}" (arg6),
119 : .{ .memory = true });
120}
121
122pub const clone = @import("arm.zig").clone;
123
124pub fn restore() callconv(.naked) noreturn {
125 asm volatile (
126 \\ mov r7, %[number]
127 \\ svc #0
128 :
129 : [number] "I" (@intFromEnum(SYS.sigreturn)),
130 );
131}
132
133pub fn restore_rt() callconv(.naked) noreturn {
134 asm volatile (
135 \\ mov r7, %[number]
136 \\ svc #0
137 :
138 : [number] "I" (@intFromEnum(SYS.rt_sigreturn)),
139 );
140}