]> git.saurik.com Git - apple/xnu.git/blame - libsyscall/custom/SYS.h
xnu-6153.141.1.tar.gz
[apple/xnu.git] / libsyscall / custom / SYS.h
CommitLineData
2d21ac55 1/*
316670eb 2 * Copyright (c) 1999-2011 Apple Inc. All rights reserved.
2d21ac55
A
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
6d2010ae 51#if defined(__i386__)
2d21ac55
A
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) \
39236c6e 64 .globl tramp_cerror ;\
2d21ac55
A
65LEAF(_##name, 0) ;\
66 movl $ SYS_##name, %eax ;\
67 UNIX_SYSCALL_SYSENTER ;\
68 jnb 2f ;\
39236c6e 69 BRANCH_EXTERN(tramp_cerror) ;\
2d21ac55
A
702:
71
72#define UNIX_SYSCALL_INT(name, nargs) \
39236c6e 73 .globl tramp_cerror ;\
2d21ac55
A
74LEAF(_##name, 0) ;\
75 movl $ SYS_##name, %eax ;\
76 UNIX_SYSCALL_TRAP ;\
77 jnb 2f ;\
39236c6e 78 BRANCH_EXTERN(tramp_cerror) ;\
2d21ac55
A
792:
80
4a3eedf9 81#if defined(__SYSCALL_32BIT_ARG_BYTES) && ((__SYSCALL_32BIT_ARG_BYTES >= 4) && (__SYSCALL_32BIT_ARG_BYTES <= 20))
316670eb 82#define UNIX_SYSCALL_NONAME(name, nargs, cerror) \
4a3eedf9 83 movl $(SYS_##name | (__SYSCALL_32BIT_ARG_BYTES << I386_SYSCALL_ARG_BYTES_SHIFT)), %eax ;\
2d21ac55
A
84 UNIX_SYSCALL_SYSENTER ;\
85 jnb 2f ;\
39236c6e 86 BRANCH_EXTERN(tramp_##cerror) ;\
2d21ac55 872:
4a3eedf9 88#else /* __SYSCALL_32BIT_ARG_BYTES < 4 || > 20 */
39236c6e 89#define UNIX_SYSCALL_NONAME(name, nargs, cerror) \
2d21ac55
A
90 movl $ SYS_##name, %eax ;\
91 UNIX_SYSCALL_SYSENTER ;\
92 jnb 2f ;\
39236c6e 93 BRANCH_EXTERN(tramp_##cerror) ;\
2d21ac55
A
942:
95#endif
96
97#define UNIX_SYSCALL_INT_NONAME(name, nargs) \
39236c6e 98 .globl tramp_cerror_nocancel ;\
2d21ac55
A
99 movl $ SYS_##name, %eax ;\
100 UNIX_SYSCALL_TRAP ;\
101 jnb 2f ;\
39236c6e 102 BRANCH_EXTERN(tramp_cerror_nocancel) ;\
2d21ac55
A
1032:
104
39236c6e 105#define PSEUDO(pseudo, name, nargs, cerror) \
6d2010ae 106LEAF(pseudo, 0) ;\
316670eb 107 UNIX_SYSCALL_NONAME(name, nargs, cerror)
2d21ac55 108
39236c6e 109#define PSEUDO_INT(pseudo, name, nargs) \
6d2010ae 110LEAF(pseudo, 0) ;\
2d21ac55
A
111 UNIX_SYSCALL_INT_NONAME(name, nargs)
112
316670eb
A
113#define __SYSCALL2(pseudo, name, nargs, cerror) \
114 PSEUDO(pseudo, name, nargs, cerror) ;\
115 ret
116
2d21ac55 117#define __SYSCALL(pseudo, name, nargs) \
39236c6e 118 PSEUDO(pseudo, name, nargs, cerror) ;\
2d21ac55
A
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
39236c6e
A
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) ;\
2d21ac55
A
1422:
143
39236c6e
A
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) ;\
2d21ac55
A
1512:
152
316670eb 153#define PSEUDO(pseudo, name, nargs, cerror) \
6d2010ae 154LEAF(pseudo, 0) ;\
316670eb
A
155 UNIX_SYSCALL_NONAME(name, nargs, cerror)
156
157#define __SYSCALL2(pseudo, name, nargs, cerror) \
158 PSEUDO(pseudo, name, nargs, cerror) ;\
159 ret
2d21ac55
A
160
161#define __SYSCALL(pseudo, name, nargs) \
316670eb 162 PSEUDO(pseudo, name, nargs, cerror) ;\
2d21ac55
A
163 ret
164
5ba3f43e
A
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) \
d9a64523 231 .text ;\
5ba3f43e
A
232 .align 2 ;\
233 .globl name ;\
5ba3f43e
A
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 == 44
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 == 48
341#define SYSCALL(name, nargs, cerror) SYSCALL_12(name, cerror)
342#define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_12(name, cerror)
343#endif
344#endif
345
346#define SYSCALL_NONAME_0to4(name, cerror) \
347 DO_SYSCALL(SYS_##name) ;\
348 bcc 1f /* branch if carry bit is clear (no error) */ ; \
349 MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \
3501:
351
352#define SYSCALL_NONAME_5(name, cerror) \
353 mov ip, sp /* save a pointer to the args */ ; \
354 stmfd sp!, { r4-r5 } /* save r4-r5 */ ;\
355 ldr r4, [ip] /* load 5th arg */ ; \
356 DO_SYSCALL(SYS_##name) ;\
357 ldmfd sp!, { r4-r5 } /* restore r4-r7 */ ; \
358 bcc 1f /* branch if carry bit is clear (no error) */ ; \
359 MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \
3601:
361
362#define SYSCALL_NONAME_6to12(name, save_regs, arg_regs, cerror) \
363 mov ip, sp /* save a pointer to the args */ ; \
364 stmfd sp!, { save_regs } /* callee save regs */ ;\
365 ldmia ip, { arg_regs } /* load arguments */ ; \
366 DO_SYSCALL(SYS_##name) ;\
367 ldmfd sp!, { save_regs } /* restore callee saved regs */ ; \
368 bcc 1f /* branch if carry bit is clear (no error) */ ; \
369 MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \
3701:
371
372
373#if __BIGGEST_ALIGNMENT__ > 4
374
375/* For the armv7k ABI, the alignment requirements may add padding. So we
376 * let the kernel figure it out and push extra on the stack to avoid un-needed
377 * copy-ins. We are relying on arguments that aren't in registers starting
378 * 32 bytes from sp. We also use r8 like in the mach case. */
379
380#define SYSCALL_NONAME_0(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
381#define SYSCALL_NONAME_1(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
382#define SYSCALL_NONAME_2(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
383#define SYSCALL_NONAME_3(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
384#define SYSCALL_NONAME_4(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror)
385#undef SYSCALL_NONAME_5
386#define SYSCALL_NONAME_5(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror)
387#define SYSCALL_NONAME_6(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror)
388#define SYSCALL_NONAME_7(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror)
389#define SYSCALL_NONAME_8(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror)
390#define SYSCALL_NONAME_12(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror)
391
392#else // !(__BIGGEST_ALIGNMENT__ > 4) (the normal arm32 ABI case)
393
394#define SYSCALL_NONAME_0(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
395#define SYSCALL_NONAME_1(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
396#define SYSCALL_NONAME_2(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
397#define SYSCALL_NONAME_3(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
398#define SYSCALL_NONAME_4(name, cerror) SYSCALL_NONAME_0to4(name, cerror)
399/* SYSCALL_NONAME_5 declared above */
400#define SYSCALL_NONAME_6(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror)
401#define SYSCALL_NONAME_7(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror)
402#define SYSCALL_NONAME_8(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror)
403#define SYSCALL_NONAME_12(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror)
404
405#endif // __BIGGEST_ALIGNMENT__ > 4
406
407#define PSEUDO(pseudo, name, nargs, cerror) \
408 .globl pseudo ;\
409 .text ;\
410 .align 2 ;\
411pseudo: ;\
412 SYSCALL_NONAME(name, nargs, cerror)
413
414#define __SYSCALL2(pseudo, name, nargs, cerror) \
415 PSEUDO(pseudo, name, nargs, cerror) ;\
416 bx lr
417
418#define __SYSCALL(pseudo, name, nargs) \
419 PSEUDO(pseudo, name, nargs, cerror) ;\
420 bx lr
421
422#elif defined(__arm64__)
423
424#include <mach/arm/syscall_sw.h>
425#include <mach/arm/vm_param.h>
426#include <mach/arm64/asm.h>
427
d9a64523
A
428#if defined(__arm64__) && !defined(__LP64__)
429#define ZERO_EXTEND(argnum) uxtw x ## argnum, w ## argnum
430#else
431#define ZERO_EXTEND(argnum)
432#endif
433
434#if defined(__arm64__) && !defined(__LP64__)
435#define SIGN_EXTEND(argnum) sxtw x ## argnum, w ## argnum
436#else
437#define SIGN_EXTEND(argnum)
438#endif
439
5ba3f43e
A
440/*
441 * ARM64 system call interface:
442 *
443 * TBD
444 */
445
446#define DO_SYSCALL(num, cerror) \
447 mov x16, #(num) %%\
448 svc #SWI_SYSCALL %%\
449 b.cc 2f %%\
450 PUSH_FRAME %%\
451 bl _##cerror %%\
452 POP_FRAME %%\
cb323159 453 ret %%\
5ba3f43e
A
4542:
455
456#define MI_GET_ADDRESS(reg,var) \
457 adrp reg, var@page %%\
458 add reg, reg, var@pageoff %%
459
460#define MI_CALL_EXTERNAL(sym) \
461 .globl sym %% \
462 bl sym
463
464#define SYSCALL_NONAME(name, nargs, cerror) \
465 DO_SYSCALL(SYS_##name, cerror) %% \
4661:
467
468#define MI_ENTRY_POINT(name) \
469 .text %% \
470 .align 2 %% \
471 .globl name %% \
472name:
473
474#define PSEUDO(pseudo, name, nargs, cerror) \
475 .text %% \
476 .align 2 %% \
477 .globl pseudo %% \
478 pseudo: %% \
479 SYSCALL_NONAME(name, nargs, cerror)
480
481#define __SYSCALL(pseudo, name, nargs) \
482 PSEUDO(pseudo, name, nargs, cerror) %% \
483 ret
484
485#define __SYSCALL2(pseudo, name, nargs, cerror) \
486 PSEUDO(pseudo, name, nargs, cerror) %% \
487 ret
488
2d21ac55
A
489#else
490#error Unsupported architecture
491#endif
316670eb 492