[PATCH] Add support for Imagination Technologies Meta

James Hogan james.hogan at imgtec.com
Fri Feb 22 14:44:10 UTC 2013


Add support for Imagination Technologies Meta architecture (the
architecture/ABI is usually referred to as metag in code). The Meta
Linux kernel port is in the process of being upstreamed for v3.9 so it
uses generic system call numbers.

Signed-off-by: James Hogan <james.hogan at imgtec.com>
Cc: Christian Svensson <blue at cmd.nu>
---
I've pulled the -C -C options on git format-patch so that the
differences against or1k can be seen in the system call table (but can
regenerate a clean patch if required):
* sys_lookup_dcookie writes a filename to buffer argument, so I've set
  TF flag
* nfsservctl appears to be set to sys_ni_syscall in asm-generic/unistd.h
  so I've left it blank
* truncate64/ftruncate64/pread64/pwrite64/readahead have unaligned 64bit
  args which are packed tightly on metag, so less arguments on metag
* fchdir/llseek takes a file descriptor so s/TF/TD/
* sync_file_range has 2 64bit args so uses 6 args, so s/4/6/
* timerfd_create/msgget/msgctl/msgrcv/semget/segtimedop/semop/shmget/
  shmctl/shmat/shmdt/recvmsg/migrate_pages have different number of args
* oldgetrlimit is just getrlimit for metag
* add TM flag to various memory syscalls
* metag doesn't directly use sys_mmap_pgoff for mmap2
* prlimit64/process_vm_readv/process_vm_writev take a pid so add TP flag
* fanotify_init doesn't appear to take a file descriptor so remove TD
* add kcmp syscall

 configure.ac                       |   4 ++
 defs.h                             |   4 +-
 linux/{arm => metag}/ioctlent.h.in |   0
 linux/{or1k => metag}/syscallent.h | 103 +++++++++++++++++++------------------
 process.c                          |   2 +
 syscall.c                          |  32 ++++++++++++
 util.c                             |   3 ++
 7 files changed, 97 insertions(+), 51 deletions(-)
 copy linux/{arm => metag}/ioctlent.h.in (100%)
 copy linux/{or1k => metag}/syscallent.h (80%)

diff --git a/configure.ac b/configure.ac
index 8703f7c..09056a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,6 +37,10 @@ sparc*)
 	arch=sparc
 	AC_DEFINE([SPARC], 1, [Define for the SPARC architecture.])
 	;;
+metag*)
+	arch=metag
+	AC_DEFINE([METAG], 1, [Define for the Meta architecture.])
+	;;
 mips*)
 	arch=mips
 	AC_DEFINE([MIPS], 1, [Define for the MIPS architecture.])
diff --git a/defs.h b/defs.h
index 3562079..d860382 100644
--- a/defs.h
+++ b/defs.h
@@ -142,6 +142,7 @@ extern char *stpcpy(char *dst, const char *src);
     || defined(ARM) || defined(AARCH64) \
     || defined(AVR32) \
     || defined(OR1K) \
+    || defined(METAG) \
     ) && defined(__GLIBC__)
 # include <sys/ptrace.h>
 #else
@@ -579,7 +580,8 @@ extern void call_summary(FILE *);
  || defined(ARM) \
  || defined(SPARC) || defined(SPARC64) \
  || defined(TILE) \
- || defined(OR1K)
+ || defined(OR1K) \
+ || defined(METAG)
 extern long get_regs_error;
 # define clear_regs()  (get_regs_error = -1)
 extern void get_regs(pid_t pid);
diff --git a/linux/arm/ioctlent.h.in b/linux/metag/ioctlent.h.in
similarity index 100%
copy from linux/arm/ioctlent.h.in
copy to linux/metag/ioctlent.h.in
diff --git a/linux/or1k/syscallent.h b/linux/metag/syscallent.h
similarity index 80%
copy from linux/or1k/syscallent.h
copy to linux/metag/syscallent.h
index 3e7613f..38300ea 100644
--- a/linux/or1k/syscallent.h
+++ b/linux/metag/syscallent.h
@@ -16,7 +16,7 @@
 	{  2,	TF,	sys_removexattr,		"lremovexattr"		}, /* 15 */
 	{  2,	TD,	sys_fremovexattr,		"fremovexattr"		}, /* 16 */
 	{  2,	TF,	sys_getcwd,			"getcwd"		}, /* 17 */
-	{  4,	0,	sys_lookup_dcookie,		"lookup_dcookie"	}, /* 18 */
+	{  4,	TF,	sys_lookup_dcookie,		"lookup_dcookie"	}, /* 18 */
 	{  2,	TD,	sys_eventfd2,			"eventfd2"		}, /* 19 */
 	{  1,	TD,	sys_epoll_create1,		"epoll_create1"		}, /* 20 */
 	{  4,	TD,	sys_epoll_ctl,			"epoll_ctl"		}, /* 21 */
@@ -40,15 +40,15 @@
 	{  2,	TF,	sys_umount2,			"umount"		}, /* 39 */
 	{  5,	TF,	sys_mount,			"mount"			}, /* 40 */
 	{  2,	TF,	sys_pivotroot,			"pivot_root"		}, /* 41 */
-	{  3,	0,	sys_nfsservctl,			"nfsservctl"		}, /* 42 */
+	{									}, /* 42 */
 	{  3,	TF,	sys_statfs64,			"statfs64"		}, /* 43 */
 	{  3,	TD,	sys_fstatfs64,			"fstatfs64"		}, /* 44 */
-	{  4,	TF,	sys_truncate64,			"truncate64"		}, /* 45 */
-	{  4,	TD,	sys_ftruncate64,		"ftruncate64"		}, /* 46 */
+	{  3,	TF,	sys_truncate64,			"truncate64"		}, /* 45 */
+	{  3,	TD,	sys_ftruncate64,		"ftruncate64"		}, /* 46 */
 	{  6,	TD,	sys_fallocate,			"fallocate"		}, /* 47 */
 	{  3,	TD|TF,	sys_faccessat,			"faccessat"		}, /* 48 */
 	{  1,	TF,	sys_chdir,			"chdir"			}, /* 49 */
-	{  1,	TF,	sys_fchdir,			"fchdir"		}, /* 50 */
+	{  1,	TD,	sys_fchdir,			"fchdir"		}, /* 50 */
 	{  1,	TF,	sys_chroot,			"chroot"		}, /* 51 */
 	{  2,	TD,	sys_fchmod,			"fchmod"		}, /* 52 */
 	{  3,	TD|TF,	sys_fchmodat,			"fchmodat"		}, /* 53 */
@@ -60,13 +60,13 @@
 	{  2,	TD,	sys_pipe2,			"pipe2"			}, /* 59 */
 	{  4,	0,	sys_quotactl,			"quotactl"		}, /* 60 */
 	{  3,	TD,	sys_getdents64,			"getdents64"		}, /* 61 */
-	{  5,	TF,	sys_llseek,			"_llseek"		}, /* 62 */
+	{  5,	TD,	sys_llseek,			"llseek"		}, /* 62 */
 	{  3,	TD,	sys_read,			"read"			}, /* 63 */
 	{  3,	TD,	sys_write,			"write"			}, /* 64 */
 	{  3,	TD,	sys_readv,			"readv"			}, /* 65 */
 	{  3,	TD,	sys_writev,			"writev"		}, /* 66 */
-	{  6,	TD,	sys_pread,			"pread64"		}, /* 67 */
-	{  6,	TD,	sys_pwrite,			"pwrite64"		}, /* 68 */
+	{  5,	TD,	sys_pread,			"pread64"		}, /* 67 */
+	{  5,	TD,	sys_pwrite,			"pwrite64"		}, /* 68 */
 	{  5,	TD,	sys_preadv,			"preadv"		}, /* 69 */
 	{  5,	TD,	sys_pwritev,			"pwritev"		}, /* 70 */
 	{  4,	TD|TN,	sys_sendfile64,			"sendfile64"		}, /* 71 */
@@ -82,8 +82,8 @@
 	{  0,	0,	sys_sync,			"sync"			}, /* 81 */
 	{  1,	TD,	sys_fsync,			"fsync"			}, /* 82 */
 	{  1,	TD,	sys_fdatasync,			"fdatasync"		}, /* 83 */
-	{  4,	TD,	sys_sync_file_range,		"sync_file_range"	}, /* 84 */
-	{  4,	TD,	sys_timerfd_create,		"timerfd_create"	}, /* 85 */
+	{  6,	TD,	sys_sync_file_range,		"sync_file_range"	}, /* 84 */
+	{  2,	TD,	sys_timerfd_create,		"timerfd_create"	}, /* 85 */
 	{  4,	TD,	sys_timerfd_settime,		"timerfd_settime"	}, /* 86 */
 	{  2,	TD,	sys_timerfd_gettime,		"timerfd_gettime"	}, /* 87 */
 	{  4,	TD|TF,	sys_utimensat,			"utimensat"		}, /* 88 */
@@ -125,7 +125,7 @@
 	{  0,	0,	sys_sched_yield,		"sched_yield"		}, /* 124 */
 	{  1,	0,	sys_sched_get_priority_max,	"sched_get_priority_max"}, /* 125 */
 	{  1,	0,	sys_sched_get_priority_min,	"sched_get_priority_min"}, /* 126 */
-	{  2,	0,	sys_sched_rr_get_interval,	"sched_rr_get_interval" }, /* 127 */
+	{  2,	0,	sys_sched_rr_get_interval,	"sched_rr_get_interval"	}, /* 127 */
 	{  0,	0,	sys_restart_syscall,		"restart_syscall"	}, /* 128 */
 	{  2,	TS,	sys_kill,			"kill"			}, /* 129 */
 	{  2,	TS,	sys_kill,			"tkill"			}, /* 130 */
@@ -161,7 +161,7 @@
 	{  1,	0,	sys_uname,			"uname"			}, /* 160 */
 	{  2,	0,	sys_sethostname,		"sethostname"		}, /* 161 */
 	{  2,	0,	sys_setdomainname,		"setdomainname"		}, /* 162 */
-	{  2,	0,	sys_getrlimit,			"oldgetrlimit"		}, /* 163 */
+	{  2,	0,	sys_getrlimit,			"getrlimit"		}, /* 163 */
 	{  2,	0,	sys_setrlimit,			"setrlimit"		}, /* 164 */
 	{  2,	0,	sys_getrusage,			"getrusage"		}, /* 165 */
 	{  1,	0,	sys_umask,			"umask"			}, /* 166 */
@@ -184,18 +184,18 @@
 	{  5,	0,	sys_mq_timedreceive,		"mq_timedreceive"	}, /* 183 */
 	{  2,	0,	sys_mq_notify,			"mq_notify"		}, /* 184 */
 	{  3,	0,	sys_mq_getsetattr,		"mq_getsetattr"		}, /* 185 */
-	{  4,	TI,	sys_msgget,			"msgget"		}, /* 186 */
-	{  4,	TI,	sys_msgctl,			"msgctl"		}, /* 187 */
-	{  4,	TI,	sys_msgrcv,			"msgrcv"		}, /* 188 */
+	{  2,	TI,	sys_msgget,			"msgget"		}, /* 186 */
+	{  3,	TI,	sys_msgctl,			"msgctl"		}, /* 187 */
+	{  5,	TI,	sys_msgrcv,			"msgrcv"		}, /* 188 */
 	{  4,	TI,	sys_msgsnd,			"msgsnd"		}, /* 189 */
-	{  4,	TI,	sys_semget,			"semget"		}, /* 190 */
+	{  3,	TI,	sys_semget,			"semget"		}, /* 190 */
 	{  4,	TI,	sys_semctl,			"semctl"		}, /* 191 */
-	{  5,	TI,	sys_semtimedop,			"semtimedop"		}, /* 192 */
-	{  4,	TI,	sys_semop,			"semop"			}, /* 193 */
-	{  4,	TI,	sys_shmget,			"shmget"		}, /* 194 */
-	{  4,	TI,	sys_shmctl,			"shmctl"		}, /* 195 */
-	{  4,	TI,	sys_shmat,			"shmat"			}, /* 196 */
-	{  4,	TI,	sys_shmdt,			"shmdt"			}, /* 197 */
+	{  4,	TI,	sys_semtimedop,			"semtimedop"		}, /* 192 */
+	{  3,	TI,	sys_semop,			"semop"			}, /* 193 */
+	{  3,	TI,	sys_shmget,			"shmget"		}, /* 194 */
+	{  3,	TI,	sys_shmctl,			"shmctl"		}, /* 195 */
+	{  3,	TI,	sys_shmat,			"shmat"			}, /* 196 */
+	{  1,	TI,	sys_shmdt,			"shmdt"			}, /* 197 */
 	{  3,	TN,	sys_socket,			"socket"		}, /* 198 */
 	{  4,	TN,	sys_socketpair,			"socketpair"		}, /* 199 */
 	{  3,	TN,	sys_bind,			"bind"			}, /* 200 */
@@ -210,45 +210,47 @@
 	{  5,	TN,	sys_getsockopt,			"getsockopt"		}, /* 209 */
 	{  2,	TN,	sys_shutdown,			"shutdown"		}, /* 210 */
 	{  3,	TN,	sys_sendmsg,			"sendmsg"		}, /* 211 */
-	{  5,	TN,	sys_recvmsg,			"recvmsg"		}, /* 212 */
-	{  5,	TD,	sys_readahead,			"readahead"		}, /* 213 */
-	{  1,	0,	sys_brk,			"brk"			}, /* 214 */
-	{  2,	0,	sys_munmap,			"munmap"		}, /* 215 */
-	{  5,	0,	sys_mremap,			"mremap"		}, /* 216 */
+	{  3,	TN,	sys_recvmsg,			"recvmsg"		}, /* 212 */
+	{  4,	TD,	sys_readahead,			"readahead"		}, /* 213 */
+	{  1,	TM,	sys_brk,			"brk"			}, /* 214 */
+	{  2,	TM,	sys_munmap,			"munmap"		}, /* 215 */
+	{  5,	TM,	sys_mremap,			"mremap"		}, /* 216 */
 	{  5,	0,	sys_add_key,			"add_key"		}, /* 217 */
 	{  4,	0,	sys_request_key,		"request_key"		}, /* 218 */
 	{  5,	0,	sys_keyctl,			"keyctl"		}, /* 219 */
 	{  5,	TP,	sys_clone,			"clone"			}, /* 220 */
 	{  3,	TF|TP,	sys_execve,			"execve"		}, /* 221 */
-	{  6,	TD|TM,	sys_mmap_pgoff,			"mmap2"			}, /* 222 */
+	{  6,	TD|TM,	sys_mmap,			"mmap2"			}, /* 222 */
 	{  6,	TD,	sys_fadvise64_64,		"fadvise64_64"		}, /* 223 */
 	{  2,	TF,	sys_swapon,			"swapon"		}, /* 224 */
 	{  1,	TF,	sys_swapoff,			"swapoff"		}, /* 225 */
-	{  3,	0,	sys_mprotect,			"mprotect"		}, /* 226 */
-	{  3,	0,	sys_msync,			"msync"			}, /* 227 */
-	{  2,	0,	sys_mlock,			"mlock"			}, /* 228 */
-	{  2,	0,	sys_munlock,			"munlock"		}, /* 229 */
-	{  1,	0,	sys_mlockall,			"mlockall"		}, /* 230 */
-	{  0,	0,	sys_munlockall,			"munlockall"		}, /* 231 */
-	{  3,	0,	sys_mincore,			"mincore"		}, /* 232 */
-	{  3,	0,	sys_madvise,			"madvise"		}, /* 233 */
-	{  5,	0,	sys_remap_file_pages,		"remap_file_pages"	}, /* 234 */
-	{  6,	0,	sys_mbind,			"mbind"			}, /* 235 */
-	{  5,	0,	sys_get_mempolicy,		"get_mempolicy"		}, /* 236 */
-	{  3,	0,	sys_set_mempolicy,		"set_mempolicy"		}, /* 237 */
-	{  5,	0,	sys_migrate_pages,		"migrate_pages"		}, /* 238 */
-	{  6,	0,	sys_move_pages,			"move_pages"		}, /* 239 */
+	{  3,	TM,	sys_mprotect,			"mprotect"		}, /* 226 */
+	{  3,	TM,	sys_msync,			"msync"			}, /* 227 */
+	{  2,	TM,	sys_mlock,			"mlock"			}, /* 228 */
+	{  2,	TM,	sys_munlock,			"munlock"		}, /* 229 */
+	{  1,	TM,	sys_mlockall,			"mlockall"		}, /* 230 */
+	{  0,	TM,	sys_munlockall,			"munlockall"		}, /* 231 */
+	{  3,	TM,	sys_mincore,			"mincore"		}, /* 232 */
+	{  3,	TM,	sys_madvise,			"madvise"		}, /* 233 */
+	{  5,	TM,	sys_remap_file_pages,		"remap_file_pages"	}, /* 234 */
+	{  6,	TM,	sys_mbind,			"mbind"			}, /* 235 */
+	{  5,	TM,	sys_get_mempolicy,		"get_mempolicy"		}, /* 236 */
+	{  3,	TM,	sys_set_mempolicy,		"set_mempolicy"		}, /* 237 */
+	{  4,	TM,	sys_migrate_pages,		"migrate_pages"		}, /* 238 */
+	{  6,	TM,	sys_move_pages,			"move_pages"		}, /* 239 */
 	{  4,	TP|TS,	sys_rt_tgsigqueueinfo,		"rt_tgsigqueueinfo"	}, /* 240 */
 	{  5,	TD,	sys_perf_event_open,		"perf_event_open"	}, /* 241 */
 	{  4,	TN,	sys_accept4,			"accept4"		}, /* 242 */
 	{  5,	TN,	sys_recvmmsg,			"recvmmsg"		}, /* 243 */
-	{  6,	NF,	sys_or1k_atomic,		"or1k_atomic"		}, /* 244 */
-
-	[245 ... 259] = { },
-
+	{									}, /* 244 */
+	{  2,	0,	printargs,			"metag_setglobalbit"	}, /* 245 */
+	{  1,	0,	printargs,			"metag_set_fpu_flags"	}, /* 246 */
+	{  1,	0,	printargs,			"metag_set_tls"		}, /* 247 */
+	{  0,	0,	printargs,			"metag_get_tls"		}, /* 248 */
+	[249 ... 259] = { },
 	{  4,	TP,	sys_wait4,			"wait4"			}, /* 260 */
-	{  4,	0,	sys_prlimit64,			"prlimit64"		}, /* 261 */
-	{  2,	TD,	sys_fanotify_init,		"fanotify_init"		}, /* 262 */
+	{  4,	TP,	sys_prlimit64,			"prlimit64"		}, /* 261 */
+	{  2,	0,	sys_fanotify_init,		"fanotify_init"		}, /* 262 */
 	{  5,	TD|TF,	sys_fanotify_mark,		"fanotify_mark"		}, /* 263 */
 	{  5,	TD|TF,	sys_name_to_handle_at,		"name_to_handle_at"	}, /* 264 */
 	{  3,	TD,	sys_open_by_handle_at,		"open_by_handle_at"	}, /* 265 */
@@ -256,5 +258,6 @@
 	{  1,	TD,	sys_syncfs,			"syncfs"		}, /* 267 */
 	{  2,	TD,	sys_setns,			"setns"			}, /* 268 */
 	{  4,	TN,	sys_sendmmsg,			"sendmmsg"		}, /* 269 */
-	{  6,	0,	sys_process_vm_readv,		"process_vm_readv"	}, /* 270 */
-	{  6,	0,	sys_process_vm_writev,		"process_vm_writev"	}, /* 271 */
+	{  6,	TP,	sys_process_vm_readv,		"process_vm_readv"	}, /* 270 */
+	{  6,	TP,	sys_process_vm_writev,		"process_vm_writev"	}, /* 271 */
+	{  5,	TP,	printargs,			"kcmp"			}, /* 272 */
diff --git a/process.c b/process.c
index a1f963e..617b78d 100644
--- a/process.c
+++ b/process.c
@@ -2277,6 +2277,8 @@ const struct xlat struct_user_offsets[] = {
 	{ sizeof(struct user),	"sizeof(struct user)"			},
 #elif defined(OR1K)
 	/* nothing */
+#elif defined(METAG)
+	/* nothing */
 #endif
 	{ 0,			NULL					},
 };
diff --git a/syscall.c b/syscall.c
index 5fce9d8..c35ba57 100644
--- a/syscall.c
+++ b/syscall.c
@@ -82,6 +82,11 @@
 # include <elf.h>
 #endif
 
+#if defined(METAG)
+# include <sys/uio.h>
+# include <elf.h>
+#endif
+
 #ifndef ERESTARTSYS
 # define ERESTARTSYS	512
 #endif
@@ -756,6 +761,11 @@ static struct user_regs_struct or1k_regs;
 static struct iovec or1k_io = {
 	.iov_base = &or1k_regs
 };
+#elif defined(METAG)
+static struct user_gp_regs metag_regs;
+static struct iovec metag_io = {
+	.iov_base = &metag_regs
+};
 #endif
 
 void
@@ -891,6 +901,8 @@ printcall(struct tcb *tcp)
 # endif
 #elif defined(OR1K)
 	tprintf("[%08lx] ", or1k_regs.pc);
+#elif defined(METAG)
+	tprintf("[%08lx] ", metag_regs.pc);
 #endif /* architecture */
 }
 
@@ -1015,6 +1027,9 @@ get_regs(pid_t pid)
 # elif defined(OR1K)
 	or1k_io.iov_len = sizeof(or1k_regs);
 	get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
+# elif defined(METAG)
+	metag_io.iov_len = sizeof(metag_regs);
+	get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &metag_io);
 # endif
 }
 #endif
@@ -1445,6 +1460,8 @@ get_scno(struct tcb *tcp)
 		return -1;
 #elif defined(OR1K)
 	scno = or1k_regs.gpr[11];
+#elif defined(METAG)
+	scno = metag_regs.dx[0][1];	/* syscall number in D1Re0 (D1.0) */
 #endif
 
 	tcp->scno = scno;
@@ -1841,6 +1858,10 @@ get_syscall_args(struct tcb *tcp)
 	(void)nargs;
 	for (i = 0; i < 6; ++i)
 		tcp->u_arg[i] = or1k_regs.gpr[3 + i];
+#elif defined(METAG)
+	for (i = 0; i < nargs; i++)
+		/* arguments go backwards from D1Ar1 (D1.3) */
+		tcp->u_arg[i] = ((unsigned long *)&metag_regs.dx[3][1])[-i];
 #else /* Other architecture (32bits specific) */
 	for (i = 0; i < nargs; ++i)
 		if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
@@ -2035,6 +2056,8 @@ get_syscall_result(struct tcb *tcp)
 		return -1;
 #elif defined(OR1K)
 	/* already done by get_regs */
+#elif defined(METAG)
+	/* already done by get_regs */
 #endif
 	return 1;
 }
@@ -2288,6 +2311,15 @@ get_error(struct tcb *tcp)
 	else {
 		tcp->u_rval = sh64_r9;
 	}
+#elif defined(METAG)
+	/* result pointer in D0Re0 (D0.0) */
+	if (check_errno && is_negated_errno(metag_regs.dx[0][0])) {
+		tcp->u_rval = -1;
+		u_error = -metag_regs.dx[0][0];
+	}
+	else {
+		tcp->u_rval = metag_regs.dx[0][0];
+	}
 #elif defined(CRISV10) || defined(CRISV32)
 	if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
 		tcp->u_rval = -1;
diff --git a/util.c b/util.c
index 4c22c5f..d8d35bf 100644
--- a/util.c
+++ b/util.c
@@ -1301,6 +1301,9 @@ change_syscall(struct tcb *tcp, arg_setup_state *state, int new)
 	/* microblaze is only supported since about linux-2.6.30 */
 #elif defined(OR1K)
 	/* never reached; OR1K is only supported by kernels since 3.1.0. */
+#elif defined(METAG)
+	/* setbpt/clearbpt never used: */
+	/* Meta is only supported since linux-3.7 */
 #else
 #warning Do not know how to handle change_syscall for this architecture
 #endif /* architecture */
-- 
1.8.1.2






More information about the Strace-devel mailing list