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 ([email protected]) 43 * Ported to m98k. 44 * 45 * 9-Jan-92 Peter King ([email protected]) 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 UNWIND_EPILOGUE 161 162 #define __SYSCALL(pseudo, name, nargs) \ 163 PSEUDO(pseudo, name, nargs, cerror) ;\ 164 ret ;\ 165 UNWIND_EPILOGUE 166 167 #elif defined(__arm__) 168 169 #include <architecture/arm/asm_help.h> 170 #include <mach/arm/syscall_sw.h> 171 172 /* 173 * ARM system call interface: 174 * 175 * swi 0x80 176 * args: r0-r6 177 * return code: r0 178 * on error, carry bit is set in the psr, otherwise carry bit is cleared. 179 */ 180 181 /* 182 * Macros. 183 */ 184 185 /* 186 * until we update the architecture project, these live here 187 */ 188 189 #if defined(__DYNAMIC__) 190 #define MI_GET_ADDRESS(reg,var) \ 191 ldr reg, 4f ;\ 192 3: ldr reg, [pc, reg] ;\ 193 b 5f ;\ 194 4: .long 6f - (3b + 8) ;\ 195 5: ;\ 196 .non_lazy_symbol_pointer ;\ 197 6: ;\ 198 .indirect_symbol var ;\ 199 .long 0 ;\ 200 .text ;\ 201 .align 2 202 #else 203 #define MI_GET_ADDRESS(reg,var) \ 204 ldr reg, 3f ;\ 205 b 4f ;\ 206 3: .long var ;\ 207 4: 208 #endif 209 210 #if defined(__DYNAMIC__) 211 #define MI_BRANCH_EXTERNAL(var) \ 212 .globl var ;\ 213 MI_GET_ADDRESS(ip, var) ;\ 214 bx ip 215 #else 216 #define MI_BRANCH_EXTERNAL(var) ;\ 217 .globl var ;\ 218 b var 219 #endif 220 221 #if defined(__DYNAMIC__) 222 #define MI_CALL_EXTERNAL(var) \ 223 .globl var ;\ 224 MI_GET_ADDRESS(ip,var) ;\ 225 blx ip 226 #else 227 #define MI_CALL_EXTERNAL(var) \ 228 .globl var ;\ 229 bl var 230 #endif 231 232 #define MI_ENTRY_POINT(name) \ 233 .text ;\ 234 .align 2 ;\ 235 .globl name ;\ 236 name: 237 238 /* load the syscall number into r12 and trap */ 239 #define DO_SYSCALL(num) \ 240 .if (((num) & 0xff) == (num)) ;\ 241 mov r12, #(num) ;\ 242 .elseif (((num) & 0x3fc) == (num)) ;\ 243 mov r12, #(num) ;\ 244 .else ;\ 245 mov r12, #((num) & 0xffffff00) /* top half of the syscall number */ ;\ 246 orr r12, r12, #((num) & 0xff) /* bottom half */ ;\ 247 .endif ;\ 248 swi #SWI_SYSCALL 249 250 /* simple syscalls (0 to 4 args) */ 251 #define SYSCALL_0to4(name, cerror) \ 252 MI_ENTRY_POINT(_##name) ;\ 253 DO_SYSCALL(SYS_##name) ;\ 254 bxcc lr /* return if carry is clear (no error) */ ; \ 255 1: MI_BRANCH_EXTERNAL(_##cerror) 256 257 /* syscalls with 5 args is different, because of the single arg register load */ 258 #define SYSCALL_5(name, cerror) \ 259 MI_ENTRY_POINT(_##name) ;\ 260 mov ip, sp /* save a pointer to the args */ ; \ 261 stmfd sp!, { r4-r5 } /* save r4-r5 */ ;\ 262 ldr r4, [ip] /* load 5th arg */ ; \ 263 DO_SYSCALL(SYS_##name) ;\ 264 ldmfd sp!, { r4-r5 } /* restore r4-r5 */ ; \ 265 bxcc lr /* return if carry is clear (no error) */ ; \ 266 1: MI_BRANCH_EXTERNAL(_##cerror) 267 268 /* syscalls with 6 to 12 args. kernel may have to read from stack */ 269 #define SYSCALL_6to12(name, save_regs, arg_regs, cerror) \ 270 MI_ENTRY_POINT(_##name) ;\ 271 mov ip, sp /* save a pointer to the args */ ; \ 272 stmfd sp!, { save_regs } /* callee saved regs */ ;\ 273 ldmia ip, { arg_regs } /* load arg regs */ ; \ 274 DO_SYSCALL(SYS_##name) ;\ 275 ldmfd sp!, { save_regs } /* restore callee saved regs */ ; \ 276 bxcc lr /* return if carry is clear (no error) */ ; \ 277 1: MI_BRANCH_EXTERNAL(_##cerror) 278 279 #define COMMA , 280 281 #if __BIGGEST_ALIGNMENT__ > 4 282 283 /* For the armv7k ABI, the alignment requirements may add padding. So we 284 * let the kernel figure it out and push extra on the stack to avoid un-needed 285 * copy-ins */ 286 287 /* We'll also use r8 for moving arguments */ 288 289 #define SYSCALL_0(name) SYSCALL_0to4(name) 290 #define SYSCALL_1(name) SYSCALL_0to4(name) 291 #define SYSCALL_2(name) SYSCALL_0to4(name) 292 #define SYSCALL_3(name) SYSCALL_0to4(name) 293 #define SYSCALL_4(name) SYSCALL_6to12(name, r4-r5, r4-r5) 294 #undef SYSCALL_5 295 #define SYSCALL_5(name) SYSCALL_6to12(name, r4-r5, r4-r5) 296 #define SYSCALL_6(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) 297 #define SYSCALL_7(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) 298 #define SYSCALL_8(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) 299 #define SYSCALL_12(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8) 300 301 #else // !(__BIGGEST_ALIGNMENT__ > 4) (the normal arm32 ABI case) 302 303 #define SYSCALL_0(name) SYSCALL_0to4(name) 304 #define SYSCALL_1(name) SYSCALL_0to4(name) 305 #define SYSCALL_2(name) SYSCALL_0to4(name) 306 #define SYSCALL_3(name) SYSCALL_0to4(name) 307 #define SYSCALL_4(name) SYSCALL_0to4(name) 308 /* SYSCALL_5 declared above */ 309 #define SYSCALL_6(name) SYSCALL_6to12(name, r4-r5, r4-r5) 310 #define SYSCALL_7(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6) 311 #define SYSCALL_8(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6) /* 8th on stack */ 312 #define SYSCALL_12(name) SYSCALL_6to12(name, r4-r6 COMMA r8, r4-r6) /* 8th-12th on stack */ 313 314 #endif // __BIGGEST_ALIGNMENT__ > 4 315 316 /* select the appropriate syscall code, based on the number of arguments */ 317 #ifndef __SYSCALL_32BIT_ARG_BYTES 318 #define SYSCALL(name, nargs, cerror) SYSCALL_##nargs(name, cerror) 319 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_##nargs(name, cerror) 320 #else 321 #if __SYSCALL_32BIT_ARG_BYTES < 20 322 #define SYSCALL(name, nargs, cerror) SYSCALL_0to4(name, cerror) 323 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_0to4(name, cerror) 324 #elif __SYSCALL_32BIT_ARG_BYTES == 20 325 #define SYSCALL(name, nargs, cerror) SYSCALL_5(name, cerror) 326 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_5(name, cerror) 327 #elif __SYSCALL_32BIT_ARG_BYTES == 24 328 #define SYSCALL(name, nargs, cerror) SYSCALL_6(name, cerror) 329 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_6(name, cerror) 330 #elif __SYSCALL_32BIT_ARG_BYTES == 28 331 #define SYSCALL(name, nargs, cerror) SYSCALL_7(name, cerror) 332 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_7(name, cerror) 333 #elif __SYSCALL_32BIT_ARG_BYTES == 32 334 #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) 335 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) 336 #elif __SYSCALL_32BIT_ARG_BYTES == 36 337 #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) 338 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) 339 #elif __SYSCALL_32BIT_ARG_BYTES == 40 340 #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) 341 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) 342 #elif __SYSCALL_32BIT_ARG_BYTES == 44 343 #define SYSCALL(name, nargs, cerror) SYSCALL_8(name, cerror) 344 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_8(name, cerror) 345 #elif __SYSCALL_32BIT_ARG_BYTES == 48 346 #define SYSCALL(name, nargs, cerror) SYSCALL_12(name, cerror) 347 #define SYSCALL_NONAME(name, nargs, cerror) SYSCALL_NONAME_12(name, cerror) 348 #endif 349 #endif 350 351 #define SYSCALL_NONAME_0to4(name, cerror) \ 352 DO_SYSCALL(SYS_##name) ;\ 353 bcc 1f /* branch if carry bit is clear (no error) */ ; \ 354 MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \ 355 1: 356 357 #define SYSCALL_NONAME_5(name, cerror) \ 358 mov ip, sp /* save a pointer to the args */ ; \ 359 stmfd sp!, { r4-r5 } /* save r4-r5 */ ;\ 360 ldr r4, [ip] /* load 5th arg */ ; \ 361 DO_SYSCALL(SYS_##name) ;\ 362 ldmfd sp!, { r4-r5 } /* restore r4-r7 */ ; \ 363 bcc 1f /* branch if carry bit is clear (no error) */ ; \ 364 MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \ 365 1: 366 367 #define SYSCALL_NONAME_6to12(name, save_regs, arg_regs, cerror) \ 368 mov ip, sp /* save a pointer to the args */ ; \ 369 stmfd sp!, { save_regs } /* callee save regs */ ;\ 370 ldmia ip, { arg_regs } /* load arguments */ ; \ 371 DO_SYSCALL(SYS_##name) ;\ 372 ldmfd sp!, { save_regs } /* restore callee saved regs */ ; \ 373 bcc 1f /* branch if carry bit is clear (no error) */ ; \ 374 MI_BRANCH_EXTERNAL(_##cerror) /* call cerror */ ; \ 375 1: 376 377 378 #if __BIGGEST_ALIGNMENT__ > 4 379 380 /* For the armv7k ABI, the alignment requirements may add padding. So we 381 * let the kernel figure it out and push extra on the stack to avoid un-needed 382 * copy-ins. We are relying on arguments that aren't in registers starting 383 * 32 bytes from sp. We also use r8 like in the mach case. */ 384 385 #define SYSCALL_NONAME_0(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 386 #define SYSCALL_NONAME_1(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 387 #define SYSCALL_NONAME_2(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 388 #define SYSCALL_NONAME_3(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 389 #define SYSCALL_NONAME_4(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror) 390 #undef SYSCALL_NONAME_5 391 #define SYSCALL_NONAME_5(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror) 392 #define SYSCALL_NONAME_6(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) 393 #define SYSCALL_NONAME_7(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) 394 #define SYSCALL_NONAME_8(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) 395 #define SYSCALL_NONAME_12(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6 COMMA r8, cerror) 396 397 #else // !(__BIGGEST_ALIGNMENT__ > 4) (the normal arm32 ABI case) 398 399 #define SYSCALL_NONAME_0(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 400 #define SYSCALL_NONAME_1(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 401 #define SYSCALL_NONAME_2(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 402 #define SYSCALL_NONAME_3(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 403 #define SYSCALL_NONAME_4(name, cerror) SYSCALL_NONAME_0to4(name, cerror) 404 /* SYSCALL_NONAME_5 declared above */ 405 #define SYSCALL_NONAME_6(name, cerror) SYSCALL_NONAME_6to12(name, r4-r5, r4-r5, cerror) 406 #define SYSCALL_NONAME_7(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror) 407 #define SYSCALL_NONAME_8(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror) 408 #define SYSCALL_NONAME_12(name, cerror) SYSCALL_NONAME_6to12(name, r4-r6 COMMA r8, r4-r6, cerror) 409 410 #endif // __BIGGEST_ALIGNMENT__ > 4 411 412 #define PSEUDO(pseudo, name, nargs, cerror) \ 413 .globl pseudo ;\ 414 .text ;\ 415 .align 2 ;\ 416 pseudo: ;\ 417 SYSCALL_NONAME(name, nargs, cerror) 418 419 #define __SYSCALL2(pseudo, name, nargs, cerror) \ 420 PSEUDO(pseudo, name, nargs, cerror) ;\ 421 bx lr 422 423 #define __SYSCALL(pseudo, name, nargs) \ 424 PSEUDO(pseudo, name, nargs, cerror) ;\ 425 bx lr 426 427 #elif defined(__arm64__) 428 429 #include <mach/arm/syscall_sw.h> 430 #include <mach/arm/vm_param.h> 431 #include <mach/arm64/asm.h> 432 433 #if defined(__arm64__) && !defined(__LP64__) 434 #define ZERO_EXTEND(argnum) uxtw x ## argnum, w ## argnum 435 #else 436 #define ZERO_EXTEND(argnum) 437 #endif 438 439 #if defined(__arm64__) && !defined(__LP64__) 440 #define SIGN_EXTEND(argnum) sxtw x ## argnum, w ## argnum 441 #else 442 #define SIGN_EXTEND(argnum) 443 #endif 444 445 /* 446 * ARM64 system call interface: 447 * 448 * TBD 449 */ 450 451 #define DO_SYSCALL(num, cerror) \ 452 mov x16, #(num) %%\ 453 svc #SWI_SYSCALL %%\ 454 b.cc 2f %%\ 455 ARM64_STACK_PROLOG %%\ 456 PUSH_FRAME %%\ 457 bl _##cerror %%\ 458 POP_FRAME %%\ 459 ARM64_STACK_EPILOG %%\ 460 2: 461 462 #define MI_GET_ADDRESS(reg,var) \ 463 adrp reg, var@page %%\ 464 add reg, reg, var@pageoff %% 465 466 #define MI_CALL_EXTERNAL(sym) \ 467 .globl sym %% \ 468 bl sym 469 470 #define SYSCALL_NONAME(name, nargs, cerror) \ 471 DO_SYSCALL(SYS_##name, cerror) %% \ 472 1: 473 474 #define MI_ENTRY_POINT(name) \ 475 .text %% \ 476 .align 2 %% \ 477 .globl name %% \ 478 name: 479 480 #define PSEUDO(pseudo, name, nargs, cerror) \ 481 .text %% \ 482 .align 2 %% \ 483 .globl pseudo %% \ 484 pseudo: %% \ 485 SYSCALL_NONAME(name, nargs, cerror) 486 487 #define __SYSCALL(pseudo, name, nargs) \ 488 PSEUDO(pseudo, name, nargs, cerror) %% \ 489 ret 490 491 #define __SYSCALL2(pseudo, name, nargs, cerror) \ 492 PSEUDO(pseudo, name, nargs, cerror) %% \ 493 ret 494 495 #else 496 #error Unsupported architecture 497 #endif 498 499