Discussion:
[PATCH v6 06/21] arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
(too old to reply)
Yury Norov
2016-01-14 17:30:02 UTC
Permalink
From: Andrew Pinski <***@cavium.com>

Define __BITS_PER_LONG depending on the ABI used (i.e. check whether
__ILP32__ or __LP64__ is defined). This is necessary for glibc to
determine the appropriate type definitions for the system call interface.

Signed-off-by: Andrew Pinski <***@cavium.com>
Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
Reviewed-by: David Daney <***@caviumnetworks.com>
---
arch/arm64/include/uapi/asm/bitsperlong.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/uapi/asm/bitsperlong.h b/arch/arm64/include/uapi/asm/bitsperlong.h
index fce9c29..4265243 100644
--- a/arch/arm64/include/uapi/asm/bitsperlong.h
+++ b/arch/arm64/include/uapi/asm/bitsperlong.h
@@ -16,7 +16,14 @@
#ifndef __ASM_BITSPERLONG_H
#define __ASM_BITSPERLONG_H

-#define __BITS_PER_LONG 64
+#if defined(__LP64__)
+/* Assuming __LP64__ will be defined for native ELF64's and not for ILP32. */
+# define __BITS_PER_LONG 64
+#elif defined(__ILP32__)
+# define __BITS_PER_LONG 32
+#else
+# error "Neither LP64 nor ILP32: unsupported ABI in asm/bitsperlong.h"
+#endif

#include <asm-generic/bitsperlong.h>
--
2.5.0
Yury Norov
2016-01-14 17:30:02 UTC
Permalink
It helps to move common code for lp64 and ilp32 to separated header.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/kernel/signal.c | 35 ++++++++++++++++++++---------------
1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 65baaef..20dca65 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -35,14 +35,18 @@
#include <asm/signal32.h>
#include <asm/vdso.h>

+struct sigframe {
+ struct ucontext uc;
+ u64 fp;
+ u64 lr;
+};
+
/*
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
*/
struct rt_sigframe {
struct siginfo info;
- struct ucontext uc;
- u64 fp;
- u64 lr;
+ struct sigframe sig;
};

static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
@@ -93,7 +97,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
}

static int restore_sigframe(struct pt_regs *regs,
- struct rt_sigframe __user *sf)
+ struct sigframe __user *sf)
{
sigset_t set;
int i, err;
@@ -145,10 +149,10 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;

- if (restore_sigframe(regs, frame))
+ if (restore_sigframe(regs, &frame->sig))
goto badframe;

- if (restore_altstack(&frame->uc.uc_stack))
+ if (restore_altstack(&frame->sig.uc.uc_stack))
goto badframe;

return regs->regs[0];
@@ -162,7 +166,7 @@ badframe:
return 0;
}

-static int setup_sigframe(struct rt_sigframe __user *sf,
+static int setup_sigframe(struct sigframe __user *sf,
struct pt_regs *regs, sigset_t *set)
{
int i, err = 0;
@@ -230,13 +234,13 @@ static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
}

static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
- void __user *frame, int usig)
+ void __user *frame, off_t sigframe_off, int usig)
{
__sigrestore_t sigtramp;

regs->regs[0] = usig;
regs->sp = (unsigned long)frame;
- regs->regs[29] = regs->sp + offsetof(struct rt_sigframe, fp);
+ regs->regs[29] = regs->sp + sigframe_off + offsetof(struct sigframe, fp);
regs->pc = (unsigned long)ka->sa.sa_handler;

if (ka->sa.sa_flags & SA_RESTORER)
@@ -257,17 +261,18 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
if (!frame)
return 1;

- __put_user_error(0, &frame->uc.uc_flags, err);
- __put_user_error(NULL, &frame->uc.uc_link, err);
+ __put_user_error(0, &frame->sig.uc.uc_flags, err);
+ __put_user_error(NULL, &frame->sig.uc.uc_link, err);

- err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
- err |= setup_sigframe(frame, regs, set);
+ err |= __save_altstack(&frame->sig.uc.uc_stack, regs->sp);
+ err |= setup_sigframe(&frame->sig, regs, set);
if (err == 0) {
- setup_return(regs, &ksig->ka, frame, usig);
+ setup_return(regs, &ksig->ka, frame,
+ offsetof(struct rt_sigframe, sig), usig);
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->regs[1] = (unsigned long)&frame->info;
- regs->regs[2] = (unsigned long)&frame->uc;
+ regs->regs[2] = (unsigned long)&frame->sig.uc;
}
}
--
2.5.0
Yury Norov
2016-01-14 17:30:02 UTC
Permalink
The wrapper that clears top halves of registers looks like this:

0000000000000068 <compat_SyS_mknod>:
COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
68: a9bf7bfd stp x29, x30, [sp,#-16]!
6c: 910003fd mov x29, sp
70: 2a0003e0 mov w0, w0
74: 94000000 bl 0 <sys_mknod>
78: a8c17bfd ldp x29, x30, [sp],#16
7c: d65f03c0 ret

It looks quite nice overall. Unsafe pointer type is fixed with
"mov w0, w0", and safe types are untouched.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/compat_wrapper.h | 14 ++++++++++++++
arch/arm64/kernel/sys_ilp32.c | 3 +++
3 files changed, 18 insertions(+)
create mode 100644 arch/arm64/include/asm/compat_wrapper.h

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 8606c15..0344fc0 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -785,6 +785,7 @@ config AARCH32_EL0

config ARM64_ILP32
bool "Kernel support for ILP32"
+ select COMPAT_WRAPPER
help
This option enables support for AArch64 ILP32 user space. ILP32
is an ABI where long and pointers are 32bits but it uses the AARCH64
diff --git a/arch/arm64/include/asm/compat_wrapper.h b/arch/arm64/include/asm/compat_wrapper.h
new file mode 100644
index 0000000..651b4e8
--- /dev/null
+++ b/arch/arm64/include/asm/compat_wrapper.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_COMPAT_WRAPPER
+#define __ASM_COMPAT_WRAPPER
+
+/*
+ * Compat system call wrappers.
+ */
+
+/*
+ * This file is empty as arm64 is satisfied with generic
+ * definitions of __SC_COMPAT_TYPE, _SC_COMPAT_CAST and
+ * COMPAT_SYSCALL_WRAPx.
+ */
+
+#endif /* __ASM_COMPAT_WRAPPER */
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
index bed308c..c63725b 100644
--- a/arch/arm64/kernel/sys_ilp32.c
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/compat.h>
+#include <linux/compat_wrapper.h>
#include <asm-generic/syscalls.h>

/* Using non-compat syscalls where necessary */
@@ -50,11 +51,13 @@ asmlinkage long ilp32_sys_rt_sigreturn_wrapper(void);

#undef __SYSCALL
#undef __SC_COMP
+#undef __SC_WRAP
#undef __SC_3264
#undef __SC_COMP_3264

#define __SYSCALL_COMPAT
#define __SYSCALL(nr, sym) [nr] = sym,
+#define __SC_WRAP(nr, sym) [nr] = compat_##sym,

/*
* The sys_call_ilp32_table array must be 4K aligned to be accessible from
--
2.5.0
Yury Norov
2016-01-14 17:30:02 UTC
Permalink
Based on Andrew Pinski's patch-series.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
Documentation/arm64/ilp32.txt | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 Documentation/arm64/ilp32.txt

diff --git a/Documentation/arm64/ilp32.txt b/Documentation/arm64/ilp32.txt
new file mode 100644
index 0000000..d14af62
--- /dev/null
+++ b/Documentation/arm64/ilp32.txt
@@ -0,0 +1,13 @@
+ILP32 AARCH64 SYSCALL ABI
+=========================
+
+This document describes the ILP32 syscall ABI and where it differs
+from the generic compat linux syscall interface.
+
+Syscalls which normally would pass 64bit values as two arguments;
+now pass the 64bit value as one argument.
+
+struct rt_sigframe is redefined and contains struct compat_siginfo,
+as compat syscalls expects, and struct sigframe, taken from lp64 to
+handle AARCH64 register set.
+
--
2.5.0
Yury Norov
2016-01-14 17:30:02 UTC
Permalink
From: Andrew Pinski <***@cavium.com>

In this patchset ILP32 ABI support is added. Additionally to AARCH32,
which is binary-compatible with ARM, ILP32 is (mostly) ABI-compatible.

From now, AARCH32_EL0 (former COMPAT) config option means the support of
AARCH32 userspace, ARM64_ILP32 - support of ILP32 ABI (see next patches),
and COMPAT indicates that one of them, or both, is enabled.

Signed-off-by: Andrew Pinski <***@caviumnetworks.com>
Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
Reviewed-by: David Daney <***@caviumnetworks.com>
---
arch/arm64/Kconfig | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 871f217..09d7b7e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -762,6 +762,10 @@ menu "Userspace binary formats"
source "fs/Kconfig.binfmt"

config COMPAT
+ def_bool y
+ depends on AARCH32_EL0
+
+config AARCH32_EL0
bool "Kernel support for 32-bit EL0"
depends on ARM64_4K_PAGES || EXPERT
select COMPAT_BINFMT_ELF
--
2.5.0
Yury Norov
2016-01-14 17:30:02 UTC
Permalink
The problem that makes us to use wrappers is that some compat
architectures allows user code to access top halves of registers.
This is not a problem for syscalls that are already handled by compat
code, or for that who has types of the same size in kernel and
userspace. In case of lp64/ilp32 the problem is in pointer types, long,
unsigned long.

S390 folks already have the solution for it. In this patch,
it is turned to be general, as arm64/ilp32 needs it too.

Build-tested on s390.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/Kconfig | 4 +
arch/s390/Kconfig | 1 +
arch/s390/include/asm/compat_wrapper.h | 25 +++
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/compat_linux.c | 6 +
arch/s390/kernel/compat_wrapper.c | 179 ----------------------
include/linux/compat_wrapper.h | 270 +++++++++++++++++++++++++++++++++
include/uapi/asm-generic/unistd.h | 224 +++++++++++++--------------
kernel/Makefile | 1 +
kernel/compat_wrapper.c | 167 ++++++++++++++++++++
10 files changed, 589 insertions(+), 290 deletions(-)
create mode 100644 arch/s390/include/asm/compat_wrapper.h
delete mode 100644 arch/s390/kernel/compat_wrapper.c
create mode 100644 include/linux/compat_wrapper.h
create mode 100644 kernel/compat_wrapper.c

diff --git a/arch/Kconfig b/arch/Kconfig
index 4e949e5..ab7692e 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -518,6 +518,10 @@ config HAVE_COPY_THREAD_TLS
normal C parameter passing, rather than extracting the syscall
argument from pt_regs.

+config COMPAT_WRAPPER
+ bool
+ depends on COMPAT
+
#
# ABI hall of shame
#
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 3a55f49..88f48b0 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -336,6 +336,7 @@ config COMPAT
select COMPAT_BINFMT_ELF if BINFMT_ELF
select ARCH_WANT_OLD_COMPAT_IPC
select COMPAT_OLD_SIGACTION
+ select COMPAT_WRAPPER
depends on MULTIUSER
help
Select this option if you want to enable your system kernel to
diff --git a/arch/s390/include/asm/compat_wrapper.h b/arch/s390/include/asm/compat_wrapper.h
new file mode 100644
index 0000000..d5a5c36
--- /dev/null
+++ b/arch/s390/include/asm/compat_wrapper.h
@@ -0,0 +1,25 @@
+#ifndef __ASM_COMPAT_WRAPPER
+#define __ASM_COMPAT_WRAPPER
+
+/*
+ * Compat system call wrappers.
+ *
+ * Copyright IBM Corp. 2014
+ */
+
+#define __SC_COMPAT_CAST(t, a) \
+({ \
+ long __ReS = a; \
+ \
+ BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) && \
+ !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t)); \
+ if (__TYPE_IS_L(t)) \
+ __ReS = (s32)a; \
+ if (__TYPE_IS_UL(t)) \
+ __ReS = (u32)a; \
+ if (__TYPE_IS_PTR(t)) \
+ __ReS = a & 0x7fffffff; \
+ (t)__ReS; \
+})
+
+#endif /* __ASM_COMPAT_WRAPPER */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index dc167a2..185cd88 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -55,7 +55,7 @@ obj-$(CONFIG_HIBERNATION) += suspend.o swsusp.o
obj-$(CONFIG_AUDIT) += audit.o
compat-obj-$(CONFIG_AUDIT) += compat_audit.o
obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o
-obj-$(CONFIG_COMPAT) += compat_wrapper.o $(compat-obj-y)
+obj-$(CONFIG_COMPAT) += $(compat-obj-y)

obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_KPROBES) += kprobes.o
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 437e611..22416a8 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -44,6 +44,7 @@
#include <linux/binfmts.h>
#include <linux/capability.h>
#include <linux/compat.h>
+#include <linux/compat_wrapper.h>
#include <linux/vfs.h>
#include <linux/ptrace.h>
#include <linux/fadvise.h>
@@ -86,6 +87,11 @@
#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)

+COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long,
+ mmio_addr, const void __user *, user_buffer, const size_t, length);
+COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long,
+ mmio_addr, void __user *, user_buffer, const size_t, length);
+
COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename,
u16, user, u16, group)
{
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
deleted file mode 100644
index fac4eed..0000000
--- a/arch/s390/kernel/compat_wrapper.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Compat system call wrappers.
- *
- * Copyright IBM Corp. 2014
- */
-
-#include <linux/syscalls.h>
-#include <linux/compat.h>
-#include "entry.h"
-
-#define COMPAT_SYSCALL_WRAP1(name, ...) \
- COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP2(name, ...) \
- COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP3(name, ...) \
- COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP4(name, ...) \
- COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP5(name, ...) \
- COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP6(name, ...) \
- COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
-
-#define __SC_COMPAT_TYPE(t, a) \
- __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
-
-#define __SC_COMPAT_CAST(t, a) \
-({ \
- long __ReS = a; \
- \
- BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) && \
- !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t)); \
- if (__TYPE_IS_L(t)) \
- __ReS = (s32)a; \
- if (__TYPE_IS_UL(t)) \
- __ReS = (u32)a; \
- if (__TYPE_IS_PTR(t)) \
- __ReS = a & 0x7fffffff; \
- (t)__ReS; \
-})
-
-/*
- * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
- * compat tasks. These wrappers will only be used for system calls where only
- * the system call arguments need sign or zero extension or zeroing of the upper
- * 33 bits of pointers.
- * Note: since the wrapper function will afterwards call a system call which
- * again performs zero and sign extension for all system call arguments with
- * a size of less than eight bytes, these compat wrappers only touch those
- * system call arguments with a size of eight bytes ((unsigned) long and
- * pointers). Zero and sign extension for e.g. int parameters will be done by
- * the regular system call wrappers.
- */
-#define COMPAT_SYSCALL_WRAPx(x, name, ...) \
-asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
-asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\
-asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
-{ \
- return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__)); \
-}
-
-COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
-COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
-COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
-COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
-COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
-COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
-COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name);
-COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode);
-COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname);
-COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode);
-COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname);
-COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes);
-COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);
-COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler);
-COMPAT_SYSCALL_WRAP1(acct, const char __user *, name);
-COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags);
-COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename);
-COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask);
-COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len);
-COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new);
-COMPAT_SYSCALL_WRAP3(readlink, const char __user *, path, char __user *, buf, int, bufsiz);
-COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library);
-COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags);
-COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg);
-COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len);
-COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len);
-COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile);
-COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len);
-COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name);
-COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot);
-COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs);
-COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags);
-COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr);
-COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data);
-COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2);
-COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence);
-COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags);
-COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len);
-COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len);
-COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param);
-COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param);
-COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param);
-COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr);
-COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout);
-COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5);
-COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size);
-COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr);
-COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data);
-COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group);
-COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist);
-COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist);
-COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid);
-COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid);
-COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group);
-COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old);
-COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec);
-COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior);
-COMPAT_SYSCALL_WRAP5(setxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
-COMPAT_SYSCALL_WRAP5(lsetxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
-COMPAT_SYSCALL_WRAP5(fsetxattr, int, fd, const char __user *, name, const void __user *, value, size_t, size, int, flags);
-COMPAT_SYSCALL_WRAP3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count);
-COMPAT_SYSCALL_WRAP4(getxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
-COMPAT_SYSCALL_WRAP4(lgetxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
-COMPAT_SYSCALL_WRAP4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size);
-COMPAT_SYSCALL_WRAP3(listxattr, const char __user *, path, char __user *, list, size_t, size);
-COMPAT_SYSCALL_WRAP3(llistxattr, const char __user *, path, char __user *, list, size_t, size);
-COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size);
-COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name);
-COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name);
-COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name);
-COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr);
-COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event);
-COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout);
-COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx);
-COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result);
-COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name);
-COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id);
-COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id);
-COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags);
-COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask);
-COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode);
-COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev);
-COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag);
-COMPAT_SYSCALL_WRAP3(unlinkat, int, dfd, const char __user *, pathname, int, flag);
-COMPAT_SYSCALL_WRAP4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname);
-COMPAT_SYSCALL_WRAP5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags);
-COMPAT_SYSCALL_WRAP3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname);
-COMPAT_SYSCALL_WRAP4(readlinkat, int, dfd, const char __user *, path, char __user *, buf, int, bufsiz);
-COMPAT_SYSCALL_WRAP3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode);
-COMPAT_SYSCALL_WRAP3(faccessat, int, dfd, const char __user *, filename, int, mode);
-COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags);
-COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
-COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags);
-COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache);
-COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags);
-COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags);
-COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr, unsigned long, tls);
-COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim);
-COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag);
-COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2);
-COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
-COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
-COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
-COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
-COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
-COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
-COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
-COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
-COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long, mmio_addr, const void __user *, user_buffer, const size_t, length);
-COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long, mmio_addr, void __user *, user_buffer, const size_t, length);
-COMPAT_SYSCALL_WRAP4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec);
-COMPAT_SYSCALL_WRAP3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen);
-COMPAT_SYSCALL_WRAP3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen);
-COMPAT_SYSCALL_WRAP4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen, int, flags);
-COMPAT_SYSCALL_WRAP3(getsockname, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
-COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
-COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len);
-COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags);
diff --git a/include/linux/compat_wrapper.h b/include/linux/compat_wrapper.h
new file mode 100644
index 0000000..6f22732
--- /dev/null
+++ b/include/linux/compat_wrapper.h
@@ -0,0 +1,270 @@
+#ifndef __COMPAT_WRAPPER
+#define __COMPAT_WRAPPER
+
+#include <asm/compat_wrapper.h>
+
+#define COMPAT_SYSCALL_WRAP1(name, ...) \
+ COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP2(name, ...) \
+ COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP3(name, ...) \
+ COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP4(name, ...) \
+ COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP5(name, ...) \
+ COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP6(name, ...) \
+ COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
+
+#ifndef __SC_COMPAT_TYPE
+#define __SC_COMPAT_TYPE(t, a) \
+ __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
+#endif
+
+#ifndef __SC_COMPAT_CAST
+#define __SC_COMPAT_CAST(t, a) ((t)(long) ((t)(-1) < 0 ? (s32)(a) : (u32)(a)))
+#endif
+/*
+ * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
+ * compat tasks. These wrappers will only be used for system calls where only
+ * the system call arguments need sign or zero extension or zeroing of the upper
+ * 33 bits of pointers.
+ * Note: since the wrapper function will afterwards call a system call which
+ * again performs zero and sign extension for all system call arguments with
+ * a size of less than eight bytes, these compat wrappers only touch those
+ * system call arguments with a size of eight bytes ((unsigned) long and
+ * pointers). Zero and sign extension for e.g. int parameters will be done by
+ * the regular system call wrappers.
+ */
+#ifndef COMPAT_SYSCALL_WRAPx
+#define COMPAT_SYSCALL_WRAPx(x, name, ...) \
+asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
+asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
+ __attribute__((alias(__stringify(compat_SyS##name)))); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
+{ \
+ return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__)); \
+}
+#endif
+
+asmlinkage long compat_sys_creat(const char __user *pathname, umode_t mode);
+asmlinkage long compat_sys_link(const char __user *oldname,
+ const char __user *newname);
+asmlinkage long compat_sys_chdir(const char __user *filename);
+asmlinkage long compat_sys_mknod(const char __user *filename, umode_t mode,
+ unsigned dev);
+asmlinkage long compat_sys_chmod(const char __user *filename, umode_t mode);
+asmlinkage long compat_sys_oldumount(char __user *name);
+asmlinkage long compat_sys_access(const char __user *filename, int mode);
+asmlinkage long compat_sys_rename(const char __user *oldname,
+ const char __user *newname);
+asmlinkage long compat_sys_mkdir(const char __user *pathname, umode_t mode);
+asmlinkage long compat_sys_rmdir(const char __user *pathname);
+asmlinkage long compat_sys_pipe(int __user *fildes);
+asmlinkage long compat_sys_brk(unsigned long brk);
+asmlinkage long compat_sys_signal(int sig, __sighandler_t handler);
+asmlinkage long compat_sys_acct(const char __user *name);
+asmlinkage long compat_sys_umount(char __user *name, int flags);
+asmlinkage long compat_sys_chroot(const char __user *filename);
+
+#ifdef CONFIG_OLD_SIGSUSPEND
+asmlinkage long compat_sys_sigsuspend(old_sigset_t mask);
+#endif
+
+#ifdef CONFIG_OLD_SIGSUSPEND3
+asmlinkage long compat_sys_sigsuspend(int unused1, int unused2, old_sigset_t mask);
+#endif
+
+asmlinkage long compat_sys_sethostname(char __user *name, int len);
+asmlinkage long compat_sys_symlink(const char __user *old, const char __user *new);
+asmlinkage long compat_sys_readlink(const char __user *path,
+ char __user *buf, int bufsiz);
+asmlinkage long compat_sys_uselib(const char __user *library);
+asmlinkage long compat_sys_swapon(const char __user *specialfile, int swap_flags);
+asmlinkage long compat_sys_reboot(int magic1, int magic2, unsigned int cmd,
+ void __user *arg);
+asmlinkage long compat_sys_munmap(unsigned long addr, size_t len);
+asmlinkage long compat_sys_munmap(unsigned long addr, size_t len);
+asmlinkage long compat_sys_syslog(int type, char __user *buf, int len);
+asmlinkage long compat_sys_swapoff(const char __user *specialfile);
+asmlinkage long compat_sys_setdomainname(char __user *name, int len);
+asmlinkage long compat_sys_newuname(struct new_utsname __user *name);
+asmlinkage long compat_sys_mprotect(unsigned long start, size_t len,
+ unsigned long prot);
+asmlinkage long compat_sys_init_module(void __user *umod, unsigned long len,
+ const char __user *uargs);
+asmlinkage long compat_sys_delete_module(const char __user *name_user,
+ unsigned int flags);
+asmlinkage long compat_sys_quotactl(unsigned int cmd, const char __user *special,
+ qid_t id, void __user *addr);
+asmlinkage long compat_sys_bdflush(int func, long data);
+asmlinkage long compat_sys_sysfs(int option,
+ unsigned long arg1, unsigned long arg2);
+asmlinkage long compat_sys_llseek(unsigned int fd, unsigned long offset_high,
+ unsigned long offset_low, loff_t __user *result,
+ unsigned int whence);
+asmlinkage long compat_sys_msync(unsigned long start, size_t len, int flags);
+asmlinkage long compat_sys_mlock(unsigned long start, size_t len);
+asmlinkage long compat_sys_munlock(unsigned long start, size_t len);
+asmlinkage long compat_sys_sched_setparam(pid_t pid,
+ struct sched_param __user *param);
+asmlinkage long compat_sys_sched_getparam(pid_t pid,
+ struct sched_param __user *param);
+asmlinkage long compat_sys_sched_setscheduler(pid_t pid, int policy,
+ struct sched_param __user *param);
+asmlinkage long compat_sys_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr);
+asmlinkage long compat_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+ int timeout);
+asmlinkage long compat_sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5);
+asmlinkage long compat_sys_getcwd(char __user *buf, unsigned long size);
+asmlinkage long compat_sys_capget(cap_user_header_t header,
+ cap_user_data_t dataptr);
+asmlinkage long compat_sys_capset(cap_user_header_t header,
+ const cap_user_data_t data);
+asmlinkage long compat_sys_lchown(const char __user *filename,
+ uid_t user, gid_t group);
+asmlinkage long compat_sys_getgroups(int gidsetsize, gid_t __user *grouplist);
+asmlinkage long compat_sys_setgroups(int gidsetsize, gid_t __user *grouplist);
+asmlinkage long compat_sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid);
+asmlinkage long compat_sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid);
+asmlinkage long compat_sys_chown(const char __user *filename,
+ uid_t user, gid_t group);
+asmlinkage long compat_sys_pivot_root(const char __user *new_root,
+ const char __user *put_old);
+asmlinkage long compat_sys_mincore(unsigned long start, size_t len,
+ unsigned char __user * vec);
+asmlinkage long compat_sys_madvise(unsigned long start, size_t len, int behavior);
+asmlinkage long compat_sys_setxattr(const char __user *path, const char __user *name,
+ const void __user *value, size_t size, int flags);
+asmlinkage long compat_sys_lsetxattr(const char __user *path, const char __user *name,
+ const void __user *value, size_t size, int flags);
+asmlinkage long compat_sys_fsetxattr(int fd, const char __user *name,
+ const void __user *value, size_t size, int flags);
+asmlinkage long compat_sys_getdents64(unsigned int fd,
+ struct linux_dirent64 __user *dirent,
+ unsigned int count);
+asmlinkage long compat_sys_getxattr(const char __user *path, const char __user *name,
+ void __user *value, size_t size);
+asmlinkage long compat_sys_lgetxattr(const char __user *path, const char __user *name,
+ void __user *value, size_t size);
+asmlinkage long compat_sys_fgetxattr(int fd, const char __user *name,
+ void __user *value, size_t size);
+asmlinkage long compat_sys_listxattr(const char __user *path, char __user *list,
+ size_t size);
+asmlinkage long compat_sys_llistxattr(const char __user *path, char __user *list,
+ size_t size);
+asmlinkage long compat_sys_flistxattr(int fd, char __user *list, size_t size);
+asmlinkage long compat_sys_listxattr(const char __user *path, char __user *list,
+ size_t size);
+asmlinkage long compat_sys_llistxattr(const char __user *path, char __user *list,
+ size_t size);
+asmlinkage long compat_sys_flistxattr(int fd, char __user *list, size_t size);
+asmlinkage long compat_sys_removexattr(const char __user *path,
+ const char __user *name);
+asmlinkage long compat_sys_lremovexattr(const char __user *path,
+ const char __user *name);
+asmlinkage long compat_sys_fremovexattr(int fd, const char __user *name);
+asmlinkage long compat_sys_set_tid_address(int __user *tidptr);
+asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
+ struct epoll_event __user *event);
+asmlinkage long compat_sys_epoll_wait(int epfd, struct epoll_event __user *events,
+ int maxevents, int timeout);
+asmlinkage long compat_sys_io_destroy(aio_context_t ctx);
+asmlinkage long compat_sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
+ struct io_event __user *result);
+asmlinkage long compat_sys_mq_unlink(const char __user *name);
+asmlinkage long compat_sys_add_key(const char __user *_type,
+ const char __user *_description,
+ const void __user *_payload,
+ size_t plen,
+ key_serial_t destringid);
+asmlinkage long compat_sys_request_key(const char __user *_type,
+ const char __user *_description,
+ const char __user *_callout_info,
+ key_serial_t destringid);
+asmlinkage long compat_sys_remap_file_pages(unsigned long start, unsigned long size,
+ unsigned long prot, unsigned long pgoff,
+ unsigned long flags);
+asmlinkage long compat_sys_inotify_add_watch(int fd, const char __user *path,
+ u32 mask);
+asmlinkage long compat_sys_mknodat(int dfd, const char __user * filename, umode_t mode,
+ unsigned dev);
+asmlinkage long compat_sys_mkdirat(int dfd, const char __user * pathname, umode_t mode);
+asmlinkage long compat_sys_fchownat(int dfd, const char __user *filename, uid_t user,
+ gid_t group, int flag);
+asmlinkage long compat_sys_unlinkat(int dfd, const char __user * pathname, int flag);
+asmlinkage long compat_sys_renameat(int olddfd, const char __user * oldname,
+ int newdfd, const char __user * newname);
+asmlinkage long compat_sys_symlinkat(const char __user * oldname,
+ int newdfd, const char __user * newname);
+asmlinkage long compat_sys_linkat(int olddfd, const char __user *oldname,
+ int newdfd, const char __user *newname, int flags);
+asmlinkage long compat_sys_readlinkat(int dfd, const char __user *path, char __user *buf,
+ int bufsiz);
+asmlinkage long compat_sys_fchmodat(int dfd, const char __user * filename,
+ umode_t mode);
+asmlinkage long compat_sys_faccessat(int dfd, const char __user *filename, int mode);
+asmlinkage long compat_sys_unshare(unsigned long unshare_flags);
+asmlinkage long compat_sys_splice(int fd_in, loff_t __user *off_in,
+ int fd_out, loff_t __user *off_out,
+ size_t len, unsigned int flags);
+asmlinkage long compat_sys_tee(int fdin, int fdout, size_t len, unsigned int flags);
+asmlinkage long compat_sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
+asmlinkage long compat_sys_pipe2(int __user *fildes, int flags);
+asmlinkage long compat_sys_perf_event_open(
+ struct perf_event_attr __user *attr_uptr,
+ pid_t pid, int cpu, int group_fd, unsigned long flags);
+
+#ifdef CONFIG_CLONE_BACKWARDS
+asmlinkage long compat_sys_clone(unsigned long, unsigned long, int __user *, unsigned long,
+ int __user *);
+#else
+#ifdef CONFIG_CLONE_BACKWARDS3
+asmlinkage long compat_sys_clone(unsigned long, unsigned long, int, int __user *,
+ int __user *, unsigned long);
+#else
+asmlinkage long compat_sys_clone(unsigned long, unsigned long, int __user *,
+ int __user *, unsigned long);
+#endif
+#endif
+
+asmlinkage long compat_sys_prlimit64(pid_t pid, unsigned int resource,
+ const struct rlimit64 __user *new_rlim,
+ struct rlimit64 __user *old_rlim);
+asmlinkage long compat_sys_name_to_handle_at(int dfd, const char __user *name,
+ struct file_handle __user *handle,
+ int __user *mnt_id, int flag);
+asmlinkage long compat_sys_kcmp(pid_t pid1, pid_t pid2, int type,
+ unsigned long idx1, unsigned long idx2);
+asmlinkage long compat_sys_finit_module(int fd, const char __user *uargs, int flags);
+asmlinkage long compat_sys_sched_setattr(pid_t pid,
+ struct sched_attr __user *attr,
+ unsigned int flags);
+asmlinkage long compat_sys_sched_getattr(pid_t pid,
+ struct sched_attr __user *attr,
+ unsigned int size,
+ unsigned int flags);
+asmlinkage long compat_sys_renameat2(int olddfd, const char __user *oldname,
+ int newdfd, const char __user *newname,
+ unsigned int flags);
+asmlinkage long compat_sys_seccomp(unsigned int op, unsigned int flags,
+ const char __user *uargs);
+asmlinkage long compat_sys_getrandom(char __user *buf, size_t count,
+ unsigned int flags);
+asmlinkage long compat_sys_memfd_create(const char __user *uname_ptr, unsigned int flags);
+asmlinkage long compat_sys_bpf(int cmd, union bpf_attr *attr, unsigned int size);
+asmlinkage long compat_sys_socketpair(int, int, int, int __user *);
+asmlinkage long compat_sys_bind(int, struct sockaddr __user *, int);
+asmlinkage long compat_sys_connect(int, struct sockaddr __user *, int);
+asmlinkage long compat_sys_accept4(int, struct sockaddr __user *, int __user *, int);
+asmlinkage long compat_sys_getsockname(int, struct sockaddr __user *, int __user *);
+asmlinkage long compat_sys_getpeername(int, struct sockaddr __user *, int __user *);
+asmlinkage long compat_sys_sendto(int, void __user *, size_t, unsigned,
+ struct sockaddr __user *, int);
+asmlinkage long compat_sys_mlock2(unsigned long start, size_t len, int flags);
+
+#endif /*__COMPAT_WRAPPER */
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 1324b02..5a5c53c 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -29,46 +29,50 @@
#define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
#endif

+#ifndef __SC_WRAP
+#define __SC_WRAP(x,y) __SYSCALL(x, y)
+#endif
+
#define __NR_io_setup 0
__SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
#define __NR_io_destroy 1
-__SYSCALL(__NR_io_destroy, sys_io_destroy)
+__SC_WRAP(__NR_io_destroy, sys_io_destroy)
#define __NR_io_submit 2
__SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit)
#define __NR_io_cancel 3
-__SYSCALL(__NR_io_cancel, sys_io_cancel)
+__SC_WRAP(__NR_io_cancel, sys_io_cancel)
#define __NR_io_getevents 4
__SC_COMP(__NR_io_getevents, sys_io_getevents, compat_sys_io_getevents)

/* fs/xattr.c */
#define __NR_setxattr 5
-__SYSCALL(__NR_setxattr, sys_setxattr)
+__SC_WRAP(__NR_setxattr, sys_setxattr)
#define __NR_lsetxattr 6
-__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
+__SC_WRAP(__NR_lsetxattr, sys_lsetxattr)
#define __NR_fsetxattr 7
-__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
+__SC_WRAP(__NR_fsetxattr, sys_fsetxattr)
#define __NR_getxattr 8
-__SYSCALL(__NR_getxattr, sys_getxattr)
+__SC_WRAP(__NR_getxattr, sys_getxattr)
#define __NR_lgetxattr 9
-__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
+__SC_WRAP(__NR_lgetxattr, sys_lgetxattr)
#define __NR_fgetxattr 10
-__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
+__SC_WRAP(__NR_fgetxattr, sys_fgetxattr)
#define __NR_listxattr 11
-__SYSCALL(__NR_listxattr, sys_listxattr)
+__SC_WRAP(__NR_listxattr, sys_listxattr)
#define __NR_llistxattr 12
-__SYSCALL(__NR_llistxattr, sys_llistxattr)
+__SC_WRAP(__NR_llistxattr, sys_llistxattr)
#define __NR_flistxattr 13
-__SYSCALL(__NR_flistxattr, sys_flistxattr)
+__SC_WRAP(__NR_flistxattr, sys_flistxattr)
#define __NR_removexattr 14
-__SYSCALL(__NR_removexattr, sys_removexattr)
+__SC_WRAP(__NR_removexattr, sys_removexattr)
#define __NR_lremovexattr 15
-__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
+__SC_WRAP(__NR_lremovexattr, sys_lremovexattr)
#define __NR_fremovexattr 16
-__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
+__SC_WRAP(__NR_fremovexattr, sys_fremovexattr)

/* fs/dcache.c */
#define __NR_getcwd 17
-__SYSCALL(__NR_getcwd, sys_getcwd)
+__SC_WRAP(__NR_getcwd, sys_getcwd)

/* fs/cookies.c */
#define __NR_lookup_dcookie 18
@@ -82,7 +86,7 @@ __SYSCALL(__NR_eventfd2, sys_eventfd2)
#define __NR_epoll_create1 20
__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
#define __NR_epoll_ctl 21
-__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
+__SC_WRAP(__NR_epoll_ctl, sys_epoll_ctl)
#define __NR_epoll_pwait 22
__SC_COMP(__NR_epoll_pwait, sys_epoll_pwait, compat_sys_epoll_pwait)

@@ -98,7 +102,7 @@ __SC_COMP_3264(__NR3264_fcntl, sys_fcntl64, sys_fcntl, compat_sys_fcntl64)
#define __NR_inotify_init1 26
__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
#define __NR_inotify_add_watch 27
-__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
+__SC_WRAP(__NR_inotify_add_watch, sys_inotify_add_watch)
#define __NR_inotify_rm_watch 28
__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)

@@ -118,17 +122,17 @@ __SYSCALL(__NR_flock, sys_flock)

/* fs/namei.c */
#define __NR_mknodat 33
-__SYSCALL(__NR_mknodat, sys_mknodat)
+__SC_WRAP(__NR_mknodat, sys_mknodat)
#define __NR_mkdirat 34
-__SYSCALL(__NR_mkdirat, sys_mkdirat)
+__SC_WRAP(__NR_mkdirat, sys_mkdirat)
#define __NR_unlinkat 35
-__SYSCALL(__NR_unlinkat, sys_unlinkat)
+__SC_WRAP(__NR_unlinkat, sys_unlinkat)
#define __NR_symlinkat 36
-__SYSCALL(__NR_symlinkat, sys_symlinkat)
+__SC_WRAP(__NR_symlinkat, sys_symlinkat)
#define __NR_linkat 37
-__SYSCALL(__NR_linkat, sys_linkat)
+__SC_WRAP(__NR_linkat, sys_linkat)
#define __NR_renameat 38
-__SYSCALL(__NR_renameat, sys_renameat)
+__SC_WRAP(__NR_renameat, sys_renameat)

/* fs/namespace.c */
#define __NR_umount2 39
@@ -136,7 +140,7 @@ __SYSCALL(__NR_umount2, sys_umount)
#define __NR_mount 40
__SC_COMP(__NR_mount, sys_mount, compat_sys_mount)
#define __NR_pivot_root 41
-__SYSCALL(__NR_pivot_root, sys_pivot_root)
+__SC_WRAP(__NR_pivot_root, sys_pivot_root)

/* fs/nfsctl.c */
#define __NR_nfsservctl 42
@@ -159,19 +163,19 @@ __SC_COMP_3264(__NR3264_ftruncate, sys_ftruncate64, sys_ftruncate, \
#define __NR_fallocate 47
__SC_COMP(__NR_fallocate, sys_fallocate, compat_sys_fallocate)
#define __NR_faccessat 48
-__SYSCALL(__NR_faccessat, sys_faccessat)
+__SC_WRAP(__NR_faccessat, sys_faccessat)
#define __NR_chdir 49
-__SYSCALL(__NR_chdir, sys_chdir)
+__SC_WRAP(__NR_chdir, sys_chdir)
#define __NR_fchdir 50
__SYSCALL(__NR_fchdir, sys_fchdir)
#define __NR_chroot 51
-__SYSCALL(__NR_chroot, sys_chroot)
+__SC_WRAP(__NR_chroot, sys_chroot)
#define __NR_fchmod 52
__SYSCALL(__NR_fchmod, sys_fchmod)
#define __NR_fchmodat 53
-__SYSCALL(__NR_fchmodat, sys_fchmodat)
+__SC_WRAP(__NR_fchmodat, sys_fchmodat)
#define __NR_fchownat 54
-__SYSCALL(__NR_fchownat, sys_fchownat)
+__SC_WRAP(__NR_fchownat, sys_fchownat)
#define __NR_fchown 55
__SYSCALL(__NR_fchown, sys_fchown)
#define __NR_openat 56
@@ -183,11 +187,11 @@ __SYSCALL(__NR_vhangup, sys_vhangup)

/* fs/pipe.c */
#define __NR_pipe2 59
-__SYSCALL(__NR_pipe2, sys_pipe2)
+__SC_WRAP(__NR_pipe2, sys_pipe2)

/* fs/quota.c */
#define __NR_quotactl 60
-__SYSCALL(__NR_quotactl, sys_quotactl)
+__SC_WRAP(__NR_quotactl, sys_quotactl)

/* fs/readdir.c */
#define __NR_getdents64 61
@@ -232,13 +236,13 @@ __SC_COMP(__NR_signalfd4, sys_signalfd4, compat_sys_signalfd4)
#define __NR_vmsplice 75
__SC_COMP(__NR_vmsplice, sys_vmsplice, compat_sys_vmsplice)
#define __NR_splice 76
-__SYSCALL(__NR_splice, sys_splice)
+__SC_WRAP(__NR_splice, sys_splice)
#define __NR_tee 77
-__SYSCALL(__NR_tee, sys_tee)
+__SC_WRAP(__NR_tee, sys_tee)

/* fs/stat.c */
#define __NR_readlinkat 78
-__SYSCALL(__NR_readlinkat, sys_readlinkat)
+__SC_WRAP(__NR_readlinkat, sys_readlinkat)
#define __NR3264_fstatat 79
__SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat)
#define __NR3264_fstat 80
@@ -277,13 +281,13 @@ __SC_COMP(__NR_utimensat, sys_utimensat, compat_sys_utimensat)

/* kernel/acct.c */
#define __NR_acct 89
-__SYSCALL(__NR_acct, sys_acct)
+__SC_WRAP(__NR_acct, sys_acct)

/* kernel/capability.c */
#define __NR_capget 90
-__SYSCALL(__NR_capget, sys_capget)
+__SC_WRAP(__NR_capget, sys_capget)
#define __NR_capset 91
-__SYSCALL(__NR_capset, sys_capset)
+__SC_WRAP(__NR_capset, sys_capset)

/* kernel/exec_domain.c */
#define __NR_personality 92
@@ -299,9 +303,9 @@ __SC_COMP(__NR_waitid, sys_waitid, compat_sys_waitid)

/* kernel/fork.c */
#define __NR_set_tid_address 96
-__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
+__SC_WRAP(__NR_set_tid_address, sys_set_tid_address)
#define __NR_unshare 97
-__SYSCALL(__NR_unshare, sys_unshare)
+__SC_WRAP(__NR_unshare, sys_unshare)

/* kernel/futex.c */
#define __NR_futex 98
@@ -329,9 +333,9 @@ __SC_COMP(__NR_kexec_load, sys_kexec_load, compat_sys_kexec_load)

/* kernel/module.c */
#define __NR_init_module 105
-__SYSCALL(__NR_init_module, sys_init_module)
+__SC_WRAP(__NR_init_module, sys_init_module)
#define __NR_delete_module 106
-__SYSCALL(__NR_delete_module, sys_delete_module)
+__SC_WRAP(__NR_delete_module, sys_delete_module)

/* kernel/posix-timers.c */
#define __NR_timer_create 107
@@ -356,7 +360,7 @@ __SC_COMP(__NR_clock_nanosleep, sys_clock_nanosleep, \

/* kernel/printk.c */
#define __NR_syslog 116
-__SYSCALL(__NR_syslog, sys_syslog)
+__SC_WRAP(__NR_syslog, sys_syslog)

/* kernel/ptrace.c */
#define __NR_ptrace 117
@@ -364,13 +368,13 @@ __SYSCALL(__NR_ptrace, sys_ptrace)

/* kernel/sched/core.c */
#define __NR_sched_setparam 118
-__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
+__SC_WRAP(__NR_sched_setparam, sys_sched_setparam)
#define __NR_sched_setscheduler 119
-__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
+__SC_WRAP(__NR_sched_setscheduler, sys_sched_setscheduler)
#define __NR_sched_getscheduler 120
__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
#define __NR_sched_getparam 121
-__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
+__SC_WRAP(__NR_sched_getparam, sys_sched_getparam)
#define __NR_sched_setaffinity 122
__SC_COMP(__NR_sched_setaffinity, sys_sched_setaffinity, \
compat_sys_sched_setaffinity)
@@ -421,7 +425,7 @@ __SYSCALL(__NR_setpriority, sys_setpriority)
#define __NR_getpriority 141
__SYSCALL(__NR_getpriority, sys_getpriority)
#define __NR_reboot 142
-__SYSCALL(__NR_reboot, sys_reboot)
+__SC_WRAP(__NR_reboot, sys_reboot)
#define __NR_setregid 143
__SYSCALL(__NR_setregid, sys_setregid)
#define __NR_setgid 144
@@ -433,11 +437,11 @@ __SYSCALL(__NR_setuid, sys_setuid)
#define __NR_setresuid 147
__SYSCALL(__NR_setresuid, sys_setresuid)
#define __NR_getresuid 148
-__SYSCALL(__NR_getresuid, sys_getresuid)
+__SC_WRAP(__NR_getresuid, sys_getresuid)
#define __NR_setresgid 149
__SYSCALL(__NR_setresgid, sys_setresgid)
#define __NR_getresgid 150
-__SYSCALL(__NR_getresgid, sys_getresgid)
+__SC_WRAP(__NR_getresgid, sys_getresgid)
#define __NR_setfsuid 151
__SYSCALL(__NR_setfsuid, sys_setfsuid)
#define __NR_setfsgid 152
@@ -453,15 +457,15 @@ __SYSCALL(__NR_getsid, sys_getsid)
#define __NR_setsid 157
__SYSCALL(__NR_setsid, sys_setsid)
#define __NR_getgroups 158
-__SYSCALL(__NR_getgroups, sys_getgroups)
+__SC_WRAP(__NR_getgroups, sys_getgroups)
#define __NR_setgroups 159
-__SYSCALL(__NR_setgroups, sys_setgroups)
+__SC_WRAP(__NR_setgroups, sys_setgroups)
#define __NR_uname 160
-__SYSCALL(__NR_uname, sys_newuname)
+__SC_WRAP(__NR_uname, sys_newuname)
#define __NR_sethostname 161
-__SYSCALL(__NR_sethostname, sys_sethostname)
+__SC_WRAP(__NR_sethostname, sys_sethostname)
#define __NR_setdomainname 162
-__SYSCALL(__NR_setdomainname, sys_setdomainname)
+__SC_WRAP(__NR_setdomainname, sys_setdomainname)
#define __NR_getrlimit 163
__SC_COMP(__NR_getrlimit, sys_getrlimit, compat_sys_getrlimit)
#define __NR_setrlimit 164
@@ -471,9 +475,9 @@ __SC_COMP(__NR_getrusage, sys_getrusage, compat_sys_getrusage)
#define __NR_umask 166
__SYSCALL(__NR_umask, sys_umask)
#define __NR_prctl 167
-__SYSCALL(__NR_prctl, sys_prctl)
+__SC_WRAP(__NR_prctl, sys_prctl)
#define __NR_getcpu 168
-__SYSCALL(__NR_getcpu, sys_getcpu)
+__SC_WRAP(__NR_getcpu, sys_getcpu)

/* kernel/time.c */
#define __NR_gettimeofday 169
@@ -505,7 +509,7 @@ __SC_COMP(__NR_sysinfo, sys_sysinfo, compat_sys_sysinfo)
#define __NR_mq_open 180
__SC_COMP(__NR_mq_open, sys_mq_open, compat_sys_mq_open)
#define __NR_mq_unlink 181
-__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
+__SC_WRAP(__NR_mq_unlink, sys_mq_unlink)
#define __NR_mq_timedsend 182
__SC_COMP(__NR_mq_timedsend, sys_mq_timedsend, compat_sys_mq_timedsend)
#define __NR_mq_timedreceive 183
@@ -550,21 +554,21 @@ __SYSCALL(__NR_shmdt, sys_shmdt)
#define __NR_socket 198
__SYSCALL(__NR_socket, sys_socket)
#define __NR_socketpair 199
-__SYSCALL(__NR_socketpair, sys_socketpair)
+__SC_WRAP(__NR_socketpair, sys_socketpair)
#define __NR_bind 200
-__SYSCALL(__NR_bind, sys_bind)
+__SC_WRAP(__NR_bind, sys_bind)
#define __NR_listen 201
__SYSCALL(__NR_listen, sys_listen)
#define __NR_accept 202
__SYSCALL(__NR_accept, sys_accept)
#define __NR_connect 203
-__SYSCALL(__NR_connect, sys_connect)
+__SC_WRAP(__NR_connect, sys_connect)
#define __NR_getsockname 204
-__SYSCALL(__NR_getsockname, sys_getsockname)
+__SC_WRAP(__NR_getsockname, sys_getsockname)
#define __NR_getpeername 205
-__SYSCALL(__NR_getpeername, sys_getpeername)
+__SC_WRAP(__NR_getpeername, sys_getpeername)
#define __NR_sendto 206
-__SYSCALL(__NR_sendto, sys_sendto)
+__SC_WRAP(__NR_sendto, sys_sendto)
#define __NR_recvfrom 207
__SC_COMP(__NR_recvfrom, sys_recvfrom, compat_sys_recvfrom)
#define __NR_setsockopt 208
@@ -584,23 +588,23 @@ __SC_COMP(__NR_readahead, sys_readahead, compat_sys_readahead)

/* mm/nommu.c, also with MMU */
#define __NR_brk 214
-__SYSCALL(__NR_brk, sys_brk)
+__SC_WRAP(__NR_brk, sys_brk)
#define __NR_munmap 215
-__SYSCALL(__NR_munmap, sys_munmap)
+__SC_WRAP(__NR_munmap, sys_munmap)
#define __NR_mremap 216
-__SYSCALL(__NR_mremap, sys_mremap)
+__SC_WRAP(__NR_mremap, sys_mremap)

/* security/keys/keyctl.c */
#define __NR_add_key 217
-__SYSCALL(__NR_add_key, sys_add_key)
+__SC_WRAP(__NR_add_key, sys_add_key)
#define __NR_request_key 218
-__SYSCALL(__NR_request_key, sys_request_key)
+__SC_WRAP(__NR_request_key, sys_request_key)
#define __NR_keyctl 219
__SC_COMP(__NR_keyctl, sys_keyctl, compat_sys_keyctl)

/* arch/example/kernel/sys_example.c */
#define __NR_clone 220
-__SYSCALL(__NR_clone, sys_clone)
+__SC_WRAP(__NR_clone, sys_clone)
#define __NR_execve 221
__SC_COMP(__NR_execve, sys_execve, compat_sys_execve)

@@ -613,27 +617,27 @@ __SC_COMP(__NR3264_fadvise64, sys_fadvise64_64, compat_sys_fadvise64_64)
/* mm/, CONFIG_MMU only */
#ifndef __ARCH_NOMMU
#define __NR_swapon 224
-__SYSCALL(__NR_swapon, sys_swapon)
+__SC_WRAP(__NR_swapon, sys_swapon)
#define __NR_swapoff 225
-__SYSCALL(__NR_swapoff, sys_swapoff)
+__SC_WRAP(__NR_swapoff, sys_swapoff)
#define __NR_mprotect 226
-__SYSCALL(__NR_mprotect, sys_mprotect)
+__SC_WRAP(__NR_mprotect, sys_mprotect)
#define __NR_msync 227
-__SYSCALL(__NR_msync, sys_msync)
+__SC_WRAP(__NR_msync, sys_msync)
#define __NR_mlock 228
-__SYSCALL(__NR_mlock, sys_mlock)
+__SC_WRAP(__NR_mlock, sys_mlock)
#define __NR_munlock 229
-__SYSCALL(__NR_munlock, sys_munlock)
+__SC_WRAP(__NR_munlock, sys_munlock)
#define __NR_mlockall 230
__SYSCALL(__NR_mlockall, sys_mlockall)
#define __NR_munlockall 231
__SYSCALL(__NR_munlockall, sys_munlockall)
#define __NR_mincore 232
-__SYSCALL(__NR_mincore, sys_mincore)
+__SC_WRAP(__NR_mincore, sys_mincore)
#define __NR_madvise 233
-__SYSCALL(__NR_madvise, sys_madvise)
+__SC_WRAP(__NR_madvise, sys_madvise)
#define __NR_remap_file_pages 234
-__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
+__SC_WRAP(__NR_remap_file_pages, sys_remap_file_pages)
#define __NR_mbind 235
__SC_COMP(__NR_mbind, sys_mbind, compat_sys_mbind)
#define __NR_get_mempolicy 236
@@ -650,9 +654,9 @@ __SC_COMP(__NR_move_pages, sys_move_pages, compat_sys_move_pages)
__SC_COMP(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo, \
compat_sys_rt_tgsigqueueinfo)
#define __NR_perf_event_open 241
-__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
+__SC_WRAP(__NR_perf_event_open, sys_perf_event_open)
#define __NR_accept4 242
-__SYSCALL(__NR_accept4, sys_accept4)
+__SC_WRAP(__NR_accept4, sys_accept4)
#define __NR_recvmmsg 243
__SC_COMP(__NR_recvmmsg, sys_recvmmsg, compat_sys_recvmmsg)

@@ -665,13 +669,13 @@ __SC_COMP(__NR_recvmmsg, sys_recvmmsg, compat_sys_recvmmsg)
#define __NR_wait4 260
__SC_COMP(__NR_wait4, sys_wait4, compat_sys_wait4)
#define __NR_prlimit64 261
-__SYSCALL(__NR_prlimit64, sys_prlimit64)
+__SC_WRAP(__NR_prlimit64, sys_prlimit64)
#define __NR_fanotify_init 262
__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
#define __NR_fanotify_mark 263
__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
#define __NR_name_to_handle_at 264
-__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+__SC_WRAP(__NR_name_to_handle_at, sys_name_to_handle_at)
#define __NR_open_by_handle_at 265
__SC_COMP(__NR_open_by_handle_at, sys_open_by_handle_at, \
compat_sys_open_by_handle_at)
@@ -690,23 +694,23 @@ __SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \
__SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
compat_sys_process_vm_writev)
#define __NR_kcmp 272
-__SYSCALL(__NR_kcmp, sys_kcmp)
+__SC_WRAP(__NR_kcmp, sys_kcmp)
#define __NR_finit_module 273
-__SYSCALL(__NR_finit_module, sys_finit_module)
+__SC_WRAP(__NR_finit_module, sys_finit_module)
#define __NR_sched_setattr 274
-__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+__SC_WRAP(__NR_sched_setattr, sys_sched_setattr)
#define __NR_sched_getattr 275
-__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
+__SC_WRAP(__NR_sched_getattr, sys_sched_getattr)
#define __NR_renameat2 276
-__SYSCALL(__NR_renameat2, sys_renameat2)
+__SC_WRAP(__NR_renameat2, sys_renameat2)
#define __NR_seccomp 277
-__SYSCALL(__NR_seccomp, sys_seccomp)
+__SC_WRAP(__NR_seccomp, sys_seccomp)
#define __NR_getrandom 278
-__SYSCALL(__NR_getrandom, sys_getrandom)
+__SC_WRAP(__NR_getrandom, sys_getrandom)
#define __NR_memfd_create 279
-__SYSCALL(__NR_memfd_create, sys_memfd_create)
+__SC_WRAP(__NR_memfd_create, sys_memfd_create)
#define __NR_bpf 280
-__SYSCALL(__NR_bpf, sys_bpf)
+__SC_WRAP(__NR_bpf, sys_bpf)
#define __NR_execveat 281
__SC_COMP(__NR_execveat, sys_execveat, compat_sys_execveat)
#define __NR_userfaultfd 282
@@ -714,7 +718,7 @@ __SYSCALL(__NR_userfaultfd, sys_userfaultfd)
#define __NR_membarrier 283
__SYSCALL(__NR_membarrier, sys_membarrier)
#define __NR_mlock2 284
-__SYSCALL(__NR_mlock2, sys_mlock2)
+__SC_WRAP(__NR_mlock2, sys_mlock2)

#undef __NR_syscalls
#define __NR_syscalls 285
@@ -731,29 +735,29 @@ __SYSCALL(__NR_mlock2, sys_mlock2)
#define __NR_open 1024
__SYSCALL(__NR_open, sys_open)
#define __NR_link 1025
-__SYSCALL(__NR_link, sys_link)
+__SC_WRAP(__NR_link, sys_link)
#define __NR_unlink 1026
-__SYSCALL(__NR_unlink, sys_unlink)
+__SC_WRAP(__NR_unlink, sys_unlink)
#define __NR_mknod 1027
-__SYSCALL(__NR_mknod, sys_mknod)
+__SC_WRAP(__NR_mknod, sys_mknod)
#define __NR_chmod 1028
-__SYSCALL(__NR_chmod, sys_chmod)
+__SC_WRAP(__NR_chmod, sys_chmod)
#define __NR_chown 1029
-__SYSCALL(__NR_chown, sys_chown)
+__SC_WRAP(__NR_chown, sys_chown)
#define __NR_mkdir 1030
-__SYSCALL(__NR_mkdir, sys_mkdir)
+__SC_WRAP(__NR_mkdir, sys_mkdir)
#define __NR_rmdir 1031
-__SYSCALL(__NR_rmdir, sys_rmdir)
+__SC_WRAP(__NR_rmdir, sys_rmdir)
#define __NR_lchown 1032
-__SYSCALL(__NR_lchown, sys_lchown)
+__SC_WRAP(__NR_lchown, sys_lchown)
#define __NR_access 1033
-__SYSCALL(__NR_access, sys_access)
+__SC_WRAP(__NR_access, sys_access)
#define __NR_rename 1034
-__SYSCALL(__NR_rename, sys_rename)
+__SC_WRAP(__NR_rename, sys_rename)
#define __NR_readlink 1035
-__SYSCALL(__NR_readlink, sys_readlink)
+__SC_WRAP(__NR_readlink, sys_readlink)
#define __NR_symlink 1036
-__SYSCALL(__NR_symlink, sys_symlink)
+__SC_WRAP(__NR_symlink, sys_symlink)
#define __NR_utimes 1037
__SYSCALL(__NR_utimes, sys_utimes)
#define __NR3264_stat 1038
@@ -767,7 +771,7 @@ __SC_3264(__NR3264_lstat, sys_lstat64, sys_newlstat)

#ifdef __ARCH_WANT_SYSCALL_NO_FLAGS
#define __NR_pipe 1040
-__SYSCALL(__NR_pipe, sys_pipe)
+__SC_WRAP(__NR_pipe, sys_pipe)
#define __NR_dup2 1041
__SYSCALL(__NR_dup2, sys_dup2)
#define __NR_epoll_create 1042
@@ -837,7 +841,7 @@ __SYSCALL(__NR_time, sys_time)
__SYSCALL(__NR_utime, sys_utime)

#define __NR_creat 1064
-__SYSCALL(__NR_creat, sys_creat)
+__SC_WRAP(__NR_creat, sys_creat)
#define __NR_getdents 1065
#define __ARCH_WANT_SYS_GETDENTS
__SYSCALL(__NR_getdents, sys_getdents)
@@ -847,9 +851,9 @@ __SYSCALL(__NR_futimesat, sys_futimesat)
#define __ARCH_WANT_SYS_SELECT
__SYSCALL(__NR_select, sys_select)
#define __NR_poll 1068
-__SYSCALL(__NR_poll, sys_poll)
+__SC_WRAP(__NR_poll, sys_poll)
#define __NR_epoll_wait 1069
-__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
+__SC_WRAP(__NR_epoll_wait, sys_epoll_wait)
#define __NR_ustat 1070
__SYSCALL(__NR_ustat, sys_ustat)
#define __NR_vfork 1071
@@ -861,12 +865,12 @@ __SYSCALL(__NR_recv, sys_recv)
#define __NR_send 1074
__SYSCALL(__NR_send, sys_send)
#define __NR_bdflush 1075
-__SYSCALL(__NR_bdflush, sys_bdflush)
+__SC_WRAP(__NR_bdflush, sys_bdflush)
#define __NR_umount 1076
-__SYSCALL(__NR_umount, sys_oldumount)
+__SC_WRAP(__NR_umount, sys_oldumount)
#define __ARCH_WANT_SYS_OLDUMOUNT
#define __NR_uselib 1077
-__SYSCALL(__NR_uselib, sys_uselib)
+__SC_WRAP(__NR_uselib, sys_uselib)
#define __NR__sysctl 1078
__SYSCALL(__NR__sysctl, sys_sysctl)

diff --git a/kernel/Makefile b/kernel/Makefile
index 53abf00..4c0dc0e 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o
obj-$(CONFIG_BINFMT_ELF) += elfcore.o
obj-$(CONFIG_COMPAT_BINFMT_ELF) += elfcore.o
+obj-$(CONFIG_COMPAT_WRAPPER) += compat_wrapper.o
obj-$(CONFIG_BINFMT_ELF_FDPIC) += elfcore.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
obj-$(CONFIG_TRACING) += trace/
diff --git a/kernel/compat_wrapper.c b/kernel/compat_wrapper.c
new file mode 100644
index 0000000..4a99811
--- /dev/null
+++ b/kernel/compat_wrapper.c
@@ -0,0 +1,167 @@
+/*
+ * Compat system call wrappers.
+ *
+ * Copyright IBM Corp. 2014
+ */
+
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+#include <linux/compat_wrapper.h>
+
+COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
+COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
+COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
+COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
+COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
+
+#ifdef __ARCH_WANT_SYS_OLDUMOUNT
+COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name);
+#endif
+
+COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode);
+COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname);
+COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname);
+COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes);
+COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);
+
+#ifdef __ARCH_WANT_SYS_SIGNAL
+COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler);
+#endif
+
+COMPAT_SYSCALL_WRAP1(acct, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags);
+COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename);
+COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask);
+COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len);
+COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new);
+COMPAT_SYSCALL_WRAP3(readlink, const char __user *, path, char __user *, buf, int, bufsiz);
+COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library);
+COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags);
+COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg);
+COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len);
+COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len);
+COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile);
+COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len);
+COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name);
+COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot);
+COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs);
+COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr);
+COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data);
+COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2);
+
+#ifdef __ARCH_WANT_SYS_LLSEEK
+COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence);
+#endif
+
+COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags);
+COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len);
+COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len);
+COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr);
+COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout);
+COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5);
+COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size);
+COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr);
+COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data);
+COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group);
+COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist);
+COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist);
+COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid);
+COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid);
+COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group);
+COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old);
+COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec);
+COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior);
+COMPAT_SYSCALL_WRAP5(setxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+COMPAT_SYSCALL_WRAP5(lsetxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+COMPAT_SYSCALL_WRAP5(fsetxattr, int, fd, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+
+#ifndef __ARCH_WANT_COMPAT_SYS_GETDENTS64
+COMPAT_SYSCALL_WRAP3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count);
+#endif
+
+COMPAT_SYSCALL_WRAP4(getxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP4(lgetxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP3(listxattr, const char __user *, path, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP3(llistxattr, const char __user *, path, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name);
+COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr);
+COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event);
+COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout);
+COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx);
+COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result);
+COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name);
+COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id);
+COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id);
+COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags);
+COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask);
+COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev);
+COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag);
+COMPAT_SYSCALL_WRAP3(unlinkat, int, dfd, const char __user *, pathname, int, flag);
+COMPAT_SYSCALL_WRAP4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname);
+COMPAT_SYSCALL_WRAP5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags);
+COMPAT_SYSCALL_WRAP3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname);
+COMPAT_SYSCALL_WRAP4(readlinkat, int, dfd, const char __user *, path, char __user *, buf, int, bufsiz);
+COMPAT_SYSCALL_WRAP3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode);
+COMPAT_SYSCALL_WRAP3(faccessat, int, dfd, const char __user *, filename, int, mode);
+COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags);
+COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags);
+COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache);
+COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags);
+COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags);
+
+#ifdef __ARCH_WANT_SYS_CLONE
+#ifdef CONFIG_CLONE_BACKWARDS
+COMPAT_SYSCALL_WRAP5(clone, unsigned long, clone_flags, unsigned long, newsp,
+ int __user *, parent_tidptr,
+ unsigned long, tls,
+ int __user *, child_tidptr);
+#elif defined(CONFIG_CLONE_BACKWARDS2)
+COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags,
+ int __user *, parent_tidptr,
+ int __user *, child_tidptr,
+ unsigned long, tls);
+#elif defined(CONFIG_CLONE_BACKWARDS3)
+COMPAT_SYSCALL_WRAP6(clone, unsigned long, clone_flags, unsigned long, newsp,
+ int, stack_size,
+ int __user *, parent_tidptr,
+ int __user *, child_tidptr,
+ unsigned long, tls);
+#else
+COMPAT_SYSCALL_WRAP5(clone, unsigned long, clone_flags, unsigned long, newsp,
+ int __user *, parent_tidptr,
+ int __user *, child_tidptr,
+ unsigned long, tls);
+#endif
+#endif
+
+COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim);
+COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag);
+COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2);
+COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
+COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
+COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
+COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
+COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
+COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
+COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
+COMPAT_SYSCALL_WRAP4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec);
+COMPAT_SYSCALL_WRAP3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen);
+COMPAT_SYSCALL_WRAP3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen);
+COMPAT_SYSCALL_WRAP4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen, int, flags);
+COMPAT_SYSCALL_WRAP3(getsockname, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
+COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
+COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len);
+COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags);
--
2.5.0
Yury Norov
2016-01-14 18:20:02 UTC
Permalink
Post by Yury Norov
The problem that makes us to use wrappers is that some compat
architectures allows user code to access top halves of registers.
This is not a problem for syscalls that are already handled by compat
code, or for that who has types of the same size in kernel and
userspace. In case of lp64/ilp32 the problem is in pointer types, long,
unsigned long.
S390 folks already have the solution for it. In this patch,
it is turned to be general, as arm64/ilp32 needs it too.
Build-tested on s390.
---
[...]
Post by Yury Norov
+#ifndef __SC_COMPAT_CAST
+#define __SC_COMPAT_CAST(t, a) ((t)(long) ((t)(-1) < 0 ? (s32)(a) : (u32)(a)))
+#endif
It should be like:
#define __SC_COMPAT_CAST(t, a) ((t) ((t)(-1) < 0 ? (s64)(s32)(a) : (u64)(u32)(a)))
Heiko Carstens
2016-01-15 12:50:02 UTC
Permalink
Post by Yury Norov
The problem that makes us to use wrappers is that some compat
architectures allows user code to access top halves of registers.
This is not a problem for syscalls that are already handled by compat
code, or for that who has types of the same size in kernel and
userspace. In case of lp64/ilp32 the problem is in pointer types, long,
unsigned long.
S390 folks already have the solution for it. In this patch,
it is turned to be general, as arm64/ilp32 needs it too.
Build-tested on s390.
If you want to make this generic then I think the footprint of the compat
Post by Yury Norov
diff --git a/arch/s390/include/asm/compat_wrapper.h b/arch/s390/include/asm/compat_wrapper.h
new file mode 100644
index 0000000..d5a5c36
--- /dev/null
+++ b/arch/s390/include/asm/compat_wrapper.h
@@ -0,0 +1,25 @@
+#ifndef __ASM_COMPAT_WRAPPER
+#define __ASM_COMPAT_WRAPPER
+
+/*
+ * Compat system call wrappers.
+ *
+ * Copyright IBM Corp. 2014
+ */
+
+#define __SC_COMPAT_CAST(t, a) \
+({ \
+ long __ReS = a; \
+ \
+ BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) && \
+ !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t)); \
+ if (__TYPE_IS_L(t)) \
+ __ReS = (s32)a; \
+ if (__TYPE_IS_UL(t)) \
+ __ReS = (u32)a; \
+ if (__TYPE_IS_PTR(t)) \
+ __ReS = a & 0x7fffffff; \
+ (t)__ReS; \
+})
+
+#endif /* __ASM_COMPAT_WRAPPER */
This should go to arch/s390/include/asm/compat.h right below Al's
__SC_DELOUSE. (no new header file please)
Post by Yury Norov
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 437e611..22416a8 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -44,6 +44,7 @@
#include <linux/binfmts.h>
#include <linux/capability.h>
#include <linux/compat.h>
+#include <linux/compat_wrapper.h>
#include <linux/vfs.h>
#include <linux/ptrace.h>
#include <linux/fadvise.h>
@@ -86,6 +87,11 @@
#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
+COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long,
+ mmio_addr, const void __user *, user_buffer, const size_t, length);
+COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long,
+ mmio_addr, void __user *, user_buffer, const size_t, length);
+
I'd really prefer if the existing common SYSCALL_DEFINE macros could be
extended to also generate the compat wrappers, if needed.

This probably means that you need another set of SYSCALL_DEFINE macros,
e.g. something like SYSCALL_COMPAT, which is defined the same like
SYSCALL_DEFINE, except that it also generates the compat_wrapper functions.

Since the list of system calls that need a wrapper is already present in
s390's compat_wrapper.c file it's "only" a matter of writing a script that
converts the required SYSCALL_DEFINEs to SYSYCALL_COMPATs.
Post by Yury Norov
diff --git a/include/linux/compat_wrapper.h b/include/linux/compat_wrapper.h
new file mode 100644
index 0000000..6f22732
--- /dev/null
+++ b/include/linux/compat_wrapper.h
@@ -0,0 +1,270 @@
+#ifndef __COMPAT_WRAPPER
+#define __COMPAT_WRAPPER
+
+#include <asm/compat_wrapper.h>
+
+#define COMPAT_SYSCALL_WRAP1(name, ...) \
+ COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP2(name, ...) \
+ COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP3(name, ...) \
+ COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP4(name, ...) \
+ COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP5(name, ...) \
+ COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP6(name, ...) \
+ COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
+
+#ifndef __SC_COMPAT_TYPE
+#define __SC_COMPAT_TYPE(t, a) \
+ __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
+#endif
+
+#ifndef __SC_COMPAT_CAST
+#define __SC_COMPAT_CAST(t, a) ((t)(long) ((t)(-1) < 0 ? (s32)(a) : (u32)(a)))
+#endif
+/*
+ * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
+ * compat tasks. These wrappers will only be used for system calls where only
+ * the system call arguments need sign or zero extension or zeroing of the upper
+ * 33 bits of pointers.
+ * Note: since the wrapper function will afterwards call a system call which
+ * again performs zero and sign extension for all system call arguments with
+ * a size of less than eight bytes, these compat wrappers only touch those
+ * system call arguments with a size of eight bytes ((unsigned) long and
+ * pointers). Zero and sign extension for e.g. int parameters will be done by
+ * the regular system call wrappers.
+ */
+#ifndef COMPAT_SYSCALL_WRAPx
+#define COMPAT_SYSCALL_WRAPx(x, name, ...) \
+asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
+asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
+ __attribute__((alias(__stringify(compat_SyS##name)))); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
+{ \
+ return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__)); \
+}
+#endif
All of this should go to include/linux/compat.h
Post by Yury Norov
+asmlinkage long compat_sys_creat(const char __user *pathname, umode_t mode);
+asmlinkage long compat_sys_link(const char __user *oldname,
+ const char __user *newname);
+asmlinkage long compat_sys_chdir(const char __user *filename);
+asmlinkage long compat_sys_mknod(const char __user *filename, umode_t mode,
+ unsigned dev);
Are these really needed?
Post by Yury Norov
diff --git a/kernel/compat_wrapper.c b/kernel/compat_wrapper.c
new file mode 100644
index 0000000..4a99811
--- /dev/null
+++ b/kernel/compat_wrapper.c
@@ -0,0 +1,167 @@
+/*
+ * Compat system call wrappers.
+ *
+ * Copyright IBM Corp. 2014
+ */
+
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+#include <linux/compat_wrapper.h>
+
+COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
+COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
+COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
+COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
+COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
With all the above changes this file wouldn't be necessary, which I think
would be good.

Just my thoughts...
Heiko Carstens
2016-01-20 08:20:02 UTC
Permalink
Post by Heiko Carstens
Post by Yury Norov
+asmlinkage long compat_sys_creat(const char __user *pathname, umode_t mode);
+asmlinkage long compat_sys_link(const char __user *oldname,
+ const char __user *newname);
+asmlinkage long compat_sys_chdir(const char __user *filename);
+asmlinkage long compat_sys_mknod(const char __user *filename, umode_t mode,
+ unsigned dev);
Are these really needed?
91 of ~160 wrapped syscalls produce compile time error without it on
arch/arm64/kernel/sys_ilp32.c:59:35: error: ‘compat_sys_io_destroy’ undeclared here (not in a function)
#define __SC_WRAP(nr, sym) [nr] = compat_##sym,
^
include/uapi/asm-generic/unistd.h:39:1: note: in expansion of macro ‘__SC_WRAP’
__SC_WRAP(__NR_io_destroy, sys_io_destroy)
^
I think, it's better to leave it as is...
I see. The syscall tables on arm seem to be generated in C code. So you
need the declarations.
diff --git a/fs/readdir.c b/fs/readdir.c
index ced6791..d34cc49 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -17,6 +17,7 @@
#include <linux/dirent.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/compat.h>
#include <linux/unistd.h>
#include <asm/uaccess.h>
return -EFAULT;
}
+#ifndef __ARCH_WANT_COMPAT_SYS_GETDENTS64
+SYSCALL_DEFINE_WRAP3(getdents64, unsigned int, fd,
+ struct linux_dirent64 __user *, dirent, unsigned int, count)
+#else
SYSCALL_DEFINE3(getdents64, unsigned int, fd,
struct linux_dirent64 __user *, dirent, unsigned int, count)
+#endif
{
struct fd f;
struct linux_dirent64 __user * lastdirent;
This is a non-obvious change at first glance. I think it would make sense
to split this patch into at least three or four separate patches:
- one which introduces the infrastructure
- one which converts the non-obvious syscalls like this one
- one which converts the rest
- one which enables the architectures
diff --git a/include/linux/compat.h b/include/linux/compat.h
index a76c917..293864c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -55,6 +55,52 @@
} \
static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
+#define SYSCALL_DEFINE_WRAP1(name, ...) SYSCALL_DEFINE_WRAPx(1, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP2(name, ...) SYSCALL_DEFINE_WRAPx(2, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP3(name, ...) SYSCALL_DEFINE_WRAPx(3, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP4(name, ...) SYSCALL_DEFINE_WRAPx(4, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP5(name, ...) SYSCALL_DEFINE_WRAPx(5, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP6(name, ...) SYSCALL_DEFINE_WRAPx(6, _##name, __VA_ARGS__)
+
+#ifndef __SC_COMPAT_TYPE
+#define __SC_COMPAT_TYPE(t, a) \
+ __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
+#endif
+
+#ifndef __SC_COMPAT_CAST
+#define __SC_COMPAT_CAST(t, a) ((t) ((t)(-1) < 0 ? (s64)(s32)(a) : (u64)(u32)(a)))
+#endif
You might consider adding a BUILD_BUG_ON() here, like within the s390 variant.

Personally I don't like the SYSCALL_DEFINE_WRAPx names too much. But that
can be changed easily if somebody comes up with a better name for it.
+#define SYSCALL_DEFINE_WRAPx(x, name, ...) \
+asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
+asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
+ __attribute__((alias(__stringify(compat_SyS##name)))); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
+{ \
+ return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__)); \
+} \
+SYSCALL_DEFINEx(x, name, __VA_ARGS__)
Given that the system call functions might be inlined, I think it would
make sense to remove the "notrace" attribute. Otherwise we would end up
with lots of untraceable (and unpatchable) functions. I didn't care back
then for the small compat wrappers...
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 0623787..ab14c3f 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -17,27 +17,41 @@ asmlinkage long sys_ni_syscall(void)
}
cond_syscall(sys_quotactl);
+cond_syscall(compat_sys_quotactl);
It might make sense to add a define which adds both variants.

Btw. for future versions please add linux-arch to cc.
Yury Norov
2016-01-20 12:20:01 UTC
Permalink
Post by Heiko Carstens
Post by Yury Norov
+#ifndef __ARCH_WANT_COMPAT_SYS_GETDENTS64
+SYSCALL_DEFINE_WRAP3(getdents64, unsigned int, fd,
+ struct linux_dirent64 __user *, dirent, unsigned int, count)
+#else
SYSCALL_DEFINE3(getdents64, unsigned int, fd,
struct linux_dirent64 __user *, dirent, unsigned int, count)
+#endif
{
struct fd f;
struct linux_dirent64 __user * lastdirent;
This is a non-obvious change at first glance. I think it would make sense
- one which introduces the infrastructure
- one which converts the non-obvious syscalls like this one
- one which converts the rest
- one which enables the architectures
Agree. This one became too big and non-trivial...
I'll prepare patchset this week. I also think, it's better
to send it separately, like we did with 32/64bit off_t:
https://lkml.org/lkml/2015/12/26/71
Post by Heiko Carstens
Post by Yury Norov
diff --git a/include/linux/compat.h b/include/linux/compat.h
index a76c917..293864c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -55,6 +55,52 @@
} \
static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
+#define SYSCALL_DEFINE_WRAP1(name, ...) SYSCALL_DEFINE_WRAPx(1, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP2(name, ...) SYSCALL_DEFINE_WRAPx(2, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP3(name, ...) SYSCALL_DEFINE_WRAPx(3, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP4(name, ...) SYSCALL_DEFINE_WRAPx(4, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP5(name, ...) SYSCALL_DEFINE_WRAPx(5, _##name, __VA_ARGS__)
+#define SYSCALL_DEFINE_WRAP6(name, ...) SYSCALL_DEFINE_WRAPx(6, _##name, __VA_ARGS__)
+
+#ifndef __SC_COMPAT_TYPE
+#define __SC_COMPAT_TYPE(t, a) \
+ __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
+#endif
+
+#ifndef __SC_COMPAT_CAST
+#define __SC_COMPAT_CAST(t, a) ((t) ((t)(-1) < 0 ? (s64)(s32)(a) : (u64)(u32)(a)))
+#endif
You might consider adding a BUILD_BUG_ON() here, like within the s390 variant.
Personally I don't like the SYSCALL_DEFINE_WRAPx names too much. But that
can be changed easily if somebody comes up with a better name for it.
Neither me... Maybe SYSCALL_DEFINE_WRAPPEDx?
Post by Heiko Carstens
Post by Yury Norov
+#define SYSCALL_DEFINE_WRAPx(x, name, ...) \
+asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
+asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
+ __attribute__((alias(__stringify(compat_SyS##name)))); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)); \
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
+{ \
+ return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__)); \
+} \
+SYSCALL_DEFINEx(x, name, __VA_ARGS__)
Given that the system call functions might be inlined, I think it would
make sense to remove the "notrace" attribute. Otherwise we would end up
with lots of untraceable (and unpatchable) functions. I didn't care back
then for the small compat wrappers...
Ok
Post by Heiko Carstens
Post by Yury Norov
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 0623787..ab14c3f 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -17,27 +17,41 @@ asmlinkage long sys_ni_syscall(void)
}
cond_syscall(sys_quotactl);
+cond_syscall(compat_sys_quotactl);
It might make sense to add a define which adds both variants.
Btw. for future versions please add linux-arch to cc.
Ok.

Yury.
Yury Norov
2016-01-14 17:30:03 UTC
Permalink
From: Andrew Pinski <***@cavium.com>

This patch adds the config option for ILP32.

Signed-off-by: Andrew Pinski <***@caviumnetworks.com>
Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
Reviewed-by: David Daney <***@caviumnetworks.com>
---
arch/arm64/Kconfig | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 2c205a4..8606c15 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -763,7 +763,7 @@ source "fs/Kconfig.binfmt"

config COMPAT
def_bool y
- depends on AARCH32_EL0
+ depends on AARCH32_EL0 || ARM64_ILP32

config AARCH32_EL0
bool "Kernel support for 32-bit EL0"
@@ -783,6 +783,13 @@ config AARCH32_EL0

If you want to execute 32-bit userspace applications, say Y.

+config ARM64_ILP32
+ bool "Kernel support for ILP32"
+ help
+ This option enables support for AArch64 ILP32 user space. ILP32
+ is an ABI where long and pointers are 32bits but it uses the AARCH64
+ instruction set.
+
config SYSVIPC_COMPAT
def_bool y
depends on COMPAT && SYSVIPC
--
2.5.0
Yury Norov
2016-01-14 17:30:03 UTC
Permalink
From: Bamvor Jian Zhang <***@linaro.org>

With the patches of ILP32, COMPAT is not equivalent to AARCH32 in EL0.
This patch fix this by updating the dependency from COMPAT to
AARCH32_EL0 for ARMV8_DEPRECATED and ARM64_ERRATUM_845719.

Signed-off-by: Bamvor Jian Zhang <***@linaro.org>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 09d7b7e..aeddddd 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -339,7 +339,7 @@ config ARM64_ERRATUM_834220

config ARM64_ERRATUM_845719
bool "Cortex-A53: 845719: a load might read incorrect data"
- depends on COMPAT
+ depends on AARCH32_EL0
default y
help
This option adds an alternative code sequence to work around ARM
@@ -592,7 +592,7 @@ config FORCE_MAX_ZONEORDER

menuconfig ARMV8_DEPRECATED
bool "Emulate deprecated/obsolete ARMv8 instructions"
- depends on COMPAT
+ depends on AARCH32_EL0
help
Legacy software support may require certain instructions
that have been deprecated or obsoleted in the architecture.
--
2.5.0
Yury Norov
2016-01-14 17:30:03 UTC
Permalink
Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/include/asm/signal32_common.h | 25 +++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/signal32.c | 85 -----------------------
arch/arm64/kernel/signal32_common.c | 115 +++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+), 85 deletions(-)
create mode 100644 arch/arm64/include/asm/signal32_common.h
create mode 100644 arch/arm64/kernel/signal32_common.c

diff --git a/arch/arm64/include/asm/signal32_common.h b/arch/arm64/include/asm/signal32_common.h
new file mode 100644
index 0000000..b4f2099
--- /dev/null
+++ b/arch/arm64/include/asm/signal32_common.h
@@ -0,0 +1,25 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGNAL32_COMMON_H
+#define __ASM_SIGNAL32_COMMON_H
+
+#ifdef CONFIG_COMPAT
+
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from);
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from);
+
+#endif /* CONFIG_COMPAT*/
+
+#endif /* __ASM_SIGNAL32_COMMON_H */
+
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index a35f2f8..4981933 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -29,6 +29,7 @@ arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o \
../../arm/kernel/opcodes.o binfmt_elf32.o
arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o
+arm64-obj-$(CONFIG_COMPAT) += signal32_common.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 71ef6dc..2a69815 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -125,91 +125,6 @@ static inline int get_sigset_t(sigset_t *set,
return 0;
}

-int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
-{
- int err;
-
- if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
- return -EFAULT;
-
- /* If you change siginfo_t structure, please be sure
- * this code is fixed accordingly.
- * It should never copy any pad contained in the structure
- * to avoid security leaks, but must copy the generic
- * 3 ints plus the relevant union member.
- * This routine must convert siginfo from 64bit to 32bit as well
- * at the same time.
- */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
- err |= __put_user((short)from->si_code, &to->si_code);
- if (from->si_code < 0)
- err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
- SI_PAD_SIZE);
- else switch (from->si_code & __SI_MASK) {
- case __SI_KILL:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- case __SI_TIMER:
- err |= __put_user(from->si_tid, &to->si_tid);
- err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- case __SI_POLL:
- err |= __put_user(from->si_band, &to->si_band);
- err |= __put_user(from->si_fd, &to->si_fd);
- break;
- case __SI_FAULT:
- err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
- &to->si_addr);
-#ifdef BUS_MCEERR_AO
- /*
- * Other callers might not initialize the si_lsb field,
- * so check explicitely for the right codes here.
- */
- if (from->si_signo == SIGBUS &&
- (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
- err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
-#endif
- break;
- case __SI_CHLD:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_status, &to->si_status);
- err |= __put_user(from->si_utime, &to->si_utime);
- err |= __put_user(from->si_stime, &to->si_stime);
- break;
- case __SI_RT: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ: /* But this is */
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- case __SI_SYS:
- err |= __put_user((compat_uptr_t)(unsigned long)
- from->si_call_addr, &to->si_call_addr);
- err |= __put_user(from->si_syscall, &to->si_syscall);
- err |= __put_user(from->si_arch, &to->si_arch);
- break;
- default: /* this is just in case for now ... */
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- break;
- }
- return err;
-}
-
-int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
-{
- if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
- copy_from_user(to->_sifields._pad,
- from->_sifields._pad, SI_PAD_SIZE))
- return -EFAULT;
-
- return 0;
-}
-
/*
* VFP save/restore code.
*
diff --git a/arch/arm64/kernel/signal32_common.c b/arch/arm64/kernel/signal32_common.c
new file mode 100644
index 0000000..1146f82
--- /dev/null
+++ b/arch/arm64/kernel/signal32_common.c
@@ -0,0 +1,115 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Modified by Will Deacon <***@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/ratelimit.h>
+
+#include <asm/esr.h>
+#include <asm/fpsimd.h>
+#include <asm/signal32_common.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
+{
+ int err;
+
+ if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
+ return -EFAULT;
+
+ /* If you change siginfo_t structure, please be sure
+ * this code is fixed accordingly.
+ * It should never copy any pad contained in the structure
+ * to avoid security leaks, but must copy the generic
+ * 3 ints plus the relevant union member.
+ * This routine must convert siginfo from 64bit to 32bit as well
+ * at the same time.
+ */
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user((short)from->si_code, &to->si_code);
+ if (from->si_code < 0)
+ err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
+ SI_PAD_SIZE);
+ else switch (from->si_code & __SI_MASK) {
+ case __SI_KILL:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ case __SI_TIMER:
+ err |= __put_user(from->si_tid, &to->si_tid);
+ err |= __put_user(from->si_overrun, &to->si_overrun);
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ case __SI_POLL:
+ err |= __put_user(from->si_band, &to->si_band);
+ err |= __put_user(from->si_fd, &to->si_fd);
+ break;
+ case __SI_FAULT:
+ err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
+ &to->si_addr);
+#ifdef BUS_MCEERR_AO
+ /*
+ * Other callers might not initialize the si_lsb field,
+ * so check explicitely for the right codes here.
+ */
+ if (from->si_signo == SIGBUS &&
+ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
+ err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
+#endif
+ break;
+ case __SI_CHLD:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_status, &to->si_status);
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ break;
+ case __SI_RT: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ: /* But this is */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ case __SI_SYS:
+ err |= __put_user((compat_uptr_t)(unsigned long)
+ from->si_call_addr, &to->si_call_addr);
+ err |= __put_user(from->si_syscall, &to->si_syscall);
+ err |= __put_user(from->si_arch, &to->si_arch);
+ break;
+ default: /* this is just in case for now ... */
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ }
+ return err;
+}
+
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
+{
+ if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
+ copy_from_user(to->_sifields._pad,
+ from->_sifields._pad, SI_PAD_SIZE))
+ return -EFAULT;
+
+ return 0;
+}
+
--
2.5.0
Yury Norov
2016-01-14 17:30:03 UTC
Permalink
ILP32 tasks are needed to be distinguished from lp64 and aarch32.
This patch adds helper functions is_ilp32_compat_{task,thread} and
thread flag TIF_32BIT_AARCH64 to address it. This is a preparation
for following patches in ilp32 patchset.

For consistency, SET_PERSONALITY are changed here accordingly.

Signed-off-by: Andrew Pinski <***@caviumnetworks.com>
Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
Reviewed-by: David Daney <***@caviumnetworks.com>
---
arch/arm64/include/asm/elf.h | 13 +++++++++++--
arch/arm64/include/asm/is_compat.h | 28 +++++++++++++++++++++++++++-
arch/arm64/include/asm/thread_info.h | 1 +
3 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 2f62ded..5e27a64 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -135,7 +135,11 @@ typedef struct user_fpsimd_state elf_fpregset_t;
*/
#define ELF_PLAT_INIT(_r, load_addr) (_r)->regs[0] = 0

-#define SET_PERSONALITY(ex) clear_thread_flag(TIF_32BIT);
+#define SET_PERSONALITY(ex) \
+do { \
+ clear_thread_flag(TIF_32BIT_AARCH64); \
+ clear_thread_flag(TIF_32BIT); \
+} while (0)

#define ARCH_DLINFO \
do { \
@@ -174,7 +178,12 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
((x)->e_flags & EF_ARM_EABI_MASK))

#define compat_start_thread compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex) set_thread_flag(TIF_32BIT);
+#define COMPAT_SET_PERSONALITY(ex) \
+do { \
+ clear_thread_flag(TIF_32BIT_AARCH64); \
+ set_thread_flag(TIF_32BIT); \
+} while (0)
+
#define COMPAT_ARCH_DLINFO
extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
int uses_interp);
diff --git a/arch/arm64/include/asm/is_compat.h b/arch/arm64/include/asm/is_compat.h
index 6139b5a..55134cf 100644
--- a/arch/arm64/include/asm/is_compat.h
+++ b/arch/arm64/include/asm/is_compat.h
@@ -45,11 +45,37 @@ static inline int is_a32_compat_thread(struct thread_info *thread)

#endif /* CONFIG_AARCH32_EL0 */

+#ifdef CONFIG_ARM64_ILP32
+
+static inline int is_ilp32_compat_task(void)
+{
+ return test_thread_flag(TIF_32BIT_AARCH64);
+}
+
+static inline int is_ilp32_compat_thread(struct thread_info *thread)
+{
+ return test_ti_thread_flag(thread, TIF_32BIT_AARCH64);
+}
+
+#else
+
+static inline int is_ilp32_compat_task(void)
+{
+ return 0;
+}
+
+static inline int is_ilp32_compat_thread(struct thread_info *thread)
+{
+ return 0;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
#ifdef CONFIG_COMPAT

static inline int is_compat_task(void)
{
- return is_a32_compat_task();
+ return is_a32_compat_task() || is_ilp32_compat_task();
}

#endif /* CONFIG_COMPAT */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index dd046c5..c74d4f5 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -113,6 +113,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTORE_SIGMASK 20
#define TIF_SINGLESTEP 21
#define TIF_32BIT 22 /* AARCH32 process */
+#define TIF_32BIT_AARCH64 23 /* 32 bit process on AArch64(ILP32) */

#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
--
2.5.0
Yury Norov
2016-01-14 17:30:04 UTC
Permalink
After that, it will be possible to reuse it in ilp32.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/include/asm/signal_common.h | 39 ++++++++++++++++++++++++++++++++++
arch/arm64/kernel/signal.c | 17 ++++++---------
2 files changed, 45 insertions(+), 11 deletions(-)
create mode 100644 arch/arm64/include/asm/signal_common.h

diff --git a/arch/arm64/include/asm/signal_common.h b/arch/arm64/include/asm/signal_common.h
new file mode 100644
index 0000000..faa82c0
--- /dev/null
+++ b/arch/arm64/include/asm/signal_common.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2016 Cavium Networks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_SIGNAL_COMMON_H
+#define __ASM_SIGNAL_COMMON_H
+
+#include <linux/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/fpsimd.h>
+
+struct sigframe {
+ struct ucontext uc;
+ u64 fp;
+ u64 lr;
+};
+
+int preserve_fpsimd_context(struct fpsimd_context __user *ctx);
+int restore_fpsimd_context(struct fpsimd_context __user *ctx);
+int setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set);
+int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf);
+void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+ void __user *frame, off_t sigframe_off, int usig);
+
+#endif /* __ASM_SIGNAL_COMMON_H */
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 20dca65..a742a61 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -34,12 +34,7 @@
#include <asm/fpsimd.h>
#include <asm/signal32.h>
#include <asm/vdso.h>
-
-struct sigframe {
- struct ucontext uc;
- u64 fp;
- u64 lr;
-};
+#include <asm/signal_common.h>

/*
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
@@ -49,7 +44,7 @@ struct rt_sigframe {
struct sigframe sig;
};

-static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
+int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
{
struct fpsimd_state *fpsimd = &current->thread.fpsimd_state;
int err;
@@ -69,7 +64,7 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
return err ? -EFAULT : 0;
}

-static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
+int restore_fpsimd_context(struct fpsimd_context __user *ctx)
{
struct fpsimd_state fpsimd;
__u32 magic, size;
@@ -96,7 +91,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
return err ? -EFAULT : 0;
}

-static int restore_sigframe(struct pt_regs *regs,
+int restore_sigframe(struct pt_regs *regs,
struct sigframe __user *sf)
{
sigset_t set;
@@ -166,7 +161,7 @@ badframe:
return 0;
}

-static int setup_sigframe(struct sigframe __user *sf,
+int setup_sigframe(struct sigframe __user *sf,
struct pt_regs *regs, sigset_t *set)
{
int i, err = 0;
@@ -233,7 +228,7 @@ static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
return frame;
}

-static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
void __user *frame, off_t sigframe_off, int usig)
{
__sigrestore_t sigtramp;
--
2.5.0
Yury Norov
2016-01-14 17:30:04 UTC
Permalink
Based on patch of Andrew Pinski.

This patch introduces is_a32_compat_task and is_a32_thread so it is
easier to say this is a a32 specific thread or a generic compat thread/task.
Corresponding functions are located in <asm/is_compat.h> to avoid mess in
headers.

Some files include both <linux/compat.h> and <asm/compat.h>,
and this is wrong because <linux/compat.h> has <asm/compat.h> already
included. It was fixed too.

Reviewed-by: David Daney <***@caviumnetworks.com>
Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
Signed-off-by: Andrew Pinski <***@caviumnetworks.com>
---
arch/arm64/include/asm/compat.h | 19 ++----------
arch/arm64/include/asm/elf.h | 7 ++---
arch/arm64/include/asm/is_compat.h | 58 ++++++++++++++++++++++++++++++++++++
arch/arm64/include/asm/memory.h | 3 +-
arch/arm64/include/asm/processor.h | 5 ++--
arch/arm64/include/asm/thread_info.h | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 10 +++----
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 5 ++--
arch/arm64/kernel/ptrace.c | 9 +++---
arch/arm64/kernel/signal.c | 4 +--
arch/arm64/kernel/traps.c | 3 +-
12 files changed, 84 insertions(+), 43 deletions(-)
create mode 100644 arch/arm64/include/asm/is_compat.h

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index eb8432b..df2f72d 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -24,6 +24,8 @@
#include <linux/types.h>
#include <linux/sched.h>

+#include <asm/is_compat.h>
+
#define COMPAT_USER_HZ 100
#ifdef __AARCH64EB__
#define COMPAT_UTS_MACHINE "armv8b\0\0"
@@ -298,23 +300,6 @@ struct compat_shmid64_ds {
compat_ulong_t __unused5;
};

-static inline int is_compat_task(void)
-{
- return test_thread_flag(TIF_32BIT);
-}
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
- return test_ti_thread_flag(thread, TIF_32BIT);
-}
-
-#else /* !CONFIG_COMPAT */
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
- return 0;
-}
-
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
#endif /* __ASM_COMPAT_H */
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index faad6df..2f62ded 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -16,6 +16,7 @@
#ifndef __ASM_ELF_H
#define __ASM_ELF_H

+#include <linux/compat.h>
#include <asm/hwcap.h>

/*
@@ -148,13 +149,9 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);

/* 1GB of VA */
-#ifdef CONFIG_COMPAT
-#define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \
+#define STACK_RND_MASK (is_compat_task() ? \
0x7ff >> (PAGE_SHIFT - 12) : \
0x3ffff >> (PAGE_SHIFT - 12))
-#else
-#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12))
-#endif

#ifdef CONFIG_COMPAT

diff --git a/arch/arm64/include/asm/is_compat.h b/arch/arm64/include/asm/is_compat.h
new file mode 100644
index 0000000..6139b5a
--- /dev/null
+++ b/arch/arm64/include/asm/is_compat.h
@@ -0,0 +1,58 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_IS_COMPAT_H
+#define __ASM_IS_COMPAT_H
+#ifndef __ASSEMBLY__
+
+#include <linux/thread_bits.h>
+
+#ifdef CONFIG_AARCH32_EL0
+
+static inline int is_a32_compat_task(void)
+{
+ return test_thread_flag(TIF_32BIT);
+}
+
+static inline int is_a32_compat_thread(struct thread_info *thread)
+{
+ return test_ti_thread_flag(thread, TIF_32BIT);
+}
+
+#else
+
+static inline int is_a32_compat_task(void)
+
+{
+ return 0;
+}
+
+static inline int is_a32_compat_thread(struct thread_info *thread)
+{
+ return 0;
+}
+
+#endif /* CONFIG_AARCH32_EL0 */
+
+#ifdef CONFIG_COMPAT
+
+static inline int is_compat_task(void)
+{
+ return is_a32_compat_task();
+}
+
+#endif /* CONFIG_COMPAT */
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_IS_COMPAT_H */
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 853953c..5ec1b74 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -25,6 +25,7 @@
#include <linux/const.h>
#include <linux/types.h>
#include <asm/sizes.h>
+#include <asm/is_compat.h>

/*
* Allow for constants defined here to be used from assembly code
@@ -60,7 +61,7 @@

#ifdef CONFIG_COMPAT
#define TASK_SIZE_32 UL(0x100000000)
-#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
+#define TASK_SIZE (is_compat_task() ? \
TASK_SIZE_32 : TASK_SIZE_64)
#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk, TIF_32BIT) ? \
TASK_SIZE_32 : TASK_SIZE_64)
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 9c4d95d..e4e56ae 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -29,6 +29,7 @@

#include <linux/string.h>

+#include <asm/is_compat.h>
#include <asm/fpsimd.h>
#include <asm/hw_breakpoint.h>
#include <asm/pgtable-hwdef.h>
@@ -39,7 +40,7 @@
#define STACK_TOP_MAX TASK_SIZE_64
#ifdef CONFIG_COMPAT
#define AARCH32_VECTORS_BASE 0xffff0000
-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+#define STACK_TOP (is_compat_task() ? \
AARCH32_VECTORS_BASE : STACK_TOP_MAX)
#else
#define STACK_TOP STACK_TOP_MAX
@@ -92,7 +93,7 @@ struct thread_struct {
#define task_user_tls(t) \
({ \
unsigned long *__tls; \
- if (is_compat_thread(task_thread_info(t))) \
+ if (is_a32_compat_thread(task_thread_info(t))) \
__tls = &(t)->thread.tp2_value; \
else \
__tls = &(t)->thread.tp_value; \
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 90c7ff2..dd046c5 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -112,7 +112,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_FREEZE 19
#define TIF_RESTORE_SIGMASK 20
#define TIF_SINGLESTEP 21
-#define TIF_32BIT 22 /* 32bit process */
+#define TIF_32BIT 22 /* AARCH32 process */

#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index b45c95d..baa1eba 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -164,7 +164,7 @@ enum hw_breakpoint_ops {
HW_BREAKPOINT_RESTORE
};

-static int is_compat_bp(struct perf_event *bp)
+static int is_a32_compat_bp(struct perf_event *bp)
{
struct task_struct *tsk = bp->hw.target;

@@ -175,7 +175,7 @@ static int is_compat_bp(struct perf_event *bp)
* deprecated behaviour if we use unaligned watchpoints in
* AArch64 state.
*/
- return tsk && is_compat_thread(task_thread_info(tsk));
+ return tsk && is_a32_compat_thread(task_thread_info(tsk));
}

/**
@@ -435,7 +435,7 @@ static int arch_build_bp_info(struct perf_event *bp)
* Watchpoints can be of length 1, 2, 4 or 8 bytes.
*/
if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
- if (is_compat_bp(bp)) {
+ if (is_a32_compat_bp(bp)) {
if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
info->ctrl.len != ARM_BREAKPOINT_LEN_4)
return -EINVAL;
@@ -492,7 +492,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
* AArch32 tasks expect some simple alignment fixups, so emulate
* that here.
*/
- if (is_compat_bp(bp)) {
+ if (is_a32_compat_bp(bp)) {
if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
alignment_mask = 0x7;
else
@@ -679,7 +679,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,

info = counter_arch_bp(wp);
/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
- if (is_compat_task()) {
+ if (is_a32_compat_task()) {
if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
alignment_mask = 0x7;
else
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
index 3f62b35..a79058f 100644
--- a/arch/arm64/kernel/perf_regs.c
+++ b/arch/arm64/kernel/perf_regs.c
@@ -45,7 +45,7 @@ int perf_reg_validate(u64 mask)

u64 perf_reg_abi(struct task_struct *task)
{
- if (is_compat_thread(task_thread_info(task)))
+ if (is_a32_compat_thread(task_thread_info(task)))
return PERF_SAMPLE_REGS_ABI_32;
else
return PERF_SAMPLE_REGS_ABI_64;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index f75b540..251e1f7 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -46,7 +46,6 @@
#include <linux/notifier.h>
#include <trace/events/power.h>

-#include <asm/compat.h>
#include <asm/cacheflush.h>
#include <asm/fpsimd.h>
#include <asm/mmu_context.h>
@@ -262,7 +261,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
asm("mrs %0, tpidr_el0" : "=r" (*task_user_tls(p)));

if (stack_start) {
- if (is_compat_thread(task_thread_info(p)))
+ if (is_a32_compat_thread(task_thread_info(p)))
childregs->compat_sp = stack_start;
/* 16-byte aligned stack mandatory on AArch64 */
else if (stack_start & 15)
@@ -299,7 +298,7 @@ static void tls_thread_switch(struct task_struct *next)
*task_user_tls(current) = tpidr;

tpidr = *task_user_tls(next);
- tpidrro = is_compat_thread(task_thread_info(next)) ?
+ tpidrro = is_a32_compat_thread(task_thread_info(next)) ?
next->thread.tp_value : 0;

asm(
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 6b02f26..c166548 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -38,7 +38,6 @@
#include <linux/tracehook.h>
#include <linux/elf.h>

-#include <asm/compat.h>
#include <asm/debug-monitors.h>
#include <asm/pgtable.h>
#include <asm/syscall.h>
@@ -79,7 +78,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
#ifdef CONFIG_AARCH32_EL0
int i;

- if (!is_compat_task())
+ if (!is_a32_compat_task())
goto send_sig;

for (i = 0; i < ARM_MAX_BRP; ++i) {
@@ -1197,9 +1196,9 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
* 32-bit children use an extended user_aarch32_ptrace_view to allow
* access to the TLS register.
*/
- if (is_compat_task())
+ if (is_a32_compat_task())
return &user_aarch32_view;
- else if (is_compat_thread(task_thread_info(task)))
+ else if (is_a32_compat_thread(task_thread_info(task)))
return &user_aarch32_ptrace_view;
#endif
return &user_aarch64_view;
@@ -1226,7 +1225,7 @@ static void tracehook_report_syscall(struct pt_regs *regs,
* A scratch register (ip(r12) on AArch32, x7 on AArch64) is
* used to denote syscall entry/exit:
*/
- regno = (is_compat_task() ? 12 : 7);
+ regno = (is_a32_compat_task() ? 12 : 7);
saved_reg = regs->regs[regno];
regs->regs[regno] = dir;

diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index e18c48c..65baaef 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -276,7 +276,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,

static void setup_restart_syscall(struct pt_regs *regs)
{
- if (is_compat_task())
+ if (is_a32_compat_task())
compat_setup_restart_syscall(regs);
else
regs->regs[8] = __NR_restart_syscall;
@@ -295,7 +295,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
/*
* Set up the stack frame
*/
- if (is_compat_task()) {
+ if (is_a32_compat_task()) {
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
else
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index b50fced..4115c44 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -18,6 +18,7 @@
*/

#include <linux/bug.h>
+#include <linux/compat.h>
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/kallsyms.h>
@@ -370,7 +371,7 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs)
{
#ifdef CONFIG_AARCH32_EL0
long ret;
- if (is_compat_task()) {
+ if (is_a32_compat_task()) {
ret = compat_arm_syscall(regs);
if (ret != -ENOSYS)
return ret;
--
2.5.0
Yury Norov
2016-01-14 17:30:04 UTC
Permalink
From: Philipp Tomsich <***@theobroma-systems.com>

ILP32 VDSO exports next symbols:
__kernel_rt_sigreturn;
__kernel_gettimeofday;
__kernel_clock_gettime;
__kernel_clock_getres;

What shared object to use, kernel selects depending on result of
is_ilp32_compat_task() in arch/arm64/kernel/vdso.c, so it substitutes
correct pages and spec.

Adjusted to move the move data page before code pages in sync with
commit 601255ae3c98fdeeee3a8bb4696425e4f868b4f1

Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/include/asm/vdso.h | 6 ++
arch/arm64/kernel/Makefile | 5 ++
arch/arm64/kernel/signal.c | 2 +
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 72 ++++++++++++++++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 ++++++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++++++++++
arch/arm64/kernel/vdso.c | 61 ++++++++++++++---
8 files changed, 266 insertions(+), 10 deletions(-)
create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S

diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 839ce00..649a9a4 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -29,6 +29,12 @@

#include <generated/vdso-offsets.h>

+#ifdef CONFIG_ARM64_ILP32
+#include <generated/vdso-ilp32-offsets.h>
+#else
+#define vdso_offset_sigtramp_ilp32
+#endif
+
#define VDSO_SYMBOL(base, name) \
({ \
(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index c846626..19d7e17 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -46,6 +46,7 @@ arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
arm64-obj-$(CONFIG_ACPI) += acpi.o

obj-y += $(arm64-obj-y) vdso/
+obj-$(CONFIG_ARM64_ILP32) += vdso-ilp32/
obj-m += $(arm64-obj-m)
head-y := head.o
extra-y += $(head-y) vmlinux.lds
@@ -53,3 +54,7 @@ extra-y += $(head-y) vmlinux.lds
# vDSO - this must be built first to generate the symbol offsets
$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
$(obj)/vdso/vdso-offsets.h: $(obj)/vdso
+
+# vDSO - this must be built first to generate the symbol offsets
+$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h
+$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index f8d4c92..0648aa5 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -241,6 +241,8 @@ void setup_return(struct pt_regs *regs, struct k_sigaction *ka,

if (ka->sa.sa_flags & SA_RESTORER)
sigtramp = ka->sa.sa_restorer;
+ else if (is_ilp32_compat_task())
+ sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32);
else
sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);

diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore
new file mode 100644
index 0000000..61806c3
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/.gitignore
@@ -0,0 +1,2 @@
+vdso-ilp32.lds
+vdso-ilp32-offsets.h
diff --git a/arch/arm64/kernel/vdso-ilp32/Makefile b/arch/arm64/kernel/vdso-ilp32/Makefile
new file mode 100644
index 0000000..c8f5472
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/Makefile
@@ -0,0 +1,72 @@
+#
+# Building a vDSO image for AArch64.
+#
+# Author: Will Deacon <***@arm.com>
+# Heavily based on the vDSO Makefiles for other archs.
+#
+
+obj-ilp32-vdso := gettimeofday-ilp32.o note-ilp32.o sigreturn-ilp32.o
+
+# Build rules
+targets := $(obj-ilp32-vdso) vdso-ilp32.so vdso-ilp32.so.dbg
+obj-ilp32-vdso := $(addprefix $(obj)/, $(obj-ilp32-vdso))
+
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-ilp32-vdso.so.1 \
+ $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+
+obj-y += vdso-ilp32.o
+extra-y += vdso-ilp32.lds vdso-ilp32-offsets.h
+CPPFLAGS_vdso-ilp32.lds += -P -C -U$(ARCH) -mabi=ilp32
+
+# Force dependency (incbin is bad)
+$(obj)/vdso-ilp32.o : $(obj)/vdso-ilp32.so
+
+# Link rule for the .so file, .lds has to be first
+$(obj)/vdso-ilp32.so.dbg: $(src)/vdso-ilp32.lds $(obj-ilp32-vdso)
+ $(call if_changed,vdso-ilp32ld)
+
+# Strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+ $(call if_changed,objcopy)
+
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+ $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \
+ cp $@ include/generated/
+endef
+
+$(obj)/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32.so.dbg FORCE
+ $(call if_changed,vdsosym)
+
+# Assembly rules for the .S files
+#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S)
+# $(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
+ $(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/note-ilp32.o: $(src)/../vdso/note.S
+ $(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/sigreturn-ilp32.o: $(src)/../vdso/sigreturn.S
+ $(call if_changed_dep,vdso-ilp32as)
+
+# Actual build commands
+quiet_cmd_vdso-ilp32ld = VDSOILP32L $@
+ cmd_vdso-ilp32ld = $(CC) $(c_flags) -mabi=ilp32 -Wl,-n -Wl,-T $^ -o $@
+quiet_cmd_vdso-ilp32as = VDSOILP32A $@
+ cmd_vdso-ilp32as = $(CC) $(a_flags) -mabi=ilp32 -c -o $@ $<
+
+# Install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+ cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso-ilp32.so: $(obj)/vdso-ilp32.so.dbg
+ @mkdir -p $(MODLIB)/vdso
+ $(call cmd,vdso_install)
+
+vdso_install: vdso-ilp32.so
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
new file mode 100644
index 0000000..46ac072
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <***@arm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+ __PAGE_ALIGNED_DATA
+
+ .globl vdso_ilp32_start, vdso_ilp32_end
+ .balign PAGE_SIZE
+vdso_ilp32_start:
+ .incbin "arch/arm64/kernel/vdso-ilp32/vdso-ilp32.so"
+ .balign PAGE_SIZE
+vdso_ilp32_end:
+
+ .previous
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
new file mode 100644
index 0000000..ddc63fd
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
@@ -0,0 +1,95 @@
+/*
+ * GNU linker script for the VDSO library.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <***@arm.com>
+ * Heavily based on the vDSO linker scripts for other archs.
+ */
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+SECTIONS
+{
+ PROVIDE(_vdso_data = . - PAGE_SIZE);
+ . = VDSO_LBASE + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note.*) } :text :note
+
+ . = ALIGN(16);
+
+ .text : { *(.text*) } :text =0xd503201f
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ .rodata : { *(.rodata*) } :text
+
+ _end = .;
+ PROVIDE(end = .);
+
+ /DISCARD/ : {
+ *(.note.GNU-stack)
+ *(.data .data.* .gnu.linkonce.d.* .sdata*)
+ *(.bss .sbss .dynbss .dynsbss)
+ }
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+ text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME;
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ LINUX_2.6 {
+ global:
+ __kernel_rt_sigreturn;
+ __kernel_gettimeofday;
+ __kernel_clock_gettime;
+ __kernel_clock_getres;
+ local: *;
+ };
+}
+
+/*
+ * Make the sigreturn code visible to the kernel.
+ */
+VDSO_sigtramp_ilp32 = __kernel_rt_sigreturn;
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 26352a6..521a8e4 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -40,6 +40,12 @@ extern char vdso_start, vdso_end;
static unsigned long vdso_pages;
static struct page **vdso_pagelist;

+#ifdef CONFIG_ARM64_ILP32
+extern char vdso_ilp32_start, vdso_ilp32_end;
+static unsigned long vdso_ilp32_pages;
+static struct page **vdso_ilp32_pagelist;
+#endif
+
/*
* The vDSO data page.
*/
@@ -109,24 +115,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
}
#endif /* CONFIG_AARCH32_EL0 */

-static struct vm_special_mapping vdso_spec[2];
-
-static int __init vdso_init(void)
+static int __init vdso_init_common(char *vdso_start, char *vdso_end,
+ unsigned long *vdso_pagesp,
+ struct page ***vdso_pagelistp,
+ struct vm_special_mapping* vdso_spec)
{
int i;
+ unsigned long vdso_pages;
+ struct page **vdso_pagelist;

- if (memcmp(&vdso_start, "\177ELF", 4)) {
+ if (memcmp(vdso_start, "\177ELF", 4)) {
pr_err("vDSO is not a valid ELF object!\n");
return -EINVAL;
}

- vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+ vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
+ *vdso_pagesp = vdso_pages;
pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
- vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
+ vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);

/* Allocate the vDSO pagelist, plus a page for the data. */
vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
GFP_KERNEL);
+ *vdso_pagelistp = vdso_pagelist;
if (vdso_pagelist == NULL)
return -ENOMEM;

@@ -135,7 +146,7 @@ static int __init vdso_init(void)

/* Grab the vDSO code pages. */
for (i = 0; i < vdso_pages; i++)
- vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+ vdso_pagelist[i + 1] = virt_to_page(vdso_start + i * PAGE_SIZE);

/* Populate the special mapping structures */
vdso_spec[0] = (struct vm_special_mapping) {
@@ -150,16 +161,46 @@ static int __init vdso_init(void)

return 0;
}
+
+static struct vm_special_mapping vdso_spec[2];
+
+static int __init vdso_init(void)
+{
+ return vdso_init_common(&vdso_start, &vdso_end,
+ &vdso_pages, &vdso_pagelist,
+ vdso_spec);
+}
arch_initcall(vdso_init);

+#ifdef CONFIG_ARM64_ILP32
+static struct vm_special_mapping vdso_ilp32_spec[2];
+
+static int __init vdso_ilp32_init(void)
+{
+ return vdso_init_common(&vdso_ilp32_start, &vdso_ilp32_end,
+ &vdso_ilp32_pages, &vdso_ilp32_pagelist,
+ vdso_ilp32_spec);
+}
+arch_initcall(vdso_ilp32_init);
+#endif
+
int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp)
{
struct mm_struct *mm = current->mm;
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;
+ unsigned long pages = vdso_pages;
+ struct vm_special_mapping *spec = vdso_spec;
+
+#ifdef CONFIG_ARM64_ILP32
+ if (is_ilp32_compat_task()) {
+ pages = vdso_ilp32_pages;
+ spec = vdso_ilp32_spec;
+ }
+#endif

- vdso_text_len = vdso_pages << PAGE_SHIFT;
+ vdso_text_len = pages << PAGE_SHIFT;
/* Be sure to map the data page */
vdso_mapping_len = vdso_text_len + PAGE_SIZE;

@@ -171,7 +212,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
}
ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
VM_READ|VM_MAYREAD,
- &vdso_spec[0]);
+ &spec[0]);
if (IS_ERR(ret))
goto up_fail;

@@ -180,7 +221,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
VM_READ|VM_EXEC|
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
- &vdso_spec[1]);
+ &spec[1]);
if (IS_ERR(ret))
goto up_fail;
--
2.5.0
Yury Norov
2016-01-14 17:30:04 UTC
Permalink
From: Andrew Pinski <***@cavium.com>

Add a separate syscall-table for ILP32, which dispatches either to native
LP64 system call implementation or to compat-syscalls, as appropriate.

Signed-off-by: Andrew Pinski <***@caviumnetworks.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/include/asm/unistd.h | 11 ++++++-
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/entry.S | 12 +++++++-
arch/arm64/kernel/sys_ilp32.c | 63 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+), 3 deletions(-)
create mode 100644 arch/arm64/kernel/sys_ilp32.c

diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 2971dea..5ea18ef 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -13,9 +13,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+#ifdef CONFIG_COMPAT
+#define __ARCH_WANT_COMPAT_STAT64
+#endif
+
+#ifdef CONFIG_ARM64_ILP32
+#define __ARCH_WANT_COMPAT_SYS_PREADV64
+#define __ARCH_WANT_COMPAT_SYS_PWRITEV64
+#endif
+
#ifdef CONFIG_AARCH32_EL0
#define __ARCH_WANT_COMPAT_SYS_GETDENTS64
-#define __ARCH_WANT_COMPAT_STAT64
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
#define __ARCH_WANT_SYS_GETPGRP
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ad7158c..a35f2f8 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o \
../../arm/kernel/opcodes.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 5eb1bb7..f348f58 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -666,9 +666,13 @@ ENDPROC(ret_from_fork)
*/
.align 6
el0_svc:
- adrp stbl, sys_call_table // load syscall table pointer
uxtw scno, w8 // syscall number in w8
mov sc_nr, #__NR_syscalls
+#ifdef CONFIG_ARM64_ILP32
+ ldr x16, [tsk, #TI_FLAGS]
+ tbnz x16, #TIF_32BIT_AARCH64, el0_ilp32_svc // We are using ILP32
+#endif
+ adrp stbl, sys_call_table // load syscall table pointer
el0_svc_naked: // compat entry point
stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number
enable_dbg_and_irq
@@ -688,6 +692,12 @@ ni_sys:
b ret_fast_syscall
ENDPROC(el0_svc)

+#ifdef CONFIG_ARM64_ILP32
+el0_ilp32_svc:
+ adrp stbl, sys_call_ilp32_table // load syscall table pointer
+ b el0_svc_naked
+#endif
+
/*
* This is the really slow path. We're going to be doing context
* switches, and waiting for our parent to respond.
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
new file mode 100644
index 0000000..0659b89
--- /dev/null
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -0,0 +1,63 @@
+/*
+ * AArch64- ILP32 specific system calls implementation
+ *
+ * Copyright (C) 2016 Cavium Inc.
+ * Author: Andrew Pinski <***@cavium.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/msg.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+#include <asm-generic/syscalls.h>
+
+/* Using non-compat syscalls where necessary */
+#define compat_sys_fadvise64_64 sys_fadvise64_64
+#define compat_sys_fallocate sys_fallocate
+#define compat_sys_ftruncate64 sys_ftruncate
+#define compat_sys_lookup_dcookie sys_lookup_dcookie
+#define compat_sys_pread64 sys_pread64
+#define compat_sys_pwrite64 sys_pwrite64
+#define compat_sys_readahead sys_readahead
+#define compat_sys_shmat sys_shmat
+#define compat_sys_sync_file_range sys_sync_file_range
+#define compat_sys_truncate64 sys_truncate
+#define sys_llseek sys_lseek
+#define sys_mmap2 sys_mmap
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#undef __SC_COMP
+#undef __SC_3264
+#undef __SC_COMP_3264
+
+#define __SYSCALL_COMPAT
+#define __SYSCALL(nr, sym) [nr] = sym,
+
+/*
+ * The sys_call_ilp32_table array must be 4K aligned to be accessible from
+ * kernel/entry.S.
+ */
+void *sys_call_ilp32_table[__NR_syscalls] __aligned(4096) = {
+ [0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
--
2.5.0
Yury Norov
2016-01-14 17:30:04 UTC
Permalink
They may be accessed from low-level code, so isolating is a measure to
avoid circular dependencies in header files.

The exact reason for circular dependency is WARN_ON() macro added by Al
Viro in patch "set_restore_sigmask() is never called without SIGPENDING
(and never should be)" [edd63a27]

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
include/linux/thread_bits.h | 55 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/thread_info.h | 44 +-----------------------------------
2 files changed, 56 insertions(+), 43 deletions(-)
create mode 100644 include/linux/thread_bits.h

diff --git a/include/linux/thread_bits.h b/include/linux/thread_bits.h
new file mode 100644
index 0000000..0d05d16
--- /dev/null
+++ b/include/linux/thread_bits.h
@@ -0,0 +1,55 @@
+
+/* thread_bits.h: common low-level thread bits accessors */
+
+#ifndef _LINUX_THREAD_BITS_H
+#define _LINUX_THREAD_BITS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bitops.h>
+#include <asm/thread_info.h>
+
+/*
+ * flag set/clear/test wrappers
+ * - pass TIF_xxxx constants to these functions
+ */
+
+static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+ set_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+ clear_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+ return test_and_set_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+ return test_and_clear_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
+{
+ return test_bit(flag, (unsigned long *)&ti->flags);
+}
+
+#define set_thread_flag(flag) \
+ set_ti_thread_flag(current_thread_info(), flag)
+#define clear_thread_flag(flag) \
+ clear_ti_thread_flag(current_thread_info(), flag)
+#define test_and_set_thread_flag(flag) \
+ test_and_set_ti_thread_flag(current_thread_info(), flag)
+#define test_and_clear_thread_flag(flag) \
+ test_and_clear_ti_thread_flag(current_thread_info(), flag)
+#define test_thread_flag(flag) \
+ test_ti_thread_flag(current_thread_info(), flag)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _LINUX_THREAD_BITS_H */
+
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index ff307b5..c905fec 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -50,8 +50,7 @@ struct restart_block {

extern long do_no_restart_syscall(struct restart_block *parm);

-#include <linux/bitops.h>
-#include <asm/thread_info.h>
+#include <linux/thread_bits.h>

#ifdef __KERNEL__

@@ -61,47 +60,6 @@ extern long do_no_restart_syscall(struct restart_block *parm);
# define THREADINFO_GFP (GFP_KERNEL | __GFP_NOTRACK)
#endif

-/*
- * flag set/clear/test wrappers
- * - pass TIF_xxxx constants to these functions
- */
-
-static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
-{
- set_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
-{
- clear_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
-{
- return test_and_set_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
-{
- return test_and_clear_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
-{
- return test_bit(flag, (unsigned long *)&ti->flags);
-}
-
-#define set_thread_flag(flag) \
- set_ti_thread_flag(current_thread_info(), flag)
-#define clear_thread_flag(flag) \
- clear_ti_thread_flag(current_thread_info(), flag)
-#define test_and_set_thread_flag(flag) \
- test_and_set_ti_thread_flag(current_thread_info(), flag)
-#define test_and_clear_thread_flag(flag) \
- test_and_clear_ti_thread_flag(current_thread_info(), flag)
-#define test_thread_flag(flag) \
- test_ti_thread_flag(current_thread_info(), flag)
-
#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)

#if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
--
2.5.0
Yury Norov
2016-01-14 17:30:04 UTC
Permalink
From: Andrew Pinski <***@cavium.com>

Signed-off-by: Andrew Pinski <***@caviumnetworks.com>
Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
Reviewed-by: David Daney <***@caviumnetworks.com>
---
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/hwcap.h | 4 ++--
arch/arm64/include/asm/processor.h | 6 +++---
arch/arm64/include/asm/ptrace.h | 2 +-
arch/arm64/include/asm/signal32.h | 6 ++++--
arch/arm64/include/asm/unistd.h | 2 +-
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/asm-offsets.c | 2 +-
arch/arm64/kernel/cpufeature.c | 8 ++++----
arch/arm64/kernel/cpuinfo.c | 4 ++--
arch/arm64/kernel/entry.S | 6 +++---
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/ptrace.c | 8 ++++----
arch/arm64/kernel/traps.c | 2 +-
arch/arm64/kernel/vdso.c | 4 ++--
drivers/clocksource/arm_arch_timer.c | 2 +-
16 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 50f559f..63b19f1 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -52,7 +52,7 @@ struct fpsimd_partial_state {
};


-#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+#if defined(__KERNEL__) && defined(CONFIG_AARCH32_EL0)
/* Masks for extracting the FPSR and FPCR from the FPSCR */
#define VFP_FPSCR_STAT_MASK 0xf800009f
#define VFP_FPSCR_CTRL_MASK 0x07f79f00
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 400b80b..2c7fc5d 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -46,7 +46,7 @@
*/
#define ELF_HWCAP (elf_hwcap)

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#define COMPAT_ELF_HWCAP (compat_elf_hwcap)
#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2)
extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
@@ -54,7 +54,7 @@ extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;

enum {
CAP_HWCAP = 1,
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
CAP_COMPAT_HWCAP,
CAP_COMPAT_HWCAP2,
#endif
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 4acb7ca..9c4d95d 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -79,7 +79,7 @@ struct cpu_context {
struct thread_struct {
struct cpu_context cpu_context; /* cpu context */
unsigned long tp_value; /* TLS register */
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
unsigned long tp2_value;
#endif
struct fpsimd_state fpsimd_state;
@@ -88,7 +88,7 @@ struct thread_struct {
struct debug_info debug; /* debugging */
};

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#define task_user_tls(t) \
({ \
unsigned long *__tls; \
@@ -119,7 +119,7 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc,
regs->sp = sp;
}

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
unsigned long sp)
{
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index e9e5467..95eff51 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -120,7 +120,7 @@ struct pt_regs {

#define arch_has_single_step() (1)

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#define compat_thumb_mode(regs) \
(((regs)->pstate & COMPAT_PSR_T_BIT))
#else
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
index eeaa975..e68fcce 100644
--- a/arch/arm64/include/asm/signal32.h
+++ b/arch/arm64/include/asm/signal32.h
@@ -17,7 +17,9 @@
#define __ASM_SIGNAL32_H

#ifdef __KERNEL__
-#ifdef CONFIG_COMPAT
+
+#ifdef CONFIG_AARCH32_EL0
+
#include <linux/compat.h>

#define AARCH32_KERN_SIGRET_CODE_OFFSET 0x500
@@ -47,6 +49,6 @@ static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t
static inline void compat_setup_restart_syscall(struct pt_regs *regs)
{
}
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */
#endif /* __KERNEL__ */
#endif /* __ASM_SIGNAL32_H */
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 41e58fe..2971dea 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#define __ARCH_WANT_COMPAT_SYS_GETDENTS64
#define __ARCH_WANT_COMPAT_STAT64
#define __ARCH_WANT_SYS_GETHOSTNAME
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 474691f..bf75a7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -25,7 +25,7 @@ OBJCOPYFLAGS := --prefix-symbols=__efistub_
$(obj)/%.stub.o: $(obj)/%.o FORCE
$(call if_changed,objcopy)

-arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
+arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o \
../../arm/kernel/opcodes.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 25de8b2..0d4f1e7 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -51,7 +51,7 @@ int main(void)
DEFINE(S_X7, offsetof(struct pt_regs, regs[7]));
DEFINE(S_LR, offsetof(struct pt_regs, regs[30]));
DEFINE(S_SP, offsetof(struct pt_regs, sp));
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
DEFINE(S_COMPAT_SP, offsetof(struct pt_regs, compat_sp));
#endif
DEFINE(S_PSTATE, offsetof(struct pt_regs, pstate));
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 0669c63..20956cd 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -30,7 +30,7 @@
unsigned long elf_hwcap __read_mostly;
EXPORT_SYMBOL_GPL(elf_hwcap);

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#define COMPAT_ELF_HWCAP_DEFAULT \
(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
@@ -674,7 +674,7 @@ static const struct arm64_cpu_capabilities arm64_hwcaps[] = {
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_ATOMICS_SHIFT, 2, CAP_HWCAP, HWCAP_ATOMICS),
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, 0, CAP_HWCAP, HWCAP_FP),
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, 0, CAP_HWCAP, HWCAP_ASIMD),
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
@@ -690,7 +690,7 @@ static void cap_set_hwcap(const struct arm64_cpu_capabilities *cap)
case CAP_HWCAP:
elf_hwcap |= cap->hwcap;
break;
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
case CAP_COMPAT_HWCAP:
compat_elf_hwcap |= (u32)cap->hwcap;
break;
@@ -713,7 +713,7 @@ static bool __maybe_unused cpus_have_hwcap(const struct arm64_cpu_capabilities *
case CAP_HWCAP:
rc = (elf_hwcap & cap->hwcap) != 0;
break;
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
case CAP_COMPAT_HWCAP:
rc = (compat_elf_hwcap & (u32)cap->hwcap) != 0;
break;
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 212ae63..4a4602d 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -125,7 +125,7 @@ static int c_show(struct seq_file *m, void *v)
*/
seq_puts(m, "Features\t:");
if (personality(current->personality) == PER_LINUX32) {
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
for (j = 0; compat_hwcap_str[j]; j++)
if (compat_elf_hwcap & (1 << j))
seq_printf(m, " %s", compat_hwcap_str[j]);
@@ -133,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
for (j = 0; compat_hwcap2_str[j]; j++)
if (compat_elf_hwcap2 & (1 << j))
seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */
} else {
for (j = 0; hwcap_str[j]; j++)
if (elf_hwcap & (1 << j))
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 7ed3d75..5eb1bb7 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -212,7 +212,7 @@ ENTRY(vectors)
ventry el0_fiq_invalid // FIQ 64-bit EL0
ventry el0_error_invalid // Error 64-bit EL0

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
ventry el0_sync_compat // Synchronous 32-bit EL0
ventry el0_irq_compat // IRQ 32-bit EL0
ventry el0_fiq_invalid_compat // FIQ 32-bit EL0
@@ -252,7 +252,7 @@ el0_error_invalid:
inv_entry 0, BAD_ERROR
ENDPROC(el0_error_invalid)

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
el0_fiq_invalid_compat:
inv_entry 0, BAD_FIQ, 32
ENDPROC(el0_fiq_invalid_compat)
@@ -414,7 +414,7 @@ el0_sync:
b.ge el0_dbg
b el0_inv

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
.align 6
el0_sync_compat:
kernel_entry 0, 32
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 23cfc08..a554e3a 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -507,7 +507,7 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems
mov x0, #0x33ff
msr cptr_el2, x0 // Disable copro. traps to EL2

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
msr hstr_el2, xzr // Disable CP15 traps to EL2
#endif

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 1971f49..6b02f26 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -76,7 +76,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
.si_addr = (void __user *)(bkpt->trigger),
};

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
int i;

if (!is_compat_task())
@@ -651,7 +651,7 @@ static const struct user_regset_view user_aarch64_view = {
.regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
};

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#include <linux/compat.h>

enum compat_regset {
@@ -1186,11 +1186,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,

return ret;
}
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */

const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
/*
* Core dumping of 32-bit tasks or compat ptrace requests must use the
* user_aarch32_view compatible with arm32. Native ptrace requests on
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e9b9b53..b50fced 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -368,7 +368,7 @@ long compat_arm_syscall(struct pt_regs *regs);

asmlinkage long do_ni_syscall(struct pt_regs *regs)
{
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
long ret;
if (is_compat_task()) {
ret = compat_arm_syscall(regs);
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 97bc68f..26352a6 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -49,7 +49,7 @@ static union {
} vdso_data_store __page_aligned_data;
struct vdso_data *vdso_data = &vdso_data_store.data;

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
/*
* Create and map the vectors page for AArch32 tasks.
*/
@@ -107,7 +107,7 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)

return PTR_ERR_OR_ZERO(ret);
}
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */

static struct vm_special_mapping vdso_spec[2];

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index c64d543..35461e1 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -303,7 +303,7 @@ static void arch_timer_evtstrm_enable(int divider)
| ARCH_TIMER_VIRT_EVT_EN;
arch_timer_set_cntkctl(cntkctl);
elf_hwcap |= HWCAP_EVTSTRM;
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
#endif
}
--
2.5.0
Yury Norov
2016-01-14 17:30:05 UTC
Permalink
From: Andrew Pinski <***@cavium.com>

The kernel needs to be compiled as a LP64 binary for ARM64, even when
using a compiler that defaults to code-generation for the ILP32 ABI.
Consequently, we need to explicitly pass '-mabi=lp64' (supported on
gcc-4.9 and newer).

Signed-off-by: Andrew Pinski <***@caviumnetworks.com>
Signed-off-by: Philipp Tomsich <***@theobroma-systems.com>
Signed-off-by: Christoph Muellner <***@theobroma-systems.com>
Signed-off-by: Yury Norov <***@caviumnetworks.com>
Reviewed-by: David Daney <***@caviumnetworks.com>
---
arch/arm64/Makefile | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index cd822d8..d6668a8 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -29,14 +29,19 @@ endif
KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr)
KBUILD_AFLAGS += $(lseinstr)

+KBUILD_CFLAGS += $(call cc-option,-mabi=lp64)
+KBUILD_AFLAGS += $(call cc-option,-mabi=lp64)
+
ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
KBUILD_CPPFLAGS += -mbig-endian
AS += -EB
LD += -EB
+LDFLAGS += -maarch64linuxb
else
KBUILD_CPPFLAGS += -mlittle-endian
AS += -EL
LD += -EL
+LDFLAGS += -maarch64linux
endif

CHECKFLAGS += -D__aarch64__
--
2.5.0
Yury Norov
2016-01-14 17:30:05 UTC
Permalink
As we support more than one compat formats, it looks more reasonable
to not use fs/compat_binfmt.c. Custom binfmt_elf32.c allows to move aarch32
specific definitions there and make code more maintainable and readable.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/Kconfig | 1 -
arch/arm64/include/asm/elf.h | 24 ------------------------
arch/arm64/include/asm/hwcap.h | 2 --
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 33 +++++++++++++++++++++++++++++++++
5 files changed, 34 insertions(+), 28 deletions(-)
create mode 100644 arch/arm64/kernel/binfmt_elf32.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index aeddddd..2c205a4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -768,7 +768,6 @@ config COMPAT
config AARCH32_EL0
bool "Kernel support for 32-bit EL0"
depends on ARM64_4K_PAGES || EXPERT
- select COMPAT_BINFMT_ELF
select HAVE_UID16
select OLD_SIGSUSPEND3
select COMPAT_OLD_SIGACTION
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 5e27a64..d33ca62 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -159,12 +159,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,

#ifdef CONFIG_COMPAT

-#ifdef __AARCH64EB__
-#define COMPAT_ELF_PLATFORM ("v8b")
-#else
-#define COMPAT_ELF_PLATFORM ("v8l")
-#endif
-
#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3)

/* AArch32 registers. */
@@ -172,24 +166,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
typedef unsigned int compat_elf_greg_t;
typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];

-/* AArch32 EABI. */
-#define EF_ARM_EABI_MASK 0xff000000
-#define compat_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \
- ((x)->e_flags & EF_ARM_EABI_MASK))
-
-#define compat_start_thread compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex) \
-do { \
- clear_thread_flag(TIF_32BIT_AARCH64); \
- set_thread_flag(TIF_32BIT); \
-} while (0)
-
-#define COMPAT_ARCH_DLINFO
-extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
- int uses_interp);
-#define compat_arch_setup_additional_pages \
- aarch32_setup_vectors_page
-
#endif /* CONFIG_COMPAT */

#endif
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 2c7fc5d..99dfd92 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -47,8 +47,6 @@
#define ELF_HWCAP (elf_hwcap)

#ifdef CONFIG_AARCH32_EL0
-#define COMPAT_ELF_HWCAP (compat_elf_hwcap)
-#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2)
extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
#endif

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index bf75a7f..f1b798a 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -27,7 +27,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE

arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o \
- ../../arm/kernel/opcodes.o
+ ../../arm/kernel/opcodes.o binfmt_elf32.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
new file mode 100644
index 0000000..5487872
--- /dev/null
+++ b/arch/arm64/kernel/binfmt_elf32.c
@@ -0,0 +1,33 @@
+/*
+ * Support for AArch32 Linux ELF binaries.
+ */
+
+/* AArch32 EABI. */
+#define EF_ARM_EABI_MASK 0xff000000
+#define compat_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \
+ ((x)->e_flags & EF_ARM_EABI_MASK))
+
+#define compat_start_thread compat_start_thread
+#define COMPAT_SET_PERSONALITY(ex) \
+do { \
+ clear_thread_flag(TIF_32BIT_AARCH64); \
+ set_thread_flag(TIF_32BIT); \
+} while (0)
+
+#define COMPAT_ARCH_DLINFO
+#define COMPAT_ELF_HWCAP (compat_elf_hwcap)
+#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2)
+
+#ifdef __AARCH64EB__
+#define COMPAT_ELF_PLATFORM ("v8b")
+#else
+#define COMPAT_ELF_PLATFORM ("v8l")
+#endif
+
+#define compat_arch_setup_additional_pages \
+ aarch32_setup_vectors_page
+struct linux_binprm;
+extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
+ int uses_interp);
+
+#include "../../../fs/compat_binfmt_elf.c"
--
2.5.0
Yury Norov
2016-01-14 17:30:05 UTC
Permalink
ILP32 uses AARCH32 compat structures and syscall handlers for signals.
But ILP32 struct rt_sigframe differs from both LP64 and AARCH32. So some
specific mechanism is needed to take care of it.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/include/asm/signal_ilp32.h | 34 +++++++++
arch/arm64/kernel/Makefile | 3 +-
arch/arm64/kernel/entry_ilp32.S | 23 ++++++
arch/arm64/kernel/signal.c | 3 +
arch/arm64/kernel/signal_ilp32.c | 128 ++++++++++++++++++++++++++++++++++
arch/arm64/kernel/sys_ilp32.c | 3 +
6 files changed, 193 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/signal_ilp32.h
create mode 100644 arch/arm64/kernel/entry_ilp32.S
create mode 100644 arch/arm64/kernel/signal_ilp32.c

diff --git a/arch/arm64/include/asm/signal_ilp32.h b/arch/arm64/include/asm/signal_ilp32.h
new file mode 100644
index 0000000..30eff23
--- /dev/null
+++ b/arch/arm64/include/asm/signal_ilp32.h
@@ -0,0 +1,34 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGNAL_ILP32_H
+#define __ASM_SIGNAL_ILP32_H
+
+#ifdef CONFIG_ARM64_ILP32
+
+#include <linux/compat.h>
+
+int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs);
+
+#else
+
+static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
+#endif /* __ASM_SIGNAL_ILP32_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 4981933..c846626 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,7 +28,8 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o \
../../arm/kernel/opcodes.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o \
+ signal_ilp32.o entry_ilp32.o
arm64-obj-$(CONFIG_COMPAT) += signal32_common.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
diff --git a/arch/arm64/kernel/entry_ilp32.S b/arch/arm64/kernel/entry_ilp32.S
new file mode 100644
index 0000000..5063172
--- /dev/null
+++ b/arch/arm64/kernel/entry_ilp32.S
@@ -0,0 +1,23 @@
+/*
+ * ILP32 system call wrappers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(ilp32_sys_rt_sigreturn_wrapper)
+ mov x0, sp
+ b ilp32_sys_rt_sigreturn
+ENDPROC(ilp32_sys_rt_sigreturn_wrapper)
+
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index a742a61..f8d4c92 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -35,6 +35,7 @@
#include <asm/signal32.h>
#include <asm/vdso.h>
#include <asm/signal_common.h>
+#include <asm/signal_ilp32.h>

/*
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
@@ -300,6 +301,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
else
ret = compat_setup_frame(usig, ksig, oldset, regs);
+ } else if (is_ilp32_compat_task()) {
+ ret = ilp32_setup_rt_frame(usig, ksig, oldset, regs);
} else {
ret = setup_rt_frame(usig, ksig, oldset, regs);
}
diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
new file mode 100644
index 0000000..b635a21
--- /dev/null
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -0,0 +1,128 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2016 Cavium Networks.
+ * Yury Norov <***@caviumnetworks.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/ratelimit.h>
+
+#include <asm/esr.h>
+#include <asm/fpsimd.h>
+#include <asm/signal32_common.h>
+#include <asm/signal_common.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ucontext.h>
+
+struct ilp32_rt_sigframe {
+ struct compat_siginfo info;
+ struct sigframe sig;
+};
+
+asmlinkage int ilp32_sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct ilp32_rt_sigframe __user *frame;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current->restart_block.fn = do_no_restart_syscall;
+
+ /*
+ * Since we stacked the signal on a 128-bit boundary,
+ * then 'sp' should be word aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ if (regs->sp & 15)
+ goto badframe;
+
+ frame = (struct ilp32_rt_sigframe __user *)regs->sp;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
+ goto badframe;
+
+ if (restore_sigframe(regs, &frame->sig))
+ goto badframe;
+
+ if (restore_altstack(&frame->sig.uc.uc_stack))
+ goto badframe;
+
+ return regs->regs[0];
+
+badframe:
+ if (show_unhandled_signals)
+ pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
+ current->comm, task_pid_nr(current), __func__,
+ regs->pc, regs->compat_sp);
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+static struct ilp32_rt_sigframe __user *ilp32_get_sigframe(struct ksignal *ksig,
+ struct pt_regs *regs)
+{
+ unsigned long sp, sp_top;
+ struct ilp32_rt_sigframe __user *frame;
+
+ sp = sp_top = sigsp(regs->sp, ksig);
+
+ sp = (sp - sizeof(struct ilp32_rt_sigframe)) & ~15;
+ frame = (struct ilp32_rt_sigframe __user *)sp;
+
+ /*
+ * Check that we can actually write to the signal frame.
+ */
+ if (!access_ok(VERIFY_WRITE, frame, sp_top - sp))
+ frame = NULL;
+
+ return frame;
+}
+
+/*
+ * ILP32 signal handling routines called from signal.c
+ */
+int ilp32_setup_rt_frame(int usig, struct ksignal *ksig,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct ilp32_rt_sigframe __user *frame;
+ int err = 0;
+
+ frame = ilp32_get_sigframe(ksig, regs);
+
+ if (!frame)
+ return 1;
+
+ __put_user_error(0, &frame->sig.uc.uc_flags, err);
+ __put_user_error(NULL, &frame->sig.uc.uc_link, err);
+
+ err |= __save_altstack(&frame->sig.uc.uc_stack, regs->sp);
+ err |= setup_sigframe(&frame->sig, regs, set);
+ if (err == 0) {
+ setup_return(regs, &ksig->ka, frame,
+ offsetof(struct ilp32_rt_sigframe, sig), usig);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
+ regs->regs[1] = (unsigned long)&frame->info;
+ regs->regs[2] = (unsigned long)&frame->sig.uc;
+ }
+ }
+
+ return err;
+}
+
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
index 0659b89..bed308c 100644
--- a/arch/arm64/kernel/sys_ilp32.c
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -43,6 +43,9 @@
#define sys_llseek sys_lseek
#define sys_mmap2 sys_mmap

+asmlinkage long ilp32_sys_rt_sigreturn_wrapper(void);
+#define compat_sys_rt_sigreturn ilp32_sys_rt_sigreturn_wrapper
+
#include <asm/syscall.h>

#undef __SYSCALL
--
2.5.0
Andreas Schwab
2016-02-29 08:30:01 UTC
Permalink
Post by Yury Norov
diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
new file mode 100644
index 0000000..b635a21
--- /dev/null
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -0,0 +1,128 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2016 Cavium Networks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/ratelimit.h>
+
+#include <asm/esr.h>
+#include <asm/fpsimd.h>
+#include <asm/signal32_common.h>
+#include <asm/signal_common.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ucontext.h>
+
+struct ilp32_rt_sigframe {
+ struct compat_siginfo info;
+ struct sigframe sig;
+};
+
+asmlinkage int ilp32_sys_rt_sigreturn(struct pt_regs *regs)
This function must be defined to return long, lest you truncate the
return value of the interrupted syscall.

Andreas.
--
Andreas Schwab, SUSE Labs, ***@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Yury Norov
2016-01-14 17:30:05 UTC
Permalink
Here new ptrace syscall handler is introsuced to avoid run-time detection of the
task type.

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/include/asm/unistd32.h | 2 +-
arch/arm64/kernel/ptrace.c | 50 ++++++++++++++++++++++++++++++++++++++-
arch/arm64/kernel/sys32.c | 1 +
include/linux/ptrace.h | 6 +++++
kernel/ptrace.c | 10 ++++----
5 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 5b925b7..f57bbe3 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -74,7 +74,7 @@ __SYSCALL(__NR_getuid, sys_getuid16)
/* 25 was sys_stime */
__SYSCALL(25, sys_ni_syscall)
#define __NR_ptrace 26
-__SYSCALL(__NR_ptrace, compat_sys_ptrace)
+__SYSCALL(__NR_ptrace, compat_sys_aarch32_ptrace)
/* 27 was sys_alarm */
__SYSCALL(27, sys_ni_syscall)
/* 28 was sys_fstat */
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index c166548..607a140 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -29,6 +29,7 @@
#include <linux/user.h>
#include <linux/seccomp.h>
#include <linux/security.h>
+#include <linux/syscalls.h>
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/uaccess.h>
@@ -1108,7 +1109,7 @@ static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
}
#endif /* CONFIG_HAVE_HW_BREAKPOINT */

-long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+static long compat_a32_ptrace(struct task_struct *child, compat_long_t request,
compat_ulong_t caddr, compat_ulong_t cdata)
{
unsigned long addr = caddr;
@@ -1185,8 +1186,55 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,

return ret;
}
+
+COMPAT_SYSCALL_DEFINE4(aarch32_ptrace, compat_long_t, request, compat_long_t, pid,
+ compat_long_t, addr, compat_long_t, data)
+{
+ struct task_struct *child;
+ long ret;
+
+ if (request == PTRACE_TRACEME) {
+ ret = ptrace_traceme();
+ goto out;
+ }
+
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
+ goto out;
+ }
+
+ if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
+ ret = ptrace_attach(child, request, addr, data);
+ goto out_put_task_struct;
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL ||
+ request == PTRACE_INTERRUPT);
+ if (!ret) {
+ ret = compat_a32_ptrace(child, request, addr, data);
+ if (ret || request != PTRACE_DETACH)
+ ptrace_unfreeze_traced(child);
+ }
+
+ out_put_task_struct:
+ put_task_struct(child);
+ out:
+ return ret;
+}
+
#endif /* CONFIG_AARCH32_EL0 */

+#ifdef CONFIG_COMPAT
+
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t caddr, compat_ulong_t cdata)
+{
+ return compat_ptrace_request(child, request, caddr, cdata);
+}
+
+#endif /* CONFIG_COMPAT */
+
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
#ifdef CONFIG_AARCH32_EL0
diff --git a/arch/arm64/kernel/sys32.c b/arch/arm64/kernel/sys32.c
index a40b134..3752443 100644
--- a/arch/arm64/kernel/sys32.c
+++ b/arch/arm64/kernel/sys32.c
@@ -38,6 +38,7 @@ asmlinkage long compat_sys_fadvise64_64_wrapper(void);
asmlinkage long compat_sys_sync_file_range2_wrapper(void);
asmlinkage long compat_sys_fallocate_wrapper(void);
asmlinkage long compat_sys_mmap2_wrapper(void);
+asmlinkage long compat_sys_aarch32_ptrace(void);

#undef __SYSCALL
#define __SYSCALL(nr, sym) [nr] = sym,
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 061265f..c38d068 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -75,6 +75,12 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
unsigned long data);
int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
unsigned long data);
+int ptrace_traceme(void);
+struct task_struct *ptrace_get_task_struct(pid_t pid);
+int ptrace_attach(struct task_struct *task, long request,
+ unsigned long addr, unsigned long flags);
+int ptrace_check_attach(struct task_struct *child, bool ignore_state);
+void ptrace_unfreeze_traced(struct task_struct *task);

/**
* ptrace_parent - return the task that is tracing the given task
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index b760bae..8f688ae 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -137,7 +137,7 @@ static bool ptrace_freeze_traced(struct task_struct *task)
return ret;
}

-static void ptrace_unfreeze_traced(struct task_struct *task)
+void ptrace_unfreeze_traced(struct task_struct *task)
{
if (task->state != __TASK_TRACED)
return;
@@ -169,7 +169,7 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
* RETURNS:
* 0 on success, -ESRCH if %child is not ready.
*/
-static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
+int ptrace_check_attach(struct task_struct *child, bool ignore_state)
{
int ret = -ESRCH;

@@ -270,7 +270,7 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
return !err;
}

-static int ptrace_attach(struct task_struct *task, long request,
+int ptrace_attach(struct task_struct *task, long request,
unsigned long addr,
unsigned long flags)
{
@@ -378,7 +378,7 @@ out:
* Performs checks and sets PT_PTRACED.
* Should be used by all ptrace implementations for PTRACE_TRACEME.
*/
-static int ptrace_traceme(void)
+ int ptrace_traceme(void)
{
int ret = -EPERM;

@@ -1028,7 +1028,7 @@ int ptrace_request(struct task_struct *child, long request,
return ret;
}

-static struct task_struct *ptrace_get_task_struct(pid_t pid)
+struct task_struct *ptrace_get_task_struct(pid_t pid)
{
struct task_struct *child;
--
2.5.0
Yury Norov
2016-01-14 17:30:05 UTC
Permalink
to handle ILP32 binaries

Signed-off-by: Yury Norov <***@caviumnetworks.com>
---
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/binfmt_ilp32.c | 91 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+)
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index f1b798a..ad7158c 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,6 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o \
../../arm/kernel/opcodes.o binfmt_elf32.o
+arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
new file mode 100644
index 0000000..a934fd4
--- /dev/null
+++ b/arch/arm64/kernel/binfmt_ilp32.c
@@ -0,0 +1,91 @@
+/*
+ * Support for ILP32 Linux/aarch64 ELF binaries.
+ */
+
+#include <linux/elfcore-compat.h>
+#include <linux/time.h>
+
+#undef ELF_CLASS
+#define ELF_CLASS ELFCLASS32
+
+#undef elfhdr
+#undef elf_phdr
+#undef elf_shdr
+#undef elf_note
+#undef elf_addr_t
+#define elfhdr elf32_hdr
+#define elf_phdr elf32_phdr
+#define elf_shdr elf32_shdr
+#define elf_note elf32_note
+#define elf_addr_t Elf32_Addr
+
+/*
+ * Some data types as stored in coredump.
+ */
+#define user_long_t compat_long_t
+#define user_siginfo_t compat_siginfo_t
+#define copy_siginfo_to_user copy_siginfo_to_user32
+
+/*
+ * The machine-dependent core note format types are defined in elfcore-compat.h,
+ * which requires asm/elf.h to define compat_elf_gregset_t et al.
+ */
+#define elf_prstatus compat_elf_prstatus
+#define elf_prpsinfo compat_elf_prpsinfo
+
+/*
+ * Compat version of cputime_to_compat_timeval, perhaps this
+ * should be an inline in <linux/compat.h>.
+ */
+static void cputime_to_compat_timeval(const cputime_t cputime,
+ struct compat_timeval *value)
+{
+ struct timeval tv;
+ cputime_to_timeval(cputime, &tv);
+ value->tv_sec = tv.tv_sec;
+ value->tv_usec = tv.tv_usec;
+}
+
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
+
+/* AARCH64 ILP32 EABI. */
+#undef elf_check_arch
+#define elf_check_arch(x) (((x)->e_machine == EM_AARCH64) \
+ && (x)->e_ident[EI_CLASS] == ELFCLASS32)
+
+#undef SET_PERSONALITY
+#define SET_PERSONALITY(ex) \
+do { \
+ set_thread_flag(TIF_32BIT_AARCH64); \
+ clear_thread_flag(TIF_32BIT); \
+} while (0)
+
+#undef ARCH_DLINFO
+#define ARCH_DLINFO \
+do { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, \
+ (elf_addr_t)(long)current->mm->context.vdso); \
+} while (0)
+
+#ifdef __AARCH64EB__
+#define COMPAT_ELF_PLATFORM ("aarch64_be:ilp32")
+#else
+#define COMPAT_ELF_PLATFORM ("aarch64:ilp32")
+#endif
+
+#undef ELF_HWCAP
+#undef ELF_HWCAP2
+#define ELF_HWCAP ((u32) elf_hwcap)
+#define ELF_HWCAP2 ((u32) (elf_hwcap >> 32))
+
+/*
+ * Rename a few of the symbols that binfmt_elf.c will define.
+ * These are all local so the names don't really matter, but it
+ * might make some debugging less confusing not to duplicate them.
+ */
+#define elf_format compat_elf_format
+#define init_elf_binfmt init_compat_elf_binfmt
+#define exit_elf_binfmt exit_compat_elf_binfmt
+
+#include "../../../fs/binfmt_elf.c"
--
2.5.0
Zhangjian (Bamvor)
2016-01-18 13:20:02 UTC
Permalink
Hi, Yury

On 2016/1/15 1:22, Yury Norov wrote:
[...]
arm64: compat: change config dependences to aarch32
There is no this patch in this series. 05/21 is missing:)

Regards

Bamvor
arm64:ilp32: add vdso-ilp32 and use for signal return
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
thread: move thread bits accessors to separated file
arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
arm64: introduce binfmt_elf32.c
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
arm64: signal: wrap struct ucontext, fp and lr with struct sigframe
arm64: signal: share lp64 signal routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: ilp32: introduce ilp32-specific handlers for sigframe
all: s390: make compat wrappers the generic solution
arm64: ilp32: wrap syscalls to remove top 32-bit vulnerability
Documentation/arm64/ilp32.txt | 13 ++
arch/Kconfig | 4 +
arch/arm64/Kconfig | 17 +-
arch/arm64/Makefile | 5 +
arch/arm64/include/asm/compat.h | 19 +-
arch/arm64/include/asm/compat_wrapper.h | 14 ++
arch/arm64/include/asm/elf.h | 32 +--
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/hwcap.h | 6 +-
arch/arm64/include/asm/is_compat.h | 84 ++++++++
arch/arm64/include/asm/memory.h | 3 +-
arch/arm64/include/asm/processor.h | 11 +-
arch/arm64/include/asm/ptrace.h | 2 +-
arch/arm64/include/asm/signal32.h | 6 +-
arch/arm64/include/asm/signal32_common.h | 25 +++
arch/arm64/include/asm/signal_common.h | 39 ++++
arch/arm64/include/asm/signal_ilp32.h | 34 ++++
arch/arm64/include/asm/thread_info.h | 3 +-
arch/arm64/include/asm/unistd.h | 11 +-
arch/arm64/include/asm/unistd32.h | 2 +-
arch/arm64/include/asm/vdso.h | 6 +
arch/arm64/include/uapi/asm/bitsperlong.h | 9 +-
arch/arm64/kernel/Makefile | 12 +-
arch/arm64/kernel/asm-offsets.c | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 33 ++++
arch/arm64/kernel/binfmt_ilp32.c | 91 +++++++++
arch/arm64/kernel/cpufeature.c | 8 +-
arch/arm64/kernel/cpuinfo.c | 4 +-
arch/arm64/kernel/entry.S | 18 +-
arch/arm64/kernel/entry_ilp32.S | 23 +++
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 10 +-
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 5 +-
arch/arm64/kernel/ptrace.c | 65 ++++++-
arch/arm64/kernel/signal.c | 47 +++--
arch/arm64/kernel/signal32.c | 85 --------
arch/arm64/kernel/signal32_common.c | 115 +++++++++++
arch/arm64/kernel/signal_ilp32.c | 128 ++++++++++++
arch/arm64/kernel/sys32.c | 1 +
arch/arm64/kernel/sys_ilp32.c | 69 +++++++
arch/arm64/kernel/traps.c | 5 +-
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 72 +++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 ++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++
arch/arm64/kernel/vdso.c | 65 +++++--
arch/s390/Kconfig | 1 +
arch/s390/include/asm/compat_wrapper.h | 25 +++
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/compat_linux.c | 6 +
arch/s390/kernel/compat_wrapper.c | 179 -----------------
drivers/clocksource/arm_arch_timer.c | 2 +-
include/linux/compat_wrapper.h | 270 ++++++++++++++++++++++++++
include/linux/ptrace.h | 6 +
include/linux/thread_bits.h | 55 ++++++
include/linux/thread_info.h | 44 +----
include/uapi/asm-generic/unistd.h | 224 ++++++++++-----------
kernel/Makefile | 1 +
kernel/compat_wrapper.c | 167 ++++++++++++++++
kernel/ptrace.c | 10 +-
61 files changed, 1777 insertions(+), 554 deletions(-)
create mode 100644 Documentation/arm64/ilp32.txt
create mode 100644 arch/arm64/include/asm/compat_wrapper.h
create mode 100644 arch/arm64/include/asm/is_compat.h
create mode 100644 arch/arm64/include/asm/signal32_common.h
create mode 100644 arch/arm64/include/asm/signal_common.h
create mode 100644 arch/arm64/include/asm/signal_ilp32.h
create mode 100644 arch/arm64/kernel/binfmt_elf32.c
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
create mode 100644 arch/arm64/kernel/entry_ilp32.S
create mode 100644 arch/arm64/kernel/signal32_common.c
create mode 100644 arch/arm64/kernel/signal_ilp32.c
create mode 100644 arch/arm64/kernel/sys_ilp32.c
create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
create mode 100644 arch/s390/include/asm/compat_wrapper.h
delete mode 100644 arch/s390/kernel/compat_wrapper.c
create mode 100644 include/linux/compat_wrapper.h
create mode 100644 include/linux/thread_bits.h
create mode 100644 kernel/compat_wrapper.c
Andreas Schwab
2016-01-18 13:30:02 UTC
Permalink
Post by Zhangjian (Bamvor)
Hi, Yury
[...]
arm64: compat: change config dependences to aarch32
There is no this patch in this series. 05/21 is missing:)
http://marc.info/?i=1452792198-10718-6-git-send-email-ynorov%20()%20caviumnetworks%20!%20com

Andreas.
--
Andreas Schwab, SUSE Labs, ***@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Bamvor Zhang Jian
2016-01-18 13:50:02 UTC
Permalink
Hi, Andreas
Post by Andreas Schwab
Post by Zhangjian (Bamvor)
Hi, Yury
[...]
arm64: compat: change config dependences to aarch32
There is no this patch in this series. 05/21 is missing:)
http://marc.info/?i=1452792198-10718-6-git-send-email-ynorov%20()%20caviumnetworks%20!%20com
Oops. It is the issue in my filter. I am in the cc in others
patches. So, there are exist in different folders.

Regards

Bamvor
Post by Andreas Schwab
Andreas.
--
-----------------------------
blog: http://aarch64.me
-----------------------------
Zhangjian (Bamvor)
2016-01-29 10:00:02 UTC
Permalink
Hi,
This is still RFC because we have no glibc yet, that correspnds new ABI
introduced here. And so we cannot run tests. LP64 and AARCH32 tests show
no regression though.
Hi,

Glad to see this version. I hope I could test it. Where could I find the
corresponding glibc? I could not find it in
http://github.com/norov/glibc.git. Or is there a plan to do it?

Besides compat wrappers discussed in these series, is there any other
blockers for upstream? I would suppose everyone is intestested in the
result of LTP...

Regards

Bamvor
v3: https://lkml.org/lkml/2014/9/3/704
v4: https://lkml.org/lkml/2015/4/13/691
v5: https://lkml.org/lkml/2015/9/29/911
- time_t, __kenel_off_t and other types turned to be 32-bit
for compatibility reasons (after v5 discussion);
- related changes applied to ILP32 syscall table and handlers;
- ILP32 VDSO code excluded. It's not mandatory, and caused questions
during review process. We definitely make sure we will follow up
with a VDSO later on because it is needed for performance reasons;
- fixed build issues with different combinations of AARCH32 / ILP32
enabling in config;
- ILP32 TLS bug fixed;
- entry32-common.S introduced to hold wrappers needed for both ILP32
and AARCH32_EL0;
- documentation updated according to latest changes;
- rebased to the current head;
- coding style re-checked;
- ILP32 syscall table turned around.
- all structures and system calls are just like AARCH32 ones now. with 2
exceptions: syscalls that take 64-bit parameter in 2 32-bit regosters
are replaced with LP64 version; struct rt_sigframe is constructed both
from LP64 and AARCH32 fields to be consistent with AARCH64 register set;
- documentation rewritten accordingly;
- common code for all 3 ABIs is moved to separated files for easy use,
new headers and objects are introduced, incl: is_compat.h, thread_bits.h,
signal_common.h, signal32_common.h.
- ILP32 VDSO code restored, Nathans comments are addressed;
- patch "arm64: ilp32: force IPC_64 in msgctl, shmctl, semctl" removed, as
Arnd suggested general solution for IPC_64 problem.
- sys_ilp32.c syscall list is fixed according to comments;
- binfmt_elf32.c and binfmt_ilp32.c are introduced to host the code handling
corresponding formats;
- statfs64, fstsatfs64 and mmap wrappers are removed;
- rebased on v4.4-rc8 + http://www.spinics.net/lists/kernel/msg2151759.html
- addressed rfc4 comments;
- turned s390 compat wrappers to be generic and applied it to arm64/ilp32.
Heiko Carsten and Martin Schwidefsky added to CC as s390 maintainers.
arm64: ensure the kernel is compiled for LP64
arm64: rename COMPAT to AARCH32_EL0 in Kconfig
arm64: change some CONFIG_COMPAT over to use CONFIG_AARCH32_EL0
instead
arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
arm64:ilp32: add sys_ilp32.c and a separate table (in entry.S) to use
it
arm64:ilp32: add ARM64_ILP32 to Kconfig
arm64: compat: change config dependences to aarch32
arm64:ilp32: add vdso-ilp32 and use for signal return
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
thread: move thread bits accessors to separated file
arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
arm64: introduce binfmt_elf32.c
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
arm64: signal: wrap struct ucontext, fp and lr with struct sigframe
arm64: signal: share lp64 signal routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: ilp32: introduce ilp32-specific handlers for sigframe
all: s390: make compat wrappers the generic solution
arm64: ilp32: wrap syscalls to remove top 32-bit vulnerability
Documentation/arm64/ilp32.txt | 13 ++
arch/Kconfig | 4 +
arch/arm64/Kconfig | 17 +-
arch/arm64/Makefile | 5 +
arch/arm64/include/asm/compat.h | 19 +-
arch/arm64/include/asm/compat_wrapper.h | 14 ++
arch/arm64/include/asm/elf.h | 32 +--
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/hwcap.h | 6 +-
arch/arm64/include/asm/is_compat.h | 84 ++++++++
arch/arm64/include/asm/memory.h | 3 +-
arch/arm64/include/asm/processor.h | 11 +-
arch/arm64/include/asm/ptrace.h | 2 +-
arch/arm64/include/asm/signal32.h | 6 +-
arch/arm64/include/asm/signal32_common.h | 25 +++
arch/arm64/include/asm/signal_common.h | 39 ++++
arch/arm64/include/asm/signal_ilp32.h | 34 ++++
arch/arm64/include/asm/thread_info.h | 3 +-
arch/arm64/include/asm/unistd.h | 11 +-
arch/arm64/include/asm/unistd32.h | 2 +-
arch/arm64/include/asm/vdso.h | 6 +
arch/arm64/include/uapi/asm/bitsperlong.h | 9 +-
arch/arm64/kernel/Makefile | 12 +-
arch/arm64/kernel/asm-offsets.c | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 33 ++++
arch/arm64/kernel/binfmt_ilp32.c | 91 +++++++++
arch/arm64/kernel/cpufeature.c | 8 +-
arch/arm64/kernel/cpuinfo.c | 4 +-
arch/arm64/kernel/entry.S | 18 +-
arch/arm64/kernel/entry_ilp32.S | 23 +++
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 10 +-
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 5 +-
arch/arm64/kernel/ptrace.c | 65 ++++++-
arch/arm64/kernel/signal.c | 47 +++--
arch/arm64/kernel/signal32.c | 85 --------
arch/arm64/kernel/signal32_common.c | 115 +++++++++++
arch/arm64/kernel/signal_ilp32.c | 128 ++++++++++++
arch/arm64/kernel/sys32.c | 1 +
arch/arm64/kernel/sys_ilp32.c | 69 +++++++
arch/arm64/kernel/traps.c | 5 +-
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 72 +++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 ++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++
arch/arm64/kernel/vdso.c | 65 +++++--
arch/s390/Kconfig | 1 +
arch/s390/include/asm/compat_wrapper.h | 25 +++
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/compat_linux.c | 6 +
arch/s390/kernel/compat_wrapper.c | 179 -----------------
drivers/clocksource/arm_arch_timer.c | 2 +-
include/linux/compat_wrapper.h | 270 ++++++++++++++++++++++++++
include/linux/ptrace.h | 6 +
include/linux/thread_bits.h | 55 ++++++
include/linux/thread_info.h | 44 +----
include/uapi/asm-generic/unistd.h | 224 ++++++++++-----------
kernel/Makefile | 1 +
kernel/compat_wrapper.c | 167 ++++++++++++++++
kernel/ptrace.c | 10 +-
61 files changed, 1777 insertions(+), 554 deletions(-)
create mode 100644 Documentation/arm64/ilp32.txt
create mode 100644 arch/arm64/include/asm/compat_wrapper.h
create mode 100644 arch/arm64/include/asm/is_compat.h
create mode 100644 arch/arm64/include/asm/signal32_common.h
create mode 100644 arch/arm64/include/asm/signal_common.h
create mode 100644 arch/arm64/include/asm/signal_ilp32.h
create mode 100644 arch/arm64/kernel/binfmt_elf32.c
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
create mode 100644 arch/arm64/kernel/entry_ilp32.S
create mode 100644 arch/arm64/kernel/signal32_common.c
create mode 100644 arch/arm64/kernel/signal_ilp32.c
create mode 100644 arch/arm64/kernel/sys_ilp32.c
create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
create mode 100644 arch/s390/include/asm/compat_wrapper.h
delete mode 100644 arch/s390/kernel/compat_wrapper.c
create mode 100644 include/linux/compat_wrapper.h
create mode 100644 include/linux/thread_bits.h
create mode 100644 kernel/compat_wrapper.c
Yury Norov
2016-01-29 17:20:04 UTC
Permalink
Post by Zhangjian (Bamvor)
Hi,
This is still RFC because we have no glibc yet, that correspnds new ABI
introduced here. And so we cannot run tests. LP64 and AARCH32 tests show
no regression though.
Hi,
Glad to see this version. I hope I could test it. Where could I find the
corresponding glibc? I could not find it in
http://github.com/norov/glibc.git. Or is there a plan to do it?
Besides compat wrappers discussed in these series, is there any other
blockers for upstream? I would suppose everyone is intestested in the
result of LTP...
Regards
Bamvor
Hi, Bamvor,

Just to order all commits, I created new ILP32 branch at [1], that
based on 4.4 kernel + [2] + [3]. There's no new glibc suitable for
rfc5. But I started with it, and I hope there will be progress soon.

You cannot run LTP as there are some syscalls that are called during
dynamic loading that fail, but you can try to build your test statically
agaginst current glibc, and there's a big chance it will work.
I have a set of 'hello-worlds' working that way.

If you have some specific test that you cannot run, you can send it to
me, and I will take a look on it.

Yury

[1] https://github.com/norov/linux/tree/rfc5
[2] http://permalink.gmane.org/gmane.linux.kernel/2116021
[3] http://comments.gmane.org/gmane.linux.kernel/2134747
Post by Zhangjian (Bamvor)
v3: https://lkml.org/lkml/2014/9/3/704
v4: https://lkml.org/lkml/2015/4/13/691
v5: https://lkml.org/lkml/2015/9/29/911
- time_t, __kenel_off_t and other types turned to be 32-bit
for compatibility reasons (after v5 discussion);
- related changes applied to ILP32 syscall table and handlers;
- ILP32 VDSO code excluded. It's not mandatory, and caused questions
during review process. We definitely make sure we will follow up
with a VDSO later on because it is needed for performance reasons;
- fixed build issues with different combinations of AARCH32 / ILP32
enabling in config;
- ILP32 TLS bug fixed;
- entry32-common.S introduced to hold wrappers needed for both ILP32
and AARCH32_EL0;
- documentation updated according to latest changes;
- rebased to the current head;
- coding style re-checked;
- ILP32 syscall table turned around.
- all structures and system calls are just like AARCH32 ones now. with 2
exceptions: syscalls that take 64-bit parameter in 2 32-bit regosters
are replaced with LP64 version; struct rt_sigframe is constructed both
from LP64 and AARCH32 fields to be consistent with AARCH64 register set;
- documentation rewritten accordingly;
- common code for all 3 ABIs is moved to separated files for easy use,
new headers and objects are introduced, incl: is_compat.h, thread_bits.h,
signal_common.h, signal32_common.h.
- ILP32 VDSO code restored, Nathans comments are addressed;
- patch "arm64: ilp32: force IPC_64 in msgctl, shmctl, semctl" removed, as
Arnd suggested general solution for IPC_64 problem.
- sys_ilp32.c syscall list is fixed according to comments;
- binfmt_elf32.c and binfmt_ilp32.c are introduced to host the code handling
corresponding formats;
- statfs64, fstsatfs64 and mmap wrappers are removed;
- rebased on v4.4-rc8 + http://www.spinics.net/lists/kernel/msg2151759.html
- addressed rfc4 comments;
- turned s390 compat wrappers to be generic and applied it to arm64/ilp32.
Heiko Carsten and Martin Schwidefsky added to CC as s390 maintainers.
arm64: ensure the kernel is compiled for LP64
arm64: rename COMPAT to AARCH32_EL0 in Kconfig
arm64: change some CONFIG_COMPAT over to use CONFIG_AARCH32_EL0
instead
arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
arm64:ilp32: add sys_ilp32.c and a separate table (in entry.S) to use
it
arm64:ilp32: add ARM64_ILP32 to Kconfig
arm64: compat: change config dependences to aarch32
arm64:ilp32: add vdso-ilp32 and use for signal return
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
thread: move thread bits accessors to separated file
arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
arm64: introduce binfmt_elf32.c
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
arm64: signal: wrap struct ucontext, fp and lr with struct sigframe
arm64: signal: share lp64 signal routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: ilp32: introduce ilp32-specific handlers for sigframe
all: s390: make compat wrappers the generic solution
arm64: ilp32: wrap syscalls to remove top 32-bit vulnerability
Documentation/arm64/ilp32.txt | 13 ++
arch/Kconfig | 4 +
arch/arm64/Kconfig | 17 +-
arch/arm64/Makefile | 5 +
arch/arm64/include/asm/compat.h | 19 +-
arch/arm64/include/asm/compat_wrapper.h | 14 ++
arch/arm64/include/asm/elf.h | 32 +--
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/hwcap.h | 6 +-
arch/arm64/include/asm/is_compat.h | 84 ++++++++
arch/arm64/include/asm/memory.h | 3 +-
arch/arm64/include/asm/processor.h | 11 +-
arch/arm64/include/asm/ptrace.h | 2 +-
arch/arm64/include/asm/signal32.h | 6 +-
arch/arm64/include/asm/signal32_common.h | 25 +++
arch/arm64/include/asm/signal_common.h | 39 ++++
arch/arm64/include/asm/signal_ilp32.h | 34 ++++
arch/arm64/include/asm/thread_info.h | 3 +-
arch/arm64/include/asm/unistd.h | 11 +-
arch/arm64/include/asm/unistd32.h | 2 +-
arch/arm64/include/asm/vdso.h | 6 +
arch/arm64/include/uapi/asm/bitsperlong.h | 9 +-
arch/arm64/kernel/Makefile | 12 +-
arch/arm64/kernel/asm-offsets.c | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 33 ++++
arch/arm64/kernel/binfmt_ilp32.c | 91 +++++++++
arch/arm64/kernel/cpufeature.c | 8 +-
arch/arm64/kernel/cpuinfo.c | 4 +-
arch/arm64/kernel/entry.S | 18 +-
arch/arm64/kernel/entry_ilp32.S | 23 +++
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 10 +-
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 5 +-
arch/arm64/kernel/ptrace.c | 65 ++++++-
arch/arm64/kernel/signal.c | 47 +++--
arch/arm64/kernel/signal32.c | 85 --------
arch/arm64/kernel/signal32_common.c | 115 +++++++++++
arch/arm64/kernel/signal_ilp32.c | 128 ++++++++++++
arch/arm64/kernel/sys32.c | 1 +
arch/arm64/kernel/sys_ilp32.c | 69 +++++++
arch/arm64/kernel/traps.c | 5 +-
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 72 +++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 ++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++
arch/arm64/kernel/vdso.c | 65 +++++--
arch/s390/Kconfig | 1 +
arch/s390/include/asm/compat_wrapper.h | 25 +++
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/compat_linux.c | 6 +
arch/s390/kernel/compat_wrapper.c | 179 -----------------
drivers/clocksource/arm_arch_timer.c | 2 +-
include/linux/compat_wrapper.h | 270 ++++++++++++++++++++++++++
include/linux/ptrace.h | 6 +
include/linux/thread_bits.h | 55 ++++++
include/linux/thread_info.h | 44 +----
include/uapi/asm-generic/unistd.h | 224 ++++++++++-----------
kernel/Makefile | 1 +
kernel/compat_wrapper.c | 167 ++++++++++++++++
kernel/ptrace.c | 10 +-
61 files changed, 1777 insertions(+), 554 deletions(-)
create mode 100644 Documentation/arm64/ilp32.txt
create mode 100644 arch/arm64/include/asm/compat_wrapper.h
create mode 100644 arch/arm64/include/asm/is_compat.h
create mode 100644 arch/arm64/include/asm/signal32_common.h
create mode 100644 arch/arm64/include/asm/signal_common.h
create mode 100644 arch/arm64/include/asm/signal_ilp32.h
create mode 100644 arch/arm64/kernel/binfmt_elf32.c
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
create mode 100644 arch/arm64/kernel/entry_ilp32.S
create mode 100644 arch/arm64/kernel/signal32_common.c
create mode 100644 arch/arm64/kernel/signal_ilp32.c
create mode 100644 arch/arm64/kernel/sys_ilp32.c
create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
create mode 100644 arch/s390/include/asm/compat_wrapper.h
delete mode 100644 arch/s390/kernel/compat_wrapper.c
create mode 100644 include/linux/compat_wrapper.h
create mode 100644 include/linux/thread_bits.h
create mode 100644 kernel/compat_wrapper.c
Zhangjian (Bamvor)
2016-01-30 04:20:02 UTC
Permalink
Hi, Yury
Post by Yury Norov
Post by Zhangjian (Bamvor)
Hi,
This is still RFC because we have no glibc yet, that correspnds new ABI
introduced here. And so we cannot run tests. LP64 and AARCH32 tests show
no regression though.
Hi,
Glad to see this version. I hope I could test it. Where could I find the
corresponding glibc? I could not find it in
http://github.com/norov/glibc.git. Or is there a plan to do it?
Besides compat wrappers discussed in these series, is there any other
blockers for upstream? I would suppose everyone is intestested in the
result of LTP...
Regards
Bamvor
Hi, Bamvor,
Just to order all commits, I created new ILP32 branch at [1], that
based on 4.4 kernel + [2] + [3]. There's no new glibc suitable for
rfc5. But I started with it, and I hope there will be progress soon.
Cool:)
Post by Yury Norov
You cannot run LTP as there are some syscalls that are called during
dynamic loading that fail, but you can try to build your test statically
agaginst current glibc, and there's a big chance it will work.
I have a set of 'hello-worlds' working that way.
Currrently, I got 300+ in ltplite with you glibc[1]. I will try static link
later.
Post by Yury Norov
If you have some specific test that you cannot run, you can send it to
me, and I will take a look on it.
Sure, I am reading the test results. Hope we could fix these failure
together.

Regards

Bamvor

[1] https://github.com/norov/glibc/tree/thunderx-ilp32-32time_toff_t
Post by Yury Norov
Yury
[1] https://github.com/norov/linux/tree/rfc5
[2] http://permalink.gmane.org/gmane.linux.kernel/2116021
[3] http://comments.gmane.org/gmane.linux.kernel/2134747
Post by Zhangjian (Bamvor)
v3: https://lkml.org/lkml/2014/9/3/704
v4: https://lkml.org/lkml/2015/4/13/691
v5: https://lkml.org/lkml/2015/9/29/911
- time_t, __kenel_off_t and other types turned to be 32-bit
for compatibility reasons (after v5 discussion);
- related changes applied to ILP32 syscall table and handlers;
- ILP32 VDSO code excluded. It's not mandatory, and caused questions
during review process. We definitely make sure we will follow up
with a VDSO later on because it is needed for performance reasons;
- fixed build issues with different combinations of AARCH32 / ILP32
enabling in config;
- ILP32 TLS bug fixed;
- entry32-common.S introduced to hold wrappers needed for both ILP32
and AARCH32_EL0;
- documentation updated according to latest changes;
- rebased to the current head;
- coding style re-checked;
- ILP32 syscall table turned around.
- all structures and system calls are just like AARCH32 ones now. with 2
exceptions: syscalls that take 64-bit parameter in 2 32-bit regosters
are replaced with LP64 version; struct rt_sigframe is constructed both
from LP64 and AARCH32 fields to be consistent with AARCH64 register set;
- documentation rewritten accordingly;
- common code for all 3 ABIs is moved to separated files for easy use,
new headers and objects are introduced, incl: is_compat.h, thread_bits.h,
signal_common.h, signal32_common.h.
- ILP32 VDSO code restored, Nathans comments are addressed;
- patch "arm64: ilp32: force IPC_64 in msgctl, shmctl, semctl" removed, as
Arnd suggested general solution for IPC_64 problem.
- sys_ilp32.c syscall list is fixed according to comments;
- binfmt_elf32.c and binfmt_ilp32.c are introduced to host the code handling
corresponding formats;
- statfs64, fstsatfs64 and mmap wrappers are removed;
- rebased on v4.4-rc8 + http://www.spinics.net/lists/kernel/msg2151759.html
- addressed rfc4 comments;
- turned s390 compat wrappers to be generic and applied it to arm64/ilp32.
Heiko Carsten and Martin Schwidefsky added to CC as s390 maintainers.
arm64: ensure the kernel is compiled for LP64
arm64: rename COMPAT to AARCH32_EL0 in Kconfig
arm64: change some CONFIG_COMPAT over to use CONFIG_AARCH32_EL0
instead
arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
arm64:ilp32: add sys_ilp32.c and a separate table (in entry.S) to use
it
arm64:ilp32: add ARM64_ILP32 to Kconfig
arm64: compat: change config dependences to aarch32
arm64:ilp32: add vdso-ilp32 and use for signal return
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
thread: move thread bits accessors to separated file
arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
arm64: introduce binfmt_elf32.c
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
arm64: signal: wrap struct ucontext, fp and lr with struct sigframe
arm64: signal: share lp64 signal routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: ilp32: introduce ilp32-specific handlers for sigframe
all: s390: make compat wrappers the generic solution
arm64: ilp32: wrap syscalls to remove top 32-bit vulnerability
Documentation/arm64/ilp32.txt | 13 ++
arch/Kconfig | 4 +
arch/arm64/Kconfig | 17 +-
arch/arm64/Makefile | 5 +
arch/arm64/include/asm/compat.h | 19 +-
arch/arm64/include/asm/compat_wrapper.h | 14 ++
arch/arm64/include/asm/elf.h | 32 +--
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/hwcap.h | 6 +-
arch/arm64/include/asm/is_compat.h | 84 ++++++++
arch/arm64/include/asm/memory.h | 3 +-
arch/arm64/include/asm/processor.h | 11 +-
arch/arm64/include/asm/ptrace.h | 2 +-
arch/arm64/include/asm/signal32.h | 6 +-
arch/arm64/include/asm/signal32_common.h | 25 +++
arch/arm64/include/asm/signal_common.h | 39 ++++
arch/arm64/include/asm/signal_ilp32.h | 34 ++++
arch/arm64/include/asm/thread_info.h | 3 +-
arch/arm64/include/asm/unistd.h | 11 +-
arch/arm64/include/asm/unistd32.h | 2 +-
arch/arm64/include/asm/vdso.h | 6 +
arch/arm64/include/uapi/asm/bitsperlong.h | 9 +-
arch/arm64/kernel/Makefile | 12 +-
arch/arm64/kernel/asm-offsets.c | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 33 ++++
arch/arm64/kernel/binfmt_ilp32.c | 91 +++++++++
arch/arm64/kernel/cpufeature.c | 8 +-
arch/arm64/kernel/cpuinfo.c | 4 +-
arch/arm64/kernel/entry.S | 18 +-
arch/arm64/kernel/entry_ilp32.S | 23 +++
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 10 +-
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 5 +-
arch/arm64/kernel/ptrace.c | 65 ++++++-
arch/arm64/kernel/signal.c | 47 +++--
arch/arm64/kernel/signal32.c | 85 --------
arch/arm64/kernel/signal32_common.c | 115 +++++++++++
arch/arm64/kernel/signal_ilp32.c | 128 ++++++++++++
arch/arm64/kernel/sys32.c | 1 +
arch/arm64/kernel/sys_ilp32.c | 69 +++++++
arch/arm64/kernel/traps.c | 5 +-
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 72 +++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 ++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++
arch/arm64/kernel/vdso.c | 65 +++++--
arch/s390/Kconfig | 1 +
arch/s390/include/asm/compat_wrapper.h | 25 +++
arch/s390/kernel/Makefile | 2 +-
arch/s390/kernel/compat_linux.c | 6 +
arch/s390/kernel/compat_wrapper.c | 179 -----------------
drivers/clocksource/arm_arch_timer.c | 2 +-
include/linux/compat_wrapper.h | 270 ++++++++++++++++++++++++++
include/linux/ptrace.h | 6 +
include/linux/thread_bits.h | 55 ++++++
include/linux/thread_info.h | 44 +----
include/uapi/asm-generic/unistd.h | 224 ++++++++++-----------
kernel/Makefile | 1 +
kernel/compat_wrapper.c | 167 ++++++++++++++++
kernel/ptrace.c | 10 +-
61 files changed, 1777 insertions(+), 554 deletions(-)
create mode 100644 Documentation/arm64/ilp32.txt
create mode 100644 arch/arm64/include/asm/compat_wrapper.h
create mode 100644 arch/arm64/include/asm/is_compat.h
create mode 100644 arch/arm64/include/asm/signal32_common.h
create mode 100644 arch/arm64/include/asm/signal_common.h
create mode 100644 arch/arm64/include/asm/signal_ilp32.h
create mode 100644 arch/arm64/kernel/binfmt_elf32.c
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
create mode 100644 arch/arm64/kernel/entry_ilp32.S
create mode 100644 arch/arm64/kernel/signal32_common.c
create mode 100644 arch/arm64/kernel/signal_ilp32.c
create mode 100644 arch/arm64/kernel/sys_ilp32.c
create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
create mode 100644 arch/s390/include/asm/compat_wrapper.h
delete mode 100644 arch/s390/kernel/compat_wrapper.c
create mode 100644 include/linux/compat_wrapper.h
create mode 100644 include/linux/thread_bits.h
create mode 100644 kernel/compat_wrapper.c
Yury Norov
2016-02-18 22:40:02 UTC
Permalink
Post by Zhangjian (Bamvor)
Hi, Yury
Post by Yury Norov
Post by Zhangjian (Bamvor)
Hi,
This is still RFC because we have no glibc yet, that correspnds new ABI
introduced here. And so we cannot run tests. LP64 and AARCH32 tests show
no regression though.
Hi,
Glad to see this version. I hope I could test it. Where could I find the
corresponding glibc? I could not find it in
http://github.com/norov/glibc.git. Or is there a plan to do it?
Besides compat wrappers discussed in these series, is there any other
blockers for upstream? I would suppose everyone is intestested in the
result of LTP...
Regards
Bamvor
Hi, Bamvor,
Just to order all commits, I created new ILP32 branch at [1], that
based on 4.4 kernel + [2] + [3]. There's no new glibc suitable for
rfc5. But I started with it, and I hope there will be progress soon.
Cool:)
Post by Yury Norov
You cannot run LTP as there are some syscalls that are called during
dynamic loading that fail, but you can try to build your test statically
agaginst current glibc, and there's a big chance it will work.
I have a set of 'hello-worlds' working that way.
Currrently, I got 300+ in ltplite with you glibc[1]. I will try static link
later.
Post by Yury Norov
If you have some specific test that you cannot run, you can send it to
me, and I will take a look on it.
Sure, I am reading the test results. Hope we could fix these failure
together.
Regards
Bamvor
[1] https://github.com/norov/glibc/tree/thunderx-ilp32-32time_toff_t
Post by Yury Norov
Yury
[1] https://github.com/norov/linux/tree/rfc5
[2] http://permalink.gmane.org/gmane.linux.kernel/2116021
[3] http://comments.gmane.org/gmane.linux.kernel/2134747
Post by Zhangjian (Bamvor)
v3: https://lkml.org/lkml/2014/9/3/704
v4: https://lkml.org/lkml/2015/4/13/691
v5: https://lkml.org/lkml/2015/9/29/911
Hi Bamvor, everybody,

I have new glibc that follows new ABI:
https://github.com/norov/glibc/tree/new-api

It's very draft and dirty, but you can try it with RFC5.
My fail list for ltplite looks like this:
pipeio_4 FAIL 11
abort01 FAIL 2
clone02 FAIL 4
kill10 FAIL 2
kill11 FAIL 2
lstat01A FAIL 1
lstat02 FAIL 1
mmap16 FAIL 6
nanosleep03 FAIL 1
nftw01 FAIL 1
nftw6401 FAIL 1
open12 FAIL 2
pathconf01 FAIL 1
pipe07 FAIL 2
profil01 FAIL 11
readdir01 FAIL 1
readlink01A FAIL 1
rename11 FAIL 2
rmdir02 FAIL 2
sigaltstack01 FAIL 1
sigaltstack02 FAIL 1
stat03 FAIL 1
stat04 FAIL 1
stat06 FAIL 1
umount2_01 FAIL 2
umount2_02 FAIL 2
umount2_03 FAIL 2
utime06 FAIL 2
writev01 FAIL 1
mtest06 FAIL 11
rwtest01 FAIL 2
rwtest02 FAIL 2
rwtest03 FAIL 2
rwtest04 FAIL 2
rwtest05 FAIL 2

Float tests are exluded, but also fail. Totally, ~40 of 787 tests
fail.

Yury
Arnd Bergmann
2016-02-19 08:30:02 UTC
Permalink
Post by Yury Norov
Hi Bamvor, everybody,
https://github.com/norov/glibc/tree/new-api
Ah, very good!
Post by Yury Norov
It's very draft and dirty, but you can try it with RFC5.
pipeio_4 FAIL 11
abort01 FAIL 2
clone02 FAIL 4
kill10 FAIL 2
kill11 FAIL 2
lstat01A FAIL 1
lstat02 FAIL 1
mmap16 FAIL 6
nanosleep03 FAIL 1
nftw01 FAIL 1
nftw6401 FAIL 1
open12 FAIL 2
pathconf01 FAIL 1
pipe07 FAIL 2
profil01 FAIL 11
readdir01 FAIL 1
readlink01A FAIL 1
rename11 FAIL 2
rmdir02 FAIL 2
sigaltstack01 FAIL 1
sigaltstack02 FAIL 1
stat03 FAIL 1
stat04 FAIL 1
stat06 FAIL 1
umount2_01 FAIL 2
umount2_02 FAIL 2
umount2_03 FAIL 2
utime06 FAIL 2
writev01 FAIL 1
mtest06 FAIL 11
rwtest01 FAIL 2
rwtest02 FAIL 2
rwtest03 FAIL 2
rwtest04 FAIL 2
rwtest05 FAIL 2
I have no idea whether this is good news or bad news ;-)

In https://github.com/norov/glibc/commit/351b8728fdb365bd4852ac113601ddf38153fdfc
I see that you are passing __IPC_64, I thought we had already resolved
that in the kernel. We might need to go back to this.

In https://github.com/norov/glibc/commit/5d4290435e428267171ece871539b76e1d079d11
you are defining a struct __kernel_stat64 in the glibc. Is this the expected
way to do it? I would have thought you'd get the definition from the kernel
headers.

Arnd
Yury Norov
2016-02-19 13:10:03 UTC
Permalink
Post by Arnd Bergmann
Post by Yury Norov
Hi Bamvor, everybody,
https://github.com/norov/glibc/tree/new-api
Ah, very good!
Post by Yury Norov
It's very draft and dirty, but you can try it with RFC5.
pipeio_4 FAIL 11
abort01 FAIL 2
clone02 FAIL 4
kill10 FAIL 2
kill11 FAIL 2
lstat01A FAIL 1
lstat02 FAIL 1
mmap16 FAIL 6
nanosleep03 FAIL 1
nftw01 FAIL 1
nftw6401 FAIL 1
open12 FAIL 2
pathconf01 FAIL 1
pipe07 FAIL 2
profil01 FAIL 11
readdir01 FAIL 1
readlink01A FAIL 1
rename11 FAIL 2
rmdir02 FAIL 2
sigaltstack01 FAIL 1
sigaltstack02 FAIL 1
stat03 FAIL 1
stat04 FAIL 1
stat06 FAIL 1
umount2_01 FAIL 2
umount2_02 FAIL 2
umount2_03 FAIL 2
utime06 FAIL 2
writev01 FAIL 1
mtest06 FAIL 11
rwtest01 FAIL 2
rwtest02 FAIL 2
rwtest03 FAIL 2
rwtest04 FAIL 2
rwtest05 FAIL 2
I have no idea whether this is good news or bad news ;-)
In https://github.com/norov/glibc/commit/351b8728fdb365bd4852ac113601ddf38153fdfc
I see that you are passing __IPC_64, I thought we had already resolved
that in the kernel. We might need to go back to this.
I'm still on 4.4 kernel. So I need it. I'll drop __IPC_64 if unneeded on
rebase. Usually I rebase on rc5 or rc6.
Post by Arnd Bergmann
In https://github.com/norov/glibc/commit/5d4290435e428267171ece871539b76e1d079d11
you are defining a struct __kernel_stat64 in the glibc. Is this the expected
way to do it? I would have thought you'd get the definition from the kernel
headers.
Arnd
Almost all ports define its own struct kernel_stat / kernel_stat64.
in "kernel_header.h" See mips, spark, alpha, i386... Some also define
function xstat_conv or similar. With all that defined, it's expected
that one of generic xstat wrappers will work properly. I tried all,
and noone got working, so I wrote this hack to make it work somehow.
Post by Arnd Bergmann
_______________________________________________
linux-arm-kernel mailing list
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Arnd Bergmann
2016-02-19 14:10:02 UTC
Permalink
Post by Yury Norov
Post by Arnd Bergmann
In https://github.com/norov/glibc/commit/5d4290435e428267171ece871539b76e1d079d11
you are defining a struct __kernel_stat64 in the glibc. Is this the expected
way to do it? I would have thought you'd get the definition from the kernel
headers.
Arnd
Almost all ports define its own struct kernel_stat / kernel_stat64.
in "kernel_header.h" See mips, spark, alpha, i386... Some also define
function xstat_conv or similar. With all that defined, it's expected
that one of generic xstat wrappers will work properly. I tried all,
and noone got working, so I wrote this hack to make it work somehow.
I see. I grepped for __kernel_stat64 and couldn't find any other
with that name, as the others tend to us slightly different names.

I would still think there is something wrong if you need to define
your own copy of xstat_conv when the kernel 'struct stat64' is
meant to be usable by user space. Shouldn't this work like any
other 32-bit architecture now?

Arnd
Yury Norov
2016-02-29 15:40:01 UTC
Permalink
Post by Arnd Bergmann
I have no idea whether this is good news or bad news ;-)
This is neutral news, I think. V5 had ~25 fails, and aarch32 and lp64 has
~5 fails each. I believe I'll manage to achieve ~25 fails soon. The
rest fails are not clear for me now, so I'll investigate it...
Andreas Schwab
2016-02-29 16:10:03 UTC
Permalink
Post by Arnd Bergmann
In https://github.com/norov/glibc/commit/5d4290435e428267171ece871539b76e1d079d11
you are defining a struct __kernel_stat64 in the glibc. Is this the expected
way to do it? I would have thought you'd get the definition from the kernel
headers.
The problem really is that struct stat64 does not match the kernel
struct stat64. The latter uses the broken st_ino, where the 64-bit
inode is actually stored at the end of the structure, and there is
padding *before* the 32-bit inode, not after (so you cannot overlay a
64-bit inode field in little endian mode). You need to add the attached
file as sysdeps/unix/sysv/linux/aarch64/bits/stat.h, then you can use
the user-space struct stat64 to communicate with the *stat64 syscalls,
and __kernel_stat64 is not needed any more.

Andreas.
--
Andreas Schwab, SUSE Labs, ***@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Arnd Bergmann
2016-02-29 16:40:03 UTC
Permalink
Post by Andreas Schwab
Post by Arnd Bergmann
In https://github.com/norov/glibc/commit/5d4290435e428267171ece871539b76e1d079d11
you are defining a struct __kernel_stat64 in the glibc. Is this the expected
way to do it? I would have thought you'd get the definition from the kernel
headers.
The problem really is that struct stat64 does not match the kernel
struct stat64. The latter uses the broken st_ino, where the 64-bit
inode is actually stored at the end of the structure, and there is
padding *before* the 32-bit inode, not after (so you cannot overlay a
64-bit inode field in little endian mode). You need to add the attached
file as sysdeps/unix/sysv/linux/aarch64/bits/stat.h, then you can use
the user-space struct stat64 to communicate with the *stat64 syscalls,
and __kernel_stat64 is not needed any more.
Ok, got it. So this is an unfortunate side-effect of using the same
'stat64' as arm32 does.

If it's really that broken, should we change the kernel (once more)
to use the layout of arm64 instead? That has the 64-bit time fields
though, so it might require similar hacks, unless we first merge
support for 64-bit time_t based syscalls (which seems unlikely
at this point, sorry for the delay on my end).

Is there possibly a way to reference the implementation that we
have for stat64 on arm32 rather than duplicating it?

Arnd
Andreas Schwab
2016-02-25 11:00:02 UTC
Permalink
Post by Yury Norov
https://github.com/norov/glibc/tree/new-api
sysdeps/unix/sysv/linux/aarch64/ilp32/getdents64.c is wrong, struct
dirent64 is not the same as struct dirent. The file needs to be renamed
to sysdeps/unix/sysv/linux/aarch64/ilp32/getdents.c so that __getdents64
comes from sysdeps/unix/sysv/linux/generic/getdents64.c.

sysdeps/unix/sysv/linux/aarch64/ilp32/*xstat*.c should not set errno,
INLINE_SYSCALL already does that, and returns -1 on error.

Andreas.
--
Andreas Schwab, SUSE Labs, ***@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Yury Norov
2016-02-25 20:30:03 UTC
Permalink
Post by Andreas Schwab
Post by Yury Norov
https://github.com/norov/glibc/tree/new-api
sysdeps/unix/sysv/linux/aarch64/ilp32/getdents64.c is wrong, struct
dirent64 is not the same as struct dirent. The file needs to be renamed
to sysdeps/unix/sysv/linux/aarch64/ilp32/getdents.c so that __getdents64
comes from sysdeps/unix/sysv/linux/generic/getdents64.c.
sysdeps/unix/sysv/linux/aarch64/ilp32/*xstat*.c should not set errno,
INLINE_SYSCALL already does that, and returns -1 on error.
Andreas.
Thank you. I'll fix it
Post by Andreas Schwab
--
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Zhangjian (Bamvor)
2016-03-18 10:40:03 UTC
Permalink
Hi, Yury

We are trying to test ilp32 in our arm64 board. But we got more
failure compare with you. So, I am wondering if we could align
the test environment with you. The source code we used:

1. glibc: the new-api branch of glibc from
***@code.huawei.com:gnu/norov_glibc.git.

2. Kernel: rfc5 from https://github.com/norov/linux.git. Is the
rc6 in your branch is the latest one? From the commit message, I
do not find any difference. Is it just a rebase?

3. Toolchain 4.9.3, could you provide the binary of toolchain(both
cross and native, gcc, gdb...)? It may be very useful for me or
other guys who interested build their own filesystem from
buildroot or something.

4. LTP: master.

For the glibc part, I found that there are 11 patches of ilp32 in top,
but the original 28 patches of ilp32 is not in the top, there are more
than 900 patches between them(referece the list below). Are you
willing rebase all the ilp32 relative patches. It is very useful for
reviewing and debugging. I saw andrew request the account in glibc,
maybe it has already been in processs?).

Regards

Bamvor

ILP32 relative patch in norov's glibc:
1 b5c4968 fix stat
2 8332b7a fix3
3 d16a202 fix statfs
4 351b872 fix IPC_64 for msgctl semctl shmctl
5 07f8ead fix readdir ????
6 4be481a fix lseek
7 4231518 fix getdents
8 de55857 fstat fix
9 5d42904 stat
10 3f70665 mmap, stat syscalls
11 574af33 Make ilp32 use the compat (old 32bit ABI).

972 8addb06 [AARCH64] Make lp64 and ilp32 directories.
973 bfe0619 [AARCH64] Add typesizes.h for ILP32
974 916581b [AARCH64] Fix up ucontext for ILP32
975 0f646ee [AARCH64] Add sigstack.h header for ILP32 reasons.
976 68e11d8 [AARCH64] Add kernel_sigaction.h for AARCH64 ILP32
977 a0087ba [AARCH64] Add ldd-rewrite.sed so that ilp32 ld.so can be found
978 0f800d9 [AARCH64] Add ILP32 ld.so to the known interpreter names.
979 45d74fd [AARCH64] Add support to ldconfig for ILP32 and libilp32
980 9926da9 [AARCH64] Add ILP32 to makefiles
981 987b522 [AARCH64] Set up wordsize for ILP32.
982 5e34e4c [AARCH64] Add ILP32 support to elf_machine_load_address.
983 1ff4dd9 [AARCH64] Reformat inline-asm in elf_machine_load_address.
984 f7ff9aa [AARCH64] Syscalls for ILP32 are passed always via 64bit values.
985 9316667 [AARCH64] Detect ILP32 in configure scripts.
986 ff0dca1 [AARCH64] Use PTR_REG in getcontext.S.
987 7c9f1b0 [AARCH64] Use PTR_* in start.S
988 ed747ff [AARCH64] Use PTR_* macros in dl-trampoline.S
989 71f6986 [AARCH64] Use PTR_REG/PTR_SIZE/PTR_SIZE_LOG in dl-tlsesc.S
990 3294b6f [AARCH64] Use PTR_REG in crti.S.
991 c8fef18 [AARCH64] Add PTR_REG, PTR_LOG_SIZE, and PTR_SIZE. Use it in LDST_PCREL and LDST_GLOBAL.
992 585197d Add dynamic ILP32 AARCH64 relocations to elf.h
993 49f1345 [AARCH64] Add header guards to sysdep.h headers.
994 2594068 Allow generic stat and statfs not have padding for 32bit targets
995 86f0aa7 Allow some fields of siginfo to be different from the generic one
996 fdffbc5 Allow fd_mask type not be an array of long.
997 453987a Allow rusage work on a big-endian 32bit-on-64bit target
998 70e6485 Add ability for the IPC structures (msqid_ds, semid_ds, shmid_ds, etc.) to have time_t being 64bit
999 9ff1730 Allow sigset be an array of a different type
1000 dc09040 [AARCH64] Fix utmp struct for compatibility reasons.
Post by Yury Norov
Post by Andreas Schwab
Post by Yury Norov
https://github.com/norov/glibc/tree/new-api
sysdeps/unix/sysv/linux/aarch64/ilp32/getdents64.c is wrong, struct
dirent64 is not the same as struct dirent. The file needs to be renamed
to sysdeps/unix/sysv/linux/aarch64/ilp32/getdents.c so that __getdents64
comes from sysdeps/unix/sysv/linux/generic/getdents64.c.
sysdeps/unix/sysv/linux/aarch64/ilp32/*xstat*.c should not set errno,
INLINE_SYSCALL already does that, and returns -1 on error.
Andreas.
Thank you. I'll fix it
Post by Andreas Schwab
--
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Alexander Graf
2016-03-18 16:00:03 UTC
Permalink
Post by Zhangjian (Bamvor)
For the glibc part, I found that there are 11 patches of ilp32 in top,
but the original 28 patches of ilp32 is not in the top, there are more
than 900 patches between them(referece the list below). Are you
willing rebase all the ilp32 relative patches. It is very useful for
reviewing and debugging. I saw andrew request the account in glibc,
maybe it has already been in processs?).
I already told there's mess there, and I'd prefer to make things work
first and then do cleanup.
So how is progress going overall? The last submission I've seen is
already 2 months ago. Are there particular bits holding you up?


Alex
Zhangjian (Bamvor)
2016-03-20 08:20:02 UTC
Permalink
Hi, Yury
Post by Alexander Graf
Post by Zhangjian (Bamvor)
For the glibc part, I found that there are 11 patches of ilp32 in top,
but the original 28 patches of ilp32 is not in the top, there are more
than 900 patches between them(referece the list below). Are you
willing rebase all the ilp32 relative patches. It is very useful for
reviewing and debugging. I saw andrew request the account in glibc,
maybe it has already been in processs?).
I already told there's mess there, and I'd prefer to make things work
first and then do cleanup.
So how is progress going overall? The last submission I've seen is
already 2 months ago. Are there particular bits holding you up?
Alex
Hi Alexander,
For last time I mostly work on library, as it needs to be reworked
well. But yes, there's one serious bug puzzling me.
Tests like umount or pathconf fail but I see no major problem with
it, as it's most probably structure padding mismatch between kernel and
glibc. But there's (at least) one major problem I see.
Float tests fail due to NULL-dereferencing (0x14 actually) at
pthread_join(). It calls tgkill(), and after that child thread crashes.
See stack trace at the end.
The minimal test reproducing it is attached. The similar test where
parent forks a child and then kills it, works fine. (Attached too).
I see that in case of pthread, there's much more stuff that is cloned.
Other's looking similar.
clone(child_stack=0xb953cea0, flags=CLONE_VM|CLONE_FS|CLONE_FILES
|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS
|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
parent_tidptr=0xb953d398, tls=0xb953d7c0, child_tidptr=0xb953d398) = 1650
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0xe5af6278) = 30537
So this most probably means that ilp32 code doesn't handle one of cloned
item properly. I have already discovered a bug where child processes
used parent TLS,
It is a kernel bug or glibc bug? Could you please explain it or show the patch?
The current ILP32 patches looks good to me. Recently, I backport these patches
to our 4.1 kernel. And I saw crash frequently even if I only do a single print
or infinite loop. There is some small changes about tls register after 4.1. I
am not sure if it is a similar issue. It is great if you have some suggestions/
ideas.

Thanks.

Bamvor
so maybe this is something similar...
Except of this, I think ILP32 series is looking pretty well, at least
kernel part.
If you have any ideas/suggestions, I'll really appreciate it.
Yury.
strace -f ./trigo
[...]
clone(child_stack=0xdbbfb000,
flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND
|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS
|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
parent_tidptr=0xdbbfb4f8, tls=0xdbbfb920, child_tidptr=0xdbbfb4f8) = 32030
rt_sigprocmask(SIG_BLOCK, [CHLD], Process 32030 attached [], 8) = 0
[pid 32029] rt_sigaction(SIGCHLD, NULL, <unfinished ...>
[pid 32030] set_robust_list(0xdbbfb504, 12 <unfinished ...>
[pid 32029] <... rt_sigaction resumed> {SIG_DFL, [ILL ABRT SEGV URG], 0}, 8) = 0
[pid 32030] <... set_robust_list resumed> ) = 0
[pid 32029] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
[pid 32030] write(1, "started\n", 8started
<unfinished ...>
[pid 32029] nanosleep({1, 65536}, <unfinished ...>
[pid 32030] <... write resumed> ) = 8
[pid 32030] rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
[pid 32030] rt_sigsuspend([] <unfinished ...>
[pid 32029] <... nanosleep resumed> 0xfff9fd98) = 0
[pid 32029] write(1, "stoping...\n", 11stoping...) = 11
[pid 32029] openat(AT_FDCWD, "/root/sys-root/libilp32/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
[pid 32029] read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0 \0\0004\0\0\0"..., 512) = 512
[pid 32029] fstat(3, {st_mode=S_IFREG|0644, st_size=429138, ...}) = 0
[pid 32029] mmap(NULL, 135104, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xdb3db000
[pid 32029] mprotect(0xdb3ec000, 61440, PROT_NONE) = 0
[pid 32029] mmap(0xdb3fb000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10000) = 0xdb3fb000
[pid 32029] close(3) = 0
[pid 32029] tgkill(32029, 32030, SIGRTMIN) = 0
[pid 32030] <... rt_sigsuspend resumed> ) = ? ERESTARTNOHAND (To be
restarted if no handler)
[pid 32029] write(1, "pthread_cancel == 0\n", 20pthread_cancel == 0) = 20
[pid 32030] --- SIGRTMIN {si_signo=SIGRTMIN, si_code=SI_TKILL, si_pid=32029, si_uid=0} ---
[pid 32029] write(1, "stopped\n", 8stopped
<unfinished ...>
[pid 32030] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x14} ---
[pid 32029] <... write resumed> ) = ? <unavailable>
[pid 32030] +++ killed by SIGSEGV +++
+++ killed by SIGSEGV +++
Segmentation fault
trigo[32246]: unhandled level 2 translation fault (11) at 0x00000014,
esr 0x90000006
pgd = ffffffc009335000
[00000014] *pgd=000000007917c003, *pud=000000007917c003,
*pmd=0000000000000000
CPU: 2 PID: 32246 Comm: trigo Not tainted 4.5.0+ #91
Hardware name: linux,dummy-virt (DT)
task: ffffffc00900e400 ti: ffffffc009078000 task.ti: ffffffc009078000
PC is at 0xda6853f0
LR is at 0xda6d5440
pc : [<00000000da6853f0>] lr : [<00000000da6d5440>] pstate: 60000000
sp : 00000000da511bc0
x29: 00000000da512e10 x28: 00000000da6a7000
x27: 0000000000000000 x26: 00000000da513490
x25: 0000000000000000 x24: 0000000000400820
x23: 00000000da6a9000 x22: 00000000ff869acb
x21: 00000000da6a9000 x20: 00000000da512e50
x19: 0000000000000000 x18: 0000000000000001
x17: 0000000000410bd8 x16: 00000000da691138
x15: 0000000000000000 x14: 0000000000000000
x13: 00000000da535970 x12: 0000000000000038
x11: 0000000000000028 x10: 0101010101010101
x9 : ff63647371607372 x8 : 0000000000000085
x7 : 0000000000007df5 x6 : 00000000da512e1c
x5 : 00000000da513518 x4 : 0000000000000002
x3 : 00000000da513920 x2 : 0000000000000000
x1 : 0000000000000008 x0 : 00000000da513490
Zhangjian (Bamvor)
2016-03-21 11:30:02 UTC
Permalink
Hi, Yury
Post by Zhangjian (Bamvor)
Hi, Yury
[...]
Post by Zhangjian (Bamvor)
The minimal test reproducing it is attached. The similar test where
parent forks a child and then kills it, works fine. (Attached too).
I see that in case of pthread, there's much more stuff that is cloned.
Other's looking similar.
clone(child_stack=0xb953cea0, flags=CLONE_VM|CLONE_FS|CLONE_FILES
|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS
|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
parent_tidptr=0xb953d398, tls=0xb953d7c0, child_tidptr=0xb953d398) = 1650
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0xe5af6278) = 30537
So this most probably means that ilp32 code doesn't handle one of cloned
item properly. I have already discovered a bug where child processes
used parent TLS,
It is a kernel bug or glibc bug? Could you please explain it or show the patch?
The current ILP32 patches looks good to me. Recently, I backport these patches
to our 4.1 kernel. And I saw crash frequently even if I only do a single print
or infinite loop. There is some small changes about tls register after 4.1. I
am not sure if it is a similar issue. It is great if you have some suggestions/
ideas.
My issue is because I forget to change is_compat_task to
is_a32_compat_task in arch/arm64/kernel/process.c such piece of code
is delete after commit d00a3810c162 ("arm64: context-switch user tls
register tpidr_el0 for compat tasks). It is not exist in upstream
kernel, never mind.

Meanwhile, I found that it seem that there is another is_compat_task
in tls_thread_flush. Is it relative the issue you mentioned?

```
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 432b094..9ab968c 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -209,7 +209,7 @@ static void tls_thread_flush(void)
{
asm ("msr tpidr_el0, xzr");

- if (is_compat_task()) {
+ if (is_a32_compat_task()) {
current->thread.tp_value = 0;

/*
```

Regards

Bamvor
Post by Zhangjian (Bamvor)
Thanks.
Bamvor
so maybe this is something similar...
Except of this, I think ILP32 series is looking pretty well, at least
kernel part.
If you have any ideas/suggestions, I'll really appreciate it.
Yury.
strace -f ./trigo
[...]
clone(child_stack=0xdbbfb000,
flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND
|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS
|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
parent_tidptr=0xdbbfb4f8, tls=0xdbbfb920, child_tidptr=0xdbbfb4f8) = 32030
rt_sigprocmask(SIG_BLOCK, [CHLD], Process 32030 attached [], 8) = 0
[pid 32029] rt_sigaction(SIGCHLD, NULL, <unfinished ...>
[pid 32030] set_robust_list(0xdbbfb504, 12 <unfinished ...>
[pid 32029] <... rt_sigaction resumed> {SIG_DFL, [ILL ABRT SEGV URG], 0}, 8) = 0
[pid 32030] <... set_robust_list resumed> ) = 0
[pid 32029] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
[pid 32030] write(1, "started\n", 8started
<unfinished ...>
[pid 32029] nanosleep({1, 65536}, <unfinished ...>
[pid 32030] <... write resumed> ) = 8
[pid 32030] rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
[pid 32030] rt_sigsuspend([] <unfinished ...>
[pid 32029] <... nanosleep resumed> 0xfff9fd98) = 0
[pid 32029] write(1, "stoping...\n", 11stoping...) = 11
[pid 32029] openat(AT_FDCWD, "/root/sys-root/libilp32/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
[pid 32029] read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0 \0\0004\0\0\0"..., 512) = 512
[pid 32029] fstat(3, {st_mode=S_IFREG|0644, st_size=429138, ...}) = 0
[pid 32029] mmap(NULL, 135104, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xdb3db000
[pid 32029] mprotect(0xdb3ec000, 61440, PROT_NONE) = 0
[pid 32029] mmap(0xdb3fb000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10000) = 0xdb3fb000
[pid 32029] close(3) = 0
[pid 32029] tgkill(32029, 32030, SIGRTMIN) = 0
[pid 32030] <... rt_sigsuspend resumed> ) = ? ERESTARTNOHAND (To be
restarted if no handler)
[pid 32029] write(1, "pthread_cancel == 0\n", 20pthread_cancel == 0) = 20
[pid 32030] --- SIGRTMIN {si_signo=SIGRTMIN, si_code=SI_TKILL, si_pid=32029, si_uid=0} ---
[pid 32029] write(1, "stopped\n", 8stopped
<unfinished ...>
[pid 32030] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x14} ---
[pid 32029] <... write resumed> ) = ? <unavailable>
[pid 32030] +++ killed by SIGSEGV +++
+++ killed by SIGSEGV +++
Segmentation fault
trigo[32246]: unhandled level 2 translation fault (11) at 0x00000014,
esr 0x90000006
pgd = ffffffc009335000
[00000014] *pgd=000000007917c003, *pud=000000007917c003,
*pmd=0000000000000000
CPU: 2 PID: 32246 Comm: trigo Not tainted 4.5.0+ #91
Hardware name: linux,dummy-virt (DT)
task: ffffffc00900e400 ti: ffffffc009078000 task.ti: ffffffc009078000
PC is at 0xda6853f0
LR is at 0xda6d5440
pc : [<00000000da6853f0>] lr : [<00000000da6d5440>] pstate: 60000000
sp : 00000000da511bc0
x29: 00000000da512e10 x28: 00000000da6a7000
x27: 0000000000000000 x26: 00000000da513490
x25: 0000000000000000 x24: 0000000000400820
x23: 00000000da6a9000 x22: 00000000ff869acb
x21: 00000000da6a9000 x20: 00000000da512e50
x19: 0000000000000000 x18: 0000000000000001
x17: 0000000000410bd8 x16: 00000000da691138
x15: 0000000000000000 x14: 0000000000000000
x13: 00000000da535970 x12: 0000000000000038
x11: 0000000000000028 x10: 0101010101010101
x9 : ff63647371607372 x8 : 0000000000000085
x7 : 0000000000007df5 x6 : 00000000da512e1c
x5 : 00000000da513518 x4 : 0000000000000002
x3 : 00000000da513920 x2 : 0000000000000000
x1 : 0000000000000008 x0 : 00000000da513490
Yury Norov
2016-03-21 19:20:02 UTC
Permalink
Post by Zhangjian (Bamvor)
Post by Zhangjian (Bamvor)
So this most probably means that ilp32 code doesn't handle one of cloned
item properly. I have already discovered a bug where child processes
used parent TLS,
It is a kernel bug or glibc bug? Could you please explain it or show the patch?
The current ILP32 patches looks good to me. Recently, I backport these patches
to our 4.1 kernel. And I saw crash frequently even if I only do a single print
or infinite loop. There is some small changes about tls register after 4.1. I
am not sure if it is a similar issue. It is great if you have some suggestions/
ideas.
My issue is because I forget to change is_compat_task to
is_a32_compat_task in arch/arm64/kernel/process.c such piece of code
is delete after commit d00a3810c162 ("arm64: context-switch user tls
register tpidr_el0 for compat tasks). It is not exist in upstream
kernel, never mind.
Meanwhile, I found that it seem that there is another is_compat_task
in tls_thread_flush. Is it relative the issue you mentioned?
```
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 432b094..9ab968c 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -209,7 +209,7 @@ static void tls_thread_flush(void)
{
asm ("msr tpidr_el0, xzr");
- if (is_compat_task()) {
+ if (is_a32_compat_task()) {
current->thread.tp_value = 0;
/*
```
Regards
Bamvor
Hi,

This fix looks correct, though doesn't fix issue.
Thank you.

Yury.
Andreas Schwab
2016-03-21 09:10:01 UTC
Permalink
This patch may fix a few LTP tests.

Andreas.

diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
index 3631903..d1010db 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
@@ -25,18 +25,29 @@
#define __O_NOFOLLOW 0100000
#define __O_DIRECT 0200000

-#define __O_LARGEFILE 0
+#ifdef __ILP32__
+# define __O_LARGEFILE 0400000
+#else
+# define __O_LARGEFILE 0
+#endif

+#ifndef __ILP32__
# define F_GETLK64 5
# define F_SETLK64 6
# define F_SETLKW64 7
+#endif

struct flock
{
short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
+#ifndef __USE_FILE_OFFSET64
__off_t l_start; /* Offset where the lock begins. */
__off_t l_len; /* Size of the locked area; zero means until EOF. */
+#else
+ __off64_t l_start; /* Offset where the lock begins. */
+ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
+#endif
__pid_t l_pid; /* Process holding the lock. */
};
--
2.7.3
--
Andreas Schwab, SUSE Labs, ***@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Arnd Bergmann
2016-03-21 09:50:02 UTC
Permalink
Post by Andreas Schwab
This patch may fix a few LTP tests.
Thanks for analyzing.
Post by Andreas Schwab
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
index 3631903..d1010db 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
@@ -25,18 +25,29 @@
#define __O_NOFOLLOW 0100000
#define __O_DIRECT 0200000
-#define __O_LARGEFILE 0
+#ifdef __ILP32__
+# define __O_LARGEFILE 0400000
+#else
+# define __O_LARGEFILE 0
+#endif
I guess this means I screwed up when I said I'd merged the kernel patch
that Yury did to fix it, sorry about that.

We need the patch to make all new architecture in the kernel default to
O_LARGEFILE, and not do this in user space. I'd suggest now to keep the
patches as part of the ILP32 series after all, to make sure they are
merged at the point when they are needed.
Post by Andreas Schwab
+#ifndef __ILP32__
# define F_GETLK64 5
# define F_SETLK64 6
# define F_SETLKW64 7
+#endif
struct flock
{
short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
+#ifndef __USE_FILE_OFFSET64
__off_t l_start; /* Offset where the lock begins. */
__off_t l_len; /* Size of the locked area; zero means until EOF. */
+#else
+ __off64_t l_start; /* Offset where the lock begins. */
+ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
+#endif
__pid_t l_pid; /* Process holding the lock. */
};
This looks like there is another bug as well, but I think this is in
libc, not in the kernel. I'm sure we had discussed this at some point
but I forgot what the outcome was. Defining 'struct flock' to have a
32-bit l_start and l_len member cannot be right if the kernel only
supports 64-bit offsets.

My guess is that the libc should either not define __off_t at all for
ILP32, and always use __off64_t in struct flock, or __off_t should
be defined as __kernel_loff_t a.k.a. long long so the #ifdef can be
avoided.

What exactly do you need to define F_GETLK64 for on LP64?

Arnd
Andreas Schwab
2016-03-21 11:00:02 UTC
Permalink
Post by Arnd Bergmann
What exactly do you need to define F_GETLK64 for on LP64?
To override the generic definitions.

Andreas.
--
Andreas Schwab, SUSE Labs, ***@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Arnd Bergmann
2016-03-21 17:10:02 UTC
Permalink
Post by Andreas Schwab
Post by Arnd Bergmann
What exactly do you need to define F_GETLK64 for on LP64?
To override the generic definitions.
Ok, got it. I misread that part as adding definitions for LP64, but it
is correctly removing the definitions for ILP32.

Arnd
Zhangjian (Bamvor)
2016-03-26 12:40:02 UTC
Permalink
Hi, Arnd
Post by Arnd Bergmann
Post by Andreas Schwab
This patch may fix a few LTP tests.
Thanks for analyzing.
Post by Andreas Schwab
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
index 3631903..d1010db 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
@@ -25,18 +25,29 @@
#define __O_NOFOLLOW 0100000
#define __O_DIRECT 0200000
-#define __O_LARGEFILE 0
+#ifdef __ILP32__
+# define __O_LARGEFILE 0400000
+#else
+# define __O_LARGEFILE 0
+#endif
I guess this means I screwed up when I said I'd merged the kernel patch
that Yury did to fix it, sorry about that.
We need the patch to make all new architecture in the kernel default to
O_LARGEFILE, and not do this in user space. I'd suggest now to keep the
patches as part of the ILP32 series after all, to make sure they are
merged at the point when they are needed.
I am a little bit confuse about off_t. In "[PATCH 08/33] 32-bit
ABI: introduce ARCH_32BIT_OFF_T config option", it mentioned that all
the new 32bit architecture should use 64bit off_t.

Should we define off_t in aarch64(for both ilp32 and lp64) in
typesize.h as following?

diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
index 7073493..13b77c5 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
@@ -33,7 +33,7 @@
#define __INO64_T_TYPE __UQUAD_TYPE
#define __MODE_T_TYPE __U32_TYPE
#define __NLINK_T_TYPE __U32_TYPE
-#define __OFF_T_TYPE __SLONGWORD_TYPE
+#define __OFF_T_TYPE __SQUAD_TYPE
#define __OFF64_T_TYPE __SQUAD_TYPE
#define __PID_T_TYPE __S32_TYPE
#define __RLIM_T_TYPE __ULONGWORD_TYPE

Then we could remove the __USE_FILE_OFFSET64 in stat.h and fcnt.h in
aarch64. And truncate and ftruncate is same as truncate64 and
ftruncate64.

Otherwise we need to handle the pad like yury do it in
stat.h, and we need to handle the bigendian as well:

From 61949bf70527b9cc450e7bbdba9182f7f120c5bd Sun March 26 00:00:00 2016
From: j00321192 <***@huawei.com>
Date: Thu, 24 Mar 2016 22:10:25 +0800
Subject: [PATCH] Fix endian issue in struct stat and stat64

There is endian issue in the existence bits/stat.h in aarch64. Fix
it by add the __AARCH64EB__ with proper pad.

Tested in our arm64 hardware. It could fix all the *stat test cases.

Signed-off-by: Yongliang Gao <***@huawei.com>
Signed-off-by: Jun Ji <***@huawei.com>
Signed-off-by: Yang Liu(Young) <***@huawei.com>
Signed-off-by: Zhang Jian(Bamvor) <***@huawei.com>
---
sysdeps/unix/sysv/linux/aarch64/bits/stat.h | 38 +++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/stat.h b/sysdeps/unix/sysv/linux/aarch64/bits/stat.h
index 3d50e7a..4c6e072 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/stat.h
@@ -35,12 +35,21 @@ struct stat
{
__dev_t st_dev; /* Device. */
#ifdef __ILP32__
+
+#if !defined(__AARCH64EB__)
unsigned int __st_ino_pad;
+#endif
+
# ifndef __USE_FILE_OFFSET64
__ino_t st_ino; /* File serial number. */
# else
__ino_t __st_ino; /* 32bit file serial number. */
# endif
+
+#if defined(__AARCH64EB__)
+ unsigned int __st_ino_pad;
+#endif
+
#else
# ifndef __USE_FILE_OFFSET64
__ino_t st_ino; /* File serial number. */
@@ -55,10 +64,17 @@ struct stat
__dev_t st_rdev; /* Device number, if device. */
__dev_t __pad1;
#ifndef __USE_FILE_OFFSET64
+
+#if defined(__ILP32__) && defined(__AARCH64EB__)
+ int __st_size_pad;
+#endif
+
__off_t st_size; /* Size of file, in bytes. */
-# ifdef __ILP32__
+
+#if defined(__ILP32__) && !defined(__AARCH64EB__)
int __st_size_pad;
-# endif
+#endif
+
#else
__off64_t st_size; /* Size of file, in bytes. */
#endif
@@ -66,10 +82,17 @@ struct stat
int __pad2;

#ifndef __USE_FILE_OFFSET64
+
+#if defined (__ILP32__) && defined(__AARCH64EB__)
+ int __st_blocks_pad;
+#endif
+
__blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
-# ifdef __ILP32__
+
+#if defined (__ILP32__) && !defined(__AARCH64EB__)
int __st_blocks_pad;
-# endif
+#endif
+
#else
__blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
#endif
@@ -94,7 +117,7 @@ struct stat
__time_t st_ctime; /* Time of last status change. */
unsigned long int st_ctimensec; /* Nsecs of last status change. */
#endif
-#if !defined __ILP32__ || !defined __USE_FILE_OFFSET64
+#if !defined (__ILP32__) || !defined __USE_FILE_OFFSET64
int __glibc_reserved[2];
#else
__ino64_t st_ino; /* File serial number. */
@@ -106,8 +129,13 @@ struct stat64
{
__dev_t st_dev; /* Device. */
# ifdef __ILP32__
+ #if !defined(__AARCH64EB__)
unsigned int __st_ino_pad;
+ #endif
__ino_t __st_ino; /* 32bit file serial number. */
+ #if defined(__AARCH64EB__)
+ unsigned int __st_ino_pad;
+ #endif
# else
__ino64_t st_ino; /* File serial number. */
# endif
--
1.8.4.5

Regards

bamvor
Post by Arnd Bergmann
Post by Andreas Schwab
+#ifndef __ILP32__
# define F_GETLK64 5
# define F_SETLK64 6
# define F_SETLKW64 7
+#endif
struct flock
{
short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
+#ifndef __USE_FILE_OFFSET64
__off_t l_start; /* Offset where the lock begins. */
__off_t l_len; /* Size of the locked area; zero means until EOF. */
+#else
+ __off64_t l_start; /* Offset where the lock begins. */
+ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
+#endif
__pid_t l_pid; /* Process holding the lock. */
};
This looks like there is another bug as well, but I think this is in
libc, not in the kernel. I'm sure we had discussed this at some point
but I forgot what the outcome was. Defining 'struct flock' to have a
32-bit l_start and l_len member cannot be right if the kernel only
supports 64-bit offsets.
My guess is that the libc should either not define __off_t at all for
ILP32, and always use __off64_t in struct flock, or __off_t should
be defined as __kernel_loff_t a.k.a. long long so the #ifdef can be
avoided.
What exactly do you need to define F_GETLK64 for on LP64?
Arnd
Arnd Bergmann
2016-03-29 11:00:02 UTC
Permalink
Post by Zhangjian (Bamvor)
Hi, Arnd
Post by Arnd Bergmann
Post by Andreas Schwab
This patch may fix a few LTP tests.
Thanks for analyzing.
Post by Andreas Schwab
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
index 3631903..d1010db 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
@@ -25,18 +25,29 @@
#define __O_NOFOLLOW 0100000
#define __O_DIRECT 0200000
-#define __O_LARGEFILE 0
+#ifdef __ILP32__
+# define __O_LARGEFILE 0400000
+#else
+# define __O_LARGEFILE 0
+#endif
I guess this means I screwed up when I said I'd merged the kernel patch
that Yury did to fix it, sorry about that.
We need the patch to make all new architecture in the kernel default to
O_LARGEFILE, and not do this in user space. I'd suggest now to keep the
patches as part of the ILP32 series after all, to make sure they are
merged at the point when they are needed.
I am a little bit confuse about off_t. In "[PATCH 08/33] 32-bit
ABI: introduce ARCH_32BIT_OFF_T config option", it mentioned that all
the new 32bit architecture should use 64bit off_t.
Ah, so it is part of the series. I had not checked that here.
Post by Zhangjian (Bamvor)
Should we define off_t in aarch64(for both ilp32 and lp64) in
typesize.h as following?
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
index 7073493..13b77c5 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
@@ -33,7 +33,7 @@
#define __INO64_T_TYPE __UQUAD_TYPE
#define __MODE_T_TYPE __U32_TYPE
#define __NLINK_T_TYPE __U32_TYPE
-#define __OFF_T_TYPE __SLONGWORD_TYPE
+#define __OFF_T_TYPE __SQUAD_TYPE
#define __OFF64_T_TYPE __SQUAD_TYPE
#define __PID_T_TYPE __S32_TYPE
#define __RLIM_T_TYPE __ULONGWORD_TYPE
Then we could remove the __USE_FILE_OFFSET64 in stat.h and fcnt.h in
aarch64. And truncate and ftruncate is same as truncate64 and
ftruncate64.
I don't know what the glibc developers prefer, but I think the
result needs to be something like that: either __OFF_T_TYPE is
defined as you write above as a 64-bit type, or the user-visible
off_t typedef unconditionally uses __OFF64_T_TYPE rather than
__OFF_T_TYPE.
Post by Zhangjian (Bamvor)
Otherwise we need to handle the pad like yury do it in
I see.
Post by Zhangjian (Bamvor)
@@ -35,12 +35,21 @@ struct stat
{
__dev_t st_dev; /* Device. */
#ifdef __ILP32__
+
+#if !defined(__AARCH64EB__)
unsigned int __st_ino_pad;
+#endif
+
# ifndef __USE_FILE_OFFSET64
__ino_t st_ino; /* File serial number. */
# else
__ino_t __st_ino; /* 32bit file serial number. */
# endif
+
+#if defined(__AARCH64EB__)
+ unsigned int __st_ino_pad;
+#endif
+
#else
This would indeed be silly, we really don't want anyone
to access the old __st_ino field or the 32-bit version of
the offset here.

Arnd
Arnd Bergmann
2016-03-29 12:50:03 UTC
Permalink
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
I am a little bit confuse about off_t. In "[PATCH 08/33] 32-bit
ABI: introduce ARCH_32BIT_OFF_T config option", it mentioned that all
the new 32bit architecture should use 64bit off_t.
Ah, so it is part of the series. I had not checked that here.
I'm preparing new submission now. I can join off_t, s390 and ilp32
patchsets. It seems, they will not be grabbed separately anyway, so
this may decrease confusions like this.
Arnd?
Yes, that sounds good.
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
Should we define off_t in aarch64(for both ilp32 and lp64) in
typesize.h as following?
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
index 7073493..13b77c5 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
@@ -33,7 +33,7 @@
#define __INO64_T_TYPE __UQUAD_TYPE
#define __MODE_T_TYPE __U32_TYPE
#define __NLINK_T_TYPE __U32_TYPE
-#define __OFF_T_TYPE __SLONGWORD_TYPE
+#define __OFF_T_TYPE __SQUAD_TYPE
#define __OFF64_T_TYPE __SQUAD_TYPE
#define __PID_T_TYPE __S32_TYPE
#define __RLIM_T_TYPE __ULONGWORD_TYPE
Then we could remove the __USE_FILE_OFFSET64 in stat.h and fcnt.h in
aarch64. And truncate and ftruncate is same as truncate64 and
ftruncate64.
I don't know what the glibc developers prefer, but I think the
result needs to be something like that: either __OFF_T_TYPE is
defined as you write above as a 64-bit type, or the user-visible
off_t typedef unconditionally uses __OFF64_T_TYPE rather than
__OFF_T_TYPE.
I'm not the glibc developer as well, but I think it's OK.
Which of the two? I guess with the example that Bamvor gave
regarding struct stat, the latter is what we want, forcing the
use of __USE_FILE_OFFSET64 rather than changing the definition of
__OFF_T_TYPE.

Arnd
Zhangjian (Bamvor)
2016-03-29 13:30:02 UTC
Permalink
Hi, Yury
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
Hi, Arnd
Post by Arnd Bergmann
Post by Andreas Schwab
This patch may fix a few LTP tests.
Thanks for analyzing.
Post by Andreas Schwab
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
index 3631903..d1010db 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/fcntl.h
@@ -25,18 +25,29 @@
#define __O_NOFOLLOW 0100000
#define __O_DIRECT 0200000
-#define __O_LARGEFILE 0
+#ifdef __ILP32__
+# define __O_LARGEFILE 0400000
+#else
+# define __O_LARGEFILE 0
+#endif
I guess this means I screwed up when I said I'd merged the kernel patch
that Yury did to fix it, sorry about that.
We need the patch to make all new architecture in the kernel default to
O_LARGEFILE, and not do this in user space. I'd suggest now to keep the
patches as part of the ILP32 series after all, to make sure they are
merged at the point when they are needed.
I am a little bit confuse about off_t. In "[PATCH 08/33] 32-bit
ABI: introduce ARCH_32BIT_OFF_T config option", it mentioned that all
the new 32bit architecture should use 64bit off_t.
Ah, so it is part of the series. I had not checked that here.
I'm preparing new submission now.
Cool:)
I can join off_t, s390 and ilp32
patchsets. It seems, they will not be grabbed separately anyway, so
this may decrease confusions like this.
Arnd?
I am curious which one is more easily to get ack:p
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
Should we define off_t in aarch64(for both ilp32 and lp64) in
typesize.h as following?
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
index 7073493..13b77c5 100644
--- a/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h
@@ -33,7 +33,7 @@
#define __INO64_T_TYPE __UQUAD_TYPE
#define __MODE_T_TYPE __U32_TYPE
#define __NLINK_T_TYPE __U32_TYPE
-#define __OFF_T_TYPE __SLONGWORD_TYPE
+#define __OFF_T_TYPE __SQUAD_TYPE
#define __OFF64_T_TYPE __SQUAD_TYPE
#define __PID_T_TYPE __S32_TYPE
#define __RLIM_T_TYPE __ULONGWORD_TYPE
Then we could remove the __USE_FILE_OFFSET64 in stat.h and fcnt.h in
aarch64. And truncate and ftruncate is same as truncate64 and
ftruncate64.
I don't know what the glibc developers prefer, but I think the
result needs to be something like that: either __OFF_T_TYPE is
defined as you write above as a 64-bit type, or the user-visible
off_t typedef unconditionally uses __OFF64_T_TYPE rather than
__OFF_T_TYPE.
I'm not the glibc developer as well, but I think it's OK.
IIUC, it is usually what glibc does.
If we want to define off_t to 64bit in ilp32, the follow syscall may
need to define as non-compat too:
sys_fadvise64
sys_sendfile
sys_sendfile64
sys_lseek
sys_splice
sys_sync_file_range2
sys_truncate
sys_ftruncate

Regards

Bamvor
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
Otherwise we need to handle the pad like yury do it in
I see.
Post by Zhangjian (Bamvor)
@@ -35,12 +35,21 @@ struct stat
{
__dev_t st_dev; /* Device. */
#ifdef __ILP32__
+
+#if !defined(__AARCH64EB__)
unsigned int __st_ino_pad;
+#endif
+
# ifndef __USE_FILE_OFFSET64
__ino_t st_ino; /* File serial number. */
# else
__ino_t __st_ino; /* 32bit file serial number. */
# endif
+
+#if defined(__AARCH64EB__)
+ unsigned int __st_ino_pad;
+#endif
+
#else
This would indeed be silly, we really don't want anyone
to access the old __st_ino field or the 32-bit version of
the offset here.
Arnd
Arnd Bergmann
2016-03-29 13:30:04 UTC
Permalink
Post by Zhangjian (Bamvor)
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
Then we could remove the __USE_FILE_OFFSET64 in stat.h and fcnt.h in
aarch64. And truncate and ftruncate is same as truncate64 and
ftruncate64.
I don't know what the glibc developers prefer, but I think the
result needs to be something like that: either __OFF_T_TYPE is
defined as you write above as a 64-bit type, or the user-visible
off_t typedef unconditionally uses __OFF64_T_TYPE rather than
__OFF_T_TYPE.
I'm not the glibc developer as well, but I think it's OK.
IIUC, it is usually what glibc does.
If we want to define off_t to 64bit in ilp32, the follow syscall may
sys_fadvise64
sys_sendfile
sys_sendfile64
sys_lseek
sys_splice
sys_sync_file_range2
sys_truncate
sys_ftruncate
I'm not following here. Do you mean in the kernel or in glibc?

In the kernel, the list of syscalls is fine, because we already only
provide syscalls passing loff_t as I said, and that is 64-bit.

In glibc, I think we need to define fewer entry points, not more.
Instead of having both lseek and lseek64, only one of them should
be provided, and that should always take a 64-bit offset, calling
into the kernel with the _llseek syscall entry.

Arnd
Joseph Myers
2016-03-29 16:00:03 UTC
Permalink
Post by Arnd Bergmann
In glibc, I think we need to define fewer entry points, not more.
Instead of having both lseek and lseek64, only one of them should
be provided, and that should always take a 64-bit offset, calling
into the kernel with the _llseek syscall entry.
lseek64 is part of the public API, on all platforms. It should be aliased
to lseek where possible.

Strictly, it would be possible to provide it in the API without it being
part of the ABI, by arranging the headers so that calls to lseek64 result
in objects with a reference to lseek (because it uses the off64_t typedef,
it's not valid to declare it yourself rather than including a header that
declares it). I don't think it would be a good idea for a new
sub-architecture port to try introducing such a difference from all other
ports, however.
--
Joseph S. Myers
***@codesourcery.com
Arnd Bergmann
2016-03-29 19:40:01 UTC
Permalink
Post by Joseph Myers
Post by Arnd Bergmann
In glibc, I think we need to define fewer entry points, not more.
Instead of having both lseek and lseek64, only one of them should
be provided, and that should always take a 64-bit offset, calling
into the kernel with the _llseek syscall entry.
lseek64 is part of the public API, on all platforms. It should be aliased
to lseek where possible.
Right, makes sense.
Post by Joseph Myers
Strictly, it would be possible to provide it in the API without it being
part of the ABI, by arranging the headers so that calls to lseek64 result
in objects with a reference to lseek (because it uses the off64_t typedef,
it's not valid to declare it yourself rather than including a header that
declares it). I don't think it would be a good idea for a new
sub-architecture port to try introducing such a difference from all other
ports, however.
How do we do it then? Should we just define __USE_FILE_OFFSET64
unconditionally for all new 32-bit architectures and leave the
code dealing with 32-bit off_t/ino_t in place but unreachable, to
minimize the differences?

Or should all the obsolete types be defined the same way as their
replacements so we have 64-bit __OFF_T_TYPE/__INO_T_TYPE
and use the same binary implementation regardless of FILE_OFFSET_BITS?

Arnd
Joseph Myers
2016-03-29 20:20:02 UTC
Permalink
Post by Arnd Bergmann
How do we do it then? Should we just define __USE_FILE_OFFSET64
unconditionally for all new 32-bit architectures and leave the
code dealing with 32-bit off_t/ino_t in place but unreachable, to
minimize the differences?
Defining __USE_FILE_OFFSET64 unconditionally would prevent glibc from
building (see: how the patches a while back prototyping changing the
default had to disable the change when glibc itself is built). A change
in the default, though desired (someone needs to pick up those patches
together with the analysis done of possible impact on distributions),
should not be tied to a new port, and would need to be discussed
thoroughly on libc-alpha.
Post by Arnd Bergmann
Or should all the obsolete types be defined the same way as their
replacements so we have 64-bit __OFF_T_TYPE/__INO_T_TYPE
and use the same binary implementation regardless of FILE_OFFSET_BITS?
I think so (along with using wordsize-64 sysdeps directories as far as
possible, like x32 does). But design questions for a glibc port really
belong on libc-alpha to get any sort of community consensus.
--
Joseph S. Myers
***@codesourcery.com
Arnd Bergmann
2016-03-29 20:30:02 UTC
Permalink
Post by Joseph Myers
Post by Arnd Bergmann
How do we do it then? Should we just define __USE_FILE_OFFSET64
unconditionally for all new 32-bit architectures and leave the
code dealing with 32-bit off_t/ino_t in place but unreachable, to
minimize the differences?
Defining __USE_FILE_OFFSET64 unconditionally would prevent glibc from
building (see: how the patches a while back prototyping changing the
default had to disable the change when glibc itself is built). A change
in the default, though desired (someone needs to pick up those patches
together with the analysis done of possible impact on distributions),
should not be tied to a new port, and would need to be discussed
thoroughly on libc-alpha.
Ok
Post by Joseph Myers
Post by Arnd Bergmann
Or should all the obsolete types be defined the same way as their
replacements so we have 64-bit __OFF_T_TYPE/__INO_T_TYPE
and use the same binary implementation regardless of FILE_OFFSET_BITS?
I think so (along with using wordsize-64 sysdeps directories as far as
possible, like x32 does). But design questions for a glibc port really
belong on libc-alpha to get any sort of community consensus.
I thought the wordsize-64 stuff was for the x86 mode where they
define __kernel_long_t as 64-bit. We don't really want to do that in
the kernel for new 32-bit architectures, that would make the kernel
ABI different from all the existing architectures.

The kernel ABI for ilp32 follows the usual wordsize-32 definitions
to make it easy for glibc while avoiding the problems that came from
redefining __kernel_long_t.

Arnd
Joseph Myers
2016-03-29 21:10:01 UTC
Permalink
Post by Arnd Bergmann
Post by Joseph Myers
I think so (along with using wordsize-64 sysdeps directories as far as
possible, like x32 does). But design questions for a glibc port really
belong on libc-alpha to get any sort of community consensus.
I thought the wordsize-64 stuff was for the x86 mode where they
define __kernel_long_t as 64-bit. We don't really want to do that in
the kernel for new 32-bit architectures, that would make the kernel
ABI different from all the existing architectures.
In general the wordsize-64 directories cover various relations of the form
"function X is an alias for function Y", which derive from "type X is
ABI-compatible with type Y". (Unfortunately, the precise set isn't
well-defined, resulting in problems for cases that want a subset of those
relations - e.g. MIPS n64 where struct stat and struct stat64 are
different, and so sysdeps/unix/sysv/linux/wordsize-64 isn't used.)

The person doing the port will need to do a detailed review of the exact
effects of the wordsize-64 directories in current glibc, and which of
those effects are appropriate for this port, to determine what is
appropriate, and to include that analysis with the port submission.

Many of the relations relate to things controlled by _FILE_OFFSET_BITS=64
- if _FILE_OFFSET_BITS=64 does not affect the ABI of off_t, struct stat,
etc., then many of the aliases are correct. Some relations may relate to
other things such as long and long long being ABI compatible - where an
alias in the correct direction can be OK for long arguments (not returns)
if a long argument is always sign-extended to long long when passed to a
function, for example.
--
Joseph S. Myers
***@codesourcery.com
Arnd Bergmann
2016-03-29 21:50:02 UTC
Permalink
Post by Joseph Myers
Post by Arnd Bergmann
Post by Joseph Myers
I think so (along with using wordsize-64 sysdeps directories as far as
possible, like x32 does). But design questions for a glibc port really
belong on libc-alpha to get any sort of community consensus.
I thought the wordsize-64 stuff was for the x86 mode where they
define __kernel_long_t as 64-bit. We don't really want to do that in
the kernel for new 32-bit architectures, that would make the kernel
ABI different from all the existing architectures.
In general the wordsize-64 directories cover various relations of the form
"function X is an alias for function Y", which derive from "type X is
ABI-compatible with type Y". (Unfortunately, the precise set isn't
well-defined, resulting in problems for cases that want a subset of those
relations - e.g. MIPS n64 where struct stat and struct stat64 are
different, and so sysdeps/unix/sysv/linux/wordsize-64 isn't used.)
For all new 32-bit architectures like this, the kernel should at least
behave in a consistent way, but it's somewhere inbetween wordsize-32 and
wordsize-64 for 32-bit architectures, because off_t and ino_t are mapped
to the 64-bit __kernel_loff_t and __kernel_ino_t, while time_t, clock_t
and size_t are mapped to 32 bit types.
Post by Joseph Myers
The person doing the port will need to do a detailed review of the exact
effects of the wordsize-64 directories in current glibc, and which of
those effects are appropriate for this port, to determine what is
appropriate, and to include that analysis with the port submission.
I think the analysis will have to be about two separate things:

* Whether new 32-bit architectures in general should use wordsize-32
or wordsize-64 or something else, based on what you write above.
I would still guess that we are better off adapting wordsize-32
to the current kernel ABI for 32-bit architectures while leaving
wordsize-64 to real 64-bit architectures and x86/x32.

* How we deal with the special case of this architecture having
nonstandard calling conventions for a couple of syscalls that
take 64-bit arguments in a single register rather than two registers
as every other 32-bit architecture does.

Arnd
Zhangjian (Bamvor)
2016-03-31 07:40:02 UTC
Permalink
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
Post by Arnd Bergmann
Post by Zhangjian (Bamvor)
Then we could remove the __USE_FILE_OFFSET64 in stat.h and fcnt.h in
aarch64. And truncate and ftruncate is same as truncate64 and
ftruncate64.
I don't know what the glibc developers prefer, but I think the
result needs to be something like that: either __OFF_T_TYPE is
defined as you write above as a 64-bit type, or the user-visible
off_t typedef unconditionally uses __OFF64_T_TYPE rather than
__OFF_T_TYPE.
I'm not the glibc developer as well, but I think it's OK.
IIUC, it is usually what glibc does.
If we want to define off_t to 64bit in ilp32, the follow syscall may
sys_fadvise64
sys_sendfile
sys_sendfile64
sys_lseek
sys_splice
sys_sync_file_range2
sys_truncate
sys_ftruncate
I'm not following here. Do you mean in the kernel or in glibc?
kernel.
Post by Arnd Bergmann
In the kernel, the list of syscalls is fine, because we already only
provide syscalls passing loff_t as I said, and that is 64-bit.
Sorry I am lost here. I understand that the syscall passing loff_t
should wrap to 64bit syscall. But if we define off_t as 64bit,
then all the offset relative syscall should wrap to 64bit syscall.
Post by Arnd Bergmann
In glibc, I think we need to define fewer entry points, not more.
Instead of having both lseek and lseek64, only one of them should
be provided, and that should always take a 64-bit offset, calling
into the kernel with the _llseek syscall entry.
Agree. We should avoid the duplicated definition.

Regards

Bamvor
Post by Arnd Bergmann
Arnd
Zhangjian (Bamvor)
2016-03-26 13:20:02 UTC
Permalink
Hi, Yury
[...]
Hi Andreas,
Thank you for your patch. It seems like it fixed a couple of tests.
float_bessel FAIL 137
float_exp_log FAIL 137
float_iperb FAIL 137
float_power FAIL 137
float_trigo FAIL 137
pipeio_3 FAIL 5
abort01 FAIL 2
clone02 FAIL 4
kill10 FAIL 2
kill11 FAIL 2
mmap16 FAIL 6
nftw01 FAIL 1
nftw6401 FAIL 1
open12 FAIL 2
pathconf01 FAIL 1
profil01 FAIL 1
rename11 FAIL 2
rmdir02 FAIL 2
umount2_01 FAIL 2
umount2_02 FAIL 2
umount2_03 FAIL 2
utime06 FAIL 2
mtest06 FAIL 11
This is a patch for glibc.
I found 64bit register is used in sysdep.h. It could fix some failure
in bigendian. I do not test it on little endian yet. Hope It helps.

Regards

Bamvor
From a4af2b7a8903ac5e033ba838ec3328bdeb1113ba Mon Sep 17 00:00:00 2001
From: Yang Yingliang <***@huawei.com>
Date: Thu, 13 Nov 2014 16:05:58 +0800
Subject: [PATCH] ARM64: ILP32: change register x1 to PTR_REG

It should use 32-bit register instead of 64-bit register in ILP32.

Suggested-by: Andrew Pinski <***@cavium.com>
Signed-off-by: Yang Yingliang <***@huawei.com>
Signed-off-by: Bamvor Jian Zhang <***@huawei.com>
---
sysdeps/aarch64/sysdep.h | 2 +-
sysdeps/unix/sysv/linux/aarch64/sysdep.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/sysdeps/aarch64/sysdep.h b/sysdeps/aarch64/sysdep.h
index 6673242..742d23c 100644
--- a/sysdeps/aarch64/sysdep.h
+++ b/sysdeps/aarch64/sysdep.h
@@ -104,7 +104,7 @@
#define LDST_GLOBAL(OP, R, T, EXPR) \
adrp x##T, :got:EXPR; \
ldr PTR_REG (T), [x##T, #:got_lo12:EXPR]; \
- OP x##R, [x##T];
+ OP PTR_REG (R), [x##T];

/* Since C identifiers are not normally prefixed with an underscore
on this system, the asm identifier `syscall_error' intrudes on the
diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep.h b/sysdeps/unix/sysv/linux/aarch64/sysdep.h
index 2bfec77..8fb8a6b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/aarch64/sysdep.h
@@ -108,7 +108,7 @@
.Lsyscall_error: \
adrp x1, :gottprel:errno; \
neg w2, w0; \
- ldr x1, [x1, :gottprel_lo12:errno]; \
+ ldr PTR_REG(1), [x1, :gottprel_lo12:errno]; \
mrs x3, tpidr_el0; \
mov x0, -1; \
str w2, [x1, x3]; \
--
1.8.4.5
Yury.
Zhangjian (Bamvor)
2016-03-26 13:50:02 UTC
Permalink
Hi, guys

Does any body test the bigendian? We found lots of failures in be in
our arm64 hardware. E.g. the signal issue.

IIUC, the signal of struct in ILP32 is align with the aarch32. If so,
we need to revert the following patch wrote by Andrew in 2014 which
align the kernel_sigaction of ilp32 to lp64:
Revert "[AARCH64] Add kernel_sigaction.h for AARCH64 ILP32"

And we also need to handle the uc_stack properly in kernel. After
apply these two patches, we could fix lots of failure in bigendian.

Regards

Bamvor

From cb08043a1f14eb997892711c2e1e5016b0e9eef6 Mon Sep 17 00:00:00 2001
From: Bamvor Jian Zhang <***@huawei.com>
Date: Thu, 24 Mar 2016 10:40:47 +0800
Subject: [PATCH] try to fix the signal issue in be

Currently, there is different layout in uc_stack in le and be.
Try to fix the issue by processing uc_stack through corresponding
compat function.

Signed-off-by: Bamvor Jian Zhang <***@huawei.com>
---
arch/arm64/kernel/signal_ilp32.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
index 26b3121..9af29e0 100644
--- a/arch/arm64/kernel/signal_ilp32.c
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -60,7 +60,7 @@ asmlinkage int ilp32_sys_rt_sigreturn(struct pt_regs *regs)
if (restore_sigframe(regs, &frame->sig))
goto badframe;

- if (restore_altstack(&frame->sig.uc.uc_stack))
+ if (compat_restore_altstack(&frame->sig.uc.uc_stack))
goto badframe;

return regs->regs[0];
@@ -112,7 +112,7 @@ int ilp32_setup_rt_frame(int usig, struct ksignal *ksig,
__put_user_error(0, &frame->sig.uc.uc_flags, err);
__put_user_error(NULL, &frame->sig.uc.uc_link, err);

- err |= __save_altstack(&frame->sig.uc.uc_stack, regs->sp);
+ err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->sp);
err |= setup_sigframe(&frame->sig, regs, set);
if (err == 0) {
setup_return(regs, &ksig->ka, frame,
--
1.8.4.5

From f6cde6e2a75a4b153758eea679c5a839fc1c39d2 Mon Sep 17 00:00:00 2001
From: "Zhang Jian(Bamvor)" <***@huawei.com>
Date: Sat, 26 Mar 2016 18:10:38 +0800
Subject: [PATCH] Revert "[AARCH64] Add kernel_sigaction.h for AARCH64 ILP32"

This reverts commit 68e11d8643cfd08a62cea3555e92d77a21bf41de.
---
sysdeps/unix/sysv/linux/aarch64/kernel_sigaction.h | 12 ------------
sysdeps/unix/sysv/linux/aarch64/sigaction.c | 10 ++++------
2 files changed, 4 insertions(+), 18 deletions(-)
delete mode 100644 sysdeps/unix/sysv/linux/aarch64/kernel_sigaction.h

diff --git a/sysdeps/unix/sysv/linux/aarch64/kernel_sigaction.h b/sysdeps/unix/sysv/linux/aarch64/kernel_sigaction.h
deleted file mode 100644
index 7b3023b..0000000
--- a/sysdeps/unix/sysv/linux/aarch64/kernel_sigaction.h
+++ /dev/null
@@ -1,12 +0,0 @@
-
-#define HAVE_SA_RESTORER
-
-/* This is the sigaction structure in aarch64 kernel.
- Note the ILP32 struct uses the same struct as LP64
- which is why the fields are 64bit in size. */
-struct kernel_sigaction {
- unsigned long long k_sa_handler;
- unsigned long long sa_flags;
- unsigned long long sa_restorer;
- sigset_t sa_mask;
-};
diff --git a/sysdeps/unix/sysv/linux/aarch64/sigaction.c b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
index 5d22b68..2679acd 100644
--- a/sysdeps/unix/sysv/linux/aarch64/sigaction.c
+++ b/sysdeps/unix/sysv/linux/aarch64/sigaction.c
@@ -39,17 +39,15 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)

if (act)
{
- kact.k_sa_handler = (unsigned long long)(uintptr_t)act->sa_handler;
+ kact.k_sa_handler = act->sa_handler;
memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
kact.sa_flags = act->sa_flags;
#ifdef HAVE_SA_RESTORER
if (kact.sa_flags & SA_RESTORER)
- kact.sa_restorer = (unsigned long long)(uintptr_t)act->sa_restorer;
+ kact.sa_restorer = act->sa_restorer;
#endif
}

- /* This is needed for ILP32 as the structures are two different sizes due to
- using the LP64 structure. */
result = INLINE_SYSCALL (rt_sigaction, 4, sig,
act ? &kact : NULL,
oact ? &koact : NULL, _NSIG / 8);
@@ -57,11 +55,11 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
{
if (oact && result >= 0)
{
- oact->sa_handler = (void*)(uintptr_t)koact.k_sa_handler;
+ oact->sa_handler = koact.k_sa_handler;
memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
oact->sa_flags = koact.sa_flags;
#ifdef HAVE_SA_RESTORER
- oact->sa_restorer = (void*)(uintptr_t)koact.sa_restorer;
+ oact->sa_restorer = koact.sa_restorer;
#endif
}
}
--
1.8.4.5
Continue reading on narkive:
Loading...