master
  1/* Copyright (C) 1992-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_I386_SYSDEP_H
 19#define _LINUX_I386_SYSDEP_H 1
 20
 21/* There is some commonality.  */
 22#include <sysdeps/unix/sysv/linux/sysdep.h>
 23#include <sysdeps/unix/i386/sysdep.h>
 24/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
 25#include <dl-sysdep.h>
 26#include <tls.h>
 27
 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#ifndef I386_USE_SYSENTER
 37# if defined USE_DL_SYSINFO \
 38     && (IS_IN (libc) || IS_IN (libpthread))
 39#  define I386_USE_SYSENTER	1
 40# else
 41#  define I386_USE_SYSENTER	0
 42# endif
 43#endif
 44
 45#if !I386_USE_SYSENTER && IS_IN (libc) && !defined SHARED
 46/* Inside static libc, we have two versions.  For compilation units
 47   with !I386_USE_SYSENTER, the vDSO entry mechanism cannot be
 48   used. */
 49# define I386_DO_SYSCALL_STRING "__libc_do_syscall_int80"
 50#else
 51# define I386_DO_SYSCALL_STRING "__libc_do_syscall"
 52#endif
 53
 54#ifdef __ASSEMBLER__
 55
 56/* Linux uses a negative return value to indicate syscall errors,
 57   unlike most Unices, which use the condition codes' carry flag.
 58
 59   Since version 2.1 the return value of a system call might be
 60   negative even if the call succeeded.  E.g., the `lseek' system call
 61   might return a large offset.  Therefore we must not anymore test
 62   for < 0, but test for a real error by making sure the value in %eax
 63   is a real error number.  Linus said he will make sure the no syscall
 64   returns a value in -1 .. -4095 as a valid result so we can safely
 65   test with -4095.  */
 66
 67/* We don't want the label for the error handle to be global when we define
 68   it here.  */
 69#undef SYSCALL_ERROR_LABEL
 70#define SYSCALL_ERROR_LABEL __syscall_error
 71
 72#undef	PSEUDO
 73#define	PSEUDO(name, syscall_name, args)				      \
 74  .text;								      \
 75  ENTRY (name)								      \
 76    DO_CALL (syscall_name, args);					      \
 77    cmpl $-4095, %eax;							      \
 78    jae SYSCALL_ERROR_LABEL
 79
 80#undef	PSEUDO_END
 81#define	PSEUDO_END(name)						      \
 82  SYSCALL_ERROR_HANDLER							      \
 83  END (name)
 84
 85#undef	PSEUDO_NOERRNO
 86#define	PSEUDO_NOERRNO(name, syscall_name, args)			      \
 87  .text;								      \
 88  ENTRY (name)								      \
 89    DO_CALL (syscall_name, args)
 90
 91#undef	PSEUDO_END_NOERRNO
 92#define	PSEUDO_END_NOERRNO(name)					      \
 93  END (name)
 94
 95#define ret_NOERRNO ret
 96
 97/* The function has to return the error code.  */
 98#undef	PSEUDO_ERRVAL
 99#define	PSEUDO_ERRVAL(name, syscall_name, args) \
100  .text;								      \
101  ENTRY (name)								      \
102    DO_CALL (syscall_name, args);					      \
103    negl %eax
104
105#undef	PSEUDO_END_ERRVAL
106#define	PSEUDO_END_ERRVAL(name) \
107  END (name)
108
109#define ret_ERRVAL ret
110
111#define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.c is used.  */
112
113/* The original calling convention for system calls on Linux/i386 is
114   to use int $0x80.  */
115#if I386_USE_SYSENTER
116# ifdef PIC
117#  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
118# else
119#  define ENTER_KERNEL call *_dl_sysinfo
120# endif
121#else
122# define ENTER_KERNEL int $0x80
123#endif
124
125/* Linux takes system call arguments in registers:
126
127	syscall number	%eax	     call-clobbered
128	arg 1		%ebx	     call-saved
129	arg 2		%ecx	     call-clobbered
130	arg 3		%edx	     call-clobbered
131	arg 4		%esi	     call-saved
132	arg 5		%edi	     call-saved
133	arg 6		%ebp	     call-saved
134
135   The stack layout upon entering the function is:
136
137	24(%esp)	Arg# 6
138	20(%esp)	Arg# 5
139	16(%esp)	Arg# 4
140	12(%esp)	Arg# 3
141	 8(%esp)	Arg# 2
142	 4(%esp)	Arg# 1
143	  (%esp)	Return address
144
145   (Of course a function with say 3 arguments does not have entries for
146   arguments 4, 5, and 6.)
147
148   The following code tries hard to be optimal.  A general assumption
149   (which is true according to the data books I have) is that
150
151	2 * xchg	is more expensive than	pushl + movl + popl
152
153   Beside this a neat trick is used.  The calling conventions for Linux
154   tell that among the registers used for parameters %ecx and %edx need
155   not be saved.  Beside this we may clobber this registers even when
156   they are not used for parameter passing.
157
158   As a result one can see below that we save the content of the %ebx
159   register in the %edx register when we have less than 3 arguments
160   (2 * movl is less expensive than pushl + popl).
161
162   Second unlike for the other registers we don't save the content of
163   %ecx and %edx when we have more than 1 and 2 registers resp.
164
165   The code below might look a bit long but we have to take care for
166   the pipelined processors (i586).  Here the `pushl' and `popl'
167   instructions are marked as NP (not pairable) but the exception is
168   two consecutive of these instruction.  This gives no penalty on
169   other processors though.  */
170
171#undef	DO_CALL
172#define DO_CALL(syscall_name, args)			      		      \
173    PUSHARGS_##args							      \
174    DOARGS_##args							      \
175    movl $SYS_ify (syscall_name), %eax;					      \
176    ENTER_KERNEL							      \
177    POPARGS_##args
178
179#define PUSHARGS_0	/* No arguments to push.  */
180#define	DOARGS_0	/* No arguments to frob.  */
181#define	POPARGS_0	/* No arguments to pop.  */
182#define	_PUSHARGS_0	/* No arguments to push.  */
183#define _DOARGS_0(n)	/* No arguments to frob.  */
184#define	_POPARGS_0	/* No arguments to pop.  */
185
186#define PUSHARGS_1	movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0
187#define	DOARGS_1	_DOARGS_1 (4)
188#define	POPARGS_1	POPARGS_0; movl %edx, %ebx; L(RESTBX1):
189#define	_PUSHARGS_1	pushl %ebx; cfi_adjust_cfa_offset (4); \
190			cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0
191#define _DOARGS_1(n)	movl n(%esp), %ebx; _DOARGS_0(n-4)
192#define	_POPARGS_1	_POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \
193			cfi_restore (ebx); L(POPBX1):
194
195#define PUSHARGS_2	PUSHARGS_1
196#define	DOARGS_2	_DOARGS_2 (8)
197#define	POPARGS_2	POPARGS_1
198#define _PUSHARGS_2	_PUSHARGS_1
199#define	_DOARGS_2(n)	movl n(%esp), %ecx; _DOARGS_1 (n-4)
200#define	_POPARGS_2	_POPARGS_1
201
202#define PUSHARGS_3	_PUSHARGS_2
203#define DOARGS_3	_DOARGS_3 (16)
204#define POPARGS_3	_POPARGS_3
205#define _PUSHARGS_3	_PUSHARGS_2
206#define _DOARGS_3(n)	movl n(%esp), %edx; _DOARGS_2 (n-4)
207#define _POPARGS_3	_POPARGS_2
208
209#define PUSHARGS_4	_PUSHARGS_4
210#define DOARGS_4	_DOARGS_4 (24)
211#define POPARGS_4	_POPARGS_4
212#define _PUSHARGS_4	pushl %esi; cfi_adjust_cfa_offset (4); \
213			cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3
214#define _DOARGS_4(n)	movl n(%esp), %esi; _DOARGS_3 (n-4)
215#define _POPARGS_4	_POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \
216			cfi_restore (esi); L(POPSI1):
217
218#define PUSHARGS_5	_PUSHARGS_5
219#define DOARGS_5	_DOARGS_5 (32)
220#define POPARGS_5	_POPARGS_5
221#define _PUSHARGS_5	pushl %edi; cfi_adjust_cfa_offset (4); \
222			cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4
223#define _DOARGS_5(n)	movl n(%esp), %edi; _DOARGS_4 (n-4)
224#define _POPARGS_5	_POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \
225			cfi_restore (edi); L(POPDI1):
226
227#define PUSHARGS_6	_PUSHARGS_6
228#define DOARGS_6	_DOARGS_6 (40)
229#define POPARGS_6	_POPARGS_6
230#define _PUSHARGS_6	pushl %ebp; cfi_adjust_cfa_offset (4); \
231			cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5
232#define _DOARGS_6(n)	movl n(%esp), %ebp; _DOARGS_5 (n-4)
233#define _POPARGS_6	_POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \
234			cfi_restore (ebp); L(POPBP1):
235
236#else	/* !__ASSEMBLER__ */
237
238extern int __syscall_error (int)
239  attribute_hidden __attribute__ ((__regparm__ (1)));
240
241/* Six-argument syscalls use an out-of-line helper, because an inline
242   asm using all registers apart from %esp cannot work reliably and
243   the assembler does not support describing an asm that saves and
244   restores %ebp itself as a separate stack frame.  This structure
245   stores the arguments not passed in registers; %edi is passed with a
246   pointer to this structure.  */
247struct libc_do_syscall_args
248{
249  int ebx, edi, ebp;
250};
251
252# define VDSO_NAME  "LINUX_2.6"
253# define VDSO_HASH  61765110
254
255/* List of system calls which are supported as vsyscalls.  */
256# define HAVE_CLOCK_GETTIME_VSYSCALL    "__vdso_clock_gettime"
257# define HAVE_CLOCK_GETTIME64_VSYSCALL  "__vdso_clock_gettime64"
258# define HAVE_GETTIMEOFDAY_VSYSCALL     "__vdso_gettimeofday"
259# define HAVE_TIME_VSYSCALL             "__vdso_time"
260# define HAVE_CLOCK_GETRES_VSYSCALL     "__vdso_clock_getres"
261
262# define HAVE_CLONE3_WRAPPER		1
263
264# undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
265# define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
266
267/* Define a macro which expands inline into the wrapper code for a system
268   call.  This use is for internal calls that do not need to handle errors
269   normally.  It will never touch errno.  This returns just what the kernel
270   gave back.
271
272   The _NCS variant allows non-constant syscall numbers but it is not
273   possible to use more than four parameters.  */
274#undef INTERNAL_SYSCALL
275#define INTERNAL_SYSCALL_MAIN_0(name, args...) \
276    INTERNAL_SYSCALL_MAIN_INLINE(name, 0, args)
277#define INTERNAL_SYSCALL_MAIN_1(name, args...) \
278    INTERNAL_SYSCALL_MAIN_INLINE(name, 1, args)
279#define INTERNAL_SYSCALL_MAIN_2(name, args...) \
280    INTERNAL_SYSCALL_MAIN_INLINE(name, 2, args)
281#define INTERNAL_SYSCALL_MAIN_3(name, args...) \
282    INTERNAL_SYSCALL_MAIN_INLINE(name, 3, args)
283#define INTERNAL_SYSCALL_MAIN_4(name, args...) \
284    INTERNAL_SYSCALL_MAIN_INLINE(name, 4, args)
285#define INTERNAL_SYSCALL_MAIN_5(name, args...) \
286    INTERNAL_SYSCALL_MAIN_INLINE(name, 5, args)
287
288#define INTERNAL_SYSCALL_MAIN_NCS_0(name, args...) \
289    INTERNAL_SYSCALL_MAIN_NCS(name, 0, args)
290#define INTERNAL_SYSCALL_MAIN_NCS_1(name, args...) \
291    INTERNAL_SYSCALL_MAIN_NCS(name, 1, args)
292#define INTERNAL_SYSCALL_MAIN_NCS_2(name, args...) \
293    INTERNAL_SYSCALL_MAIN_NCS(name, 2, args)
294#define INTERNAL_SYSCALL_MAIN_NCS_3(name, args...) \
295    INTERNAL_SYSCALL_MAIN_NCS(name, 3, args)
296#define INTERNAL_SYSCALL_MAIN_NCS_4(name, args...) \
297    INTERNAL_SYSCALL_MAIN_NCS(name, 4, args)
298#define INTERNAL_SYSCALL_MAIN_NCS_5(name, args...) \
299    INTERNAL_SYSCALL_MAIN_NCS(name, 5, args)
300
301/* Each object using 6-argument inline syscalls must include a
302   definition of __libc_do_syscall.  */
303#define INTERNAL_SYSCALL_MAIN_6(name, arg1, arg2, arg3,			\
304				arg4, arg5, arg6)			\
305  struct libc_do_syscall_args _xv =					\
306    {									\
307      (int) (arg1),							\
308      (int) (arg5),							\
309      (int) (arg6)							\
310    };									\
311    asm volatile (							\
312    "movl %1, %%eax\n\t"						\
313    "call " I386_DO_SYSCALL_STRING					\
314    : "=a" (resultvar)							\
315    : "i" (__NR_##name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \
316    : "memory", "cc")
317#define INTERNAL_SYSCALL_MAIN_NCS_6(name, arg1, arg2, arg3,		\
318				    arg4, arg5, arg6)			\
319  struct libc_do_syscall_args _xv =					\
320    {									\
321      (int) (arg1),							\
322      (int) (arg5),							\
323      (int) (arg6)							\
324    };									\
325    asm volatile (							\
326    "movl %1, %%eax\n\t"						\
327    "call " I386_DO_SYSCALL_STRING					\
328    : "=a" (resultvar)							\
329    : "a" (name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv)	\
330    : "memory", "cc")
331
332#define INTERNAL_SYSCALL(name, nr, args...) \
333  ({									      \
334    register unsigned int resultvar;					      \
335    INTERNAL_SYSCALL_MAIN_##nr (name, args);			      	      \
336    (int) resultvar; })
337#define INTERNAL_SYSCALL_NCS(name, nr, args...) \
338  ({									      \
339    register unsigned int resultvar;					      \
340    INTERNAL_SYSCALL_MAIN_NCS_##nr (name, args);		      	      \
341    (int) resultvar; })
342
343#if I386_USE_SYSENTER
344# ifdef PIC
345#  define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
346    LOADREGS_##nr(args)							\
347    asm volatile (							\
348    "call *%%gs:%P2"							\
349    : "=a" (resultvar)							\
350    : "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		\
351      ASMARGS_##nr(args) : "memory", "cc")
352#  define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
353    LOADREGS_##nr(args)							\
354    asm volatile (							\
355    "call *%%gs:%P2"							\
356    : "=a" (resultvar)							\
357    : "a" (name), "i" (offsetof (tcbhead_t, sysinfo))			\
358      ASMARGS_##nr(args) : "memory", "cc")
359# else /* I386_USE_SYSENTER && !PIC */
360#  define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
361    LOADREGS_##nr(args)							\
362    asm volatile (							\
363    "call *_dl_sysinfo"							\
364    : "=a" (resultvar)							\
365    : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
366#  define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
367    LOADREGS_##nr(args)							\
368    asm volatile (							\
369    "call *_dl_sysinfo"							\
370    : "=a" (resultvar)							\
371    : "a" (name) ASMARGS_##nr(args) : "memory", "cc")
372# endif /* I386_USE_SYSENTER && !PIC */
373#else /* !I386_USE_SYSENTER */
374# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
375    LOADREGS_##nr(args)							\
376    asm volatile (							\
377    "int $0x80"								\
378    : "=a" (resultvar)							\
379    : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
380# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
381    LOADREGS_##nr(args)							\
382    asm volatile (							\
383    "int $0x80"								\
384    : "=a" (resultvar)							\
385    : "a" (name) ASMARGS_##nr(args) : "memory", "cc")
386#endif /* !I386_USE_SYSENTER */
387
388#define LOADREGS_0()
389#define ASMARGS_0()
390#define LOADREGS_1(arg1) \
391	LOADREGS_0 ()
392#define ASMARGS_1(arg1) \
393	ASMARGS_0 (), "b" ((unsigned int) (arg1))
394#define LOADREGS_2(arg1, arg2) \
395	LOADREGS_1 (arg1)
396#define ASMARGS_2(arg1, arg2) \
397	ASMARGS_1 (arg1), "c" ((unsigned int) (arg2))
398#define LOADREGS_3(arg1, arg2, arg3) \
399	LOADREGS_2 (arg1, arg2)
400#define ASMARGS_3(arg1, arg2, arg3) \
401	ASMARGS_2 (arg1, arg2), "d" ((unsigned int) (arg3))
402#define LOADREGS_4(arg1, arg2, arg3, arg4) \
403	LOADREGS_3 (arg1, arg2, arg3)
404#define ASMARGS_4(arg1, arg2, arg3, arg4) \
405	ASMARGS_3 (arg1, arg2, arg3), "S" ((unsigned int) (arg4))
406#define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \
407	LOADREGS_4 (arg1, arg2, arg3, arg4)
408#define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \
409	ASMARGS_4 (arg1, arg2, arg3, arg4), "D" ((unsigned int) (arg5))
410
411#define ASMFMT_0()
412#ifdef __PIC__
413# define ASMFMT_1(arg1) \
414	, "cd" (arg1)
415# define ASMFMT_2(arg1, arg2) \
416	, "d" (arg1), "c" (arg2)
417# define ASMFMT_3(arg1, arg2, arg3) \
418	, "D" (arg1), "c" (arg2), "d" (arg3)
419# define ASMFMT_4(arg1, arg2, arg3, arg4) \
420	, "D" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
421# define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
422	, "0" (arg1), "m" (_xv), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
423#else
424# define ASMFMT_1(arg1) \
425	, "b" (arg1)
426# define ASMFMT_2(arg1, arg2) \
427	, "b" (arg1), "c" (arg2)
428# define ASMFMT_3(arg1, arg2, arg3) \
429	, "b" (arg1), "c" (arg2), "d" (arg3)
430# define ASMFMT_4(arg1, arg2, arg3, arg4) \
431	, "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
432# define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
433	, "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
434#endif
435
436#define EXTRAVAR_0
437#define EXTRAVAR_1
438#define EXTRAVAR_2
439#define EXTRAVAR_3
440#define EXTRAVAR_4
441#ifdef __PIC__
442# define EXTRAVAR_5 int _xv;
443#else
444# define EXTRAVAR_5
445#endif
446
447#endif	/* __ASSEMBLER__ */
448
449#endif /* linux/i386/sysdep.h */