]> git.saurik.com Git - apple/xnu.git/blob - libsyscall/custom/SYS.h
xnu-4903.270.47.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 == 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 */ ; \
350 1:
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 */ ; \
360 1:
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 */ ; \
370 1:
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 ;\
411 pseudo: ;\
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
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
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 %%\
453 2:
454
455 #define MI_GET_ADDRESS(reg,var) \
456 adrp reg, var@page %%\
457 add reg, reg, var@pageoff %%
458
459 #define MI_CALL_EXTERNAL(sym) \
460 .globl sym %% \
461 bl sym
462
463 #define SYSCALL_NONAME(name, nargs, cerror) \
464 DO_SYSCALL(SYS_##name, cerror) %% \
465 1:
466
467 #define MI_ENTRY_POINT(name) \
468 .text %% \
469 .align 2 %% \
470 .globl name %% \
471 name:
472
473 #define PSEUDO(pseudo, name, nargs, cerror) \
474 .text %% \
475 .align 2 %% \
476 .globl pseudo %% \
477 pseudo: %% \
478 SYSCALL_NONAME(name, nargs, cerror)
479
480 #define __SYSCALL(pseudo, name, nargs) \
481 PSEUDO(pseudo, name, nargs, cerror) %% \
482 ret
483
484 #define __SYSCALL2(pseudo, name, nargs, cerror) \
485 PSEUDO(pseudo, name, nargs, cerror) %% \
486 ret
487
488 #else
489 #error Unsupported architecture
490 #endif
491