[PATCH] Add biarch support for powerpc64

Andreas Schwab schwab at linux-m68k.org
Sat Jul 3 19:59:02 UTC 2010


* acinclude.m4 (AC_LITTLE_ENDIAN_LONG_LONG): Use int instead of
long.
* configure.ac: Use arch=powerpc64 and define POWERPC64 for powerpc64.
* defs.h (SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE)
(PERSONALITY1_WORDSIZE) [POWERPC64]: Define.
* file.c: Handle POWERPC64 like POWERPC.
(struct stat_powerpc32, printstat_powerpc32) [POWERPC64]:
Define.
(printstat) [POWERPC64]: Call printstat_powerpc32 for 32bit
personality.
(sys_newfstatat) [POWERPC64]: Handle personality.
* ioctl.c: Handle POWERPC64 like POWERPC.
* linux/errnoent.h: Handle POWERPC64 like POWERPC.
* linux/powerpc64/errnoent1.h: New file.
* linux/powerpc64/ioctlent.h: New file.
* linux/powerpc64/ioctlent1.h: New file.
* linux/powerpc64/signalent1.h: New file.
* linux/powerpc64/syscallent.h: New file.
* linux/powerpc64/syscallent1.h: New file.
* linux/syscall.h: Handle POWERPC64 like POWERPC.
* mem.c: Handle POWERPC64 like POWERPC.
* process.c: Handle POWERPC64 like POWERPC.
* signal.c: Handle POWERPC64 like POWERPC.
(sys_sigreturn) [POWERPC64]: Check for personality.
* syscall.c: Handle POWERPC64 like POWERPC.
(get_scno) [POWERPC64]: Check for 64/32 bit mode.
* util.c:Handle POWERPC64 like POWERPC.
(printllval) [POWERPC64]: Check for personality.
---
 acinclude.m4                  |    2 +-
 configure.ac                  |    4 ++
 defs.h                        |   11 ++++-
 file.c                        |   83 +++++++++++++++++++++++++++++++++++++++-
 ioctl.c                       |    2 +-
 linux/errnoent.h              |    2 +-
 linux/powerpc64/errnoent1.h   |    1 +
 linux/powerpc64/ioctlent.h    |    1 +
 linux/powerpc64/ioctlent1.h   |    1 +
 linux/powerpc64/signalent1.h  |    1 +
 linux/powerpc64/syscallent.h  |    1 +
 linux/powerpc64/syscallent1.h |    1 +
 linux/syscall.h               |    4 +-
 mem.c                         |    2 +-
 process.c                     |    7 ++-
 signal.c                      |    9 +++-
 syscall.c                     |   34 ++++++++++++++---
 util.c                        |   20 +++++++---
 18 files changed, 157 insertions(+), 29 deletions(-)
 create mode 100644 linux/powerpc64/errnoent1.h
 create mode 100644 linux/powerpc64/ioctlent.h
 create mode 100644 linux/powerpc64/ioctlent1.h
 create mode 100644 linux/powerpc64/signalent1.h
 create mode 100644 linux/powerpc64/syscallent.h
 create mode 100644 linux/powerpc64/syscallent1.h

diff --git a/acinclude.m4 b/acinclude.m4
index da66c64..1741ab9 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -280,7 +280,7 @@ AC_CACHE_VAL(ac_cv_have_little_endian_long_long,
 int main () {
 	union {
 		long long ll;
-		long l [2];
+		int l [2];
 	} u;
 	u.ll = 0x12345678;
 	if (u.l[0] == 0x12345678)
diff --git a/configure.ac b/configure.ac
index 76f55d2..5f86783 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,10 @@ alpha*)
 	arch=alpha
 	AC_DEFINE([ALPHA], 1, [Define for the Alpha architecture.])
 	;;
+powerpc64*)
+	arch=powerpc64
+	AC_DEFINE([POWERPC64], 1, [Define for the PowerPC64 architecture.])
+	;;
 powerpc*)
 	arch=powerpc
 	AC_DEFINE([POWERPC], 1, [Define for the PowerPC architecture.])
diff --git a/defs.h b/defs.h
index a7e8793..3f04b1b 100644
--- a/defs.h
+++ b/defs.h
@@ -246,6 +246,13 @@ extern int ptrace(int, int, char *, int, ...);
 #define PERSONALITY1_WORDSIZE 4
 #endif
 
+#if defined POWERPC64
+#undef SUPPORTED_PERSONALITIES
+#define SUPPORTED_PERSONALITIES 2
+#define PERSONALITY0_WORDSIZE 8
+#define PERSONALITY1_WORDSIZE 4
+#endif
+
 #ifdef SVR4
 #ifdef HAVE_MP_PROCFS
 extern int mp_ioctl (int f, int c, void *a, int s);
@@ -370,7 +377,7 @@ struct tcb {
  * See "stray syscall exit: eax = " message in syscall_fixup().
  */
 # if defined(ALPHA) || defined(AVR32) || defined(SPARC) || defined(SPARC64) \
-  || defined(POWERPC) || defined(IA64) || defined(HPPA) \
+  || defined(POWERPC) || defined(POWERPC64) || defined(IA64) || defined(HPPA) \
   || defined(SH) || defined(SH64) || defined(S390) || defined(S390X) \
   || defined(ARM) || defined(MIPS) || defined(BFIN) || defined(TILE)
 #  define TCB_WAITEXECVE 02000	/* ignore SIGTRAP after exceve */
@@ -389,7 +396,7 @@ struct tcb {
 #   define __NR_exit_group 231
 #  elif defined IA64
 #   define __NR_exit_group 1236
-#  elif defined POWERPC
+#  elif defined POWERPC || defined POWERPC64
 #   define __NR_exit_group 234
 #  elif defined S390 || defined S390X
 #   define __NR_exit_group 248
diff --git a/file.c b/file.c
index 854548f..876e148 100644
--- a/file.c
+++ b/file.c
@@ -859,6 +859,71 @@ printstat_sparc64(struct tcb *tcp, long addr)
 #endif /* SPARC64 */
 #endif /* LINUXSPARC */
 
+#if defined LINUX && defined POWERPC64
+struct stat_powerpc32 {
+	unsigned int	st_dev;
+	unsigned int	st_ino;
+	unsigned int	st_mode;
+	unsigned short	st_nlink;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	unsigned int	st_rdev;
+	unsigned int	st_size;
+	unsigned int	st_blksize;
+	unsigned int	st_blocks;
+	unsigned int	st_atime;
+	unsigned int	st_atime_nsec;
+	unsigned int	st_mtime;
+	unsigned int	st_mtime_nsec;
+	unsigned int	st_ctime;
+	unsigned int	st_ctime_nsec;
+	unsigned int	__unused4;
+	unsigned int	__unused5;
+};
+
+static void
+printstat_powerpc32(struct tcb *tcp, long addr)
+{
+	struct stat_powerpc32 statbuf;
+
+	if (umove(tcp, addr, &statbuf) < 0) {
+		tprintf("{...}");
+		return;
+	}
+
+	if (!abbrev(tcp)) {
+		tprintf("{st_dev=makedev(%u, %u), st_ino=%u, st_mode=%s, ",
+			major(statbuf.st_dev), minor(statbuf.st_dev),
+			statbuf.st_ino,
+			sprintmode(statbuf.st_mode));
+		tprintf("st_nlink=%u, st_uid=%u, st_gid=%u, ",
+			statbuf.st_nlink, statbuf.st_uid, statbuf.st_gid);
+		tprintf("st_blksize=%u, ", statbuf.st_blksize);
+		tprintf("st_blocks=%u, ", statbuf.st_blocks);
+	}
+	else
+		tprintf("{st_mode=%s, ", sprintmode(statbuf.st_mode));
+	switch (statbuf.st_mode & S_IFMT) {
+	case S_IFCHR: case S_IFBLK:
+		tprintf("st_rdev=makedev(%lu, %lu), ",
+			(unsigned long) major(statbuf.st_rdev),
+			(unsigned long) minor(statbuf.st_rdev));
+		break;
+	default:
+		tprintf("st_size=%u, ", statbuf.st_size);
+		break;
+	}
+	if (!abbrev(tcp)) {
+		tprintf("st_atime=%s, ", sprinttime(statbuf.st_atime));
+		tprintf("st_mtime=%s, ", sprinttime(statbuf.st_mtime));
+		tprintf("st_ctime=%s", sprinttime(statbuf.st_ctime));
+		tprintf("}");
+	}
+	else
+		tprintf("...}");
+}
+#endif /* LINUX && POWERPC64 */
+
 static const struct xlat fileflags[] = {
 #ifdef FREEBSD
 	{ UF_NODUMP,	"UF_NODUMP"	},
@@ -998,6 +1063,13 @@ printstat(struct tcb *tcp, long addr)
 #endif
 #endif /* LINUXSPARC */
 
+#if defined LINUX && defined POWERPC64
+	if (current_personality == 1) {
+		printstat_powerpc32(tcp, addr);
+		return;
+	}
+#endif
+
 	if (umove(tcp, addr, &statbuf) < 0) {
 		tprintf("{...}");
 		return;
@@ -1259,7 +1331,12 @@ sys_newfstatat(struct tcb *tcp)
 		printpath(tcp, tcp->u_arg[1]);
 		tprintf(", ");
 	} else {
-#if defined HAVE_STAT64 && !(defined POWERPC && defined __powerpc64__)
+#ifdef POWERPC64
+		if (current_personality == 0)
+			printstat(tcp, tcp->u_arg[2]);
+		else
+			printstat64(tcp, tcp->u_arg[2]);
+#elif defined HAVE_STAT64
 		printstat64(tcp, tcp->u_arg[2]);
 #else
 		printstat(tcp, tcp->u_arg[2]);
@@ -2824,13 +2901,13 @@ sys_fadvise64_64(struct tcb *tcp)
 	if (entering(tcp)) {
 		int argn;
 		tprintf("%ld, ", tcp->u_arg[0]);
-#if defined ARM || defined POWERPC
+#if defined ARM || defined POWERPC || defined POWERPC64
 		argn = printllval(tcp, "%lld, ", 2);
 #else
 		argn = printllval(tcp, "%lld, ", 1);
 #endif
 		argn = printllval(tcp, "%lld, ", argn);
-#if defined ARM || defined POWERPC
+#if defined ARM || defined POWERPC || defined POWERPC64
 		printxval(advise, tcp->u_arg[1], "POSIX_FADV_???");
 #else
 		printxval(advise, tcp->u_arg[argn], "POSIX_FADV_???");
diff --git a/ioctl.c b/ioctl.c
index 906c71e..3f97dfd 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -117,7 +117,7 @@ long code, arg;
 {
 	switch ((code >> 8) & 0xff) {
 #ifdef LINUX
-#if defined(ALPHA) || defined(POWERPC)
+#if defined(ALPHA) || defined(POWERPC) || defined(POWERPC64)
 	case 'f': case 't': case 'T':
 #else /* !ALPHA */
 	case 0x54:
diff --git a/linux/errnoent.h b/linux/errnoent.h
index c52d1d0..aead207 100644
--- a/linux/errnoent.h
+++ b/linux/errnoent.h
@@ -56,7 +56,7 @@
 	"ENOANO", /* 55 */
 	"EBADRQC", /* 56 */
 	"EBADSLT", /* 57 */
-#ifdef POWERPC
+#if defined POWERPC || defined POWERPC64
 	"EDEADLOCK", /* 58 */
 #else
 	"ERRNO_58", /* 58 */
diff --git a/linux/powerpc64/errnoent1.h b/linux/powerpc64/errnoent1.h
new file mode 100644
index 0000000..441c66b
--- /dev/null
+++ b/linux/powerpc64/errnoent1.h
@@ -0,0 +1 @@
+#include "../errnoent.h"
diff --git a/linux/powerpc64/ioctlent.h b/linux/powerpc64/ioctlent.h
new file mode 100644
index 0000000..f65411c
--- /dev/null
+++ b/linux/powerpc64/ioctlent.h
@@ -0,0 +1 @@
+#include "../powerpc/ioctlent.h"
diff --git a/linux/powerpc64/ioctlent1.h b/linux/powerpc64/ioctlent1.h
new file mode 100644
index 0000000..f65411c
--- /dev/null
+++ b/linux/powerpc64/ioctlent1.h
@@ -0,0 +1 @@
+#include "../powerpc/ioctlent.h"
diff --git a/linux/powerpc64/signalent1.h b/linux/powerpc64/signalent1.h
new file mode 100644
index 0000000..d31e6a4
--- /dev/null
+++ b/linux/powerpc64/signalent1.h
@@ -0,0 +1 @@
+#include "../signalent.h"
diff --git a/linux/powerpc64/syscallent.h b/linux/powerpc64/syscallent.h
new file mode 100644
index 0000000..b909c82
--- /dev/null
+++ b/linux/powerpc64/syscallent.h
@@ -0,0 +1 @@
+#include "../powerpc/syscallent.h"
diff --git a/linux/powerpc64/syscallent1.h b/linux/powerpc64/syscallent1.h
new file mode 100644
index 0000000..b909c82
--- /dev/null
+++ b/linux/powerpc64/syscallent1.h
@@ -0,0 +1 @@
+#include "../powerpc/syscallent.h"
diff --git a/linux/syscall.h b/linux/syscall.h
index 6bfed87..68604a9 100644
--- a/linux/syscall.h
+++ b/linux/syscall.h
@@ -165,7 +165,7 @@ int sys_osf_utimes();
 #  define SYS_waitid 1270
 # elif defined M68K
 #  define SYS_waitid 277
-# elif defined POWERPC
+# elif defined POWERPC || defined POWERPC64
 #  define SYS_waitid 272
 # elif defined S390 || defined S390X
 #  define SYS_waitid 281
@@ -328,7 +328,7 @@ int sys_cacheflush();
 
 int sys_pread64(), sys_pwrite64();
 
-#ifdef POWERPC
+#if defined POWERPC || defined POWERPC64
 int sys_subpage_prot();
 #endif
 
diff --git a/mem.c b/mem.c
index ec5707a..bacb1ea 100644
--- a/mem.c
+++ b/mem.c
@@ -955,7 +955,7 @@ struct tcb *tcp;
 }
 #endif
 
-#if defined(LINUX) && defined(POWERPC)
+#if defined(LINUX) && (defined(POWERPC) || defined(POWERPC64))
 int
 sys_subpage_prot(tcp)
 struct tcb *tcp;
diff --git a/process.c b/process.c
index dadf830..388fcbd 100644
--- a/process.c
+++ b/process.c
@@ -689,7 +689,7 @@ change_syscall(struct tcb *tcp, int new)
 	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
 		return -1;
 	return 0;
-#elif defined(POWERPC)
+#elif defined(POWERPC) || defined(POWERPC64)
 	if (ptrace(PTRACE_POKEUSER, tcp->pid,
 		   (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
 		return -1;
@@ -2401,7 +2401,7 @@ const struct xlat struct_user_offsets[] = {
 	/* XXX No support for these offsets yet. */
 #   elif defined(HPPA)
 	/* XXX No support for these offsets yet. */
-#   elif defined(POWERPC)
+#   elif defined(POWERPC) || defined(POWERPC64)
 #    ifndef PT_ORIG_R3
 #     define PT_ORIG_R3 34
 #    endif
@@ -3094,7 +3094,8 @@ const struct xlat struct_user_offsets[] = {
 
 #   if !defined(SPARC) && !defined(HPPA) && !defined(POWERPC) \
 		&& !defined(ALPHA) && !defined(IA64) \
-		&& !defined(CRISV10) && !defined(CRISV32)
+		&& !defined(CRISV10) && !defined(CRISV32) \
+		&& !defined(POWERPC64)
 #    if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SPARC64) && !defined(AVR32) && !defined(BFIN) && !defined(TILE)
 	{ uoff(u_fpvalid),	"offsetof(struct user, u_fpvalid)"	},
 #    endif
diff --git a/signal.c b/signal.c
index bf97e90..dcd0d00 100644
--- a/signal.c
+++ b/signal.c
@@ -1321,7 +1321,7 @@ sys_sigreturn(struct tcb *tcp)
 		return RVAL_NONE | RVAL_STR;
 	}
 	return 0;
-#elif defined(POWERPC)
+#elif defined(POWERPC) || defined(POWERPC64)
 	long esp;
 	struct sigcontext_struct sc;
 
@@ -1330,8 +1330,11 @@ sys_sigreturn(struct tcb *tcp)
 		if (upeek(tcp, sizeof(unsigned long)*PT_R1, &esp) < 0)
 			return 0;
 		/* Skip dummy stack frame. */
-#ifdef __powerpc64__
-		esp += 128;
+#ifdef POWERPC64
+		if (current_personality == 0)
+			esp += 128;
+		else
+			esp += 64;
 #else
 		esp += 64;
 #endif
diff --git a/syscall.c b/syscall.c
index ba2185c..467ac87 100644
--- a/syscall.c
+++ b/syscall.c
@@ -724,7 +724,7 @@ internal_syscall(struct tcb *tcp)
 #elif defined (IA64)
 	long r8, r10, psr;
 	long ia32 = 0;
-#elif defined (POWERPC)
+#elif defined (POWERPC) || defined (POWERPC64)
 	static long result,flags;
 #elif defined (M68K)
 	static long d0;
@@ -873,7 +873,7 @@ get_scno(struct tcb *tcp)
 			scno = (scno | tmp) & 0xff;
 		}
 	}
-# elif defined (POWERPC)
+# elif defined (POWERPC) || defined (POWERPC64)
 	if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
 		return -1;
 	if (!(tcp->flags & TCB_INSYSCALL)) {
@@ -883,6 +883,28 @@ get_scno(struct tcb *tcp)
 			return 0;
 		}
 	}
+
+#  ifdef POWERPC64
+	if (!(tcp->flags & TCB_INSYSCALL)) {
+		static int currpers = -1;
+		long val;
+		int pid = tcp->pid;
+
+		/* Check for 64/32 bit mode. */
+		if (upeek(tcp, sizeof (unsigned long)*PT_MSR, &val) < 0)
+			return -1;
+		if (val < 0)
+			currpers = 0;
+		else
+			currpers = 1;
+		if (currpers != current_personality) {
+			static const char *const names[] = {"64 bit", "32 bit"};
+			set_personality(currpers);
+			printf("[ Process PID=%d runs in %s mode. ]\n",
+					pid, names[current_personality]);
+		}
+#  endif
+	}
 # elif defined(AVR32)
 	/*
 	 * Read complete register set in one go.
@@ -1460,7 +1482,7 @@ syscall_fixup(struct tcb *tcp)
 		 */
 		gpr2 = 0;
 	}
-#elif defined (POWERPC)
+#elif defined (POWERPC) || defined (POWERPC64)
 # define SO_MASK 0x10000000
 	if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
 		return -1;
@@ -1588,7 +1610,7 @@ get_error(struct tcb *tcp)
 			tcp->u_rval = r2;
 			u_error = 0;
 		}
-# elif defined(POWERPC)
+# elif defined(POWERPC) || defined(POWERPC64)
 		if (is_negated_errno(result)) {
 			tcp->u_rval = -1;
 			u_error = -result;
@@ -1842,7 +1864,7 @@ force_result(tcp, error, rval)
 	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
 	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
 		return -1;
-# elif defined(POWERPC)
+# elif defined(POWERPC) || defined(POWERPC64)
 	if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
 		return -1;
 	if (error) {
@@ -2092,7 +2114,7 @@ syscall_enter(struct tcb *tcp)
 			}
 		}
 	}
-#elif defined (POWERPC)
+#elif defined (POWERPC) || defined (POWERPC64)
 # ifndef PT_ORIG_R3
 #  define PT_ORIG_R3 34
 # endif
diff --git a/util.c b/util.c
index bd12c0f..69d1e44 100644
--- a/util.c
+++ b/util.c
@@ -251,20 +251,24 @@ int
 printllval(struct tcb *tcp, const char *format, int llarg)
 {
 # if defined(FREEBSD) \
-     || (defined(LINUX) && defined(POWERPC) && !defined(__powerpc64__)) \
+     || (defined(LINUX) && defined(POWERPC)) \
      || defined (LINUX_MIPSO32)
 	/* Align 64bit argument to 64bit boundary.  */
 	if (llarg % 2) llarg++;
 # endif
-# if defined LINUX && defined X86_64
+# if defined LINUX && (defined X86_64 || defined POWERPC64)
 	if (current_personality == 0) {
 		tprintf(format, tcp->u_arg[llarg]);
 		llarg++;
 	} else {
+#  ifdef POWERPC64
+		/* Align 64bit argument to 64bit boundary.  */
+		if (llarg % 2) llarg++;
+#  endif
 		tprintf(format, LONG_LONG(tcp->u_arg[llarg], tcp->u_arg[llarg + 1]));
 		llarg += 2;
 	}
-# elif defined IA64 || defined ALPHA || (defined POWERPC && defined __powerpc64__)
+# elif defined IA64 || defined ALPHA
 	tprintf(format, tcp->u_arg[llarg]);
 	llarg++;
 # elif defined LINUX_MIPSN32
@@ -1106,14 +1110,18 @@ printcall(struct tcb *tcp)
 		return;
 	}
 	tprintf("[%08lx] ", ip);
-# elif defined(POWERPC)
+# elif defined(POWERPC) || defined(POWERPC64)
 	long pc;
 
 	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
-		tprintf ("[????????] ");
+		PRINTBADPC;
 		return;
 	}
+#  ifdef POWERPC64
+	tprintf("[%016lx] ", pc);
+#  else
 	tprintf("[%08lx] ", pc);
+#  endif
 # elif defined(M68K)
 	long pc;
 
@@ -1402,7 +1410,7 @@ typedef struct pt_regs arg_setup_state;
 #   elif defined (AVR32)
 #    define arg0_offset	(REG_R12)
 #    define arg1_offset	(REG_R11)
-#   elif defined (POWERPC)
+#   elif defined (POWERPC) || defined (POWERPC64)
 #    define arg0_offset	(sizeof(unsigned long)*PT_R3)
 #    define arg1_offset	(sizeof(unsigned long)*PT_R4)
 #    define restore_arg0(tcp, state, val) ((void) (state), 0)
-- 
1.7.1.1


-- 
Andreas Schwab, schwab at linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."




More information about the Strace-devel mailing list