diff options
Diffstat (limited to 'libc/sysdeps/linux/xtensa')
| -rw-r--r-- | libc/sysdeps/linux/xtensa/Makefile.arch | 3 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/__start_context.S | 104 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/bits/elf-fdpic.h | 117 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/bits/fcntl.h | 2 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/bits/stat.h | 4 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h | 3 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/bits/xtensa-config.h | 20 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/clone.S | 6 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/crt1.S | 108 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/crti.S | 10 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/crtn.S | 6 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/crtreloc.c | 105 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/getcontext.S | 100 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/makecontext.c | 184 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/setcontext.S | 117 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/setjmp.S | 3 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/swapcontext.S | 174 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/sysdep.h | 55 | ||||
| -rw-r--r-- | libc/sysdeps/linux/xtensa/ucontext_i.sym | 15 | 
19 files changed, 1125 insertions, 11 deletions
| diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch index 23cd08ee5..f3a93caaa 100644 --- a/libc/sysdeps/linux/xtensa/Makefile.arch +++ b/libc/sysdeps/linux/xtensa/Makefile.arch @@ -10,3 +10,6 @@ SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \  	  sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S  CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c + +CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c +SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += setcontext.S getcontext.S swapcontext.S __start_context.S diff --git a/libc/sysdeps/linux/xtensa/__start_context.S b/libc/sysdeps/linux/xtensa/__start_context.S new file mode 100644 index 000000000..e6ce93347 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/__start_context.S @@ -0,0 +1,104 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <http://www.gnu.org/licenses/>.  */ + +#include <sysdep.h> + +#if defined(__XTENSA_CALL0_ABI__) +/* + * There's no entry instruction, makecontext sets up ucontext_t as if + * getcontext was called above and is about to return here. + * Registers on entry to this function: + *   a12: func to call (function descriptor in case of FDPIC) + *   a13: ucp->uc_link, next context to activate if func returns + *   a14: func argc + *   a15: current GOT pointer (in case of FDPIC) + */ +	.literal_position + +ENTRY_PREFIX(__start_context) + +	beqz	a14, 1f + +	/* load func arguments 0..1 from stack and free that space */ +	l32i	a2, a1, 8 +	l32i	a3, a1, 12 +	addi	a1, a1, 16 +	bltui	a14, 3, 1f + +	/* load func arguments 2..5 from stack and free that space */ +	l32i	a4, a1, 0 +	l32i	a5, a1, 4 +	l32i	a6, a1, 8 +	l32i	a7, a1, 12 +	addi	a1, a1, 16 +	/* func arguments 6..argc - 1 are now at the top of the stack */ +1: +	FDPIC_LOAD_FUNCDESC (a12, a12) +	callx0	a12 +	beqz	a13, 1f +	mov	a2, a13 +	movi	a4, JUMPTARGET (setcontext) +	FDPIC_LOAD_JUMPTARGET (a4, a15, a4) +	callx0	a4 +1: +	movi	a4, JUMPTARGET (_exit) +	movi	a2, 0 +	FDPIC_LOAD_JUMPTARGET (a4, a15, a4) +	callx0	a4 +	ill +END(__start_context) +#elif defined(__XTENSA_WINDOWED_ABI__) +/* + * There's no entry instruction, makecontext sets up ucontext_t as if + * getcontext was called above and is about to return here. + * Registers on entry to this function: + *   a2: func to call + *   a3: ucp->uc_link, next context to activate if func returns + *   a4: func argc + *   a5..a7: func arguments 0..2 + */ +	.literal_position + +ENTRY_PREFIX(__start_context) + +	mov	a10, a5 +	mov	a11, a6 +	mov	a12, a7 +	bltui	a4, 4, 1f + +	/* load func arguments 3..5 from stack and free that space */ +	l32i	a13, a1, 4 +	l32i	a14, a1, 8 +	l32i	a15, a1, 12 +	addi	a5, a1, 16 +	movsp	a1, a5 +	/* func arguments 6..argc - 1 are now at the top of the stack */ +1: +	callx8	a2 +	beqz	a3, 1f +	mov	a6, a3 +	movi	a4, JUMPTARGET (setcontext) +	callx4	a4 +1: +	movi	a4, JUMPTARGET (_exit) +	movi	a6, 0 +	callx4	a4 +	ill +END(__start_context) +#else +#error Unsupported Xtensa ABI +#endif diff --git a/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h b/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h new file mode 100644 index 000000000..19bb247b8 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/bits/elf-fdpic.h @@ -0,0 +1,117 @@ +/* Copyright 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file.  (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB.  If +not, see <http://www.gnu.org/licenses/>.  */ + +#ifndef _BITS_ELF_FDPIC_H +#define _BITS_ELF_FDPIC_H + +/* These data structures are described in the FDPIC ABI extension. +   The kernel passes a process a memory map, such that for every LOAD +   segment there is an elf32_fdpic_loadseg entry.  A pointer to an +   elf32_fdpic_loadmap is passed in r7 at start-up, and a pointer to +   an additional such map is passed in r8 for the interpreter, when +   there is one.  */ + +#include <elf.h> + +/* This data structure represents a PT_LOAD segment.  */ +struct elf32_fdpic_loadseg +{ +  /* Core address to which the segment is mapped.  */ +  Elf32_Addr addr; +  /* VMA recorded in the program header.  */ +  Elf32_Addr p_vaddr; +  /* Size of this segment in memory.  */ +  Elf32_Word p_memsz; +}; + +struct elf32_fdpic_loadmap { +  /* Protocol version number, must be zero.  */ +  Elf32_Half version; +  /* Number of segments in this map.  */ +  Elf32_Half nsegs; +  /* The actual memory map.  */ +  struct elf32_fdpic_loadseg segs[/*nsegs*/]; +}; + +struct elf32_fdpic_loadaddr { +  struct elf32_fdpic_loadmap *map; +  void *got_value; +}; + +/* Map a pointer's VMA to its corresponding address according to the +   load map.  */ +static __always_inline void * +__reloc_pointer (void *p, +		 const struct elf32_fdpic_loadmap *map) +{ +  int c; + +#if 0 +  if (map->version != 0) +    /* Crash.  */ +    ((void(*)())0)(); +#endif + +  /* No special provision is made for NULL.  We don't want NULL +     addresses to go through relocation, so they shouldn't be in +     .rofixup sections, and, if they're present in dynamic +     relocations, they shall be mapped to the NULL address without +     undergoing relocations.  */ + +  for (c = 0; +       /* Take advantage of the fact that the loadmap is ordered by +	  virtual addresses.  In general there will only be 2 entries, +	  so it's not profitable to do a binary search.  */ +       c < map->nsegs && p >= (void*)map->segs[c].p_vaddr; +       c++) +    { +      /* This should be computed as part of the pointer comparison +	 above, but we want to use the carry in the comparison, so we +	 can't convert it to an integer type beforehand.  */ +      unsigned long offset = (char*)p - (char*)map->segs[c].p_vaddr; +      /* We only check for one-past-the-end for the last segment, +	 assumed to be the data segment, because other cases are +	 ambiguous in the absence of padding between segments, and +	 rofixup already serves as padding between text and data. +	 Unfortunately, unless we special-case the last segment, we +	 fail to relocate the _end symbol.  */ +      if (offset < map->segs[c].p_memsz +	  || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs)) +	return (char*)map->segs[c].addr + offset; +    } + +  /* We might want to crash instead.  */ +  return (void*)-1; +} + +# define __RELOC_POINTER(ptr, loadaddr) \ +  (__reloc_pointer ((void*)(ptr), \ +		    (loadaddr).map)) + +void* +__self_reloc (const struct elf32_fdpic_loadmap *map, void ***p, void ***e); + +#endif /* _BITS_ELF_FDPIC_H */ diff --git a/libc/sysdeps/linux/xtensa/bits/fcntl.h b/libc/sysdeps/linux/xtensa/bits/fcntl.h index 5af9d2124..9bc5fa893 100644 --- a/libc/sysdeps/linux/xtensa/bits/fcntl.h +++ b/libc/sysdeps/linux/xtensa/bits/fcntl.h @@ -245,3 +245,5 @@ extern ssize_t tee (int __fdin, int __fdout, size_t __len,  #endif  __END_DECLS +/* Include generic Linux declarations.  */ +#include <bits/fcntl-linux.h> diff --git a/libc/sysdeps/linux/xtensa/bits/stat.h b/libc/sysdeps/linux/xtensa/bits/stat.h index 045a017fd..43af825ec 100644 --- a/libc/sysdeps/linux/xtensa/bits/stat.h +++ b/libc/sysdeps/linux/xtensa/bits/stat.h @@ -54,7 +54,7 @@ struct stat      unsigned long __pad2;      __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */  #endif -#ifdef __USE_MISC +#if defined(__USE_MISC) || defined(__USE_XOPEN2K8)      /* Nanosecond resolution timestamps are stored in a format         equivalent to 'struct timespec'.  This is the type used         whenever possible but the Unix namespace rules do not allow the @@ -94,7 +94,7 @@ struct stat64      unsigned long __pad2;      __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */ -#ifdef __USE_MISC +#if defined(__USE_MISC) || defined(__USE_XOPEN2K8)      /* Nanosecond resolution timestamps are stored in a format         equivalent to 'struct timespec'.  This is the type used         whenever possible but the Unix namespace rules do not allow the diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h index de9b38983..a15744c2f 100644 --- a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h @@ -11,9 +11,6 @@  /* can your target use syscall6() for mmap ? */  #define __UCLIBC_MMAP_HAS_6_ARGS__ -/* does your target use statx */ -#undef __UCLIBC_HAVE_STATX__ -  /* does your target align 64bit values in register pairs ? (32bit arches only) */  #define __UCLIBC_SYSCALL_ALIGN_64BIT__ diff --git a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h index b99928b1e..bfcd571d2 100644 --- a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h +++ b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h @@ -32,21 +32,41 @@     macros.  */  #undef XCHAL_HAVE_NSA +#ifdef __XCHAL_HAVE_NSA +#define XCHAL_HAVE_NSA			__XCHAL_HAVE_NSA +#else  #define XCHAL_HAVE_NSA			1 +#endif  #undef XCHAL_HAVE_LOOPS +#ifdef __XCHAL_HAVE_LOOPS +#define XCHAL_HAVE_LOOPS		__XCHAL_HAVE_LOOPS +#else  #define XCHAL_HAVE_LOOPS		1 +#endif  /* Assume the maximum number of AR registers.  This currently only affects     the __window_spill function, and it is always safe to flush extra.  */  #undef XCHAL_NUM_AREGS +#ifdef __XCHAL_NUM_AREGS +#define XCHAL_NUM_AREGS			__XCHAL_NUM_AREGS +#else  #define XCHAL_NUM_AREGS			64 +#endif  #undef XCHAL_HAVE_S32C1I +#ifdef __XCHAL_HAVE_S32C1I +#define XCHAL_HAVE_S32C1I		__XCHAL_HAVE_S32C1I +#else  #define XCHAL_HAVE_S32C1I		1 +#endif  #undef XCHAL_HAVE_EXCLUSIVE +#ifdef __XCHAL_HAVE_EXCLUSIVE +#define XCHAL_HAVE_EXCLUSIVE		__XCHAL_HAVE_EXCLUSIVE +#else  #define XCHAL_HAVE_EXCLUSIVE		0 +#endif  #endif /* !XTENSA_CONFIG_H */ diff --git a/libc/sysdeps/linux/xtensa/clone.S b/libc/sysdeps/linux/xtensa/clone.S index ebfdcc1f6..a11044cd0 100644 --- a/libc/sysdeps/linux/xtensa/clone.S +++ b/libc/sysdeps/linux/xtensa/clone.S @@ -81,11 +81,17 @@ ENTRY (__clone)  	callx4	a2  #elif defined(__XTENSA_CALL0_ABI__)  	mov	a2, a9			/* load up the 'arg' parameter */ +#ifdef __FDPIC__ +	mov	a12, a11 +	l32i	a11, a7, 4 +	l32i	a7, a7, 0 +#endif  	callx0	a7			/* call the user's function */  	/* Call _exit.  Note that any return parameter from the user's  	   function in a2 is seen as inputs to _exit.  */  	movi	a0, JUMPTARGET(_exit) +	FDPIC_LOAD_JUMPTARGET(a0, a12, a0)  	callx0	a0  #else  #error Unsupported Xtensa ABI diff --git a/libc/sysdeps/linux/xtensa/crt1.S b/libc/sysdeps/linux/xtensa/crt1.S index efbe264c0..a12f82dd6 100644 --- a/libc/sysdeps/linux/xtensa/crt1.S +++ b/libc/sysdeps/linux/xtensa/crt1.S @@ -35,6 +35,86 @@  #include <features.h> +#if defined(__FDPIC__) + +/* This is the canonical entry point, usually the first thing in the text +   segment.  When the entry point runs, most register values are unspecified, +   except for: + +	a6	Address of .dynamic section +	a5	Interpreter map +	a4	Executable map + +	a2	Contains a function pointer to be registered with `atexit'. +		This is how the dynamic linker arranges to have DT_FINI +		functions called for shared libraries that have been loaded +		before this code runs. + +	a1	The stack (i.e., a1+16) contains the arguments and environment: +		a1+0			argc +		a1+4			argv[0] +		... +		a1+(4*argc)		NULL +		a1+(4*(argc+1))		envp[0] +		... +					NULL + */ +	.text +	.align	4 +	.literal_position +	.global	_start +	.type	_start, @function +_start: +#if defined(__XTENSA_CALL0_ABI__) + +	.begin	no-transform +	call0	1f +2: +	.end	no-transform +	.align	4 +	.literal_position +1: +	movi	a15, 2b +	sub	a15, a0, a15 + +	mov	a12, a4 +	mov	a13, a5 +	mov	a14, a6 +	mov	a2, a4 +	movi	a3, __ROFIXUP_LIST__ +	add	a3, a3, a15 +	movi	a4, __ROFIXUP_END__ +	add	a4, a4, a15 +	movi	a0, __self_reloc +	add	a0, a0, a15 +	callx0	a0 + +	mov	a11, a2 +	movi	a2, main@GOTOFFFUNCDESC +	add	a2, a2, a11 +	l32i	a3, sp, 0	/* argc */ +	addi	a4, sp, 4	/* argv */ +	/* a5 is either 0 when static or set by the RTLD to the rtld_fini */ +	mov	a7, a13 +	/* unused stack_end argument is what used to be argc */ +	movi	a5, _init@GOTOFFFUNCDESC +	add	a5, a5, a11 +	movi	a6, _fini@GOTOFFFUNCDESC +	add	a6, a6, a11 + +	movi	a0, __uClibc_main@GOTOFFFUNCDESC +	add	a0, a0, a11 +	l32i	a11, a0, 4 +	l32i	a0, a0, 0 +	callx0	a0 +	ill + +#else +#error Unsupported Xtensa ABI +#endif + +#else /* defined(__FDPIC__) */ +  #ifndef __UCLIBC_CTOR_DTOR__          .weak _init          .weak _fini @@ -76,9 +156,26 @@  	.global	_start  	.type	_start, @function  _start: +#ifdef L_rcrt1 +	.begin	no-transform +	call0	1f +.Lret_addr: +	.end	no-transform +	.align	4 +1: +#endif  #if defined(__XTENSA_WINDOWED_ABI__) +#ifdef L_rcrt1 +	movi	a6, .Lret_addr +	sub	a6, a0, a6 +	movi	a0, 0 +	movi	a4, reloc_static_pie +	add	a4, a4, a6 +	callx4	a4 +#else  	/* Clear a0 to obviously mark the outermost frame.  */  	movi	a0, 0 +#endif  	/* Load up the user's main function.  */  	movi	a6, main @@ -106,8 +203,18 @@ _start:  	movi	a4, __uClibc_main  	callx4	a4  #elif defined(__XTENSA_CALL0_ABI__) +#ifdef L_rcrt1 +	mov	a12, a2 +	movi	a2, .Lret_addr +	sub	a2, a0, a2 +	movi	a0, reloc_static_pie +	add	a0, a0, a2 +	callx0	a0 +	mov	a7, a12 +#else  	/* Setup the shared library termination function.  */  	mov	a7, a2 +#endif  	/* Load up the user's main function.  */  	movi	a2, main @@ -146,3 +253,4 @@ __data_start:  	.long	0  	.weak	data_start  	data_start = __data_start +#endif /* defined(__FDPIC__) */ diff --git a/libc/sysdeps/linux/xtensa/crti.S b/libc/sysdeps/linux/xtensa/crti.S index ba804eb45..2923ff09d 100644 --- a/libc/sysdeps/linux/xtensa/crti.S +++ b/libc/sysdeps/linux/xtensa/crti.S @@ -3,6 +3,7 @@  	.section .init  	.align	4  	.global	_init +	.hidden _init  	.type	_init, @function  _init:  #if defined(__XTENSA_WINDOWED_ABI__) @@ -10,6 +11,10 @@ _init:  #elif defined(__XTENSA_CALL0_ABI__)  	addi	sp, sp, -16  	s32i	a0, sp, 0 +#ifdef __FDPIC__ +	s32i	a12, sp, 4 +	mov	a12, a11 +#endif  #else  #error Unsupported Xtensa ABI  #endif @@ -17,6 +22,7 @@ _init:  	.section .fini  	.align	4  	.global	_fini +	.hidden _fini  	.type	_fini, @function  _fini:  #if defined(__XTENSA_WINDOWED_ABI__) @@ -24,6 +30,10 @@ _fini:  #elif defined(__XTENSA_CALL0_ABI__)  	addi	sp, sp, -16  	s32i	a0, sp, 0 +#ifdef __FDPIC__ +	s32i	a12, sp, 4 +	mov	a12, a11 +#endif  #else  #error Unsupported Xtensa ABI  #endif diff --git a/libc/sysdeps/linux/xtensa/crtn.S b/libc/sysdeps/linux/xtensa/crtn.S index a3598da1a..6f797e8bd 100644 --- a/libc/sysdeps/linux/xtensa/crtn.S +++ b/libc/sysdeps/linux/xtensa/crtn.S @@ -4,6 +4,9 @@  #if defined(__XTENSA_WINDOWED_ABI__)  	retw  #elif defined(__XTENSA_CALL0_ABI__) +#ifdef __FDPIC__ +	l32i	a12, sp, 4 +#endif  	l32i	a0, sp, 0  	addi	sp, sp, 16  	ret @@ -15,6 +18,9 @@  #if defined(__XTENSA_WINDOWED_ABI__)  	retw  #elif defined(__XTENSA_CALL0_ABI__) +#ifdef __FDPIC__ +	l32i	a12, sp, 4 +#endif  	l32i	a0, sp, 0  	addi	sp, sp, 16  	ret diff --git a/libc/sysdeps/linux/xtensa/crtreloc.c b/libc/sysdeps/linux/xtensa/crtreloc.c new file mode 100644 index 000000000..697ef91ab --- /dev/null +++ b/libc/sysdeps/linux/xtensa/crtreloc.c @@ -0,0 +1,105 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   written by Alexandre Oliva <aoliva@redhat.com> +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file.  (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB.  If +not, see <http://www.gnu.org/licenses/>.  */ + +#ifdef __FDPIC__ + +#include <sys/types.h> +#include <link.h> + +/* This file is to be compiled into crt object files, to enable +   executables to easily self-relocate.  */ + +/* Compute the runtime address of pointer in the range [p,e), and then +   map the pointer pointed by it.  */ +static __always_inline void *** +reloc_range_indirect (void ***p, void ***e, +		      const struct elf32_fdpic_loadmap *map) +{ +  while (p < e) +    { +      if (*p != (void **)-1) +	{ +	  void *ptr = __reloc_pointer (*p, map); + +	  if (ptr != (void *)-1) +	    { +	      unsigned long off = ((unsigned long)ptr & 3) * 8; +	      unsigned long *pa = (unsigned long *)((unsigned long)ptr & -4); +	      unsigned long v2; +	      void *pt; + +	      if (off) +		{ +		  unsigned long v0, v1; +#ifdef __XTENSA_EB__ +		  v0 = pa[1]; v1 = pa[0]; +		  v2 = (v1 >> (32 - off)) | (v0 << off); +#else /* __XTENSA_EL__ */ +		  v0 = pa[0]; v1 = pa[1]; +		  v2 = (v0 << (32 - off)) | (v1 >> off); +#endif +		  pt = (void *)((v1 << (32 - off)) | (v0 >> off)); +		} +	      else +		pt = *(void**)ptr; +	      pt = __reloc_pointer (pt, map); +	      if (off) +		{ +		  unsigned long v = (unsigned long)pt; +#ifdef __XTENSA_EB__ +		  pa[0] = (v2 << (32 - off)) | (v >> off); +		  pa[1] = (v << (32 - off)) | (v2 >> off); +#else /* __XTENSA_EL__ */ +		  pa[0] = (v2 >> (32 - off)) | (v << off); +		  pa[1] = (v >> (32 - off)) | (v2 << off); +#endif +		} +	      else +		*(void**)ptr = pt; +	    } +	} +      p++; +    } +  return p; +} + +/* Call __reloc_range_indirect for the given range except for the last +   entry, whose contents are only relocated.  It's expected to hold +   the GOT value.  */ +attribute_hidden void* +__self_reloc (const struct elf32_fdpic_loadmap *map, +	      void ***p, void ***e) +{ +  p = reloc_range_indirect (p, e-1, map); + +  if (p >= e) +    return (void*)-1; + +  return __reloc_pointer (*p, map); +} + +#endif /* __FDPIC__ */ diff --git a/libc/sysdeps/linux/xtensa/getcontext.S b/libc/sysdeps/linux/xtensa/getcontext.S new file mode 100644 index 000000000..4cc644552 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/getcontext.S @@ -0,0 +1,100 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <http://www.gnu.org/licenses/>.  */ + +#include <sysdep.h> +#include "ucontext_i.h" + +#if defined(__XTENSA_CALL0_ABI__) +ENTRY(__getcontext) +	s32i	a0, a2, MCONTEXT_SC_PC +	s32i	a1, a2, MCONTEXT_SC_A_0 + 4 + +	/* save callee-saved registers in the context */ +	s32i	a12, a2, MCONTEXT_SC_A_0 + 48 +	s32i	a13, a2, MCONTEXT_SC_A_0 + 52 +	s32i	a14, a2, MCONTEXT_SC_A_0 + 56 +	s32i	a15, a2, MCONTEXT_SC_A_0 + 60 + +	movi	a3, 0 +	addi	a4, a2, UCONTEXT_SIGMASK +	movi	a2, SIG_BLOCK +	movi	a5, JUMPTARGET (sigprocmask) +	FDPIC_LOAD_JUMPTARGET (a5, a11, a5) +	jx	a5 +END(__getcontext) +#elif defined(__XTENSA_WINDOWED_ABI__) +ENTRY(__getcontext) +	movi	a4, __window_spill +	callx4	a4 +	s32i	a0, a2, MCONTEXT_SC_PC + +	/* copy registers a0..a3 from spill area */ +	addi	a3, a1, -16 +	l32i	a4, a3, 0 +	l32i	a5, a3, 4 +	l32i	a6, a3, 8 +	l32i	a7, a3, 12 +	s32i	a4, a2, MCONTEXT_SC_A_0 + 0 +	s32i	a5, a2, MCONTEXT_SC_A_0 + 4 +	s32i	a6, a2, MCONTEXT_SC_A_0 + 8 +	s32i	a7, a2, MCONTEXT_SC_A_0 + 12 + +	/* if it was call4 then register saving is done */ +	extui	a4, a0, 30, 2 +	bltui	a4, 2, 1f + +	/* otherwise load spill overflow area address into a3 */ +	addi	a3, a5, -16 +	l32i	a3, a3, 4 +	addi	a3, a3, -32 +	beqi	a4, 2, 2f + +	/* copy registers a8..a11 from spill overflow area */ +	addi	a3, a3, -16 +	l32i	a4, a3, 16 +	l32i	a5, a3, 20 +	l32i	a6, a3, 24 +	l32i	a7, a3, 28 +	s32i	a4, a2, MCONTEXT_SC_A_0 + 32 +	s32i	a5, a2, MCONTEXT_SC_A_0 + 36 +	s32i	a6, a2, MCONTEXT_SC_A_0 + 40 +	s32i	a7, a2, MCONTEXT_SC_A_0 + 44 + +	/* copy registers a4..a7 from spill overflow area */ +2: +	l32i	a4, a3, 0 +	l32i	a5, a3, 4 +	l32i	a6, a3, 8 +	l32i	a7, a3, 12 +	s32i	a4, a2, MCONTEXT_SC_A_0 + 16 +	s32i	a5, a2, MCONTEXT_SC_A_0 + 20 +	s32i	a6, a2, MCONTEXT_SC_A_0 + 24 +	s32i	a7, a2, MCONTEXT_SC_A_0 + 28 +1: +	movi	a6, SIG_BLOCK +	movi	a7, 0 +	addi	a8, a2, UCONTEXT_SIGMASK +	movi	a4, JUMPTARGET (sigprocmask) +	callx4	a4 +	mov	a2, a6 +	retw +END(__getcontext) +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__getcontext, getcontext) diff --git a/libc/sysdeps/linux/xtensa/makecontext.c b/libc/sysdeps/linux/xtensa/makecontext.c new file mode 100644 index 000000000..0a8f7116f --- /dev/null +++ b/libc/sysdeps/linux/xtensa/makecontext.c @@ -0,0 +1,184 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <http://www.gnu.org/licenses/>.  */ + +#include <sysdep.h> +#include <stdarg.h> +#include <stdint.h> +#include <string.h> +#include <ucontext.h> + +extern void __start_context (void); + +#if defined(__XTENSA_CALL0_ABI__) +/* + * makecontext sets up new stack like this: + * + *    +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size) + *    | optional alignment + *    +------------------ CFA of __start_context, initial sp points here + *    | optional padding + *    +------------------ Optional arguments 6..argc - 1 + *    | func arg argc - 1 + *    | func arg argc - 2 + *    |  ... + *    | func arg 6 + *    +------------------ Optional arguments 2..5 + *    | func arg 5 + * 16 | func arg 4 + *    | func arg 3 + *    | func arg 2 + *    +------------------ Optional arguments 0..1 + *    | func arg 1 + * 16 | func arg 0 + *    | padding + *    | padding + *    +------------------ CFA of pseudo getcontext + *    | + *    +------------------ stack bottom (uc_stack.ss_sp) + * + * When argc is 0 arguments areas are not allocated, + * when 1 <= argc < 3 only area for arguments 0..1 is allocated, + * when 3 <= argc < 7 areas for arguments 0..1 and 2..5 is allocated, + * when argc >= 7 all three arguments areas are allocated. + * Arguments 0..5 area is deallocated by the __start_context after + * arguments are loaded into registers. + * uc_mcontext registers are set as if __start_context made call0 + * to getcontext, sp points to that pseudo getcontext CFA. + * setcontext/swapcontext will arrange for restoring regiters + * a1, a12..a15 of __start_context. + */ + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ +  unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp +    + ucp->uc_stack.ss_size) & -16; +  int i; + +  if (argc > 0) +    sp -= 4 * (argc + 2); +  sp &= -16; + +#ifdef __FDPIC__ +  ucp->uc_mcontext.sc_pc = ((unsigned long *) __start_context)[0]; +  ucp->uc_mcontext.sc_a[15] = ((unsigned long *) __start_context)[1]; +#else +  ucp->uc_mcontext.sc_pc = (unsigned long) __start_context; +#endif +  ucp->uc_mcontext.sc_a[1] = sp; +  ucp->uc_mcontext.sc_a[12] = (unsigned long) func; +  ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link; +  ucp->uc_mcontext.sc_a[14] = argc; + +  if (argc) +    { +      va_list ap; + +      va_start (ap, argc); +      for (i = 0; i < argc; ++i) +	((int *) sp)[i + 2] = va_arg (ap, int); +      va_end (ap); +    } +} +#elif defined(__XTENSA_WINDOWED_ABI__) +/* + * makecontext sets up new stack like this: + * + *    +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size) + *    | optional alignment + *    +------------------ CFA of __start_context + * 16 | Outermost caller spill area + *    +------------------ + * 16 | __start_context overflow area + *    +------------------ initial sp points here + *    | optional padding + *    +------------------ Optional arguments 6..argc - 1 + *    | func arg argc - 1 + *    | func arg argc - 2 + *    |  ... + *    | func arg 6 + *    +------------------ Optional arguments 3..5 + *    | func arg 5 + * 16 | func arg 4 + *    | func arg 3 + *    | padding + *    +------------------ CFA of pseudo getcontext + * 16 | __start_context caller spill area + *    +------------------ + *    | + *    +------------------ stack bottom (uc_stack.ss_sp) + * + * When argc < 4 both arguments areas are not allocated, + * when 4 <= argc < 7 only area for arguments 3..5 is allocated, + * when argc >= 7 both arguments areas are allocated. + * Arguments 3..5 area is deallocated by the __start_context after + * arguments are loaded into registers. + * uc_mcontext registers are set as if __start_context made call8 + * to getcontext, sp points to that pseudo getcontext CFA, spill + * area under that sp has a1 pointing to the __start_context CFA + * at the top of the stack. setcontext/swapcontext will arrange for + * restoring regiters a0..a7 of __start_context. + */ + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) +{ +  unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp +    + ucp->uc_stack.ss_size - 32) & -16; +  unsigned long spill0[4] = +    { +      0, sp + 32, 0, 0, +    }; +  int i; + +  memset ((void *) sp, 0, 32); + +  if (argc > 2) +    sp -= 4 * (argc - 2); +  sp &= -16; + +  ucp->uc_mcontext.sc_pc = +    ((unsigned long) __start_context & 0x3fffffff) + 0x80000000; +  ucp->uc_mcontext.sc_a[0] = 0; +  ucp->uc_mcontext.sc_a[1] = sp; +  ucp->uc_mcontext.sc_a[2] = (unsigned long) func; +  ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link; +  ucp->uc_mcontext.sc_a[4] = argc; + +  if (argc) +    { +      va_list ap; + +      va_start (ap, argc); +      for (i = 0; i < argc; ++i) +	{ +	  if (i < 3) +	    ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int); +	  else +	    ((int *) sp)[i - 2] = va_arg (ap, int); +	} +      va_end (ap); +    } + +  sp -= 16; +  memcpy ((void *) sp, spill0, sizeof (spill0)); +} +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__makecontext, makecontext) diff --git a/libc/sysdeps/linux/xtensa/setcontext.S b/libc/sysdeps/linux/xtensa/setcontext.S new file mode 100644 index 000000000..72915ef8d --- /dev/null +++ b/libc/sysdeps/linux/xtensa/setcontext.S @@ -0,0 +1,117 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <http://www.gnu.org/licenses/>.  */ + +#include <sysdep.h> +#include "ucontext_i.h" + +#if defined(__XTENSA_CALL0_ABI__) +ENTRY(__setcontext) +	addi	sp, sp, -16 +	s32i	a0, sp, 0 +	s32i	a2, sp, 4 + +	addi	a3, a2, UCONTEXT_SIGMASK +	movi	a4, 0 +	movi	a2, SIG_SETMASK +	movi	a5, JUMPTARGET (sigprocmask) +	FDPIC_LOAD_JUMPTARGET (a5, a11, a5) +	callx0	a5 +	bnez	a2, .Lerror + +	l32i	a2, sp, 4 +	l32i	a0, a2, MCONTEXT_SC_PC +	l32i	a1, a2, MCONTEXT_SC_A_0 + 4 + +	/* load callee-saved registers from the context */ +	l32i	a12, a2, MCONTEXT_SC_A_0 + 48 +	l32i	a13, a2, MCONTEXT_SC_A_0 + 52 +	l32i	a14, a2, MCONTEXT_SC_A_0 + 56 +	l32i	a15, a2, MCONTEXT_SC_A_0 + 60 +	movi	a2, 0 +	ret +.Lerror: +	l32i	a0, sp, 0 +	addi	sp, sp, 16 +	ret +END(__setcontext) +#elif defined(__XTENSA_WINDOWED_ABI__) +ENTRY(__setcontext) +	movi	a6, SIG_SETMASK +	addi	a7, a2, UCONTEXT_SIGMASK +	movi	a8, 0 +	movi	a4, JUMPTARGET (sigprocmask) +	callx4	a4 +	bnez	a6, .Lerror +	movi	a4, __window_spill +	callx4	a4 + +	l32i	a0, a2, MCONTEXT_SC_PC + +	/* copy registers a0..a3 to spill area */ +	addi	a3, a1, -16 +	l32i	a4, a2, MCONTEXT_SC_A_0 + 0 +	l32i	a5, a2, MCONTEXT_SC_A_0 + 4 +	l32i	a6, a2, MCONTEXT_SC_A_0 + 8 +	l32i	a7, a2, MCONTEXT_SC_A_0 + 12 +	s32i	a4, a3, 0 +	s32i	a5, a3, 4 +	s32i	a6, a3, 8 +	s32i	a7, a3, 12 + +	/* if it was call4 then register setup is done */ +	extui	a4, a0, 30, 2 +	bltui	a4, 2, 1f + +	/* otherwise load spill overflow area address into a3 */ +	addi	a3, a5, -16 +	l32i	a3, a3, 4 +	addi	a3, a3, -32 +	beqi	a4, 2, 2f + +	/* copy registers a8..a11 to spill overflow area */ +	addi	a3, a3, -16 +	l32i	a4, a2, MCONTEXT_SC_A_0 + 32 +	l32i	a5, a2, MCONTEXT_SC_A_0 + 36 +	l32i	a6, a2, MCONTEXT_SC_A_0 + 40 +	l32i	a7, a2, MCONTEXT_SC_A_0 + 44 +	s32i	a4, a3, 16 +	s32i	a5, a3, 20 +	s32i	a6, a3, 24 +	s32i	a7, a3, 28 + +	/* copy registers a4..a7 to spill overflow area */ +2: +	l32i	a4, a2, MCONTEXT_SC_A_0 + 16 +	l32i	a5, a2, MCONTEXT_SC_A_0 + 20 +	l32i	a6, a2, MCONTEXT_SC_A_0 + 24 +	l32i	a7, a2, MCONTEXT_SC_A_0 + 28 +	s32i	a4, a3, 0 +	s32i	a5, a3, 4 +	s32i	a6, a3, 8 +	s32i	a7, a3, 12 +1: +	movi	a2, 0 +	retw +.Lerror: +	mov	a2, a6 +	retw +END(__setcontext) +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__setcontext, setcontext) diff --git a/libc/sysdeps/linux/xtensa/setjmp.S b/libc/sysdeps/linux/xtensa/setjmp.S index b8152fdd8..d629c11a8 100644 --- a/libc/sysdeps/linux/xtensa/setjmp.S +++ b/libc/sysdeps/linux/xtensa/setjmp.S @@ -155,7 +155,8 @@ ENTRY (__sigsetjmp)  	s32i	a14, a2, 16  	s32i	a15, a2, 20  	mov	a12, a2 -	movi	a0, __sigjmp_save +	movi	a0, JUMPTARGET(__sigjmp_save) +	FDPIC_LOAD_JUMPTARGET(a0, a11, a0)  	callx0	a0  	l32i	a0, a12, 0  	l32i	a12, a12, 8 diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S b/libc/sysdeps/linux/xtensa/swapcontext.S new file mode 100644 index 000000000..40b38e98c --- /dev/null +++ b/libc/sysdeps/linux/xtensa/swapcontext.S @@ -0,0 +1,174 @@ +/* Copyright (C) 2018 - 2022 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, see +   <http://www.gnu.org/licenses/>.  */ + +#include <sysdep.h> +#include "ucontext_i.h" + +#if defined(__XTENSA_CALL0_ABI__) +ENTRY(__swapcontext) +	s32i	a0, a2, MCONTEXT_SC_PC +	s32i	a1, a2, MCONTEXT_SC_A_0 + 4 + +	/* save callee-saved registers in the context */ +	s32i	a12, a2, MCONTEXT_SC_A_0 + 48 +	s32i	a13, a2, MCONTEXT_SC_A_0 + 52 +	s32i	a14, a2, MCONTEXT_SC_A_0 + 56 +	s32i	a15, a2, MCONTEXT_SC_A_0 + 60 + +	mov	a12, a3 +	mov	a13, a2 + +	addi	a3, a3, UCONTEXT_SIGMASK +	addi	a4, a2, UCONTEXT_SIGMASK +	movi	a2, SIG_SETMASK +	movi	a5, JUMPTARGET (sigprocmask) +	FDPIC_LOAD_JUMPTARGET (a5, a11, a5) +	callx0	a5 +	bnez	a2, .Lerror + +	mov	a2, a12 +	l32i	a0, a2, MCONTEXT_SC_PC +	l32i	a1, a2, MCONTEXT_SC_A_0 + 4 + +	/* load callee-saved registers from the context */ +	l32i	a12, a2, MCONTEXT_SC_A_0 + 48 +	l32i	a13, a2, MCONTEXT_SC_A_0 + 52 +	l32i	a14, a2, MCONTEXT_SC_A_0 + 56 +	l32i	a15, a2, MCONTEXT_SC_A_0 + 60 + +	movi	a2, 0 +	ret +.Lerror: +	l32i	a0, a13, MCONTEXT_SC_PC +	l32i	a12, a13, MCONTEXT_SC_A_0 + 48 +	l32i	a13, a13, MCONTEXT_SC_A_0 + 52 +	ret +END(__swapcontext) +#elif defined(__XTENSA_WINDOWED_ABI__) +ENTRY(__swapcontext) +	movi	a4, __window_spill +	callx4	a4 +	mov	a9, a3 +	s32i	a0, a2, MCONTEXT_SC_PC + +	/* copy registers a0..a3 from spill area */ +	addi	a3, a1, -16 +	l32i	a4, a3, 0 +	l32i	a5, a3, 4 +	l32i	a6, a3, 8 +	l32i	a7, a3, 12 +	s32i	a4, a2, MCONTEXT_SC_A_0 + 0 +	s32i	a5, a2, MCONTEXT_SC_A_0 + 4 +	s32i	a6, a2, MCONTEXT_SC_A_0 + 8 +	s32i	a7, a2, MCONTEXT_SC_A_0 + 12 + +	/* if it was call4 then register saving is done */ +	extui	a4, a0, 30, 2 +	bltui	a4, 2, 1f + +	/* otherwise load spill overflow area address into a3 */ +	addi	a3, a5, -16 +	l32i	a3, a3, 4 +	addi	a3, a3, -32 +	beqi	a4, 2, 2f + +	/* copy registers a8..a11 from spill overflow area */ +	addi	a3, a3, -16 +	l32i	a4, a3, 16 +	l32i	a5, a3, 20 +	l32i	a6, a3, 24 +	l32i	a7, a3, 28 +	s32i	a4, a2, MCONTEXT_SC_A_0 + 32 +	s32i	a5, a2, MCONTEXT_SC_A_0 + 36 +	s32i	a6, a2, MCONTEXT_SC_A_0 + 40 +	s32i	a7, a2, MCONTEXT_SC_A_0 + 44 + +	/* copy registers a4..a7 from spill overflow area */ +2: +	l32i	a4, a3, 0 +	l32i	a5, a3, 4 +	l32i	a6, a3, 8 +	l32i	a7, a3, 12 +	s32i	a4, a2, MCONTEXT_SC_A_0 + 16 +	s32i	a5, a2, MCONTEXT_SC_A_0 + 20 +	s32i	a6, a2, MCONTEXT_SC_A_0 + 24 +	s32i	a7, a2, MCONTEXT_SC_A_0 + 28 +1: +	movi	a6, SIG_SETMASK +	addi	a7, a9, UCONTEXT_SIGMASK +	addi	a8, a2, UCONTEXT_SIGMASK +	mov	a2, a9 +	movi	a4, JUMPTARGET (sigprocmask) +	callx4	a4 +	bnez	a6, .Lerror + +	l32i	a0, a2, MCONTEXT_SC_PC + +	/* copy registers a0..a3 to spill area */ +	addi	a3, a1, -16 +	l32i	a4, a2, MCONTEXT_SC_A_0 + 0 +	l32i	a5, a2, MCONTEXT_SC_A_0 + 4 +	l32i	a6, a2, MCONTEXT_SC_A_0 + 8 +	l32i	a7, a2, MCONTEXT_SC_A_0 + 12 +	s32i	a4, a3, 0 +	s32i	a5, a3, 4 +	s32i	a6, a3, 8 +	s32i	a7, a3, 12 + +	/* if it was call4 then register setup is done */ +	extui	a4, a0, 30, 2 +	bltui	a4, 2, 1f + +	/* otherwise load spill overflow area address into a3 */ +	addi	a3, a5, -16 +	l32i	a3, a3, 4 +	addi	a3, a3, -32 +	beqi	a4, 2, 2f + +	/* copy registers a8..a11 to spill overflow area */ +	addi	a3, a3, -16 +	l32i	a4, a2, MCONTEXT_SC_A_0 + 32 +	l32i	a5, a2, MCONTEXT_SC_A_0 + 36 +	l32i	a6, a2, MCONTEXT_SC_A_0 + 40 +	l32i	a7, a2, MCONTEXT_SC_A_0 + 44 +	s32i	a4, a3, 16 +	s32i	a5, a3, 20 +	s32i	a6, a3, 24 +	s32i	a7, a3, 28 + +	/* copy registers a4..a7 to spill overflow area */ +2: +	l32i	a4, a2, MCONTEXT_SC_A_0 + 16 +	l32i	a5, a2, MCONTEXT_SC_A_0 + 20 +	l32i	a6, a2, MCONTEXT_SC_A_0 + 24 +	l32i	a7, a2, MCONTEXT_SC_A_0 + 28 +	s32i	a4, a3, 0 +	s32i	a5, a3, 4 +	s32i	a6, a3, 8 +	s32i	a7, a3, 12 +1: +	movi	a2, 0 +	retw +.Lerror: +	mov	a2, a6 +	retw +END(__swapcontext) +#else +#error Unsupported Xtensa ABI +#endif + +weak_alias (__swapcontext, swapcontext) diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h index 0671f0783..d05741027 100644 --- a/libc/sysdeps/linux/xtensa/sysdep.h +++ b/libc/sysdeps/linux/xtensa/sysdep.h @@ -39,12 +39,15 @@  #endif -#define	ENTRY(name)							\ +#define	ENTRY_PREFIX(name)						\    .globl C_SYMBOL_NAME(name);				\    ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function);			\    .align ALIGNARG(2);							\    LITERAL_POSITION;							\ -  C_LABEL(name)								\ +  C_LABEL(name) + +#define	ENTRY(name)							\ +  ENTRY_PREFIX(name)							\    abi_entry(sp, FRAMESIZE);  #define	HIDDEN_ENTRY(name)						\ @@ -72,13 +75,27 @@  #define LITERAL_POSITION .literal_position  #undef JUMPTARGET -#ifdef __PIC__ +#if defined(__FDPIC__) +#define JUMPTARGET(name) name##@GOTOFFFUNCDESC +#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc)		\ +	l32i	a11, funcdesc, 4;				\ +	l32i	call_target, funcdesc, 0 + +#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)\ +	add	call_target, got_base, jumptarget;		\ +	FDPIC_LOAD_FUNCDESC(call_target, call_target) + +#elif defined(__PIC__)  /* The "@PLT" suffix is currently a no-op for non-shared linking, but     it doesn't hurt to use it conditionally for PIC code in case that     changes someday.  */  #define JUMPTARGET(name) name##@PLT +#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc) +#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)  #else  #define JUMPTARGET(name) name +#define FDPIC_LOAD_FUNCDESC(call_target, funcdesc) +#define FDPIC_LOAD_JUMPTARGET(call_target, got_base, jumptarget)  #endif  #ifndef FRAMESIZE @@ -150,6 +167,21 @@  #if defined _LIBC_REENTRANT  # if defined USE___THREAD +#ifdef __FDPIC__ +#   define SYSCALL_ERROR_ERRNO errno +#  define SYSCALL_ERROR_HANDLER						      \ +0:	rur	a4, THREADPTR;						      \ +	movi	a3, SYSCALL_ERROR_ERRNO@GOTTPOFF;			      \ +	.reloc	., R_XTENSA_TLS_TPOFF_PTR, SYSCALL_ERROR_ERRNO;		      \ +	add	a3, a3, a11;						      \ +	.reloc	., R_XTENSA_TLS_TPOFF_LOAD, SYSCALL_ERROR_ERRNO;	      \ +	l32i	a3, a3, 0;						      \ +	neg	a2, a2;							      \ +	add	a4, a4, a3;						      \ +	s32i	a2, a4, 0;						      \ +	movi	a2, -1;							      \ +	j	.Lpseudo_end; +#else  #   define SYSCALL_ERROR_ERRNO errno  #  define SYSCALL_ERROR_HANDLER						      \  0:	rur	a4, THREADPTR;						      \ @@ -159,13 +191,14 @@  	s32i	a2, a4, 0;						      \  	movi	a2, -1;							      \  	j	.Lpseudo_end; +#endif  # else /* !USE___THREAD */  #if defined(__XTENSA_WINDOWED_ABI__)  #  define SYSCALL_ERROR_HANDLER						      \  0:	neg	a2, a2;							      \  	mov	a6, a2;							      \ -	movi	a4, __errno_location@PLT;				      \ +	movi	a4, JUMPTARGET(__errno_location);			      \  	callx4	a4;						              \  	s32i	a2, a6, 0;						      \  	movi	a2, -1;							      \ @@ -176,7 +209,8 @@  	addi	a1, a1, -16;						      \  	s32i	a0, a1, 0;						      \  	s32i	a2, a1, 4;						      \ -	movi	a0, __errno_location@PLT;				      \ +	movi	a0, JUMPTARGET(__errno_location);			      \ +	FDPIC_LOAD_JUMPTARGET(a0, a11, a0);				      \  	callx0	a0;						              \  	l32i	a0, a1, 0;						      \  	l32i	a3, a1, 4;						      \ @@ -190,12 +224,23 @@  # endif /* !USE___THREAD */  #else /* !_LIBC_REENTRANT */ +#ifdef __FDPIC__ +#define SYSCALL_ERROR_HANDLER						      \ +0:	movi	a4, errno@GOT;						      \ +	add	a4, a4, a11;						      \ +	l32i	a4, a4, 0;						      \ +	neg	a2, a2;							      \ +	s32i	a2, a4, 0;						      \ +	movi	a2, -1;							      \ +	j	.Lpseudo_end; +#else  #define SYSCALL_ERROR_HANDLER						      \  0:	movi	a4, errno;						      \  	neg	a2, a2;							      \  	s32i	a2, a4, 0;						      \  	movi	a2, -1;							      \  	j	.Lpseudo_end; +#endif /* __FDPIC__ */  #endif /* _LIBC_REENTRANT */  #endif	/* __ASSEMBLER__ */ diff --git a/libc/sysdeps/linux/xtensa/ucontext_i.sym b/libc/sysdeps/linux/xtensa/ucontext_i.sym new file mode 100644 index 000000000..4770c36c9 --- /dev/null +++ b/libc/sysdeps/linux/xtensa/ucontext_i.sym @@ -0,0 +1,15 @@ +#include <inttypes.h> +#include <signal.h> +#include <stddef.h> +#include <sys/ucontext.h> + +SIG_BLOCK +SIG_SETMASK + +-- Offsets of the fields in the ucontext_t structure. +#define ucontext(member)	offsetof (ucontext_t, member) +#define mcontext(member)	ucontext (uc_mcontext.member) + +UCONTEXT_SIGMASK		ucontext (uc_sigmask) +MCONTEXT_SC_A_0			mcontext (sc_a[0]) +MCONTEXT_SC_PC			mcontext (sc_pc) | 
