1 /* Copyright (C) 2005-2016 Free Software Foundation, Inc. 2 3 The GNU C Library is free software; you can redistribute it and/or 4 modify it under the terms of the GNU Lesser General Public License as 5 published by the Free Software Foundation; either version 2.1 of the 6 License, or (at your option) any later version. 7 8 The GNU C Library is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public 14 License along with the GNU C Library; if not, see 15 <http://www.gnu.org/licenses/>. */ 16 17 #ifndef _LINUX_AARCH64_SYSDEP_H 18 #define _LINUX_AARCH64_SYSDEP_H 1 19 20 #include <common/sysdep.h> 21 #include <sys/syscall.h> 22 23 /* In order to get __set_errno() definition in INLINE_SYSCALL. */ 24 #ifndef __ASSEMBLER__ 25 #include <errno.h> 26 #endif 27 28 /* For Linux we can use the system call table in the header file 29 /usr/include/asm/unistd.h 30 of the kernel. But these symbols do not follow the SYS_* syntax 31 so we have to redefine the `SYS_ify' macro here. */ 32 #undef SYS_ify 33 #define SYS_ify(syscall_name) (__NR_##syscall_name) 34 35 #ifdef __ASSEMBLER__ 36 37 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name 38 39 /* Local label name for asm code. */ 40 #ifndef L 41 # define L(name) .L##name 42 #endif 43 44 /* Define an entry point visible from C. */ 45 #define ENTRY(name) \ 46 .globl C_SYMBOL_NAME(name); \ 47 .type C_SYMBOL_NAME(name),%function; \ 48 .align 4; \ 49 C_LABEL(name) \ 50 cfi_startproc; 51 52 /* Define an entry point visible from C. */ 53 #define ENTRY_ALIGN(name, align) \ 54 .globl C_SYMBOL_NAME(name); \ 55 .type C_SYMBOL_NAME(name),%function; \ 56 .p2align align; \ 57 C_LABEL(name) \ 58 cfi_startproc; 59 60 #undef END 61 #define END(name) \ 62 cfi_endproc; \ 63 ASM_SIZE_DIRECTIVE(name) 64 65 /* Linux uses a negative return value to indicate syscall errors, 66 unlike most Unices, which use the condition codes' carry flag. 67 68 Since version 2.1 the return value of a system call might be 69 negative even if the call succeeded. E.g., the `lseek' system call 70 might return a large offset. Therefore we must not anymore test 71 for < 0, but test for a real error by making sure the value in R0 72 is a real error number. Linus said he will make sure the no syscall 73 returns a value in -1 .. -4095 as a valid result so we can safely 74 test with -4095. */ 75 76 # undef PSEUDO 77 # define PSEUDO(name, syscall_name, args) \ 78 .text; \ 79 ENTRY (name); \ 80 DO_CALL (syscall_name, args); \ 81 cmn x0, #4095; \ 82 b.cs .Lsyscall_error; 83 84 # undef PSEUDO_END 85 # define PSEUDO_END(name) \ 86 SYSCALL_ERROR_HANDLER \ 87 END (name) 88 89 # undef PSEUDO_NOERRNO 90 # define PSEUDO_NOERRNO(name, syscall_name, args) \ 91 .text; \ 92 ENTRY (name); \ 93 DO_CALL (syscall_name, args); 94 95 # undef PSEUDO_END_NOERRNO 96 # define PSEUDO_END_NOERRNO(name) \ 97 END (name) 98 99 # define ret_NOERRNO ret 100 101 /* The function has to return the error code. */ 102 # undef PSEUDO_ERRVAL 103 # define PSEUDO_ERRVAL(name, syscall_name, args) \ 104 .text; \ 105 ENTRY (name) \ 106 DO_CALL (syscall_name, args); \ 107 neg x0, x0 108 109 # undef PSEUDO_END_ERRVAL 110 # define PSEUDO_END_ERRVAL(name) \ 111 END (name) 112 113 # define ret_ERRVAL ret 114 115 #if defined NOT_IN_libc 116 # define SYSCALL_ERROR .Lsyscall_error 117 # define SYSCALL_ERROR_HANDLER \ 118 .Lsyscall_error: \ 119 adrp x1, :gottprel:errno; \ 120 neg w2, w0; \ 121 ldr x1, [x1, :gottprel_lo12:errno]; \ 122 mrs x3, tpidr_el0; \ 123 mov x0, -1; \ 124 str w2, [x1, x3]; \ 125 ret; 126 #else 127 # define SYSCALL_ERROR __syscall_error 128 # define SYSCALL_ERROR_HANDLER \ 129 .Lsyscall_error: \ 130 b __syscall_error; 131 #endif 132 133 # undef DO_CALL 134 # define DO_CALL(syscall_name, args) \ 135 mov x8, SYS_ify (syscall_name); \ 136 svc 0 137 138 #endif /* __ASSEMBLER__ */ 139 140 #endif /* linux/aarch64/sysdep.h */ 141