2018-05-16 08:20:30

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.
- Zhou Chengming's reported-by for patch 2 and signed-off-by for
patch 21 removed because his email became invalid. Zhou, please
share your new email.

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-16 08:21:05

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]>
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-16 08:21:51

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-16 08:22:29

by Yury Norov

[permalink] [raw]
Subject: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

All new 32-bit architectures should have 64-bit userspace off_t type, but
existing architectures has 32-bit ones.

To enforce the rule, new config option is added to arch/Kconfig that defaults
ARCH_32BIT_OFF_T to be disabled for new 32-bit architectures. All existing
32-bit architectures enable it explicitly.

New option affects force_o_largefile() behaviour. Namely, if userspace
off_t is 64-bits long, we have no reason to reject user to open big files.

Note that even if architectures has only 64-bit off_t in the kernel
(arc, c6x, h8300, hexagon, metag, nios2, openrisc, tile32 and unicore32),
a libc may use 32-bit off_t, and therefore want to limit the file size
to 4GB unless specified differently in the open flags.

Signed-off-by: Yury Norov <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
---
arch/Kconfig | 15 +++++++++++++++
arch/arc/Kconfig | 1 +
arch/arm/Kconfig | 1 +
arch/blackfin/Kconfig | 1 +
arch/cris/Kconfig | 1 +
arch/frv/Kconfig | 1 +
arch/h8300/Kconfig | 1 +
arch/hexagon/Kconfig | 1 +
arch/m32r/Kconfig | 1 +
arch/m68k/Kconfig | 1 +
arch/metag/Kconfig | 1 +
arch/microblaze/Kconfig | 1 +
arch/mips/Kconfig | 1 +
arch/mn10300/Kconfig | 1 +
arch/nios2/Kconfig | 1 +
arch/openrisc/Kconfig | 1 +
arch/parisc/Kconfig | 1 +
arch/powerpc/Kconfig | 1 +
arch/score/Kconfig | 1 +
arch/sh/Kconfig | 1 +
arch/sparc/Kconfig | 1 +
arch/tile/Kconfig | 1 +
arch/unicore32/Kconfig | 1 +
arch/x86/Kconfig | 1 +
arch/x86/um/Kconfig | 1 +
arch/xtensa/Kconfig | 1 +
include/linux/fcntl.h | 2 +-
27 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 76c0b54443b1..ee079244dc3c 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
config ARCH_WANTS_DYNAMIC_TASK_STRUCT
bool

+config ARCH_32BIT_OFF_T
+ bool
+ depends on !64BIT
+ help
+ All new 32-bit architectures should have 64-bit off_t type on
+ userspace side which corresponds to the loff_t kernel type. This
+ is the requirement for modern ABIs. Some existing architectures
+ already have 32-bit off_t. This option is enabled for all such
+ architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
+ h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
+ nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
+ unicore32, x86_32 and xtensa. This is the complete list. Any
+ new 32-bit architecture should declare 64-bit off_t type on user
+ side and so should not enable this option.
+
config HAVE_REGS_AND_STACK_ACCESS_API
bool
help
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index d76bf4a83740..9b48c82a12f6 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -11,6 +11,7 @@ config ARC
select ARC_TIMERS
select ARCH_HAS_SG_CHAIN
select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
+ select ARCH_32BIT_OFF_T
select BUILDTIME_EXTABLE_SORT
select CLONE_BACKWARDS
select COMMON_CLK
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7e3d53575486..825a611a9d86 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2,6 +2,7 @@
config ARM
bool
default y
+ select ARCH_32BIT_OFF_T
select ARCH_CLOCKSOURCE_DATA
select ARCH_DISCARD_MEMBLOCK if !HAVE_ARCH_PFN_VALID && !KEXEC
select ARCH_HAS_DEBUG_VIRTUAL if MMU
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index d9c2866ba618..5a99c1ccad67 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -13,6 +13,7 @@ config RWSEM_XCHGADD_ALGORITHM

config BLACKFIN
def_bool y
+ select ARCH_32BIT_OFF_T
select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK
select HAVE_DYNAMIC_FTRACE
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index cd5a0865c97f..db7ea0a9e805 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -54,6 +54,7 @@ config LOCKDEP_SUPPORT
config CRIS
bool
default y
+ select ARCH_32BIT_OFF_T
select HAVE_IDE
select GENERIC_ATOMIC64
select HAVE_UID16
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index af369b05fed5..9dc671f8f4a6 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -2,6 +2,7 @@
config FRV
bool
default y
+ select ARCH_32BIT_OFF_T
select HAVE_IDE
select HAVE_ARCH_TRACEHOOK
select HAVE_PERF_EVENTS
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 091d6d04b5e5..6fc8a034ddb6 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config H8300
def_bool y
+ select ARCH_32BIT_OFF_T
select GENERIC_ATOMIC64
select HAVE_UID16
select VIRT_TO_BUS
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 76d2f20d525e..f6e748178292 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -4,6 +4,7 @@ comment "Linux Kernel Configuration for Hexagon"

config HEXAGON
def_bool y
+ select ARCH_32BIT_OFF_T
select HAVE_OPROFILE
# Other pending projects/to-do items.
# select HAVE_REGS_AND_STACK_ACCESS_API
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index dd84ee194579..8d9c2244b144 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -2,6 +2,7 @@
config M32R
bool
default y
+ select ARCH_32BIT_OFF_T
select HAVE_IDE
select HAVE_OPROFILE
select INIT_ALL_POSSIBLE
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 785612b576f7..8aafd39b5142 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -2,6 +2,7 @@
config M68K
bool
default y
+ select ARCH_32BIT_OFF_T
select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
select ARCH_NO_COHERENT_DMA_MMAP if !MMU
select HAVE_IDE
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index c7b62a339539..8bc07fa5982d 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config METAG
def_bool y
+ select ARCH_32BIT_OFF_T
select EMBEDDED
select GENERIC_ATOMIC64
select GENERIC_CLOCKEVENTS
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 3817a3e2146c..48270951c3aa 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -1,5 +1,6 @@
config MICROBLAZE
def_bool y
+ select ARCH_32BIT_OFF_T
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_NO_COHERENT_DMA_MMAP if !MMU
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 8128c3b68d6b..3eb048042004 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2,6 +2,7 @@
config MIPS
bool
default y
+ select ARCH_32BIT_OFF_T if !64BIT
select ARCH_BINFMT_ELF_STATE
select ARCH_CLOCKSOURCE_DATA
select ARCH_DISCARD_MEMBLOCK
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index e9d8d60bd28b..7840859b3f9f 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config MN10300
def_bool y
+ select ARCH_32BIT_OFF_T
select HAVE_EXIT_THREAD
select HAVE_OPROFILE
select HAVE_UID16
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 3d4ec88f1db1..9b4a9cf4af3b 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config NIOS2
def_bool y
+ select ARCH_32BIT_OFF_T
select TIMER_OF
select GENERIC_ATOMIC64
select GENERIC_CLOCKEVENTS
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 339df7324e9c..24c7c25064e5 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -6,6 +6,7 @@

config OPENRISC
def_bool y
+ select ARCH_32BIT_OFF_T
select OF
select OF_EARLY_FLATTREE
select IRQ_DOMAIN
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 9792d8cf4f56..93f8cecbb741 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config PARISC
def_bool y
+ select ARCH_32BIT_OFF_T if !64BIT
select ARCH_MIGHT_HAVE_PC_PARPORT
select HAVE_IDE
select HAVE_OPROFILE
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 73ce5dd07642..4f38ce304b78 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -134,6 +134,7 @@ config PPC
#
# Please keep this list sorted alphabetically.
#
+ select ARCH_32BIT_OFF_T if PPC32
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_DMA_SET_COHERENT_MASK
select ARCH_HAS_ELF_RANDOMIZE
diff --git a/arch/score/Kconfig b/arch/score/Kconfig
index d881f99c9ddd..7371e5fb18b9 100644
--- a/arch/score/Kconfig
+++ b/arch/score/Kconfig
@@ -3,6 +3,7 @@ menu "Machine selection"

config SCORE
def_bool y
+ select ARCH_32BIT_OFF_T
select GENERIC_IRQ_SHOW
select GENERIC_IOMAP
select GENERIC_ATOMIC64
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 97fe29316476..bbd75a7cbbc4 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -58,6 +58,7 @@ config SUPERH

config SUPERH32
def_bool ARCH = "sh"
+ select ARCH_32BIT_OFF_T
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_IOREMAP_PROT if MMU && !X2TLB
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 8767e45f1b2b..3cc26d90ab82 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -47,6 +47,7 @@ config SPARC

config SPARC32
def_bool !64BIT
+ select ARCH_32BIT_OFF_T
select GENERIC_ATOMIC64
select CLZ_TAB
select HAVE_UID16
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index ef9d403cbbe4..542bf49cdfcc 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -4,6 +4,7 @@

config TILE
def_bool y
+ select ARCH_32BIT_OFF_T if !64BIT
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_WANT_FRAME_POINTERS
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
index 462e59a7ae78..34694eb7c790 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
config UNICORE32
def_bool y
+ select ARCH_32BIT_OFF_T
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0fa71a78ec99..47c2f1eaa7ad 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -44,6 +44,7 @@ config X86
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ANON_INODES
+ select ARCH_32BIT_OFF_T if X86_32
select ARCH_CLOCKSOURCE_DATA
select ARCH_DISCARD_MEMBLOCK
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 13ed827c7c66..d1de823a8fe7 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -22,6 +22,7 @@ config 64BIT
config X86_32
def_bool !64BIT
select HAVE_AOUT
+ select ARCH_32BIT_OFF_T
select ARCH_WANT_IPC_PARSE_VERSION
select MODULES_USE_ELF_REL
select CLONE_BACKWARDS
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index c921e8bccdc8..20ebab4fbaf6 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -4,6 +4,7 @@ config ZONE_DMA

config XTENSA
def_bool y
+ select ARCH_32BIT_OFF_T
select ARCH_NO_COHERENT_DMA_MMAP if !MMU
select ARCH_WANT_FRAME_POINTERS
select ARCH_WANT_IPC_PARSE_VERSION
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 27dc7a60693e..d019df946cb2 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -12,7 +12,7 @@
O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)

#ifndef force_o_largefile
-#define force_o_largefile() (BITS_PER_LONG != 32)
+#define force_o_largefile() (!IS_ENABLED(CONFIG_ARCH_32BIT_OFF_T))
#endif

#if BITS_PER_LONG == 32
--
2.17.0


2018-05-16 08:22:34

by Yury Norov

[permalink] [raw]
Subject: [PATCH 09/24] arm64: rename functions that reference compat term

The ILP32 for ARM64 patch series introduces another 'compat' mode for
arm64. So to avoid confusing, aarch32-only functions renamed in according
to it.

Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/include/asm/ptrace.h | 10 ++--
arch/arm64/include/asm/signal32.h | 13 ++--
arch/arm64/kernel/armv8_deprecated.c | 6 +-
arch/arm64/kernel/cpufeature.c | 6 +-
arch/arm64/kernel/debug-monitors.c | 4 +-
arch/arm64/kernel/perf_callchain.c | 22 +++----
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 4 +-
arch/arm64/kernel/signal.c | 8 +--
arch/arm64/kernel/signal32.c | 88 ++++++++++++++--------------
arch/arm64/kernel/sys_compat.c | 10 ++--
arch/arm64/kernel/traps.c | 6 +-
12 files changed, 90 insertions(+), 89 deletions(-)

diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 0c85b469ad68..1ca181a6903a 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -155,16 +155,16 @@ static inline void forget_syscall(struct pt_regs *regs)
#define arch_has_single_step() (1)

#ifdef CONFIG_AARCH32_EL0
-#define compat_thumb_mode(regs) \
+#define a32_thumb_mode(regs) \
(((regs)->pstate & COMPAT_PSR_T_BIT))
#else
-#define compat_thumb_mode(regs) (0)
+#define a32_thumb_mode(regs) (0)
#endif

#define user_mode(regs) \
(((regs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t)

-#define compat_user_mode(regs) \
+#define a32_user_mode(regs) \
(((regs)->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == \
(PSR_MODE32_BIT | PSR_MODE_EL0t))

@@ -178,10 +178,10 @@ static inline void forget_syscall(struct pt_regs *regs)
(!((regs)->pstate & PSR_F_BIT))

#define GET_USP(regs) \
- (!compat_user_mode(regs) ? (regs)->sp : (regs)->compat_sp)
+ (!a32_user_mode(regs) ? (regs)->sp : (regs)->compat_sp)

#define SET_USP(ptregs, value) \
- (!compat_user_mode(regs) ? ((regs)->sp = value) : ((regs)->compat_sp = value))
+ (!a32_user_mode(regs) ? ((regs)->sp = value) : ((regs)->compat_sp = value))

extern int regs_query_register_offset(const char *name);
extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
index 2ebde460f5a0..92f48828b13a 100644
--- a/arch/arm64/include/asm/signal32.h
+++ b/arch/arm64/include/asm/signal32.h
@@ -24,27 +24,28 @@

#define AARCH32_KERN_SIGRET_CODE_OFFSET 0x500

-int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
+int a32_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs);
-int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+
+int a32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs);

-void compat_setup_restart_syscall(struct pt_regs *regs);
+void a32_setup_restart_syscall(struct pt_regs *regs);
#else

-static inline int compat_setup_frame(int usid, struct ksignal *ksig,
+static inline int a32_setup_frame(int usid, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs)
{
return -ENOSYS;
}

-static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+static inline int a32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
return -ENOSYS;
}

-static inline void compat_setup_restart_syscall(struct pt_regs *regs)
+static inline void a32_setup_restart_syscall(struct pt_regs *regs)
{
}
#endif /* CONFIG_AARCH32_EL0 */
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 68450e954d47..b4f5ab915a0d 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -555,7 +555,7 @@ static int setend_set_hw_mode(bool enable)
return 0;
}

-static int compat_setend_handler(struct pt_regs *regs, u32 big_endian)
+static int __a32_setend_handler(struct pt_regs *regs, u32 big_endian)
{
char *insn;

@@ -578,14 +578,14 @@ static int compat_setend_handler(struct pt_regs *regs, u32 big_endian)

static int a32_setend_handler(struct pt_regs *regs, u32 instr)
{
- int rc = compat_setend_handler(regs, (instr >> 9) & 1);
+ int rc = __a32_setend_handler(regs, (instr >> 9) & 1);
arm64_skip_faulting_instruction(regs, 4);
return rc;
}

static int t16_setend_handler(struct pt_regs *regs, u32 instr)
{
- int rc = compat_setend_handler(regs, (instr >> 3) & 1);
+ int rc = __a32_setend_handler(regs, (instr >> 3) & 1);
arm64_skip_faulting_instruction(regs, 2);
return rc;
}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 1ea242547466..28b7bc582334 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1132,7 +1132,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
{},
};

-static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = {
+static const struct arm64_cpu_capabilities a32_elf_hwcaps[] = {
#ifdef CONFIG_AARCH32_EL0
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
@@ -1331,7 +1331,7 @@ static void verify_local_cpu_capabilities(void)
verify_local_elf_hwcaps(arm64_elf_hwcaps);

if (system_supports_32bit_el0())
- verify_local_elf_hwcaps(compat_elf_hwcaps);
+ verify_local_elf_hwcaps(a32_elf_hwcaps);

if (system_supports_sve())
verify_sve_features();
@@ -1394,7 +1394,7 @@ void __init setup_cpu_features(void)
setup_elf_hwcaps(arm64_elf_hwcaps);

if (system_supports_32bit_el0())
- setup_elf_hwcaps(compat_elf_hwcaps);
+ setup_elf_hwcaps(a32_elf_hwcaps);

sve_setup();

diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 53781f5687c5..541f681c3203 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -338,10 +338,10 @@ int aarch32_break_handler(struct pt_regs *regs)
bool bp = false;
void __user *pc = (void __user *)instruction_pointer(regs);

- if (!compat_user_mode(regs))
+ if (!a32_user_mode(regs))
return -EFAULT;

- if (compat_thumb_mode(regs)) {
+ if (a32_thumb_mode(regs)) {
/* get 16-bit Thumb instruction */
__le16 instr;
get_user(instr, (__le16 __user *)pc);
diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c
index 32e07818835d..6019d53d4ec6 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -64,21 +64,21 @@ user_backtrace(struct frame_tail __user *tail,
* The registers we're interested in are at the end of the variable
* length saved register structure. The fp points at the end of this
* structure so the address of this struct is:
- * (struct compat_frame_tail *)(xxx->fp)-1
+ * (struct a32_frame_tail *)(xxx->fp)-1
*
* This code has been adapted from the ARM OProfile support.
*/
-struct compat_frame_tail {
- compat_uptr_t fp; /* a (struct compat_frame_tail *) in compat mode */
+struct a32_frame_tail {
+ compat_uptr_t fp; /* a (struct a32_frame_tail *) in compat mode */
u32 sp;
u32 lr;
} __attribute__((packed));

-static struct compat_frame_tail __user *
-compat_user_backtrace(struct compat_frame_tail __user *tail,
+static struct a32_frame_tail __user *
+compat_user_backtrace(struct a32_frame_tail __user *tail,
struct perf_callchain_entry_ctx *entry)
{
- struct compat_frame_tail buftail;
+ struct a32_frame_tail buftail;
unsigned long err;

/* Also check accessibility of one struct frame_tail beyond */
@@ -98,11 +98,11 @@ compat_user_backtrace(struct compat_frame_tail __user *tail,
* Frame pointers should strictly progress back up the stack
* (towards higher addresses).
*/
- if (tail + 1 >= (struct compat_frame_tail __user *)
+ if (tail + 1 >= (struct a32_frame_tail __user *)
compat_ptr(buftail.fp))
return NULL;

- return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1;
+ return (struct a32_frame_tail __user *)compat_ptr(buftail.fp) - 1;
}
#endif /* CONFIG_AARCH32_EL0 */

@@ -116,7 +116,7 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,

perf_callchain_store(entry, regs->pc);

- if (!compat_user_mode(regs)) {
+ if (!a32_user_mode(regs)) {
/* AARCH64 mode */
struct frame_tail __user *tail;

@@ -128,9 +128,9 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
} else {
#ifdef CONFIG_AARCH32_EL0
/* AARCH32 compat mode */
- struct compat_frame_tail __user *tail;
+ struct a32_frame_tail __user *tail;

- tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;
+ tail = (struct a32_frame_tail __user *)regs->compat_fp - 1;

while ((entry->nr < entry->max_stack) &&
tail && !((unsigned long)tail & 0x3))
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
index 1d091d048d04..513e279b12d3 100644
--- a/arch/arm64/kernel/perf_regs.c
+++ b/arch/arm64/kernel/perf_regs.c
@@ -19,7 +19,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
* - PC has been set in the pt_regs struct in kernel_entry,
* - Handle SP and LR here.
*/
- if (compat_user_mode(regs)) {
+ if (a32_user_mode(regs)) {
if ((u32)idx == PERF_REG_ARM64_SP)
return regs->compat_sp;
if ((u32)idx == PERF_REG_ARM64_LR)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index c0da6efe5465..105f79d126ee 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -174,7 +174,7 @@ static void print_pstate(struct pt_regs *regs)
{
u64 pstate = regs->pstate;

- if (compat_user_mode(regs)) {
+ if (a32_user_mode(regs)) {
printk("pstate: %08llx (%c%c%c%c %c %s %s %c%c%c)\n",
pstate,
pstate & COMPAT_PSR_N_BIT ? 'N' : 'n',
@@ -208,7 +208,7 @@ void __show_regs(struct pt_regs *regs)
int i, top_reg;
u64 lr, sp;

- if (compat_user_mode(regs)) {
+ if (a32_user_mode(regs)) {
lr = regs->compat_lr;
sp = regs->compat_sp;
top_reg = 12;
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 65406218743c..fb7c1a510ed4 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -779,7 +779,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())
- compat_setup_restart_syscall(regs);
+ a32_setup_restart_syscall(regs);
else
regs->regs[8] = __NR_restart_syscall;
}
@@ -799,9 +799,9 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
*/
if (is_compat_task()) {
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
- ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
+ ret = a32_setup_rt_frame(usig, ksig, oldset, regs);
else
- ret = compat_setup_frame(usig, ksig, oldset, regs);
+ ret = a32_setup_frame(usig, ksig, oldset, regs);
} else {
ret = setup_rt_frame(usig, ksig, oldset, regs);
}
@@ -841,7 +841,7 @@ static void do_signal(struct pt_regs *regs)
*/
if (in_syscall(regs)) {
continue_addr = regs->pc;
- restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4);
+ restart_addr = continue_addr - (a32_thumb_mode(regs) ? 2 : 4);
retval = regs->regs[0];

/*
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 79feb861929b..739e13b54820 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -29,7 +29,7 @@
#include <linux/uaccess.h>
#include <asm/unistd.h>

-struct compat_sigcontext {
+struct a32_sigcontext {
/* We always set these two fields to 0 */
compat_ulong_t trap_no;
compat_ulong_t error_code;
@@ -55,17 +55,17 @@ struct compat_sigcontext {
compat_ulong_t fault_address;
};

-struct compat_ucontext {
+struct a32_ucontext {
compat_ulong_t uc_flags;
compat_uptr_t uc_link;
compat_stack_t uc_stack;
- struct compat_sigcontext uc_mcontext;
+ struct a32_sigcontext uc_mcontext;
compat_sigset_t uc_sigmask;
int __unused[32 - (sizeof (compat_sigset_t) / sizeof (int))];
compat_ulong_t uc_regspace[128] __attribute__((__aligned__(8)));
};

-struct compat_vfp_sigframe {
+struct a32_vfp_sigframe {
compat_ulong_t magic;
compat_ulong_t size;
struct compat_user_vfp {
@@ -80,25 +80,25 @@ struct compat_vfp_sigframe {
} __attribute__((__aligned__(8)));

#define VFP_MAGIC 0x56465001
-#define VFP_STORAGE_SIZE sizeof(struct compat_vfp_sigframe)
+#define VFP_STORAGE_SIZE sizeof(struct a32_vfp_sigframe)

#define FSR_WRITE_SHIFT (11)

-struct compat_aux_sigframe {
- struct compat_vfp_sigframe vfp;
+struct a32_aux_sigframe {
+ struct a32_vfp_sigframe vfp;

/* Something that isn't a valid magic number for any coprocessor. */
unsigned long end_magic;
} __attribute__((__aligned__(8)));

-struct compat_sigframe {
- struct compat_ucontext uc;
+struct a32_sigframe {
+ struct a32_ucontext uc;
compat_ulong_t retcode[2];
};

-struct compat_rt_sigframe {
+struct a32_rt_sigframe {
struct compat_siginfo info;
- struct compat_sigframe sig;
+ struct a32_sigframe sig;
};

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -129,7 +129,7 @@ static inline int get_sigset_t(sigset_t *set,
* VFP save/restore code.
*
* We have to be careful with endianness, since the fpsimd context-switch
- * code operates on 128-bit (Q) register values whereas the compat ABI
+ * code operates on 128-bit (Q) register values whereas the a32 ABI
* uses an array of 64-bit (D) registers. Consequently, we need to swap
* the two halves of each Q register when running on a big-endian CPU.
*/
@@ -146,7 +146,7 @@ union __fpsimd_vreg {
};
};

-static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
+static int a32_preserve_vfp_context(struct a32_vfp_sigframe __user *frame)
{
struct user_fpsimd_state const *fpsimd =
&current->thread.fpsimd_state.user_fpsimd;
@@ -196,7 +196,7 @@ static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
return err ? -EFAULT : 0;
}

-static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
+static int a32_restore_vfp_context(struct a32_vfp_sigframe __user *frame)
{
struct user_fpsimd_state fpsimd;
compat_ulong_t magic = VFP_MAGIC;
@@ -236,12 +236,12 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
return err ? -EFAULT : 0;
}

-static int compat_restore_sigframe(struct pt_regs *regs,
- struct compat_sigframe __user *sf)
+static int a32_restore_sigframe(struct pt_regs *regs,
+ struct a32_sigframe __user *sf)
{
int err;
sigset_t set;
- struct compat_aux_sigframe __user *aux;
+ struct a32_aux_sigframe __user *aux;

err = get_sigset_t(&set, &sf->uc.uc_sigmask);
if (err == 0) {
@@ -274,16 +274,16 @@ static int compat_restore_sigframe(struct pt_regs *regs,

err |= !valid_user_regs(&regs->user_regs, current);

- aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
+ aux = (struct a32_aux_sigframe __user *) sf->uc.uc_regspace;
if (err == 0)
- err |= compat_restore_vfp_context(&aux->vfp);
+ err |= a32_restore_vfp_context(&aux->vfp);

return err;
}

asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)
{
- struct compat_sigframe __user *frame;
+ struct a32_sigframe __user *frame;

/* Always make any pending restarted system calls return -EINTR */
current->restart_block.fn = do_no_restart_syscall;
@@ -296,12 +296,12 @@ asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)
if (regs->compat_sp & 7)
goto badframe;

- frame = (struct compat_sigframe __user *)regs->compat_sp;
+ frame = (struct a32_sigframe __user *)regs->compat_sp;

if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;

- if (compat_restore_sigframe(regs, frame))
+ if (a32_restore_sigframe(regs, frame))
goto badframe;

return regs->regs[0];
@@ -317,7 +317,7 @@ asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)

asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
{
- struct compat_rt_sigframe __user *frame;
+ struct a32_rt_sigframe __user *frame;

/* Always make any pending restarted system calls return -EINTR */
current->restart_block.fn = do_no_restart_syscall;
@@ -330,12 +330,12 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
if (regs->compat_sp & 7)
goto badframe;

- frame = (struct compat_rt_sigframe __user *)regs->compat_sp;
+ frame = (struct a32_rt_sigframe __user *)regs->compat_sp;

if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;

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

if (compat_restore_altstack(&frame->sig.uc.uc_stack))
@@ -352,7 +352,7 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
return 0;
}

-static void __user *compat_get_sigframe(struct ksignal *ksig,
+static void __user *a32_get_sigframe(struct ksignal *ksig,
struct pt_regs *regs,
int framesize)
{
@@ -373,7 +373,7 @@ static void __user *compat_get_sigframe(struct ksignal *ksig,
return frame;
}

-static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+static void a32_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
compat_ulong_t __user *rc, void __user *frame,
int usig)
{
@@ -417,10 +417,10 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
regs->pstate = spsr;
}

-static int compat_setup_sigframe(struct compat_sigframe __user *sf,
+static int a32_setup_sigframe(struct a32_sigframe __user *sf,
struct pt_regs *regs, sigset_t *set)
{
- struct compat_aux_sigframe __user *aux;
+ struct a32_aux_sigframe __user *aux;
int err = 0;

__put_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err);
@@ -442,7 +442,7 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf,
__put_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err);

__put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.trap_no, err);
- /* set the compat FSR WnR */
+ /* set the aarch32 FSR WnR */
__put_user_error(!!(current->thread.fault_code & ESR_ELx_WNR) <<
FSR_WRITE_SHIFT, &sf->uc.uc_mcontext.error_code, err);
__put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
@@ -450,25 +450,25 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf,

err |= put_sigset_t(&sf->uc.uc_sigmask, set);

- aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
+ aux = (struct a32_aux_sigframe __user *) sf->uc.uc_regspace;

if (err == 0)
- err |= compat_preserve_vfp_context(&aux->vfp);
+ err |= a32_preserve_vfp_context(&aux->vfp);
__put_user_error(0, &aux->end_magic, err);

return err;
}

/*
- * 32-bit signal handling routines called from signal.c
+ * aarch32-bit signal handling routines called from signal.c
*/
-int compat_setup_rt_frame(int usig, struct ksignal *ksig,
+int a32_setup_rt_frame(int usig, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs)
{
- struct compat_rt_sigframe __user *frame;
+ struct a32_rt_sigframe __user *frame;
int err = 0;

- frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
+ frame = a32_get_sigframe(ksig, regs, sizeof(*frame));

if (!frame)
return 1;
@@ -480,10 +480,10 @@ int compat_setup_rt_frame(int usig, struct ksignal *ksig,

err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->compat_sp);

- err |= compat_setup_sigframe(&frame->sig, regs, set);
+ err |= a32_setup_sigframe(&frame->sig, regs, set);

if (err == 0) {
- compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
+ a32_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
}
@@ -491,27 +491,27 @@ int compat_setup_rt_frame(int usig, struct ksignal *ksig,
return err;
}

-int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
+int a32_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
- struct compat_sigframe __user *frame;
+ struct a32_sigframe __user *frame;
int err = 0;

- frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
+ frame = a32_get_sigframe(ksig, regs, sizeof(*frame));

if (!frame)
return 1;

__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);

- err |= compat_setup_sigframe(frame, regs, set);
+ err |= a32_setup_sigframe(frame, regs, set);
if (err == 0)
- compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
+ a32_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);

return err;
}

-void compat_setup_restart_syscall(struct pt_regs *regs)
+void a32_setup_restart_syscall(struct pt_regs *regs)
{
regs->regs[7] = __NR_compat_restart_syscall;
}
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index a382b2a1b84e..44eabb78d116 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -30,7 +30,7 @@
#include <asm/unistd.h>

static long
-__do_compat_cache_op(unsigned long start, unsigned long end)
+__do_a32_cache_op(unsigned long start, unsigned long end)
{
long ret;

@@ -52,7 +52,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
}

static inline long
-do_compat_cache_op(unsigned long start, unsigned long end, int flags)
+do_a32_cache_op(unsigned long start, unsigned long end, int flags)
{
if (end < start || flags)
return -EINVAL;
@@ -60,12 +60,12 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags)
if (!access_ok(VERIFY_READ, (const void __user *)start, end - start))
return -EFAULT;

- return __do_compat_cache_op(start, end);
+ return __do_a32_cache_op(start, end);
}
/*
* Handle all unrecognised system calls.
*/
-long compat_arm_syscall(struct pt_regs *regs)
+long a32_arm_syscall(struct pt_regs *regs)
{
unsigned int no = regs->regs[7];

@@ -85,7 +85,7 @@ long compat_arm_syscall(struct pt_regs *regs)
* the specified region).
*/
case __ARM_NR_compat_cacheflush:
- return do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);
+ return do_a32_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);

case __ARM_NR_compat_set_tls:
current->thread.tp_value = regs->regs[0];
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 691b3bbc7606..d2ebfc2f4fbc 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -278,7 +278,7 @@ static int call_undef_hook(struct pt_regs *regs)
if (!user_mode(regs))
return 1;

- if (compat_thumb_mode(regs)) {
+ if (a32_thumb_mode(regs)) {
/* 16-bit Thumb instruction */
__le16 instr_le;
if (get_user(instr_le, (__le16 __user *)pc))
@@ -513,14 +513,14 @@ asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs)
do_undefinstr(regs);
}

-long compat_arm_syscall(struct pt_regs *regs);
+long a32_arm_syscall(struct pt_regs *regs);

asmlinkage long do_ni_syscall(struct pt_regs *regs)
{
#ifdef CONFIG_AARCH32_EL0
long ret;
if (is_compat_task()) {
- ret = compat_arm_syscall(regs);
+ ret = a32_arm_syscall(regs);
if (ret != -ENOSYS)
return ret;
}
--
2.17.0


2018-05-16 08:22:58

by Yury Norov

[permalink] [raw]
Subject: [PATCH 12/24] arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64

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 is changed here accordingly.

Signed-off-by: Andrew Pinski <[email protected]>
Signed-off-by: Philipp Tomsich <[email protected]>
Signed-off-by: Christoph Muellner <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
Reviewed-by: David Daney <[email protected]>
---
arch/arm64/include/asm/elf.h | 2 ++
arch/arm64/include/asm/is_compat.h | 30 ++++++++++++++++++++++++++--
arch/arm64/include/asm/thread_info.h | 2 ++
3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index b4b10eefc667..023b2fbc1454 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -143,6 +143,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;

#define SET_PERSONALITY(ex) \
({ \
+ clear_thread_flag(TIF_32BIT_AARCH64); \
clear_thread_flag(TIF_32BIT); \
current->personality &= ~READ_IMPLIES_EXEC; \
})
@@ -194,6 +195,7 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
*/
#define COMPAT_SET_PERSONALITY(ex) \
({ \
+ clear_thread_flag(TIF_32BIT_AARCH64); \
set_thread_flag(TIF_32BIT); \
})
#define COMPAT_ARCH_DLINFO
diff --git a/arch/arm64/include/asm/is_compat.h b/arch/arm64/include/asm/is_compat.h
index 19868588fbef..484c01def030 100644
--- a/arch/arm64/include/asm/is_compat.h
+++ b/arch/arm64/include/asm/is_compat.h
@@ -33,18 +33,44 @@ 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 */

static inline int is_compat_thread(struct thread_info *thread)
{
- return is_a32_compat_thread(thread);
+ return is_a32_compat_thread(thread) || is_ilp32_compat_thread(thread);
}


diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 6d2d58daa9d7..8ed56630e6a5 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -94,6 +94,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#define TIF_32BIT 22 /* AARCH32 process */
#define TIF_SVE 23 /* Scalable Vector Extension in use */
#define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */
+#define TIF_32BIT_AARCH64 25 /* 32 bit process on AArch64(ILP32) */

#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
@@ -108,6 +109,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#define _TIF_FSCHECK (1 << TIF_FSCHECK)
#define _TIF_32BIT (1 << TIF_32BIT)
#define _TIF_SVE (1 << TIF_SVE)
+#define _TIF_32BIT_AARCH64 (1 << TIF_32BIT_AARCH64)

#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
_TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
--
2.17.0


2018-05-16 08:23:00

by Yury Norov

[permalink] [raw]
Subject: [PATCH 13/24] arm64: introduce binfmt_elf32.c

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 <[email protected]>
---
arch/arm64/Kconfig | 1 -
arch/arm64/include/asm/elf.h | 26 +++---------------------
arch/arm64/include/asm/hwcap.h | 2 --
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 35 ++++++++++++++++++++++++++++++++
5 files changed, 39 insertions(+), 27 deletions(-)
create mode 100644 arch/arm64/kernel/binfmt_elf32.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a16916be20f5..0685754a9f7b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1232,7 +1232,6 @@ config AARCH32_EL0
bool "Kernel support for 32-bit EL0"
def_bool y
depends on ARM64_4K_PAGES || EXPERT
- select COMPAT_BINFMT_ELF if 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 023b2fbc1454..f04b27bd9bb6 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -175,36 +175,16 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,

/* PIE load location for compat arm. Must match ARM ELF_ET_DYN_BASE. */
#define COMPAT_ELF_ET_DYN_BASE 0x000400000UL
+#endif /*CONFIG_COMPAT */

+#ifdef CONFIG_AARCH32_EL0
/* AArch32 registers. */
#define COMPAT_ELF_NGREG 18
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) (system_supports_32bit_el0() && \
- ((x)->e_machine == EM_ARM) && \
- ((x)->e_flags & EF_ARM_EABI_MASK))
-
-#define compat_start_thread compat_start_thread
-/*
- * Unlike the native SET_PERSONALITY macro, the compat version maintains
- * READ_IMPLIES_EXEC across an execve() since this is the behaviour on
- * arch/arm/.
- */
-#define COMPAT_SET_PERSONALITY(ex) \
-({ \
- clear_thread_flag(TIF_32BIT_AARCH64); \
- set_thread_flag(TIF_32BIT); \
- })
-#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 /* CONFIG_AARCH32_EL0 */

#endif /* !__ASSEMBLY__ */

diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 2c7fc5d89813..99dfd9277559 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 cff1a78bdf4c..c63e0164fc12 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -27,7 +27,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
$(call if_changed,objcopy)

arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
- sys_compat.o entry32.o
+ sys_compat.o entry32.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_ARM64_MODULE_PLTS) += module-plts.o
diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
new file mode 100644
index 000000000000..440fa84f62b3
--- /dev/null
+++ b/arch/arm64/kernel/binfmt_elf32.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Support for AArch32 Linux ELF binaries.
+ */
+
+/* AArch32 EABI. */
+#define EF_ARM_EABI_MASK 0xff000000
+
+#define compat_start_thread compat_start_thread
+/*
+ * Unlike the native SET_PERSONALITY macro, the compat version inherits
+ * READ_IMPLIES_EXEC across a fork() since this is the behaviour on
+ * arch/arm/.
+ */
+#define COMPAT_SET_PERSONALITY(ex) \
+({ \
+ clear_thread_flag(TIF_32BIT_AARCH64); \
+ set_thread_flag(TIF_32BIT); \
+})
+
+#define COMPAT_ARCH_DLINFO
+#define COMPAT_ELF_HWCAP (compat_elf_hwcap)
+#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2)
+
+#define compat_arch_setup_additional_pages \
+ aarch32_setup_vectors_page
+
+/* AArch32 EABI. */
+#define compat_elf_check_arch(x) (system_supports_32bit_el0() && \
+ ((x)->e_machine == EM_ARM) && \
+ ((x)->e_flags & EF_ARM_EABI_MASK))
+
+
+#include "../../../fs/compat_binfmt_elf.c"
--
2.17.0


2018-05-16 08:23:15

by Yury Norov

[permalink] [raw]
Subject: [PATCH 06/24] thread: move thread bits accessors to separated file

Thread bits 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 in patch
edd63a27 "set_restore_sigmask() is never called without SIGPENDING (and
never should be)"

Signed-off-by: Yury Norov <[email protected]>
---
include/linux/sched.h | 1 +
include/linux/thread_bits.h | 76 +++++++++++++++++++++++++++++++++++++
include/linux/thread_info.h | 64 +------------------------------
3 files changed, 78 insertions(+), 63 deletions(-)
create mode 100644 include/linux/thread_bits.h

diff --git a/include/linux/sched.h b/include/linux/sched.h
index b161ef8a902e..c1bddf06baed 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -27,6 +27,7 @@
#include <linux/signal_types.h>
#include <linux/mm_types_task.h>
#include <linux/task_io_accounting.h>
+#include <linux/thread_bits.h>

/* task_struct member predeclarations (sorted alphabetically): */
struct audit_context;
diff --git a/include/linux/thread_bits.h b/include/linux/thread_bits.h
new file mode 100644
index 000000000000..7512f8527e9a
--- /dev/null
+++ b/include/linux/thread_bits.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/* Common low-level thread bits accessors */
+
+#ifndef _LINUX_THREAD_BITS_H
+#define _LINUX_THREAD_BITS_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * For per-arch arch_within_stack_frames() implementations, defined in
+ * asm/thread_info.h.
+ */
+enum {
+ BAD_STACK = -1,
+ NOT_STACK = 0,
+ GOOD_FRAME,
+ GOOD_STACK,
+};
+
+#include <linux/bitops.h>
+#include <asm/thread_info.h>
+
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+/*
+ * For CONFIG_THREAD_INFO_IN_TASK kernels we need <asm/current.h> for the
+ * definition of current, but for !CONFIG_THREAD_INFO_IN_TASK kernels,
+ * including <asm/current.h> can cause a circular dependency on some platforms.
+ */
+#include <asm/current.h>
+#define current_thread_info() ((struct thread_info *)current)
+#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)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _LINUX_THREAD_BITS_H */
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 34f053a150a9..793ab9b290ad 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -11,30 +11,9 @@
#include <linux/types.h>
#include <linux/bug.h>
#include <linux/restart_block.h>
-
-#ifdef CONFIG_THREAD_INFO_IN_TASK
-/*
- * For CONFIG_THREAD_INFO_IN_TASK kernels we need <asm/current.h> for the
- * definition of current, but for !CONFIG_THREAD_INFO_IN_TASK kernels,
- * including <asm/current.h> can cause a circular dependency on some platforms.
- */
-#include <asm/current.h>
-#define current_thread_info() ((struct thread_info *)current)
-#endif
+#include <linux/thread_bits.h>

#include <linux/bitops.h>
-
-/*
- * For per-arch arch_within_stack_frames() implementations, defined in
- * asm/thread_info.h.
- */
-enum {
- BAD_STACK = -1,
- NOT_STACK = 0,
- GOOD_FRAME,
- GOOD_STACK,
-};
-
#include <asm/thread_info.h>

#ifdef __KERNEL__
@@ -49,47 +28,6 @@ enum {
# define THREADINFO_GFP (GFP_KERNEL_ACCOUNT)
#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)

#ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
--
2.17.0


2018-05-16 08:23:45

by Yury Norov

[permalink] [raw]
Subject: [PATCH 08/24] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

From: Andrew Pinski <[email protected]>

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, and ARM64_ILP32 - support of ILP32 ABI (see following
patches), and COMPAT indicates that one of them or both is enabled.

Where needed, CONFIG_COMPAT is changed over to use CONFIG_AARCH32_EL0
instead.

Reviewed-by: David Daney <[email protected]>
Signed-off-by: Andrew Pinski <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
Signed-off-by: Philipp Tomsich <[email protected]>
Signed-off-by: Christoph Muellner <[email protected]>
Signed-off-by: Bamvor Jian Zhang <[email protected]>
---
arch/arm64/Kconfig | 9 +++++++--
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/seccomp.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 | 8 ++++----
arch/arm64/kernel/entry.S | 6 +++---
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/perf_callchain.c | 6 +++---
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 +-
19 files changed, 45 insertions(+), 38 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 7381eeb7ef8e..a16916be20f5 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -433,7 +433,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
@@ -906,7 +906,7 @@ config HARDEN_BRANCH_PREDICTOR

menuconfig ARMV8_DEPRECATED
bool "Emulate deprecated/obsolete ARMv8 instructions"
- depends on COMPAT
+ depends on AARCH32_EL0
depends on SYSCTL
help
Legacy software support may require certain instructions
@@ -1225,7 +1225,12 @@ 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"
+ def_bool y
depends on ARM64_4K_PAGES || EXPERT
select COMPAT_BINFMT_ELF if BINFMT_ELF
select HAVE_UID16
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 8857a0f0d0f7..0971bf730d44 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -49,7 +49,7 @@ struct fpsimd_state {
unsigned int cpu;
};

-#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 400b80b49595..2c7fc5d89813 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 fce604e3e599..79cbc385f52a 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -104,7 +104,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;
@@ -126,7 +126,7 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
*offset = *size = 0;
}

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#define task_user_tls(t) \
({ \
unsigned long *__tls; \
@@ -160,7 +160,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 6069d66e0bc2..0c85b469ad68 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -154,7 +154,7 @@ static inline void forget_syscall(struct pt_regs *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/seccomp.h b/arch/arm64/include/asm/seccomp.h
index c76fac979629..00ef0bf63230 100644
--- a/arch/arm64/include/asm/seccomp.h
+++ b/arch/arm64/include/asm/seccomp.h
@@ -13,7 +13,7 @@

#include <asm/unistd.h>

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
#define __NR_seccomp_read_32 __NR_compat_read
#define __NR_seccomp_write_32 __NR_compat_write
#define __NR_seccomp_exit_32 __NR_compat_exit
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
index 81abea0b7650..2ebde460f5a0 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
@@ -45,6 +47,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 a0baa9af5487..99d29290c98b 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_STAT64
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index b87541360f43..cff1a78bdf4c 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -26,7 +26,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
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 1303e04110cd..a416c2333e2f 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -69,7 +69,7 @@ int main(void)
DEFINE(S_X28, offsetof(struct pt_regs, regs[28]));
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 2985a067fc13..1ea242547466 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -37,7 +37,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|\
@@ -1133,7 +1133,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
};

static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = {
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
@@ -1149,7 +1149,7 @@ static void __init cap_set_elf_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;
@@ -1172,7 +1172,7 @@ static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap)
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 7f94623df8a5..23fdf30dc0a3 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -80,7 +80,7 @@ static const char *const hwcap_str[] = {
NULL
};

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
static const char *const compat_hwcap_str[] = {
"swp",
"half",
@@ -115,7 +115,7 @@ static const char *const compat_hwcap2_str[] = {
"crc32",
NULL
};
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */

static int c_show(struct seq_file *m, void *v)
{
@@ -148,7 +148,7 @@ static int c_show(struct seq_file *m, void *v)
*/
seq_puts(m, "Features\t:");
if (compat) {
-#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]);
@@ -156,7 +156,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 ec2ee720e33e..698907724eed 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -423,7 +423,7 @@ ENTRY(vectors)
kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0
kernel_ventry 0, error // Error 64-bit EL0

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0
@@ -492,7 +492,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)
@@ -656,7 +656,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 2b6b8b24e5ab..fdd706a839e4 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -544,7 +544,7 @@ set_hcr:
msr vpidr_el2, x0
msr vmpidr_el2, x1

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

diff --git a/arch/arm64/kernel/perf_callchain.c b/arch/arm64/kernel/perf_callchain.c
index bcafd7dcfe8b..32e07818835d 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -59,7 +59,7 @@ user_backtrace(struct frame_tail __user *tail,
return buftail.fp;
}

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
/*
* The registers we're interested in are at the end of the variable
* length saved register structure. The fp points at the end of this
@@ -104,7 +104,7 @@ compat_user_backtrace(struct compat_frame_tail __user *tail,

return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1;
}
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */

void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
@@ -126,7 +126,7 @@ void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
tail && !((unsigned long)tail & 0xf))
tail = user_backtrace(tail, entry);
} else {
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
/* AARCH32 compat mode */
struct compat_frame_tail __user *tail;

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 9ae31f7e2243..04e9b7973b28 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -188,7 +188,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
info.si_code = TRAP_HWBKPT;
info.si_addr = (void __user *)(bkpt->trigger);

-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
if (is_compat_task()) {
int si_errno = 0;
int i;
@@ -1039,7 +1039,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 {
@@ -1581,11 +1581,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 eb2d15147e8d..691b3bbc7606 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -517,7 +517,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 2d419006ad43..440fe2652d4a 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.
*/
@@ -108,7 +108,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 int vdso_mremap(const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 57cb2f00fc07..c3c6a8d48adc 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -764,7 +764,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
cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
--
2.17.0


2018-05-16 08:24:23

by Yury Norov

[permalink] [raw]
Subject: [PATCH 20/24] arm64: ilp32: introduce ilp32-specific sigframe and ucontext

From: Yury Norov <[email protected]>

ILP32 uses AARCH32 compat structures and syscall handlers for signals. But
ILP32 rt_sigframe and ucontext structures differ from both LP64 and AARCH32.
From software point of view ILP32 is typical 32-bit compat ABI, and from
hardware point of view, it's just like LP64.

struct rt_sigframe defined in this patch in
arch/arm64/kernel/signal_ilp32.c redefines one in
arch/arm64/kernel/signal.c. And functions located in
arch/arm64/include/signal_common.h pick up new structure to generate the
code suitable for ILP32.

Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/include/asm/signal_ilp32.h | 23 ++++++++++
arch/arm64/kernel/Makefile | 3 +-
arch/arm64/kernel/entry_ilp32.S | 12 +++++
arch/arm64/kernel/signal_ilp32.c | 65 +++++++++++++++++++++++++++
4 files changed, 102 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 000000000000..7ee97c133605
--- /dev/null
+++ b/arch/arm64/include/asm/signal_ilp32.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#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 9e127c47a25c..27ddf5369f89 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 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) += entry32_common.o 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 000000000000..562d5d0a7d82
--- /dev/null
+++ b/arch/arm64/kernel/entry_ilp32.S
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * ILP32 system call wrappers
+ */
+
+#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_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
new file mode 100644
index 000000000000..f4bcb7332010
--- /dev/null
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2018 Cavium Networks.
+ * Yury Norov <[email protected]>
+ */
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+
+#include <asm/fpsimd.h>
+#include <asm/unistd.h>
+#include <asm/ucontext.h>
+#include <asm/vdso.h>
+
+#include <asm/signal_ilp32.h>
+#include <asm/signal32_common.h>
+
+#define get_sigset(s, m) get_sigset_t(s, m)
+#define put_sigset(s, m) put_sigset_t(m, s)
+
+#define restore_altstack(stack) compat_restore_altstack(stack)
+#define __save_altstack(stack, sp) __compat_save_altstack(stack, sp)
+#define copy_siginfo_to_user(frame_info, ksig_info) \
+ copy_siginfo_to_user32(frame_info, ksig_info)
+
+#define setup_return(regs, ka, user_layout, usig) \
+{ \
+ __setup_return(regs, ka, user_layout, usig); \
+ regs->regs[30] = \
+ (unsigned long)VDSO_SYMBOL(current->mm->context.vdso, \
+ sigtramp_ilp32); \
+}
+
+struct ilp32_ucontext {
+ u32 uc_flags;
+ u32 uc_link;
+ compat_stack_t uc_stack;
+ compat_sigset_t uc_sigmask;
+ /* glibc uses a 1024-bit sigset_t */
+ __u8 __unused[1024 / 8 - sizeof(compat_sigset_t)];
+ /* last for future expansion */
+ struct sigcontext uc_mcontext;
+};
+
+struct rt_sigframe {
+ struct compat_siginfo info;
+ struct ilp32_ucontext uc;
+};
+
+#include <asm/signal_common.h>
+
+asmlinkage long ilp32_sys_rt_sigreturn(struct pt_regs *regs)
+{
+ return __sys_rt_sigreturn(regs);
+}
+
+int ilp32_setup_rt_frame(int usig, struct ksignal *ksig,
+ sigset_t *set, struct pt_regs *regs)
+{
+ return __setup_rt_frame(usig, ksig, set, regs);
+}
--
2.17.0


2018-05-16 08:24:37

by Yury Norov

[permalink] [raw]
Subject: [PATCH 17/24] arm64: ilp32: add sys_ilp32.c and a separate table (in entry.S) to use it

From: Andrew Pinski <[email protected]>

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 <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
Signed-off-by: Bamvor Jian Zhang <[email protected]>
---
arch/arm64/include/asm/unistd.h | 8 ++-
arch/arm64/include/uapi/asm/unistd.h | 12 ++++
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/entry.S | 31 +++++++++-
arch/arm64/kernel/sys_ilp32.c | 90 ++++++++++++++++++++++++++++
5 files changed, 137 insertions(+), 6 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 99d29290c98b..1bf5572cd078 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -13,12 +13,16 @@
* 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_AARCH32_EL0
+
+#ifdef CONFIG_COMPAT
#define __ARCH_WANT_COMPAT_STAT64
+#define __ARCH_WANT_SYS_LLSEEK
+#endif
+
+#ifdef CONFIG_AARCH32_EL0
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
#define __ARCH_WANT_SYS_NICE
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h
index 439b1c55c827..80f1cb4ae2e1 100644
--- a/arch/arm64/include/uapi/asm/unistd.h
+++ b/arch/arm64/include/uapi/asm/unistd.h
@@ -15,7 +15,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

+/*
+ * Use AARCH32 interface for sys_sync_file_range() as it passes 64-bit arguments.
+ */
+#if defined(__ILP32__) || defined(__SYSCALL_COMPAT)
+#define __ARCH_WANT_SYNC_FILE_RANGE2
+#endif
+
+/*
+ * AARCH64/ILP32 is introduced after next syscalls were deprecated.
+ */
+#if !(defined(__ILP32__) || defined(__SYSCALL_COMPAT))
#define __ARCH_WANT_RENAMEAT
#define __ARCH_WANT_SET_GET_RLIMIT
+#endif

#include <asm-generic/unistd.h>
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2dde9ae508ec..a6db407d4089 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 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_COMPAT) += entry32_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.S b/arch/arm64/kernel/entry.S
index 698907724eed..d03542418f9b 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -401,6 +401,23 @@ tsk .req x28 // current thread_info

.text

+#ifdef CONFIG_ARM64_ILP32
+/*
+ * AARCH64/ILP32. Zero top halves of x0-x7
+ * registers as userspace may put garbage there.
+ */
+ .macro delouse_input_regs
+ mov w0, w0
+ mov w1, w1
+ mov w2, w2
+ mov w3, w3
+ mov w4, w4
+ mov w5, w5
+ mov w6, w6
+ mov w7, w7
+ .endm
+#endif
+
/*
* Exception vectors.
*/
@@ -695,6 +712,7 @@ el0_svc_compat:
*/
ldr x16, [tsk, #TSK_TI_FLAGS] // load thread flags
adrp stbl, compat_sys_call_table // load compat syscall table pointer
+ ldr x19, [tsk, #TSK_TI_FLAGS]
mov wscno, w7 // syscall number in w7 (r7)
mov wsc_nr, #__NR_compat_syscalls
b el0_svc_naked
@@ -916,14 +934,15 @@ ENDPROC(ret_to_user)
el0_svc:
ldr x16, [tsk, #TSK_TI_FLAGS] // load thread flags
adrp stbl, sys_call_table // load syscall table pointer
+ ldr x19, [tsk, #TSK_TI_FLAGS]
mov wscno, w8 // syscall number in w8
mov wsc_nr, #__NR_syscalls

#ifdef CONFIG_ARM64_SVE
alternative_if_not ARM64_SVE
- b el0_svc_naked
+ b el0_svc_select_table
alternative_else_nop_endif
- tbz x16, #TIF_SVE, el0_svc_naked // Skip unless TIF_SVE set:
+ tbz x16, #TIF_SVE, el0_svc_select_table // Skip unless TIF_SVE set:
bic x16, x16, #_TIF_SVE // discard SVE state
str x16, [tsk, #TSK_TI_FLAGS]

@@ -939,12 +958,18 @@ alternative_else_nop_endif
msr cpacr_el1, x9 // synchronised by eret to el0
#endif

+el0_svc_select_table:
+#ifdef CONFIG_ARM64_ILP32
+ tbz x19, #TIF_32BIT_AARCH64, el0_svc_naked // We are using LP64 syscall table
+ adrp stbl, sys_call_ilp32_table // load ilp32 syscall table pointer
+ delouse_input_regs
+#endif
el0_svc_naked: // compat entry point
stp x0, xscno, [sp, #S_ORIG_X0] // save the original x0 and syscall number
enable_daif
ct_user_exit 1

- tst x16, #_TIF_SYSCALL_WORK // check for syscall hooks
+ tst x19, #_TIF_SYSCALL_WORK // check for syscall hooks
b.ne __sys_trace
cmp wscno, wsc_nr // check upper syscall limit
b.hs ni_sys
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
new file mode 100644
index 000000000000..9803d7806328
--- /dev/null
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * AArch64- ILP32 specific system calls implementation
+ *
+ * Copyright (C) 2018 Cavium Inc.
+ * Author: Andrew Pinski <[email protected]>
+ */
+
+#define __SYSCALL_COMPAT
+
+#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>
+
+/*
+ * AARCH32 requires 4-page alignment for shared memory,
+ * but AARCH64 - only 1 page. This is the only difference
+ * between compat and native sys_shmat(). So ILP32 just pick
+ * AARCH64 version.
+ */
+#define compat_sys_shmat sys_shmat
+
+/*
+ * ILP32 needs special handling for some ptrace requests.
+ */
+#define sys_ptrace compat_sys_ptrace
+
+/*
+ * Using AARCH32 interface for syscalls that take 64-bit
+ * parameters in registers.
+ */
+#define compat_sys_fadvise64_64 compat_sys_fadvise64_64_wrapper
+#define compat_sys_fallocate compat_sys_fallocate_wrapper
+#define compat_sys_ftruncate64 compat_sys_ftruncate64_wrapper
+#define compat_sys_pread64 compat_sys_pread64_wrapper
+#define compat_sys_pwrite64 compat_sys_pwrite64_wrapper
+#define compat_sys_readahead compat_sys_readahead_wrapper
+#define compat_sys_sync_file_range2 compat_sys_sync_file_range2_wrapper
+#define compat_sys_truncate64 compat_sys_truncate64_wrapper
+#define sys_mmap2 compat_sys_mmap2_wrapper
+
+/*
+ * Using AARCH32 interface for syscalls that take the size of
+ * struct statfs as an argument, as it's calculated differently
+ * in kernel and user spaces.
+ */
+#define compat_sys_fstatfs64 compat_sys_fstatfs64_wrapper
+#define compat_sys_statfs64 compat_sys_statfs64_wrapper
+
+/*
+ * Using custom wrapper for rt_sigreturn() to handle custom
+ * struct rt_sigframe.
+ */
+#define compat_sys_rt_sigreturn ilp32_sys_rt_sigreturn_wrapper
+
+asmlinkage long compat_sys_fstatfs64_wrapper(void);
+asmlinkage long compat_sys_statfs64_wrapper(void);
+asmlinkage long compat_sys_fadvise64_64_wrapper(void);
+asmlinkage long compat_sys_fallocate_wrapper(void);
+asmlinkage long compat_sys_ftruncate64_wrapper(void);
+asmlinkage long compat_sys_mmap2_wrapper(void);
+asmlinkage long compat_sys_pread64_wrapper(void);
+asmlinkage long compat_sys_pwrite64_wrapper(void);
+asmlinkage long compat_sys_readahead_wrapper(void);
+asmlinkage long compat_sys_sync_file_range2_wrapper(void);
+asmlinkage long compat_sys_truncate64_wrapper(void);
+asmlinkage long ilp32_sys_rt_sigreturn_wrapper(void);
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#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.17.0


2018-05-16 08:24:49

by Yury Norov

[permalink] [raw]
Subject: [PATCH 18/24] arm64: signal: share lp64 signal structures and routines to ilp32

Following patches of the series introduce ILP32-specific structures and
handlers for signal subsystem. In this patch, functions and structures
that common for LP64 and ILP32 are moved to
arch/arm64/include/asm/signal_common.h to let ILP32 code reuse them. Some
functions work with struct rt_sigframe which differs for ILP32. Therefore,
to let ILP32 generate correct code, body of that functions are moved to
arch/arm64/include/asm/signal_common.h. Others just declared in new header.

Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/include/asm/signal_common.h | 306 ++++++++++++++++++++++
arch/arm64/kernel/signal.c | 336 ++++---------------------
2 files changed, 359 insertions(+), 283 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 000000000000..84abe973e8b3
--- /dev/null
+++ b/arch/arm64/include/asm/signal_common.h
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2018 Cavium Networks.
+ */
+
+#ifndef __ASM_SIGNAL_COMMON_H
+#define __ASM_SIGNAL_COMMON_H
+
+#include <linux/uaccess.h>
+#include <asm/fpsimd.h>
+
+#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
+#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
+#define SIGCONTEXT_RESERVED_SIZE sizeof(((struct sigcontext *)0)->__reserved)
+#define RT_SIGFRAME_RESERVED_OFFSET \
+ offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved)
+
+/*
+ * Sanity limit on the approximate maximum size of signal frame we'll
+ * try to generate. Stack alignment padding and the frame record are
+ * not taken into account. This limit is not a guarantee and is
+ * NOT ABI.
+ */
+#define SIGFRAME_MAXSZ SZ_64K
+
+struct rt_sigframe_user_layout {
+ void __user *sigframe;
+ struct frame_record __user *next_frame;
+
+ unsigned long size; /* size of allocated sigframe data */
+ unsigned long limit; /* largest allowed size */
+
+ unsigned long fpsimd_offset;
+ unsigned long esr_offset;
+ unsigned long sve_offset;
+ unsigned long extra_offset;
+ unsigned long end_offset;
+};
+
+struct user_ctxs {
+ struct fpsimd_context __user *fpsimd;
+ struct sve_context __user *sve;
+};
+
+struct frame_record {
+ u64 fp;
+ u64 lr;
+};
+
+void __user *apply_user_offset(struct rt_sigframe_user_layout const *user,
+ unsigned long offset);
+
+int setup_sigframe_layout(struct rt_sigframe_user_layout *user);
+int setup_extra_context(char __user *sfp, unsigned long sf_size,
+ char __user *exprap);
+int __parse_user_sigcontext(struct user_ctxs *user,
+ struct sigcontext __user const *sc,
+ void __user const *sigframe_base);
+#define parse_user_sigcontext(user, sf) \
+ __parse_user_sigcontext(user, &(sf)->uc.uc_mcontext, sf)
+
+int preserve_fpsimd_context(struct fpsimd_context __user *ctx);
+int restore_fpsimd_context(struct fpsimd_context __user *ctx);
+
+#ifdef CONFIG_ARM64_SVE
+int preserve_sve_context(struct sve_context __user *ctx);
+int restore_sve_fpsimd_context(struct user_ctxs *user);
+#else /* ! CONFIG_ARM64_SVE */
+
+/* Turn any non-optimised out attempts to use these into a link error: */
+extern int preserve_sve_context(void __user *ctx);
+extern int restore_sve_fpsimd_context(struct user_ctxs *user);
+
+#endif /* ! CONFIG_ARM64_SVE */
+
+int sigframe_alloc(struct rt_sigframe_user_layout *user,
+ unsigned long *offset, size_t size);
+int sigframe_alloc_end(struct rt_sigframe_user_layout *user);
+
+void __setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+ struct rt_sigframe_user_layout *user, int usig);
+
+static void init_user_layout(struct rt_sigframe_user_layout *user)
+{
+ memset(user, 0, sizeof(*user));
+ user->size = RT_SIGFRAME_RESERVED_OFFSET;
+
+ user->limit = user->size + SIGCONTEXT_RESERVED_SIZE;
+
+ user->limit -= TERMINATOR_SIZE;
+ user->limit -= EXTRA_CONTEXT_SIZE;
+ /* Reserve space for extension and terminator ^ */
+}
+
+static size_t sigframe_size(struct rt_sigframe_user_layout const *user)
+{
+ return round_up(max(user->size, sizeof(struct rt_sigframe)), 16);
+}
+
+static int get_sigframe(struct rt_sigframe_user_layout *user,
+ struct ksignal *ksig, struct pt_regs *regs)
+{
+ unsigned long sp, sp_top;
+ int err;
+
+ init_user_layout(user);
+ err = setup_sigframe_layout(user);
+ if (err)
+ return err;
+
+ sp = sp_top = sigsp(regs->sp, ksig);
+
+ sp = round_down(sp - sizeof(struct frame_record), 16);
+ user->next_frame = (struct frame_record __user *)sp;
+
+ sp = round_down(sp, 16) - sigframe_size(user);
+ user->sigframe = (void __user *)sp;
+
+ /*
+ * Check that we can actually write to the signal frame.
+ */
+ if (!access_ok(VERIFY_WRITE, user->sigframe, sp_top - sp))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int restore_sigframe(struct pt_regs *regs,
+ struct rt_sigframe __user *sf)
+{
+ sigset_t set;
+ int i, err;
+ struct user_ctxs user;
+
+ err = get_sigset(&set, &sf->uc.uc_sigmask);
+ if (err == 0)
+ set_current_blocked(&set);
+
+ for (i = 0; i < 31; i++)
+ __get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
+ err);
+ __get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
+ __get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
+ __get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
+
+ /*
+ * Avoid sys_rt_sigreturn() restarting.
+ */
+ forget_syscall(regs);
+
+ err |= !valid_user_regs(&regs->user_regs, current);
+ if (err == 0)
+ err = parse_user_sigcontext(&user, sf);
+
+ if (err == 0) {
+ if (!user.fpsimd)
+ return -EINVAL;
+
+ if (user.sve) {
+ if (!system_supports_sve())
+ return -EINVAL;
+
+ err = restore_sve_fpsimd_context(&user);
+ } else {
+ err = restore_fpsimd_context(user.fpsimd);
+ }
+ }
+
+ return err;
+}
+
+static int setup_sigframe(struct rt_sigframe_user_layout *user,
+ struct pt_regs *regs, sigset_t *set)
+{
+ int i, err = 0;
+ struct rt_sigframe __user *sf = user->sigframe;
+
+ /* set up the stack frame for unwinding */
+ __put_user_error(regs->regs[29], &user->next_frame->fp, err);
+ __put_user_error(regs->regs[30], &user->next_frame->lr, err);
+
+ for (i = 0; i < 31; i++)
+ __put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
+ err);
+ __put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
+ __put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
+ __put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
+
+ __put_user_error(current->thread.fault_address,
+ &sf->uc.uc_mcontext.fault_address, err);
+
+ err |= put_sigset(set, &sf->uc.uc_sigmask);
+
+ if (err == 0) {
+ struct fpsimd_context __user *fpsimd_ctx =
+ apply_user_offset(user, user->fpsimd_offset);
+ err |= preserve_fpsimd_context(fpsimd_ctx);
+ }
+
+ /* fault information, if valid */
+ if (err == 0 && user->esr_offset) {
+ struct esr_context __user *esr_ctx =
+ apply_user_offset(user, user->esr_offset);
+
+ __put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err);
+ __put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err);
+ __put_user_error(current->thread.fault_code,
+ &esr_ctx->esr, err);
+ }
+
+ /* Scalable Vector Extension state, if present */
+ if (system_supports_sve() && err == 0 && user->sve_offset) {
+ struct sve_context __user *sve_ctx =
+ apply_user_offset(user, user->sve_offset);
+ err |= preserve_sve_context(sve_ctx);
+ }
+
+ if (err == 0 && user->extra_offset)
+ setup_extra_context((char __user *)user->sigframe, user->size,
+ (char __user *)apply_user_offset(user,
+ user->extra_offset));
+
+ /* set the "end" magic */
+ if (err == 0) {
+ struct _aarch64_ctx __user *end =
+ apply_user_offset(user, user->end_offset);
+
+ __put_user_error(0, &end->magic, err);
+ __put_user_error(0, &end->size, err);
+ }
+
+ return err;
+}
+
+static long __sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct 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 (regs->sp & 15)
+ goto badframe;
+
+ frame = (struct rt_sigframe __user *)regs->sp;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (restore_sigframe(regs, frame))
+ goto badframe;
+
+ if (restore_altstack(&frame->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->sp);
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+static int __setup_rt_frame(int usig, struct ksignal *ksig,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe_user_layout user;
+ struct rt_sigframe __user *frame;
+ int err = 0;
+
+ fpsimd_signal_preserve_current_state();
+
+ if (get_sigframe(&user, ksig, regs))
+ return 1;
+
+ frame = user.sigframe;
+
+ __put_user_error(0, &frame->uc.uc_flags, err);
+ __put_user_error((typeof(frame->uc.uc_link)) 0,
+ &frame->uc.uc_link, err);
+
+ err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
+ err |= setup_sigframe(&user, regs, set);
+ if (err == 0) {
+ setup_return(regs, &ksig->ka, &user, 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;
+ }
+ }
+
+ return err;
+}
+
+#endif /* __ASM_SIGNAL_COMMON_H */
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 0a829f6f1832..c1a2523bac02 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -41,6 +41,10 @@
#include <asm/ptrace.h>
#include <asm/signal32.h>
#include <asm/vdso.h>
+#include <asm/signal_ilp32.h>
+
+#define get_sigset(s, m) __copy_from_user(s, m, sizeof(*s))
+#define put_sigset(s, m) __copy_to_user(m, s, sizeof(*s))

/*
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
@@ -49,57 +53,12 @@ struct rt_sigframe {
struct siginfo info;
struct ucontext uc;
};
+struct rt_sigframe_user_layout;

-struct frame_record {
- u64 fp;
- u64 lr;
-};
-
-struct rt_sigframe_user_layout {
- struct rt_sigframe __user *sigframe;
- struct frame_record __user *next_frame;
-
- unsigned long size; /* size of allocated sigframe data */
- unsigned long limit; /* largest allowed size */
-
- unsigned long fpsimd_offset;
- unsigned long esr_offset;
- unsigned long sve_offset;
- unsigned long extra_offset;
- unsigned long end_offset;
-};
-
-#define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16)
-#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
-#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
-
-static void init_user_layout(struct rt_sigframe_user_layout *user)
-{
- const size_t reserved_size =
- sizeof(user->sigframe->uc.uc_mcontext.__reserved);
-
- memset(user, 0, sizeof(*user));
- user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved);
-
- user->limit = user->size + reserved_size;
-
- user->limit -= TERMINATOR_SIZE;
- user->limit -= EXTRA_CONTEXT_SIZE;
- /* Reserve space for extension and terminator ^ */
-}
-
-static size_t sigframe_size(struct rt_sigframe_user_layout const *user)
-{
- return round_up(max(user->size, sizeof(struct rt_sigframe)), 16);
-}
+static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+ struct rt_sigframe_user_layout *user, int usig);

-/*
- * Sanity limit on the approximate maximum size of signal frame we'll
- * try to generate. Stack alignment padding and the frame record are
- * not taken into account. This limit is not a guarantee and is
- * NOT ABI.
- */
-#define SIGFRAME_MAXSZ SZ_64K
+#include <asm/signal_common.h>

static int __sigframe_alloc(struct rt_sigframe_user_layout *user,
unsigned long *offset, size_t size, bool extend)
@@ -144,14 +103,14 @@ static int __sigframe_alloc(struct rt_sigframe_user_layout *user,
* signal frame. The offset from the signal frame base address to the
* allocated block is assigned to *offset.
*/
-static int sigframe_alloc(struct rt_sigframe_user_layout *user,
+int sigframe_alloc(struct rt_sigframe_user_layout *user,
unsigned long *offset, size_t size)
{
return __sigframe_alloc(user, offset, size, true);
}

/* Allocate the null terminator record and prevent further allocations */
-static int sigframe_alloc_end(struct rt_sigframe_user_layout *user)
+int sigframe_alloc_end(struct rt_sigframe_user_layout *user)
{
int ret;

@@ -168,7 +127,7 @@ static int sigframe_alloc_end(struct rt_sigframe_user_layout *user)
return 0;
}

-static void __user *apply_user_offset(
+void __user *apply_user_offset(
struct rt_sigframe_user_layout const *user, unsigned long offset)
{
char __user *base = (char __user *)user->sigframe;
@@ -176,7 +135,7 @@ static void __user *apply_user_offset(
return base + offset;
}

-static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
+int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
{
struct user_fpsimd_state const *fpsimd =
&current->thread.fpsimd_state.user_fpsimd;
@@ -194,7 +153,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 user_fpsimd_state fpsimd;
__u32 magic, size;
@@ -223,15 +182,9 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
return err ? -EFAULT : 0;
}

-
-struct user_ctxs {
- struct fpsimd_context __user *fpsimd;
- struct sve_context __user *sve;
-};
-
#ifdef CONFIG_ARM64_SVE

-static int preserve_sve_context(struct sve_context __user *ctx)
+int preserve_sve_context(struct sve_context __user *ctx)
{
int err = 0;
u16 reserved[ARRAY_SIZE(ctx->__reserved)];
@@ -263,7 +216,7 @@ static int preserve_sve_context(struct sve_context __user *ctx)
return err ? -EFAULT : 0;
}

-static int restore_sve_fpsimd_context(struct user_ctxs *user)
+int restore_sve_fpsimd_context(struct user_ctxs *user)
{
int err;
unsigned int vq;
@@ -326,15 +279,9 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
return err ? -EFAULT : 0;
}

-#else /* ! CONFIG_ARM64_SVE */
-
-/* Turn any non-optimised out attempts to use these into a link error: */
-extern int preserve_sve_context(void __user *ctx);
-extern int restore_sve_fpsimd_context(struct user_ctxs *user);
-
#endif /* ! CONFIG_ARM64_SVE */

-static int __parse_user_sigcontext(struct user_ctxs *user,
+int __parse_user_sigcontext(struct user_ctxs *user,
struct sigcontext __user const *sc,
void __user const *sigframe_base)
{
@@ -492,91 +439,13 @@ static int __parse_user_sigcontext(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)
-{
- sigset_t set;
- int i, err;
- struct user_ctxs user;
-
- err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
- if (err == 0)
- set_current_blocked(&set);
-
- for (i = 0; i < 31; i++)
- __get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
- err);
- __get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
- __get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
- __get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
-
- /*
- * Avoid sys_rt_sigreturn() restarting.
- */
- forget_syscall(regs);
-
- err |= !valid_user_regs(&regs->user_regs, current);
- if (err == 0)
- err = parse_user_sigcontext(&user, sf);
-
- if (err == 0) {
- if (!user.fpsimd)
- return -EINVAL;
-
- if (user.sve) {
- if (!system_supports_sve())
- return -EINVAL;
-
- err = restore_sve_fpsimd_context(&user);
- } else {
- err = restore_fpsimd_context(user.fpsimd);
- }
- }
-
- return err;
-}
-
asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
{
- struct 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 (regs->sp & 15)
- goto badframe;
-
- frame = (struct rt_sigframe __user *)regs->sp;
-
- if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
- goto badframe;
-
- if (restore_sigframe(regs, frame))
- goto badframe;
-
- if (restore_altstack(&frame->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->sp);
- force_sig(SIGSEGV, current);
- return 0;
+ return __sys_rt_sigreturn(regs);
}

/* Determine the layout of optional records in the signal frame */
-static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
+int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
{
int err;

@@ -608,123 +477,50 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
return sigframe_alloc_end(user);
}

-
-static int setup_sigframe(struct rt_sigframe_user_layout *user,
- struct pt_regs *regs, sigset_t *set)
+int setup_extra_context(char __user *sfp, unsigned long sf_size,
+ char __user *extrap)
{
- int i, err = 0;
- struct rt_sigframe __user *sf = user->sigframe;
-
- /* set up the stack frame for unwinding */
- __put_user_error(regs->regs[29], &user->next_frame->fp, err);
- __put_user_error(regs->regs[30], &user->next_frame->lr, err);
-
- for (i = 0; i < 31; i++)
- __put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
- err);
- __put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
- __put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
- __put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
-
- __put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
-
- err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
-
- if (err == 0) {
- struct fpsimd_context __user *fpsimd_ctx =
- apply_user_offset(user, user->fpsimd_offset);
- err |= preserve_fpsimd_context(fpsimd_ctx);
- }
-
- /* fault information, if valid */
- if (err == 0 && user->esr_offset) {
- struct esr_context __user *esr_ctx =
- apply_user_offset(user, user->esr_offset);
-
- __put_user_error(ESR_MAGIC, &esr_ctx->head.magic, err);
- __put_user_error(sizeof(*esr_ctx), &esr_ctx->head.size, err);
- __put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
- }
-
- /* Scalable Vector Extension state, if present */
- if (system_supports_sve() && err == 0 && user->sve_offset) {
- struct sve_context __user *sve_ctx =
- apply_user_offset(user, user->sve_offset);
- err |= preserve_sve_context(sve_ctx);
- }
-
- if (err == 0 && user->extra_offset) {
- char __user *sfp = (char __user *)user->sigframe;
- char __user *userp =
- apply_user_offset(user, user->extra_offset);
-
- struct extra_context __user *extra;
- struct _aarch64_ctx __user *end;
- u64 extra_datap;
- u32 extra_size;
-
- extra = (struct extra_context __user *)userp;
- userp += EXTRA_CONTEXT_SIZE;
-
- end = (struct _aarch64_ctx __user *)userp;
- userp += TERMINATOR_SIZE;
+ int err = 0;
+ struct extra_context __user *extra;
+ struct _aarch64_ctx __user *end;
+ u64 extra_datap;
+ u32 extra_size;

- /*
- * extra_datap is just written to the signal frame.
- * The value gets cast back to a void __user *
- * during sigreturn.
- */
- extra_datap = (__force u64)userp;
- extra_size = sfp + round_up(user->size, 16) - userp;
+ extra = (struct extra_context __user *)extrap;
+ extrap += EXTRA_CONTEXT_SIZE;

- __put_user_error(EXTRA_MAGIC, &extra->head.magic, err);
- __put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err);
- __put_user_error(extra_datap, &extra->datap, err);
- __put_user_error(extra_size, &extra->size, err);
+ end = (struct _aarch64_ctx __user *)extrap;
+ extrap += TERMINATOR_SIZE;

- /* Add the terminator */
- __put_user_error(0, &end->magic, err);
- __put_user_error(0, &end->size, err);
- }
+ /*
+ * extra_datap is just written to the signal frame.
+ * The value gets cast back to a void __user *
+ * during sigreturn.
+ */
+ extra_datap = (__force u64)extrap;
+ extra_size = sfp + round_up(sf_size, 16) - extrap;

- /* set the "end" magic */
- if (err == 0) {
- struct _aarch64_ctx __user *end =
- apply_user_offset(user, user->end_offset);
+ __put_user_error(EXTRA_MAGIC, &extra->head.magic, err);
+ __put_user_error(EXTRA_CONTEXT_SIZE, &extra->head.size, err);
+ __put_user_error(extra_datap, &extra->datap, err);
+ __put_user_error(extra_size, &extra->size, err);

- __put_user_error(0, &end->magic, err);
- __put_user_error(0, &end->size, err);
- }
+ /* Add the terminator */
+ __put_user_error(0, &end->magic, err);
+ __put_user_error(0, &end->size, err);

return err;
}

-static int get_sigframe(struct rt_sigframe_user_layout *user,
- struct ksignal *ksig, struct pt_regs *regs)
+void __setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+ struct rt_sigframe_user_layout *user, int usig)
{
- unsigned long sp, sp_top;
- int err;
-
- init_user_layout(user);
- err = setup_sigframe_layout(user);
- if (err)
- return err;
-
- sp = sp_top = sigsp(regs->sp, ksig);
-
- sp = round_down(sp - sizeof(struct frame_record), 16);
- user->next_frame = (struct frame_record __user *)sp;

- sp = round_down(sp, 16) - sigframe_size(user);
- user->sigframe = (struct rt_sigframe __user *)sp;
-
- /*
- * Check that we can actually write to the signal frame.
- */
- if (!access_ok(VERIFY_WRITE, user->sigframe, sp_top - sp))
- return -EFAULT;
+ regs->regs[0] = usig;
+ regs->sp = (unsigned long)user->sigframe;
+ regs->regs[29] = (unsigned long)&user->next_frame->fp;
+ regs->pc = (unsigned long)ka->sa.sa_handler;

- return 0;
}

static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
@@ -732,10 +528,7 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
{
__sigrestore_t sigtramp;

- regs->regs[0] = usig;
- regs->sp = (unsigned long)user->sigframe;
- regs->regs[29] = (unsigned long)&user->next_frame->fp;
- regs->pc = (unsigned long)ka->sa.sa_handler;
+ __setup_return(regs, ka, user, usig);

if (ka->sa.sa_flags & SA_RESTORER)
sigtramp = ka->sa.sa_restorer;
@@ -748,32 +541,7 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
- struct rt_sigframe_user_layout user;
- struct rt_sigframe __user *frame;
- int err = 0;
-
- fpsimd_signal_preserve_current_state();
-
- if (get_sigframe(&user, ksig, regs))
- return 1;
-
- frame = user.sigframe;
-
- __put_user_error(0, &frame->uc.uc_flags, err);
- __put_user_error(NULL, &frame->uc.uc_link, err);
-
- err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
- err |= setup_sigframe(&user, regs, set);
- if (err == 0) {
- setup_return(regs, &ksig->ka, &user, 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;
- }
- }
-
- return err;
+ return __setup_rt_frame(usig, ksig, set, regs);
}

static void setup_restart_syscall(struct pt_regs *regs)
@@ -802,6 +570,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
ret = a32_setup_rt_frame(usig, ksig, oldset, regs);
else
ret = a32_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);
}
--
2.17.0


2018-05-16 08:25:13

by Yury Norov

[permalink] [raw]
Subject: [PATCH 23/24] arm64:ilp32: add ARM64_ILP32 to Kconfig

From: Andrew Pinski <[email protected]>

This patch adds the config option for ILP32.

Signed-off-by: Andrew Pinski <[email protected]>
Signed-off-by: Philipp Tomsich <[email protected]>
Signed-off-by: Christoph Muellner <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
Reviewed-by: David Daney <[email protected]>
---
arch/arm64/Kconfig | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 0685754a9f7b..a3134b8e3123 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1226,7 +1226,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"
@@ -1247,6 +1247,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.17.0


2018-05-16 08:25:25

by Yury Norov

[permalink] [raw]
Subject: [PATCH 21/24] arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32

ILP32 has context-related structures different from both aarch32 and
aarch64/lp64. In this patch compat_arch_ptrace() renamed to
compat_a32_ptrace(), and compat_arch_ptrace() only makes choice between
compat_a32_ptrace() and new compat_ilp32_ptrace() handler.

compat_ilp32_ptrace() calls generic compat_ptrace_request() for all
requests except PTRACE_GETSIGMASK and PTRACE_SETSIGMASK, which need
special handling.

Signed-off-by: Yury Norov <[email protected]>
Signed-off-by: Bamvor Jian Zhang <[email protected]>
---
arch/arm64/kernel/ptrace.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 4d0a541d049b..da7f47c7e586 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -1038,9 +1038,11 @@ static const struct user_regset_view user_aarch64_view = {
.regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
};

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

+#ifdef CONFIG_AARCH32_EL0
enum compat_regset {
REGSET_COMPAT_GPR,
REGSET_COMPAT_VFP,
@@ -1503,7 +1505,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;
@@ -1580,8 +1582,23 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,

return ret;
}
+
+#else
+#define compat_a32_ptrace(child, request, caddr, cdata) (0)
#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)
+{
+ if (is_a32_compat_task())
+ return compat_a32_ptrace(child, request, caddr, cdata);
+
+ /* ILP32 */
+ return compat_ptrace_request(child, request, caddr, cdata);
+}
+#endif
+
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
#ifdef CONFIG_AARCH32_EL0
--
2.17.0


2018-05-16 08:25:55

by Yury Norov

[permalink] [raw]
Subject: [PATCH 24/24] arm64: ilp32: Make the Kconfig option default y

From: Catalin Marinas <[email protected]>

The intention of the ILP32 branches is to enable ILP32 by default. This
default is to be revisited for upstream merging.

Signed-off-by: Catalin Marinas <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/Kconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a3134b8e3123..3551990a2726 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1249,6 +1249,7 @@ config AARCH32_EL0

config ARM64_ILP32
bool "Kernel support for ILP32"
+ default y
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
--
2.17.0


2018-05-16 08:26:50

by Yury Norov

[permalink] [raw]
Subject: [PATCH 22/24] arm64:ilp32: add vdso-ilp32 and use for signal return

From: Philipp Tomsich <[email protected]>

ILP32 VDSO exports following 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 data page before code pages in sync with
commit 601255ae3c98 ("arm64: vdso: move data page before code pages")

Signed-off-by: Philipp Tomsich <[email protected]>
Signed-off-by: Christoph Muellner <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
Signed-off-by: Bamvor Jian Zhang <[email protected]>
---
arch/arm64/Makefile | 3 +
arch/arm64/include/asm/vdso.h | 6 ++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/asm-offsets.c | 7 ++
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 | 61 ++++++++++++--
arch/arm64/kernel/vdso/gettimeofday.S | 20 ++++-
arch/arm64/kernel/vdso/vdso.S | 6 +-
11 files changed, 280 insertions(+), 14 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/Makefile b/arch/arm64/Makefile
index b481b4a7c011..55fb91420ebc 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -160,6 +160,9 @@ archclean:
prepare: vdso_prepare
vdso_prepare: prepare0
$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso include/generated/vdso-offsets.h
+ifeq ($(CONFIG_ARM64_ILP32), y)
+ $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso-ilp32 include/generated/vdso-ilp32-offsets.h
+endif

define archhelp
echo '* Image.gz - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 839ce0031bd5..33a4e10014aa 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 ({ BUILD_BUG(); 0; })
+#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 27ddf5369f89..6510dad702d0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -62,6 +62,7 @@ arm64-obj-$(CONFIG_HARDEN_BRANCH_PREDICTOR) += bpi.o
endif

obj-y += $(arm64-obj-y) vdso/ probes/
+obj-$(CONFIG_ARM64_ILP32) += vdso-ilp32/
obj-m += $(arm64-obj-m)
head-y := head.o
extra-y += $(head-y) vmlinux.lds
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index a416c2333e2f..54c9768dd964 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -124,6 +124,13 @@ int main(void)
DEFINE(TSPEC_TV_SEC, offsetof(struct timespec, tv_sec));
DEFINE(TSPEC_TV_NSEC, offsetof(struct timespec, tv_nsec));
BLANK();
+#ifdef CONFIG_COMPAT
+ DEFINE(COMPAT_TVAL_TV_SEC, offsetof(struct compat_timeval, tv_sec));
+ DEFINE(COMPAT_TVAL_TV_USEC, offsetof(struct compat_timeval, tv_usec));
+ DEFINE(COMPAT_TSPEC_TV_SEC, offsetof(struct compat_timespec, tv_sec));
+ DEFINE(COMPAT_TSPEC_TV_NSEC, offsetof(struct compat_timespec, tv_nsec));
+ BLANK();
+#endif
DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
BLANK();
diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore
new file mode 100644
index 000000000000..61806c3fd68b
--- /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 000000000000..e372740e43b5
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/Makefile
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+#
+# Building a vDSO image for AArch64.
+#
+# Author: Will Deacon <[email protected]>
+# 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)
+
+# Disable gcov profiling for VDSO code
+GCOV_PROFILE := n
+
+# Workaround for bare-metal (ELF) toolchains that neglect to pass -shared
+# down to collect2, resulting in silent corruption of the vDSO image.
+ccflags-y += -Wl,-shared
+
+obj-y += vdso-ilp32.o
+extra-y += vdso-ilp32.lds
+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 > $@
+endef
+
+include/generated/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)
+
+# This one should be fine because ILP32 uses the same generic
+# __NR_rt_sigreturn syscall number.
+$(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)/[email protected] $(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 000000000000..dee65ab79662
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * Copyright (C) 2012 ARM Limited
+ * Author: Will Deacon <[email protected]>
+ */
+
+#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 000000000000..9f14666feef7
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * GNU linker script for the VDSO library.
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Author: Will Deacon <[email protected]>
+ * 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_4.12 {
+ 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 440fe2652d4a..a37342ed1503 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -37,8 +37,13 @@
#include <asm/vdso.h>
#include <asm/vdso_datapage.h>

-extern char vdso_start[], vdso_end[];
-static unsigned long vdso_pages __ro_after_init;
+extern char vdso_lp64_start[], vdso_lp64_end[];
+static unsigned long vdso_lp64_pages __ro_after_init;
+
+#ifdef CONFIG_ARM64_ILP32
+extern char vdso_ilp32_start[], vdso_ilp32_end[];
+static unsigned long vdso_ilp32_pages __ro_after_init;
+#endif

/*
* The vDSO data page.
@@ -114,7 +119,7 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
{
unsigned long new_size = new_vma->vm_end - new_vma->vm_start;
- unsigned long vdso_size = vdso_end - vdso_start;
+ unsigned long vdso_size = vdso_lp64_end - vdso_lp64_start;

if (vdso_size != new_size)
return -EINVAL;
@@ -124,7 +129,7 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
return 0;
}

-static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
+static struct vm_special_mapping vdso_lp64_spec[2] __ro_after_init = {
{
.name = "[vvar]",
},
@@ -134,9 +139,23 @@ static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
},
};

-static int __init vdso_init(void)
+#ifdef CONFIG_ARM64_ILP32
+static struct vm_special_mapping vdso_ilp32_spec[2] __ro_after_init = {
+ {
+ .name = "[vvar]",
+ },
+ {
+ .name = "[vdso]",
+ },
+};
+#endif
+
+static int __init vdso_init(char *vdso_start, char *vdso_end,
+ unsigned long *vdso_pagesp,
+ struct vm_special_mapping *vdso_spec)
{
int i;
+ unsigned long vdso_pages;
struct page **vdso_pagelist;
unsigned long pfn;

@@ -146,8 +165,10 @@ static int __init vdso_init(void)
}

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 *),
@@ -170,7 +191,22 @@ static int __init vdso_init(void)

return 0;
}
-arch_initcall(vdso_init);
+
+static int __init vdso_lp64_init(void)
+{
+ return vdso_init(vdso_lp64_start, vdso_lp64_end,
+ &vdso_lp64_pages, vdso_lp64_spec);
+}
+arch_initcall(vdso_lp64_init);
+
+#ifdef CONFIG_ARM64_ILP32
+static int __init vdso_ilp32_init(void)
+{
+ return vdso_init(vdso_ilp32_start, vdso_ilp32_end,
+ &vdso_ilp32_pages, vdso_ilp32_spec);
+}
+arch_initcall(vdso_ilp32_init);
+#endif

int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp)
@@ -178,8 +214,17 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
struct mm_struct *mm = current->mm;
unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
void *ret;
+ unsigned long pages = vdso_lp64_pages;
+ struct vm_special_mapping *vdso_spec = vdso_lp64_spec;
+
+#ifdef CONFIG_ARM64_ILP32
+ if (is_ilp32_compat_task()) {
+ pages = vdso_ilp32_pages;
+ vdso_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;

diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index c39872a7b03c..9aa415098e0e 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -25,6 +25,16 @@
#define NSEC_PER_SEC_LO16 0xca00
#define NSEC_PER_SEC_HI16 0x3b9a

+#ifdef __LP64__
+#define PTR_REG(n) x##n
+#define OFFSET(n) n
+#define DELOUSE(n)
+#else
+#define PTR_REG(n) w##n
+#define OFFSET(n) COMPAT_##n
+#define DELOUSE(n) mov w##n, w##n
+#endif
+
vdso_data .req x6
seqcnt .req w7
w_tmp .req w8
@@ -119,7 +129,7 @@ x_tmp .req x8
.if \shift == 1
lsr x11, x11, x12
.endif
- stp x10, x11, [x1, #TSPEC_TV_SEC]
+ stp PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)]
mov x0, xzr
ret
.endm
@@ -136,6 +146,8 @@ x_tmp .req x8
/* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
ENTRY(__kernel_gettimeofday)
.cfi_startproc
+ DELOUSE(0)
+ DELOUSE(1)
adr vdso_data, _vdso_data
/* If tv is NULL, skip to the timezone code. */
cbz x0, 2f
@@ -160,7 +172,7 @@ ENTRY(__kernel_gettimeofday)
mov x13, #1000
lsl x13, x13, x12
udiv x11, x11, x13
- stp x10, x11, [x0, #TVAL_TV_SEC]
+ stp PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)]
2:
/* If tz is NULL, return 0. */
cbz x1, 3f
@@ -182,6 +194,7 @@ ENDPROC(__kernel_gettimeofday)
/* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
ENTRY(__kernel_clock_gettime)
.cfi_startproc
+ DELOUSE(1)
cmp w0, #JUMPSLOT_MAX
b.hi syscall
adr vdso_data, _vdso_data
@@ -296,6 +309,7 @@ ENDPROC(__kernel_clock_gettime)
/* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */
ENTRY(__kernel_clock_getres)
.cfi_startproc
+ DELOUSE(1)
cmp w0, #CLOCK_REALTIME
ccmp w0, #CLOCK_MONOTONIC, #0x4, ne
ccmp w0, #CLOCK_MONOTONIC_RAW, #0x4, ne
@@ -310,7 +324,7 @@ ENTRY(__kernel_clock_getres)
ldr x2, 6f
2:
cbz x1, 3f
- stp xzr, x2, [x1]
+ stp PTR_REG(zr), PTR_REG(2), [x1]

3: /* res == NULL. */
mov w0, wzr
diff --git a/arch/arm64/kernel/vdso/vdso.S b/arch/arm64/kernel/vdso/vdso.S
index 82379a70ef03..a40ae2485430 100644
--- a/arch/arm64/kernel/vdso/vdso.S
+++ b/arch/arm64/kernel/vdso/vdso.S
@@ -21,12 +21,12 @@
#include <linux/const.h>
#include <asm/page.h>

- .globl vdso_start, vdso_end
+ .globl vdso_lp64_start, vdso_lp64_end
.section .rodata
.balign PAGE_SIZE
-vdso_start:
+vdso_lp64_start:
.incbin "arch/arm64/kernel/vdso/vdso.so"
.balign PAGE_SIZE
-vdso_end:
+vdso_lp64_end:

.previous
--
2.17.0


2018-05-16 08:27:08

by Yury Norov

[permalink] [raw]
Subject: [PATCH 19/24] arm64: signal32: move ilp32 and aarch32 common code to separated file

ILP32 needs to mix 32bit struct siginfo and 64bit sigframe for its signal
handlers. Move the existing compat code for copying siginfo to user space
and manipulating signal masks into signal32_common.c so it can be used to
deliver aarch32 and ilp32 signals.

Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/include/asm/signal32_common.h | 13 +++++++++
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/signal32.c | 23 +--------------
arch/arm64/kernel/signal32_common.c | 37 ++++++++++++++++++++++++
4 files changed, 52 insertions(+), 23 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 000000000000..10bcdf6b8b4c
--- /dev/null
+++ b/arch/arm64/include/asm/signal32_common.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __ASM_SIGNAL32_COMMON_H
+#define __ASM_SIGNAL32_COMMON_H
+
+#ifdef CONFIG_COMPAT
+
+int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set);
+int get_sigset_t(sigset_t *set, const compat_sigset_t __user *uset);
+
+#endif /* CONFIG_COMPAT*/
+
+#endif /* __ASM_SIGNAL32_COMMON_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index a6db407d4089..9e127c47a25c 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -29,7 +29,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o binfmt_elf32.o
arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o
-arm64-obj-$(CONFIG_COMPAT) += entry32_common.o
+arm64-obj-$(CONFIG_COMPAT) += entry32_common.o signal32_common.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 739e13b54820..fdcc210028b5 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -26,6 +26,7 @@
#include <asm/esr.h>
#include <asm/fpsimd.h>
#include <asm/signal32.h>
+#include <asm/signal32_common.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>

@@ -103,28 +104,6 @@ struct a32_rt_sigframe {

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

-static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
-{
- compat_sigset_t cset;
-
- cset.sig[0] = set->sig[0] & 0xffffffffull;
- cset.sig[1] = set->sig[0] >> 32;
-
- return copy_to_user(uset, &cset, sizeof(*uset));
-}
-
-static inline int get_sigset_t(sigset_t *set,
- const compat_sigset_t __user *uset)
-{
- compat_sigset_t s32;
-
- if (copy_from_user(&s32, uset, sizeof(*uset)))
- return -EFAULT;
-
- set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
- 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 000000000000..21995fc4e0b4
--- /dev/null
+++ b/arch/arm64/kernel/signal32_common.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Modified by Will Deacon <[email protected]>
+ */
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+
+#include <asm/signal32_common.h>
+#include <asm/unistd.h>
+
+int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
+{
+ compat_sigset_t cset;
+
+ cset.sig[0] = set->sig[0] & 0xffffffffull;
+ cset.sig[1] = set->sig[0] >> 32;
+
+ return copy_to_user(uset, &cset, sizeof(*uset));
+}
+
+int get_sigset_t(sigset_t *set, const compat_sigset_t __user *uset)
+{
+ compat_sigset_t s32;
+
+ if (copy_from_user(&s32, uset, sizeof(*uset)))
+ return -EFAULT;
+
+ set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
+ return 0;
+}
--
2.17.0


2018-05-16 08:28:14

by Yury Norov

[permalink] [raw]
Subject: [PATCH 15/24] arm64: ilp32: introduce binfmt_ilp32.c

Like binfmt_elf32.c for AARCH32, binfmt_ilp32.c is needed to handle
ILP32 binaries.

Signed-off-by: Yury Norov <[email protected]>
Signed-off-by: Bamvor Jian Zhang <[email protected]>
---
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/binfmt_ilp32.c | 87 ++++++++++++++++++++++++++++++++
2 files changed, 88 insertions(+)
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index c63e0164fc12..3114191750ae 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 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_ARM64_MODULE_PLTS) += module-plts.o
diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
new file mode 100644
index 000000000000..26b2477d190d
--- /dev/null
+++ b/arch/arm64/kernel/binfmt_ilp32.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Support for ILP32 Linux/aarch64 ELF binaries.
+ */
+#undef CONFIG_AARCH32_EL0
+#define compat_elf_gregset_t elf_gregset_t
+
+#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
+
+/* 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_bit(TIF_32BIT, &current->mm->context.flags); \
+ 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)
+
+#undef ELF_PLATFORM
+#ifdef __AARCH64EB__
+#define ELF_PLATFORM ("aarch64_be:ilp32")
+#else
+#define ELF_PLATFORM ("aarch64:ilp32")
+#endif
+
+#undef ELF_ET_DYN_BASE
+#define ELF_ET_DYN_BASE COMPAT_ELF_ET_DYN_BASE
+
+#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
+
+#undef ns_to_timeval
+#define ns_to_timeval ns_to_compat_timeval
+
+#include "../../../fs/binfmt_elf.c"
--
2.17.0


2018-05-16 08:29:14

by Yury Norov

[permalink] [raw]
Subject: [PATCH 16/24] arm64: ilp32: share aarch32 syscall handlers

According to userspace/kernel ABI, userspace off_t is passed in register
pair just like in aarch32. In this patch corresponding aarch32 handlers
are shared to ilp32 code.

Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/entry32.S | 80 ------------------------
arch/arm64/kernel/entry32_common.S | 97 ++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 80 deletions(-)
create mode 100644 arch/arm64/kernel/entry32_common.S

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 3114191750ae..2dde9ae508ec 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -29,6 +29,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o binfmt_elf32.o
arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o
+arm64-obj-$(CONFIG_COMPAT) += entry32_common.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o
diff --git a/arch/arm64/kernel/entry32.S b/arch/arm64/kernel/entry32.S
index f332d5d1f6b4..4bede0324440 100644
--- a/arch/arm64/kernel/entry32.S
+++ b/arch/arm64/kernel/entry32.S
@@ -39,83 +39,3 @@ ENTRY(compat_sys_rt_sigreturn_wrapper)
mov x0, sp
b compat_sys_rt_sigreturn
ENDPROC(compat_sys_rt_sigreturn_wrapper)
-
-ENTRY(compat_sys_statfs64_wrapper)
- mov w3, #84
- cmp w1, #88
- csel w1, w3, w1, eq
- b compat_sys_statfs64
-ENDPROC(compat_sys_statfs64_wrapper)
-
-ENTRY(compat_sys_fstatfs64_wrapper)
- mov w3, #84
- cmp w1, #88
- csel w1, w3, w1, eq
- b compat_sys_fstatfs64
-ENDPROC(compat_sys_fstatfs64_wrapper)
-
-/*
- * Note: off_4k (w5) is always in units of 4K. If we can't do the
- * requested offset because it is not page-aligned, we return -EINVAL.
- */
-ENTRY(compat_sys_mmap2_wrapper)
-#if PAGE_SHIFT > 12
- tst w5, #~PAGE_MASK >> 12
- b.ne 1f
- lsr w5, w5, #PAGE_SHIFT - 12
-#endif
- b sys_mmap_pgoff
-1: mov x0, #-EINVAL
- ret
-ENDPROC(compat_sys_mmap2_wrapper)
-
-/*
- * Wrappers for AArch32 syscalls that either take 64-bit parameters
- * in registers or that take 32-bit parameters which require sign
- * extension.
- */
-ENTRY(compat_sys_pread64_wrapper)
- regs_to_64 x3, x4, x5
- b sys_pread64
-ENDPROC(compat_sys_pread64_wrapper)
-
-ENTRY(compat_sys_pwrite64_wrapper)
- regs_to_64 x3, x4, x5
- b sys_pwrite64
-ENDPROC(compat_sys_pwrite64_wrapper)
-
-ENTRY(compat_sys_truncate64_wrapper)
- regs_to_64 x1, x2, x3
- b sys_truncate
-ENDPROC(compat_sys_truncate64_wrapper)
-
-ENTRY(compat_sys_ftruncate64_wrapper)
- regs_to_64 x1, x2, x3
- b sys_ftruncate
-ENDPROC(compat_sys_ftruncate64_wrapper)
-
-ENTRY(compat_sys_readahead_wrapper)
- regs_to_64 x1, x2, x3
- mov w2, w4
- b sys_readahead
-ENDPROC(compat_sys_readahead_wrapper)
-
-ENTRY(compat_sys_fadvise64_64_wrapper)
- mov w6, w1
- regs_to_64 x1, x2, x3
- regs_to_64 x2, x4, x5
- mov w3, w6
- b sys_fadvise64_64
-ENDPROC(compat_sys_fadvise64_64_wrapper)
-
-ENTRY(compat_sys_sync_file_range2_wrapper)
- regs_to_64 x2, x2, x3
- regs_to_64 x3, x4, x5
- b sys_sync_file_range2
-ENDPROC(compat_sys_sync_file_range2_wrapper)
-
-ENTRY(compat_sys_fallocate_wrapper)
- regs_to_64 x2, x2, x3
- regs_to_64 x3, x4, x5
- b sys_fallocate
-ENDPROC(compat_sys_fallocate_wrapper)
diff --git a/arch/arm64/kernel/entry32_common.S b/arch/arm64/kernel/entry32_common.S
new file mode 100644
index 000000000000..6ef4752162d0
--- /dev/null
+++ b/arch/arm64/kernel/entry32_common.S
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+/*
+ * Compat system call wrappers
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Authors: Will Deacon <[email protected]>
+ * Catalin Marinas <[email protected]>
+ */
+
+#include <linux/linkage.h>
+#include <linux/const.h>
+
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/errno.h>
+#include <asm/page.h>
+
+/*
+ * Note: off_4k (w5) is always in units of 4K. If we can't do the
+ * requested offset because it is not page-aligned, we return -EINVAL.
+ */
+ENTRY(compat_sys_mmap2_wrapper)
+#if PAGE_SHIFT > 12
+ tst w5, #~PAGE_MASK >> 12
+ b.ne 1f
+ lsr w5, w5, #PAGE_SHIFT - 12
+#endif
+ b sys_mmap_pgoff
+1: mov x0, #-EINVAL
+ ret
+ENDPROC(compat_sys_mmap2_wrapper)
+
+/*
+ * Wrappers for AArch32 syscalls that either take 64-bit parameters
+ * in registers or that take 32-bit parameters which require sign
+ * extension.
+ */
+ENTRY(compat_sys_pread64_wrapper)
+ regs_to_64 x3, x4, x5
+ b sys_pread64
+ENDPROC(compat_sys_pread64_wrapper)
+
+ENTRY(compat_sys_pwrite64_wrapper)
+ regs_to_64 x3, x4, x5
+ b sys_pwrite64
+ENDPROC(compat_sys_pwrite64_wrapper)
+
+ENTRY(compat_sys_truncate64_wrapper)
+ regs_to_64 x1, x2, x3
+ b sys_truncate
+ENDPROC(compat_sys_truncate64_wrapper)
+
+ENTRY(compat_sys_ftruncate64_wrapper)
+ regs_to_64 x1, x2, x3
+ b sys_ftruncate
+ENDPROC(compat_sys_ftruncate64_wrapper)
+
+ENTRY(compat_sys_readahead_wrapper)
+ regs_to_64 x1, x2, x3
+ mov w2, w4
+ b sys_readahead
+ENDPROC(compat_sys_readahead_wrapper)
+
+ENTRY(compat_sys_fadvise64_64_wrapper)
+ mov w6, w1
+ regs_to_64 x1, x2, x3
+ regs_to_64 x2, x4, x5
+ mov w3, w6
+ b sys_fadvise64_64
+ENDPROC(compat_sys_fadvise64_64_wrapper)
+
+ENTRY(compat_sys_sync_file_range2_wrapper)
+ regs_to_64 x2, x2, x3
+ regs_to_64 x3, x4, x5
+ b sys_sync_file_range2
+ENDPROC(compat_sys_sync_file_range2_wrapper)
+
+ENTRY(compat_sys_fallocate_wrapper)
+ regs_to_64 x2, x2, x3
+ regs_to_64 x3, x4, x5
+ b sys_fallocate
+ENDPROC(compat_sys_fallocate_wrapper)
+
+ENTRY(compat_sys_statfs64_wrapper)
+ mov w3, #84
+ cmp w1, #88
+ csel w1, w3, w1, eq
+ b compat_sys_statfs64
+ENDPROC(compat_sys_statfs64_wrapper)
+
+ENTRY(compat_sys_fstatfs64_wrapper)
+ mov w3, #84
+ cmp w1, #88
+ csel w1, w3, w1, eq
+ b compat_sys_fstatfs64
+ENDPROC(compat_sys_fstatfs64_wrapper)
--
2.17.0


2018-05-16 08:29:27

by Yury Norov

[permalink] [raw]
Subject: [PATCH 11/24] arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)

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.

Signed-off-by: Yury Norov <[email protected]>
Signed-off-by: Andrew Pinski <[email protected]>
Signed-off-by: Bamvor Jian Zhang <[email protected]>
---
arch/arm64/include/asm/compat.h | 19 ++--------
arch/arm64/include/asm/elf.h | 10 +++---
arch/arm64/include/asm/ftrace.h | 2 +-
arch/arm64/include/asm/is_compat.h | 52 ++++++++++++++++++++++++++++
arch/arm64/include/asm/processor.h | 9 ++---
arch/arm64/include/asm/syscall.h | 2 +-
arch/arm64/include/asm/thread_info.h | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 8 ++---
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 7 ++--
arch/arm64/kernel/ptrace.c | 11 +++---
arch/arm64/kernel/signal.c | 4 +--
arch/arm64/kernel/traps.c | 3 +-
arch/arm64/mm/mmap.c | 2 +-
14 files changed, 85 insertions(+), 48 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 c00c62e1a4a3..412d7c07a3dd 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -25,6 +25,8 @@
#include <linux/sched.h>
#include <linux/sched/task_stack.h>

+#include <asm/is_compat.h>
+
#define COMPAT_USER_HZ 100
#ifdef __AARCH64EB__
#define COMPAT_UTS_MACHINE "armv8b\0\0"
@@ -234,23 +236,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 fac1c4de7898..b4b10eefc667 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -16,6 +16,10 @@
#ifndef __ASM_ELF_H
#define __ASM_ELF_H

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

/*
@@ -156,13 +160,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 __AARCH64EB__
#define COMPAT_ELF_PLATFORM ("v8b")
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index caa955f10e19..0feb28ad10dd 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -54,7 +54,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
{
- return is_compat_task();
+ return is_a32_compat_task();
}
#endif /* ifndef __ASSEMBLY__ */

diff --git a/arch/arm64/include/asm/is_compat.h b/arch/arm64/include/asm/is_compat.h
new file mode 100644
index 000000000000..19868588fbef
--- /dev/null
+++ b/arch/arm64/include/asm/is_compat.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#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 */
+
+static inline int is_compat_thread(struct thread_info *thread)
+{
+ return is_a32_compat_thread(thread);
+}
+
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_IS_COMPAT_H */
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 79cbc385f52a..78f9e71ad6fc 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -37,6 +37,7 @@
#include <linux/string.h>

#include <asm/alternative.h>
+#include <asm/is_compat.h>
#include <asm/fpsimd.h>
#include <asm/hw_breakpoint.h>
#include <asm/lse.h>
@@ -50,9 +51,9 @@
*/
#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) ? \
+#define TASK_SIZE_OF(tsk) (is_compat_thread(tsk) ? \
TASK_SIZE_32 : TASK_SIZE_64)
#else
#define TASK_SIZE TASK_SIZE_64
@@ -63,7 +64,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
@@ -130,7 +131,7 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
#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/syscall.h b/arch/arm64/include/asm/syscall.h
index 709a574468f0..ce09641f888d 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -113,7 +113,7 @@ static inline void syscall_set_arguments(struct task_struct *task,
*/
static inline int syscall_get_arch(void)
{
- if (is_compat_task())
+ if (is_a32_compat_task())
return AUDIT_ARCH_ARM;

return AUDIT_ARCH_AARCH64;
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 740aa03c5f0d..6d2d58daa9d7 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -91,7 +91,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#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_SVE 23 /* Scalable Vector Extension in use */
#define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */

diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index 74bb56f656ef..55c09285f444 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -169,7 +169,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;

@@ -180,7 +180,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));
}

/**
@@ -480,7 +480,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;
@@ -537,7 +537,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
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
index 513e279b12d3..6efbbd171670 100644
--- a/arch/arm64/kernel/perf_regs.c
+++ b/arch/arm64/kernel/perf_regs.c
@@ -47,7 +47,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 105f79d126ee..50b1249844b7 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -51,7 +51,6 @@
#include <linux/thread_info.h>

#include <asm/alternative.h>
-#include <asm/compat.h>
#include <asm/cacheflush.h>
#include <asm/exec.h>
#include <asm/fpsimd.h>
@@ -256,7 +255,7 @@ static void tls_thread_flush(void)
{
write_sysreg(0, tpidr_el0);

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

/*
@@ -340,7 +339,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
*task_user_tls(p) = read_sysreg(tpidr_el0);

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;
else
childregs->sp = stack_start;
@@ -378,7 +377,7 @@ static void tls_thread_switch(struct task_struct *next)
{
tls_preserve_current_state();

- if (is_compat_thread(task_thread_info(next)))
+ if (is_a32_compat_thread(task_thread_info(next)))
write_sysreg(next->thread.tp_value, tpidrro_el0);
else if (!arm64_kernel_unmapped_at_el0())
write_sysreg(0, tpidrro_el0);
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 04e9b7973b28..4d0a541d049b 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -40,7 +40,6 @@
#include <linux/tracehook.h>
#include <linux/elf.h>

-#include <asm/compat.h>
#include <asm/cpufeature.h>
#include <asm/debug-monitors.h>
#include <asm/pgtable.h>
@@ -189,7 +188,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
info.si_addr = (void __user *)(bkpt->trigger);

#ifdef CONFIG_AARCH32_EL0
- if (is_compat_task()) {
+ if (is_a32_compat_task()) {
int si_errno = 0;
int i;

@@ -1592,9 +1591,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;
@@ -1621,7 +1620,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;

@@ -1732,7 +1731,7 @@ int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
regs->pstate &= ~DBG_SPSR_SS;

- if (is_compat_thread(task_thread_info(task)))
+ if (is_a32_compat_thread(task_thread_info(task)))
return valid_compat_regs(regs);
else
return valid_native_regs(regs);
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index fb7c1a510ed4..0a829f6f1832 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -778,7 +778,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())
a32_setup_restart_syscall(regs);
else
regs->regs[8] = __NR_restart_syscall;
@@ -797,7 +797,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 = a32_setup_rt_frame(usig, ksig, oldset, regs);
else
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index d2ebfc2f4fbc..0d6eda51eca1 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>
@@ -519,7 +520,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 = a32_arm_syscall(regs);
if (ret != -ENOSYS)
return ret;
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index decccffb03ca..65be0d308d75 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -54,7 +54,7 @@ unsigned long arch_mmap_rnd(void)
unsigned long rnd;

#ifdef CONFIG_COMPAT
- if (test_thread_flag(TIF_32BIT))
+ if (is_compat_task())
rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
else
#endif
--
2.17.0


2018-05-16 08:29:32

by Yury Norov

[permalink] [raw]
Subject: [PATCH 14/24] arm64: change compat_elf_hwcap and compat_elf_hwcap2 prefix to a32

ILP32 patch series introduces new type of binaries which is also compat.
So rename existung aarch32 compat_elf_hwcap's helps to avoid confusing.

Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/include/asm/hwcap.h | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 4 ++--
arch/arm64/kernel/cpufeature.c | 14 +++++++-------
arch/arm64/kernel/cpuinfo.c | 10 +++++-----
drivers/clocksource/arm_arch_timer.c | 2 +-
5 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 99dfd9277559..428b745b5386 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -47,7 +47,7 @@
#define ELF_HWCAP (elf_hwcap)

#ifdef CONFIG_AARCH32_EL0
-extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
+extern unsigned int a32_elf_hwcap, a32_elf_hwcap2;
#endif

enum {
diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
index 440fa84f62b3..2b49d2a40d8b 100644
--- a/arch/arm64/kernel/binfmt_elf32.c
+++ b/arch/arm64/kernel/binfmt_elf32.c
@@ -20,8 +20,8 @@
})

#define COMPAT_ARCH_DLINFO
-#define COMPAT_ELF_HWCAP (compat_elf_hwcap)
-#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2)
+#define COMPAT_ELF_HWCAP (a32_elf_hwcap)
+#define COMPAT_ELF_HWCAP2 (a32_elf_hwcap2)

#define compat_arch_setup_additional_pages \
aarch32_setup_vectors_page
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 28b7bc582334..4867fb142e86 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -38,15 +38,15 @@ unsigned long elf_hwcap __read_mostly;
EXPORT_SYMBOL_GPL(elf_hwcap);

#ifdef CONFIG_AARCH32_EL0
-#define COMPAT_ELF_HWCAP_DEFAULT \
+#define AARCH32_EL0_ELF_HWCAP_DEFAULT \
(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\
COMPAT_HWCAP_LPAE)
-unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
-unsigned int compat_elf_hwcap2 __read_mostly;
+unsigned int a32_elf_hwcap __read_mostly = AARCH32_EL0_ELF_HWCAP_DEFAULT;
+unsigned int a32_elf_hwcap2 __read_mostly;
#endif

DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
@@ -1151,10 +1151,10 @@ static void __init cap_set_elf_hwcap(const struct arm64_cpu_capabilities *cap)
break;
#ifdef CONFIG_AARCH32_EL0
case CAP_COMPAT_HWCAP:
- compat_elf_hwcap |= (u32)cap->hwcap;
+ a32_elf_hwcap |= (u32)cap->hwcap;
break;
case CAP_COMPAT_HWCAP2:
- compat_elf_hwcap2 |= (u32)cap->hwcap;
+ a32_elf_hwcap2 |= (u32)cap->hwcap;
break;
#endif
default:
@@ -1174,10 +1174,10 @@ static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap)
break;
#ifdef CONFIG_AARCH32_EL0
case CAP_COMPAT_HWCAP:
- rc = (compat_elf_hwcap & (u32)cap->hwcap) != 0;
+ rc = (a32_elf_hwcap & (u32)cap->hwcap) != 0;
break;
case CAP_COMPAT_HWCAP2:
- rc = (compat_elf_hwcap2 & (u32)cap->hwcap) != 0;
+ rc = (a32_elf_hwcap2 & (u32)cap->hwcap) != 0;
break;
#endif
default:
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 23fdf30dc0a3..a57a6fd0afab 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -120,7 +120,7 @@ static const char *const compat_hwcap2_str[] = {
static int c_show(struct seq_file *m, void *v)
{
int i, j;
- bool compat = personality(current->personality) == PER_LINUX32;
+ bool aarch32 = personality(current->personality) == PER_LINUX32;

for_each_online_cpu(i) {
struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
@@ -132,7 +132,7 @@ static int c_show(struct seq_file *m, void *v)
* "processor". Give glibc what it expects.
*/
seq_printf(m, "processor\t: %d\n", i);
- if (compat)
+ if (aarch32)
seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);

@@ -147,14 +147,14 @@ static int c_show(struct seq_file *m, void *v)
* software which does already (at least for 32-bit).
*/
seq_puts(m, "Features\t:");
- if (compat) {
+ if (aarch32) {
#ifdef CONFIG_AARCH32_EL0
for (j = 0; compat_hwcap_str[j]; j++)
- if (compat_elf_hwcap & (1 << j))
+ if (a32_elf_hwcap & (1 << j))
seq_printf(m, " %s", compat_hwcap_str[j]);

for (j = 0; compat_hwcap2_str[j]; j++)
- if (compat_elf_hwcap2 & (1 << j))
+ if (a32_elf_hwcap2 & (1 << j))
seq_printf(m, " %s", compat_hwcap2_str[j]);
#endif /* CONFIG_AARCH32_EL0 */
} else {
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index c3c6a8d48adc..d8b12b9be97b 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -765,7 +765,7 @@ static void arch_timer_evtstrm_enable(int divider)
arch_timer_set_cntkctl(cntkctl);
elf_hwcap |= HWCAP_EVTSTRM;
#ifdef CONFIG_AARCH32_EL0
- compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
+ a32_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
#endif
cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
}
--
2.17.0


2018-05-16 08:30:10

by Yury Norov

[permalink] [raw]
Subject: [PATCH 10/24] arm64: uapi: set __BITS_PER_LONG correctly for ILP32 and LP64

From: Andrew Pinski <[email protected]>

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 <[email protected]>
Signed-off-by: Philipp Tomsich <[email protected]>
Signed-off-by: Christoph Muellner <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
Reviewed-by: David Daney <[email protected]>
---
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 485d60bee26c..9a05a9659e76 100644
--- a/arch/arm64/include/uapi/asm/bitsperlong.h
+++ b/arch/arm64/include/uapi/asm/bitsperlong.h
@@ -17,7 +17,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.17.0


2018-05-16 08:30:26

by Yury Norov

[permalink] [raw]
Subject: [PATCH 07/24] arm64: ilp32: add documentation on the ILP32 ABI for ARM64

Based on Andrew Pinski's patch-series.

Signed-off-by: Yury Norov <[email protected]>
---
Documentation/arm64/ilp32.txt | 45 +++++++++++++++++++++++++++++++++++
1 file changed, 45 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 000000000000..d0fd5109c4b2
--- /dev/null
+++ b/Documentation/arm64/ilp32.txt
@@ -0,0 +1,45 @@
+ILP32 AARCH64 SYSCALL ABI
+=========================
+
+This document describes the ILP32 syscall ABI and where it differs
+from the generic compat linux syscall interface.
+
+AARCH64/ILP32 userspace can pass garbage in the top halve of w0-w7 registers
+(syscall arguments). So top 32 bits are zeroed for them.
+
+Comparing to AARCH32, AARCH64/ILP32 has 64-bit length of following types:
+ino_t is u64 type.
+off_t is s64 type.
+blkcnt_t is s64 type.
+fsblkcnt_t is u64 type.
+fsfilcnt_t is u64 type.
+rlim_t is u64 type.
+
+AARCH64/ILP32 ABI uses standard syscall table which can be found at
+include/uapi/asm-generic/unistd.h, with the exceptions listed below.
+
+Syscalls which pass 64-bit values are handled by the code shared from
+AARCH32 and pass that value as a pair. Following syscalls are affected:
+fadvise64_64()
+fallocate()
+ftruncate64()
+pread64()
+pwrite64()
+readahead()
+sync_file_range()
+truncate64()
+
+ptrace() syscall is handled by compat version.
+
+shmat() syscall is handled by non-compat handler as aarch64/ilp32 has no
+limitation on 4-pages alignment for shared memory.
+
+statfs() and fstatfs() take the size of struct statfs as an argument.
+It is calculated differently in kernel and user spaces. So AARCH32 handlers
+are taken to handle it.
+
+struct rt_sigframe is redefined and contains struct compat_siginfo,
+as compat syscalls expect, and struct ilp32_ucontext, to handle
+AARCH64 register set and 32-bit userspace register representation.
+
+elf_gregset_t is taken from lp64 to handle registers properly.
--
2.17.0


2018-05-16 08:30:46

by Yury Norov

[permalink] [raw]
Subject: [PATCH 03/24] compat ABI: use non-compat openat and open_by_handle_at variants

The only difference between native and compat openat and open_by_handle_at
is that non-compat version forces O_LARGEFILE, and it should be the
default behaviour for all architectures, as we are going to drop the
support of 32-bit userspace off_t.

The exception is tile32 that continues with compat version of syscalls.

Signed-off-by: Yury Norov <[email protected]>
Acked-by: Arnd Bergmann <[email protected]>
Acked-by: Chris Metcalf <[email protected]> [for tile]
---
arch/tile/kernel/compat.c | 3 +++
include/uapi/asm-generic/unistd.h | 5 ++---
2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index bdaf71d31a4a..3b7853c59395 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -103,6 +103,9 @@ COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
#define compat_sys_readahead sys32_readahead
#define sys_llseek compat_sys_llseek

+#define sys_openat compat_sys_openat
+#define sys_open_by_handle_at compat_sys_open_by_handle_at
+
/* Call the assembly trampolines where necessary. */
#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
#define sys_clone _sys_clone
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 8b87de067bc7..426a1a496d9d 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -179,7 +179,7 @@ __SYSCALL(__NR_fchownat, sys_fchownat)
#define __NR_fchown 55
__SYSCALL(__NR_fchown, sys_fchown)
#define __NR_openat 56
-__SC_COMP(__NR_openat, sys_openat, compat_sys_openat)
+__SYSCALL(__NR_openat, sys_openat)
#define __NR_close 57
__SYSCALL(__NR_close, sys_close)
#define __NR_vhangup 58
@@ -676,8 +676,7 @@ __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)
#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)
+__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
#define __NR_clock_adjtime 266
__SC_COMP(__NR_clock_adjtime, sys_clock_adjtime, compat_sys_clock_adjtime)
#define __NR_syncfs 267
--
2.17.0


2018-05-23 14:07:17

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 07/24] arm64: ilp32: add documentation on the ILP32 ABI for ARM64

On Wed 2018-05-16 11:18:52, Yury Norov wrote:
> Based on Andrew Pinski's patch-series.
>
> Signed-off-by: Yury Norov <[email protected]>

So Andrew's signoff should be here?

> ---
> Documentation/arm64/ilp32.txt | 45 +++++++++++++++++++++++++++++++++++
> 1 file changed, 45 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 000000000000..d0fd5109c4b2
> --- /dev/null
> +++ b/Documentation/arm64/ilp32.txt
> @@ -0,0 +1,45 @@
> +ILP32 AARCH64 SYSCALL ABI
> +=========================
> +
> +This document describes the ILP32 syscall ABI and where it differs
> +from the generic compat linux syscall interface.

I was hoping to learn what ILP32 is / what is it good for, but no,
this does not tell me... it would be good to do a short explanation
here, and maybe reference it from cover letter of the series...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (1.10 kB)
signature.asc (188.00 B)
Digital signature
Download all attachments

2018-05-24 12:16:54

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH 07/24] arm64: ilp32: add documentation on the ILP32 ABI for ARM64

Hi Pavel,

On Wed, May 23, 2018 at 04:06:20PM +0200, Pavel Machek wrote:
> On Wed 2018-05-16 11:18:52, Yury Norov wrote:
> > Based on Andrew Pinski's patch-series.
> >
> > Signed-off-by: Yury Norov <[email protected]>
>
> So Andrew's signoff should be here?

Yes it should, but it lost since v4. I'll restore it.

> > ---
> > Documentation/arm64/ilp32.txt | 45 +++++++++++++++++++++++++++++++++++
> > 1 file changed, 45 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 000000000000..d0fd5109c4b2
> > --- /dev/null
> > +++ b/Documentation/arm64/ilp32.txt
> > @@ -0,0 +1,45 @@
> > +ILP32 AARCH64 SYSCALL ABI
> > +=========================
> > +
> > +This document describes the ILP32 syscall ABI and where it differs
> > +from the generic compat linux syscall interface.
>
> I was hoping to learn what ILP32 is / what is it good for, but no,
> this does not tell me... it would be good to do a short explanation
> here, and maybe reference it from cover letter of the series...
> Pavel

ILP32 is ABI acronym that means "Integers, Longs and Pointers are 32-bit".
And LP64 means "Longs and Pointers are 64-bit".

There's AN490 - "ILP32 for AArch64 Whitepaper" from ARM which covers
the topic:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0490a/ar01s01.html

And some talks:
http://connect.linaro.org/resource/bkk16/bkk16-305b/

Briefly, ILP32 is 32-bit ABI that works with AARCH64 instruction set. It looks
better in some performance tests, and is useful for compatibility with 32-bit
legacy code.

If you're more familiar with x86 terminology, in ARM world LP64 corresponds
to x86_64, AARCH32_EL0 corresponds to x86_32, and ILP32 corresponds to x32
ABI.

I'll add link to AN490 in next submission.

Yury

> --
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html




2018-05-24 12:27:20

by Philipp Tomsich

[permalink] [raw]
Subject: Re: [PATCH 07/24] arm64: ilp32: add documentation on the ILP32 ABI for ARM64

Yury & Pavel,

> On 24 May 2018, at 14:15, Yury Norov <[email protected]> wrote:
>
> Hi Pavel,
>
> On Wed, May 23, 2018 at 04:06:20PM +0200, Pavel Machek wrote:
>> On Wed 2018-05-16 11:18:52, Yury Norov wrote:
>>> Based on Andrew Pinski's patch-series.
>>>
>>> Signed-off-by: Yury Norov <[email protected]>
>>
>> So Andrew's signoff should be here?
>
> Yes it should, but it lost since v4. I'll restore it.
>
>>> ---
>>> Documentation/arm64/ilp32.txt | 45 +++++++++++++++++++++++++++++++++++
>>> 1 file changed, 45 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 000000000000..d0fd5109c4b2
>>> --- /dev/null
>>> +++ b/Documentation/arm64/ilp32.txt
>>> @@ -0,0 +1,45 @@
>>> +ILP32 AARCH64 SYSCALL ABI
>>> +=========================
>>> +
>>> +This document describes the ILP32 syscall ABI and where it differs
>>> +from the generic compat linux syscall interface.
>>
>> I was hoping to learn what ILP32 is / what is it good for, but no,
>> this does not tell me... it would be good to do a short explanation
>> here, and maybe reference it from cover letter of the series...
>> Pavel
>
> ILP32 is ABI acronym that means "Integers, Longs and Pointers are 32-bit".
> And LP64 means "Longs and Pointers are 64-bit”.

Just a nitpick: ILP32 is in fact just the memory model, but calling from ILP32
code into the Linux kernel requires modifications to the syscall-ABI due to
datastructure layout changing (every time a pointer or a ‘long’ is present in
a structure). As such structures are passed between the userspace and the
kernel (and also due to the fact that time_t is an ‘unsigned long’ in the C
language standard), modifications to the syscall ABI in Linux are needed to
support ILP32 processes calling into the kernel.

Things get a bit more involved, as the final consensus was to pass 64bit
quantities in the lower half of 2 64bit registers instead of as a single register:
this makes the way (on AArch64) that an ILP32 process calls into the kernel
more dissimilar from a LP64 process calling the same syscall.

What this rambling boils down to is: “ILP32" is the memory model, whereas
this series deals with the “Linux/AArch64 syscall ABI for ILP32 processes”.

Thanks,
Phil.

>
> There's AN490 - "ILP32 for AArch64 Whitepaper" from ARM which covers
> the topic:
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0490a/ar01s01.html
>
> And some talks:
> http://connect.linaro.org/resource/bkk16/bkk16-305b/
>
> Briefly, ILP32 is 32-bit ABI that works with AARCH64 instruction set. It looks
> better in some performance tests, and is useful for compatibility with 32-bit
> legacy code.
>
> If you're more familiar with x86 terminology, in ARM world LP64 corresponds
> to x86_64, AARCH32_EL0 corresponds to x86_32, and ILP32 corresponds to x32
> ABI.
>
> I'll add link to AN490 in next submission.
>
> Yury
>
>> --
>> (english) http://www.livejournal.com/~pavelmachek
>> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


2018-06-08 17:32:56

by Catalin Marinas

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
> diff --git a/arch/Kconfig b/arch/Kconfig
> index 76c0b54443b1..ee079244dc3c 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
> config ARCH_WANTS_DYNAMIC_TASK_STRUCT
> bool
>
> +config ARCH_32BIT_OFF_T
> + bool
> + depends on !64BIT
> + help
> + All new 32-bit architectures should have 64-bit off_t type on
> + userspace side which corresponds to the loff_t kernel type. This
> + is the requirement for modern ABIs. Some existing architectures
> + already have 32-bit off_t. This option is enabled for all such
> + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
> + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
> + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
> + unicore32, x86_32 and xtensa. This is the complete list. Any
> + new 32-bit architecture should declare 64-bit off_t type on user
> + side and so should not enable this option.

Do you know if this is the case for riscv and nds32, merged in the
meantime? If not, I suggest you drop this patch altogether and just
define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
"all new 32-bit architectures should have 64-bit off_t".

--
Catalin

2018-06-08 22:34:46

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Fri, 08 Jun 2018 10:32:07 PDT (-0700), [email protected] wrote:
> On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
>> diff --git a/arch/Kconfig b/arch/Kconfig
>> index 76c0b54443b1..ee079244dc3c 100644
>> --- a/arch/Kconfig
>> +++ b/arch/Kconfig
>> @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
>> config ARCH_WANTS_DYNAMIC_TASK_STRUCT
>> bool
>>
>> +config ARCH_32BIT_OFF_T
>> + bool
>> + depends on !64BIT
>> + help
>> + All new 32-bit architectures should have 64-bit off_t type on
>> + userspace side which corresponds to the loff_t kernel type. This
>> + is the requirement for modern ABIs. Some existing architectures
>> + already have 32-bit off_t. This option is enabled for all such
>> + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
>> + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
>> + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
>> + unicore32, x86_32 and xtensa. This is the complete list. Any
>> + new 32-bit architecture should declare 64-bit off_t type on user
>> + side and so should not enable this option.
>
> Do you know if this is the case for riscv and nds32, merged in the
> meantime? If not, I suggest you drop this patch altogether and just
> define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
> "all new 32-bit architectures should have 64-bit off_t".

We (RISC-V) don't have support for rv32i in glibc yet, so there really isn't a
fixed ABI there yet. From my understanding the rv32i port as it currently
stands has a 32-bit off_t (via __kernel_off_t being defined as long), so this
change would technically be a kernel ABI break.

Since we don't have rv32i glibc yet I'm not fundamentally opposed to an ABI
break. Is there a concrete advantage to this?

2018-06-09 07:43:55

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Fri, Jun 08, 2018 at 06:32:07PM +0100, Catalin Marinas wrote:
> On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
> > diff --git a/arch/Kconfig b/arch/Kconfig
> > index 76c0b54443b1..ee079244dc3c 100644
> > --- a/arch/Kconfig
> > +++ b/arch/Kconfig
> > @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
> > config ARCH_WANTS_DYNAMIC_TASK_STRUCT
> > bool
> >
> > +config ARCH_32BIT_OFF_T
> > + bool
> > + depends on !64BIT
> > + help
> > + All new 32-bit architectures should have 64-bit off_t type on
> > + userspace side which corresponds to the loff_t kernel type. This
> > + is the requirement for modern ABIs. Some existing architectures
> > + already have 32-bit off_t. This option is enabled for all such
> > + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
> > + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
> > + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
> > + unicore32, x86_32 and xtensa. This is the complete list. Any
> > + new 32-bit architecture should declare 64-bit off_t type on user
> > + side and so should not enable this option.
>
> Do you know if this is the case for riscv and nds32, merged in the
> meantime? If not, I suggest you drop this patch altogether and just
> define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
> "all new 32-bit architectures should have 64-bit off_t".

I wrote this patch at request of Arnd Bergmann. This is actually his
words that all new 32-bit architectures should have 64-bit off_t. So
I was surprized when riscv was merged with 32-bit off_t (and I didn't
follow nds32).

If this rule is still in force, we'd better add new exceptions to this
patch. Otherwise, we can drop it.

Arnd, could you please comment it?

Yury

2018-06-09 07:45:00

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Fri, Jun 08, 2018 at 03:33:51PM -0700, Palmer Dabbelt wrote:
> On Fri, 08 Jun 2018 10:32:07 PDT (-0700), [email protected] wrote:
> > On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
> > > diff --git a/arch/Kconfig b/arch/Kconfig
> > > index 76c0b54443b1..ee079244dc3c 100644
> > > --- a/arch/Kconfig
> > > +++ b/arch/Kconfig
> > > @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
> > > config ARCH_WANTS_DYNAMIC_TASK_STRUCT
> > > bool
> > >
> > > +config ARCH_32BIT_OFF_T
> > > + bool
> > > + depends on !64BIT
> > > + help
> > > + All new 32-bit architectures should have 64-bit off_t type on
> > > + userspace side which corresponds to the loff_t kernel type. This
> > > + is the requirement for modern ABIs. Some existing architectures
> > > + already have 32-bit off_t. This option is enabled for all such
> > > + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
> > > + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
> > > + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
> > > + unicore32, x86_32 and xtensa. This is the complete list. Any
> > > + new 32-bit architecture should declare 64-bit off_t type on user
> > > + side and so should not enable this option.
> >
> > Do you know if this is the case for riscv and nds32, merged in the
> > meantime? If not, I suggest you drop this patch altogether and just
> > define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
> > "all new 32-bit architectures should have 64-bit off_t".
>
> We (RISC-V) don't have support for rv32i in glibc yet, so there really isn't
> a fixed ABI there yet. From my understanding the rv32i port as it currently
> stands has a 32-bit off_t (via __kernel_off_t being defined as long), so
> this change would technically be a kernel ABI break.
>
> Since we don't have rv32i glibc yet I'm not fundamentally opposed to an ABI
> break. Is there a concrete advantage to this?

One obvious advantage is manipulating large files - if file is greater than
2G, you cannot easily mmap(), lseek() etc with 32-bit offset.

Another point is unification of layuots for structures like struct
stat between 32- and 64-bit worlds.

On glibc side it helps to unify 32-bit and 64-bit versions of syscalls.
Refer, for example this commit:
3c7f1f59cd161 (Consolidate lseek/lseek64/llseek implementations).

Yury

2018-06-09 21:16:01

by Adam Borowski

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Fri, Jun 08, 2018 at 03:33:51PM -0700, Palmer Dabbelt wrote:
> On Fri, 08 Jun 2018 10:32:07 PDT (-0700), [email protected] wrote:
> > On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
> > > +config ARCH_32BIT_OFF_T
> > > + bool
> > > + depends on !64BIT
> > > + help
> > > + All new 32-bit architectures should have 64-bit off_t type on
> > > + userspace side which corresponds to the loff_t kernel type. This
> > > + is the requirement for modern ABIs. Some existing architectures
> > > + already have 32-bit off_t. This option is enabled for all such
> > > + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
> > > + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
> > > + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
> > > + unicore32, x86_32 and xtensa. This is the complete list. Any
> > > + new 32-bit architecture should declare 64-bit off_t type on user
> > > + side and so should not enable this option.
> >
> > Do you know if this is the case for riscv and nds32, merged in the
> > meantime? If not, I suggest you drop this patch altogether and just
> > define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
> > "all new 32-bit architectures should have 64-bit off_t".

nds32 was obsolete even at the time of merging (it's just that Andes have
a novel idea of actually supporting their old product lines!), thus it'll
be a short lived port. It doesn't matter much if it carries legacy baggage
-- especially that it has existing out-of-mainline users.

Not so much for riscv32, which is designed and planned to be very long
lived. And has no existing _Linux_ users.

> We (RISC-V) don't have support for rv32i in glibc yet, so there really isn't
> a fixed ABI there yet. From my understanding the rv32i port as it currently
> stands has a 32-bit off_t (via __kernel_off_t being defined as long), so
> this change would technically be a kernel ABI break.
>
> Since we don't have rv32i glibc yet I'm not fundamentally opposed to an ABI
> break. Is there a concrete advantage to this?

While modern userland tends to implement LFS support, it's still opt in for
individual binaries at compile time. With my (userland) porter hat on, I
can tell you that no matter how you preach about using sane build systems, a
terrifying portion of packages manage to fail to pass such flags.
Especially for lesser-known or new architectures -- you need to specifically
add the flag for every new arch for every such piece of software.

Its lack is also not so easy to spot in an automated way; an experimental
and hacky attempt to detect them (IIRC by checking whether the program in
question imports an open/lseek/etc symbol instead of open64) is here:
https://lintian.debian.org/tags/binary-file-built-without-LFS-support.html
20511 ELFs in 5953 packages!

If there's no 32-bit open() (ie, it's an alias to open64()), all these bugs
are immediately fixed. Well, a program can still store file size in an int,
but at least there's no interface problem.


On the kernel side, you avoid the need to carry syscalls and structs for
32-bit variants. This gets you less complexity and a smaller kernel.


Meow!
--
⢀⣴⠾⠻⢶⣦⠀ I've read an article about how lively happy music boosts
⣾⠁⢰⠒⠀⣿⡁ productivity. You can read it, too, you just need the
⢿⡄⠘⠷⠚⠋⠀ right music while doing so. I recommend Skepticism
⠈⠳⣄⠀⠀⠀⠀ (funeral doom metal).

2018-06-11 07:50:02

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Sat, Jun 9, 2018 at 9:42 AM, Yury Norov <[email protected]> wrote:
> On Fri, Jun 08, 2018 at 06:32:07PM +0100, Catalin Marinas wrote:
>> On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
>> > diff --git a/arch/Kconfig b/arch/Kconfig
>> > index 76c0b54443b1..ee079244dc3c 100644
>> > --- a/arch/Kconfig
>> > +++ b/arch/Kconfig
>> > @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
>> > config ARCH_WANTS_DYNAMIC_TASK_STRUCT
>> > bool
>> >
>> > +config ARCH_32BIT_OFF_T
>> > + bool
>> > + depends on !64BIT
>> > + help
>> > + All new 32-bit architectures should have 64-bit off_t type on
>> > + userspace side which corresponds to the loff_t kernel type. This
>> > + is the requirement for modern ABIs. Some existing architectures
>> > + already have 32-bit off_t. This option is enabled for all such
>> > + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
>> > + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
>> > + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
>> > + unicore32, x86_32 and xtensa. This is the complete list. Any
>> > + new 32-bit architecture should declare 64-bit off_t type on user
>> > + side and so should not enable this option.
>>
>> Do you know if this is the case for riscv and nds32, merged in the
>> meantime? If not, I suggest you drop this patch altogether and just
>> define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
>> "all new 32-bit architectures should have 64-bit off_t".
>
> I wrote this patch at request of Arnd Bergmann. This is actually his
> words that all new 32-bit architectures should have 64-bit off_t. So
> I was surprized when riscv was merged with 32-bit off_t (and I didn't
> follow nds32).
>
> If this rule is still in force, we'd better add new exceptions to this
> patch. Otherwise, we can drop it.
>
> Arnd, could you please comment it?

I completely forgot about it and had assumed that it was merged long
ago, sorry about that.

Arnd

2018-06-11 11:28:48

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Mon, Jun 11, 2018 at 09:48:02AM +0200, Arnd Bergmann wrote:
> On Sat, Jun 9, 2018 at 9:42 AM, Yury Norov <[email protected]> wrote:
> > On Fri, Jun 08, 2018 at 06:32:07PM +0100, Catalin Marinas wrote:
> >> On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
> >> > diff --git a/arch/Kconfig b/arch/Kconfig
> >> > index 76c0b54443b1..ee079244dc3c 100644
> >> > --- a/arch/Kconfig
> >> > +++ b/arch/Kconfig
> >> > @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
> >> > config ARCH_WANTS_DYNAMIC_TASK_STRUCT
> >> > bool
> >> >
> >> > +config ARCH_32BIT_OFF_T
> >> > + bool
> >> > + depends on !64BIT
> >> > + help
> >> > + All new 32-bit architectures should have 64-bit off_t type on
> >> > + userspace side which corresponds to the loff_t kernel type. This
> >> > + is the requirement for modern ABIs. Some existing architectures
> >> > + already have 32-bit off_t. This option is enabled for all such
> >> > + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
> >> > + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
> >> > + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
> >> > + unicore32, x86_32 and xtensa. This is the complete list. Any
> >> > + new 32-bit architecture should declare 64-bit off_t type on user
> >> > + side and so should not enable this option.
> >>
> >> Do you know if this is the case for riscv and nds32, merged in the
> >> meantime? If not, I suggest you drop this patch altogether and just
> >> define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
> >> "all new 32-bit architectures should have 64-bit off_t".
> >
> > I wrote this patch at request of Arnd Bergmann. This is actually his
> > words that all new 32-bit architectures should have 64-bit off_t. So
> > I was surprized when riscv was merged with 32-bit off_t (and I didn't
> > follow nds32).
> >
> > If this rule is still in force, we'd better add new exceptions to this
> > patch. Otherwise, we can drop it.
> >
> > Arnd, could you please comment it?
>
> I completely forgot about it and had assumed that it was merged long
> ago, sorry about that.

Hi Arnd,

There are 3 patches like this in ILP32 series that change ABI for new
targets. I've submitted them in separated series:
https://lkml.org/lkml/2017/9/25/574

They all seems to be acked by you. If you ready to upstream the
series, I can rebase it and add riscv32 and nds32 exceptions.

If Palmer and riscv people will decide to follow new rules, we can
easily drop the exception.

Yury

2018-06-25 06:21:08

by Yury Norov

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Mon, Jun 11, 2018 at 02:27:36PM +0300, Yury Norov wrote:
> On Mon, Jun 11, 2018 at 09:48:02AM +0200, Arnd Bergmann wrote:
> > On Sat, Jun 9, 2018 at 9:42 AM, Yury Norov <[email protected]> wrote:
> > > On Fri, Jun 08, 2018 at 06:32:07PM +0100, Catalin Marinas wrote:
> > >> On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
> > >> > diff --git a/arch/Kconfig b/arch/Kconfig
> > >> > index 76c0b54443b1..ee079244dc3c 100644
> > >> > --- a/arch/Kconfig
> > >> > +++ b/arch/Kconfig
> > >> > @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
> > >> > config ARCH_WANTS_DYNAMIC_TASK_STRUCT
> > >> > bool
> > >> >
> > >> > +config ARCH_32BIT_OFF_T
> > >> > + bool
> > >> > + depends on !64BIT
> > >> > + help
> > >> > + All new 32-bit architectures should have 64-bit off_t type on
> > >> > + userspace side which corresponds to the loff_t kernel type. This
> > >> > + is the requirement for modern ABIs. Some existing architectures
> > >> > + already have 32-bit off_t. This option is enabled for all such
> > >> > + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
> > >> > + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
> > >> > + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
> > >> > + unicore32, x86_32 and xtensa. This is the complete list. Any
> > >> > + new 32-bit architecture should declare 64-bit off_t type on user
> > >> > + side and so should not enable this option.
> > >>
> > >> Do you know if this is the case for riscv and nds32, merged in the
> > >> meantime? If not, I suggest you drop this patch altogether and just
> > >> define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
> > >> "all new 32-bit architectures should have 64-bit off_t".
> > >
> > > I wrote this patch at request of Arnd Bergmann. This is actually his
> > > words that all new 32-bit architectures should have 64-bit off_t. So
> > > I was surprized when riscv was merged with 32-bit off_t (and I didn't
> > > follow nds32).
> > >
> > > If this rule is still in force, we'd better add new exceptions to this
> > > patch. Otherwise, we can drop it.
> > >
> > > Arnd, could you please comment it?
> >
> > I completely forgot about it and had assumed that it was merged long
> > ago, sorry about that.
>
> Hi Arnd,
>
> There are 3 patches like this in ILP32 series that change ABI for new
> targets. I've submitted them in separated series:
> https://lkml.org/lkml/2017/9/25/574
>
> They all seems to be acked by you. If you ready to upstream the
> series, I can rebase it and add riscv32 and nds32 exceptions.
>
> If Palmer and riscv people will decide to follow new rules, we can
> easily drop the exception.

Ping?

2018-07-24 17:41:50

by Yury Norov

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

Hi all,

+ Pavel Machek, Palmer Dabbelt, Wookey.

On Wed, May 16, 2018 at 11:18:45AM +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.
> - Zhou Chengming's reported-by for patch 2 and signed-off-by for
> patch 21 removed because his email became invalid. Zhou, please
> share your new email.

This is the update of the series based on 4.17 kernel
https://github.com/norov/linux/tree/ilp32-4.17
with the following non-critical changes:
- documentation patch extended with few words about ILP32 in general, and
the link to ARM document about it added;
- nds32 and riscv32 exceptions added for ARCH_32BIT_OFF_T and
{get,set}rlimit (patches 4 and 5).
- changes to architectures that are unsupported anymore are dropped.
- Chris Metcalf's ack for patch #3 removed, as it is related to
tile32 which is unsupported now.

Reminder to Arnd. There's arch subseries acked by you but still
without progress. Could you consider taking it upstream?
[PATCH 03/24] compat ABI: use non-compat openat and open_by_handle_at variants
[PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option
[PATCH 05/24] asm-generic: Drop getrlimit and setrlimit syscalls from default list

Yury

2018-07-25 09:50:19

by Andreas Schwab

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

On Jul 24 2018, Yury Norov <[email protected]> wrote:

> This is the update of the series based on 4.17 kernel
> https://github.com/norov/linux/tree/ilp32-4.17

Note that commit 947bd8e7cd (arm64: ilp32: add
is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64) conflicts with
commit 9dd9614f54 (arm64: ssbd: Introduce thread flag to control
userspace mitigation) (which has been backported to stable).

Andreas.

--
Andreas Schwab, SUSE Labs, [email protected]
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

2018-08-02 18:48:35

by Palmer Dabbelt

[permalink] [raw]
Subject: Re: [PATCH 04/24] 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option

On Sun, 24 Jun 2018 23:19:50 PDT (-0700), [email protected] wrote:
> On Mon, Jun 11, 2018 at 02:27:36PM +0300, Yury Norov wrote:
>> On Mon, Jun 11, 2018 at 09:48:02AM +0200, Arnd Bergmann wrote:
>> > On Sat, Jun 9, 2018 at 9:42 AM, Yury Norov <[email protected]> wrote:
>> > > On Fri, Jun 08, 2018 at 06:32:07PM +0100, Catalin Marinas wrote:
>> > >> On Wed, May 16, 2018 at 11:18:49AM +0300, Yury Norov wrote:
>> > >> > diff --git a/arch/Kconfig b/arch/Kconfig
>> > >> > index 76c0b54443b1..ee079244dc3c 100644
>> > >> > --- a/arch/Kconfig
>> > >> > +++ b/arch/Kconfig
>> > >> > @@ -264,6 +264,21 @@ config ARCH_THREAD_STACK_ALLOCATOR
>> > >> > config ARCH_WANTS_DYNAMIC_TASK_STRUCT
>> > >> > bool
>> > >> >
>> > >> > +config ARCH_32BIT_OFF_T
>> > >> > + bool
>> > >> > + depends on !64BIT
>> > >> > + help
>> > >> > + All new 32-bit architectures should have 64-bit off_t type on
>> > >> > + userspace side which corresponds to the loff_t kernel type. This
>> > >> > + is the requirement for modern ABIs. Some existing architectures
>> > >> > + already have 32-bit off_t. This option is enabled for all such
>> > >> > + architectures explicitly. Namely: arc, arm, blackfin, cris, frv,
>> > >> > + h8300, hexagon, m32r, m68k, metag, microblaze, mips32, mn10300,
>> > >> > + nios2, openrisc, parisc32, powerpc32, score, sh, sparc, tile32,
>> > >> > + unicore32, x86_32 and xtensa. This is the complete list. Any
>> > >> > + new 32-bit architecture should declare 64-bit off_t type on user
>> > >> > + side and so should not enable this option.
>> > >>
>> > >> Do you know if this is the case for riscv and nds32, merged in the
>> > >> meantime? If not, I suggest you drop this patch altogether and just
>> > >> define force_o_largefile() for arm64/ilp32 as we don't seem to stick to
>> > >> "all new 32-bit architectures should have 64-bit off_t".
>> > >
>> > > I wrote this patch at request of Arnd Bergmann. This is actually his
>> > > words that all new 32-bit architectures should have 64-bit off_t. So
>> > > I was surprized when riscv was merged with 32-bit off_t (and I didn't
>> > > follow nds32).
>> > >
>> > > If this rule is still in force, we'd better add new exceptions to this
>> > > patch. Otherwise, we can drop it.
>> > >
>> > > Arnd, could you please comment it?
>> >
>> > I completely forgot about it and had assumed that it was merged long
>> > ago, sorry about that.
>>
>> Hi Arnd,
>>
>> There are 3 patches like this in ILP32 series that change ABI for new
>> targets. I've submitted them in separated series:
>> https://lkml.org/lkml/2017/9/25/574
>>
>> They all seems to be acked by you. If you ready to upstream the
>> series, I can rebase it and add riscv32 and nds32 exceptions.
>>
>> If Palmer and riscv people will decide to follow new rules, we can
>> easily drop the exception.
>
> Ping?

Sorry to be a bit slow, but we just decided to skip this current glibc release
for rv32i and instead focus on getting the 32-bit ABI nice and clean for the
next release. Thus we in RISC-V land are OK with taking these changes to the
32-bit kernel ABI.

2018-10-10 14:11:29

by Eugene Syromiatnikov

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

On Tue, Jul 24, 2018 at 08:39:57PM +0300, Yury Norov wrote:
> Hi all,
>
> + Pavel Machek, Palmer Dabbelt, Wookey.
>
> On Wed, May 16, 2018 at 11:18:45AM +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 is the update of the series based on 4.17 kernel
> https://github.com/norov/linux/tree/ilp32-4.17

Hello.

I have some questions regarding AArch64 ILP32 implementation for which I
failed to find an answer myself:
* How ptrace() tracer is supposed to distinguish between ILP32 and LP64
tracees? For MIPS N32 and x32 this is possible based on syscall
number, but for AArch64 ILP32 I do not see such a sign. There's also
ARM_ip is employed for signalling entering/exiting, I wonder whether
it's possible to employ it also for signalling tracee's personality.
* What's the reasoning behind capping syscall arguments to 32 bit? x32
and MIPS N32 do not have such a restriction (and do not need special
wrappers for syscalls that pass 64-bit values as a result, except
when they do, as it is the case for preadv2 on x32); moreover, that
would lead to insurmountable difficulties for AArch64 ILP32 tracers
that try to trace LP64 tracees, as it would be impossible to pass
64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.

Thank you.

2018-10-10 14:20:14

by Arnd Bergmann

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

On 10/10/18, Eugene Syromiatnikov <[email protected]> wrote:
> On Tue, Jul 24, 2018 at 08:39:57PM +0300, Yury Norov wrote:
>> Hi all,
>>
>> + Pavel Machek, Palmer Dabbelt, Wookey.
>>
>> On Wed, May 16, 2018 at 11:18:45AM +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 is the update of the series based on 4.17 kernel
>> https://github.com/norov/linux/tree/ilp32-4.17
>
> Hello.
>
> I have some questions regarding AArch64 ILP32 implementation for which I
> failed to find an answer myself:
> * How ptrace() tracer is supposed to distinguish between ILP32 and LP64
> tracees? For MIPS N32 and x32 this is possible based on syscall
> number, but for AArch64 ILP32 I do not see such a sign. There's also
> ARM_ip is employed for signalling entering/exiting, I wonder whether
> it's possible to employ it also for signalling tracee's personality.

Don't know.

> * What's the reasoning behind capping syscall arguments to 32 bit? x32
> and MIPS N32 do not have such a restriction (and do not need special
> wrappers for syscalls that pass 64-bit values as a result, except
> when they do, as it is the case for preadv2 on x32); moreover, that
> would lead to insurmountable difficulties for AArch64 ILP32 tracers
> that try to trace LP64 tracees, as it would be impossible to pass
> 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.

The idea is to keep the syscall entry points as similar as possible
between arm (aarch32) emulation and aarch64-ilp32 mode when
you have a kernel that supports both.

Arnd

2018-10-10 14:40:26

by Szabolcs Nagy

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

On 10/10/18 15:10, Eugene Syromiatnikov wrote:
> * What's the reasoning behind capping syscall arguments to 32 bit? x32
> and MIPS N32 do not have such a restriction (and do not need special
> wrappers for syscalls that pass 64-bit values as a result, except
> when they do, as it is the case for preadv2 on x32); moreover, that
> would lead to insurmountable difficulties for AArch64 ILP32 tracers
> that try to trace LP64 tracees, as it would be impossible to pass
> 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.

but that's necessarily the case for all ilp32 abis:
the userspace syscall function receives 32bit
arguments so even if the kernel abi takes 64bit
args you cannot use that from c code. (the libc
does not even know which args should be sign or
zero extended.)

process_vm_readv/writev is limited by the ilp32
iovec struct, not by the syscall arguments.

ptrace is specified to take void* addr argument,
and void* is 32bit on all ilp32 targets.
so again on the c language level there is no
way around the 32bit limitation.

2018-10-10 15:39:24

by Catalin Marinas

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

On Wed, Oct 10, 2018 at 04:10:21PM +0200, Eugene Syromiatnikov wrote:
> I have some questions regarding AArch64 ILP32 implementation for which I
> failed to find an answer myself:
> * How ptrace() tracer is supposed to distinguish between ILP32 and LP64
> tracees? For MIPS N32 and x32 this is possible based on syscall
> number, but for AArch64 ILP32 I do not see such a sign. There's also
> ARM_ip is employed for signalling entering/exiting, I wonder whether
> it's possible to employ it also for signalling tracee's personality.

With the current implementation, I don't think you can distinguish. From
the kernel perspective, the register set is the same. What is the
use-case for this?

We could add a new regset to expose the ILP32 state (NT_ARM_..., I can't
think of a name now but probably not PER* as this implies PER_LINUX_...
which is independent from TIF_32BIT_*).

> * What's the reasoning behind capping syscall arguments to 32 bit? x32
> and MIPS N32 do not have such a restriction (and do not need special
> wrappers for syscalls that pass 64-bit values as a result, except
> when they do, as it is the case for preadv2 on x32); moreover, that
> would lead to insurmountable difficulties for AArch64 ILP32 tracers
> that try to trace LP64 tracees, as it would be impossible to pass
> 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.

We've attempted in earlier versions to allow a mix of 32 and 64-bit
register values from ILP32 but it got pretty complicated. The entry code
would need to know which registers need zeroing of the top 32-bit and
the generic unistd.h wrapper hacks were not very nice. Some past
discussions:

https://www.mail-archive.com/[email protected]/msg1211716.html

--
Catalin

2018-10-13 02:09:16

by Eugene Syromiatnikov

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

On Wed, Oct 10, 2018 at 03:39:07PM +0100, Szabolcs Nagy wrote:
> On 10/10/18 15:10, Eugene Syromiatnikov wrote:
> > * What's the reasoning behind capping syscall arguments to 32 bit? x32
> > and MIPS N32 do not have such a restriction (and do not need special
> > wrappers for syscalls that pass 64-bit values as a result, except
> > when they do, as it is the case for preadv2 on x32); moreover, that
> > would lead to insurmountable difficulties for AArch64 ILP32 tracers
> > that try to trace LP64 tracees, as it would be impossible to pass
> > 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.
>
> but that's necessarily the case for all ilp32 abis:
> the userspace syscall function receives 32bit
> arguments so even if the kernel abi takes 64bit
> args you cannot use that from c code. (the libc
> does not even know which args should be sign or
> zero extended.)

glibc's syscall() prototype has kernel_ulong_t as its arguments (more
specifically, to __syscall_ulong_t, which is 64-bit wide on x32; it
should also have kernel_long_t as its return type instead of long,
but that's another story), so it works perfectly fine in case of x32.

> process_vm_readv/writev is limited by the ilp32
> iovec struct, not by the syscall arguments.

Right, on x32/N32 this issue is worked around by the usage of the respective
x86_64/N64 call, and it looks like another thing that is impossible
with AArch64 ilp32.

> ptrace is specified to take void* addr argument,
> and void* is 32bit on all ilp32 targets.
> so again on the c language level there is no
> way around the 32bit limitation.

Which is an issue.

2018-10-13 02:15:08

by Eugene Syromiatnikov

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

On Wed, Oct 10, 2018 at 04:36:56PM +0100, Catalin Marinas wrote:
> On Wed, Oct 10, 2018 at 04:10:21PM +0200, Eugene Syromiatnikov wrote:
> > I have some questions regarding AArch64 ILP32 implementation for which I
> > failed to find an answer myself:
> > * How ptrace() tracer is supposed to distinguish between ILP32 and LP64
> > tracees? For MIPS N32 and x32 this is possible based on syscall
> > number, but for AArch64 ILP32 I do not see such a sign. There's also
> > ARM_ip is employed for signalling entering/exiting, I wonder whether
> > it's possible to employ it also for signalling tracee's personality.
>
> With the current implementation, I don't think you can distinguish. From
> the kernel perspective, the register set is the same. What is the
> use-case for this?

Err, a ptrace()-based tracer trying to trace a process, for example?

> We could add a new regset to expose the ILP32 state (NT_ARM_..., I can't
> think of a name now but probably not PER* as this implies PER_LINUX_...
> which is independent from TIF_32BIT_*).

So that would require an additional ptrace() call on each syscall stop,
is that correct?

> > * What's the reasoning behind capping syscall arguments to 32 bit? x32
> > and MIPS N32 do not have such a restriction (and do not need special
> > wrappers for syscalls that pass 64-bit values as a result, except
> > when they do, as it is the case for preadv2 on x32); moreover, that
> > would lead to insurmountable difficulties for AArch64 ILP32 tracers
> > that try to trace LP64 tracees, as it would be impossible to pass
> > 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.
>
> We've attempted in earlier versions to allow a mix of 32 and 64-bit
> register values from ILP32 but it got pretty complicated. The entry code
> would need to know which registers need zeroing of the top 32-bit

If kernel specifies 64-bit wide registers for syscalls, then it's the
caller's (libc's) responsibility to properly sign-extend arguments when
needed, and glibc, for example, already has proper type definitions that
aimed to handle this.

> and the generic unistd.h wrapper hacks were not very nice.

They are already implemented in glibc during x32 introduction period.

> Some past discussions:
>
> https://www.mail-archive.com/[email protected]/msg1211716.html
>
> --
> Catalin

2018-10-13 09:20:54

by Catalin Marinas

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

On Sat, Oct 13, 2018 at 04:07:31AM +0200, Eugene Syromiatnikov wrote:
> On Wed, Oct 10, 2018 at 03:39:07PM +0100, Szabolcs Nagy wrote:
> > On 10/10/18 15:10, Eugene Syromiatnikov wrote:
> > > * What's the reasoning behind capping syscall arguments to 32 bit? x32
> > > and MIPS N32 do not have such a restriction (and do not need special
> > > wrappers for syscalls that pass 64-bit values as a result, except
> > > when they do, as it is the case for preadv2 on x32); moreover, that
> > > would lead to insurmountable difficulties for AArch64 ILP32 tracers
> > > that try to trace LP64 tracees, as it would be impossible to pass
> > > 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.
> >
> > but that's necessarily the case for all ilp32 abis:
> > the userspace syscall function receives 32bit
> > arguments so even if the kernel abi takes 64bit
> > args you cannot use that from c code. (the libc
> > does not even know which args should be sign or
> > zero extended.)
>
> glibc's syscall() prototype has kernel_ulong_t as its arguments (more
> specifically, to __syscall_ulong_t, which is 64-bit wide on x32; it
> should also have kernel_long_t as its return type instead of long,
> but that's another story), so it works perfectly fine in case of x32.

This would have been my preferred approach but the libc community were
not entirely happy with it as it breaks POSIX compatibility:

https://sourceware.org/bugzilla/show_bug.cgi?id=16437
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-February/323348.html

(there are other threads around x32 and people arguing whether POSIX is
wrong)

Some sometime around version 4 or 5 of this series, we made the move
(back) to compat-like ABI.

--
Catalin

2018-10-13 09:36:32

by Catalin Marinas

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

On Sat, Oct 13, 2018 at 04:14:16AM +0200, Eugene Syromiatnikov wrote:
> On Wed, Oct 10, 2018 at 04:36:56PM +0100, Catalin Marinas wrote:
> > On Wed, Oct 10, 2018 at 04:10:21PM +0200, Eugene Syromiatnikov wrote:
> > > I have some questions regarding AArch64 ILP32 implementation for which I
> > > failed to find an answer myself:
> > > * How ptrace() tracer is supposed to distinguish between ILP32 and LP64
> > > tracees? For MIPS N32 and x32 this is possible based on syscall
> > > number, but for AArch64 ILP32 I do not see such a sign. There's also
> > > ARM_ip is employed for signalling entering/exiting, I wonder whether
> > > it's possible to employ it also for signalling tracee's personality.
> >
> > With the current implementation, I don't think you can distinguish. From
> > the kernel perspective, the register set is the same. What is the
> > use-case for this?
>
> Err, a ptrace()-based tracer trying to trace a process, for example?

I first thought it wouldn't matter for ptrace-based tracers since the
syscall numbers are (mostly) the same. But the arguments layout in
register is indeed different, so I see your point now about having to
distinguish.

> > We could add a new regset to expose the ILP32 state (NT_ARM_..., I can't
> > think of a name now but probably not PER* as this implies PER_LINUX_...
> > which is independent from TIF_32BIT_*).
>
> So that would require an additional ptrace() call on each syscall stop,
> is that correct?

The ILP32 state does not change at run-time, so it could only do a
ptrace() call once and save the information. No need to re-read it on
each syscall stop.

We could set a high bit in the syscall number reported to the ptrace
caller (though not changing the syscall ABI) but I haven't thought of
other consequences. For example, can the ptrace caller change the
syscall number?

> > > * What's the reasoning behind capping syscall arguments to 32 bit? x32
> > > and MIPS N32 do not have such a restriction (and do not need special
> > > wrappers for syscalls that pass 64-bit values as a result, except
> > > when they do, as it is the case for preadv2 on x32); moreover, that
> > > would lead to insurmountable difficulties for AArch64 ILP32 tracers
> > > that try to trace LP64 tracees, as it would be impossible to pass
> > > 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.
> >
> > We've attempted in earlier versions to allow a mix of 32 and 64-bit
> > register values from ILP32 but it got pretty complicated. The entry code
> > would need to know which registers need zeroing of the top 32-bit
>
> If kernel specifies 64-bit wide registers for syscalls, then it's the
> caller's (libc's) responsibility to properly sign-extend arguments when
> needed, and glibc, for example, already has proper type definitions that
> aimed to handle this.

We tried, see my other reply.

--
Catalin

2018-10-13 13:43:53

by Yury Norov

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

On Sat, Oct 13, 2018 at 10:34:11AM +0100, Catalin Marinas wrote:
>
> Lines: 73
>
> External Email
>
> On Sat, Oct 13, 2018 at 04:14:16AM +0200, Eugene Syromiatnikov wrote:
> > On Wed, Oct 10, 2018 at 04:36:56PM +0100, Catalin Marinas wrote:
> > > On Wed, Oct 10, 2018 at 04:10:21PM +0200, Eugene Syromiatnikov wrote:
> > > > I have some questions regarding AArch64 ILP32 implementation for which I
> > > > failed to find an answer myself:
> > > > * How ptrace() tracer is supposed to distinguish between ILP32 and LP64
> > > > tracees? For MIPS N32 and x32 this is possible based on syscall
> > > > number, but for AArch64 ILP32 I do not see such a sign. There's also
> > > > ARM_ip is employed for signalling entering/exiting, I wonder whether
> > > > it's possible to employ it also for signalling tracee's personality.
> > >
> > > With the current implementation, I don't think you can distinguish. From
> > > the kernel perspective, the register set is the same. What is the
> > > use-case for this?
> >
> > Err, a ptrace()-based tracer trying to trace a process, for example?
>
> I first thought it wouldn't matter for ptrace-based tracers since the
> syscall numbers are (mostly) the same. But the arguments layout in
> register is indeed different, so I see your point now about having to
> distinguish.
>
> > > We could add a new regset to expose the ILP32 state (NT_ARM_..., I can't
> > > think of a name now but probably not PER* as this implies PER_LINUX_...
> > > which is independent from TIF_32BIT_*).
> >
> > So that would require an additional ptrace() call on each syscall stop,
> > is that correct?
>
> The ILP32 state does not change at run-time, so it could only do a
> ptrace() call once and save the information. No need to re-read it on
> each syscall stop.
>
> We could set a high bit in the syscall number reported to the ptrace
> caller (though not changing the syscall ABI) but I haven't thought of
> other consequences. For example, can the ptrace caller change the
> syscall number?

I believe, /proc/PID/auxv is enough to distinguish between arm64, ilp32
and aarch32 ABis. If no, I think it's better to do it there.

I don't have ILP32 machine available at the moment, but I'll check it soon.

> > > > * What's the reasoning behind capping syscall arguments to 32 bit? x32
> > > > and MIPS N32 do not have such a restriction (and do not need special
> > > > wrappers for syscalls that pass 64-bit values as a result, except
> > > > when they do, as it is the case for preadv2 on x32); moreover, that
> > > > would lead to insurmountable difficulties for AArch64 ILP32 tracers
> > > > that try to trace LP64 tracees, as it would be impossible to pass
> > > > 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.
> > >
> > > We've attempted in earlier versions to allow a mix of 32 and 64-bit
> > > register values from ILP32 but it got pretty complicated. The entry code
> > > would need to know which registers need zeroing of the top 32-bit
> >
> > If kernel specifies 64-bit wide registers for syscalls, then it's the
> > caller's (libc's) responsibility to properly sign-extend arguments when
> > needed, and glibc, for example, already has proper type definitions that
> > aimed to handle this.
>
> We tried, see my other reply.

A couple of links to recall the story:
https://www.spinics.net/lists/linux-s390/msg11593.html
http://linux-kernel.2935.n7.nabble.com/RFC6-PATCH-v6-00-21-ILP32-for-ARM64-td1345105.html

Cover-letter of the series has links to previous discussions.

I would also notice that even if we pass 64-bit parameters in a single
register, we cannot avoid using the compat layer. It looks more natural
not to split the 64-bit register, but from performance point of view
there is almost no difference, either we split registers or not (2.6%
for empty syscall, as I measured). And the cost of overcomplication was
considered too much. So we chose to stick to more standard compat layer
and gain in maintainability.

Yury


2018-10-13 16:55:36

by Andy Lutomirski

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

> On Oct 13, 2018, at 2:34 AM, Catalin Marinas <[email protected]> wrote:
>
>> On Sat, Oct 13, 2018 at 04:14:16AM +0200, Eugene Syromiatnikov wrote:
>>> On Wed, Oct 10, 2018 at 04:36:56PM +0100, Catalin Marinas wrote:
>>>> On Wed, Oct 10, 2018 at 04:10:21PM +0200, Eugene Syromiatnikov wrote:
>>>> I have some questions regarding AArch64 ILP32 implementation for which I
>>>> failed to find an answer myself:
>>>> * How ptrace() tracer is supposed to distinguish between ILP32 and LP64
>>>> tracees? For MIPS N32 and x32 this is possible based on syscall
>>>> number, but for AArch64 ILP32 I do not see such a sign. There's also
>>>> ARM_ip is employed for signalling entering/exiting, I wonder whether
>>>> it's possible to employ it also for signalling tracee's personality.
>>>
>>> With the current implementation, I don't think you can distinguish. From
>>> the kernel perspective, the register set is the same. What is the
>>> use-case for this?
>>
>> Err, a ptrace()-based tracer trying to trace a process, for example?
>
> I first thought it wouldn't matter for ptrace-based tracers since the
> syscall numbers are (mostly) the same. But the arguments layout in
> register is indeed different, so I see your point now about having to
> distinguish.
>
>>> We could add a new regset to expose the ILP32 state (NT_ARM_..., I can't
>>> think of a name now but probably not PER* as this implies PER_LINUX_...
>>> which is independent from TIF_32BIT_*).
>>
>> So that would require an additional ptrace() call on each syscall stop,
>> is that correct?
>
> The ILP32 state does not change at run-time, so it could only do a
> ptrace() call once and save the information. No need to re-read it on
> each syscall stop.
>

Please solve this in an arch independent way. This situation is
basically unusably broken on x86 right now. Please solve it for real,
by, for example, adding a new ptrace operation that returns something
like this:

enum ptrace_syscall_state {
NO_SYSCALL,
SYSCALL_ENTRY,
SYSCALL_EXIT,
/* other values may be defined in the future. */
};

struct ptrace_syscall_info {
enum ptrace_syscall_state state;
unsigned long arch;
union {
struct {
unsigned long nr;
unsigned long args[6];
} entry;
struct {
unsigned long ret;
} exit;
};

where arch is an AUDIT_ARCH_XYZ constant.

On x86, it's currently essentially impossible for tools like strace to
correctly decode syscalls.

> We could set a high bit in the syscall number reported to the ptrace
> caller (though not changing the syscall ABI) but I haven't thought of
> other consequences. For example, can the ptrace caller change the
> syscall number?

Yes it can.

>
>>>> * What's the reasoning behind capping syscall arguments to 32 bit? x32
>>>> and MIPS N32 do not have such a restriction (and do not need special
>>>> wrappers for syscalls that pass 64-bit values as a result, except
>>>> when they do, as it is the case for preadv2 on x32); moreover, that
>>>> would lead to insurmountable difficulties for AArch64 ILP32 tracers
>>>> that try to trace LP64 tracees, as it would be impossible to pass
>>>> 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.
>>>
>>> We've attempted in earlier versions to allow a mix of 32 and 64-bit
>>> register values from ILP32 but it got pretty complicated. The entry code
>>> would need to know which registers need zeroing of the top 32-bit
>>
>> If kernel specifies 64-bit wide registers for syscalls, then it's the
>> caller's (libc's) responsibility to properly sign-extend arguments when
>> needed, and glibc, for example, already has proper type definitions that
>> aimed to handle this.
>
> We tried, see my other reply.
>
> --
> Catalin

2018-10-13 19:38:07

by Andy Lutomirski

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

On Wed, May 16, 2018 at 1:19 AM Yury Norov <[email protected]> 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.

A few thoughts:

1. I've never been able to shake the feeling that x32 should not need
kernel support at all. As far as I can tell, the kernel support is an
enormous amount of code and complexity to deal with exactly two
issues. First, ILP32 only has 32-bit pointers, so there needs to be a
way to tell the kernel to only use the lower 4 GB of user address
space. That part is easy. Second, ILP32 user code is highly unlikely
to end up with the same struct layout as ILP64 code. The latter seems
like it should be solved entirely in userspace by adding a way to
annotate a structure as being a kernel ABI structure and getting the
toolchain to lay it out as if it were ILP64 even though the target is
ILP32.

2. I think you should make a conscious decision as to whether the
ILP32-ness of a syscall is a property of the task or of the syscall.
On x86, x32-ness is a property of the syscall, but historically it
also got rather entangled with the state of the task, and the result
was a mess. It looks like you're making it be a property of the task,
which is fine, but you're making it impossible for very clever ILP32
libraries to include little ILP64 stubs that do fancy things with full
64-bit syscalls.

3. Make very certain that you aren't exploitable by malicious
processes that set the high bits in ILP32 syscall args. x86 compat
has issues like that in the past.

2018-10-14 19:50:58

by Arnd Bergmann

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

On Sat, Oct 13, 2018 at 9:36 PM Andy Lutomirski <[email protected]> wrote:
>
> On Wed, May 16, 2018 at 1:19 AM Yury Norov <[email protected]> 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.
>
> Second, ILP32 user code is highly unlikely
> to end up with the same struct layout as ILP64 code. The latter seems
> like it should be solved entirely in userspace by adding a way to
> annotate a structure as being a kernel ABI structure and getting the
> toolchain to lay it out as if it were ILP64 even though the target is
> ILP32.

The syscall ABI could be almost completely abstracted in glibc, the
main issue is ioctl and a couple of related interfaces that pass data
structures (read() on /dev/input/*, mmap on /dev/snd/*
or raw sockets, fcntl).

The question whether a data type is laid out like a 64-bit architecture
would cannot be a property of the type in most of those cases,
because the same types are used elsewhere. Many ioctls just
take a pointer to a 'long' or similar, and then you have structures
like 'timespec' that are used both in syscall/ioctl ABI and in normal
user space code, but are required to be laid out differently there.
(timespec is a bad example because y2038 of course, but it
illustrates the point).

> 2. I think you should make a conscious decision as to whether the
> ILP32-ness of a syscall is a property of the task or of the syscall.
> On x86, x32-ness is a property of the syscall, but historically it
> also got rather entangled with the state of the task, and the result
> was a mess. It looks like you're making it be a property of the task,
> which is fine, but you're making it impossible for very clever ILP32
> libraries to include little ILP64 stubs that do fancy things with full
> 64-bit syscalls.
>
> 3. Make very certain that you aren't exploitable by malicious
> processes that set the high bits in ILP32 syscall args. x86 compat
> has issues like that in the past.

This point was actually the most important one for keeping the
aarch64 ilp32 interface as restricted as it is: it doesn't allow
anything that the normal aarch32/armv7 emulation doesn't
already provide.

Arnd

2018-10-14 19:54:16

by Arnd Bergmann

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

On Sat, Oct 13, 2018 at 4:07 AM Eugene Syromiatnikov <[email protected]> wrote:
>
> On Wed, Oct 10, 2018 at 03:39:07PM +0100, Szabolcs Nagy wrote:
> > On 10/10/18 15:10, Eugene Syromiatnikov wrote:
> > > * What's the reasoning behind capping syscall arguments to 32 bit? x32
> > > and MIPS N32 do not have such a restriction (and do not need special
> > > wrappers for syscalls that pass 64-bit values as a result, except
> > > when they do, as it is the case for preadv2 on x32); moreover, that
> > > would lead to insurmountable difficulties for AArch64 ILP32 tracers
> > > that try to trace LP64 tracees, as it would be impossible to pass
> > > 64-bit addresses to process_vm_{read,write} or ptrace PEEK/POKE.
> >
> > but that's necessarily the case for all ilp32 abis:
> > the userspace syscall function receives 32bit
> > arguments so even if the kernel abi takes 64bit
> > args you cannot use that from c code. (the libc
> > does not even know which args should be sign or
> > zero extended.)
>
> glibc's syscall() prototype has kernel_ulong_t as its arguments (more
> specifically, to __syscall_ulong_t, which is 64-bit wide on x32; it
> should also have kernel_long_t as its return type instead of long,
> but that's another story), so it works perfectly fine in case of x32.
>
> > process_vm_readv/writev is limited by the ilp32
> > iovec struct, not by the syscall arguments.
>
> Right, on x32/N32 this issue is worked around by the usage of the respective
> x86_64/N64 call, and it looks like another thing that is impossible
> with AArch64 ilp32.
>
> > ptrace is specified to take void* addr argument,
> > and void* is 32bit on all ilp32 targets.
> > so again on the c language level there is no
> > way around the 32bit limitation.
>
> Which is an issue.

I have no idea why you think this is a problem specific to aarch64-ilp32:
If we want to be able to debug 64-bit tasks from a 32-bit task on any
architecture that has compat mode, we should solve it once and
extend the ptrace interface to allow it on *all* of them. We certainly
don't need /more/ special cases for the x32 hack, there should really
be fewer of them.

Arnd

2018-10-18 11:15:28

by Catalin Marinas

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

On Sun, Oct 14, 2018 at 09:49:01PM +0200, Arnd Bergmann wrote:
> On Sat, Oct 13, 2018 at 9:36 PM Andy Lutomirski <[email protected]> wrote:
> >
> > On Wed, May 16, 2018 at 1:19 AM Yury Norov <[email protected]> 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.
> >
> > Second, ILP32 user code is highly unlikely
> > to end up with the same struct layout as ILP64 code. The latter seems
> > like it should be solved entirely in userspace by adding a way to
> > annotate a structure as being a kernel ABI structure and getting the
> > toolchain to lay it out as if it were ILP64 even though the target is
> > ILP32.
>
> The syscall ABI could be almost completely abstracted in glibc, the
> main issue is ioctl and a couple of related interfaces that pass data
> structures (read() on /dev/input/*, mmap on /dev/snd/*
> or raw sockets, fcntl).

There is another case on struct siginfo which has some pointers and it
wouldn't look like an LP64 structure at all (and glibc doesn't normally
intercept the sighandler call to rewrite the structure). We could add
padding around void * members as the kernel zeros them, I don't recall
the kernel reading these pointers from user. Anyway, using something
that resembles compat_siginfo looked the simplest for ILP32.

--
Catalin

2018-11-19 21:31:17

by Yury Norov

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

Hi all,

On Wed, May 16, 2018 at 11:18:45AM +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.
> - Zhou Chengming's reported-by for patch 2 and signed-off-by for
> patch 21 removed because his email became invalid. Zhou, please
> share your new email.

This is the 4.19-based update:
https://github.com/norov/linux/tree/ilp32-4.19

Syscall machinery is rewritten in C in mainline kernel, ILP32 is aligned
with it. The following patches are mostly affected:

arm64: ilp32: introduce ilp32-specific sigframe and ucontext
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: signal: share lp64 signal structures and routines to ilp32
arm64: ilp32: introduce syscall table for ILP32
arm64: ilp32: share aarch32 syscall handlers

4.18 branch from Catalin is here:
https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=staging/ilp32-4.18

Yury

2019-01-07 16:41:03

by Yuri Norov

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

Hi all,

On Wed, May 16, 2018 at 11:18:45AM +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.
> - Zhou Chengming's reported-by for patch 2 and signed-off-by for
> patch 21 removed because his email became invalid. Zhou, please
> share your new email.

This is 4.20-based version.
https://github.com/norov/linux/tree/ilp32-4.20

There's no important changes comparing to 4.19, but I would like to remind
that this series contains some generic arch patches that ACKed, but still
not upstreamed:
Yury Norov asm-generic: Drop getrlimit and setrlimit syscalls from default list
Yury Norov 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option
Yury Norov compat ABI: use non-compat openat and open_by_handle_at variants
James Morse ptrace: Add compat PTRACE_{G,S}ETSIGMASK handlers
Dave Martin arm64: signal: Make parse_user_sigframe() independent of rt_sigframe layout

Please also notice that my email address is changed, from now it's
[email protected]

Yury

2019-01-07 21:12:25

by Yuri Norov

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

On Mon, Jan 07, 2019 at 09:48:44AM -0800, Andy Lutomirski wrote:
>
>
> > On Jan 7, 2019, at 7:50 AM, Yuri Norov <[email protected]> wrote:
> >
> > Hi all,
> >
> >> On Wed, May 16, 2018 at 11:18:45AM +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.
> >> - Zhou Chengming's reported-by for patch 2 and signed-off-by for
> >> patch 21 removed because his email became invalid. Zhou, please
> >> share your new email.
> >
> > This is 4.20-based version.
> > https://github.com/norov/linux/tree/ilp32-4.20
> >
> > There's no important changes comparing to 4.19, but I would like to remind
> > that this series contains some generic arch patches that ACKed, but still
> > not upstreamed:
> > Yury Norov asm-generic: Drop getrlimit and setrlimit syscalls from default list
> > Yury Norov 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option
> > Yury Norov compat ABI: use non-compat openat and open_by_handle_at variants
> > James Morse ptrace: Add compat PTRACE_{G,S}ETSIGMASK handlers
> > Dave Martin arm64: signal: Make parse_user_sigframe() independent of rt_sigframe layout
> >
> > Please also notice that my email address is changed, from now it's
> > [email protected]
> >
>
> Having spent some time hating x32 lately, here is a cursory review:

I followed the recent discussion on x32 drop, but I don't track the story
from the beginning. Can you summarize your complains here (or maybe in
patch for Documentation)? It will be good for ilp32 because we will check
the series against all possible problems, and it will be good for history
because future compat architectures developers will be aware.

On your following questions, I'll try answer according to my understanding.
If it's wrong or incomplete, I kindly ask others fix me.

> You say “ILP32 has context-related structures different from both aarch32 and
> aarch64/lp64.” Why? Why not just use the lp64 context structure?

Because the alternative is nothing better than how we do now. We can make
rt_sigframe for ilp32 look exactly like lp64. But on user side we will
have to add pads therefore. On the kernel side, before passing rt_sigframe
to kernel, we will have to make sure that pads are zeroed, just like we do
with x0-x7 in delouse_pt_regs() before passing syscall arguments to handlers.
So we cannot get rid of get/set_sigframe() converters in this case.

Current approach lets us keep user part looking more natural, and on
kernel side we don't add complexity because we reuse existing aarch32
or existing lp64 handlers, and don't invent something new.

> Do you have some objection to letting greg_t be a u64 on ilp32?

In binfmt_ilp32.c we
#define compat_elf_gregset_t elf_gregset_t
So in fact we use 64-bit gregset. Or I misunderstood you?

> Since you can’t tell LP64 and ILP32 syscalls apart by number, you need to add
> and wire up a new AUDIT_ARCH value for ILP32. syscall_get_arch() needs to work correctly.

Thanks for pointing to this. I'll append AUDIT_ARCH patch to this series.

Yury

2019-01-08 22:54:38

by Yuri Norov

[permalink] [raw]
Subject: [PATCH] arm64: introduce AUDIT_ARCH_AARCH64ILP32 for ilp32

Make syscall_get_arch() distinguish arm64 and arm64/ilp32 by adding
AUDIT_ARCH_AARCH64ILP32.

Sugested-by: Andy Lutomirski <[email protected]>
Signed-off-by: Yury Norov <[email protected]>
---
arch/arm64/include/asm/syscall.h | 3 +++
include/uapi/linux/audit.h | 1 +
2 files changed, 4 insertions(+)

diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 73fbe08763b0..77578d703cb1 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -126,6 +126,9 @@ static inline int syscall_get_arch(void)
if (is_a32_compat_task())
return AUDIT_ARCH_ARM;

+ if (is_ilp32_compat_task())
+ return AUDIT_ARCH_AARCH64ILP32;
+
return AUDIT_ARCH_AARCH64;
}

diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 818ae690ab79..624127147404 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -374,6 +374,7 @@ enum {
#define __AUDIT_ARCH_LE 0x40000000

#define AUDIT_ARCH_AARCH64 (EM_AARCH64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_AARCH64ILP32 (EM_AARCH64|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_ALPHA (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_ARMEB (EM_ARM)
--
2.17.1


2019-03-05 20:57:33

by Yury Norov

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

On Wed, May 16, 2018 at 11:18:45AM +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.
> - Zhou Chengming's reported-by for patch 2 and signed-off-by for
> patch 21 removed because his email became invalid. Zhou, please
> share your new email.

Hi all,

This is the 5.0-based version.
https://github.com/norov/linux/tree/ilp32-5.0

Since 4.20:
- all new files are consistently GPL2.0-licensed;
- AUDIT_ARCH_AARCH64ILP32 added to let syscall_get_arch()
differentiate ARM64/ILP32 from ARM64/ILP32.

Yury

2019-05-08 23:10:08

by Yury Norov

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

Hi all,

On Wed, May 16, 2018 at 11:18:45AM +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

This is the 5.1-based version.
Changes comparing to 5.0:
- drop arch patches that has been taken upstream:
80d7da1cac62 asm-generic: Drop getrlimit and setrlimit syscalls from default list
942fa985e9f1 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option
0d0216c03a7a compat ABI: use non-compat openat and open_by_handle_at variants
- in include/linux/thread_bits.h define current_thread_info() prior to
inclusion of asm/thread_info.h, to avoid circullar dependencies (thread: move
thread bits accessors to separated file);
- enable old IPC interfaces for ilp32, according to mainline changes
(arm64: ilp32: introduce syscall table for ILP32).

Thanks,
Yury

2019-05-08 23:13:43

by Yury Norov

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

On Wed, May 08, 2019 at 03:59:00PM -0700, Yury Norov wrote:
> Hi all,
>
> On Wed, May 16, 2018 at 11:18:45AM +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
>
> This is the 5.1-based version.
> Changes comparing to 5.0:
> - drop arch patches that has been taken upstream:
> 80d7da1cac62 asm-generic: Drop getrlimit and setrlimit syscalls from default list
> 942fa985e9f1 32-bit userspace ABI: introduce ARCH_32BIT_OFF_T config option
> 0d0216c03a7a compat ABI: use non-compat openat and open_by_handle_at variants
> - in include/linux/thread_bits.h define current_thread_info() prior to
> inclusion of asm/thread_info.h, to avoid circullar dependencies (thread: move
> thread bits accessors to separated file);
> - enable old IPC interfaces for ilp32, according to mainline changes
> (arm64: ilp32: introduce syscall table for ILP32).

Missed link:
https://github.com/norov/linux/tree/ilp32-5.1

>
> Thanks,
> Yury

2019-05-13 09:15:02

by Andreas Schwab

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

There is a problem with the stack size accounting during execve when
there is no stack limit:

$ ulimit -s
8192
$ ./hello.ilp32
Hello World!
$ ulimit -s unlimited
$ ./hello.ilp32
Segmentation fault
$ strace ./hello.ilp32
execve("./hello.ilp32", ["./hello.ilp32"], 0xfffff10548f0 /* 77 vars */) = -1 ENOMEM (Cannot allocate memory)
+++ killed by SIGSEGV +++
Segmentation fault (core dumped)

Andreas.

--
Andreas Schwab, SUSE Labs, [email protected]
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

2019-05-13 20:22:11

by Yuri Norov

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

+ [email protected]

> There is a problem with the stack size accounting during execve when
> there is no stack limit:
>
> $ ulimit -s
> 8192
> $ ./hello.ilp32
> Hello World!
> $ ulimit -s unlimited
> $ ./hello.ilp32
> Segmentation fault
> $ strace ./hello.ilp32
> execve("./hello.ilp32", ["./hello.ilp32"], 0xfffff10548f0 /* 77 vars */) = -1 ENOMEM (Cannot allocate memory)
> +++ killed by SIGSEGV +++
> Segmentation fault (core dumped)
>
> Andreas.

Thanks Andreas, I will take a look. Do we have such test in LTP?

Yury

2019-05-14 10:44:56

by Cyril Hrubis

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

Hi!
> > There is a problem with the stack size accounting during execve when
> > there is no stack limit:
> >
> > $ ulimit -s
> > 8192
> > $ ./hello.ilp32
> > Hello World!
> > $ ulimit -s unlimited
> > $ ./hello.ilp32
> > Segmentation fault
> > $ strace ./hello.ilp32
> > execve("./hello.ilp32", ["./hello.ilp32"], 0xfffff10548f0 /* 77 vars */) = -1 ENOMEM (Cannot allocate memory)
> > +++ killed by SIGSEGV +++
> > Segmentation fault (core dumped)
> >
> > Andreas.
>
> Thanks Andreas, I will take a look. Do we have such test in LTP?

We do have a test that we can run a binary with very small stack size
i.e. 512kB but there does not seem to be anything that would catch this
specific problem.

Can you please open an issue and describe how to reproduce the problem
at our github tracker:

https://github.com/linux-test-project/ltp/issues

Then we can create testcase based on that reproducer later on.

--
Cyril Hrubis
[email protected]

2019-05-14 23:06:48

by Yury Norov

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

On Tue, May 14, 2019 at 12:43:11PM +0200, Cyril Hrubis wrote:
> Hi!
> > > There is a problem with the stack size accounting during execve when
> > > there is no stack limit:
> > >
> > > $ ulimit -s
> > > 8192
> > > $ ./hello.ilp32
> > > Hello World!
> > > $ ulimit -s unlimited
> > > $ ./hello.ilp32
> > > Segmentation fault
> > > $ strace ./hello.ilp32
> > > execve("./hello.ilp32", ["./hello.ilp32"], 0xfffff10548f0 /* 77 vars */) = -1 ENOMEM (Cannot allocate memory)
> > > +++ killed by SIGSEGV +++
> > > Segmentation fault (core dumped)
> > >
> > > Andreas.
> >
> > Thanks Andreas, I will take a look. Do we have such test in LTP?

So the problem was in not converting new compat-sensitive code:

diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 5bdf357169d8..c509f83fa506 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -63,7 +63,7 @@
TASK_SIZE_32 : TASK_SIZE_64)
#define TASK_SIZE_OF(tsk) (is_compat_thread(tsk) ? \
TASK_SIZE_32 : TASK_SIZE_64)
-#define DEFAULT_MAP_WINDOW (test_thread_flag(TIF_32BIT) ? \
+#define DEFAULT_MAP_WINDOW (is_compat_task() ? \
TASK_SIZE_32 : DEFAULT_MAP_WINDOW_64)
#else
#define TASK_SIZE TASK_SIZE_64

The fix is incorporated in ilp32-5.1.1:
https://github.com/norov/linux/tree/ilp32-5.1.1

> We do have a test that we can run a binary with very small stack size
> i.e. 512kB but there does not seem to be anything that would catch this
> specific problem.
>
> Can you please open an issue and describe how to reproduce the problem
> at our github tracker:
>
> https://github.com/linux-test-project/ltp/issues
>
> Then we can create testcase based on that reproducer later on.
>
> --
> Cyril Hrubis
> [email protected]

OK, I'll do.

Yury

2019-05-14 23:45:04

by Yury Norov

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

On Tue, May 14, 2019 at 12:43:11PM +0200, Cyril Hrubis wrote:
> Hi!
> > > There is a problem with the stack size accounting during execve when
> > > there is no stack limit:
> > >
> > > $ ulimit -s
> > > 8192
> > > $ ./hello.ilp32
> > > Hello World!
> > > $ ulimit -s unlimited
> > > $ ./hello.ilp32
> > > Segmentation fault
> > > $ strace ./hello.ilp32
> > > execve("./hello.ilp32", ["./hello.ilp32"], 0xfffff10548f0 /* 77 vars */) = -1 ENOMEM (Cannot allocate memory)
> > > +++ killed by SIGSEGV +++
> > > Segmentation fault (core dumped)
> > >
> > > Andreas.
> >
> > Thanks Andreas, I will take a look. Do we have such test in LTP?
>
> We do have a test that we can run a binary with very small stack size
> i.e. 512kB but there does not seem to be anything that would catch this
> specific problem.
>
> Can you please open an issue and describe how to reproduce the problem
> at our github tracker:
>
> https://github.com/linux-test-project/ltp/issues
>
> Then we can create testcase based on that reproducer later on.

This is it:
https://github.com/linux-test-project/ltp/issues/530

Yury

2019-07-09 22:48:09

by Yury Norov

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

Hi all,

On Wed, May 16, 2018 at 11:18:45AM +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.
> - Zhou Chengming's reported-by for patch 2 and signed-off-by for
> patch 21 removed because his email became invalid. Zhou, please
> share your new email.

This is a 5.2-based version of series.
https://github.com/norov/linux/tree/ilp32-5.2

Thanks,
Yury