aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-08-17 07:18:33 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-08-17 07:18:33 +0000
commit156eb2a65dd14820c58b0e35f7cf1a7ecda85a50 (patch)
tree5e8645362aa601adaca198ca22dd28b3299bf935
parente2d728a3d0c60a1aa72dcb785027abd38918ced8 (diff)
downloadklibc-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--SYSCALLS5
-rw-r--r--arch/sparc/crt0i.S28
-rw-r--r--arch/sparc/include/klibc/archsys.h23
-rw-r--r--fork.c6
-rw-r--r--include/arch/sparc/klibc/archsys.h23
-rw-r--r--include/signal.h3
-rw-r--r--klibc/SYSCALLS5
-rw-r--r--klibc/arch/sparc/crt0i.S28
-rw-r--r--klibc/arch/sparc/include/klibc/archsys.h23
-rw-r--r--klibc/fork.c6
-rw-r--r--klibc/include/signal.h3
-rw-r--r--klibc/tests/getenvtest.c1
-rw-r--r--tests/getenvtest.c1
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
diff --git a/fork.c b/fork.c
index 1bf0169068a83..080e38c4329c0 100644
--- a/fork.c
+++ b/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/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]);
}