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/* Binary compatibility stubs for syscalls that no longer exist */ 52 53#ifndef SYS_setquota 54#define SYS_setquota 148 55#endif 56#ifndef SYS_quota 57#define SYS_quota 149 58#endif 59 60#if defined(__i386__) 61 62#include <architecture/i386/asm_help.h> 63#include <mach/i386/syscall_sw.h> 64 65/* 66 * We have two entry points. int's is used for syscalls which need to preserve 67 * %ecx across the call, or return a 64-bit value in %eax:%edx. sysenter is used 68 * for the majority of syscalls which just return a value in %eax. 69 */ 70 71#define UNIX_SYSCALL_SYSENTER call __sysenter_trap 72#define UNIX_SYSCALL(name, nargs) \ 73 .globl cerror ;\ 74LEAF(_##name, 0) ;\ 75 movl $ SYS_##name, %eax ;\ 76 UNIX_SYSCALL_SYSENTER ;\ 77 jnb 2f ;\ 78 BRANCH_EXTERN(cerror) ;\ 792: 80 81#define UNIX_SYSCALL_INT(name, nargs) \ 82 .globl cerror ;\ 83LEAF(_##name, 0) ;\ 84 movl $ SYS_##name, %eax ;\ 85 UNIX_SYSCALL_TRAP ;\ 86 jnb 2f ;\ 87 BRANCH_EXTERN(cerror) ;\ 882: 89 90#if defined(__SYSCALL_32BIT_ARG_BYTES) && ((__SYSCALL_32BIT_ARG_BYTES >= 4) && (__SYSCALL_32BIT_ARG_BYTES <= 20)) 91#define UNIX_SYSCALL_NONAME(name, nargs, cerror) \ 92 movl $(SYS_##name | (__SYSCALL_32BIT_ARG_BYTES << I386_SYSCALL_ARG_BYTES_SHIFT)), %eax ;\ 93 UNIX_SYSCALL_SYSENTER ;\ 94 jnb 2f ;\ 95 BRANCH_EXTERN(cerror) ;\ 962: 97#else /* __SYSCALL_32BIT_ARG_BYTES < 4 || > 20 */ 98#define UNIX_SYSCALL_NONAME(name, nargs, cerror) \ 99 .globl cerror ;\ 100 movl $ SYS_##name, %eax ;\ 101 UNIX_SYSCALL_SYSENTER ;\ 102 jnb 2f ;\ 103 BRANCH_EXTERN(cerror) ;\ 1042: 105#endif 106 107#define UNIX_SYSCALL_INT_NONAME(name, nargs) \ 108 .globl cerror ;\ 109 movl $ SYS_##name, %eax ;\ 110 UNIX_SYSCALL_TRAP ;\ 111 jnb 2f ;\ 112 BRANCH_EXTERN(cerror_nocancel) ;\ 1132: 114 115#define PSEUDO(pseudo, name, nargs, cerror) \ 116LEAF(pseudo, 0) ;\ 117 UNIX_SYSCALL_NONAME(name, nargs, cerror) 118 119#define PSEUDO_INT(pseudo, name, nargs) \ 120LEAF(pseudo, 0) ;\ 121 UNIX_SYSCALL_INT_NONAME(name, nargs) 122 123#define __SYSCALL2(pseudo, name, nargs, cerror) \ 124 PSEUDO(pseudo, name, nargs, cerror) ;\ 125 ret 126 127#define __SYSCALL(pseudo, name, nargs) \ 128 PSEUDO(pseudo, name, nargs, cerror) ;\ 129 ret 130 131#define __SYSCALL_INT(pseudo, name, nargs) \ 132 PSEUDO_INT(pseudo, name, nargs) ;\ 133 ret 134 135#elif defined(__x86_64__) 136 137#include <architecture/i386/asm_help.h> 138#include <mach/i386/syscall_sw.h> 139 140#define UNIX_SYSCALL_SYSCALL \ 141 movq %rcx, %r10 ;\ 142 syscall 143 144#define UNIX_SYSCALL(name, nargs) \ 145 .globl cerror ;\ 146LEAF(_##name, 0) ;\ 147 movl $ SYSCALL_CONSTRUCT_UNIX(SYS_##name), %eax ;\ 148 UNIX_SYSCALL_SYSCALL ;\ 149 jnb 2f ;\ 150 BRANCH_EXTERN(cerror) ;\ 1512: 152 153#define UNIX_SYSCALL_NONAME(name, nargs, cerror) \ 154 .globl cerror ;\ 155 movl $ SYSCALL_CONSTRUCT_UNIX(SYS_##name), %eax ;\ 156 UNIX_SYSCALL_SYSCALL ;\ 157 jnb 2f ;\ 158 BRANCH_EXTERN(cerror) ;\ 1592: 160 161#define PSEUDO(pseudo, name, nargs, cerror) \ 162LEAF(pseudo, 0) ;\ 163 UNIX_SYSCALL_NONAME(name, nargs, cerror) 164 165#define __SYSCALL2(pseudo, name, nargs, cerror) \ 166 PSEUDO(pseudo, name, nargs, cerror) ;\ 167 ret 168 169#define __SYSCALL(pseudo, name, nargs) \ 170 PSEUDO(pseudo, name, nargs, cerror) ;\ 171 ret 172 173#elif defined(__arm__) 174 175#define SWI_SYSCALL 0x80 // from <mach/vm_param.h> 176 177/* 178 * ARM system call interface: 179 * 180 * swi 0x80 181 * args: r0-r6 182 * return code: r0 183 * on error, carry bit is set in the psr, otherwise carry bit is cleared. 184 */ 185 186/* 187 * Macros. 188 */ 189 190/* 191 * until we update the architecture project, these live here 192 */ 193 194#if defined(__DYNAMIC__) 195#define MI_GET_ADDRESS(reg,var) \ 196 ldr reg, 4f ;\ 1973: ldr reg, [pc, reg] ;\ 198 b 5f ;\ 1994: .long 6f - (3b + 8) ;\ 2005: ;\ 201 .non_lazy_symbol_pointer ;\ 2026: ;\ 203 .indirect_symbol var ;\ 204 .long 0 ;\ 205 .text ;\ 206 .align 2 207#else 208#define MI_GET_ADDRESS(reg,var) \ 209 ldr reg, 3f ;\ 210 b 4f ;\ 2113: .long var ;\ 2124: 213#endif 214 215#if defined(__DYNAMIC__) 216#define MI_BRANCH_EXTERNAL(var) \ 217 .globl var ;\ 218 MI_GET_ADDRESS(ip, var) ;\ 219 bx ip 220#else 221#define MI_BRANCH_EXTERNAL(var) ;\ 222 .globl var ;\ 223 b var 224#endif 225 226#if defined(__DYNAMIC__) 227#define MI_CALL_EXTERNAL(var) \ 228 .globl var ;\ 229 MI_GET_ADDRESS(ip,var) ;\ 230 mov lr, pc ;\ 231 bx ip 232#else 233#define MI_CALL_EXTERNAL(var) \ 234 .globl var ;\ 235 bl var 236#endif 237 238#define MI_ENTRY_POINT(name) \ 239 .align 2 ;\ 240 .globl name ;\ 241 .text ;\ 242name: 243 244/* load the syscall number into r12 and trap */ 245#define DO_SYSCALL(num) \ 246 .if (((num) & 0xff) == (num)) ;\ 247 mov r12, #(num) ;\ 248 .elseif (((num) & 0x3fc) == (num)) ;\ 249 mov r12, #(num) ;\ 250 .else ;\ 251 mov r12, #((num) & 0xffffff00) /* top half of the syscall number */ ;\ 252 orr r12, r12, #((num) & 0xff) /* bottom half */ ;\ 253 .endif ;\ 254 swi #SWI_SYSCALL 255 256/* simple syscalls (0 to 4 args) */ 257#define SYSCALL_0to4(name) \ 258 MI_ENTRY_POINT(_##name) ;\ 259 DO_SYSCALL(SYS_##name) ;\ 260 bxcc lr /* return if carry is clear (no error) */ ; \ 2611: MI_BRANCH_EXTERNAL(cerror) 262 263/* syscalls with 5 args is different, because of the single arg register load */ 264#define SYSCALL_5(name) \ 265 MI_ENTRY_POINT(_##name) ;\ 266 mov ip, sp /* save a pointer to the args */ ; \ 267 stmfd sp!, { r4-r5 } /* save r4-r5 */ ;\ 268 ldr r4, [ip] /* load 5th arg */ ; \ 269 DO_SYSCALL(SYS_##name) ;\ 270 ldmfd sp!, { r4-r5 } /* restore r4-r5 */ ; \ 271 bxcc lr /* return if carry is clear (no error) */ ; \ 2721: MI_BRANCH_EXTERNAL(cerror) 273 274/* syscalls with 6 to 8 args */ 275#define SYSCALL_6to8(name, save_regs, arg_regs) \ 276 MI_ENTRY_POINT(_##name) ;\ 277 mov ip, sp /* save a pointer to the args */ ; \ 278 stmfd sp!, { save_regs } /* callee saved regs */ ;\ 279 ldmia ip, { arg_regs } /* load arg regs */ ; \ 280 DO_SYSCALL(SYS_##name) ;\ 281 ldmfd sp!, { save_regs } /* restore callee saved regs */ ; \ 282 bxcc lr /* return if carry is clear (no error) */ ; \ 2831: MI_BRANCH_EXTERNAL(cerror) 284 285#define COMMA , 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_0to4(name) 292/* SYSCALL_5 declared above */ 293#define SYSCALL_6(name) SYSCALL_6to8(name, r4-r5, r4-r5) 294#define SYSCALL_7(name) SYSCALL_6to8(name, r4-r6 COMMA r8, r4-r6) 295#define SYSCALL_8(name) SYSCALL_6to8(name, r4-r6 COMMA r8, r4-r6 COMMA r8) 296 297/* select the appropriate syscall code, based on the number of arguments */ 298#define SYSCALL(name, nargs) SYSCALL_##nargs(name) 299 300#define SYSCALL_NONAME_0to4(name) \ 301 DO_SYSCALL(SYS_##name) ;\ 302 bcc 1f /* branch if carry bit is clear (no error) */ ; \ 303 MI_BRANCH_EXTERNAL(cerror) /* call cerror */ ; \ 3041: 305 306#define SYSCALL_NONAME_5(name) \ 307 mov ip, sp /* save a pointer to the args */ ; \ 308 stmfd sp!, { r4-r5 } /* save r4-r5 */ ;\ 309 ldr r4, [ip] /* load 5th arg */ ; \ 310 DO_SYSCALL(SYS_##name) ;\ 311 ldmfd sp!, { r4-r5 } /* restore r4-r7 */ ; \ 312 bcc 1f /* branch if carry bit is clear (no error) */ ; \ 313 MI_BRANCH_EXTERNAL(cerror) /* call cerror */ ; \ 3141: 315 316#define SYSCALL_NONAME_6to8(name, save_regs, arg_regs) \ 317 mov ip, sp /* save a pointer to the args */ ; \ 318 stmfd sp!, { save_regs } /* callee save regs */ ;\ 319 ldmia ip, { arg_regs } /* load arguments */ ; \ 320 DO_SYSCALL(SYS_##name) ;\ 321 ldmfd sp!, { save_regs } /* restore callee saved regs */ ; \ 322 bcc 1f /* branch if carry bit is clear (no error) */ ; \ 323 MI_BRANCH_EXTERNAL(cerror) /* call cerror */ ; \ 3241: 325 326#define SYSCALL_NONAME_0(name) SYSCALL_NONAME_0to4(name) 327#define SYSCALL_NONAME_1(name) SYSCALL_NONAME_0to4(name) 328#define SYSCALL_NONAME_2(name) SYSCALL_NONAME_0to4(name) 329#define SYSCALL_NONAME_3(name) SYSCALL_NONAME_0to4(name) 330#define SYSCALL_NONAME_4(name) SYSCALL_NONAME_0to4(name) 331/* SYSCALL_NONAME_5 declared above */ 332#define SYSCALL_NONAME_6(name) SYSCALL_NONAME_6to8(name, r4-r5, r4-r5) 333#define SYSCALL_NONAME_7(name) SYSCALL_NONAME_6to8(name, r4-r6 COMMA r8, r4-r6) 334#define SYSCALL_NONAME_8(name) SYSCALL_NONAME_6to8(name, r4-r6 COMMA r8, r4-r6 COMMA r8) 335 336/* select the appropriate syscall code, based on the number of arguments */ 337#define SYSCALL_NONAME(name, nargs) SYSCALL_NONAME_##nargs(name) 338 339#define PSEUDO(pseudo, name, nargs) \ 340 .globl _##pseudo ;\ 341 .text ;\ 342 .align 2 ;\ 343_##pseudo: ;\ 344 SYSCALL_NONAME(name, nargs) 345 346#define PSEUDO2(pseudo, name, nargs) \ 347 .globl pseudo ;\ 348 .text ;\ 349 .align 2 ;\ 350pseudo: ;\ 351 SYSCALL_NONAME(name, nargs) 352 353#define __SYSCALL(pseudo, name, nargs) \ 354 PSEUDO(pseudo, name, nargs) ;\ 355 bx lr 356 357#define __SYSCALL2(pseudo, name, nargs, cerror) \ 358 PSEUDO2(pseudo, name, nargs) ;\ 359 bx lr 360 361#else 362#error Unsupported architecture 363#endif 364 365