2018-05-15 19:13:01

by Yury Norov

[permalink] [raw]
Subject: [PATCH v9 00/24] ILP32 for ARM64

This series enables AARCH64 with ILP32 mode.

As supporting work, it introduces ARCH_32BIT_OFF_T configuration
option that is enabled for existing 32-bit architectures but disabled
for new arches (so 64-bit off_t userspace type is used by new userspace).
Also it deprecates getrlimit and setrlimit syscalls prior to prlimit64.

Based on kernel v4.16. Tested with LTP, glibc testsuite, trinity, lmbench,
CPUSpec.

This series on github:
https://github.com/norov/linux/tree/ilp32-4.16
Linaro toolchain:
http://snapshots.linaro.org/components/toolchain/binaries/7.3-2018.04-rc1/aarch64-linux-gnu_ilp32/
Debian repo:
http://people.linaro.org/~wookey/ilp32/
OpenSUSE repo:
https://build.opensuse.org/project/show/devel:ARM:Factory:Contrib:ILP32

Changes:
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
v6: https://lkml.org/lkml/2016/5/23/661
v7: https://lkml.org/lkml/2017/1/9/213
v8: https://lkml.org/lkml/2017/6/19/624
v9: - rebased on top of v4.16;
- signal subsystem reworked to avoid code duplication, as requested
by Dave Martin (patches 18 and 20);
- new files introduced in series use SPDX notation for license;
- linux-api and linux-arch CCed as the series changes kernel ABI;
- checkpatch and other minor fixes.

Andrew Pinski (4):
arm64: rename COMPAT to AARCH32_EL0 in Kconfig
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

Catalin Marinas (1):
arm64: ilp32: Make the Kconfig option default y

Dave Martin (1):
arm64: signal: Make parse_user_sigframe() independent of rt_sigframe
layout

James Morse (1):
ptrace: Add compat PTRACE_{G,S}ETSIGMASK handlers

Philipp Tomsich (1):
arm64:ilp32: add vdso-ilp32 and use for signal return

Yury Norov (16):
compat ABI: use non-compat openat and open_by_handle_at variants
32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option
asm-generic: Drop getrlimit and setrlimit syscalls from default list
thread: move thread bits accessors to separated file
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
arm64: rename functions that reference compat term
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: change compat_elf_hwcap and compat_elf_hwcap2 prefix to a32
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ilp32: share aarch32 syscall handlers
arm64: signal: share lp64 signal structures and routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: ilp32: introduce ilp32-specific sigframe and ucontext
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32

Documentation/arm64/ilp32.txt | 45 +++
arch/Kconfig | 15 +
arch/arc/Kconfig | 1 +
arch/arc/include/uapi/asm/unistd.h | 1 +
arch/arm/Kconfig | 1 +
arch/arm64/Kconfig | 18 +-
arch/arm64/Makefile | 3 +
arch/arm64/include/asm/compat.h | 19 +-
arch/arm64/include/asm/elf.h | 36 +-
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/ftrace.h | 2 +-
arch/arm64/include/asm/hwcap.h | 8 +-
arch/arm64/include/asm/is_compat.h | 78 ++++
arch/arm64/include/asm/processor.h | 15 +-
arch/arm64/include/asm/ptrace.h | 12 +-
arch/arm64/include/asm/seccomp.h | 2 +-
arch/arm64/include/asm/signal32.h | 19 +-
arch/arm64/include/asm/signal32_common.h | 13 +
arch/arm64/include/asm/signal_common.h | 306 +++++++++++++++
arch/arm64/include/asm/signal_ilp32.h | 23 ++
arch/arm64/include/asm/syscall.h | 2 +-
arch/arm64/include/asm/thread_info.h | 4 +-
arch/arm64/include/asm/unistd.h | 6 +-
arch/arm64/include/asm/vdso.h | 6 +
arch/arm64/include/uapi/asm/bitsperlong.h | 9 +-
arch/arm64/include/uapi/asm/unistd.h | 13 +
arch/arm64/kernel/Makefile | 8 +-
arch/arm64/kernel/armv8_deprecated.c | 6 +-
arch/arm64/kernel/asm-offsets.c | 9 +-
arch/arm64/kernel/binfmt_elf32.c | 35 ++
arch/arm64/kernel/binfmt_ilp32.c | 87 +++++
arch/arm64/kernel/cpufeature.c | 28 +-
arch/arm64/kernel/cpuinfo.c | 18 +-
arch/arm64/kernel/debug-monitors.c | 4 +-
arch/arm64/kernel/entry.S | 37 +-
arch/arm64/kernel/entry32.S | 80 ----
arch/arm64/kernel/entry32_common.S | 97 +++++
arch/arm64/kernel/entry_ilp32.S | 12 +
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 8 +-
arch/arm64/kernel/perf_callchain.c | 28 +-
arch/arm64/kernel/perf_regs.c | 4 +-
arch/arm64/kernel/process.c | 11 +-
arch/arm64/kernel/ptrace.c | 36 +-
arch/arm64/kernel/signal.c | 352 +++---------------
arch/arm64/kernel/signal32.c | 111 +++---
arch/arm64/kernel/signal32_common.c | 37 ++
arch/arm64/kernel/signal_ilp32.c | 65 ++++
arch/arm64/kernel/sys_compat.c | 10 +-
arch/arm64/kernel/sys_ilp32.c | 90 +++++
arch/arm64/kernel/traps.c | 11 +-
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 82 ++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 22 ++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 84 +++++
arch/arm64/kernel/vdso.c | 65 +++-
arch/arm64/kernel/vdso/gettimeofday.S | 20 +-
arch/arm64/kernel/vdso/vdso.S | 6 +-
arch/arm64/mm/mmap.c | 2 +-
arch/blackfin/Kconfig | 1 +
arch/c6x/include/uapi/asm/unistd.h | 1 +
arch/cris/Kconfig | 1 +
arch/frv/Kconfig | 1 +
arch/h8300/Kconfig | 1 +
arch/h8300/include/uapi/asm/unistd.h | 1 +
arch/hexagon/Kconfig | 1 +
arch/hexagon/include/uapi/asm/unistd.h | 1 +
arch/m32r/Kconfig | 1 +
arch/m68k/Kconfig | 1 +
arch/metag/Kconfig | 1 +
arch/metag/include/uapi/asm/unistd.h | 1 +
arch/microblaze/Kconfig | 1 +
arch/mips/Kconfig | 1 +
arch/mn10300/Kconfig | 1 +
arch/nios2/Kconfig | 1 +
arch/nios2/include/uapi/asm/unistd.h | 1 +
arch/openrisc/Kconfig | 1 +
arch/openrisc/include/uapi/asm/unistd.h | 1 +
arch/parisc/Kconfig | 1 +
arch/powerpc/Kconfig | 1 +
arch/score/Kconfig | 1 +
arch/score/include/uapi/asm/unistd.h | 1 +
arch/sh/Kconfig | 1 +
arch/sparc/Kconfig | 1 +
arch/tile/Kconfig | 1 +
arch/tile/include/uapi/asm/unistd.h | 1 +
arch/tile/kernel/compat.c | 3 +
arch/unicore32/Kconfig | 1 +
arch/unicore32/include/uapi/asm/unistd.h | 1 +
arch/x86/Kconfig | 1 +
arch/x86/um/Kconfig | 1 +
arch/xtensa/Kconfig | 1 +
drivers/clocksource/arm_arch_timer.c | 4 +-
include/linux/fcntl.h | 2 +-
include/linux/sched.h | 1 +
include/linux/thread_bits.h | 76 ++++
include/linux/thread_info.h | 64 +---
include/uapi/asm-generic/unistd.h | 10 +-
kernel/ptrace.c | 48 ++-
scripts/checksyscalls.sh | 5 +
100 files changed, 1675 insertions(+), 698 deletions(-)
create mode 100644 Documentation/arm64/ilp32.txt
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/entry32_common.S
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 include/linux/thread_bits.h

--
2.17.0



2018-05-15 19:13:32

by Yury Norov

[permalink] [raw]
Subject: [PATCH 01/24] arm64: signal: Make parse_user_sigframe() independent of rt_sigframe layout

From: Dave Martin <[email protected]>

ILP32 uses the same struct sigcontext as the native ABI (i.e.,
LP64), but a different layout for the rest of the signal frame (since
siginfo_t and ucontext_t are both ABI-dependent).

Since the purpose of parse_user_sigframe() is really to parse sigcontext
and not the whole signal frame, the function does not need to depend
on the layout of rt_sigframe -- the only purpose of the rt_sigframe
pointer is for use as a base to measure the signal frame size.

So, this patch renames the function to make it clear that only the
sigcontext is really being parsed, and makes the sigframe base pointer
generic. A macro is defined to provide a suitable duck-typed interface
that can be used with both sigframe definitions.

Suggested-by: Yury Norov <[email protected]>
Signed-off-by: Dave Martin <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/kernel/signal.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index f60c052e8d1c..65406218743c 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -334,17 +334,16 @@ extern int restore_sve_fpsimd_context(struct user_ctxs *user);

#endif /* ! CONFIG_ARM64_SVE */

-
-static int parse_user_sigframe(struct user_ctxs *user,
- struct rt_sigframe __user *sf)
+static int __parse_user_sigcontext(struct user_ctxs *user,
+ struct sigcontext __user const *sc,
+ void __user const *sigframe_base)
{
- struct sigcontext __user *const sc = &sf->uc.uc_mcontext;
struct _aarch64_ctx __user *head;
char __user *base = (char __user *)&sc->__reserved;
size_t offset = 0;
size_t limit = sizeof(sc->__reserved);
bool have_extra_context = false;
- char const __user *const sfp = (char const __user *)sf;
+ char const __user *const sfp = (char const __user *)sigframe_base;

user->fpsimd = NULL;
user->sve = NULL;
@@ -493,6 +492,9 @@ static int parse_user_sigframe(struct user_ctxs *user,
return -EINVAL;
}

+#define parse_user_sigcontext(user, sf) \
+ __parse_user_sigcontext(user, &(sf)->uc.uc_mcontext, sf)
+
static int restore_sigframe(struct pt_regs *regs,
struct rt_sigframe __user *sf)
{
@@ -518,7 +520,7 @@ static int restore_sigframe(struct pt_regs *regs,

err |= !valid_user_regs(&regs->user_regs, current);
if (err == 0)
- err = parse_user_sigframe(&user, sf);
+ err = parse_user_sigcontext(&user, sf);

if (err == 0) {
if (!user.fpsimd)
--
2.17.0


2018-05-15 19:15:24

by Yury Norov

[permalink] [raw]
Subject: [PATCH 02/24] ptrace: Add compat PTRACE_{G,S}ETSIGMASK handlers

From: James Morse <[email protected]>

compat_ptrace_request() lacks handlers for PTRACE_{G,S}ETSIGMASK,
instead using those in ptrace_request(). The compat variant should
read a compat_sigset_t from userspace instead of ptrace_request()s
sigset_t.

While compat_sigset_t is the same size as sigset_t, it is defined as
2xu32, instead of a single u64. On a big-endian CPU this means that
compat_sigset_t is passed to user-space using middle-endianness,
where the least-significant u32 is written most significant byte
first.

If ptrace_request()s code is used userspace will read the most
significant u32 where it expected the least significant.

Instead of duplicating ptrace_request()s code as a special case in
the arch code, handle it here.

Fixes: 29000caecbe87 ("ptrace: add ability to get/set signal-blocked mask")
CC: Andrey Vagin <[email protected]>
Reported-by: Zhou Chengming <[email protected]>
Signed-off-by: James Morse <[email protected]>

Yury:
Replace sigset_{to,from}_compat() with new {get,put}_compat_sigset()
Signed-off-by: Yury Norov <[email protected]>
---
kernel/ptrace.c | 48 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 21fec73d45d4..214944d7c268 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -880,6 +880,22 @@ static int ptrace_regset(struct task_struct *task, int req, unsigned int type,
EXPORT_SYMBOL_GPL(task_user_regset_view);
#endif

+static int ptrace_setsigmask(struct task_struct *child, sigset_t *new_set)
+{
+ sigdelsetmask(new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+ /*
+ * Every thread does recalc_sigpending() after resume, so
+ * retarget_shared_pending() and recalc_sigpending() are not
+ * called here.
+ */
+ spin_lock_irq(&child->sighand->siglock);
+ child->blocked = *new_set;
+ spin_unlock_irq(&child->sighand->siglock);
+
+ return 0;
+}
+
int ptrace_request(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -951,18 +967,7 @@ int ptrace_request(struct task_struct *child, long request,
break;
}

- sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
-
- /*
- * Every thread does recalc_sigpending() after resume, so
- * retarget_shared_pending() and recalc_sigpending() are not
- * called here.
- */
- spin_lock_irq(&child->sighand->siglock);
- child->blocked = new_set;
- spin_unlock_irq(&child->sighand->siglock);
-
- ret = 0;
+ ret = ptrace_setsigmask(child, &new_set);
break;
}

@@ -1181,6 +1186,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
{
compat_ulong_t __user *datap = compat_ptr(data);
compat_ulong_t word;
+ sigset_t new_set;
siginfo_t siginfo;
int ret;

@@ -1221,6 +1227,24 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
else
ret = ptrace_setsiginfo(child, &siginfo);
break;
+ case PTRACE_GETSIGMASK:
+ if (addr != sizeof(compat_sigset_t))
+ return -EINVAL;
+
+ ret = put_compat_sigset((compat_sigset_t __user *) datap,
+ &child->blocked, sizeof(compat_sigset_t));
+ break;
+ case PTRACE_SETSIGMASK:
+ if (addr != sizeof(compat_sigset_t))
+ return -EINVAL;
+
+ ret = get_compat_sigset(&new_set,
+ (compat_sigset_t __user *) datap);
+ if (ret)
+ break;
+
+ ret = ptrace_setsigmask(child, &new_set);
+ break;
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
case PTRACE_GETREGSET:
case PTRACE_SETREGSET:
--
2.17.0


2018-05-15 19:41:48

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH v9 00/24] ILP32 for ARM64

Hi all,

On Tue, May 15, 2018 at 10:11:50PM +0300, Yury Norov wrote:
> This series enables AARCH64 with ILP32 mode.
>
> As supporting work, it introduces ARCH_32BIT_OFF_T configuration
> option that is enabled for existing 32-bit architectures but disabled
> for new arches (so 64-bit off_t userspace type is used by new userspace).
> Also it deprecates getrlimit and setrlimit syscalls prior to prlimit64.
>
> Based on kernel v4.16. Tested with LTP, glibc testsuite, trinity, lmbench,
> CPUSpec.
>
> This series on github:
> https://github.com/norov/linux/tree/ilp32-4.16
> Linaro toolchain:
> http://snapshots.linaro.org/components/toolchain/binaries/7.3-2018.04-rc1/aarch64-linux-gnu_ilp32/
> Debian repo:
> http://people.linaro.org/~wookey/ilp32/
> OpenSUSE repo:
> https://build.opensuse.org/project/show/devel:ARM:Factory:Contrib:ILP32
>
> Changes:
> 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
> v6: https://lkml.org/lkml/2016/5/23/661
> v7: https://lkml.org/lkml/2017/1/9/213
> v8: https://lkml.org/lkml/2017/6/19/624
> v9: - rebased on top of v4.16;
> - signal subsystem reworked to avoid code duplication, as requested
> by Dave Martin (patches 18 and 20);
> - new files introduced in series use SPDX notation for license;
> - linux-api and linux-arch CCed as the series changes kernel ABI;
> - checkpatch and other minor fixes.

My mail server seems broken. I will try to submit series tomorroe
again. Sorry for noise.

Yury