1 /* Copyright (C) 2001-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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/>. */
18 #ifndef _LINUX_X86_64_SYSDEP_H
19 #define _LINUX_X86_64_SYSDEP_H 1
21 /* There is some commonality. */
22 #include <sysdeps/unix/sysv/linux/sysdep.h>
23 #include <sysdeps/unix/x86_64/sysdep.h>
26 /* Defines RTLD_PRIVATE_ERRNO. */
27 #include <dl-sysdep.h>
29 /* For Linux we can use the system call table in the header file
30 /usr/include/asm/unistd.h
31 of the kernel. But these symbols do not follow the SYS_* syntax
32 so we have to redefine the `SYS_ify' macro here. */
34 #define SYS_ify(syscall_name) __NR_##syscall_name
38 /* Linux uses a negative return value to indicate syscall errors,
39 unlike most Unices, which use the condition codes' carry flag.
41 Since version 2.1 the return value of a system call might be
42 negative even if the call succeeded. E.g., the `lseek' system call
43 might return a large offset. Therefore we must not anymore test
44 for < 0, but test for a real error by making sure the value in %eax
45 is a real error number. Linus said he will make sure the no syscall
46 returns a value in -1 .. -4095 as a valid result so we can safely
49 /* We don't want the label for the error handle to be global when we define
51 # undef SYSCALL_ERROR_LABEL
53 # undef SYSCALL_ERROR_LABEL
54 # define SYSCALL_ERROR_LABEL 0f
56 # undef SYSCALL_ERROR_LABEL
57 # define SYSCALL_ERROR_LABEL syscall_error
60 /* PSEUDO and T_PSEUDO macros have 2 extra arguments for unsigned long
62 # define PSEUDOS_HAVE_ULONG_INDICES 1
64 # ifndef SYSCALL_ULONG_ARG_1
65 # define SYSCALL_ULONG_ARG_1 0
66 # define SYSCALL_ULONG_ARG_2 0
70 # if SYSCALL_ULONG_ARG_1
71 # define PSEUDO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
74 DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \
76 jae SYSCALL_ERROR_LABEL
78 # define PSEUDO(name, syscall_name, args) \
81 DO_CALL (syscall_name, args, 0, 0); \
83 jae SYSCALL_ERROR_LABEL
87 # define PSEUDO_END(name) \
88 SYSCALL_ERROR_HANDLER \
91 # undef PSEUDO_NOERRNO
92 # if SYSCALL_ULONG_ARG_1
93 # define PSEUDO_NOERRNO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
96 DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2)
98 # define PSEUDO_NOERRNO(name, syscall_name, args) \
101 DO_CALL (syscall_name, args, 0, 0)
104 # undef PSEUDO_END_NOERRNO
105 # define PSEUDO_END_NOERRNO(name) \
108 # define ret_NOERRNO ret
110 # undef PSEUDO_ERRVAL
111 # if SYSCALL_ULONG_ARG_1
112 # define PSEUDO_ERRVAL(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
115 DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2); \
118 # define PSEUDO_ERRVAL(name, syscall_name, args) \
121 DO_CALL (syscall_name, args, 0, 0); \
125 # undef PSEUDO_END_ERRVAL
126 # define PSEUDO_END_ERRVAL(name) \
129 # define ret_ERRVAL ret
131 # if defined PIC && RTLD_PRIVATE_ERRNO
132 # define SYSCALL_SET_ERRNO \
133 lea rtld_errno(%rip), %RCX_LP; \
138 # define SYSCALL_ERROR_ERRNO __libc_errno
140 # define SYSCALL_ERROR_ERRNO errno
142 # define SYSCALL_SET_ERRNO \
143 movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
145 movl %eax, %fs:(%rcx);
149 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
151 # define SYSCALL_ERROR_HANDLER \
158 /* The Linux/x86-64 kernel expects the system call parameters in
159 registers according to the following table:
169 The Linux kernel uses and destroys internally these registers:
172 eflags from syscall r11
174 Normal function call, including calls to the system call stub
175 functions in the libc, get the first six parameters passed in
176 registers and the seventh parameter and later on the stack. The
177 register use is as follows:
179 system call number in the DO_CALL macro
187 We have to take care that the stack is aligned to 16 bytes. When
188 called the stack is not aligned since the return address has just
192 Syscalls of more than 6 arguments are not supported. */
195 # define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \
197 ZERO_EXTEND_##ulong_arg_1 \
198 ZERO_EXTEND_##ulong_arg_2 \
199 movl $SYS_ify (syscall_name), %eax; \
202 # define DOARGS_0 /* nothing */
203 # define DOARGS_1 /* nothing */
204 # define DOARGS_2 /* nothing */
205 # define DOARGS_3 /* nothing */
206 # define DOARGS_4 movq %rcx, %r10;
207 # define DOARGS_5 DOARGS_4
208 # define DOARGS_6 DOARGS_5
210 # define ZERO_EXTEND_0 /* nothing */
211 # define ZERO_EXTEND_1 /* nothing */
212 # define ZERO_EXTEND_2 /* nothing */
213 # define ZERO_EXTEND_3 /* nothing */
214 # define ZERO_EXTEND_4 /* nothing */
215 # define ZERO_EXTEND_5 /* nothing */
216 # define ZERO_EXTEND_6 /* nothing */
218 #else /* !__ASSEMBLER__ */
220 /* Registers clobbered by syscall. */
221 # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
223 /* NB: This also works when X is an array. For an array X, type of
224 (X) - (X) is ptrdiff_t, which is signed, since size of ptrdiff_t
225 == size of pointer, cast is a NOP. */
226 #define TYPEFY1(X) __typeof__ ((X) - (X))
227 /* Explicit cast the argument. */
228 #define ARGIFY(X) ((TYPEFY1 (X)) (X))
229 /* Create a variable 'name' based on type of variable 'X' to avoid
231 #define TYPEFY(X, name) __typeof__ (ARGIFY (X)) name
233 #undef INTERNAL_SYSCALL
234 #define INTERNAL_SYSCALL(name, nr, args...) \
235 internal_syscall##nr (SYS_ify (name), args)
237 #undef INTERNAL_SYSCALL_NCS
238 #define INTERNAL_SYSCALL_NCS(number, nr, args...) \
239 internal_syscall##nr (number, args)
241 #undef internal_syscall0
242 #define internal_syscall0(number, dummy...) \
244 unsigned long int resultvar; \
249 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
250 (long int) resultvar; \
253 #undef internal_syscall1
254 #define internal_syscall1(number, arg1) \
256 unsigned long int resultvar; \
257 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
258 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
262 : "0" (number), "r" (_a1) \
263 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
264 (long int) resultvar; \
267 #undef internal_syscall2
268 #define internal_syscall2(number, arg1, arg2) \
270 unsigned long int resultvar; \
271 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
272 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
273 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
274 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
278 : "0" (number), "r" (_a1), "r" (_a2) \
279 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
280 (long int) resultvar; \
283 #undef internal_syscall3
284 #define internal_syscall3(number, arg1, arg2, arg3) \
286 unsigned long int resultvar; \
287 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
288 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
289 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
290 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
291 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
292 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
296 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3) \
297 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
298 (long int) resultvar; \
301 #undef internal_syscall4
302 #define internal_syscall4(number, arg1, arg2, arg3, arg4) \
304 unsigned long int resultvar; \
305 TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
306 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
307 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
308 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
309 register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
310 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
311 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
312 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
316 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4) \
317 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
318 (long int) resultvar; \
321 #undef internal_syscall5
322 #define internal_syscall5(number, arg1, arg2, arg3, arg4, arg5) \
324 unsigned long int resultvar; \
325 TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
326 TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
327 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
328 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
329 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
330 register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
331 register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
332 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
333 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
334 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
338 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
340 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
341 (long int) resultvar; \
344 #undef internal_syscall6
345 #define internal_syscall6(number, arg1, arg2, arg3, arg4, arg5, arg6) \
347 unsigned long int resultvar; \
348 TYPEFY (arg6, __arg6) = ARGIFY (arg6); \
349 TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
350 TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
351 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
352 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
353 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
354 register TYPEFY (arg6, _a6) asm ("r9") = __arg6; \
355 register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
356 register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
357 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
358 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
359 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
363 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
364 "r" (_a5), "r" (_a6) \
365 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
366 (long int) resultvar; \
370 # define VDSO_NAME "LINUX_2.6"
371 # define VDSO_HASH 61765110
373 /* List of system calls which are supported as vsyscalls. */
374 # define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime"
375 # define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday"
376 # define HAVE_TIME_VSYSCALL "__vdso_time"
377 # define HAVE_GETCPU_VSYSCALL "__vdso_getcpu"
378 # define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres"
380 # define HAVE_CLONE3_WRAPPER 1
382 #endif /* __ASSEMBLER__ */
384 /* How to pass the off{64}_t argument on p{readv,writev}{64}. */
386 #define LO_HI_LONG(val) (val), 0
388 /* Each shadow stack slot takes 8 bytes. Assuming that each stack
389 frame takes 256 bytes, this is used to compute shadow stack size
391 #define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
393 #endif /* linux/x86_64/sysdep.h */