diff options
author | H. Peter Anvin <hpa@zytor.com> | 2002-08-17 07:18:33 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2002-08-17 07:18:33 +0000 |
commit | 156eb2a65dd14820c58b0e35f7cf1a7ecda85a50 (patch) | |
tree | 5e8645362aa601adaca198ca22dd28b3299bf935 | |
parent | e2d728a3d0c60a1aa72dcb785027abd38918ced8 (diff) | |
download | klibc-156eb2a65dd14820c58b0e35f7cf1a7ecda85a50.tar.gz |
SPARC fixes: fork/vfork are special; crt0 needs to reserve more space;klibc-0.47
define NSIG to _NSIG if the former does not exist.
-rw-r--r-- | SYSCALLS | 5 | ||||
-rw-r--r-- | arch/sparc/crt0i.S | 28 | ||||
-rw-r--r-- | arch/sparc/include/klibc/archsys.h | 23 | ||||
-rw-r--r-- | fork.c | 6 | ||||
-rw-r--r-- | include/arch/sparc/klibc/archsys.h | 23 | ||||
-rw-r--r-- | include/signal.h | 3 | ||||
-rw-r--r-- | klibc/SYSCALLS | 5 | ||||
-rw-r--r-- | klibc/arch/sparc/crt0i.S | 28 | ||||
-rw-r--r-- | klibc/arch/sparc/include/klibc/archsys.h | 23 | ||||
-rw-r--r-- | klibc/fork.c | 6 | ||||
-rw-r--r-- | klibc/include/signal.h | 3 | ||||
-rw-r--r-- | klibc/tests/getenvtest.c | 1 | ||||
-rw-r--r-- | tests/getenvtest.c | 1 |
13 files changed, 133 insertions, 22 deletions
diff --git a/SYSCALLS b/SYSCALLS index 613fb92f55105..75b848a0f7b01 100644 --- a/SYSCALLS +++ b/SYSCALLS @@ -5,13 +5,14 @@ # linker can do its job properly. # # The full description of a line is: -# [<[!]arch,...>] type [sysname[@systype]::]funcname(args) +# [<[!]arch,...>] type sysname[@systype][::funcname](args) # # # Process-related syscalls # -<!mips,mips64> pid_t vfork() +<!mips,mips64,sparc> pid_t vfork() +<sparc> pid_t vfork@forkish() <!alpha> pid_t getpid() <alpha> pid_t getxpid@dual0::getpid() int setpgid(pid_t, pid_t) diff --git a/arch/sparc/crt0i.S b/arch/sparc/crt0i.S index a83fefa77dca7..44f9092bc168b 100644 --- a/arch/sparc/crt0i.S +++ b/arch/sparc/crt0i.S @@ -67,19 +67,31 @@ _start: ! or without an imposed bias. andcc %sp, 1, %g5 - bnz,a .LHaveBias + bz,a .LNoBias + nop mov 2047, %g5 -.LHaveBias: +.LNoBias: add %sp, %g5, %g5 +! On entry, the kernel leaves room for one register frame, but +! the C API wants more free space. Thus, we need to drop the stack +! pointer additionally. + +#if TARGET_PTR_SIZE == 32 + sub %sp, 32, %sp ! make room for incoming arguments +#else /* TARGET_PTR_SIZE == 64 */ + sub %sp, 64, %sp ! make room for incoming arguments +#endif + +! Set up pointers to argc and argv #if TARGET_PTR_SIZE == 32 - ld [%g5 + 0x40], %o0 ! argc + ld [%g5 + 0x40], %o0 ! argc add %g5, 0x44, %o1 ! argv add %o0, 1, %o2 sll %o2, 2, %o2 #else /* TARGET_PTR_SIZE == 64 */ - ld [%g5 + 0x88], %o0 ! argc.lo - add %sp, 0x90, %o1 ! argv + ld [%g5 + 0x80], %o0 ! argc.lo + add %sp, 0x88, %o1 ! argv add %o0, 1, %o2 sll %o2, 3, %o2 #endif @@ -87,16 +99,16 @@ _start: sethi %hi (environ), %o3 or %o3, %lo (environ), %o3 #if TARGET_PTR_SIZE == 32 - st %o2, [%o3 + %g4] + st %o2, [%o3 + %g4] #else /* TARGET_PTR_SIZE == 64 */ stx %o2, [%o3 + %g4] #endif call main - nop + nop call exit - nop + nop ! If all the above methods fail to terminate the program, try an illegal insn. ! If that does not work, the o/s is hosed more than we are. diff --git a/arch/sparc/include/klibc/archsys.h b/arch/sparc/include/klibc/archsys.h index 61be72656ab80..fe6e68df8a3bd 100644 --- a/arch/sparc/include/klibc/archsys.h +++ b/arch/sparc/include/klibc/archsys.h @@ -7,6 +7,29 @@ #ifndef _KLIBC_ARCHSYS_H #define _KLIBC_ARCHSYS_H +/* fork and vfork return the "other process" pid in %o0 and an + "is child" flag in %o1... */ + +#define _syscall0_forkish(type,name) \ +type name(void) \ +{ \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register unsigned long __o0 __asm__ ("o0"); \ +register unsigned long __o1 __asm__ ("o1"); \ +__asm__ __volatile__ ("t 0x10\n\t" \ + "bcc 1f\n\t" \ + "mov %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__o0), "=r" (__o1)\ + : "r" (__g1) \ + : "cc"); \ +if ((unsigned long)__o0 < (unsigned long)-255) \ + return (type)(__o0 & (__o1-1)); \ +errno = (int)-__o0; \ +return -1; \ +} + /* SPARC seems to lack _syscall6() in its headers */ #ifndef _syscall6 @@ -11,9 +11,13 @@ #ifdef __NR_fork +#ifdef __sparc__ +_syscall0_forkish(pid_t,fork); +#else _syscall0(pid_t,fork); +#endif -#else +#else /* __NR_fork */ static inline _syscall2(pid_t,clone,unsigned long,flags,void *,newsp); diff --git a/include/arch/sparc/klibc/archsys.h b/include/arch/sparc/klibc/archsys.h index 61be72656ab80..fe6e68df8a3bd 100644 --- a/include/arch/sparc/klibc/archsys.h +++ b/include/arch/sparc/klibc/archsys.h @@ -7,6 +7,29 @@ #ifndef _KLIBC_ARCHSYS_H #define _KLIBC_ARCHSYS_H +/* fork and vfork return the "other process" pid in %o0 and an + "is child" flag in %o1... */ + +#define _syscall0_forkish(type,name) \ +type name(void) \ +{ \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register unsigned long __o0 __asm__ ("o0"); \ +register unsigned long __o1 __asm__ ("o1"); \ +__asm__ __volatile__ ("t 0x10\n\t" \ + "bcc 1f\n\t" \ + "mov %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__o0), "=r" (__o1)\ + : "r" (__g1) \ + : "cc"); \ +if ((unsigned long)__o0 < (unsigned long)-255) \ + return (type)(__o0 & (__o1-1)); \ +errno = (int)-__o0; \ +return -1; \ +} + /* SPARC seems to lack _syscall6() in its headers */ #ifndef _syscall6 diff --git a/include/signal.h b/include/signal.h index fc12fa104e086..d417e40c16f0c 100644 --- a/include/signal.h +++ b/include/signal.h @@ -18,6 +18,9 @@ #ifndef SA_NODEFER # define SA_NODEFER SA_NOMASK #endif +#ifndef NSIG +# define NSIG _NSIG +#endif __extern const char * const sys_siglist[]; diff --git a/klibc/SYSCALLS b/klibc/SYSCALLS index 613fb92f55105..75b848a0f7b01 100644 --- a/klibc/SYSCALLS +++ b/klibc/SYSCALLS @@ -5,13 +5,14 @@ # linker can do its job properly. # # The full description of a line is: -# [<[!]arch,...>] type [sysname[@systype]::]funcname(args) +# [<[!]arch,...>] type sysname[@systype][::funcname](args) # # # Process-related syscalls # -<!mips,mips64> pid_t vfork() +<!mips,mips64,sparc> pid_t vfork() +<sparc> pid_t vfork@forkish() <!alpha> pid_t getpid() <alpha> pid_t getxpid@dual0::getpid() int setpgid(pid_t, pid_t) diff --git a/klibc/arch/sparc/crt0i.S b/klibc/arch/sparc/crt0i.S index a83fefa77dca7..44f9092bc168b 100644 --- a/klibc/arch/sparc/crt0i.S +++ b/klibc/arch/sparc/crt0i.S @@ -67,19 +67,31 @@ _start: ! or without an imposed bias. andcc %sp, 1, %g5 - bnz,a .LHaveBias + bz,a .LNoBias + nop mov 2047, %g5 -.LHaveBias: +.LNoBias: add %sp, %g5, %g5 +! On entry, the kernel leaves room for one register frame, but +! the C API wants more free space. Thus, we need to drop the stack +! pointer additionally. + +#if TARGET_PTR_SIZE == 32 + sub %sp, 32, %sp ! make room for incoming arguments +#else /* TARGET_PTR_SIZE == 64 */ + sub %sp, 64, %sp ! make room for incoming arguments +#endif + +! Set up pointers to argc and argv #if TARGET_PTR_SIZE == 32 - ld [%g5 + 0x40], %o0 ! argc + ld [%g5 + 0x40], %o0 ! argc add %g5, 0x44, %o1 ! argv add %o0, 1, %o2 sll %o2, 2, %o2 #else /* TARGET_PTR_SIZE == 64 */ - ld [%g5 + 0x88], %o0 ! argc.lo - add %sp, 0x90, %o1 ! argv + ld [%g5 + 0x80], %o0 ! argc.lo + add %sp, 0x88, %o1 ! argv add %o0, 1, %o2 sll %o2, 3, %o2 #endif @@ -87,16 +99,16 @@ _start: sethi %hi (environ), %o3 or %o3, %lo (environ), %o3 #if TARGET_PTR_SIZE == 32 - st %o2, [%o3 + %g4] + st %o2, [%o3 + %g4] #else /* TARGET_PTR_SIZE == 64 */ stx %o2, [%o3 + %g4] #endif call main - nop + nop call exit - nop + nop ! If all the above methods fail to terminate the program, try an illegal insn. ! If that does not work, the o/s is hosed more than we are. diff --git a/klibc/arch/sparc/include/klibc/archsys.h b/klibc/arch/sparc/include/klibc/archsys.h index 61be72656ab80..fe6e68df8a3bd 100644 --- a/klibc/arch/sparc/include/klibc/archsys.h +++ b/klibc/arch/sparc/include/klibc/archsys.h @@ -7,6 +7,29 @@ #ifndef _KLIBC_ARCHSYS_H #define _KLIBC_ARCHSYS_H +/* fork and vfork return the "other process" pid in %o0 and an + "is child" flag in %o1... */ + +#define _syscall0_forkish(type,name) \ +type name(void) \ +{ \ +register long __g1 __asm__ ("g1") = __NR_##name; \ +register unsigned long __o0 __asm__ ("o0"); \ +register unsigned long __o1 __asm__ ("o1"); \ +__asm__ __volatile__ ("t 0x10\n\t" \ + "bcc 1f\n\t" \ + "mov %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" \ + : "=r" (__o0), "=r" (__o1)\ + : "r" (__g1) \ + : "cc"); \ +if ((unsigned long)__o0 < (unsigned long)-255) \ + return (type)(__o0 & (__o1-1)); \ +errno = (int)-__o0; \ +return -1; \ +} + /* SPARC seems to lack _syscall6() in its headers */ #ifndef _syscall6 diff --git a/klibc/fork.c b/klibc/fork.c index 1bf0169068a83..080e38c4329c0 100644 --- a/klibc/fork.c +++ b/klibc/fork.c @@ -11,9 +11,13 @@ #ifdef __NR_fork +#ifdef __sparc__ +_syscall0_forkish(pid_t,fork); +#else _syscall0(pid_t,fork); +#endif -#else +#else /* __NR_fork */ static inline _syscall2(pid_t,clone,unsigned long,flags,void *,newsp); diff --git a/klibc/include/signal.h b/klibc/include/signal.h index fc12fa104e086..d417e40c16f0c 100644 --- a/klibc/include/signal.h +++ b/klibc/include/signal.h @@ -18,6 +18,9 @@ #ifndef SA_NODEFER # define SA_NODEFER SA_NOMASK #endif +#ifndef NSIG +# define NSIG _NSIG +#endif __extern const char * const sys_siglist[]; diff --git a/klibc/tests/getenvtest.c b/klibc/tests/getenvtest.c index c0742200162e0..76d89018a36bb 100644 --- a/klibc/tests/getenvtest.c +++ b/klibc/tests/getenvtest.c @@ -17,6 +17,7 @@ int main(int argc, char *argv[], char *envp[]) printf("USER = %s\n", getenv("USER")); /* Test argc/argv */ + printf("argc = %d\n", argc); for ( i = 0 ; i < argc ; i++ ) { printf("argv[%2d] = %s\n", i, argv[i]); } diff --git a/tests/getenvtest.c b/tests/getenvtest.c index c0742200162e0..76d89018a36bb 100644 --- a/tests/getenvtest.c +++ b/tests/getenvtest.c @@ -17,6 +17,7 @@ int main(int argc, char *argv[], char *envp[]) printf("USER = %s\n", getenv("USER")); /* Test argc/argv */ + printf("argc = %d\n", argc); for ( i = 0 ; i < argc ; i++ ) { printf("argv[%2d] = %s\n", i, argv[i]); } |