]>
git.saurik.com Git - apple/xnu.git/blob - libsyscall/custom/SYS.h
2 * Copyright (c) 1999-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
32 * Definition of the user side of the UNIX system call interface
35 * Errors are flagged by the location of the trap return (ie., which
36 * instruction is executed upon rfi):
38 * SC PC + 4: Error (typically branch to cerror())
42 * 18-Nov-92 Ben Fathi (benf@next.com)
45 * 9-Jan-92 Peter King (king@next.com)
49 #include <sys/syscall.h>
53 #include <architecture/i386/asm_help.h>
54 #include <mach/i386/syscall_sw.h>
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.
62 #define UNIX_SYSCALL_SYSENTER call __sysenter_trap
63 #define UNIX_SYSCALL(name, nargs) \
64 .globl tramp_cerror ;\
66 movl $ SYS_##name, %eax ;\
67 UNIX_SYSCALL_SYSENTER ;\
69 BRANCH_EXTERN(tramp_cerror) ;\
72 #define UNIX_SYSCALL_INT(name, nargs) \
73 .globl tramp_cerror ;\
75 movl $ SYS_##name, %eax ;\
78 BRANCH_EXTERN(tramp_cerror) ;\
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 ;\
86 BRANCH_EXTERN(tramp_##cerror) ;\
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 ;\
93 BRANCH_EXTERN(tramp_##cerror) ;\
97 #define UNIX_SYSCALL_INT_NONAME(name, nargs) \
98 .globl tramp_cerror_nocancel ;\
99 movl $ SYS_##name, %eax ;\
102 BRANCH_EXTERN(tramp_cerror_nocancel) ;\
105 #define PSEUDO(pseudo, name, nargs, cerror) \
107 UNIX_SYSCALL_NONAME(name, nargs, cerror)
109 #define PSEUDO_INT(pseudo, name, nargs) \
111 UNIX_SYSCALL_INT_NONAME(name, nargs)
113 #define __SYSCALL2(pseudo, name, nargs, cerror) \
114 PSEUDO(pseudo, name, nargs, cerror) ;\
117 #define __SYSCALL(pseudo, name, nargs) \
118 PSEUDO(pseudo, name, nargs, cerror) ;\
121 #define __SYSCALL_INT(pseudo, name, nargs) \
122 PSEUDO_INT(pseudo, name, nargs) ;\
125 #elif defined(__x86_64__)
127 #include <architecture/i386/asm_help.h>
128 #include <mach/i386/syscall_sw.h>
130 #define UNIX_SYSCALL_SYSCALL \
134 #define UNIX_SYSCALL(name, nargs) \
137 movl $ SYSCALL_CONSTRUCT_UNIX(SYS_##name), %eax ;\
138 UNIX_SYSCALL_SYSCALL ;\
141 BRANCH_EXTERN(_cerror) ;\
144 #define UNIX_SYSCALL_NONAME(name, nargs, cerror) \
146 movl $ SYSCALL_CONSTRUCT_UNIX(SYS_##name), %eax ;\
147 UNIX_SYSCALL_SYSCALL ;\
150 BRANCH_EXTERN(_##cerror) ;\
153 #define PSEUDO(pseudo, name, nargs, cerror) \
155 UNIX_SYSCALL_NONAME(name, nargs, cerror)
157 #define __SYSCALL2(pseudo, name, nargs, cerror) \
158 PSEUDO(pseudo, name, nargs, cerror) ;\
161 #define __SYSCALL(pseudo, name, nargs) \
162 PSEUDO(pseudo, name, nargs, cerror) ;\
165 #elif defined(__arm__)
167 #include <architecture/arm/asm_help.h>
168 #include <mach/arm/syscall_sw.h>
171 * ARM system call interface:
176 * on error, carry bit is set in the psr, otherwise carry bit is cleared.
184 * until we update the architecture project, these live here
187 #if defined(__DYNAMIC__)
188 #define MI_GET_ADDRESS(reg,var) \
190 3: ldr reg, [pc, reg] ;\
192 4: .long 6f - (3b + 8) ;\
194 .non_lazy_symbol_pointer ;\
196 .indirect_symbol var ;\
201 #define MI_GET_ADDRESS(reg,var) \
208 #if defined(__DYNAMIC__)
209 #define MI_BRANCH_EXTERNAL(var) \
211 MI_GET_ADDRESS(ip, var) ;\
214 #define MI_BRANCH_EXTERNAL(var) ;\
219 #if defined(__DYNAMIC__)
220 #define MI_CALL_EXTERNAL(var) \
222 MI_GET_ADDRESS(ip,var) ;\
225 #define MI_CALL_EXTERNAL(var) \
230 #define MI_ENTRY_POINT(name) \
236 /* load the syscall number into r12 and trap */
237 #define DO_SYSCALL(num) \
238 .if (((num) & 0xff) == (num)) ;\
240 .elseif (((num) & 0x3fc) == (num)) ;\
243 mov r12, #((num) & 0xffffff00) /* top half of the syscall number */ ;\
244 orr r12, r12, #((num) & 0xff) /* bottom half */ ;\
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)
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)
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)
279 #if __BIGGEST_ALIGNMENT__ > 4
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
285 /* We'll also use r8 for moving arguments */
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)
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)
299 #else // !(__BIGGEST_ALIGNMENT__ > 4) (the normal arm32 ABI case)
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 */
312 #endif // __BIGGEST_ALIGNMENT__ > 4
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)
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)
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 */ ; \
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 */ ; \
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 */ ; \
376 #if __BIGGEST_ALIGNMENT__ > 4
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. */
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)
395 #else // !(__BIGGEST_ALIGNMENT__ > 4) (the normal arm32 ABI case)
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)
408 #endif // __BIGGEST_ALIGNMENT__ > 4
410 #define PSEUDO(pseudo, name, nargs, cerror) \
415 SYSCALL_NONAME(name, nargs, cerror)
417 #define __SYSCALL2(pseudo, name, nargs, cerror) \
418 PSEUDO(pseudo, name, nargs, cerror) ;\
421 #define __SYSCALL(pseudo, name, nargs) \
422 PSEUDO(pseudo, name, nargs, cerror) ;\
425 #elif defined(__arm64__)
427 #include <mach/arm/syscall_sw.h>
428 #include <mach/arm/vm_param.h>
429 #include <mach/arm64/asm.h>
431 #if defined(__arm64__) && !defined(__LP64__)
432 #define ZERO_EXTEND(argnum) uxtw x ## argnum, w ## argnum
434 #define ZERO_EXTEND(argnum)
437 #if defined(__arm64__) && !defined(__LP64__)
438 #define SIGN_EXTEND(argnum) sxtw x ## argnum, w ## argnum
440 #define SIGN_EXTEND(argnum)
444 * ARM64 system call interface:
449 #define DO_SYSCALL(num, cerror) \
453 ARM64_STACK_PROLOG %%\
457 ARM64_STACK_EPILOG %%\
460 #define MI_GET_ADDRESS(reg,var) \
461 adrp reg, var@page %%\
462 add reg, reg, var@pageoff %%
464 #define MI_CALL_EXTERNAL(sym) \
468 #define SYSCALL_NONAME(name, nargs, cerror) \
469 DO_SYSCALL(SYS_##name, cerror) %% \
472 #define MI_ENTRY_POINT(name) \
478 #define PSEUDO(pseudo, name, nargs, cerror) \
483 SYSCALL_NONAME(name, nargs, cerror)
485 #define __SYSCALL(pseudo, name, nargs) \
486 PSEUDO(pseudo, name, nargs, cerror) %% \
489 #define __SYSCALL2(pseudo, name, nargs, cerror) \
490 PSEUDO(pseudo, name, nargs, cerror) %% \
494 #error Unsupported architecture