From patchwork Sat Jan 27 03:57:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Palmer Dabbelt X-Patchwork-Id: 25603 Received: (qmail 106316 invoked by alias); 27 Jan 2018 03:58:22 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 106169 invoked by uid 89); 27 Jan 2018 03:58:21 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-pl0-f53.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:date:message-id:in-reply-to:references :cc:from:to; bh=6iOx+HKjqQ7hUGAMxMyz5y6tZgDc1WA5cs3Wb/1Kfv8=; b=DQa89tXZUW49KZ/jka3oHgkT3btWIuP9yu3oQQwZeOvTu4wnXcagkLUqpK2DF+5Ndh laGlhHSShzpbVovjagTVDNd0wYNIsMhHTABbIrvVHXAF5H8c5fjswHJjR0r1Mc4+53cO BDKe/lixZNHq7gtAjFX3HzDb7zLVSqJJBYsq4figvLYjlZ22uW/Vs7aGUHVHnu2oUb4Q bYuYXrFx121oG4tDGhoF6OAC9FwJGx2UfDQxw2z+57j85VlkgApH6VVqSd0+T8IuJbmu EOAwdlRiaprEXf65cXIZ411TSqYnAV1WZmVL07nYcKxN4qg4ciIHmupqUYT6wSNsRLZV /2GA== X-Gm-Message-State: AKwxytcufSHHZctizBAHjXFmp8gO55oLn3lf0UAvVsCesLidubPpGWRE 6aP/DEcfEZd10I5A+OaeKn0mqQ== X-Google-Smtp-Source: AH8x224UdmS6ijCDkd/SlTqzXx9sKFDXwPXTU33euKe4G2Ddy4iqb3si+UAOTmCAwuEOGBUC918/uA== X-Received: by 2002:a17:902:2cc3:: with SMTP id n61-v6mr15773395plb.440.1517025493167; Fri, 26 Jan 2018 19:58:13 -0800 (PST) Subject: [PATCH v7 11/17] RISC-V: Linux Syscall Interface Date: Fri, 26 Jan 2018 19:57:38 -0800 Message-Id: <20180127035744.10058-12-palmer@dabbelt.com> In-Reply-To: <20180127035744.10058-1-palmer@dabbelt.com> References: <20180127035744.10058-1-palmer@dabbelt.com> Cc: Palmer Dabbelt From: Palmer Dabbelt To: libc-alpha@sourceware.org, joseph@codesourcery.com Contains the Linux system call interface, as well as the definitions of a handful of system calls. 2018-01-26 Palmer Dabbelt * sysdeps/riscv/nptl/nptl-sysdep.S: New file. * sysdeps/unix/sysv/linux/riscv/arch-fork.h: Likewise. * sysdeps/unix/sysv/linux/riscv/clone.S: Likewise. * sysdeps/unix/sysv/linux/riscv/profil-counter.h: Likewise. * sysdeps/unix/sysv/linux/riscv/pt-vfork.S: Likewise. * sysdeps/unix/sysv/linux/riscv/syscall.c: Likewise. * 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/nptl-sysdep.S | 2 + sysdeps/unix/sysv/linux/riscv/arch-fork.h | 26 ++ sysdeps/unix/sysv/linux/riscv/clone.S | 86 +++++++ sysdeps/unix/sysv/linux/riscv/profil-counter.h | 31 +++ sysdeps/unix/sysv/linux/riscv/pt-vfork.S | 1 + sysdeps/unix/sysv/linux/riscv/syscall.c | 35 +++ sysdeps/unix/sysv/linux/riscv/sysdep.S | 51 ++++ sysdeps/unix/sysv/linux/riscv/sysdep.h | 325 +++++++++++++++++++++++++ sysdeps/unix/sysv/linux/riscv/vfork.S | 44 ++++ 9 files changed, 601 insertions(+) create mode 100644 sysdeps/riscv/nptl/nptl-sysdep.S create mode 100644 sysdeps/unix/sysv/linux/riscv/arch-fork.h create mode 100644 sysdeps/unix/sysv/linux/riscv/clone.S create mode 100644 sysdeps/unix/sysv/linux/riscv/profil-counter.h create mode 100644 sysdeps/unix/sysv/linux/riscv/pt-vfork.S create mode 100644 sysdeps/unix/sysv/linux/riscv/syscall.c create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.S create mode 100644 sysdeps/unix/sysv/linux/riscv/sysdep.h create mode 100644 sysdeps/unix/sysv/linux/riscv/vfork.S diff --git a/sysdeps/riscv/nptl/nptl-sysdep.S b/sysdeps/riscv/nptl/nptl-sysdep.S new file mode 100644 index 000000000000..3f5c2a364afd --- /dev/null +++ b/sysdeps/riscv/nptl/nptl-sysdep.S @@ -0,0 +1,2 @@ +/* Pull in __syscall_error. */ +#include diff --git a/sysdeps/unix/sysv/linux/riscv/arch-fork.h b/sysdeps/unix/sysv/linux/riscv/arch-fork.h new file mode 100644 index 000000000000..f6f5d733439b --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/arch-fork.h @@ -0,0 +1,26 @@ +/* Internal definitions for thread-friendly fork implementation. Linux/RISC-V. + Copyright (C) 2002-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 + . */ + +#include +#include +#include + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ + NULL, NULL, &THREAD_SELF->tid) diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S new file mode 100644 index 000000000000..392af72b55da --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/clone.S @@ -0,0 +1,86 @@ +/* Wrapper around clone system call. 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 + . */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#define _ERRNO_H 1 +#include +#include +#include "tcb-offsets.h" + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + void *parent_tidptr, void *tls, void *child_tidptr) */ + + .text +LEAF (__clone) + + /* Sanity check arguments. */ + beqz a0,L (invalid) /* No NULL function pointers. */ + beqz a1,L (invalid) /* No NULL stack pointers. */ + + addi a1,a1,-16 /* Reserve argument save space. */ + REG_S a0,0(a1) /* Save function pointer. */ + REG_S a3,SZREG(a1) /* Save argument pointer. */ + + /* The syscall expects the args to be in different slots. */ + mv a0,a2 + mv a2,a4 + mv a3,a5 + mv a4,a6 + + /* Do the system call. */ + li a7,__NR_clone + scall + + bltz a0,L (error) + beqz a0,L (thread_start) + + /* Successful return from the parent. */ + ret + +L (invalid): + li a0, -EINVAL + /* Something bad happened -- no child created. */ +L (error): + j __syscall_error + END (__clone) + +/* Load up the arguments to the function. Put this block of code in + its own function so that we can terminate the stack trace with our + debug info. */ + +ENTRY (__thread_start) +L (thread_start): + /* Restore the arg for user's function. */ + REG_L a1,0(sp) /* Function pointer. */ + REG_L a0,SZREG(sp) /* Argument pointer. */ + + /* Call the user's function. */ + jalr a1 + + /* Call exit with the function's return value. */ + li a7, __NR_exit + scall + + END (__thread_start) + +libc_hidden_def (__clone) +weak_alias (__clone, clone) diff --git a/sysdeps/unix/sysv/linux/riscv/profil-counter.h b/sysdeps/unix/sysv/linux/riscv/profil-counter.h new file mode 100644 index 000000000000..748019ee1b9d --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/profil-counter.h @@ -0,0 +1,31 @@ +/* Low-level statistical profiling support function. 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 + . */ + +#include +#include + +static void +__profil_counter (int signo, const SIGCONTEXT scp) +{ + profil_count ((void *) GET_PC (scp)); + + /* This is a hack to prevent the compiler from implementing the + above function call as a sibcall. The sibcall would overwrite + the signal context. */ + asm volatile (""); +} diff --git a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S new file mode 100644 index 000000000000..1cc893170070 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/sysdeps/unix/sysv/linux/riscv/syscall.c b/sysdeps/unix/sysv/linux/riscv/syscall.c new file mode 100644 index 000000000000..6589dde385e0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/syscall.c @@ -0,0 +1,35 @@ +/* system call interface. Linux/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 + . */ + +#include + +long int +syscall (long int syscall_number, long int arg1, long int arg2, long int arg3, + long int arg4, long int arg5, long int arg6, long int arg7) +{ + long int ret; + INTERNAL_SYSCALL_DECL (err); + + ret = INTERNAL_SYSCALL_NCS (syscall_number, err, 7, arg1, arg2, arg3, arg4, + arg5, arg6, arg7); + + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return __syscall_error (ret); + + return ret; +} diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.S b/sysdeps/unix/sysv/linux/riscv/sysdep.S new file mode 100644 index 000000000000..0d9c0b5bd907 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.S @@ -0,0 +1,51 @@ +/* syscall error handlers + 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 + . */ + +#include + +#if IS_IN (libc) +# define errno __libc_errno +#endif + +ENTRY (__syscall_error) + mv t0, ra + /* Fall through to __syscall_set_errno. */ +END (__syscall_error) + +/* Non-standard calling convention: argument in a0, return address in t0, + and clobber only t1. */ +ENTRY (__syscall_set_errno) + /* We got here because a0 < 0, but only codes in the range [-4095, -1] + represent errors. Otherwise, just return the result normally. */ + li t1, -4096 + bleu a0, t1, 1f + neg a0, a0 +#if RTLD_PRIVATE_ERRNO + sw a0, rtld_errno, t1 +#elif defined(__PIC__) + la.tls.ie t1, errno + add t1, t1, tp + sw a0, 0(t1) +#else + lui t1, %tprel_hi(errno) + add t1, t1, tp, %tprel_add(errno) + sw a0, %tprel_lo(errno)(t1) +#endif + li a0, -1 +1: jr t0 +END (__syscall_set_errno) diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h new file mode 100644 index 000000000000..5470ea3d2a68 --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h @@ -0,0 +1,325 @@ +/* Assembly macros for RISC-V. + Copyright (C) 2011-2018 + 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 + . */ + +#ifndef _LINUX_RISCV_SYSDEP_H +#define _LINUX_RISCV_SYSDEP_H 1 + +#include +#include + +#ifdef __ASSEMBLER__ + +# include + +# define ENTRY(name) LEAF(name) + +# define L(label) .L ## label + +/* Performs a system call, handling errors by setting errno. Linux indicates + errors by setting a0 to a value between -1 and -4095. */ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + .align 2; \ + ENTRY (name); \ + li a7, SYS_ify (syscall_name); \ + scall; \ + li a7, -4096; \ + bgtu a0, a7, .Lsyscall_error ## name; + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + SYSCALL_ERROR_HANDLER (sym) \ + ret; \ + END (sym) + +# if !IS_IN (libc) +# if RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER(name) \ +.Lsyscall_error ## name: \ + li t1, -4096; \ + neg a0, a0; \ + sw a0, rtld_errno, t1; \ + li a0, -1; +# elif defined (__PIC__) +# define SYSCALL_ERROR_HANDLER(name) \ +.Lsyscall_error ## name: \ + la.tls.ie t1, errno; \ + add t1, t1, tp; \ + neg a0, a0; \ + sw a0, 0(t1); \ + li a0, -1; +# else +# define SYSCALL_ERROR_HANDLER(name) \ +.Lsyscall_error ## name: \ + lui t1, %tprel_hi(errno); \ + add t1, t1, tp, %tprel_add(errno); \ + neg a0, a0; \ + sw a0, %tprel_lo(errno)(t1); \ + li a0, -1; +# endif +# else +# define SYSCALL_ERROR_HANDLER(name) \ +.Lsyscall_error ## name: \ + j __syscall_error; +# endif + +/* Performs a system call, not setting errno. */ +# undef PSEUDO_NEORRNO +# define PSEUDO_NOERRNO(name, syscall_name, args) \ + .align 2; \ + ENTRY (name); \ + li a7, SYS_ify (syscall_name); \ + scall; + +# undef PSEUDO_END_NOERRNO +# define PSEUDO_END_NOERRNO(name) \ + END (name) + +# undef ret_NOERRNO +# define ret_NOERRNO ret + +/* Perfroms a system call, returning the error code. */ +# undef PSEUDO_ERRVAL +# define PSEUDO_ERRVAL(name, syscall_name, args) \ + PSEUDO_NOERRNO (name, syscall_name, args) \ + neg a0, a0; + +# undef PSEUDO_END_ERRVAL +# define PSEUDO_END_ERRVAL(name) \ + END (name) + +# undef ret_ERRVAL +# define ret_ERRVAL ret + +#endif /* __ASSEMBLER__ */ + +/* In order to get __set_errno() definition in INLINE_SYSCALL. */ +#ifndef __ASSEMBLER__ +# include +#endif + +#include + +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +#ifndef __ASSEMBLER__ + +/* List of system calls which are supported as vsyscalls. */ +# define HAVE_CLOCK_GETRES_VSYSCALL 1 +# define HAVE_CLOCK_GETTIME_VSYSCALL 1 +# define HAVE_GETTIMEOFDAY_VSYSCALL 1 +# define HAVE_GETCPU_VSYSCALL 1 + +/* Define a macro which expands into the inline wrapper code for a system + call. */ +# undef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long int __sys_result = INTERNAL_SYSCALL (name, err, nr, args); \ + if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__sys_result, ))) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (__sys_result, )); \ + __sys_result = (unsigned long) -1; \ + } \ + __sys_result; }) + +# define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +# define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned long int) (val) > -4096UL) + +# define INTERNAL_SYSCALL_ERRNO(val, err) (-val) + +# define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr (SYS_ify (name), err, args) + +# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (number, err, args) + +# define internal_syscall0(number, err, dummy...) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0"); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "=r" (__a0) \ + : "r" (__a7) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define internal_syscall1(number, err, arg0) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0") = (long int) (arg0); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define internal_syscall2(number, err, arg0, arg1) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0") = (long int) (arg0); \ + register long int __a1 asm ("a1") = (long int) (arg1); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7), "r" (__a1) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define internal_syscall3(number, err, arg0, arg1, arg2) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0") = (long int) (arg0); \ + register long int __a1 asm ("a1") = (long int) (arg1); \ + register long int __a2 asm ("a2") = (long int) (arg2); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define internal_syscall4(number, err, arg0, arg1, arg2, arg3) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0") = (long int) (arg0); \ + register long int __a1 asm ("a1") = (long int) (arg1); \ + register long int __a2 asm ("a2") = (long int) (arg2); \ + register long int __a3 asm ("a3") = (long int) (arg3); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0") = (long int) (arg0); \ + register long int __a1 asm ("a1") = (long int) (arg1); \ + register long int __a2 asm ("a2") = (long int) (arg2); \ + register long int __a3 asm ("a3") = (long int) (arg3); \ + register long int __a4 asm ("a4") = (long int) (arg4); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r" (__a4) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0") = (long int) (arg0); \ + register long int __a1 asm ("a1") = (long int) (arg1); \ + register long int __a2 asm ("a2") = (long int) (arg2); \ + register long int __a3 asm ("a3") = (long int) (arg3); \ + register long int __a4 asm ("a4") = (long int) (arg4); \ + register long int __a5 asm ("a5") = (long int) (arg5); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3), \ + "r" (__a4), "r" (__a5) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + long int _sys_result; \ + \ + { \ + register long int __a7 asm ("a7") = number; \ + register long int __a0 asm ("a0") = (long int) (arg0); \ + register long int __a1 asm ("a1") = (long int) (arg1); \ + register long int __a2 asm ("a2") = (long int) (arg2); \ + register long int __a3 asm ("a3") = (long int) (arg3); \ + register long int __a4 asm ("a4") = (long int) (arg4); \ + register long int __a5 asm ("a5") = (long int) (arg5); \ + register long int __a6 asm ("a6") = (long int) (arg6); \ + __asm__ volatile ( \ + "scall\n\t" \ + : "+r" (__a0) \ + : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3), \ + "r" (__a4), "r" (__a5), "r" (__a6) \ + : __SYSCALL_CLOBBERS); \ + _sys_result = __a0; \ + } \ + _sys_result; \ +}) + +# define __SYSCALL_CLOBBERS "memory" + +extern long int __syscall_error (long int neg_errno); + +#endif /* ! __ASSEMBLER__ */ + +/* Pointer mangling is not supported. */ +#define PTR_MANGLE(var) (void) (var) +#define PTR_DEMANGLE(var) (void) (var) + +#endif /* linux/riscv/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S new file mode 100644 index 000000000000..6c53e93a928d --- /dev/null +++ b/sysdeps/unix/sysv/linux/riscv/vfork.S @@ -0,0 +1,44 @@ +/* vfork for Linux, RISC-V version. + Copyright (C) 2005-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 + . */ + +/* vfork() is just a special case of clone(). */ + +#include +#include +#define __ASSEMBLY__ +#include +#include + + .text +LEAF (__libc_vfork) + + li a0, (CLONE_VFORK | CLONE_VM | SIGCHLD) + mv a1, sp + + li a7, __NR_clone + scall + + bltz a0, 1f + ret + +1: j __syscall_error +END (__libc_vfork) + +weak_alias (__libc_vfork, vfork) +strong_alias (__libc_vfork, __vfork) +libc_hidden_def (__vfork)