diff options
author | Palmer Dabbelt <palmer@dabbelt.com> | 2018-01-29 10:28:32 -0800 |
---|---|---|
committer | Palmer Dabbelt <palmer@dabbelt.com> | 2018-01-29 10:37:27 -0800 |
commit | 7f33b09c65e3fdb6b6a1af8816918bcce977b38a (patch) | |
tree | 820a99249081334d21f7a4eb7fa621c05d2337ca | |
parent | 36960f0c763a904d6d1f028e2c33b7bbe43c2a3a (diff) | |
download | glibc-7f33b09c65e3fdb6b6a1af8816918bcce977b38a.tar.gz |
RISC-V: Linux ABI
Linux-specific code that is required for maintaining ABI compatibility.
This doesn't contain the actual system call interface, that is split out
in order to avoid having a patch that's too big.
2018-01-29 Palmer Dabbelt <palmer@sifive.com>
* sysdeps/riscv/nptl/pthread-offsets.h: New file.
* sysdeps/riscv/nptl/pthreaddef.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/bits/fcntl.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/bits/mman.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/dl-cache.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/flush-icache.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/getcontext.S: Likewise.
* sysdeps/unix/sysv/linux/riscv/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/makecontext.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/readelflib.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/register-dump.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/setcontext.S: Likewise.
* sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/swapcontext.S: Likewise.
* sysdeps/unix/sysv/linux/riscv/sys/cachectl.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/sys/procfs.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/sys/ucontext.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/sys/user.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/ucontext-macros.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/ucontext_i.sym: Likewise.
24 files changed, 1445 insertions, 0 deletions
@@ -105,6 +105,28 @@ * sysdeps/unix/sysv/linux/riscv/sysdep.S: Likewise. * sysdeps/unix/sysv/linux/riscv/sysdep.h: Likewise. * sysdeps/unix/sysv/linux/riscv/vfork.S: Likewise. + * sysdeps/riscv/nptl/pthread-offsets.h: New file. + * sysdeps/riscv/nptl/pthreaddef.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/bits/fcntl.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/bits/mman.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/dl-cache.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/flush-icache.c: Likewise. + * sysdeps/unix/sysv/linux/riscv/getcontext.S: Likewise. + * sysdeps/unix/sysv/linux/riscv/init-first.c: Likewise. + * sysdeps/unix/sysv/linux/riscv/libc-vdso.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/makecontext.c: Likewise. + * sysdeps/unix/sysv/linux/riscv/readelflib.c: Likewise. + * sysdeps/unix/sysv/linux/riscv/register-dump.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/setcontext.S: Likewise. + * sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/swapcontext.S: Likewise. + * sysdeps/unix/sysv/linux/riscv/sys/cachectl.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/sys/procfs.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/sys/ucontext.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/sys/user.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/ucontext-macros.h: Likewise. + * sysdeps/unix/sysv/linux/riscv/ucontext_i.sym: Likewise. 2018-01-29 Florian Weimer <fweimer@redhat.com> diff --git a/sysdeps/riscv/nptl/pthread-offsets.h b/sysdeps/riscv/nptl/pthread-offsets.h new file mode 100644 index 0000000000..5f7031834f --- /dev/null +++ b/sysdeps/riscv/nptl/pthread-offsets.h @@ -0,0 +1,24 @@ +/* RISC-V pthread offsets + Copyright (C) 2017-2018 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/>. */ + +#define __PTHREAD_MUTEX_NUSERS_OFFSET 12 +#define __PTHREAD_MUTEX_KIND_OFFSET 16 +#define __PTHREAD_MUTEX_SPINS_OFFSET 20 +#define __PTHREAD_MUTEX_ELISION_OFFSET 22 +#define __PTHREAD_MUTEX_LIST_OFFSET 24 diff --git a/sysdeps/riscv/nptl/pthreaddef.h b/sysdeps/riscv/nptl/pthreaddef.h new file mode 100644 index 0000000000..442422aefb --- /dev/null +++ b/sysdeps/riscv/nptl/pthreaddef.h @@ -0,0 +1,32 @@ +/* pthread machine parameter definitions, RISC-V version. + Copyright (C) 2011-2018 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/>. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) diff --git a/sysdeps/unix/sysv/linux/riscv/bits/fcntl.h b/sysdeps/unix/sysv/linux/riscv/bits/fcntl.h new file mode 100644 index 0000000000..6bea085c70 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/bits/fcntl.h @@ -0,0 +1,62 @@ +/* O_*, F_*, FD_* bit values for Linux / RISC-V. + Copyright (C) 2011-2018 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/>. */ + +#ifndef _FCNTL_H +# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead." +#endif + +#include <bits/wordsize.h> + +/* In 64-bit ISA files are always with 64bit off_t and F_*LK64 are the same as + non-64-bit versions. It will need to be revised for 128-bit. */ +#if __WORDSIZE == 64 +# define __O_LARGEFILE 0 + +# define F_GETLK64 5 /* Get record locking info. */ +# define F_SETLK64 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 7 /* Set record locking info (blocking). */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Include generic Linux declarations. */ +#include <bits/fcntl-linux.h> diff --git a/sysdeps/unix/sysv/linux/riscv/bits/mman.h b/sysdeps/unix/sysv/linux/riscv/bits/mman.h new file mode 100644 index 0000000000..0e64f1eea7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/bits/mman.h @@ -0,0 +1,36 @@ +/* Definitions for POSIX memory map interface. Linux/RISC-V version. + Copyright (C) 1997-2018 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/>. */ + +#ifndef _SYS_MMAN_H +# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead." +#endif + +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY. */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +# define MAP_STACK 0x20000 /* Allocation is for a stack. */ +# define MAP_HUGETLB 0x40000 /* Create huge page mapping. */ +#endif + +/* Include generic Linux declarations. */ +#include <bits/mman-linux.h> diff --git a/sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h b/sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h new file mode 100644 index 0000000000..9b896a6262 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/bits/sigcontext.h @@ -0,0 +1,32 @@ +/* Machine-dependent signal context structure for Linux. RISC-V version. + Copyright (C) 1996-2018 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/>. */ + +#ifndef _BITS_SIGCONTEXT_H +#define _BITS_SIGCONTEXT_H 1 + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead." +#endif + +struct sigcontext { + /* gregs[0] holds the program counter. */ + unsigned long int gregs[32]; + unsigned long long int fpregs[66] __attribute__ ((__aligned__ (16))); +}; + +#endif diff --git a/sysdeps/unix/sysv/linux/riscv/dl-cache.h b/sysdeps/unix/sysv/linux/riscv/dl-cache.h new file mode 100644 index 0000000000..cbd6ef5e09 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/dl-cache.h @@ -0,0 +1,75 @@ +/* Support for reading /etc/ld.so.cache files written by Linux ldconfig. + Copyright (C) 2003-2018 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 <ldconfig.h> + +/* For now we only support the natural XLEN ABI length on all targets, so the + only bits that need to go into ld.so.cache are the FLEG ABI length. */ +#if defined __riscv_float_abi_double +# define _DL_CACHE_DEFAULT_ID (FLAG_RISCV_FLOAT_ABI_DOUBLE | FLAG_ELF_LIBC6) +#else +# define _DL_CACHE_DEFAULT_ID (FLAG_RISCV_FLOAT_ABI_SOFT | FLAG_ELF_LIBC6) +#endif + +#define _dl_cache_check_flags(flags) \ + ((flags) == _DL_CACHE_DEFAULT_ID) + +/* If given a path to one of our library directories, adds every library + directory via add_dir (), otherwise just adds the giver directory. On + RISC-V, libraries can be found in paths ending in: + - /lib64/lp64d + - /lib64/lp64 + - /lib (only ld.so) + so this will add all of those paths. + + According to Joseph Myers: + My reasoning for that would be: generic autoconf-configured (etc.) + software may only know about using the lib directory, so you want the + lib directory to be searched regardless of the ABI - but it's also + useful to be able to e.g. list /usr/local/lib in /etc/ld.so.conf for all + architectures and have that automatically imply /usr/local/lib64/lp64d + etc. so that libraries can be found that come from software that does + use the ABI-specific directories. */ +#define add_system_dir(dir) \ + do \ + { \ + size_t len = strlen (dir); \ + char path[len + 9]; \ + memcpy (path, dir, len + 1); \ + if (len >= 12 && ! memcmp(path + len - 12, "/lib64/lp64d", 12)) \ + { \ + len -= 8; \ + path[len] = '\0'; \ + } \ + if (len >= 11 && ! memcmp(path + len - 11, "/lib64/lp64", 11)) \ + { \ + len -= 7; \ + path[len] = '\0'; \ + } \ + add_dir (path); \ + if (len >= 4 && ! memcmp(path + len - 4, "/lib", 4)) \ + { \ + memcpy (path + len, "64/lp64d", 9); \ + add_dir (path); \ + memcpy (path + len, "64/lp64", 8); \ + add_dir (path); \ + } \ + } while (0) + + +#include_next <dl-cache.h> diff --git a/sysdeps/unix/sysv/linux/riscv/flush-icache.c b/sysdeps/unix/sysv/linux/riscv/flush-icache.c new file mode 100644 index 0000000000..d612ef4c6c --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/flush-icache.c @@ -0,0 +1,73 @@ +/* RISC-V instruction cache flushing VDSO calls + Copyright (C) 2017-2018 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 <dl-vdso.h> +#include <stdlib.h> +#include <atomic.h> +#include <sys/cachectl.h> +#include <asm/syscalls.h> + +typedef int (*func_type) (void *, void *, unsigned long int); + +static int +__riscv_flush_icache_syscall (void *start, void *end, unsigned long int flags) +{ + return INLINE_SYSCALL (riscv_flush_icache, 3, start, end, flags); +} + +static func_type +__lookup_riscv_flush_icache (void) +{ + PREPARE_VERSION_KNOWN (linux_version, LINUX_4_15); + + func_type func = _dl_vdso_vsym ("__vdso_flush_icache", &linux_version); + + /* If there is no vDSO entry then call the system call directly. All Linux + versions provide the vDSO entry, but QEMU's user-mode emulation doesn't + provide a vDSO. */ + if (!func) + func = &__riscv_flush_icache_syscall; + + return func; +} + +#ifdef SHARED + +# define INIT_ARCH() +libc_ifunc (__riscv_flush_icache, __lookup_riscv_flush_icache ()) + +#else + +int +__riscv_flush_icache (void *start, void *end, unsigned long int flags) +{ + static volatile func_type cached_func; + + func_type func = atomic_load_relaxed (&cached_func); + + if (!func) + { + func = __lookup_riscv_flush_icache (); + atomic_store_relaxed (&cached_func, func); + } + + return func (start, end, flags); +} + +#endif diff --git a/sysdeps/unix/sysv/linux/riscv/getcontext.S b/sysdeps/unix/sysv/linux/riscv/getcontext.S new file mode 100644 index 0000000000..bde350f721 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/getcontext.S @@ -0,0 +1,77 @@ +/* Save current context. + Copyright (C) 2009-2018 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 "ucontext-macros.h" + +/* int getcontext (ucontext_t *ucp) */ + + .text +LEAF (__getcontext) + SAVE_INT_REG (ra, 0, a0) + SAVE_INT_REG (ra, 1, a0) + SAVE_INT_REG (sp, 2, a0) + SAVE_INT_REG (s0, 8, a0) + SAVE_INT_REG (s1, 9, a0) + SAVE_INT_REG (x0, 10, a0) /* return 0 by overwriting a0. */ + SAVE_INT_REG (s2, 18, a0) + SAVE_INT_REG (s3, 19, a0) + SAVE_INT_REG (s4, 20, a0) + SAVE_INT_REG (s5, 21, a0) + SAVE_INT_REG (s6, 22, a0) + SAVE_INT_REG (s7, 23, a0) + SAVE_INT_REG (s8, 24, a0) + SAVE_INT_REG (s9, 25, a0) + SAVE_INT_REG (s10, 26, a0) + SAVE_INT_REG (s11, 27, a0) + +#ifndef __riscv_float_abi_soft + frsr a1 + + SAVE_FP_REG (fs0, 8, a0) + SAVE_FP_REG (fs1, 9, a0) + SAVE_FP_REG (fs2, 18, a0) + SAVE_FP_REG (fs3, 19, a0) + SAVE_FP_REG (fs4, 20, a0) + SAVE_FP_REG (fs5, 21, a0) + SAVE_FP_REG (fs6, 22, a0) + SAVE_FP_REG (fs7, 23, a0) + SAVE_FP_REG (fs8, 24, a0) + SAVE_FP_REG (fs9, 25, a0) + SAVE_FP_REG (fs10, 26, a0) + SAVE_FP_REG (fs11, 27, a0) + + sw a1, MCONTEXT_FSR(a0) +#endif /* __riscv_float_abi_soft */ + +/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */ + li a3, _NSIG8 + add a2, a0, UCONTEXT_SIGMASK + mv a1, zero + li a0, SIG_BLOCK + + li a7, SYS_ify (rt_sigprocmask) + scall + bltz a0, 99f + + ret + +99: j __syscall_error + +PSEUDO_END (__getcontext) + +weak_alias (__getcontext, getcontext) diff --git a/sysdeps/unix/sysv/linux/riscv/init-first.c b/sysdeps/unix/sysv/linux/riscv/init-first.c new file mode 100644 index 0000000000..56abe51d96 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/init-first.c @@ -0,0 +1,58 @@ +/* RISC-V VDSO initialization + Copyright (C) 2017-2018 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/>. */ + +#ifdef SHARED +# include <dl-vdso.h> +# include <libc-vdso.h> + +long int (*VDSO_SYMBOL (getcpu)) (unsigned int *, unsigned int *, void *) + attribute_hidden; +long int (*VDSO_SYMBOL (gettimeofday)) (struct timeval *, void *) + attribute_hidden; +long int (*VDSO_SYMBOL (clock_gettime)) (clockid_t, struct timespec *) + attribute_hidden; +long int (*VDSO_SYMBOL (clock_getres)) (clockid_t, struct timespec *) + attribute_hidden; + +static inline void +_libc_vdso_platform_setup (void) +{ + PREPARE_VERSION_KNOWN (linux_version, LINUX_4_15); + + void *p = _dl_vdso_vsym ("__vdso_getcpu", &linux_version); + PTR_MANGLE (p); + VDSO_SYMBOL (getcpu) = p; + + p = _dl_vdso_vsym ("__vdso_gettimeofday", &linux_version); + PTR_MANGLE (p); + VDSO_SYMBOL (gettimeofday) = p; + + p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux_version); + PTR_MANGLE (p); + VDSO_SYMBOL (clock_gettime) = p; + + p = _dl_vdso_vsym ("__vdso_clock_getres", &linux_version); + PTR_MANGLE (p); + VDSO_SYMBOL (clock_getres) = p; +} + +# define VDSO_SETUP _libc_vdso_platform_setup +#endif + +#include <csu/init-first.c> diff --git a/sysdeps/unix/sysv/linux/riscv/libc-vdso.h b/sysdeps/unix/sysv/linux/riscv/libc-vdso.h new file mode 100644 index 0000000000..1d44b34e02 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/libc-vdso.h @@ -0,0 +1,38 @@ +/* RISC-V VDSO function declarations + Copyright (C) 2017-2018 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/>. */ + +#ifndef _LIBC_VDSO_H +#define _LIBC_VDSO_H + +#ifdef SHARED + +# include <sysdep-vdso.h> + +extern long int (*VDSO_SYMBOL (getcpu)) (unsigned int *, unsigned int *, void *) + attribute_hidden; +extern long int (*VDSO_SYMBOL (gettimeofday)) (struct timeval *, void *) + attribute_hidden; +extern long int (*VDSO_SYMBOL (clock_gettime)) (clockid_t, struct timespec *) + attribute_hidden; +extern long int (*VDSO_SYMBOL (clock_getres)) (clockid_t, struct timespec *) + attribute_hidden; + +#endif + +#endif /* _LIBC_VDSO_H */ diff --git a/sysdeps/unix/sysv/linux/riscv/makecontext.c b/sysdeps/unix/sysv/linux/riscv/makecontext.c new file mode 100644 index 0000000000..b8054a29b0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/makecontext.c @@ -0,0 +1,78 @@ +/* Create new context. RISC-V version. + Copyright (C) 2001-2018 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 <sys/asm.h> +#include <sys/ucontext.h> +#include <stdarg.h> +#include <assert.h> + +void +__makecontext (ucontext_t *ucp, void (*func) (void), int argc, + long int a0, long int a1, long int a2, long int a3, long int a4, + ...) +{ + extern void __start_context (void) attribute_hidden; + long int i, sp; + + _Static_assert (REG_NARGS == 8, "__makecontext assumes 8 argument registers"); + + /* Set up the stack. */ + sp = ((long int) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) & ALMASK; + + /* Set up the register context. + ra = s0 = 0, terminating the stack for backtracing purposes. + s1 = the function we must call. + s2 = the subsequent context to run. */ + ucp->uc_mcontext.__gregs[REG_RA] = 0; + ucp->uc_mcontext.__gregs[REG_S0] = 0; + ucp->uc_mcontext.__gregs[REG_S1] = (long int) func; + ucp->uc_mcontext.__gregs[REG_S2] = (long int) ucp->uc_link; + ucp->uc_mcontext.__gregs[REG_SP] = sp; + ucp->uc_mcontext.__gregs[REG_PC] = (long int) &__start_context; + + /* Put args in a0-a7, then put any remaining args on the stack. */ + ucp->uc_mcontext.__gregs[REG_A0 + 0] = a0; + ucp->uc_mcontext.__gregs[REG_A0 + 1] = a1; + ucp->uc_mcontext.__gregs[REG_A0 + 2] = a2; + ucp->uc_mcontext.__gregs[REG_A0 + 3] = a3; + ucp->uc_mcontext.__gregs[REG_A0 + 4] = a4; + + if (__glibc_unlikely (argc > 5)) + { + va_list vl; + va_start (vl, a4); + + long reg_args = argc < REG_NARGS ? argc : REG_NARGS; + for (i = 5; i < reg_args; i++) + ucp->uc_mcontext.__gregs[REG_A0 + i] = va_arg (vl, long); + + long int stack_args = argc - reg_args; + if (stack_args > 0) + { + sp = (sp - stack_args * sizeof (long int)) & ALMASK; + ucp->uc_mcontext.__gregs[REG_SP] = sp; + for (i = 0; i < stack_args; i++) + ((long int *) sp)[i] = va_arg (vl, long int); + } + + va_end (vl); + } +} + +weak_alias (__makecontext, makecontext) diff --git a/sysdeps/unix/sysv/linux/riscv/readelflib.c b/sysdeps/unix/sysv/linux/riscv/readelflib.c new file mode 100644 index 0000000000..6e249ff82f --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/readelflib.c @@ -0,0 +1,96 @@ +/* Support for reading ELF files. + Copyright (C) 1999-2018 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/>. */ + + +int process_elf32_file (const char *file_name, const char *lib, int *flag, + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); +int process_elf64_file (const char *file_name, const char *lib, int *flag, + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); + +/* The ELF flags supported by our current glibc port: + - EF_RISCV_FLOAT_ABI: We support the soft and double ABIs. + - EF_RISCV_RVC: While the Linux ABI mandates the presence of the C + extension, we can still support libraries compiled without that extension + so we just ignore this flag. + - EF_RISCV_RVE: glibc (and Linux) don't support RV32E based systems. + - EF_RISCV_TSO: The TSO extension isn't supported, as doing so would require + some mechanism to ensure that the TSO extension is enabled which doesn't + currently exist. */ +#define SUPPORTED_ELF_FLAGS (EF_RISCV_FLOAT_ABI | EF_RISCV_RVC) + +/* Returns 0 if everything is ok, != 0 in case of error. */ +int +process_elf_file (const char *file_name, const char *lib, int *flag, + unsigned int *osversion, char **soname, void *file_contents, + size_t file_length) +{ + ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents; + Elf32_Ehdr *elf32_header = (Elf32_Ehdr *) elf_header; + int ret; + long flags; + + /* RISC-V libraries are always libc.so.6+. */ + *flag = FLAG_ELF_LIBC6; + + if (elf_header->e_ident [EI_CLASS] == ELFCLASS32) + { + ret = process_elf32_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); + flags = elf32_header->e_flags; + } + else + { + ret = process_elf64_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); + flags = elf32_header->e_flags; + } + + /* RISC-V linkers encode the floating point ABI as part of the ELF headers. */ + switch (flags & EF_RISCV_FLOAT_ABI) + { + case EF_RISCV_FLOAT_ABI_SOFT: + *flag |= FLAG_RISCV_FLOAT_ABI_SOFT; + break; + case EF_RISCV_FLOAT_ABI_DOUBLE: + *flag |= FLAG_RISCV_FLOAT_ABI_DOUBLE; + break; + default: + return 1; + } + + /* If there are any other ELF flags set then glibc doesn't support this + library. */ + if (flags & ~SUPPORTED_ELF_FLAGS) + return 1; + + return ret; +} + +#undef __ELF_NATIVE_CLASS +#undef process_elf_file +#define process_elf_file process_elf32_file +#define __ELF_NATIVE_CLASS 32 +#include "elf/readelflib.c" + +#undef __ELF_NATIVE_CLASS +#undef process_elf_file +#define process_elf_file process_elf64_file +#define __ELF_NATIVE_CLASS 64 +#include "elf/readelflib.c" diff --git a/sysdeps/unix/sysv/linux/riscv/register-dump.h b/sysdeps/unix/sysv/linux/riscv/register-dump.h new file mode 100644 index 0000000000..234ce630f9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/register-dump.h @@ -0,0 +1,63 @@ +/* Dump registers. + Copyright (C) 2000-2018 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 <unistd.h> +#include <string.h> +#include <_itoa.h> + +static void +hexvalue (unsigned long int value, char *buf, size_t len) +{ + char *cp = _itoa_word (value, buf + len, 16, 0); + while (cp > buf) + *--cp = '0'; +} + +#define REGDUMP_NREGS 32 +#define REGDUMP_PER_LINE (80 / (__WORDSIZE / 4 + 4)) + +static void +register_dump (int fd, ucontext_t *ctx) +{ + int i; + char regvalue[__WORDSIZE / 4 + 1]; + char str[82 * ((REGDUMP_NREGS + REGDUMP_PER_LINE - 1) / REGDUMP_PER_LINE)]; + + static const char names[REGDUMP_NREGS][4] = { + "pc", "ra", "sp", "gp", "tp", "t0", "t1", "t2", + "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", + "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", + "s8", "s9", "sA", "sB", "t3", "t4", "t5", "t6" + }; + + str[0] = 0; + for (i = 0; i < REGDUMP_NREGS; i++) + { + strcat (str, names[i]); + strcat (str, " "); + hexvalue (ctx->uc_mcontext.__gregs[i], regvalue, __WORDSIZE / 4); + strcat (str, regvalue); + + if ((i + 1) % REGDUMP_PER_LINE == 0) + strcat (str, "\n"); + } + + write (fd, str, strlen (str)); +} + +#define REGISTER_DUMP register_dump (fd, ctx) diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/jmp_buf-macros.h b/sysdeps/unix/sysv/linux/riscv/rv64/jmp_buf-macros.h new file mode 100644 index 0000000000..34434a8d93 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/rv64/jmp_buf-macros.h @@ -0,0 +1,53 @@ +/* jump buffer constants for RISC-V + Copyright (C) 2017-2018 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/>. */ + +/* Produced by this program: + + #include <stdio.h> + #include <unistd.h> + #include <setjmp.h> + #include <stddef.h> + + int main (int argc, char **argv) + { + printf ("#define JMP_BUF_SIZE %d\n", sizeof (jmp_buf)); + printf ("#define JMP_BUF_ALIGN %d\n", __alignof__ (jmp_buf)); + printf ("#define SIGJMP_BUF_SIZE %d\n", sizeof (sigjmp_buf)); + printf ("#define SIGJMP_BUF_ALIGN %d\n", __alignof__ (sigjmp_buf)); + printf ("#define MASK_WAS_SAVED_OFFSET %d\n", offsetof (struct __jmp_buf_tag, __mask_was_saved)); + printf ("#define SAVED_MASK_OFFSET %d\n", offsetof (struct __jmp_buf_tag, __saved_mask)); + } */ + +#if defined __riscv_float_abi_soft +# define JMP_BUF_SIZE 248 +# define JMP_BUF_ALIGN 8 +# define SIGJMP_BUF_SIZE 248 +# define SIGJMP_BUF_ALIGN 8 +# define MASK_WAS_SAVED_OFFSET 112 +# define SAVED_MASK_OFFSET 120 +#elif defined __riscv_float_abi_double +# define JMP_BUF_SIZE 344 +# define JMP_BUF_ALIGN 8 +# define SIGJMP_BUF_SIZE 344 +# define SIGJMP_BUF_ALIGN 8 +# define MASK_WAS_SAVED_OFFSET 208 +# define SAVED_MASK_OFFSET 216 +#else +# error "Unknown RISC-V floating-point ABI" +#endif diff --git a/sysdeps/unix/sysv/linux/riscv/setcontext.S b/sysdeps/unix/sysv/linux/riscv/setcontext.S new file mode 100644 index 0000000000..9f1c7b41fd --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/setcontext.S @@ -0,0 +1,114 @@ +/* Set current context. + Copyright (C) 2009-2018 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 "ucontext-macros.h" + +/* int __setcontext (const ucontext_t *ucp) + + Restores the machine context in UCP and thereby resumes execution + in that context. + + This implementation is intended to be used for *synchronous* context + switches only. Therefore, it does not have to restore anything + other than the PRESERVED state. */ + + .text +LEAF (__setcontext) + + mv t0, a0 /* Save ucp into t0. */ + +/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */ + li a3, _NSIG8 + mv a2, zero + add a1, a0, UCONTEXT_SIGMASK + li a0, SIG_SETMASK + + li a7, SYS_ify (rt_sigprocmask) + scall + + bltz a0, 99f + + cfi_def_cfa (t0, 0) + +#ifndef __riscv_float_abi_soft + lw t1, MCONTEXT_FSR(t0) + + RESTORE_FP_REG_CFI (fs0, 8, t0) + RESTORE_FP_REG_CFI (fs1, 9, t0) + RESTORE_FP_REG_CFI (fs2, 18, t0) + RESTORE_FP_REG_CFI (fs3, 19, t0) + RESTORE_FP_REG_CFI (fs4, 20, t0) + RESTORE_FP_REG_CFI (fs5, 21, t0) + RESTORE_FP_REG_CFI (fs6, 22, t0) + RESTORE_FP_REG_CFI (fs7, 23, t0) + RESTORE_FP_REG_CFI (fs8, 24, t0) + RESTORE_FP_REG_CFI (fs9, 25, t0) + RESTORE_FP_REG_CFI (fs10, 26, t0) + RESTORE_FP_REG_CFI (fs11, 27, t0) + + fssr t1 +#endif /* __riscv_float_abi_soft */ + + /* Note the contents of argument registers will be random + unless makecontext() has been called. */ + RESTORE_INT_REG (t1, 0, t0) + RESTORE_INT_REG_CFI (ra, 1, t0) + RESTORE_INT_REG (sp, 2, t0) + RESTORE_INT_REG_CFI (s0, 8, t0) + RESTORE_INT_REG_CFI (s1, 9, t0) + RESTORE_INT_REG (a0, 10, t0) + RESTORE_INT_REG (a1, 11, t0) + RESTORE_INT_REG (a2, 12, t0) + RESTORE_INT_REG (a3, 13, t0) + RESTORE_INT_REG (a4, 14, t0) + RESTORE_INT_REG (a5, 15, t0) + RESTORE_INT_REG (a6, 16, t0) + RESTORE_INT_REG (a7, 17, t0) + RESTORE_INT_REG_CFI (s2, 18, t0) + RESTORE_INT_REG_CFI (s3, 19, t0) + RESTORE_INT_REG_CFI (s4, 20, t0) + RESTORE_INT_REG_CFI (s5, 21, t0) + RESTORE_INT_REG_CFI (s6, 22, t0) + RESTORE_INT_REG_CFI (s7, 23, t0) + RESTORE_INT_REG_CFI (s8, 24, t0) + RESTORE_INT_REG_CFI (s9, 25, t0) + RESTORE_INT_REG_CFI (s10, 26, t0) + RESTORE_INT_REG_CFI (s11, 27, t0) + + jr t1 + +99: j __syscall_error + +PSEUDO_END (__setcontext) +weak_alias (__setcontext, setcontext) + +LEAF (__start_context) + + /* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */ + cfi_register (ra, s0) + + /* Call the function passed to makecontext. */ + jalr s1 + + /* Invoke subsequent context if present, else exit(0). */ + mv a0, s2 + beqz s2, 1f + jal __setcontext +1: j exit + +PSEUDO_END (__start_context) diff --git a/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h b/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h new file mode 100644 index 0000000000..3ca8a80d8b --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h @@ -0,0 +1,28 @@ +/* RISC-V definitions for signal handling calling conventions. + Copyright (C) 2000-2018 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 <sys/ucontext.h> + +#define SIGCONTEXT siginfo_t *_si, ucontext_t * +#define SIGCONTEXT_EXTRA_ARGS _si, +#define GET_PC(ctx) ((void *) ctx->uc_mcontext.__gregs[REG_PC]) +#define GET_FRAME(ctx) ((void *) ctx->uc_mcontext.__gregs[REG_S0]) +#define GET_STACK(ctx) ((void *) ctx->uc_mcontext.__gregs[REG_SP]) + +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/sysdeps/unix/sysv/linux/riscv/swapcontext.S b/sysdeps/unix/sysv/linux/riscv/swapcontext.S new file mode 100644 index 0000000000..75b58dc668 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/swapcontext.S @@ -0,0 +1,125 @@ +/* Save and set current context. + Copyright (C) 2009-2018 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 "ucontext-macros.h" + +/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ + +LEAF (__swapcontext) + mv t0, a1 /* Save ucp into t0. */ + + SAVE_INT_REG (ra, 0, a0) + SAVE_INT_REG (ra, 1, a0) + SAVE_INT_REG (sp, 2, a0) + SAVE_INT_REG (s0, 8, a0) + SAVE_INT_REG (s1, 9, a0) + SAVE_INT_REG (x0, 10, a0) /* return 0 by overwriting a0. */ + SAVE_INT_REG (s2, 18, a0) + SAVE_INT_REG (s3, 19, a0) + SAVE_INT_REG (s4, 20, a0) + SAVE_INT_REG (s5, 21, a0) + SAVE_INT_REG (s6, 22, a0) + SAVE_INT_REG (s7, 23, a0) + SAVE_INT_REG (s8, 24, a0) + SAVE_INT_REG (s9, 25, a0) + SAVE_INT_REG (s10, 26, a0) + SAVE_INT_REG (s11, 27, a0) + +#ifndef __riscv_float_abi_soft + frsr a1 + + SAVE_FP_REG (fs0, 8, a0) + SAVE_FP_REG (fs1, 9, a0) + SAVE_FP_REG (fs2, 18, a0) + SAVE_FP_REG (fs3, 19, a0) + SAVE_FP_REG (fs4, 20, a0) + SAVE_FP_REG (fs5, 21, a0) + SAVE_FP_REG (fs6, 22, a0) + SAVE_FP_REG (fs7, 23, a0) + SAVE_FP_REG (fs8, 24, a0) + SAVE_FP_REG (fs9, 25, a0) + SAVE_FP_REG (fs10, 26, a0) + SAVE_FP_REG (fs11, 27, a0) + + sw a1, MCONTEXT_FSR(a0) +#endif /* __riscv_float_abi_soft */ + +/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */ + li a3, _NSIG8 + add a2, a0, UCONTEXT_SIGMASK + add a1, t0, UCONTEXT_SIGMASK + li a0, SIG_SETMASK + + li a7, SYS_ify (rt_sigprocmask) + scall + + bltz a0, 99f + +#ifndef __riscv_float_abi_soft + lw t1, MCONTEXT_FSR(t0) + + RESTORE_FP_REG (fs0, 8, t0) + RESTORE_FP_REG (fs1, 9, t0) + RESTORE_FP_REG (fs2, 18, t0) + RESTORE_FP_REG (fs3, 19, t0) + RESTORE_FP_REG (fs4, 20, t0) + RESTORE_FP_REG (fs5, 21, t0) + RESTORE_FP_REG (fs6, 22, t0) + RESTORE_FP_REG (fs7, 23, t0) + RESTORE_FP_REG (fs8, 24, t0) + RESTORE_FP_REG (fs9, 25, t0) + RESTORE_FP_REG (fs10, 26, t0) + RESTORE_FP_REG (fs11, 27, t0) + + fssr t1 +#endif /* __riscv_float_abi_soft */ + + /* Note the contents of argument registers will be random + unless makecontext() has been called. */ + RESTORE_INT_REG (t1, 0, t0) + RESTORE_INT_REG (ra, 1, t0) + RESTORE_INT_REG (sp, 2, t0) + RESTORE_INT_REG (s0, 8, t0) + RESTORE_INT_REG (s1, 9, t0) + RESTORE_INT_REG (a0, 10, t0) + RESTORE_INT_REG (a1, 11, t0) + RESTORE_INT_REG (a2, 12, t0) + RESTORE_INT_REG (a3, 13, t0) + RESTORE_INT_REG (a4, 14, t0) + RESTORE_INT_REG (a5, 15, t0) + RESTORE_INT_REG (a6, 16, t0) + RESTORE_INT_REG (a7, 17, t0) + RESTORE_INT_REG (s2, 18, t0) + RESTORE_INT_REG (s3, 19, t0) + RESTORE_INT_REG (s4, 20, t0) + RESTORE_INT_REG (s5, 21, t0) + RESTORE_INT_REG (s6, 22, t0) + RESTORE_INT_REG (s7, 23, t0) + RESTORE_INT_REG (s8, 24, t0) + RESTORE_INT_REG (s9, 25, t0) + RESTORE_INT_REG (s10, 26, t0) + RESTORE_INT_REG (s11, 27, t0) + + jr t1 + + +99: j __syscall_error + +PSEUDO_END (__swapcontext) + +weak_alias (__swapcontext, swapcontext) diff --git a/sysdeps/unix/sysv/linux/riscv/sys/cachectl.h b/sysdeps/unix/sysv/linux/riscv/sys/cachectl.h new file mode 100644 index 0000000000..46a2cb6082 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sys/cachectl.h @@ -0,0 +1,32 @@ +/* RISC-V instruction cache flushing interface + Copyright (C) 2017-2018 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/>. */ + +#ifndef _SYS_CACHECTL_H +#define _SYS_CACHECTL_H 1 + +#include <features.h> + +__BEGIN_DECLS + +extern int __riscv_flush_icache (void *__start, void *__end, + unsigned long int __flags); + +__END_DECLS + +#endif /* sys/cachectl.h */ diff --git a/sysdeps/unix/sysv/linux/riscv/sys/procfs.h b/sysdeps/unix/sysv/linux/riscv/sys/procfs.h new file mode 100644 index 0000000000..518de56741 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sys/procfs.h @@ -0,0 +1,114 @@ +/* Core image file related definitions, RISC-V version. + Copyright (C) 1996-2018 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/>. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include <features.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/user.h> +#include <sys/ucontext.h> + +/* ELF register definitions */ +#define ELF_NGREG NGREG +#define ELF_NFPREG NFPREG + +typedef unsigned long int elf_greg_t; +typedef unsigned long int elf_gregset_t[32]; +typedef union __riscv_mc_fp_state elf_fpregset_t; + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + long int pr_uid; + long int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris <proc_service.h> interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h b/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h new file mode 100644 index 0000000000..7df430b504 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sys/ucontext.h @@ -0,0 +1,110 @@ +/* struct ucontext definition, RISC-V version. + Copyright (C) 1997-2018 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/>. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include <features.h> + +#include <bits/types/sigset_t.h> +#include <bits/types/stack_t.h> + +typedef unsigned long int __riscv_mc_gp_state[32]; + +#ifdef __USE_MISC +# define NGREG 32 + +# define REG_PC 0 +# define REG_RA 1 +# define REG_SP 2 +# define REG_TP 4 +# define REG_S0 8 +# define REG_S1 9 +# define REG_A0 10 +# define REG_S2 18 +# define REG_NARGS 8 + +typedef unsigned long int greg_t; + +/* Container for all general registers. */ +typedef __riscv_mc_gp_state gregset_t; + +/* Container for floating-point state. */ +typedef union __riscv_mc_fp_state fpregset_t; +#endif + +struct __riscv_mc_f_ext_state + { + unsigned int __f[32]; + unsigned int __fcsr; + }; + +struct __riscv_mc_d_ext_state + { + unsigned long long int __f[32]; + unsigned int __fcsr; + }; + +struct __riscv_mc_q_ext_state + { + unsigned long long int __f[64] __attribute__ ((__aligned__ (16))); + unsigned int __fcsr; + /* Reserved for expansion of sigcontext structure. Currently zeroed + upon signal, and must be zero upon sigreturn. */ + unsigned int __glibc_reserved[3]; + }; + +union __riscv_mc_fp_state + { + struct __riscv_mc_f_ext_state __f; + struct __riscv_mc_d_ext_state __d; + struct __riscv_mc_q_ext_state __q; + }; + +typedef struct mcontext_t + { + __riscv_mc_gp_state __gregs; + union __riscv_mc_fp_state __fpregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext_t + { + unsigned long int __uc_flags; + struct ucontext_t *uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + /* There's some padding here to allow sigset_t to be expanded in the + future. Though this is unlikely, other architectures put uc_sigmask + at the end of this structure and explicitly state it can be + expanded, so we didn't want to box ourselves in here. */ + char __glibc_reserved[1024 / 8 - sizeof (sigset_t)]; + /* We can't put uc_sigmask at the end of this structure because we need + to be able to expand sigcontext in the future. For example, the + vector ISA extension will almost certainly add ISA state. We want + to ensure all user-visible ISA state can be saved and restored via a + ucontext, so we're putting this at the end in order to allow for + infinite extensibility. Since we know this will be extended and we + assume sigset_t won't be extended an extreme amount, we're + prioritizing this. */ + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/sysdeps/unix/sysv/linux/riscv/sys/user.h b/sysdeps/unix/sysv/linux/riscv/sys/user.h new file mode 100644 index 0000000000..7e648f2d5c --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sys/user.h @@ -0,0 +1,23 @@ +/* Copyright (C) 2001-2018 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/>. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + + + +#endif /* _SYS_USER_H */ diff --git a/sysdeps/unix/sysv/linux/riscv/ucontext-macros.h b/sysdeps/unix/sysv/linux/riscv/ucontext-macros.h new file mode 100644 index 0000000000..a73c3a9b04 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/ucontext-macros.h @@ -0,0 +1,49 @@ +/* Macros for ucontext routines. + Copyright (C) 2017-2018 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/>. */ + +#ifndef _LINUX_RISCV_UCONTEXT_MACROS_H +#define _LINUX_RISCV_UCONTEXT_MACROS_H + +#include <sysdep.h> +#include <sys/asm.h> + +#include "ucontext_i.h" + +#define MCONTEXT_FSR (32 * SZFREG + MCONTEXT_FPREGS) + +#define SAVE_FP_REG(name, num, base) \ + FREG_S name, ((num) * SZFREG + MCONTEXT_FPREGS)(base) + +#define RESTORE_FP_REG(name, num, base) \ + FREG_L name, ((num) * SZFREG + MCONTEXT_FPREGS)(base) + +#define RESTORE_FP_REG_CFI(name, num, base) \ + RESTORE_FP_REG (name, num, base); \ + cfi_offset (name, (num) * SZFREG + MCONTEXT_FPREGS) + +#define SAVE_INT_REG(name, num, base) \ + REG_S name, ((num) * SZREG + MCONTEXT_GREGS)(base) + +#define RESTORE_INT_REG(name, num, base) \ + REG_L name, ((num) * SZREG + MCONTEXT_GREGS)(base) + +#define RESTORE_INT_REG_CFI(name, num, base) \ + RESTORE_INT_REG (name, num, base); \ + cfi_offset (name, (num) * SZREG + MCONTEXT_GREGS) + +#endif /* _LINUX_RISCV_UCONTEXT_MACROS_H */ diff --git a/sysdeps/unix/sysv/linux/riscv/ucontext_i.sym b/sysdeps/unix/sysv/linux/riscv/ucontext_i.sym new file mode 100644 index 0000000000..be55b26310 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/ucontext_i.sym @@ -0,0 +1,31 @@ +#include <inttypes.h> +#include <signal.h> +#include <stddef.h> +#include <sys/ucontext.h> + +-- Constants used by the rt_sigprocmask call. + +SIG_BLOCK +SIG_SETMASK + +_NSIG8 (_NSIG / 8) + +-- Offsets of the fields in the ucontext_t structure. +#define ucontext(member) offsetof (ucontext_t, member) +#define stack(member) ucontext (uc_stack.member) +#define mcontext(member) ucontext (uc_mcontext.member) + +UCONTEXT_FLAGS ucontext (__uc_flags) +UCONTEXT_LINK ucontext (uc_link) +UCONTEXT_STACK ucontext (uc_stack) +UCONTEXT_MCONTEXT ucontext (uc_mcontext) +UCONTEXT_SIGMASK ucontext (uc_sigmask) + +STACK_SP stack (ss_sp) +STACK_SIZE stack (ss_size) +STACK_FLAGS stack (ss_flags) + +MCONTEXT_GREGS mcontext (__gregs) +MCONTEXT_FPREGS mcontext (__fpregs) + +UCONTEXT_SIZE sizeof (ucontext_t) |