diff options
author | Tobias Anderberg <tobias.anderberg@axis.com> | 2002-09-20 15:17:16 +0000 |
---|---|---|
committer | Tobias Anderberg <tobias.anderberg@axis.com> | 2002-09-20 15:17:16 +0000 |
commit | cb9136d9843e3756ebc79f91a3a522ed4ca73eda (patch) | |
tree | 32c4645d05a7b4d7ec5b56abeb6f837c574e3af8 /libc/sysdeps/linux/cris | |
parent | 750c0194b0b645120ddccf25b82848b06be6cdc2 (diff) |
* Added clone() system call.
* Proper implementation of bits/syscalls.h, no cheating by just including
<asm/unistd.h>.
* Proper implementation of syscall.S, it no longer contains the
__syscall_error, instead it contains code which makes syscall(nr,...) a
system call.
* Added sysdep.S which contains the code for __syscall_error.
* Added some macros to sysdep.h.
* Added sys/procfs.h, which is needed when compiling with thread support.
* Removed unused syscall-cris.c.
Diffstat (limited to 'libc/sysdeps/linux/cris')
-rw-r--r-- | libc/sysdeps/linux/cris/Makefile | 3 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/bits/syscalls.h | 165 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/clone.S | 89 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/sys/procfs.h | 115 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/syscall-cris.c | 41 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/syscall.S | 52 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/sysdep.S | 77 | ||||
-rw-r--r-- | libc/sysdeps/linux/cris/sysdep.h | 16 |
8 files changed, 493 insertions, 65 deletions
diff --git a/libc/sysdeps/linux/cris/Makefile b/libc/sysdeps/linux/cris/Makefile index 398139be5..0955be53c 100644 --- a/libc/sysdeps/linux/cris/Makefile +++ b/libc/sysdeps/linux/cris/Makefile @@ -19,7 +19,7 @@ ASFLAGS=$(CFLAGS) CRT0=crt0.c CRT0_OBJ=$(patsubst %.c,%.o, $(CRT0)) -SSRC= setjmp.S __longjmp.S +SSRC= setjmp.S __longjmp.S clone.S sysdep.S syscall.S ifeq ($(UNIFIED_SYSCALL),true) SSRC += __uClibc_syscall.S endif @@ -53,6 +53,7 @@ $(COBJS): %.o : %.c headers: @(TOPDIR=$(TOPDIR) CC=$(CC) /bin/sh $(TOPDIR)/extra/scripts/gen_bits_syscall_h.sh > bits/syscall.h ) +# cd $(TOPDIR)/include/sys && ln -fs ../../libc/sysdeps/linux/m68k/reg.h . clean: rm -f *.[oa] *~ core diff --git a/libc/sysdeps/linux/cris/bits/syscalls.h b/libc/sysdeps/linux/cris/bits/syscalls.h index 5c30e2193..4e9d53e84 100644 --- a/libc/sysdeps/linux/cris/bits/syscalls.h +++ b/libc/sysdeps/linux/cris/bits/syscalls.h @@ -1,10 +1,159 @@ -/* - * nothing needed here until we want pthread support or similar - */ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H -#include <features.h> -/* Do something very evil for now. Until we include our out syscall - * macros, short circuit bits/syscall.h and use asm/unistd.h instead */ -#define _BITS_SYSCALL_H -#include <asm/unistd.h> +#ifndef _SYSCALL_H +#error "Never use <bits/syscall.h> directly; include <sys/syscall.h> instead." +#endif +/* Include the __NR_<name> definitions. */ +#include <bits/syscall.h> + +#if 0 +#ifndef __set_errno +#define __set_errno(val) (*__errno_location()) = (val) +#endif +#endif + +#undef SYS_ify +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#ifndef __ASSEMBLER__ + +#undef _syscall0 +#define _syscall0(type,name) \ +type name(void) \ +{ \ +return (type) (INLINE_SYSCALL(name, 0)); \ +} + +#undef _syscall1 +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +return (type) (INLINE_SYSCALL(name, 1, arg1)); \ +} + +#undef _syscall2 +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +return (type) (INLINE_SYSCALL(name, 2, arg1, arg2)); \ +} + +#undef _syscall3 +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +return (type) (INLINE_SYSCALL(name, 3, arg1, arg2, arg3)); \ +} + +#undef _syscall4 +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +return (type) (INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4)); \ +} + +#undef _syscall5 +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +return (type) (INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5)); \ +} + +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ \ + unsigned long __sys_res; \ + register unsigned long __res asm ("r10"); \ + LOAD_ARGS_c_##nr (args) \ + register unsigned long __callno asm ("r9") \ + = SYS_ify (name); \ + asm volatile (LOAD_ARGS_asm_##nr (args) \ + CHECK_ARGS_asm_##nr \ + "break 13" \ + : "=r" (__res) \ + : ASM_ARGS_##nr (args) \ + : ASM_CLOBBER_##nr); \ + __sys_res = __res; \ + \ + if (__sys_res >= (unsigned long) -4096) \ + { \ + __set_errno (- __sys_res); \ + __sys_res = (unsigned long) -1; \ + } \ + __sys_res; \ + }) + +#define LOAD_ARGS_c_0() +#define LOAD_ARGS_asm_0() +#define ASM_CLOBBER_0 "memory" +#define ASM_ARGS_0() "r" (__callno) +#define CHECK_ARGS_asm_0 + +#define LOAD_ARGS_c_1(r10) \ + LOAD_ARGS_c_0() \ + register unsigned long __r10 __asm__ ("r10") = (unsigned long) (r10); +#define LOAD_ARGS_asm_1(r10) LOAD_ARGS_asm_0 () +#define ASM_CLOBBER_1 ASM_CLOBBER_0 +#define ASM_ARGS_1(r10) ASM_ARGS_0 (), "0" (__r10) +#define CHECK_ARGS_asm_1 \ + ".ifnc %0,$r10\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_2(r10, r11) \ + LOAD_ARGS_c_1(r10) \ + register unsigned long __r11 __asm__ ("r11") = (unsigned long) (r11); +#define LOAD_ARGS_asm_2(r10, r11) LOAD_ARGS_asm_1 (r10) +#define ASM_CLOBBER_2 ASM_CLOBBER_1 +#define ASM_ARGS_2(r10, r11) ASM_ARGS_1 (r10), "r" (__r11) +#define CHECK_ARGS_asm_2 \ + ".ifnc %0-%3,$r10-$r11\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_3(r10, r11, r12) \ + LOAD_ARGS_c_2(r10, r11) \ + register unsigned long __r12 __asm__ ("r12") = (unsigned long) (r12); +#define LOAD_ARGS_asm_3(r10, r11, r12) LOAD_ARGS_asm_2 (r10, r11) +#define ASM_CLOBBER_3 ASM_CLOBBER_2 +#define ASM_ARGS_3(r10, r11, r12) ASM_ARGS_2 (r10, r11), "r" (__r12) +#define CHECK_ARGS_asm_3 \ + ".ifnc %0-%3-%4,$r10-$r11-$r12\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_4(r10, r11, r12, r13) \ + LOAD_ARGS_c_3(r10, r11, r12) \ + register unsigned long __r13 __asm__ ("r13") = (unsigned long) (r13); +#define LOAD_ARGS_asm_4(r10, r11, r12, r13) LOAD_ARGS_asm_3 (r10, r11, r12) +#define ASM_CLOBBER_4 ASM_CLOBBER_3 +#define ASM_ARGS_4(r10, r11, r12, r13) ASM_ARGS_3 (r10, r11, r12), "r" (__r13) +#define CHECK_ARGS_asm_4 \ + ".ifnc %0-%3-%4-%5,$r10-$r11-$r12-$r13\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_5(r10, r11, r12, r13, mof) \ + LOAD_ARGS_c_4(r10, r11, r12, r13) +#define LOAD_ARGS_asm_5(r10, r11, r12, r13, mof) \ + LOAD_ARGS_asm_4 (r10, r11, r12, r13) "move %6,$mof\n\t" +#define ASM_CLOBBER_5 ASM_CLOBBER_4 +#define ASM_ARGS_5(r10, r11, r12, r13, mof) \ + ASM_ARGS_4 (r10, r11, r12, r13), "g" (mof) +#define CHECK_ARGS_asm_5 CHECK_ARGS_asm_4 + +#define LOAD_ARGS_c_6(r10, r11, r12, r13, mof, srp) \ + LOAD_ARGS_c_5(r10, r11, r12, r13, mof) +#define LOAD_ARGS_asm_6(r10, r11, r12, r13, mof, srp) \ + LOAD_ARGS_asm_5(r10, r11, r12, r13, mof) \ + "move %7,$srp\n\t" +#define ASM_CLOBBER_6 ASM_CLOBBER_5, "srp" +#define ASM_ARGS_6(r10, r11, r12, r13, mof, srp) \ + ASM_ARGS_5 (r10, r11, r12, r13, mof), "g" (srp) +#define CHECK_ARGS_asm_6 CHECK_ARGS_asm_5 + +#endif /* not __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/libc/sysdeps/linux/cris/clone.S b/libc/sysdeps/linux/cris/clone.S new file mode 100644 index 000000000..56ea05c72 --- /dev/null +++ b/libc/sysdeps/linux/cris/clone.S @@ -0,0 +1,89 @@ +/* Copyright (C) 2001 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <asm/errno.h> +#include <sys/syscall.h> +#include <sysdep.h> + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .syntax no_register_prefix + + .text +ENTRY (__clone) + /* Sanity check arguments: No NULL function pointers. Allow a NULL + stack pointer though; it makes the kernel allocate stack. */ + test.d r10 + beq 1f + nop + + /* We need to muck with a few registers. */ + movem r1,[sp=sp-8] + + /* Save the function pointer and argument. We can't save them + onto the new stack since it can be NULL. */ + move.d r10,r0 + move.d r13,r1 + + /* Move the other arguments into place for the system call. */ + move.d r11,r10 + move.d r12,r11 + + /* Do the system call. */ + movu.w SYS_ify (clone),r9 + break 13 + test.d r10 + beq .Lthread_start + nop + + /* Jump to error handler if we get (unsigned) -4096 .. 0xffffffff. */ + cmps.w -4096,r10 + bhs 0f + movem [sp+],r1 + + /* In parent, successful return. (Avoid using "ret" - it's a macro.) */ + Ret + nop + +.Lthread_start: + /* Terminate frame pointers here. */ + moveq 0,r8 + + /* I've told you once. */ + move.d r1,r10 + jsr r0 + + SETUP_PIC + PLTCALL (_exit) + + /* Die horribly. */ + test.d [6809] + + /* Stop the unstoppable. */ +9: + ba 9b + nop + +/* Local error handler. */ +1: + movs.w -EINVAL,r10 + /* Drop through into the ordinary error handler. */ +PSEUDO_END (__clone) + +.globl clone + clone = __clone diff --git a/libc/sysdeps/linux/cris/sys/procfs.h b/libc/sysdeps/linux/cris/sys/procfs.h new file mode 100644 index 000000000..072029bc8 --- /dev/null +++ b/libc/sysdeps/linux/cris/sys/procfs.h @@ -0,0 +1,115 @@ +/* Copyright (C) 1996, 1997, 1999 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#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 <signal.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/ucontext.h> +#include <sys/user.h> +#include <asm/elf.h> + +__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 + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + 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. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __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. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + 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. */ + unsigned short int pr_uid; + unsigned short 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. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef gregset_t prgregset_t; +typedef 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; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/libc/sysdeps/linux/cris/syscall-cris.c b/libc/sysdeps/linux/cris/syscall-cris.c deleted file mode 100644 index fa923ec9d..000000000 --- a/libc/sysdeps/linux/cris/syscall-cris.c +++ /dev/null @@ -1,41 +0,0 @@ -/* syscall.c - generalized linux system call interface */ - -#include <stdarg.h> -#include <syscall.h> -#include <errno.h> - -/* perform a Linux/CRIS system call with variable number of arguments - * put them and the syscall number in the right registers and call - * break 13. - */ - -int -syscall(int number, ...) -{ - register long __a __asm__ ("r10"); - register long __b __asm__ ("r11"); - register long __c __asm__ ("r12"); - register long __d __asm__ ("r13"); - register long __e __asm__ ("r0"); - va_list args; - - va_start(args, number); - __a = va_arg(args, int); - __b = va_arg(args, int); - __c = va_arg(args, int); - __d = va_arg(args, int); - __e = va_arg(args, int); - va_end(args); - - __asm__ volatile ("movu.w %1,$r9\n\tbreak 13\n\t" - : "=r" (__a) - : "g" (number), "0" (__a), "r" (__b), "r" (__c), "r" (__d), - "r" (__e) - : "r10", "r9"); - - if (__a >= 0) - return __a; - - errno = -__a; - return -1; -} diff --git a/libc/sysdeps/linux/cris/syscall.S b/libc/sysdeps/linux/cris/syscall.S index d52a6ba05..eb5cdcccf 100644 --- a/libc/sysdeps/linux/cris/syscall.S +++ b/libc/sysdeps/linux/cris/syscall.S @@ -1,18 +1,40 @@ -#include <sys/syscall.h> - - .globl __syscall_error -__syscall_error: - - neg.d $r10,$r10 +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. - push $r10 - push $srp - jsr __errno_location - pop $srp - pop $r11 - move.d $r11,[$r10] + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. - moveq -1, $r10 - ret - nop + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <sysdep.h> + + .syntax no_register_prefix + +/* Make syscall (callno, ...) into a system call. */ + +ENTRY (syscall) + move.d r10,r9 + move.d r11,r10 + move.d r12,r11 + move.d r13,r12 + move.d [sp],r13 + move srp,[sp] + move [sp+4],mof + move [sp+8],srp + break 13 + cmps.w -4096,r10 + bhs 0f + move [sp],srp + Ret + nop +PSEUDO_END (syscall) diff --git a/libc/sysdeps/linux/cris/sysdep.S b/libc/sysdeps/linux/cris/sysdep.S new file mode 100644 index 000000000..f027119dc --- /dev/null +++ b/libc/sysdeps/linux/cris/sysdep.S @@ -0,0 +1,77 @@ +/* Copyright (C) 2001 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <sysdep.h> + +/* Make space for the errno variable. */ + + .globl C_SYMBOL_NAME(errno) + .type C_SYMBOL_NAME(errno),@object + .lcomm C_SYMBOL_NAME(errno),4 + + errno = _errno + + /* weak_alias (errno, _errno) */ + + +/* The syscall stubs jump here when they detect an error, bot for PIC and + non-PIC. */ + + .syntax no_register_prefix + +ENTRY (__syscall_error) + neg.d r10,r10 + +#ifdef _LIBC_REENTRANT + push r10 + push srp + + /* Note that __syscall_error is only visible within this library, + and no-one passes it on as a pointer, so can assume that R0 (GOT + pointer) is correctly set up. */ + PLTCALL (__errno_location) + + pop srp + pop r11 + move.d r11,[r10] + +#else /* not _LIBC_REENTRANT */ +# ifdef __PIC__ + move.d [r0+C_SYMBOL_NAME(errno:GOT)],r9 + move.d r10,[r9] +# else + move.d r10,[C_SYMBOL_NAME(errno)] +# endif +#endif /* _LIBC_REENTRANT */ + +#ifdef __PIC__ +/* PIC callers are supposed to have R0 on stack, ready for us to restore. + Callers are only allowed from within this DSO, so the GOT in r0 is the + one we want to use. + + (Don't use "ret" - it's a macro). */ + + moveq -1,r10 + Ret + pop r0 +#else + Ret + moveq -1,r10 +#endif + +END (__syscall_error) diff --git a/libc/sysdeps/linux/cris/sysdep.h b/libc/sysdeps/linux/cris/sysdep.h index e01752ae9..2068557c5 100644 --- a/libc/sysdeps/linux/cris/sysdep.h +++ b/libc/sysdeps/linux/cris/sysdep.h @@ -91,6 +91,22 @@ #define END(name) \ ASM_SIZE_DIRECTIVE (C_SYMBOL_NAME (name)) +#define PSEUDO(name, syscall_name, args) \ + ENTRY (name) @ \ + DOARGS_##args @ \ + movu.w SYS_ify (syscall_name),$r9 @ \ + break 13 @ \ + cmps.w -4096,$r10 @ \ + bhs 0f @ \ + nop @ \ + UNDOARGS_return_##args + +#define PSEUDO_END(name) \ +0: @ \ + SETUP_PIC @ \ + PLTJUMP (syscall_error) @ \ + END (name) + /* If compiled for profiling, call `mcount' at the start of each function. FIXME: Note that profiling is not actually implemented. This is just example code which might not even compile, though it is believed to be |