Blame sysdeps/unix/sysv/linux/i386/sysdep.h

Packit 6c4009
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifndef _LINUX_I386_SYSDEP_H
Packit 6c4009
#define _LINUX_I386_SYSDEP_H 1
Packit 6c4009
Packit 6c4009
/* There is some commonality.  */
Packit 6c4009
#include <sysdeps/unix/sysv/linux/sysdep.h>
Packit 6c4009
#include <sysdeps/unix/i386/sysdep.h>
Packit 6c4009
/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
Packit 6c4009
#include <dl-sysdep.h>
Packit 6c4009
#include <tls.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* For Linux we can use the system call table in the header file
Packit 6c4009
	/usr/include/asm/unistd.h
Packit 6c4009
   of the kernel.  But these symbols do not follow the SYS_* syntax
Packit 6c4009
   so we have to redefine the `SYS_ify' macro here.  */
Packit 6c4009
#undef SYS_ify
Packit 6c4009
#define SYS_ify(syscall_name)	__NR_##syscall_name
Packit 6c4009
Packit 6c4009
#ifndef I386_USE_SYSENTER
Packit 6c4009
# if defined USE_DL_SYSINFO \
Packit 6c4009
     && (IS_IN (libc) || IS_IN (libpthread))
Packit 6c4009
#  define I386_USE_SYSENTER	1
Packit 6c4009
# else
Packit 6c4009
#  define I386_USE_SYSENTER	0
Packit 6c4009
# endif
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Since GCC 5 and above can properly spill %ebx with PIC when needed,
Packit 6c4009
   we can inline syscalls with 6 arguments if GCC 5 or above is used
Packit 6c4009
   to compile glibc.  Disable GCC 5 optimization when compiling for
Packit 6c4009
   profiling or when -fno-omit-frame-pointer is used since asm ("ebp")
Packit 6c4009
   can't be used to put the 6th argument in %ebp for syscall.  */
Packit 6c4009
#if __GNUC_PREREQ (5,0) && !defined PROF && CAN_USE_REGISTER_ASM_EBP
Packit 6c4009
# define OPTIMIZE_FOR_GCC_5
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef __ASSEMBLER__
Packit 6c4009
Packit 6c4009
/* Linux uses a negative return value to indicate syscall errors,
Packit 6c4009
   unlike most Unices, which use the condition codes' carry flag.
Packit 6c4009
Packit 6c4009
   Since version 2.1 the return value of a system call might be
Packit 6c4009
   negative even if the call succeeded.  E.g., the `lseek' system call
Packit 6c4009
   might return a large offset.  Therefore we must not anymore test
Packit 6c4009
   for < 0, but test for a real error by making sure the value in %eax
Packit 6c4009
   is a real error number.  Linus said he will make sure the no syscall
Packit 6c4009
   returns a value in -1 .. -4095 as a valid result so we can savely
Packit 6c4009
   test with -4095.  */
Packit 6c4009
Packit 6c4009
/* We don't want the label for the error handle to be global when we define
Packit 6c4009
   it here.  */
Packit 6c4009
#define SYSCALL_ERROR_LABEL __syscall_error
Packit 6c4009
Packit 6c4009
#undef	PSEUDO
Packit 6c4009
#define	PSEUDO(name, syscall_name, args)				      \
Packit 6c4009
  .text;								      \
Packit 6c4009
  ENTRY (name)								      \
Packit 6c4009
    DO_CALL (syscall_name, args);					      \
Packit 6c4009
    cmpl $-4095, %eax;							      \
Packit 6c4009
    jae SYSCALL_ERROR_LABEL
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_END
Packit 6c4009
#define	PSEUDO_END(name)						      \
Packit 6c4009
  SYSCALL_ERROR_HANDLER							      \
Packit 6c4009
  END (name)
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_NOERRNO
Packit 6c4009
#define	PSEUDO_NOERRNO(name, syscall_name, args)			      \
Packit 6c4009
  .text;								      \
Packit 6c4009
  ENTRY (name)								      \
Packit 6c4009
    DO_CALL (syscall_name, args)
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_END_NOERRNO
Packit 6c4009
#define	PSEUDO_END_NOERRNO(name)					      \
Packit 6c4009
  END (name)
Packit 6c4009
Packit 6c4009
#define ret_NOERRNO ret
Packit 6c4009
Packit 6c4009
/* The function has to return the error code.  */
Packit 6c4009
#undef	PSEUDO_ERRVAL
Packit 6c4009
#define	PSEUDO_ERRVAL(name, syscall_name, args) \
Packit 6c4009
  .text;								      \
Packit 6c4009
  ENTRY (name)								      \
Packit 6c4009
    DO_CALL (syscall_name, args);					      \
Packit 6c4009
    negl %eax
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_END_ERRVAL
Packit 6c4009
#define	PSEUDO_END_ERRVAL(name) \
Packit 6c4009
  END (name)
Packit 6c4009
Packit 6c4009
#define ret_ERRVAL ret
Packit 6c4009
Packit 6c4009
#define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.c is used.  */
Packit 6c4009
Packit 6c4009
/* The original calling convention for system calls on Linux/i386 is
Packit 6c4009
   to use int $0x80.  */
Packit 6c4009
#if I386_USE_SYSENTER
Packit 6c4009
# ifdef PIC
Packit 6c4009
#  define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
Packit 6c4009
# else
Packit 6c4009
#  define ENTER_KERNEL call *_dl_sysinfo
Packit 6c4009
# endif
Packit 6c4009
#else
Packit 6c4009
# define ENTER_KERNEL int $0x80
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Linux takes system call arguments in registers:
Packit 6c4009
Packit 6c4009
	syscall number	%eax	     call-clobbered
Packit 6c4009
	arg 1		%ebx	     call-saved
Packit 6c4009
	arg 2		%ecx	     call-clobbered
Packit 6c4009
	arg 3		%edx	     call-clobbered
Packit 6c4009
	arg 4		%esi	     call-saved
Packit 6c4009
	arg 5		%edi	     call-saved
Packit 6c4009
	arg 6		%ebp	     call-saved
Packit 6c4009
Packit 6c4009
   The stack layout upon entering the function is:
Packit 6c4009
Packit 6c4009
	24(%esp)	Arg# 6
Packit 6c4009
	20(%esp)	Arg# 5
Packit 6c4009
	16(%esp)	Arg# 4
Packit 6c4009
	12(%esp)	Arg# 3
Packit 6c4009
	 8(%esp)	Arg# 2
Packit 6c4009
	 4(%esp)	Arg# 1
Packit 6c4009
	  (%esp)	Return address
Packit 6c4009
Packit 6c4009
   (Of course a function with say 3 arguments does not have entries for
Packit 6c4009
   arguments 4, 5, and 6.)
Packit 6c4009
Packit 6c4009
   The following code tries hard to be optimal.  A general assumption
Packit 6c4009
   (which is true according to the data books I have) is that
Packit 6c4009
Packit 6c4009
	2 * xchg	is more expensive than	pushl + movl + popl
Packit 6c4009
Packit 6c4009
   Beside this a neat trick is used.  The calling conventions for Linux
Packit 6c4009
   tell that among the registers used for parameters %ecx and %edx need
Packit 6c4009
   not be saved.  Beside this we may clobber this registers even when
Packit 6c4009
   they are not used for parameter passing.
Packit 6c4009
Packit 6c4009
   As a result one can see below that we save the content of the %ebx
Packit 6c4009
   register in the %edx register when we have less than 3 arguments
Packit 6c4009
   (2 * movl is less expensive than pushl + popl).
Packit 6c4009
Packit 6c4009
   Second unlike for the other registers we don't save the content of
Packit 6c4009
   %ecx and %edx when we have more than 1 and 2 registers resp.
Packit 6c4009
Packit 6c4009
   The code below might look a bit long but we have to take care for
Packit 6c4009
   the pipelined processors (i586).  Here the `pushl' and `popl'
Packit 6c4009
   instructions are marked as NP (not pairable) but the exception is
Packit 6c4009
   two consecutive of these instruction.  This gives no penalty on
Packit 6c4009
   other processors though.  */
Packit 6c4009
Packit 6c4009
#undef	DO_CALL
Packit 6c4009
#define DO_CALL(syscall_name, args)			      		      \
Packit 6c4009
    PUSHARGS_##args							      \
Packit 6c4009
    DOARGS_##args							      \
Packit 6c4009
    movl $SYS_ify (syscall_name), %eax;					      \
Packit 6c4009
    ENTER_KERNEL							      \
Packit 6c4009
    POPARGS_##args
Packit 6c4009
Packit 6c4009
#define PUSHARGS_0	/* No arguments to push.  */
Packit 6c4009
#define	DOARGS_0	/* No arguments to frob.  */
Packit 6c4009
#define	POPARGS_0	/* No arguments to pop.  */
Packit 6c4009
#define	_PUSHARGS_0	/* No arguments to push.  */
Packit 6c4009
#define _DOARGS_0(n)	/* No arguments to frob.  */
Packit 6c4009
#define	_POPARGS_0	/* No arguments to pop.  */
Packit 6c4009
Packit 6c4009
#define PUSHARGS_1	movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0
Packit 6c4009
#define	DOARGS_1	_DOARGS_1 (4)
Packit 6c4009
#define	POPARGS_1	POPARGS_0; movl %edx, %ebx; L(RESTBX1):
Packit 6c4009
#define	_PUSHARGS_1	pushl %ebx; cfi_adjust_cfa_offset (4); \
Packit 6c4009
			cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0
Packit 6c4009
#define _DOARGS_1(n)	movl n(%esp), %ebx; _DOARGS_0(n-4)
Packit 6c4009
#define	_POPARGS_1	_POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \
Packit 6c4009
			cfi_restore (ebx); L(POPBX1):
Packit 6c4009
Packit 6c4009
#define PUSHARGS_2	PUSHARGS_1
Packit 6c4009
#define	DOARGS_2	_DOARGS_2 (8)
Packit 6c4009
#define	POPARGS_2	POPARGS_1
Packit 6c4009
#define _PUSHARGS_2	_PUSHARGS_1
Packit 6c4009
#define	_DOARGS_2(n)	movl n(%esp), %ecx; _DOARGS_1 (n-4)
Packit 6c4009
#define	_POPARGS_2	_POPARGS_1
Packit 6c4009
Packit 6c4009
#define PUSHARGS_3	_PUSHARGS_2
Packit 6c4009
#define DOARGS_3	_DOARGS_3 (16)
Packit 6c4009
#define POPARGS_3	_POPARGS_3
Packit 6c4009
#define _PUSHARGS_3	_PUSHARGS_2
Packit 6c4009
#define _DOARGS_3(n)	movl n(%esp), %edx; _DOARGS_2 (n-4)
Packit 6c4009
#define _POPARGS_3	_POPARGS_2
Packit 6c4009
Packit 6c4009
#define PUSHARGS_4	_PUSHARGS_4
Packit 6c4009
#define DOARGS_4	_DOARGS_4 (24)
Packit 6c4009
#define POPARGS_4	_POPARGS_4
Packit 6c4009
#define _PUSHARGS_4	pushl %esi; cfi_adjust_cfa_offset (4); \
Packit 6c4009
			cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3
Packit 6c4009
#define _DOARGS_4(n)	movl n(%esp), %esi; _DOARGS_3 (n-4)
Packit 6c4009
#define _POPARGS_4	_POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \
Packit 6c4009
			cfi_restore (esi); L(POPSI1):
Packit 6c4009
Packit 6c4009
#define PUSHARGS_5	_PUSHARGS_5
Packit 6c4009
#define DOARGS_5	_DOARGS_5 (32)
Packit 6c4009
#define POPARGS_5	_POPARGS_5
Packit 6c4009
#define _PUSHARGS_5	pushl %edi; cfi_adjust_cfa_offset (4); \
Packit 6c4009
			cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4
Packit 6c4009
#define _DOARGS_5(n)	movl n(%esp), %edi; _DOARGS_4 (n-4)
Packit 6c4009
#define _POPARGS_5	_POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \
Packit 6c4009
			cfi_restore (edi); L(POPDI1):
Packit 6c4009
Packit 6c4009
#define PUSHARGS_6	_PUSHARGS_6
Packit 6c4009
#define DOARGS_6	_DOARGS_6 (40)
Packit 6c4009
#define POPARGS_6	_POPARGS_6
Packit 6c4009
#define _PUSHARGS_6	pushl %ebp; cfi_adjust_cfa_offset (4); \
Packit 6c4009
			cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5
Packit 6c4009
#define _DOARGS_6(n)	movl n(%esp), %ebp; _DOARGS_5 (n-4)
Packit 6c4009
#define _POPARGS_6	_POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \
Packit 6c4009
			cfi_restore (ebp); L(POPBP1):
Packit 6c4009
Packit 6c4009
#else	/* !__ASSEMBLER__ */
Packit 6c4009
Packit 6c4009
extern int __syscall_error (int)
Packit 6c4009
  attribute_hidden __attribute__ ((__regparm__ (1)));
Packit 6c4009
Packit 6c4009
#ifndef OPTIMIZE_FOR_GCC_5
Packit 6c4009
/* We need some help from the assembler to generate optimal code.  We
Packit 6c4009
   define some macros here which later will be used.  */
Packit 6c4009
asm (".L__X'%ebx = 1\n\t"
Packit 6c4009
     ".L__X'%ecx = 2\n\t"
Packit 6c4009
     ".L__X'%edx = 2\n\t"
Packit 6c4009
     ".L__X'%eax = 3\n\t"
Packit 6c4009
     ".L__X'%esi = 3\n\t"
Packit 6c4009
     ".L__X'%edi = 3\n\t"
Packit 6c4009
     ".L__X'%ebp = 3\n\t"
Packit 6c4009
     ".L__X'%esp = 3\n\t"
Packit 6c4009
     ".macro bpushl name reg\n\t"
Packit 6c4009
     ".if 1 - \\name\n\t"
Packit 6c4009
     ".if 2 - \\name\n\t"
Packit 6c4009
     "error\n\t"
Packit 6c4009
     ".else\n\t"
Packit 6c4009
     "xchgl \\reg, %ebx\n\t"
Packit 6c4009
     ".endif\n\t"
Packit 6c4009
     ".endif\n\t"
Packit 6c4009
     ".endm\n\t"
Packit 6c4009
     ".macro bpopl name reg\n\t"
Packit 6c4009
     ".if 1 - \\name\n\t"
Packit 6c4009
     ".if 2 - \\name\n\t"
Packit 6c4009
     "error\n\t"
Packit 6c4009
     ".else\n\t"
Packit 6c4009
     "xchgl \\reg, %ebx\n\t"
Packit 6c4009
     ".endif\n\t"
Packit 6c4009
     ".endif\n\t"
Packit 6c4009
     ".endm\n\t");
Packit 6c4009
Packit 6c4009
/* Six-argument syscalls use an out-of-line helper, because an inline
Packit 6c4009
   asm using all registers apart from %esp cannot work reliably and
Packit 6c4009
   the assembler does not support describing an asm that saves and
Packit 6c4009
   restores %ebp itself as a separate stack frame.  This structure
Packit 6c4009
   stores the arguments not passed in registers; %edi is passed with a
Packit 6c4009
   pointer to this structure.  */
Packit 6c4009
struct libc_do_syscall_args
Packit 6c4009
{
Packit 6c4009
  int ebx, edi, ebp;
Packit 6c4009
};
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Define a macro which expands inline into the wrapper code for a system
Packit 6c4009
   call.  */
Packit 6c4009
#undef INLINE_SYSCALL
Packit 6c4009
#if IS_IN (libc)
Packit 6c4009
# define INLINE_SYSCALL(name, nr, args...) \
Packit 6c4009
  ({									      \
Packit 6c4009
    unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);	      \
Packit 6c4009
    __glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))		      \
Packit 6c4009
    ? __syscall_error (-INTERNAL_SYSCALL_ERRNO (resultvar, ))		      \
Packit 6c4009
    : (int) resultvar; })
Packit 6c4009
#else
Packit 6c4009
# define INLINE_SYSCALL(name, nr, args...) \
Packit 6c4009
  ({									      \
Packit 6c4009
    unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);	      \
Packit 6c4009
    if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, )))	      \
Packit 6c4009
      {									      \
Packit 6c4009
	__set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));		      \
Packit 6c4009
	resultvar = 0xffffffff;						      \
Packit 6c4009
      }									      \
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Set error number and return -1.  Return the internal function,
Packit 6c4009
   __syscall_error, which sets errno from the negative error number
Packit 6c4009
   and returns -1, to avoid PIC.  */
Packit 6c4009
#undef INLINE_SYSCALL_ERROR_RETURN_VALUE
Packit 6c4009
#define INLINE_SYSCALL_ERROR_RETURN_VALUE(resultvar) \
Packit 6c4009
  __syscall_error (-(resultvar))
Packit 6c4009
Packit 6c4009
/* List of system calls which are supported as vsyscalls.  */
Packit 6c4009
# define HAVE_CLOCK_GETTIME_VSYSCALL    1
Packit 6c4009
# define HAVE_GETTIMEOFDAY_VSYSCALL     1
Packit 6c4009
Packit 6c4009
/* Define a macro which expands inline into the wrapper code for a system
Packit 6c4009
   call.  This use is for internal calls that do not need to handle errors
Packit 6c4009
   normally.  It will never touch errno.  This returns just what the kernel
Packit 6c4009
   gave back.
Packit 6c4009
Packit 6c4009
   The _NCS variant allows non-constant syscall numbers but it is not
Packit 6c4009
   possible to use more than four parameters.  */
Packit 6c4009
#undef INTERNAL_SYSCALL
Packit 6c4009
#define INTERNAL_SYSCALL_MAIN_0(name, err, args...) \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 0, args)
Packit 6c4009
#define INTERNAL_SYSCALL_MAIN_1(name, err, args...) \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 1, args)
Packit 6c4009
#define INTERNAL_SYSCALL_MAIN_2(name, err, args...) \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 2, args)
Packit 6c4009
#define INTERNAL_SYSCALL_MAIN_3(name, err, args...) \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 3, args)
Packit 6c4009
#define INTERNAL_SYSCALL_MAIN_4(name, err, args...) \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 4, args)
Packit 6c4009
#define INTERNAL_SYSCALL_MAIN_5(name, err, args...) \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 5, args)
Packit 6c4009
/* Each object using 6-argument inline syscalls must include a
Packit 6c4009
   definition of __libc_do_syscall.  */
Packit 6c4009
#ifdef OPTIMIZE_FOR_GCC_5
Packit 6c4009
# define INTERNAL_SYSCALL_MAIN_6(name, err, args...) \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_INLINE(name, err, 6, args)
Packit 6c4009
#else /* GCC 5  */
Packit 6c4009
# define INTERNAL_SYSCALL_MAIN_6(name, err, arg1, arg2, arg3,		\
Packit 6c4009
				 arg4, arg5, arg6)			\
Packit 6c4009
  struct libc_do_syscall_args _xv =					\
Packit 6c4009
    {									\
Packit 6c4009
      (int) (arg1),							\
Packit 6c4009
      (int) (arg5),							\
Packit 6c4009
      (int) (arg6)							\
Packit 6c4009
    };									\
Packit 6c4009
    asm volatile (							\
Packit 6c4009
    "movl %1, %%eax\n\t"						\
Packit 6c4009
    "call __libc_do_syscall"						\
Packit 6c4009
    : "=a" (resultvar)							\
Packit 6c4009
    : "i" (__NR_##name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \
Packit 6c4009
    : "memory", "cc")
Packit 6c4009
#endif /* GCC 5  */
Packit 6c4009
#define INTERNAL_SYSCALL(name, err, nr, args...) \
Packit 6c4009
  ({									      \
Packit 6c4009
    register unsigned int resultvar;					      \
Packit 6c4009
    INTERNAL_SYSCALL_MAIN_##nr (name, err, args);			      \
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
#if I386_USE_SYSENTER
Packit 6c4009
# ifdef OPTIMIZE_FOR_GCC_5
Packit 6c4009
#  ifdef PIC
Packit 6c4009
#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
Packit 6c4009
    LOADREGS_##nr(args)							\
Packit 6c4009
    asm volatile (							\
Packit 6c4009
    "call *%%gs:%P2"							\
Packit 6c4009
    : "=a" (resultvar)							\
Packit 6c4009
    : "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		\
Packit 6c4009
      ASMARGS_##nr(args) : "memory", "cc")
Packit 6c4009
#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
Packit 6c4009
  ({									\
Packit 6c4009
    register unsigned int resultvar;					\
Packit 6c4009
    LOADREGS_##nr(args)							\
Packit 6c4009
    asm volatile (							\
Packit 6c4009
    "call *%%gs:%P2"							\
Packit 6c4009
    : "=a" (resultvar)							\
Packit 6c4009
    : "a" (name), "i" (offsetof (tcbhead_t, sysinfo))			\
Packit 6c4009
      ASMARGS_##nr(args) : "memory", "cc");				\
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
#  else
Packit 6c4009
#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
Packit 6c4009
    LOADREGS_##nr(args)							\
Packit 6c4009
    asm volatile (							\
Packit 6c4009
    "call *_dl_sysinfo"							\
Packit 6c4009
    : "=a" (resultvar)							\
Packit 6c4009
    : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
Packit 6c4009
#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
Packit 6c4009
  ({									\
Packit 6c4009
    register unsigned int resultvar;					\
Packit 6c4009
    LOADREGS_##nr(args)							\
Packit 6c4009
    asm volatile (							\
Packit 6c4009
    "call *_dl_sysinfo"							\
Packit 6c4009
    : "=a" (resultvar)							\
Packit 6c4009
    : "a" (name) ASMARGS_##nr(args) : "memory", "cc");			\
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
#  endif
Packit 6c4009
# else /* GCC 5  */
Packit 6c4009
#  ifdef PIC
Packit 6c4009
#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
Packit 6c4009
    EXTRAVAR_##nr							      \
Packit 6c4009
    asm volatile (							      \
Packit 6c4009
    LOADARGS_##nr							      \
Packit 6c4009
    "movl %1, %%eax\n\t"						      \
Packit 6c4009
    "call *%%gs:%P2\n\t"						      \
Packit 6c4009
    RESTOREARGS_##nr							      \
Packit 6c4009
    : "=a" (resultvar)							      \
Packit 6c4009
    : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo))		      \
Packit 6c4009
      ASMFMT_##nr(args) : "memory", "cc")
Packit 6c4009
#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
Packit 6c4009
  ({									      \
Packit 6c4009
    register unsigned int resultvar;					      \
Packit 6c4009
    EXTRAVAR_##nr							      \
Packit 6c4009
    asm volatile (							      \
Packit 6c4009
    LOADARGS_##nr							      \
Packit 6c4009
    "call *%%gs:%P2\n\t"						      \
Packit 6c4009
    RESTOREARGS_##nr							      \
Packit 6c4009
    : "=a" (resultvar)							      \
Packit 6c4009
    : "0" (name), "i" (offsetof (tcbhead_t, sysinfo))			      \
Packit 6c4009
      ASMFMT_##nr(args) : "memory", "cc");				      \
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
#  else
Packit 6c4009
#   define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
Packit 6c4009
    EXTRAVAR_##nr							      \
Packit 6c4009
    asm volatile (							      \
Packit 6c4009
    LOADARGS_##nr							      \
Packit 6c4009
    "movl %1, %%eax\n\t"						      \
Packit 6c4009
    "call *_dl_sysinfo\n\t"						      \
Packit 6c4009
    RESTOREARGS_##nr							      \
Packit 6c4009
    : "=a" (resultvar)							      \
Packit 6c4009
    : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
Packit 6c4009
#   define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
Packit 6c4009
  ({									      \
Packit 6c4009
    register unsigned int resultvar;					      \
Packit 6c4009
    EXTRAVAR_##nr							      \
Packit 6c4009
    asm volatile (							      \
Packit 6c4009
    LOADARGS_##nr							      \
Packit 6c4009
    "call *_dl_sysinfo\n\t"						      \
Packit 6c4009
    RESTOREARGS_##nr							      \
Packit 6c4009
    : "=a" (resultvar)							      \
Packit 6c4009
    : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
#  endif
Packit 6c4009
# endif /* GCC 5  */
Packit 6c4009
#else
Packit 6c4009
# ifdef OPTIMIZE_FOR_GCC_5
Packit 6c4009
#  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
Packit 6c4009
    LOADREGS_##nr(args)							\
Packit 6c4009
    asm volatile (							\
Packit 6c4009
    "int $0x80"								\
Packit 6c4009
    : "=a" (resultvar)							\
Packit 6c4009
    : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
Packit 6c4009
#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
Packit 6c4009
  ({									\
Packit 6c4009
    register unsigned int resultvar;					\
Packit 6c4009
    LOADREGS_##nr(args)							\
Packit 6c4009
    asm volatile (							\
Packit 6c4009
    "int $0x80"								\
Packit 6c4009
    : "=a" (resultvar)							\
Packit 6c4009
    : "a" (name) ASMARGS_##nr(args) : "memory", "cc");			\
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
# else /* GCC 5  */
Packit 6c4009
#  define INTERNAL_SYSCALL_MAIN_INLINE(name, err, nr, args...) \
Packit 6c4009
    EXTRAVAR_##nr							      \
Packit 6c4009
    asm volatile (							      \
Packit 6c4009
    LOADARGS_##nr							      \
Packit 6c4009
    "movl %1, %%eax\n\t"						      \
Packit 6c4009
    "int $0x80\n\t"							      \
Packit 6c4009
    RESTOREARGS_##nr							      \
Packit 6c4009
    : "=a" (resultvar)							      \
Packit 6c4009
    : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
Packit 6c4009
#  define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
Packit 6c4009
  ({									      \
Packit 6c4009
    register unsigned int resultvar;					      \
Packit 6c4009
    EXTRAVAR_##nr							      \
Packit 6c4009
    asm volatile (							      \
Packit 6c4009
    LOADARGS_##nr							      \
Packit 6c4009
    "int $0x80\n\t"							      \
Packit 6c4009
    RESTOREARGS_##nr							      \
Packit 6c4009
    : "=a" (resultvar)							      \
Packit 6c4009
    : "0" (name) ASMFMT_##nr(args) : "memory", "cc");			      \
Packit 6c4009
    (int) resultvar; })
Packit 6c4009
# endif /* GCC 5  */
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_DECL
Packit 6c4009
#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_ERROR_P
Packit 6c4009
#define INTERNAL_SYSCALL_ERROR_P(val, err) \
Packit 6c4009
  ((unsigned int) (val) >= 0xfffff001u)
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_ERRNO
Packit 6c4009
#define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
Packit 6c4009
Packit 6c4009
#define LOADARGS_0
Packit 6c4009
#ifdef __PIC__
Packit 6c4009
# if I386_USE_SYSENTER && defined PIC
Packit 6c4009
#  define LOADARGS_1 \
Packit 6c4009
    "bpushl .L__X'%k3, %k3\n\t"
Packit 6c4009
#  define LOADARGS_5 \
Packit 6c4009
    "movl %%ebx, %4\n\t"						      \
Packit 6c4009
    "movl %3, %%ebx\n\t"
Packit 6c4009
# else
Packit 6c4009
#  define LOADARGS_1 \
Packit 6c4009
    "bpushl .L__X'%k2, %k2\n\t"
Packit 6c4009
#  define LOADARGS_5 \
Packit 6c4009
    "movl %%ebx, %3\n\t"						      \
Packit 6c4009
    "movl %2, %%ebx\n\t"
Packit 6c4009
# endif
Packit 6c4009
# define LOADARGS_2	LOADARGS_1
Packit 6c4009
# define LOADARGS_3 \
Packit 6c4009
    "xchgl %%ebx, %%edi\n\t"
Packit 6c4009
# define LOADARGS_4	LOADARGS_3
Packit 6c4009
#else
Packit 6c4009
# define LOADARGS_1
Packit 6c4009
# define LOADARGS_2
Packit 6c4009
# define LOADARGS_3
Packit 6c4009
# define LOADARGS_4
Packit 6c4009
# define LOADARGS_5
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#define RESTOREARGS_0
Packit 6c4009
#ifdef __PIC__
Packit 6c4009
# if I386_USE_SYSENTER && defined PIC
Packit 6c4009
#  define RESTOREARGS_1 \
Packit 6c4009
    "bpopl .L__X'%k3, %k3\n\t"
Packit 6c4009
#  define RESTOREARGS_5 \
Packit 6c4009
    "movl %4, %%ebx"
Packit 6c4009
# else
Packit 6c4009
#  define RESTOREARGS_1 \
Packit 6c4009
    "bpopl .L__X'%k2, %k2\n\t"
Packit 6c4009
#  define RESTOREARGS_5 \
Packit 6c4009
    "movl %3, %%ebx"
Packit 6c4009
# endif
Packit 6c4009
# define RESTOREARGS_2	RESTOREARGS_1
Packit 6c4009
# define RESTOREARGS_3 \
Packit 6c4009
    "xchgl %%edi, %%ebx\n\t"
Packit 6c4009
# define RESTOREARGS_4	RESTOREARGS_3
Packit 6c4009
#else
Packit 6c4009
# define RESTOREARGS_1
Packit 6c4009
# define RESTOREARGS_2
Packit 6c4009
# define RESTOREARGS_3
Packit 6c4009
# define RESTOREARGS_4
Packit 6c4009
# define RESTOREARGS_5
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef OPTIMIZE_FOR_GCC_5
Packit 6c4009
# define LOADREGS_0()
Packit 6c4009
# define ASMARGS_0()
Packit 6c4009
# define LOADREGS_1(arg1) \
Packit 6c4009
	LOADREGS_0 ()
Packit 6c4009
# define ASMARGS_1(arg1) \
Packit 6c4009
	ASMARGS_0 (), "b" ((unsigned int) (arg1))
Packit 6c4009
# define LOADREGS_2(arg1, arg2) \
Packit 6c4009
	LOADREGS_1 (arg1)
Packit 6c4009
# define ASMARGS_2(arg1, arg2) \
Packit 6c4009
	ASMARGS_1 (arg1), "c" ((unsigned int) (arg2))
Packit 6c4009
# define LOADREGS_3(arg1, arg2, arg3) \
Packit 6c4009
	LOADREGS_2 (arg1, arg2)
Packit 6c4009
# define ASMARGS_3(arg1, arg2, arg3) \
Packit 6c4009
	ASMARGS_2 (arg1, arg2), "d" ((unsigned int) (arg3))
Packit 6c4009
# define LOADREGS_4(arg1, arg2, arg3, arg4) \
Packit 6c4009
	LOADREGS_3 (arg1, arg2, arg3)
Packit 6c4009
# define ASMARGS_4(arg1, arg2, arg3, arg4) \
Packit 6c4009
	ASMARGS_3 (arg1, arg2, arg3), "S" ((unsigned int) (arg4))
Packit 6c4009
# define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \
Packit 6c4009
	LOADREGS_4 (arg1, arg2, arg3, arg4)
Packit 6c4009
# define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \
Packit 6c4009
	ASMARGS_4 (arg1, arg2, arg3, arg4), "D" ((unsigned int) (arg5))
Packit 6c4009
# define LOADREGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
Packit 6c4009
	register unsigned int _a6 asm ("ebp") = (unsigned int) (arg6); \
Packit 6c4009
	LOADREGS_5 (arg1, arg2, arg3, arg4, arg5)
Packit 6c4009
# define ASMARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
Packit 6c4009
	ASMARGS_5 (arg1, arg2, arg3, arg4, arg5), "r" (_a6)
Packit 6c4009
#endif /* GCC 5  */
Packit 6c4009
Packit 6c4009
#define ASMFMT_0()
Packit 6c4009
#ifdef __PIC__
Packit 6c4009
# define ASMFMT_1(arg1) \
Packit 6c4009
	, "cd" (arg1)
Packit 6c4009
# define ASMFMT_2(arg1, arg2) \
Packit 6c4009
	, "d" (arg1), "c" (arg2)
Packit 6c4009
# define ASMFMT_3(arg1, arg2, arg3) \
Packit 6c4009
	, "D" (arg1), "c" (arg2), "d" (arg3)
Packit 6c4009
# define ASMFMT_4(arg1, arg2, arg3, arg4) \
Packit 6c4009
	, "D" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
Packit 6c4009
# define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
Packit 6c4009
	, "0" (arg1), "m" (_xv), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
Packit 6c4009
#else
Packit 6c4009
# define ASMFMT_1(arg1) \
Packit 6c4009
	, "b" (arg1)
Packit 6c4009
# define ASMFMT_2(arg1, arg2) \
Packit 6c4009
	, "b" (arg1), "c" (arg2)
Packit 6c4009
# define ASMFMT_3(arg1, arg2, arg3) \
Packit 6c4009
	, "b" (arg1), "c" (arg2), "d" (arg3)
Packit 6c4009
# define ASMFMT_4(arg1, arg2, arg3, arg4) \
Packit 6c4009
	, "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
Packit 6c4009
# define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
Packit 6c4009
	, "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#define EXTRAVAR_0
Packit 6c4009
#define EXTRAVAR_1
Packit 6c4009
#define EXTRAVAR_2
Packit 6c4009
#define EXTRAVAR_3
Packit 6c4009
#define EXTRAVAR_4
Packit 6c4009
#ifdef __PIC__
Packit 6c4009
# define EXTRAVAR_5 int _xv;
Packit 6c4009
#else
Packit 6c4009
# define EXTRAVAR_5
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Consistency check for position-independent code.  */
Packit 6c4009
#if defined __PIC__ && !defined OPTIMIZE_FOR_GCC_5
Packit 6c4009
# define check_consistency()						      \
Packit 6c4009
  ({ int __res;								      \
Packit 6c4009
     __asm__ __volatile__						      \
Packit 6c4009
       (LOAD_PIC_REG_STR (cx) ";"					      \
Packit 6c4009
	"subl %%ebx, %%ecx;"						      \
Packit 6c4009
	"je 1f;"							      \
Packit 6c4009
	"ud2;"								      \
Packit 6c4009
	"1:\n"								      \
Packit 6c4009
	: "=c" (__res));						      \
Packit 6c4009
     __res; })
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#endif	/* __ASSEMBLER__ */
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Pointer mangling support.  */
Packit 6c4009
#if IS_IN (rtld)
Packit 6c4009
/* We cannot use the thread descriptor because in ld.so we use setjmp
Packit 6c4009
   earlier than the descriptor is initialized.  Using a global variable
Packit 6c4009
   is too complicated here since we have no PC-relative addressing mode.  */
Packit 6c4009
#else
Packit 6c4009
# ifdef __ASSEMBLER__
Packit 6c4009
#  define PTR_MANGLE(reg)	xorl %gs:POINTER_GUARD, reg;		      \
Packit 6c4009
				roll $9, reg
Packit 6c4009
#  define PTR_DEMANGLE(reg)	rorl $9, reg;				      \
Packit 6c4009
				xorl %gs:POINTER_GUARD, reg
Packit 6c4009
# else
Packit 6c4009
#  define PTR_MANGLE(var)	asm ("xorl %%gs:%c2, %0\n"		      \
Packit 6c4009
				     "roll $9, %0"			      \
Packit 6c4009
				     : "=r" (var)			      \
Packit 6c4009
				     : "0" (var),			      \
Packit 6c4009
				       "i" (offsetof (tcbhead_t,	      \
Packit 6c4009
						      pointer_guard)))
Packit 6c4009
#  define PTR_DEMANGLE(var)	asm ("rorl $9, %0\n"			      \
Packit 6c4009
				     "xorl %%gs:%c2, %0"		      \
Packit 6c4009
				     : "=r" (var)			      \
Packit 6c4009
				     : "0" (var),			      \
Packit 6c4009
				       "i" (offsetof (tcbhead_t,	      \
Packit 6c4009
						      pointer_guard)))
Packit 6c4009
# endif
Packit 6c4009
#endif
Packit 6c4009
Packit Service 7ee92a
/* Each shadow stack slot takes 4 bytes.  Assuming that each stack
Packit Service 7ee92a
   frame takes 128 bytes, this is used to compute shadow stack size
Packit Service 7ee92a
   from stack size.  */
Packit Service 7ee92a
#define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
Packit Service 7ee92a
Packit 6c4009
#endif /* linux/i386/sysdep.h */