1 /* Copyright (C) 1992-2022 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library. If not, see 16 <https://www.gnu.org/licenses/>. */ 17 18 #ifndef _LINUX_ALPHA_SYSDEP_H 19 #define _LINUX_ALPHA_SYSDEP_H 1 20 21 /* There is some commonality. */ 22 #include <sysdeps/unix/sysv/linux/sysdep.h> 23 #include <sysdeps/unix/sysdep.h> 24 #include <dl-sysdep.h> /* Defines RTLD_PRIVATE_ERRNO. */ 25 26 #include <tls.h> 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 #include <asm/pal.h> 37 #include <alpha/regdef.h> 38 39 #define __LABEL(x) x##: 40 41 #define LEAF(name, framesize) \ 42 .globl name; \ 43 .align 4; \ 44 .ent name, 0; \ 45 __LABEL(name) \ 46 .frame sp, framesize, ra 47 48 #define ENTRY(name) \ 49 .globl name; \ 50 .align 4; \ 51 .ent name, 0; \ 52 __LABEL(name) \ 53 .frame sp, 0, ra 54 55 /* Mark the end of function SYM. */ 56 #undef END 57 #define END(sym) .end sym 58 59 #ifdef PROF 60 # define PSEUDO_PROF \ 61 .set noat; \ 62 lda AT, _mcount; \ 63 jsr AT, (AT), _mcount; \ 64 .set at 65 #else 66 # define PSEUDO_PROF 67 #endif 68 69 #ifdef PROF 70 # define PSEUDO_PROLOGUE \ 71 .frame sp, 0, ra; \ 72 ldgp gp,0(pv); \ 73 PSEUDO_PROF; \ 74 .prologue 1 75 #elif defined PIC 76 # define PSEUDO_PROLOGUE \ 77 .frame sp, 0, ra; \ 78 .prologue 0 79 #else 80 # define PSEUDO_PROLOGUE \ 81 .frame sp, 0, ra; \ 82 ldgp gp,0(pv); \ 83 .prologue 1 84 #endif /* PROF */ 85 86 #ifdef PROF 87 # define USEPV_PROF std 88 #else 89 # define USEPV_PROF no 90 #endif 91 92 #undef SYSCALL_ERROR_LABEL 93 #if RTLD_PRIVATE_ERRNO 94 # define SYSCALL_ERROR_LABEL $syscall_error 95 # define SYSCALL_ERROR_HANDLER \ 96 $syscall_error: \ 97 stl v0, rtld_errno(gp) !gprel; \ 98 lda v0, -1; \ 99 ret 100 # define SYSCALL_ERROR_FALLTHRU 101 #elif defined(PIC) 102 # define SYSCALL_ERROR_LABEL __syscall_error !samegp 103 # define SYSCALL_ERROR_HANDLER 104 # define SYSCALL_ERROR_FALLTHRU br SYSCALL_ERROR_LABEL 105 #else 106 # define SYSCALL_ERROR_LABEL $syscall_error 107 # define SYSCALL_ERROR_HANDLER \ 108 $syscall_error: \ 109 jmp $31, __syscall_error 110 # define SYSCALL_ERROR_FALLTHRU 111 #endif /* RTLD_PRIVATE_ERRNO */ 112 113 /* Overridden by specific syscalls. */ 114 #undef PSEUDO_PREPARE_ARGS 115 #define PSEUDO_PREPARE_ARGS /* Nothing. */ 116 117 #define PSEUDO(name, syscall_name, args) \ 118 .globl name; \ 119 .align 4; \ 120 .ent name,0; \ 121 __LABEL(name) \ 122 PSEUDO_PROLOGUE; \ 123 PSEUDO_PREPARE_ARGS \ 124 lda v0, SYS_ify(syscall_name); \ 125 call_pal PAL_callsys; \ 126 bne a3, SYSCALL_ERROR_LABEL 127 128 #undef PSEUDO_END 129 #define PSEUDO_END(sym) \ 130 SYSCALL_ERROR_HANDLER; \ 131 END(sym) 132 133 #define PSEUDO_NOERRNO(name, syscall_name, args) \ 134 .globl name; \ 135 .align 4; \ 136 .ent name,0; \ 137 __LABEL(name) \ 138 PSEUDO_PROLOGUE; \ 139 PSEUDO_PREPARE_ARGS \ 140 lda v0, SYS_ify(syscall_name); \ 141 call_pal PAL_callsys; 142 143 #undef PSEUDO_END_NOERRNO 144 #define PSEUDO_END_NOERRNO(sym) END(sym) 145 146 #define ret_NOERRNO ret 147 148 #define PSEUDO_ERRVAL(name, syscall_name, args) \ 149 .globl name; \ 150 .align 4; \ 151 .ent name,0; \ 152 __LABEL(name) \ 153 PSEUDO_PROLOGUE; \ 154 PSEUDO_PREPARE_ARGS \ 155 lda v0, SYS_ify(syscall_name); \ 156 call_pal PAL_callsys; 157 158 #undef PSEUDO_END_ERRVAL 159 #define PSEUDO_END_ERRVAL(sym) END(sym) 160 161 #define ret_ERRVAL ret 162 163 #define r0 v0 164 #define r1 a4 165 166 #define MOVE(x,y) mov x,y 167 168 #else /* !ASSEMBLER */ 169 170 #define INTERNAL_SYSCALL(name, nr, args...) \ 171 internal_syscall##nr(__NR_##name, args) 172 173 #define INTERNAL_SYSCALL_NCS(name, nr, args...) \ 174 internal_syscall##nr(name, args) 175 176 /* The normal Alpha calling convention sign-extends 32-bit quantties 177 no matter what the "real" sign of the 32-bit type. We want to 178 preserve that when filling in values for the kernel. */ 179 #define syscall_promote(arg) \ 180 (sizeof (arg) == 4 ? (long int)(int)(long int)(arg) : (long int)(arg)) 181 182 #define internal_syscall_clobbers \ 183 "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \ 184 "$22", "$23", "$24", "$25", "$27", "$28", "memory" 185 186 /* It is moderately important optimization-wise to limit the lifetime 187 of the hard-register variables as much as possible. Thus we copy 188 in/out as close to the asm as possible. */ 189 190 #define internal_syscall0(name, args...) \ 191 ({ \ 192 register long int _sc_19 __asm__("$19"); \ 193 register long int _sc_0 = name; \ 194 __asm__ __volatile__ \ 195 ("callsys # %0 %1 <= %2" \ 196 : "+v"(_sc_0), "=r"(_sc_19) \ 197 : : internal_syscall_clobbers, \ 198 "$16", "$17", "$18", "$20", "$21"); \ 199 _sc_19 != 0 ? -_sc_0 : _sc_0; \ 200 }) 201 202 #define internal_syscall1(name,arg1) \ 203 ({ \ 204 register long int _tmp_16 = syscall_promote (arg1); \ 205 register long int _sc_0 = name; \ 206 register long int _sc_16 __asm__("$16") = _tmp_16; \ 207 register long int _sc_19 __asm__("$19"); \ 208 __asm__ __volatile__ \ 209 ("callsys # %0 %1 <= %2 %3" \ 210 : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16) \ 211 : : internal_syscall_clobbers, \ 212 "$17", "$18", "$20", "$21"); \ 213 _sc_19 != 0 ? -_sc_0 : _sc_0; \ 214 }) 215 216 #define internal_syscall2(name,arg1,arg2) \ 217 ({ \ 218 register long int _tmp_16 = syscall_promote (arg1); \ 219 register long int _tmp_17 = syscall_promote (arg2); \ 220 register long int _sc_0 = name; \ 221 register long int _sc_16 __asm__("$16") = _tmp_16; \ 222 register long int _sc_17 __asm__("$17") = _tmp_17; \ 223 register long int _sc_19 __asm__("$19"); \ 224 __asm__ __volatile__ \ 225 ("callsys # %0 %1 <= %2 %3 %4" \ 226 : "+v"(_sc_0), "=r"(_sc_19), \ 227 "+r"(_sc_16), "+r"(_sc_17) \ 228 : : internal_syscall_clobbers, \ 229 "$18", "$20", "$21"); \ 230 _sc_19 != 0 ? -_sc_0 : _sc_0; \ 231 }) 232 233 #define internal_syscall3(name,arg1,arg2,arg3) \ 234 ({ \ 235 register long int _tmp_16 = syscall_promote (arg1); \ 236 register long int _tmp_17 = syscall_promote (arg2); \ 237 register long int _tmp_18 = syscall_promote (arg3); \ 238 register long int _sc_0 = name; \ 239 register long int _sc_16 __asm__("$16") = _tmp_16; \ 240 register long int _sc_17 __asm__("$17") = _tmp_17; \ 241 register long int _sc_18 __asm__("$18") = _tmp_18; \ 242 register long int _sc_19 __asm__("$19"); \ 243 __asm__ __volatile__ \ 244 ("callsys # %0 %1 <= %2 %3 %4 %5" \ 245 : "+v"(_sc_0), "=r"(_sc_19), "+r"(_sc_16), \ 246 "+r"(_sc_17), "+r"(_sc_18) \ 247 : : internal_syscall_clobbers, "$20", "$21"); \ 248 _sc_19 != 0 ? -_sc_0 : _sc_0; \ 249 }) 250 251 #define internal_syscall4(name,arg1,arg2,arg3,arg4) \ 252 ({ \ 253 register long int _tmp_16 = syscall_promote (arg1); \ 254 register long int _tmp_17 = syscall_promote (arg2); \ 255 register long int _tmp_18 = syscall_promote (arg3); \ 256 register long int _tmp_19 = syscall_promote (arg4); \ 257 register long int _sc_0 = name; \ 258 register long int _sc_16 __asm__("$16") = _tmp_16; \ 259 register long int _sc_17 __asm__("$17") = _tmp_17; \ 260 register long int _sc_18 __asm__("$18") = _tmp_18; \ 261 register long int _sc_19 __asm__("$19") = _tmp_19; \ 262 __asm__ __volatile__ \ 263 ("callsys # %0 %1 <= %2 %3 %4 %5 %6" \ 264 : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16), \ 265 "+r"(_sc_17), "+r"(_sc_18) \ 266 : : internal_syscall_clobbers, "$20", "$21"); \ 267 _sc_19 != 0 ? -_sc_0 : _sc_0; \ 268 }) 269 270 #define internal_syscall5(name,arg1,arg2,arg3,arg4,arg5) \ 271 ({ \ 272 register long int _tmp_16 = syscall_promote (arg1); \ 273 register long int _tmp_17 = syscall_promote (arg2); \ 274 register long int _tmp_18 = syscall_promote (arg3); \ 275 register long int _tmp_19 = syscall_promote (arg4); \ 276 register long int _tmp_20 = syscall_promote (arg5); \ 277 register long int _sc_0 = name; \ 278 register long int _sc_16 __asm__("$16") = _tmp_16; \ 279 register long int _sc_17 __asm__("$17") = _tmp_17; \ 280 register long int _sc_18 __asm__("$18") = _tmp_18; \ 281 register long int _sc_19 __asm__("$19") = _tmp_19; \ 282 register long int _sc_20 __asm__("$20") = _tmp_20; \ 283 __asm__ __volatile__ \ 284 ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7" \ 285 : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16), \ 286 "+r"(_sc_17), "+r"(_sc_18), "+r"(_sc_20) \ 287 : : internal_syscall_clobbers, "$21"); \ 288 _sc_19 != 0 ? -_sc_0 : _sc_0; \ 289 }) 290 291 #define internal_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \ 292 ({ \ 293 register long int _tmp_16 = syscall_promote (arg1); \ 294 register long int _tmp_17 = syscall_promote (arg2); \ 295 register long int _tmp_18 = syscall_promote (arg3); \ 296 register long int _tmp_19 = syscall_promote (arg4); \ 297 register long int _tmp_20 = syscall_promote (arg5); \ 298 register long int _tmp_21 = syscall_promote (arg6); \ 299 register long int _sc_0 = name; \ 300 register long int _sc_16 __asm__("$16") = _tmp_16; \ 301 register long int _sc_17 __asm__("$17") = _tmp_17; \ 302 register long int _sc_18 __asm__("$18") = _tmp_18; \ 303 register long int _sc_19 __asm__("$19") = _tmp_19; \ 304 register long int _sc_20 __asm__("$20") = _tmp_20; \ 305 register long int _sc_21 __asm__("$21") = _tmp_21; \ 306 __asm__ __volatile__ \ 307 ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8" \ 308 : "+v"(_sc_0), "+r"(_sc_19), "+r"(_sc_16), \ 309 "+r"(_sc_17), "+r"(_sc_18), "+r"(_sc_20), \ 310 "+r"(_sc_21) \ 311 : : internal_syscall_clobbers); \ 312 _sc_19 != 0 ? -_sc_0 : _sc_0; \ 313 }) 314 #endif /* ASSEMBLER */ 315 316 /* Pointer mangling support. Note that tls access is slow enough that 317 we don't deoptimize things by placing the pointer check value there. */ 318 319 #ifdef __ASSEMBLER__ 320 # if IS_IN (rtld) 321 # define PTR_MANGLE(dst, src, tmp) \ 322 ldah tmp, __pointer_chk_guard_local($29) !gprelhigh; \ 323 ldq tmp, __pointer_chk_guard_local(tmp) !gprellow; \ 324 xor src, tmp, dst 325 # define PTR_MANGLE2(dst, src, tmp) \ 326 xor src, tmp, dst 327 # elif defined SHARED 328 # define PTR_MANGLE(dst, src, tmp) \ 329 ldq tmp, __pointer_chk_guard; \ 330 xor src, tmp, dst 331 # else 332 # define PTR_MANGLE(dst, src, tmp) \ 333 ldq tmp, __pointer_chk_guard_local; \ 334 xor src, tmp, dst 335 # endif 336 # define PTR_MANGLE2(dst, src, tmp) \ 337 xor src, tmp, dst 338 # define PTR_DEMANGLE(dst, tmp) PTR_MANGLE(dst, dst, tmp) 339 # define PTR_DEMANGLE2(dst, tmp) PTR_MANGLE2(dst, dst, tmp) 340 #else 341 # include <stdint.h> 342 # if (IS_IN (rtld) \ 343 || (!defined SHARED && (IS_IN (libc) \ 344 || IS_IN (libpthread)))) 345 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; 346 # define PTR_MANGLE(var) \ 347 (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) 348 # else 349 extern uintptr_t __pointer_chk_guard attribute_relro; 350 # define PTR_MANGLE(var) \ 351 (var) = (__typeof(var)) ((uintptr_t) (var) ^ __pointer_chk_guard) 352 # endif 353 # define PTR_DEMANGLE(var) PTR_MANGLE(var) 354 #endif /* ASSEMBLER */ 355 356 #endif /* _LINUX_ALPHA_SYSDEP_H */ 357