AArch64: Add support for AArch64 to the syscall interface
This patch adds support for AArch64 to the syscall interface. The kernel
implementation exports a set of canonical syscalls, therefore some of
the userspace exported syscalls are implemented as stubs based on the
canonical set.
Change-Id: Ia965d71e97769b8be9d7655193fc40303964c4df
Signed-off-by: Serban Constantinescu <serban.constantinescu@arm.com>
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index ca1784f..f31073f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -6,7 +6,7 @@
#
# where:
# arch_list ::= "all" | arch+
-# arch ::= "arm" | "mips" | "x86" | "x86_64"
+# arch ::= "aarch64" | "arm" | "mips" | "x86" | "x86_64"
#
# Note:
# - syscall_name corresponds to the name of the syscall, which may differ from
@@ -27,54 +27,54 @@
int execve(const char*, char* const*, char* const*) all
uid_t getuid:getuid32() arm,x86
-uid_t getuid:getuid() mips,x86_64
+uid_t getuid:getuid() aarch64,mips,x86_64
gid_t getgid:getgid32() arm,x86
-gid_t getgid:getgid() mips,x86_64
+gid_t getgid:getgid() aarch64,mips,x86_64
uid_t geteuid:geteuid32() arm,x86
-uid_t geteuid:geteuid() mips,x86_64
+uid_t geteuid:geteuid() aarch64,mips,x86_64
gid_t getegid:getegid32() arm,x86
-gid_t getegid:getegid() mips,x86_64
+gid_t getegid:getegid() aarch64,mips,x86_64
uid_t getresuid:getresuid32(uid_t* ruid, uid_t* euid, uid_t* suid) arm,x86
-uid_t getresuid:getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) mips,x86_64
+uid_t getresuid:getresuid(uid_t* ruid, uid_t* euid, uid_t* suid) aarch64,mips,x86_64
gid_t getresgid:getresgid32(gid_t* rgid, gid_t* egid, gid_t* sgid) arm,x86
-gid_t getresgid:getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) mips,x86_64
+gid_t getresgid:getresgid(gid_t* rgid, gid_t* egid, gid_t* sgid) aarch64,mips,x86_64
pid_t gettid() all
ssize_t readahead(int, off64_t, size_t) all
int getgroups:getgroups32(int, gid_t*) arm,x86
-int getgroups:getgroups(int, gid_t*) mips,x86_64
+int getgroups:getgroups(int, gid_t*) aarch64,mips,x86_64
pid_t getpgid(pid_t) all
pid_t getppid() all
pid_t getsid(pid_t) all
pid_t setsid() all
int setgid:setgid32(gid_t) arm,x86
-int setgid:setgid(gid_t) mips,x86_64
+int setgid:setgid(gid_t) aarch64,mips,x86_64
int setuid:setuid32(uid_t) arm,x86
-int setuid:setuid(uid_t) mips,x86_64
+int setuid:setuid(uid_t) aarch64,mips,x86_64
int setreuid:setreuid32(uid_t, uid_t) arm,x86
-int setreuid:setreuid(uid_t, uid_t) mips,x86_64
+int setreuid:setreuid(uid_t, uid_t) aarch64,mips,x86_64
int setresuid:setresuid32(uid_t, uid_t, uid_t) arm,x86
-int setresuid:setresuid(uid_t, uid_t, uid_t) mips,x86_64
+int setresuid:setresuid(uid_t, uid_t, uid_t) aarch64,mips,x86_64
int setresgid:setresgid32(gid_t, gid_t, gid_t) arm,x86
-int setresgid:setresgid(gid_t, gid_t, gid_t) mips,x86_64
+int setresgid:setresgid(gid_t, gid_t, gid_t) aarch64,mips,x86_64
void* __brk:brk(void*) all
# See comments in kill.S to understand why we don't generate ARM stubs for kill/tkill/tgkill.
-int kill(pid_t, int) mips,x86,x86_64
-int tkill(pid_t tid, int sig) mips,x86,x86_64
-int tgkill(pid_t tgid, pid_t tid, int sig) mips,x86,x86_64
+int kill(pid_t, int) aarch64,mips,x86,x86_64
+int tkill(pid_t tid, int sig) aarch64,mips,x86,x86_64
+int tgkill(pid_t tgid, pid_t tid, int sig) aarch64,mips,x86,x86_64
int __ptrace:ptrace(int request, int pid, void* addr, void* data) all
int __set_thread_area:set_thread_area(void* user_desc) mips,x86
int __getpriority:getpriority(int, int) all
int setpriority(int, int, int) all
int setrlimit(int resource, const struct rlimit* rlp) all
int getrlimit:ugetrlimit(int resource, struct rlimit* rlp) arm,x86
-int getrlimit:getrlimit(int resource, struct rlimit* rlp) mips,x86_64
+int getrlimit:getrlimit(int resource, struct rlimit* rlp) aarch64,mips,x86_64
int getrusage(int who, struct rusage* r_usage) all
int setgroups:setgroups32(int, const gid_t*) arm,x86
-int setgroups:setgroups(int, const gid_t*) mips,x86_64
+int setgroups:setgroups(int, const gid_t*) aarch64,mips,x86_64
int setpgid(pid_t, pid_t) all
pid_t vfork(void) arm
int setregid:setregid32(gid_t, gid_t) arm,x86
-int setregid:setregid(gid_t, gid_t) mips,x86_64
+int setregid:setregid(gid_t, gid_t) aarch64,mips,x86_64
int chroot(const char*) all
# IMPORTANT: Even though <sys/prctl.h> declares prctl(int, ...), the syscall stub must take 6 arguments
# to match the kernel implementation.
@@ -92,8 +92,8 @@
ssize_t pwrite64(int, void*, size_t, off64_t) all
int close(int) all
pid_t getpid() all
-void* mmap(void*, size_t, int, int, int, long) x86_64
-void* __mmap2:mmap2(void*, size_t, int, int, int, long) arm,x86,mips
+void* mmap(void*, size_t, int, int, int, long) aarch64,x86_64
+void* __mmap2:mmap2(void*, size_t, int, int, int, long) arm,mips,x86
int munmap(void*, size_t) all
void* mremap(void*, size_t, size_t, unsigned long) all
int msync(const void*, size_t, int) all
@@ -107,8 +107,8 @@
int __ioctl:ioctl(int, int, void*) all
int readv(int, const struct iovec*, int) all
int writev(int, const struct iovec*, int) all
-int __fcntl:fcntl(int, int, void*) arm,x86,mips
-int fcntl(int, void*) x86_64
+int __fcntl:fcntl(int, int, void*) arm,mips,x86
+int fcntl(int, void*) aarch64,x86_64
int flock(int, int) all
int fchmod(int, mode_t) all
int dup(int) all
@@ -118,11 +118,11 @@
int fsync(int) all
int fdatasync(int) all
int fchown:fchown32(int, uid_t, gid_t) arm,x86
-int fchown:fchown(int, uid_t, gid_t) mips,x86_64
+int fchown:fchown(int, uid_t, gid_t) aarch64,mips,x86_64
void sync(void) all
-int __fcntl64:fcntl64(int, int, void*) arm,x86,mips
-int __fstatfs64:fstatfs64(int, size_t, struct statfs*) arm,x86,mips
-int fstatfs(int, struct statfs*) x86_64
+int __fcntl64:fcntl64(int, int, void*) arm,mips,x86
+int __fstatfs64:fstatfs64(int, size_t, struct statfs*) arm,mips,x86
+int fstatfs(int, struct statfs*) aarch64,x86_64
int fsetxattr(int, const char*, const void*, size_t, int) all
ssize_t fgetxattr(int, const char*, void*, size_t) all
ssize_t flistxattr(int, char*, size_t) all
@@ -132,8 +132,8 @@
int faccessat(int, const char*, int, int) all
int fchmodat(int, const char*, mode_t, int) all
int fchownat(int, const char*, uid_t, gid_t, int) all
-int fstatat:fstatat64(int, const char*, struct stat*, int) arm,x86,mips
-int fstatat:newfstatat(int, const char*, struct stat*, int) x86_64
+int fstatat:fstatat64(int, const char*, struct stat*, int) arm,mips,x86
+int fstatat:newfstatat(int, const char*, struct stat*, int) aarch64,x86_64
int linkat(int, const char*, int, const char*, int) all
int mkdirat(int, const char*, mode_t) all
int mknodat(int, const char*, mode_t, dev_t) all
@@ -149,23 +149,23 @@
# That means that every system call in this section should take three lines.
off_t lseek(int, off_t, int) arm,mips,x86
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
-off_t lseek|lseek64(int, off_t, int) x86_64
+off_t lseek|lseek64(int, off_t, int) aarch64,x86_64
int ftruncate(int, off_t) arm,mips,x86
int ftruncate64(int, off64_t) arm,mips,x86
-int ftruncate|ftruncate64(int, off_t) x86_64
+int ftruncate|ftruncate64(int, off_t) aarch64,x86_64
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) arm,mips,x86
-ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) x86_64
+ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) aarch64,x86_64
int truncate(const char*, off_t) arm,mips,x86
int truncate64(const char*, off64_t) arm,mips,x86
-int truncate|truncate64(const char*, off_t) x86_64
+int truncate|truncate64(const char*, off_t) aarch64,x86_64
# file system
int chdir(const char*) all
int mount(const char*, const char*, const char*, unsigned long, const void*) all
int umount2(const char*, int) all
-int fstat:fstat64(int, struct stat*) arm,x86,mips
-int fstat(int, struct stat*) x86_64
+int fstat:fstat64(int, struct stat*) arm,mips,x86
+int fstat(int, struct stat*) aarch64,x86_64
int __getcwd:getcwd(char* buf, size_t size) all
int fchdir(int) all
int setxattr(const char*, const char*, const void*, size_t, int) all
@@ -176,8 +176,8 @@
ssize_t llistxattr(const char*, char*, size_t) all
int removexattr(const char*, const char*) all
int lremovexattr(const char*, const char*) all
-int __statfs64:statfs64(const char*, size_t, struct statfs*) arm,x86,mips
-int statfs(const char*, struct statfs*) x86_64
+int __statfs64:statfs64(const char*, size_t, struct statfs*) arm,mips,x86
+int statfs(const char*, struct statfs*) aarch64,x86_64
long unshare(unsigned long) all
int swapon(const char*, int) all
int swapoff(const char*) all
@@ -212,21 +212,21 @@
int signalfd4(int, const sigset_t*, size_t, int) all
# sockets
-int socket(int, int, int) arm,mips,x86_64
-int socketpair(int, int, int, int*) arm,mips,x86_64
-int bind(int, struct sockaddr*, int) arm,mips,x86_64
-int connect(int, struct sockaddr*, socklen_t) arm,mips,x86_64
-int listen(int, int) arm,mips,x86_64
-int accept(int, struct sockaddr*, socklen_t*) arm,mips,x86_64
-int getsockname(int, struct sockaddr*, socklen_t*) arm,mips,x86_64
-int getpeername(int, struct sockaddr*, socklen_t*) arm,mips,x86_64
-int sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,mips,x86_64
-int recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) arm,mips,x86_64
-int shutdown(int, int) arm,mips,x86_64
-int setsockopt(int, int, int, const void*, socklen_t) arm,mips,x86_64
-int getsockopt(int, int, int, void*, socklen_t*) arm,mips,x86_64
-int sendmsg(int, const struct msghdr*, unsigned int) arm,mips,x86_64
-int recvmsg(int, struct msghdr*, unsigned int) arm,mips,x86_64
+int socket(int, int, int) aarch64,arm,mips,x86_64
+int socketpair(int, int, int, int*) aarch64,arm,mips,x86_64
+int bind(int, struct sockaddr*, int) aarch64,arm,mips,x86_64
+int connect(int, struct sockaddr*, socklen_t) aarch64,arm,mips,x86_64
+int listen(int, int) aarch64,arm,mips,x86_64
+int accept(int, struct sockaddr*, socklen_t*) aarch64,arm,mips,x86_64
+int getsockname(int, struct sockaddr*, socklen_t*) aarch64,arm,mips,x86_64
+int getpeername(int, struct sockaddr*, socklen_t*) aarch64,arm,mips,x86_64
+int sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) aarch64,arm,mips,x86_64
+int recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) aarch64,arm,mips,x86_64
+int shutdown(int, int) aarch64,arm,mips,x86_64
+int setsockopt(int, int, int, const void*, socklen_t) aarch64,arm,mips,x86_64
+int getsockopt(int, int, int, void*, socklen_t*) aarch64,arm,mips,x86_64
+int sendmsg(int, const struct msghdr*, unsigned int) aarch64,arm,mips,x86_64
+int recvmsg(int, struct msghdr*, unsigned int) aarch64,arm,mips,x86_64
# sockets for x86. These are done as an "indexed" call to socketcall syscall.
int socket:socketcall:1(int, int, int) x86
diff --git a/libc/tools/bionic_utils.py b/libc/tools/bionic_utils.py
index f8d8897..39dc76a 100644
--- a/libc/tools/bionic_utils.py
+++ b/libc/tools/bionic_utils.py
@@ -2,7 +2,7 @@
import sys, os, commands, string
-all_arches = [ "arm", "mips", "x86", "x86_64" ]
+all_arches = [ "aarch64", "arm", "mips", "x86", "x86_64" ]
# basic debugging trace support
# call D_setlevel to set the verbosity level
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 5595cd7..bf44b70 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -56,6 +56,29 @@
#
+# AArch64 assembler templates for each syscall stub
+#
+
+aarch64_call = syscall_stub_header + """\
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+ str x8, [sp, #-16]!
+
+ mov x8, %(__NR_name)s
+ svc #0
+
+ ldr x8, [sp], #16
+ ldp x29, x30, [sp], #16
+
+ cmn x0, #(MAX_ERRNO + 1)
+ cneg x0, x0, hi
+ b.hi __set_errno
+
+ ret
+END(%(func)s)
+"""
+
+#
# ARM assembler templates for each syscall stub
#
@@ -246,6 +269,10 @@
return stub
+def aarch64_genstub(syscall):
+ return aarch64_call % syscall
+
+
def arm_eabi_genstub(syscall):
num_regs = count_arm_param_registers(syscall["params"])
if num_regs > 4:
@@ -277,6 +304,7 @@
result += x86_return % syscall
return result
+
def x86_genstub_socketcall(syscall):
# %ebx <--- Argument 1 - The call id of the needed vectored
# syscall (socket, bind, recv, etc)
@@ -339,6 +367,9 @@
for syscall in self.syscalls:
syscall["__NR_name"] = make__NR_name(syscall["name"])
+ if syscall.has_key("aarch64"):
+ syscall["asm-aarch64"] = add_footer(64, aarch64_genstub(syscall), syscall)
+
if syscall.has_key("arm"):
syscall["asm-arm"] = add_footer(32, arm_eabi_genstub(syscall), syscall)
@@ -357,7 +388,6 @@
if syscall.has_key("x86_64"):
syscall["asm-x86_64"] = add_footer(64, x86_64_genstub(syscall), syscall)
-
# Scan a Linux kernel asm/unistd.h file containing __NR_* constants
# and write out equivalent SYS_* constants for glibc source compatibility.
def scan_linux_unistd_h(self, fp, path):
@@ -380,7 +410,9 @@
glibc_fp.write("#ifndef _BIONIC_GLIBC_SYSCALLS_H_\n")
glibc_fp.write("#define _BIONIC_GLIBC_SYSCALLS_H_\n")
- glibc_fp.write("#if defined(__arm__)\n")
+ glibc_fp.write("#if defined(__aarch64__)\n")
+ self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/uapi/asm-generic/unistd.h")
+ glibc_fp.write("#elif defined(__arm__)\n")
self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/arch-arm/asm/unistd.h")
glibc_fp.write("#elif defined(__mips__)\n")
self.scan_linux_unistd_h(glibc_fp, bionic_libc_root + "/kernel/arch-mips/asm/unistd.h")