Signed-off-by: Vineet Gupta <vgupta@xxxxxxxxxxxx> --- ChangeLog | 12 ++ sysdeps/unix/sysv/linux/arc/cacheflush.c | 29 +++ sysdeps/unix/sysv/linux/arc/clone.S | 100 ++++++++++ sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h | 6 + sysdeps/unix/sysv/linux/arc/kernel-features.h | 28 +++ sysdeps/unix/sysv/linux/arc/mmap_internal.h | 26 +++ sysdeps/unix/sysv/linux/arc/profil-counter.h | 2 + sysdeps/unix/sysv/linux/arc/pt-vfork.S | 1 + sysdeps/unix/sysv/linux/arc/sigaction.c | 69 +++++++ sysdeps/unix/sysv/linux/arc/syscall.S | 38 ++++ sysdeps/unix/sysv/linux/arc/sysdep.c | 33 ++++ sysdeps/unix/sysv/linux/arc/sysdep.h | 259 ++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/arc/vfork.S | 42 +++++ 13 files changed, 645 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/arc/cacheflush.c create mode 100644 sysdeps/unix/sysv/linux/arc/clone.S create mode 100644 sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h create mode 100644 sysdeps/unix/sysv/linux/arc/kernel-features.h create mode 100644 sysdeps/unix/sysv/linux/arc/mmap_internal.h create mode 100644 sysdeps/unix/sysv/linux/arc/profil-counter.h create mode 100644 sysdeps/unix/sysv/linux/arc/pt-vfork.S create mode 100644 sysdeps/unix/sysv/linux/arc/sigaction.c create mode 100644 sysdeps/unix/sysv/linux/arc/syscall.S create mode 100644 sysdeps/unix/sysv/linux/arc/sysdep.c create mode 100644 sysdeps/unix/sysv/linux/arc/sysdep.h create mode 100644 sysdeps/unix/sysv/linux/arc/vfork.S diff --git a/ChangeLog b/ChangeLog index b946f57204b6..08a3ac7e8064 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,6 +44,18 @@ * sysdeps/arc/nofpu/math-tests-exception.h: New file. * sysdeps/arc/nofpu/math-tests-rounding.h: New file. * sysdeps/arc/sfp-machine.h: New file. + * sysdeps/unix/sysv/linux/arc/cacheflush.c: New file. + * sysdeps/unix/sysv/linux/arc/clone.S: New file. + * sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h: New file. + * sysdeps/unix/sysv/linux/arc/kernel-features.h: New file. + * sysdeps/unix/sysv/linux/arc/mmap_internal.h: New file. + * sysdeps/unix/sysv/linux/arc/profil-counter.h: New file. + * sysdeps/unix/sysv/linux/arc/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/arc/sigaction.c: New file. + * sysdeps/unix/sysv/linux/arc/syscall.S: New file. + * sysdeps/unix/sysv/linux/arc/sysdep.c: New file. + * sysdeps/unix/sysv/linux/arc/sysdep.h: New file. + * sysdeps/unix/sysv/linux/arc/vfork.S: New file. 2018-12-17 Joseph Myers <joseph@xxxxxxxxxxxxxxxx> diff --git a/sysdeps/unix/sysv/linux/arc/cacheflush.c b/sysdeps/unix/sysv/linux/arc/cacheflush.c new file mode 100644 index 000000000000..7b14211eccf7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/cacheflush.c @@ -0,0 +1,29 @@ +/* cacheflush system call for ARC Linux. + 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 <sysdep.h> +#include <stddef.h> +#include <unistd.h> + +/* Flush cache(s). */ +int +_flush_cache (char *addr, const int nbytes, const int op) +{ + return INLINE_SYSCALL (cacheflush, 3, addr, nbytes, op); +} +weak_alias (_flush_cache, cacheflush) diff --git a/sysdeps/unix/sysv/linux/arc/clone.S b/sysdeps/unix/sysv/linux/arc/clone.S new file mode 100644 index 000000000000..04f2df5ef06d --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/clone.S @@ -0,0 +1,100 @@ +/* clone() implementation for ARC. + Copyright (C) 2008-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andrew Jenner <andrew@xxxxxxxxxxxxxxxx>, 2008. + + 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> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +#define CLONE_SETTLS 0x00080000 + +; int clone(int (*fn)(void *), void *child_stack, +; int flags, void *arg, ... +; /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */); +; +; NOTE: I'm assuming that the last 3 args are NOT var-args and in case all +; 3 are not relevant, caller will nevertheless pass those as NULL. +; Current (Jul 2012) upstream powerpc/clone.S assumes similarly. +; Our LTP (from 2007) doesn't seem to have tests to prove otherwise + +; clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS) +; +; int sys_clone(unsigned long clone_flags, +; unsigned long newsp, +; int __user *parent_tidptr, +; void *tls, +; int __user *child_tidptr) + +ENTRY(__clone) + cmp r0, 0 ; @fn can't be NULL + cmp.ne r1, 0 ; @child_stack can't be NULL + bz .L__sys_err + + ; save some of the orig args + ; r0 containg @fn will be clobbered AFTER syscall (with ret val) + ; rest are clobbered BEFORE syscall due to different arg ordering + mov r10, r0 ; @fn + mov r11, r3 ; @args + mov r12, r2 ; @clone_flags + mov r9, r5 ; @tls + + ; adjust libc args for syscall + + mov r0, r2 ; libc @flags is 1st syscall arg + mov r2, r4 ; libc @ptid + mov r3, r5 ; libc @tls + mov r4, r6 ; libc @ctid + mov r8, __NR_clone + ARC_TRAP_INSN + + cmp r0, 0 ; return code : 0 new process, !0 parent + blt .L__sys_err2 ; < 0 (signed) error + jnz [blink] ; Parent returns + + ; ----- child starts here --------- + + ; Setup TP register (only recent kernels v4.19+ do that) + and.f 0, r12, CLONE_SETTLS + mov.nz r25, r9 + + ; child jumps off to @fn with @arg as argument, and returns here + jl.d [r10] + mov r0, r11 + + ; exit() with result from @fn (already in r0) + mov r8, __NR_exit + ARC_TRAP_INSN + ; In case it ever came back + flag 1 + +.L__sys_err: + mov r0, -EINVAL +.L__sys_err2: + ; (1) No need to make -ve kernel error code as positive errno + ; __syscall_error expects the -ve error code returned by kernel + ; (2) r0 still had orig -ve kernel error code + ; (3) Tail call to __syscall_error so we dont have to come back + ; here hence instead of jmp-n-link (reg push/pop) we do jmp + ; (4) No need to route __syscall_error via PLT, B is inherently + ; position independent + b __syscall_error +PSEUDO_END (__clone) +libc_hidden_def (__clone) +weak_alias (__clone, clone) diff --git a/sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h b/sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h new file mode 100644 index 000000000000..2fec69d21657 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/jmp_buf-macros.h @@ -0,0 +1,6 @@ +#define JMP_BUF_SIZE (32 + 1 + 1024/32) * 4 +#define SIGJMP_BUF_SIZE (32 + 1 + 1024/32) * 4 +#define JMP_BUF_ALIGN 4 +#define SIGJMP_BUF_ALIGN 4 +#define MASK_WAS_SAVED_OFFSET 32 * 4 +#define SAVED_MASK_OFFSET 33 * 4 diff --git a/sysdeps/unix/sysv/linux/arc/kernel-features.h b/sysdeps/unix/sysv/linux/arc/kernel-features.h new file mode 100644 index 000000000000..d8f667ca4759 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/kernel-features.h @@ -0,0 +1,28 @@ +/* Set flags signalling availability of kernel features based on given + kernel version number. + + 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/>. */ + +/* The minimum supported kernel version for ARC is 3.9, + guaranteeing many kernel features. */ + +#include_next <kernel-features.h> + +#undef __ASSUME_CLONE_DEFAULT +#define __ASSUME_CLONE_BACKWARDS 1 diff --git a/sysdeps/unix/sysv/linux/arc/mmap_internal.h b/sysdeps/unix/sysv/linux/arc/mmap_internal.h new file mode 100644 index 000000000000..3c8c55d57d0e --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/mmap_internal.h @@ -0,0 +1,26 @@ +/* mmap - map files or devices into memory. Linux/ARC version. + 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 MMAP_ARC_INTERNAL_H +#define MMAP_ARC_INTERNAL_H + +#define MMAP2_PAGE_UNIT 8192ULL /* 8K page is default for ARC */ + +#include_next <mmap_internal.h> + +#endif diff --git a/sysdeps/unix/sysv/linux/arc/profil-counter.h b/sysdeps/unix/sysv/linux/arc/profil-counter.h new file mode 100644 index 000000000000..8a6a0bcf3d59 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/profil-counter.h @@ -0,0 +1,2 @@ +/* We can use the ix86 version. */ +#include <sysdeps/unix/sysv/linux/i386/profil-counter.h> diff --git a/sysdeps/unix/sysv/linux/arc/pt-vfork.S b/sysdeps/unix/sysv/linux/arc/pt-vfork.S new file mode 100644 index 000000000000..65cc3823ac87 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/pt-vfork.S @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/alpha/pt-vfork.S> diff --git a/sysdeps/unix/sysv/linux/arc/sigaction.c b/sysdeps/unix/sysv/linux/arc/sigaction.c new file mode 100644 index 000000000000..0a58e78f8834 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/sigaction.c @@ -0,0 +1,69 @@ +/* ARC specific sigaction and signal restorer + 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/>. */ + +#include <sysdep.h> +#include <errno.h> +#include <signal.h> +#include <string.h> +#include <sys/syscall.h> + +/* + * Default sigretrun stub if user doesn't specify SA_RESTORER + */ +static void __default_rt_sa_restorer(void) +{ + INTERNAL_SYSCALL_NCS(__NR_rt_sigreturn, , 0); +} + +#define SA_RESTORER 0x04000000 + +/* If @act is not NULL, change the action for @sig to @act. + If @oact is not NULL, put the old action for @sig in @oact. */ +int +__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + struct sigaction kact; + const struct sigaction *arg; + + /* + * SA_RESTORER is only relevant for act != NULL case + * (!act means caller only wants to know @oact) + */ + if (act && !(act->sa_flags & SA_RESTORER)) { + kact.sa_restorer = __default_rt_sa_restorer; + kact.sa_flags = act->sa_flags | SA_RESTORER; + + kact.sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask; + + arg = &kact; + } else { + arg = act; + } + + /* + * syscall also expects sizeof(sa_mask) and asm-generic kernel syscall + * ABI mandates it be 2 words (8 bytes below) although glibc defines + * sigset_to be much larger (1024 / 32 == 64 bytes) + */ + return INLINE_SYSCALL(rt_sigaction, 4, sig, arg, oact, _NSIG / 8); +} + +libc_hidden_def (__libc_sigaction) + +#include <nptl/sigaction.c> diff --git a/sysdeps/unix/sysv/linux/arc/syscall.S b/sysdeps/unix/sysv/linux/arc/syscall.S new file mode 100644 index 000000000000..8f76fa43e95f --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/syscall.S @@ -0,0 +1,38 @@ +/* syscall - indirect system call. + 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 <sysdep.h> + +ENTRY (syscall) + mov_s r8, r0 + mov_s r0, r1 + mov_s r1, r2 + mov_s r2, r3 + mov_s r3, r4 +#ifdef __ARC700__ + mov r4, r5 + mov r5, r6 +#else + mov_s r4, r5 + mov_s r5, r6 +#endif + + ARC_TRAP_INSN + brhi r0, -1024, .Lcall_syscall_err + j [blink] +PSEUDO_END (syscall) diff --git a/sysdeps/unix/sysv/linux/arc/sysdep.c b/sysdeps/unix/sysv/linux/arc/sysdep.c new file mode 100644 index 000000000000..d9bcc305b846 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/sysdep.c @@ -0,0 +1,33 @@ +/* ARC wrapper for setting errno + 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/>. */ + +#include <sysdep.h> +#include <errno.h> + +/* All syscall handler come here to avoid generated code bloat due to + * GOT reference to errno_location or it's equivalent + */ +int __syscall_error(int err_no) +{ + __set_errno(-err_no); + return -1; +} + +#if IS_IN (libc) +hidden_def (__syscall_error) +#endif diff --git a/sysdeps/unix/sysv/linux/arc/sysdep.h b/sysdeps/unix/sysv/linux/arc/sysdep.h new file mode 100644 index 000000000000..39d1f03c3710 --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/sysdep.h @@ -0,0 +1,259 @@ +/* Assembler macros for ARC. + 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/>. */ + +#ifndef _LINUX_ARC_SYSDEP_H +#define _LINUX_ARC_SYSDEP_H 1 + +#include <asm/unistd.h> +#include <sysdeps/arc/sysdep.h> +#include <sysdeps/unix/sysv/linux/generic/sysdep.h> + +/* For RTLD_PRIVATE_ERRNO. */ +#include <dl-sysdep.h> + +#include <tls.h> + +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +#ifdef __ASSEMBLER__ + +/* This is a "normal" system call stub: if there is an error, + it returns -1 and sets errno. */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + PSEUDO_NOERRNO(name, syscall_name, args) ASM_LINE_SEP \ + brhi r0, -1024, .Lcall_syscall_err ASM_LINE_SEP + +#define ret j [blink] + +# undef PSEUDO_END +# define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER ASM_LINE_SEP \ + END (name) + +/* --------- helper for SYSCALL_NOERRNO ----------- */ + +/* This kind of system call stub never returns an error. + We return the return value register to the caller unexamined. */ + +# undef PSEUDO_NOERRNO +# define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text ASM_LINE_SEP \ + ENTRY (name) ASM_LINE_SEP \ + DO_CALL (syscall_name, args) ASM_LINE_SEP \ + +/* return the return value register unexamined + * r0 is both syscall return reg and function return reg, so no need to do + * anything + */ +# define ret_NOERRNO \ + j_s [blink] ASM_LINE_SEP + +# undef PSEUDO_END_NOERRNO +# define PSEUDO_END_NOERRNO(name) \ + END (name) + +/* --------- helper for SYSCALL_ERRVAL ----------- */ + +/* This kind of system call stub returns the errno code as its return + value, or zero for success. We may massage the kernel's return value + to meet that ABI, but we never set errno here. */ + +# undef PSEUDO_ERRVAL +# define PSEUDO_ERRVAL(name, syscall_name, args) \ + PSEUDO_NOERRNO(name, syscall_name, args) ASM_LINE_SEP + +/* don't set errno, return kernel error (in errno form) or zero */ +# define ret_ERRVAL \ + rsub r0, r0, 0 ASM_LINE_SEP \ + ret_NOERRNO + +# undef PSEUDO_END_ERRVAL +# define PSEUDO_END_ERRVAL(name) \ + END (name) + + +/* To reduce the code footprint, we confine the actual errno access + * to single place in __syscall_error() + * this takes raw kernel error value, sets errno and returns -1 + */ +#if IS_IN (libc) +#define CALL_ERRNO_SETTER_C bl PLTJMP(HIDDEN_JUMPTARGET(__syscall_error)) +#else +#define CALL_ERRNO_SETTER_C bl PLTJMP(__syscall_error) +#endif + +# define SYSCALL_ERROR_HANDLER \ +.Lcall_syscall_err: ASM_LINE_SEP \ + st.a blink, [sp, -4] ASM_LINE_SEP \ + cfi_adjust_cfa_offset (4) ASM_LINE_SEP \ + cfi_rel_offset (blink, 0) ASM_LINE_SEP \ + CALL_ERRNO_SETTER_C ASM_LINE_SEP \ + ld.ab blink, [sp, 4] ASM_LINE_SEP \ + cfi_adjust_cfa_offset (-4) ASM_LINE_SEP \ + cfi_restore (blink) ASM_LINE_SEP \ + j [blink] + +# define DO_CALL(syscall_name, args) \ + mov r8, SYS_ify (syscall_name) ASM_LINE_SEP \ + ARC_TRAP_INSN ASM_LINE_SEP + +#define ARC_TRAP_INSN trap_s 0 + +#else /* !__ASSEMBLER__ */ + +# define SINGLE_THREAD_BY_GLOBAL 1 + +/* In order to get __set_errno() definition in INLINE_SYSCALL. */ +#include <errno.h> + +extern int __syscall_error (int); + +#if IS_IN (libc) +hidden_proto (__syscall_error) +#define CALL_ERRNO_SETTER "bl __syscall_error \n\t" +#else +#define CALL_ERRNO_SETTER "bl __syscall_error@plt \n\t" +#endif + + +/* Define a macro which expands into the inline wrapper code for a system + call. */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr_args, args...) \ +({ \ + register int __res __asm__("r0"); \ + __res = INTERNAL_SYSCALL_NCS(__NR_##name, , nr_args, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P ((__res), ), 0)) \ + { \ + asm volatile ("st.a blink, [sp, -4] \n\t" \ + CALL_ERRNO_SETTER \ + "ld.ab blink, [sp, 4] \n\t" \ + :"+r" (__res) \ + : \ + :"r1","r2","r3","r4","r5","r6", \ + "r7","r8","r9","r10","r11","r12"); \ + } \ + __res; \ +}) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#undef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +/* -1 to -1023 are valid errno values */ +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) > -1024U) + +#define ARC_TRAP_INSN "trap_s 0 \n\t" + +#undef INTERNAL_SYSCALL_RAW +#define INTERNAL_SYSCALL_RAW(name, err, nr_args, args...) \ +({ \ + /* Per ABI, r0 is 1st arg and return reg */ \ + register int __ret __asm__("r0"); \ + register int _sys_num __asm__("r8"); \ + \ + LOAD_ARGS_##nr_args (name, args) \ + \ + __asm__ volatile ( \ + ARC_TRAP_INSN \ + : "+r" (__ret) \ + : "r"(_sys_num) ASM_ARGS_##nr_args \ + : "memory"); \ + \ + __ret; \ +}) + +/* Macros for setting up inline __asm__ input regs */ +#define ASM_ARGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "r" (__ret) +#define ASM_ARGS_2 ASM_ARGS_1, "r" (_arg2) +#define ASM_ARGS_3 ASM_ARGS_2, "r" (_arg3) +#define ASM_ARGS_4 ASM_ARGS_3, "r" (_arg4) +#define ASM_ARGS_5 ASM_ARGS_4, "r" (_arg5) +#define ASM_ARGS_6 ASM_ARGS_5, "r" (_arg6) +#define ASM_ARGS_7 ASM_ARGS_6, "r" (_arg7) + +/* Macros for converting sys-call wrapper args into sys call args */ +#define LOAD_ARGS_0(nm, arg) \ + _sys_num = (int) (nm); + +#define LOAD_ARGS_1(nm, arg1) \ + __ret = (int) (arg1); \ + LOAD_ARGS_0 (nm, arg1) + +/* + * Note that the use of _tmpX might look superflous, however it is needed + * to ensure that register variables are not clobbered if arg happens to be + * a function call itself. e.g. sched_setaffinity() calling getpid() for arg2 + * + * Also this specific order of recursive calling is important to segregate + * the tmp args evaluation (function call case described above) and assigment + * of register variables + */ +#define LOAD_ARGS_2(nm, arg1, arg2) \ + int _tmp2 = (int) (arg2); \ + LOAD_ARGS_1 (nm, arg1) \ + register int _arg2 __asm__ ("r1") = _tmp2; + +#define LOAD_ARGS_3(nm, arg1, arg2, arg3) \ + int _tmp3 = (int) (arg3); \ + LOAD_ARGS_2 (nm, arg1, arg2) \ + register int _arg3 __asm__ ("r2") = _tmp3; + +#define LOAD_ARGS_4(nm, arg1, arg2, arg3, arg4) \ + int _tmp4 = (int) (arg4); \ + LOAD_ARGS_3 (nm, arg1, arg2, arg3) \ + register int _arg4 __asm__ ("r3") = _tmp4; + +#define LOAD_ARGS_5(nm, arg1, arg2, arg3, arg4, arg5) \ + int _tmp5 = (int) (arg5); \ + LOAD_ARGS_4 (nm, arg1, arg2, arg3, arg4) \ + register int _arg5 __asm__ ("r4") = _tmp5; + +#define LOAD_ARGS_6(nm, arg1, arg2, arg3, arg4, arg5, arg6) \ + int _tmp6 = (int) (arg6); \ + LOAD_ARGS_5 (nm, arg1, arg2, arg3, arg4, arg5) \ + register int _arg6 __asm__ ("r5") = _tmp6; + +#define LOAD_ARGS_7(nm, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ + int _tmp7 = (int) (arg7); \ + LOAD_ARGS_6 (nm, arg1, arg2, arg3, arg4, arg5, arg6) \ + register int _arg7 __asm__ ("r6") = _tmp7; + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args) + +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(number, err, nr, args) + +/* Pointer mangling not yet supported */ +# define PTR_MANGLE(var) (void) (var) +# define PTR_DEMANGLE(var) (void) (var) + +#endif /* !__ASSEMBLER__ */ + +#endif /* linux/arc/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/arc/vfork.S b/sysdeps/unix/sysv/linux/arc/vfork.S new file mode 100644 index 000000000000..6d7f63c9900b --- /dev/null +++ b/sysdeps/unix/sysv/linux/arc/vfork.S @@ -0,0 +1,42 @@ +/* vfork for ARC Linux. + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sys/syscall.h> +#include <sysdep.h> +#include <tcb-offsets.h> +#define _SIGNAL_H +#include <bits/signum.h> /* For SIGCHLD */ + +#define CLONE_VM 0x00000100 +#define CLONE_VFORK 0x00004000 +#define CLONE_FLAGS_FOR_VFORK (CLONE_VM|CLONE_VFORK|SIGCHLD) + +ENTRY(__vfork) + mov r0, CLONE_FLAGS_FOR_VFORK + mov_s r1, sp + mov r8, __NR_clone + ARC_TRAP_INSN + + cmp r0, 0 + jge [blink] ; child continues + + b __syscall_error +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) -- 2.7.4 _______________________________________________ linux-snps-arc mailing list linux-snps-arc@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/linux-snps-arc