]> git.saurik.com Git - apple/xnu.git/blob - libsyscall/custom/SYS.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libsyscall / custom / SYS.h
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