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