2004-07-07  David S. Miller  <davem@nuts.davemloft.net>

	* linux/sparc/syscallent.h: Sync with reality.
	* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
	sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
	sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
	sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
	sys_removexattr, sys_lremovexattr, sys_fremovexattr,
	sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
	sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
	sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
	sys_timer_settime, sys_timer_gettime): New declarations.
	* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
	linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
	linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
	linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
	linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
	linux/sparc64/signalent.h, linux/sparc64/signalent.h,
	linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
	linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
	linux/sparc64/syscallent1.h: New files.
	* defs.h (LINUXSPARC): Define also when SPARC64.
	(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
	Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
	Define possibly missing __NR_exit_group.  Declare getrval2.
	* configure.ac (sparc64): New architecture case.
	* config.h.in (SPARC64): New define.
	* file.c (stat_sparc64): New structure.
	(printstat_sparc64): New output routine for that.
	(printstat): Call it, if personality is 2.
	(printstat64): Likewise.
	* util.c: Conditionalize ptrace defines on LINUXSPARC
	not LINUX && SPARC.
	(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
	to PTRACE_FOOREGS64 so that more sparc code can be shared
	between 64-bit and 32-bit.
	(_hack_syscall5): Correct trap number when SPARC64.
	(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
	(getpc): Handle SPARC64 && LINUX.
	(printcall): Likewise.
	(arg fetching/setting): Use same code for SPARC64 LINUX
	as for SPARC.
	(setbpt): Handle SPARC64 && LINUX.
	(clearbpt): Likewise.
	* signal.c: Conditionalize ptrace defines on SPARC and
	SPARC64.
	(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
	to PTRACE_FOOREGS64 so that more sparc code can be shared
	between 64-bit and 32-bit.
	(m_siginfo): Use same definition on SPARC64 as SPARC.
	(sys_sigreturn): Handle LINUX && SPARC64.
	* syscall.c: Conditionalize ptrace defines on SPARC and
	SPARC64.
	(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
	to PTRACE_FOOREGS64 so that more sparc code can be shared
	between 64-bit and 32-bit.
	(getscno): Use same static state on SPARC64 as SPARC,
	and add SPARC64 handling.
	(get_error): Handle LINUX && SPARC64.
	(force_result): Likewise.
	(syscall_enter): Likewise.
	(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
	just like SPARC.
	(getrval2): Handle LINUX && SPARC64.
	* process.c: Conditionalize ptrace defines on SPARC and
	SPARC64.
	(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
	to PTRACE_FOOREGS64 so that more sparc code can be shared
	between 64-bit and 32-bit.
	(change_syscall): Handle LINUX && SPARC64.
	(struct_user_offsets): Ifdef out those which do not exist
	on SPARC64.
	* net.c (sys_pipe): Handle LINUX && SPARC64.
	* ioctl.c: Fix initializer typo for nioctlents2, was
	nioctlents1 by accident.
diff --git a/syscall.c b/syscall.c
index 4264a80..b6d526d 100644
--- a/syscall.c
+++ b/syscall.c
@@ -43,13 +43,13 @@
 #include <sys/param.h>
 
 #if HAVE_ASM_REG_H
-#ifdef SPARC
+#if defined (SPARC) || defined (SPARC64)
 #  define fpq kernel_fpq
 #  define fq kernel_fq
 #  define fpu kernel_fpu
 #endif
 #include <asm/reg.h>
-#ifdef SPARC
+#if defined (SPARC) || defined (SPARC64)
 #  undef fpq
 #  undef fq
 #  undef fpu
@@ -74,6 +74,14 @@
 # undef pt_all_user_regs
 #endif
 
+#if defined (LINUX) && defined (SPARC64)
+# define r_pc r_tpc
+# undef PTRACE_GETREGS
+# define PTRACE_GETREGS PTRACE_GETREGS64
+# undef PTRACE_SETREGS
+# define PTRACE_SETREGS PTRACE_SETREGS64
+#endif /* LINUX && SPARC64 */
+
 #if defined(LINUX) && defined(IA64)
 # include <asm/ptrace_offsets.h>
 # include <asm/rse.h>
@@ -715,7 +723,7 @@
 #elif defined (ALPHA)
 	static long r0;
 	static long a3;
-#elif defined (SPARC)
+#elif defined (SPARC) || defined (SPARC64)
 	static struct regs regs;
 	static unsigned long trap;
 #elif defined(MIPS)
@@ -1062,7 +1070,7 @@
 		if (upeek(pid, REG_R0, &r0) < 0)
 			return -1;
 	}
-#elif defined (SPARC)
+#elif defined (SPARC) || defined (SPARC64)
 	/* Everything we need is in the current register set. */
 	if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
 		return -1;
@@ -1072,6 +1080,9 @@
 		/* Retrieve the syscall trap instruction. */
 		errno = 0;
 		trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
+#if defined(SPARC64)
+		trap >>= 32;
+#endif
 		if (errno)
 			return -1;
 
@@ -1083,8 +1094,8 @@
 			break;
 		case 0x91d0206d:
 			/* Linux/SPARC64 syscall trap. */
-			fprintf(stderr,"syscall: Linux/SPARC64 not supported yet\n");
-			return -1;
+			set_personality(2);
+			break;
 		case 0x91d02000:
 			/* SunOS syscall trap. (pers 1) */
 			fprintf(stderr,"syscall: SunOS no support\n");
@@ -1107,7 +1118,11 @@
 				tcp->flags &= ~TCB_WAITEXECVE;
 				return 0;
 			}
+#if defined (SPARC64)
+			fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
+#else
 			fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
+#endif
 			return -1;
 		}
 
@@ -1478,6 +1493,16 @@
 			u_error = 0;
 		}
 #else /* !SPARC */
+#ifdef SPARC64
+		if (regs.r_tstate & 0x1100000000UL) {
+			tcp->u_rval = -1;
+			u_error = regs.r_o0;
+		}
+		else {
+			tcp->u_rval = regs.r_o0;
+			u_error = 0;
+		}
+#else /* !SPARC64 */
 #ifdef HPPA
 		if (r28 && (unsigned) -r28 < nerrnos) {
 			tcp->u_rval = -1;
@@ -1513,6 +1538,7 @@
 #endif /* SH */
 #endif /* HPPA */
 #endif /* SPARC */
+#endif /* SPARC64 */
 #endif /* ALPHA */
 #endif /* ARM */
 #endif /* M68K */
@@ -1705,6 +1731,20 @@
 	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
 		return -1;
 #else /* !SPARC */
+#ifdef SPARC64
+	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
+		return -1;
+	if (error) {
+		regs.r_tstate |= 0x1100000000UL;
+		regs.r_o0 = error;
+	}
+	else {
+		regs.r_tstate &= ~0x1100000000UL;
+		regs.r_o0 = rval;
+	}
+	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
+		return -1;
+#else /* !SPARC64 */
 #ifdef HPPA
 	r28 = error ? -error : rval;
 	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
@@ -1723,6 +1763,7 @@
 #endif /* SH */
 #endif /* HPPA */
 #endif /* SPARC */
+#endif /* SPARC64 */
 #endif /* ALPHA */
 #endif /* ARM */
 #endif /* M68K */
@@ -1901,7 +1942,7 @@
 				return -1;
 		}
 	}
-#elif defined (SPARC)
+#elif defined (SPARC) || defined (SPARC64)
 	{
 		int i;
 
@@ -2285,7 +2326,7 @@
 
 	switch (tcp->scno + NR_SYSCALL_BASE) {
 #ifdef LINUX
-#if !defined (ALPHA) && !defined(SPARC) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64)
+#if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64)
 	case SYS_socketcall:
 		decode_subcall(tcp, SYS_socket_subcall,
 			SYS_socket_nsubcalls, deref_style);
@@ -2294,8 +2335,8 @@
 		decode_subcall(tcp, SYS_ipc_subcall,
 			SYS_ipc_nsubcalls, shift_style);
 		break;
-#endif /* !ALPHA && !MIPS && !SPARC && !HPPA && !X86_64 */
-#ifdef SPARC
+#endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA && !X86_64 */
+#if defined (SPARC) || defined (SPARC64)
 	case SYS_socketcall:
 		sparc_socket_decode (tcp);
 		break;
@@ -2435,7 +2476,7 @@
 	long val = -1;
 
 #ifdef LINUX
-#ifdef SPARC
+#if defined (SPARC) || defined (SPARC64)
 	struct regs regs;
 	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
 		return -1;
@@ -2443,7 +2484,7 @@
 #elif defined(SH)
 	if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
 		return -1;
-#endif /* SPARC */
+#endif /* SPARC || SPARC64 */
 #elif defined(IA64)
 	if (upeek(tcp->pid, PT_R9, &val) < 0)
 		return -1;