[klibc] sparc: deal with SA_RESTORER; sparc64 requires a restorer function

Fake out SA_RESTORER on sparc; sparc64 requires a restorer function, so
make sure one is provided.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/usr/include/arch/sparc/klibc/archsignal.h b/usr/include/arch/sparc/klibc/archsignal.h
index 0ff7aab..6e845a8 100644
--- a/usr/include/arch/sparc/klibc/archsignal.h
+++ b/usr/include/arch/sparc/klibc/archsignal.h
@@ -18,4 +18,7 @@
 	sigset_t	sa_mask;
 };
 
+/* Not actually used by the kernel... */
+#define SA_RESTORER	0x80000000
+
 #endif
diff --git a/usr/include/arch/sparc64/klibc/archconfig.h b/usr/include/arch/sparc64/klibc/archconfig.h
index 212f616..bb0c003 100644
--- a/usr/include/arch/sparc64/klibc/archconfig.h
+++ b/usr/include/arch/sparc64/klibc/archconfig.h
@@ -10,5 +10,6 @@
 #define _KLIBC_ARCHCONFIG_H
 
 #define _KLIBC_USE_RT_SIG 1	/* Use rt_* signals */
+#define _KLIBC_NEEDS_SA_RESTORER 1 /* Need a restorer function */
 
 #endif				/* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/sparc64/klibc/archsignal.h b/usr/include/arch/sparc64/klibc/archsignal.h
index 55f0550..bb0a5ce 100644
--- a/usr/include/arch/sparc64/klibc/archsignal.h
+++ b/usr/include/arch/sparc64/klibc/archsignal.h
@@ -11,4 +11,7 @@
 #define __WANT_POSIX1B_SIGNALS__
 #include <asm/signal.h>
 
+/* Not actually used by the kernel... */
+#define SA_RESTORER	0x80000000
+
 #endif
diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def
index 9ab685d..435abd5 100644
--- a/usr/klibc/SYSCALLS.def
+++ b/usr/klibc/SYSCALLS.def
@@ -186,6 +186,7 @@
 int rt_sigsuspend::__rt_sigsuspend(const sigset_t *, size_t)
 int rt_sigpending::__rt_sigpending(sigset_t *, size_t)
 int rt_sigprocmask::__rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t)
+<sparc64> void rt_sigreturn::__sigreturn(void)
 #else
 int sigaction::__sigaction(int, const struct sigaction *, struct sigaction *)
 int sigsuspend(const sigset_t *)
diff --git a/usr/klibc/sigaction.c b/usr/klibc/sigaction.c
index f0dbe21..658c3ad 100644
--- a/usr/klibc/sigaction.c
+++ b/usr/klibc/sigaction.c
@@ -10,7 +10,7 @@
 __extern int __sigaction(int, const struct sigaction *, struct sigaction *);
 #ifdef __sparc__
 __extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *,
-			    void *, size_t);
+			    void (*)(void), size_t);
 #else
 __extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *,
 			    size_t);
@@ -36,7 +36,13 @@
 
 #if _KLIBC_USE_RT_SIG
 # ifdef __sparc__
-	rv = __rt_sigaction(sig, act, oact, NULL, sizeof(sigset_t));
+	{
+		void (*restorer)(void);
+		restorer = (act && act->sa_flags & SA_RESTORER)
+			? (void (*)(void))((uintptr_t)act->sa_restorer - 8)
+			: NULL;
+		rv = __rt_sigaction(sig, act, oact, restorer, sizeof(sigset_t));
+	}
 # else
 	rv = __rt_sigaction(sig, act, oact, sizeof(sigset_t));
 # endif