1/* Copyright (C) 2001-2025 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_X86_64_SYSDEP_H
 19#define _LINUX_X86_64_SYSDEP_H 1
 20
 21/* There is some commonality.  */
 22#include <sysdeps/unix/sysv/linux/sysdep.h>
 23#include <sysdeps/unix/x86_64/sysdep.h>
 24#include <tls.h>
 25
 26/* Defines RTLD_PRIVATE_ERRNO.  */
 27#include <dl-sysdep.h>
 28
 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.  */
 33#undef SYS_ify
 34#define SYS_ify(syscall_name)	__NR_##syscall_name
 35
 36#ifdef __ASSEMBLER__
 37
 38/* Linux uses a negative return value to indicate syscall errors,
 39   unlike most Unices, which use the condition codes' carry flag.
 40
 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
 47   test with -4095.  */
 48
 49/* We don't want the label for the error handle to be global when we define
 50   it here.  */
 51# undef SYSCALL_ERROR_LABEL
 52# ifdef PIC
 53#  undef SYSCALL_ERROR_LABEL
 54#  define SYSCALL_ERROR_LABEL 0f
 55# else
 56#  undef SYSCALL_ERROR_LABEL
 57#  define SYSCALL_ERROR_LABEL syscall_error
 58# endif
 59
 60/* PSEUDO and T_PSEUDO macros have 2 extra arguments for unsigned long
 61   int arguments.  */
 62# define PSEUDOS_HAVE_ULONG_INDICES 1
 63
 64# ifndef SYSCALL_ULONG_ARG_1
 65#  define SYSCALL_ULONG_ARG_1 0
 66#  define SYSCALL_ULONG_ARG_2 0
 67# endif
 68
 69# undef	PSEUDO
 70# if SYSCALL_ULONG_ARG_1
 71#  define PSEUDO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
 72  .text;							      \
 73  ENTRY (name)							      \
 74    DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2);	      \
 75    cmpq $-4095, %rax;						      \
 76    jae SYSCALL_ERROR_LABEL
 77# else
 78#  define PSEUDO(name, syscall_name, args) \
 79  .text;							      \
 80  ENTRY (name)							      \
 81    DO_CALL (syscall_name, args, 0, 0);				      \
 82    cmpq $-4095, %rax;						      \
 83    jae SYSCALL_ERROR_LABEL
 84# endif
 85
 86# undef	PSEUDO_END
 87# define PSEUDO_END(name)						      \
 88  SYSCALL_ERROR_HANDLER							      \
 89  END (name)
 90
 91# undef	PSEUDO_NOERRNO
 92# if SYSCALL_ULONG_ARG_1
 93#  define PSEUDO_NOERRNO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
 94  .text;							      \
 95  ENTRY (name)							      \
 96    DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2)
 97# else
 98#  define PSEUDO_NOERRNO(name, syscall_name, args) \
 99  .text;							      \
100  ENTRY (name)							      \
101    DO_CALL (syscall_name, args, 0, 0)
102# endif
103
104# undef	PSEUDO_END_NOERRNO
105# define PSEUDO_END_NOERRNO(name) \
106  END (name)
107
108# define ret_NOERRNO ret
109
110# undef	PSEUDO_ERRVAL
111# if SYSCALL_ULONG_ARG_1
112#  define PSEUDO_ERRVAL(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
113  .text;							\
114  ENTRY (name)							\
115    DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2);	\
116    negq %rax
117# else
118#  define PSEUDO_ERRVAL(name, syscall_name, args) \
119  .text;							\
120  ENTRY (name)							\
121    DO_CALL (syscall_name, args, 0, 0);				\
122    negq %rax
123# endif
124
125# undef	PSEUDO_END_ERRVAL
126# define PSEUDO_END_ERRVAL(name) \
127  END (name)
128
129# define ret_ERRVAL ret
130
131# if defined PIC && RTLD_PRIVATE_ERRNO
132#  define SYSCALL_SET_ERRNO			\
133  lea rtld_errno(%rip), %RCX_LP;		\
134  neg %eax;					\
135  movl %eax, (%rcx)
136# else
137#  if IS_IN (libc)
138#   define SYSCALL_ERROR_ERRNO __libc_errno
139#  else
140#   define SYSCALL_ERROR_ERRNO errno
141#  endif
142#  define SYSCALL_SET_ERRNO			\
143  movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
144  neg %eax;					\
145  movl %eax, %fs:(%rcx);
146# endif
147
148# ifndef PIC
149#  define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
150# else
151#  define SYSCALL_ERROR_HANDLER			\
1520:						\
153  SYSCALL_SET_ERRNO;				\
154  or $-1, %RAX_LP;				\
155  ret;
156# endif	/* PIC */
157
158/* The Linux/x86-64 kernel expects the system call parameters in
159   registers according to the following table:
160
161    syscall number	rax
162    arg 1		rdi
163    arg 2		rsi
164    arg 3		rdx
165    arg 4		r10
166    arg 5		r8
167    arg 6		r9
168
169    The Linux kernel uses and destroys internally these registers:
170    return address from
171    syscall		rcx
172    eflags from syscall	r11
173
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:
178
179     system call number	in the DO_CALL macro
180     arg 1		rdi
181     arg 2		rsi
182     arg 3		rdx
183     arg 4		rcx
184     arg 5		r8
185     arg 6		r9
186
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
189    been pushed.
190
191
192    Syscalls of more than 6 arguments are not supported.  */
193
194# undef	DO_CALL
195# define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \
196    DOARGS_##args				\
197    ZERO_EXTEND_##ulong_arg_1			\
198    ZERO_EXTEND_##ulong_arg_2			\
199    movl $SYS_ify (syscall_name), %eax;		\
200    syscall;
201
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
209
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 */
217
218#else	/* !__ASSEMBLER__ */
219
220/* Registers clobbered by syscall.  */
221# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
222
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
230   explicit types.  */
231#define TYPEFY(X, name) __typeof__ (ARGIFY (X)) name
232
233#undef INTERNAL_SYSCALL
234#define INTERNAL_SYSCALL(name, nr, args...)				\
235	internal_syscall##nr (SYS_ify (name), args)
236
237#undef INTERNAL_SYSCALL_NCS
238#define INTERNAL_SYSCALL_NCS(number, nr, args...)			\
239	internal_syscall##nr (number, args)
240
241#undef internal_syscall0
242#define internal_syscall0(number, dummy...)				\
243({									\
244    unsigned long int resultvar;					\
245    asm volatile (							\
246    "syscall\n\t"							\
247    : "=a" (resultvar)							\
248    : "0" (number)							\
249    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
250    (long int) resultvar;						\
251})
252
253#undef internal_syscall1
254#define internal_syscall1(number, arg1)					\
255({									\
256    unsigned long int resultvar;					\
257    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
258    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
259    asm volatile (							\
260    "syscall\n\t"							\
261    : "=a" (resultvar)							\
262    : "0" (number), "r" (_a1)						\
263    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
264    (long int) resultvar;						\
265})
266
267#undef internal_syscall2
268#define internal_syscall2(number, arg1, arg2)				\
269({									\
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;			\
275    asm volatile (							\
276    "syscall\n\t"							\
277    : "=a" (resultvar)							\
278    : "0" (number), "r" (_a1), "r" (_a2)				\
279    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
280    (long int) resultvar;						\
281})
282
283#undef internal_syscall3
284#define internal_syscall3(number, arg1, arg2, arg3)			\
285({									\
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;			\
293    asm volatile (							\
294    "syscall\n\t"							\
295    : "=a" (resultvar)							\
296    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3)			\
297    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
298    (long int) resultvar;						\
299})
300
301#undef internal_syscall4
302#define internal_syscall4(number, arg1, arg2, arg3, arg4)		\
303({									\
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;			\
313    asm volatile (							\
314    "syscall\n\t"							\
315    : "=a" (resultvar)							\
316    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4)		\
317    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
318    (long int) resultvar;						\
319})
320
321#undef internal_syscall5
322#define internal_syscall5(number, arg1, arg2, arg3, arg4, arg5)	\
323({									\
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;			\
335    asm volatile (							\
336    "syscall\n\t"							\
337    : "=a" (resultvar)							\
338    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\
339      "r" (_a5)								\
340    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
341    (long int) resultvar;						\
342})
343
344#undef internal_syscall6
345#define internal_syscall6(number, arg1, arg2, arg3, arg4, arg5, arg6) \
346({									\
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;			\
360    asm volatile (							\
361    "syscall\n\t"							\
362    : "=a" (resultvar)							\
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;						\
367})
368
369
370# define VDSO_NAME  "LINUX_2.6"
371# define VDSO_HASH  61765110
372
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"
379# define HAVE_GETRANDOM_VSYSCALL        "__vdso_getrandom"
380
381# define HAVE_CLONE3_WRAPPER			1
382
383#endif	/* __ASSEMBLER__ */
384
385/* How to pass the off{64}_t argument on p{readv,writev}{64}.  */
386#undef LO_HI_LONG
387#define LO_HI_LONG(val) (val), 0
388
389/* Each shadow stack slot takes 8 bytes.  Assuming that each stack
390   frame takes 256 bytes, this is used to compute shadow stack size
391   from stack size.  */
392#define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
393
394#endif /* linux/x86_64/sysdep.h */