]> git.saurik.com Git - apple/xnu.git/blame_incremental - libsyscall/custom/SYS.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libsyscall / custom / SYS.h
... / ...
CommitLineData
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 ;\
65LEAF(_##name, 0) ;\
66 movl $ SYS_##name, %eax ;\
67 UNIX_SYSCALL_SYSENTER ;\
68 jnb 2f ;\
69 BRANCH_EXTERN(tramp_cerror) ;\
702:
71
72#define UNIX_SYSCALL_INT(name, nargs) \
73 .globl tramp_cerror ;\
74LEAF(_##name, 0) ;\
75 movl $ SYS_##name, %eax ;\
76 UNIX_SYSCALL_TRAP ;\
77 jnb 2f ;\
78 BRANCH_EXTERN(tramp_cerror) ;\
792:
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) ;\
872:
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) ;\
942:
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) ;\
1032:
104
105#define PSEUDO(pseudo, name, nargs, cerror) \
106LEAF(pseudo, 0) ;\
107 UNIX_SYSCALL_NONAME(name, nargs, cerror)
108
109#define PSEUDO_INT(pseudo, name, nargs) \
110LEAF(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 ;\
136LEAF(_##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) ;\
1422:
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) ;\
1512:
152
153#define PSEUDO(pseudo, name, nargs, cerror) \
154LEAF(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 ;\
1903: ldr reg, [pc, reg] ;\
191 b 5f ;\
1924: .long 6f - (3b + 8) ;\
1935: ;\
194 .non_lazy_symbol_pointer ;\
1956: ;\
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 ;\
2043: .long var ;\
2054:
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 ;\
234name:
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) */ ; \
2531: 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) */ ; \
2641: 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) */ ; \
2751: 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 */ ; \
3531:
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 */ ; \
3631:
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 */ ; \
3731:
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 ;\
414pseudo: ;\
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 %%\
4582:
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) %% \
4701:
471
472#define MI_ENTRY_POINT(name) \
473 .text %% \
474 .align 2 %% \
475 .globl name %% \
476name:
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