]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 1999-2011 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. | |
29 | * | |
30 | * File: SYS.h | |
31 | * | |
32 | * Definition of the user side of the UNIX system call interface | |
33 | * for M98K. | |
34 | * | |
35 | * Errors are flagged by the location of the trap return (ie., which | |
36 | * instruction is executed upon rfi): | |
37 | * | |
38 | * SC PC + 4: Error (typically branch to cerror()) | |
39 | * SC PC + 8: Success | |
40 | * | |
41 | * HISTORY | |
42 | * 18-Nov-92 Ben Fathi (benf@next.com) | |
43 | * Ported to m98k. | |
44 | * | |
45 | * 9-Jan-92 Peter King (king@next.com) | |
46 | * Created. | |
47 | */ | |
48 | ||
49 | #include <sys/syscall.h> | |
50 | ||
51 | #if defined(__i386__) | |
52 | ||
53 | #include <architecture/i386/asm_help.h> | |
54 | #include <mach/i386/syscall_sw.h> | |
55 | ||
56 | /* | |
57 | * We have two entry points. int's is used for syscalls which need to preserve | |
58 | * %ecx across the call, or return a 64-bit value in %eax:%edx. sysenter is used | |
59 | * for the majority of syscalls which just return a value in %eax. | |
60 | */ | |
61 | ||
62 | #define UNIX_SYSCALL_SYSENTER call __sysenter_trap | |
63 | #define UNIX_SYSCALL(name, nargs) \ | |
64 | .globl tramp_cerror ;\ | |
65 | LEAF(_##name, 0) ;\ | |
66 | movl $ SYS_##name, %eax ;\ | |
67 | UNIX_SYSCALL_SYSENTER ;\ | |
68 | jnb 2f ;\ | |
69 | BRANCH_EXTERN(tramp_cerror) ;\ | |
70 | 2: | |
71 | ||
72 | #define UNIX_SYSCALL_INT(name, nargs) \ | |
73 | .globl tramp_cerror ;\ | |
74 | LEAF(_##name, 0) ;\ | |
75 | movl $ SYS_##name, %eax ;\ | |
76 | UNIX_SYSCALL_TRAP ;\ | |
77 | jnb 2f ;\ | |
78 | BRANCH_EXTERN(tramp_cerror) ;\ | |
79 | 2: | |
80 | ||
81 | #if defined(__SYSCALL_32BIT_ARG_BYTES) && ((__SYSCALL_32BIT_ARG_BYTES >= 4) && (__SYSCALL_32BIT_ARG_BYTES <= 20)) | |
82 | #define UNIX_SYSCALL_NONAME(name, nargs, cerror) \ | |
83 | movl $(SYS_##name | (__SYSCALL_32BIT_ARG_BYTES << I386_SYSCALL_ARG_BYTES_SHIFT)), %eax ;\ | |
84 | UNIX_SYSCALL_SYSENTER ;\ | |
85 | jnb 2f ;\ | |
86 | BRANCH_EXTERN(tramp_##cerror) ;\ | |
87 | 2: | |
88 | #else /* __SYSCALL_32BIT_ARG_BYTES < 4 || > 20 */ | |
89 | #define UNIX_SYSCALL_NONAME(name, nargs, cerror) \ | |
90 | movl $ SYS_##name, %eax ;\ | |
91 | UNIX_SYSCALL_SYSENTER ;\ | |
92 | jnb 2f ;\ | |
93 | BRANCH_EXTERN(tramp_##cerror) ;\ | |
94 | 2: | |
95 | #endif | |
96 | ||
97 | #define UNIX_SYSCALL_INT_NONAME(name, nargs) \ | |
98 | .globl tramp_cerror_nocancel ;\ | |
99 | movl $ SYS_##name, %eax ;\ | |
100 | UNIX_SYSCALL_TRAP ;\ | |
101 | jnb 2f ;\ | |
102 | BRANCH_EXTERN(tramp_cerror_nocancel) ;\ | |
103 | 2: | |
104 | ||
105 | #define PSEUDO(pseudo, name, nargs, cerror) \ | |
106 | LEAF(pseudo, 0) ;\ | |
107 | UNIX_SYSCALL_NONAME(name, nargs, cerror) | |
108 | ||
109 | #define PSEUDO_INT(pseudo, name, nargs) \ | |
110 | LEAF(pseudo, 0) ;\ | |
111 | UNIX_SYSCALL_INT_NONAME(name, nargs) | |
112 | ||
113 | #define __SYSCALL2(pseudo, name, nargs, cerror) \ | |
114 | PSEUDO(pseudo, name, nargs, cerror) ;\ | |
115 | ret | |
116 | ||
117 | #define __SYSCALL(pseudo, name, nargs) \ | |
118 | PSEUDO(pseudo, name, nargs, cerror) ;\ | |
119 | ret | |
120 | ||
121 | #define __SYSCALL_INT(pseudo, name, nargs) \ | |
122 | PSEUDO_INT(pseudo, name, nargs) ;\ | |
123 | ret | |
124 | ||
125 | #elif defined(__x86_64__) | |
126 | ||
127 | #include <architecture/i386/asm_help.h> | |
128 | #include <mach/i386/syscall_sw.h> | |
129 | ||
130 | #define UNIX_SYSCALL_SYSCALL \ | |
131 | movq %rcx, %r10 ;\ | |
132 | syscall | |
133 | ||
134 | #define UNIX_SYSCALL(name, nargs) \ | |
135 | .globl cerror ;\ | |
136 | LEAF(_##name, 0) ;\ | |
137 | movl $ SYSCALL_CONSTRUCT_UNIX(SYS_##name), %eax ;\ | |
138 | UNIX_SYSCALL_SYSCALL ;\ | |
139 | jnb 2f ;\ | |
140 | movq %rax, %rdi ;\ | |
141 | BRANCH_EXTERN(_cerror) ;\ | |
142 | 2: | |
143 | ||
144 | #define UNIX_SYSCALL_NONAME(name, nargs, cerror) \ | |
145 | .globl cerror ;\ | |
146 | movl $ SYSCALL_CONSTRUCT_UNIX(SYS_##name), %eax ;\ | |
147 | UNIX_SYSCALL_SYSCALL ;\ | |
148 | jnb 2f ;\ | |
149 | movq %rax, %rdi ;\ | |
150 | BRANCH_EXTERN(_##cerror) ;\ | |
151 | 2: | |
152 | ||
153 | #define PSEUDO(pseudo, name, nargs, cerror) \ | |
154 | LEAF(pseudo, 0) ;\ | |
155 | UNIX_SYSCALL_NONAME(name, nargs, cerror) | |
156 | ||
157 | #define __SYSCALL2(pseudo, name, nargs, cerror) \ | |
158 | PSEUDO(pseudo, name, nargs, cerror) ;\ | |
159 | ret | |
160 | ||
161 | #define __SYSCALL(pseudo, name, nargs) \ | |
162 | PSEUDO(pseudo, name, nargs, cerror) ;\ | |
163 | ret | |
164 | ||
165 | #elif defined(__arm__) | |
166 | ||
167 | #include <architecture/arm/asm_help.h> | |
168 | #include <mach/arm/syscall_sw.h> | |
169 | ||
170 | /* | |
171 | * ARM system call interface: | |
172 | * | |
173 | * swi 0x80 | |
174 | * args: r0-r6 | |
175 | * return code: r0 | |
176 | * on error, carry bit is set in the psr, otherwise carry bit is cleared. | |
177 | */ | |
178 | ||
179 | /* | |
180 | * Macros. | |
181 | */ | |
182 | ||
183 | /* | |
184 | * until we update the architecture project, these live here | |
185 | */ | |
186 | ||
187 | #if defined(__DYNAMIC__) | |
188 | #define MI_GET_ADDRESS(reg,var) \ | |
189 | ldr reg, 4f ;\ | |
190 | 3: ldr reg, [pc, reg] ;\ | |
191 | b 5f ;\ | |
192 | 4: .long 6f - (3b + 8) ;\ | |
193 | 5: ;\ | |
194 | .non_lazy_symbol_pointer ;\ | |
195 | 6: ;\ | |
196 | .indirect_symbol var ;\ | |
197 | .long 0 ;\ | |
198 | .text ;\ | |
199 | .align 2 | |
200 | #else | |
201 | #define MI_GET_ADDRESS(reg,var) \ | |
202 | ldr reg, 3f ;\ | |
203 | b 4f ;\ | |
204 | 3: .long var ;\ | |
205 | 4: | |
206 | #endif | |
207 | ||
208 | #if defined(__DYNAMIC__) | |
209 | #define MI_BRANCH_EXTERNAL(var) \ | |
210 | .globl var ;\ | |
211 | MI_GET_ADDRESS(ip, var) ;\ | |
212 | bx ip | |
213 | #else | |
214 | #define MI_BRANCH_EXTERNAL(var) ;\ | |
215 | .globl var ;\ | |
216 | b var | |
217 | #endif | |
218 | ||
219 | #if defined(__DYNAMIC__) | |
220 | #define MI_CALL_EXTERNAL(var) \ | |
221 | .globl var ;\ | |
222 | MI_GET_ADDRESS(ip,var) ;\ | |
223 | blx ip | |
224 | #else | |
225 | #define MI_CALL_EXTERNAL(var) \ | |
226 | .globl var ;\ | |
227 | bl var | |
228 | #endif | |
229 | ||
230 | #define MI_ENTRY_POINT(name) \ | |
231 | .text ;\ | |
232 | .align 2 ;\ | |
233 | .globl name ;\ | |
234 | name: | |
235 | ||
236 | /* load the syscall number into r12 and trap */ | |
237 | #define DO_SYSCALL(num) \ | |
238 | .if (((num) & 0xff) == (num)) ;\ | |
239 | mov r12, #(num) ;\ | |
240 | .elseif (((num) & 0x3fc) == (num)) ;\ | |
241 | mov r12, #(num) ;\ | |
242 | .else ;\ | |
243 | mov r12, #((num) & 0xffffff00) /* top half of the syscall number */ ;\ | |
244 | orr r12, r12, #((num) & 0xff) /* bottom half */ ;\ | |
245 | .endif ;\ | |
246 | swi #SWI_SYSCALL | |
247 | ||
248 | /* simple syscalls (0 to 4 args) */ | |
249 | #define SYSCALL_0to4(name, cerror) \ | |
250 | MI_ENTRY_POINT(_##name) ;\ | |
251 | DO_SYSCALL(SYS_##name) ;\ | |
252 | bxcc lr /* return if carry is clear (no error) */ ; \ | |
253 | 1: MI_BRANCH_EXTERNAL(_##cerror) | |
254 | ||
255 | /* syscalls with 5 args is different, because of the single arg register load */ | |
256 | #define SYSCALL_5(name, cerror) \ | |
257 | MI_ENTRY_POINT(_##name) ;\ | |
258 | mov ip, sp /* save a pointer to the args */ ; \ | |
259 | stmfd sp!, { r4-r5 } /* save r4-r5 */ ;\ | |
260 | ldr r4, [ip] /* load 5th arg */ ; \ | |
261 | DO_SYSCALL(SYS_##name) ;\ | |
262 | ldmfd sp!, { r4-r5 } /* restore r4-r5 */ ; \ | |
263 | bxcc lr /* return if carry is clear (no error) */ ; \ | |
264 | 1: MI_BRANCH_EXTERNAL(_##cerror) | |
265 | ||
266 | /* syscalls with 6 to 12 args. kernel may have to read from stack */ | |
267 | #define SYSCALL_6to12(name, save_regs, arg_regs, cerror) \ | |
268 | MI_ENTRY_POINT(_##name) ;\ | |
269 | mov ip, sp /* save a pointer to the args */ ; \ | |
270 | stmfd sp!, { save_regs } /* callee saved regs */ ;\ | |
271 | ldmia ip, { arg_regs } /* load arg regs */ ; \ | |
272 | DO_SYSCALL(SYS_##name) ;\ | |
273 | ldmfd sp!, { save_regs } /* restore callee saved regs */ ; \ | |
274 | bxcc lr /* return if carry is clear (no error) */ ; \ | |
275 | 1: MI_BRANCH_EXTERNAL(_##cerror) | |
276 | ||
277 | #define COMMA , | |
278 | ||
279 | #if __BIGGEST_ALIGNMENT__ > 4 | |
280 | ||
281 | /* For the armv7k ABI, the alignment requirements may add padding. So we | |
282 | * let the kernel figure it out and push extra on the stack to avoid un-needed | |
283 | * copy-ins */ | |
284 | ||
285 | /* We'll also use r8 for moving arguments */ | |
286 | ||
287 | #define SYSCALL_0(name) SYSCALL_0to4(name) | |
288 | #define SYSCALL_1(name) SYSCALL_0to4(name) | |
289 | #define SYSCALL_2(name) SYSCALL_0to4(name) | |
290 | #define SYSCALL_3(name) SYSCALL_0to4(name) | |
291 | #define SYSCALL_4(name) SYSCALL_6to12(name, r4-r5, r4-r5) | |
292 | #undef SYSCALL_5 | |
293 | #define SYSCALL_5(name) SYSCALL_6to12(name, r4-r5, r4-r5) | |
294 | #define SYSCALL_6(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) | |
295 | #define SYSCALL_7(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) | |
296 | #define SYSCALL_8(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) | |
297 | #define SYSCALL_12(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) | |
298 | ||
299 | #else // !(__BIGGEST_ALIGNMENT__ > 4) (the normal arm32 ABI case) | |
300 | ||
301 | #define SYSCALL_0(name) SYSCALL_0to4(name) | |
302 | #define SYSCALL_1(name) SYSCALL_0to4(name) | |
303 | #define SYSCALL_2(name) SYSCALL_0to4(name) | |
304 | #define SYSCALL_3(name) SYSCALL_0to4(name) | |
305 | #define SYSCALL_4(name) SYSCALL_0to4(name) | |
306 | /* SYSCALL_5 declared above */ | |
307 | #define SYSCALL_6(name) SYSCALL_6to12(name, r4-r5, r4-r5) | |
308 | #define SYSCALL_7(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6) | |
309 | #define SYSCALL_8(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6) /* 8th on stack */ | |
310 | #define SYSCALL_12(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6) /* 8th-12th on stack */ | |
311 | ||
312 | #endif // __BIGGEST_ALIGNMENT__ > 4 | |
313 | ||
314 | /* select the appropriate syscall code, based on the number of arguments */ | |
315 | #ifndef __SYSCALL_32BIT_ARG_BYTES | |
316 | #define SYSCALL(name, nargs, cerror) SYSCALL_##nargs(name, cerror) | |
317 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_##nargs(name, cerror) | |
318 | #else | |
319 | #if __SYSCALL_32BIT_ARG_BYTES < 20 | |
320 | #define SYSCALL(name, nargs, cerror) SYSCALL_0to4(name, cerror) | |
321 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
322 | #elif __SYSCALL_32BIT_ARG_BYTES == 20 | |
323 | #define SYSCALL(name, nargs, cerror) SYSCALL_5(name, cerror) | |
324 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_5(name, cerror) | |
325 | #elif __SYSCALL_32BIT_ARG_BYTES == 24 | |
326 | #define SYSCALL(name, nargs, cerror) SYSCALL_6(name, cerror) | |
327 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_6(name, cerror) | |
328 | #elif __SYSCALL_32BIT_ARG_BYTES == 28 | |
329 | #define SYSCALL(name, nargs, cerror) SYSCALL_7(name, cerror) | |
330 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_7(name, cerror) | |
331 | #elif __SYSCALL_32BIT_ARG_BYTES == 32 | |
332 | #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) | |
333 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) | |
334 | #elif __SYSCALL_32BIT_ARG_BYTES == 36 | |
335 | #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) | |
336 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) | |
337 | #elif __SYSCALL_32BIT_ARG_BYTES == 40 | |
338 | #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) | |
339 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) | |
340 | #elif __SYSCALL_32BIT_ARG_BYTES == 44 | |
341 | #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) | |
342 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) | |
343 | #elif __SYSCALL_32BIT_ARG_BYTES == 48 | |
344 | #define SYSCALL(name, nargs, cerror) SYSCALL_12(name, cerror) | |
345 | #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_12(name, cerror) | |
346 | #endif | |
347 | #endif | |
348 | ||
349 | #define SYSCALL_NONAME_0to4(name, cerror) \ | |
350 | DO_SYSCALL(SYS_##name) ;\ | |
351 | bcc 1f /* branch if carry bit is clear (no error) */ ; \ | |
352 | MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \ | |
353 | 1: | |
354 | ||
355 | #define SYSCALL_NONAME_5(name, cerror) \ | |
356 | mov ip, sp /* save a pointer to the args */ ; \ | |
357 | stmfd sp!, { r4-r5 } /* save r4-r5 */ ;\ | |
358 | ldr r4, [ip] /* load 5th arg */ ; \ | |
359 | DO_SYSCALL(SYS_##name) ;\ | |
360 | ldmfd sp!, { r4-r5 } /* restore r4-r7 */ ; \ | |
361 | bcc 1f /* branch if carry bit is clear (no error) */ ; \ | |
362 | MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \ | |
363 | 1: | |
364 | ||
365 | #define SYSCALL_NONAME_6to12(name, save_regs, arg_regs, cerror) \ | |
366 | mov ip, sp /* save a pointer to the args */ ; \ | |
367 | stmfd sp!, { save_regs } /* callee save regs */ ;\ | |
368 | ldmia ip, { arg_regs } /* load arguments */ ; \ | |
369 | DO_SYSCALL(SYS_##name) ;\ | |
370 | ldmfd sp!, { save_regs } /* restore callee saved regs */ ; \ | |
371 | bcc 1f /* branch if carry bit is clear (no error) */ ; \ | |
372 | MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \ | |
373 | 1: | |
374 | ||
375 | ||
376 | #if __BIGGEST_ALIGNMENT__ > 4 | |
377 | ||
378 | /* For the armv7k ABI, the alignment requirements may add padding. So we | |
379 | * let the kernel figure it out and push extra on the stack to avoid un-needed | |
380 | * copy-ins. We are relying on arguments that aren't in registers starting | |
381 | * 32 bytes from sp. We also use r8 like in the mach case. */ | |
382 | ||
383 | #define SYSCALL_NONAME_0(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
384 | #define SYSCALL_NONAME_1(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
385 | #define SYSCALL_NONAME_2(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
386 | #define SYSCALL_NONAME_3(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
387 | #define SYSCALL_NONAME_4(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror) | |
388 | #undef SYSCALL_NONAME_5 | |
389 | #define SYSCALL_NONAME_5(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror) | |
390 | #define SYSCALL_NONAME_6(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) | |
391 | #define SYSCALL_NONAME_7(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) | |
392 | #define SYSCALL_NONAME_8(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) | |
393 | #define SYSCALL_NONAME_12(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) | |
394 | ||
395 | #else // !(__BIGGEST_ALIGNMENT__ > 4) (the normal arm32 ABI case) | |
396 | ||
397 | #define SYSCALL_NONAME_0(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
398 | #define SYSCALL_NONAME_1(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
399 | #define SYSCALL_NONAME_2(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
400 | #define SYSCALL_NONAME_3(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
401 | #define SYSCALL_NONAME_4(name, cerror) SYSCALL_NONAME_0to4(name, cerror) | |
402 | /* SYSCALL_NONAME_5 declared above */ | |
403 | #define SYSCALL_NONAME_6(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror) | |
404 | #define SYSCALL_NONAME_7(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror) | |
405 | #define SYSCALL_NONAME_8(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror) | |
406 | #define SYSCALL_NONAME_12(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror) | |
407 | ||
408 | #endif // __BIGGEST_ALIGNMENT__ > 4 | |
409 | ||
410 | #define PSEUDO(pseudo, name, nargs, cerror) \ | |
411 | .globl pseudo ;\ | |
412 | .text ;\ | |
413 | .align 2 ;\ | |
414 | pseudo: ;\ | |
415 | SYSCALL_NONAME(name, nargs, cerror) | |
416 | ||
417 | #define __SYSCALL2(pseudo, name, nargs, cerror) \ | |
418 | PSEUDO(pseudo, name, nargs, cerror) ;\ | |
419 | bx lr | |
420 | ||
421 | #define __SYSCALL(pseudo, name, nargs) \ | |
422 | PSEUDO(pseudo, name, nargs, cerror) ;\ | |
423 | bx lr | |
424 | ||
425 | #elif defined(__arm64__) | |
426 | ||
427 | #include <mach/arm/syscall_sw.h> | |
428 | #include <mach/arm/vm_param.h> | |
429 | #include <mach/arm64/asm.h> | |
430 | ||
431 | #if defined(__arm64__) && !defined(__LP64__) | |
432 | #define ZERO_EXTEND(argnum) uxtw x ## argnum, w ## argnum | |
433 | #else | |
434 | #define ZERO_EXTEND(argnum) | |
435 | #endif | |
436 | ||
437 | #if defined(__arm64__) && !defined(__LP64__) | |
438 | #define SIGN_EXTEND(argnum) sxtw x ## argnum, w ## argnum | |
439 | #else | |
440 | #define SIGN_EXTEND(argnum) | |
441 | #endif | |
442 | ||
443 | /* | |
444 | * ARM64 system call interface: | |
445 | * | |
446 | * TBD | |
447 | */ | |
448 | ||
449 | #define DO_SYSCALL(num, cerror) \ | |
450 | mov x16, #(num) %%\ | |
451 | svc #SWI_SYSCALL %%\ | |
452 | b.cc 2f %%\ | |
453 | ARM64_STACK_PROLOG %%\ | |
454 | PUSH_FRAME %%\ | |
455 | bl _##cerror %%\ | |
456 | POP_FRAME %%\ | |
457 | ARM64_STACK_EPILOG %%\ | |
458 | 2: | |
459 | ||
460 | #define MI_GET_ADDRESS(reg,var) \ | |
461 | adrp reg, var@page %%\ | |
462 | add reg, reg, var@pageoff %% | |
463 | ||
464 | #define MI_CALL_EXTERNAL(sym) \ | |
465 | .globl sym %% \ | |
466 | bl sym | |
467 | ||
468 | #define SYSCALL_NONAME(name, nargs, cerror) \ | |
469 | DO_SYSCALL(SYS_##name, cerror) %% \ | |
470 | 1: | |
471 | ||
472 | #define MI_ENTRY_POINT(name) \ | |
473 | .text %% \ | |
474 | .align 2 %% \ | |
475 | .globl name %% \ | |
476 | name: | |
477 | ||
478 | #define PSEUDO(pseudo, name, nargs, cerror) \ | |
479 | .text %% \ | |
480 | .align 2 %% \ | |
481 | .globl pseudo %% \ | |
482 | pseudo: %% \ | |
483 | SYSCALL_NONAME(name, nargs, cerror) | |
484 | ||
485 | #define __SYSCALL(pseudo, name, nargs) \ | |
486 | PSEUDO(pseudo, name, nargs, cerror) %% \ | |
487 | ret | |
488 | ||
489 | #define __SYSCALL2(pseudo, name, nargs, cerror) \ | |
490 | PSEUDO(pseudo, name, nargs, cerror) %% \ | |
491 | ret | |
492 | ||
493 | #else | |
494 | #error Unsupported architecture | |
495 | #endif | |
496 |