Skip to contentSkip to conversation

ILP32 for ARM64

RFC PATCH Superseded Yury Norov 6 participants 44 messages Jun 17, 2016 – Aug 29, 2016

Subsystems (25)

v7 of 9 Superseded Latest is v9 →

lore
Share & tools
lore

Yury Norov

author
#0 lore raw

v7 cover ILP32 for ARM64

This series enables aarch64 with ilp32 mode, and as supporting work, 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 is is used by new userspace).

This version is based on kernel v4.7-rc3.
It works with glibc-2.23, and tested with LTP.

This is RFC because there is no solid understanding what type of registers top-halves delousing we prefer. In this patchset, w0-w7 are cleared for each syscall in assembler entry. The alternative approach is in introducing compat wrappers which is little faster for natively routed syscalls (~2.6% for syscall with no payload) but much more complicated.

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: RFC nowrap:
- wrappers removed, unconditional register delousing is introduced.
- ino_t, off_t etc are turned to 64-bit.
- added is_compat_thread(),
- fixed ilp32 ELF_PLATFORM MACRO,
- fixed ilp32 ELF_DYN_BASE,
- ptrace redirected to compat version.
- stat, statfs - related syscalls are redirected to native handlers.
- elf_greg_t and elf_gregset_t types are taken from lp64.
- Documentation updated.

Links:
This series: https://github.com/norov/linux/commits/ilp32-nowrap
v7 with wrappers: https://github.com/norov/linux/commits/ilp32
glibc (dirty): https://github.com/norov/glibc/commits/ilp32-nowrap
glibc with wrappers: https://github.com/norov/glibc/commits/ilp32-dev

Andrew Pinski (6):
arm64: ensure the kernel is compiled for LP64
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: introduce ilp32-specific handlers for sigframe and ucontext arm64:ilp32: add ARM64_ILP32 to Kconfig

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

Yury Norov (12):
compat ABI: use non-compat openat and open_by_handle_at variants 32-bit ABI: introduce ARCH_32BIT_OFF_T config option
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
thread: move thread bits accessors to separated file
arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
arm64: introduce binfmt_elf32.c
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
arm64: ilp32: share aarch32 syscall handlers
arm64: signal: share lp64 signal routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file

 Documentation/arm64/ilp32.txt                 |  54 +++++++
 arch/Kconfig                                  |   4 +
 arch/arc/Kconfig                              |   1 +
 arch/arm/Kconfig                              |   1 +
 arch/arm64/Kconfig                            |  19 ++-
 arch/arm64/Makefile                           |   5 +
 arch/arm64/include/asm/compat.h               |  19 +--
 arch/arm64/include/asm/elf.h                  |  29 +++-
 arch/arm64/include/asm/fpsimd.h               |   2 +-
 arch/arm64/include/asm/ftrace.h               |   2 +-
 arch/arm64/include/asm/hwcap.h                |   6 +-
 arch/arm64/include/asm/is_compat.h            |  90 ++++++++++++
 arch/arm64/include/asm/memory.h               |   5 +-
 arch/arm64/include/asm/processor.h            |  11 +-
 arch/arm64/include/asm/ptrace.h               |   2 +-
 arch/arm64/include/asm/signal32.h             |   6 +-
 arch/arm64/include/asm/signal32_common.h      |  25 ++++
 arch/arm64/include/asm/signal_common.h        |  33 +++++
 arch/arm64/include/asm/signal_ilp32.h         |  34 +++++
 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/unistd32.h             |   2 +-
 arch/arm64/include/asm/vdso.h                 |   6 +
 arch/arm64/include/uapi/asm/bitsperlong.h     |   9 +-
 arch/arm64/kernel/Makefile                    |  14 +-
 arch/arm64/kernel/asm-offsets.c               |   9 +-
 arch/arm64/kernel/binfmt_elf32.c              |  31 ++++
 arch/arm64/kernel/binfmt_ilp32.c              |  96 +++++++++++++
 arch/arm64/kernel/cpufeature.c                |   8 +-
 arch/arm64/kernel/cpuinfo.c                   |  20 +--
 arch/arm64/kernel/entry.S                     |  35 ++++-
 arch/arm64/kernel/entry32.S                   |  65 ---------
 arch/arm64/kernel/entry32_common.S            |  93 ++++++++++++
 arch/arm64/kernel/entry_ilp32.S               |  23 +++
 arch/arm64/kernel/head.S                      |   2 +-
 arch/arm64/kernel/hw_breakpoint.c             |  10 +-
 arch/arm64/kernel/perf_regs.c                 |   2 +-
 arch/arm64/kernel/process.c                   |   7 +-
 arch/arm64/kernel/ptrace.c                    |  67 +++++++--
 arch/arm64/kernel/signal.c                    | 102 +++++++++-----
 arch/arm64/kernel/signal32.c                  |  85 -----------
 arch/arm64/kernel/signal32_common.c           | 115 +++++++++++++++
 arch/arm64/kernel/signal_ilp32.c              | 194 ++++++++++++++++++++++++++
 arch/arm64/kernel/sys32.c                     |   1 +
 arch/arm64/kernel/sys_ilp32.c                 |  84 +++++++++++
 arch/arm64/kernel/traps.c                     |   5 +-
 arch/arm64/kernel/vdso-ilp32/.gitignore       |   2 +
 arch/arm64/kernel/vdso-ilp32/Makefile         |  74 ++++++++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S     |  33 +++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S |  95 +++++++++++++
 arch/arm64/kernel/vdso.c                      |  65 +++++++--
 arch/arm64/kernel/vdso/gettimeofday.S         |  20 ++-
 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/tile/kernel/compat.c                     |   3 +
 arch/unicore32/Kconfig                        |   1 +
 arch/x86/Kconfig                              |   1 +
 arch/x86/um/Kconfig                           |   1 +
 arch/xtensa/Kconfig                           |   1 +
 drivers/clocksource/arm_arch_timer.c          |   2 +-
 include/linux/fcntl.h                         |   2 +-
 include/linux/ptrace.h                        |   6 +
 include/linux/thread_bits.h                   |  55 ++++++++
 include/linux/thread_info.h                   |  44 +-----
 kernel/ptrace.c                               |  10 +-
 83 files changed, 1536 insertions(+), 343 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
Signature · 1 line
2.7.4
author
#1 lore raw

PATCH v7 1/19 compat ABI: use non-compat openat and open_by_handle_at variants

The only difference is that non-compat version forces O_LARGEFILE, and it should be the default behaviour for all architectures, as we don't support 32-bit off_t. The only exception is tile32, that continues with compat version of syscalls.

---
 arch/tile/kernel/compat.c | 3 +++
 1 file changed, 3 insertions(+)
arch/tile/kernel/compat.c +3 -0
index 4912084..489ae19 100644
@@ -94,6 +94,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
Signature · 1 line
2.7.4
#2 lore raw

Re: [PATCH 01/19] compat ABI: use non-compat openat and open_by_handle_at variants

Quoted 17 lines · Yury Norov

The only difference is that non-compat version forces O_LARGEFILE, and it should be the default behaviour for all architectures, as we don't support 32-bit off_t. The only exception is tile32, that continues with compat version of syscalls.

---
 arch/tile/kernel/compat.c | 3 +++
 1 file changed, 3 insertions(+)
arch/tile/kernel/compat.c +0 -0
index 4912084..489ae19 100644

arch/tile/kernel/compat.c COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high, · line 102

Quoted 9 lines
arch/tile/kernel/compat.c +3 -0
@@ -94,6 +94,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

This is a no-op. Did you mean to add this? Without that the testsuite of tar fails on ILP32.

include/uapi/asm-generic/unistd.h +2 -3
index a26415b..4dcc38d 100644
@@ -178,7 +178,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
Signature · 9 lines
2.9.0


Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab at suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
author
#3 lore raw

Re: [PATCH 01/19] compat ABI: use non-compat openat and open_by_handle_at variants

Quoted 22 lines · Andreas Schwab
Quoted 20 lines · Yury Norov

The only difference is that non-compat version forces O_LARGEFILE, and it should be the default behaviour for all architectures, as we don't support 32-bit off_t. The only exception is tile32, that continues with compat version of syscalls.

---
 arch/tile/kernel/compat.c | 3 +++
 1 file changed, 3 insertions(+)
arch/tile/kernel/compat.c +0 -0
index 4912084..489ae19 100644
@@ -94,6 +94,9 @@ COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
 #define compat_sys_readahead sys32_readahead
 #define sys_llseek compat_sys_llseek
 
Quoted 9 lines

arch/tile/kernel/compat.c COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high, · line 102

Quoted 6 lines
arch/tile/kernel/compat.c +3 -0
+#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

This is a no-op. Did you mean to add this? Without that the testsuite of tar fails on ILP32.

The change you suggest below is what I originally sent at the end of December, but that chunk was lost after one of numerous rebases probably.

http://lkml.iu.edu/hypermail/linux/kernel/1512.3/00510.html

IIRC, the only difference between this couple of syscalls and their compat versions is that non-compat syscalls set O_LARGEFILE depending on (BITS_PER_LONG != 32). Next patch of this series introduces ARCH_32BIT_OFF_T config option to force O_LARGEFILE for 64-bit arches, and all new 32-bit arches, as ARCH_32BIT_OFF_T is enabled for existing 32-bit arches explicitly.

O_LARGEFILE is controlled like this:

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

So if I restore original patch, everything will work. But my question
is: if ARCH_32BIT_OFF_T disables O_LARGEFILE for tile32 anyway, what for we redirect native syscall handlers to compat ones? They are looking identical...

If my understanding is correct, we can drop the change in arch/tile/kernel/compat.c and join this patch with next one in this series.

Chris, Arnd?

Quoted 34 lines
include/uapi/asm-generic/unistd.h +2 -3
index a26415b..4dcc38d 100644
@@ -178,7 +178,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
Signature · 9 lines
2.9.0


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."
maintainer
#4 lore raw

Re: [PATCH 01/19] compat ABI: use non-compat openat and open_by_handle_at variants

Quoted 45 lines · CEST Yury Norov
Quoted 22 lines · Andreas Schwab
Quoted 20 lines · Yury Norov

The only difference is that non-compat version forces O_LARGEFILE, and it should be the default behaviour for all architectures, as we don't support 32-bit off_t. The only exception is tile32, that continues with compat version of syscalls.

---
 arch/tile/kernel/compat.c | 3 +++
 1 file changed, 3 insertions(+)
arch/tile/kernel/compat.c +0 -0
index 4912084..489ae19 100644
@@ -94,6 +94,9 @@ COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
 #define compat_sys_readahead sys32_readahead
 #define sys_llseek compat_sys_llseek
 
Quoted 9 lines

arch/tile/kernel/compat.c COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high, · line 102

Quoted 6 lines
arch/tile/kernel/compat.c +3 -0
+#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

This is a no-op. Did you mean to add this? Without that the testsuite of tar fails on ILP32.

The change you suggest below is what I originally sent at the end of December, but that chunk was lost after one of numerous rebases probably.

http://lkml.iu.edu/hypermail/linux/kernel/1512.3/00510.html

IIRC, the only difference between this couple of syscalls and their compat versions is that non-compat syscalls set O_LARGEFILE depending on (BITS_PER_LONG != 32). Next patch of this series introduces ARCH_32BIT_OFF_T config option to force O_LARGEFILE for 64-bit arches, and all new 32-bit arches, as ARCH_32BIT_OFF_T is enabled for existing 32-bit arches explicitly.

Quoted 8 lines

O_LARGEFILE is controlled like this:

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

So if I restore original patch, everything will work. But my question
is: if ARCH_32BIT_OFF_T disables O_LARGEFILE for tile32 anyway, what for we redirect native syscall handlers to compat ones? They are looking identical...

I've lost context here, but let me try to recall what we had discussed in the past:

- native 32-bit architectures are handled using CONFIG_ARCH_32BIT_OFF_T
- native 64-bit architectures keep setting the flag.
- compat 32-bit architectures need special cases, but the only one that exists is tile, which has to keep not setting O_LARGEFILE while new compat architectures (ilp32) should set it.

Quoted 5 lines

If my understanding is correct, we can drop the change in arch/tile/kernel/compat.c and join this patch with next one in this series.

Chris, Arnd?

The change in arch/tile/kernel/compat.c can either come before the below change, or in the same patch, but not later.

Arnd

Quoted 24 lines
Quoted 23 lines
include/uapi/asm-generic/unistd.h +2 -3
index a26415b..4dcc38d 100644
@@ -178,7 +178,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
author
#5 lore raw

Re: [PATCH 01/19] compat ABI: use non-compat openat and open_by_handle_at variants

Quoted 68 lines · Arnd Bergmann
Quoted 45 lines · CEST Yury Norov
Quoted 22 lines · Andreas Schwab
Quoted 20 lines · Yury Norov

The only difference is that non-compat version forces O_LARGEFILE, and it should be the default behaviour for all architectures, as we don't support 32-bit off_t. The only exception is tile32, that continues with compat version of syscalls.

---
 arch/tile/kernel/compat.c | 3 +++
 1 file changed, 3 insertions(+)
arch/tile/kernel/compat.c +0 -0
index 4912084..489ae19 100644
@@ -94,6 +94,9 @@ COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
 #define compat_sys_readahead sys32_readahead
 #define sys_llseek compat_sys_llseek
 
Quoted 9 lines

arch/tile/kernel/compat.c COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high, · line 102

Quoted 6 lines
arch/tile/kernel/compat.c +3 -0
+#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

This is a no-op. Did you mean to add this? Without that the testsuite of tar fails on ILP32.

The change you suggest below is what I originally sent at the end of December, but that chunk was lost after one of numerous rebases probably.

http://lkml.iu.edu/hypermail/linux/kernel/1512.3/00510.html

IIRC, the only difference between this couple of syscalls and their compat versions is that non-compat syscalls set O_LARGEFILE depending on (BITS_PER_LONG != 32). Next patch of this series introduces ARCH_32BIT_OFF_T config option to force O_LARGEFILE for 64-bit arches, and all new 32-bit arches, as ARCH_32BIT_OFF_T is enabled for existing 32-bit arches explicitly.

Quoted 8 lines

O_LARGEFILE is controlled like this:

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

So if I restore original patch, everything will work. But my question
is: if ARCH_32BIT_OFF_T disables O_LARGEFILE for tile32 anyway, what for we redirect native syscall handlers to compat ones? They are looking identical...

I've lost context here, but let me try to recall what we had discussed in the past:

- native 32-bit architectures are handled using CONFIG_ARCH_32BIT_OFF_T
- native 64-bit architectures keep setting the flag.
- compat 32-bit architectures need special cases, but the only one that exists is tile, which has to keep not setting O_LARGEFILE while new compat architectures (ilp32) should set it.

Quoted 4 lines

If my understanding is correct, we can drop the change in arch/tile/kernel/compat.c and join this patch with next one in this series.

Quoted 6 lines
Quoted 1 line

Chris, Arnd?

The change in arch/tile/kernel/compat.c can either come before the below change, or in the same patch, but not later.

Arnd

Correct, I'll add it to this patch

Quoted 26 lines
Quoted 25 lines
Quoted 24 lines
include/uapi/asm-generic/unistd.h +2 -3
index a26415b..4dcc38d 100644
@@ -178,7 +178,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
author
#6 lore raw

PATCH v7 2/19 32-bit ABI: introduce ARCH_32BIT_OFF_T config option

In reply to Yury Norov

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

To handle it, new config option is added to arch/Kconfig that defaults ARCH_32BIT_OFF_T to be disabled for non-64 bit architectures. All existing 32-bit architectures enable it explicitly here.

New option affects force_o_largefile() behaviour. Namely, if 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.

---
 arch/Kconfig            | 4 ++++
 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, 30 insertions(+), 1 deletion(-)
arch/Kconfig +4 -0
index d794384..fdfc4ad 100644
@@ -234,6 +234,10 @@ config ARCH_THREAD_INFO_ALLOCATOR
 config ARCH_WANTS_DYNAMIC_TASK_STRUCT
 	bool
 
+config ARCH_32BIT_OFF_T
+	bool
+	depends on !64BIT
+
 config HAVE_REGS_AND_STACK_ACCESS_API
 	bool
 	help
arch/arc/Kconfig +1 -0
index 0d3e59f..d5ca749 100644
@@ -9,6 +9,7 @@
 config ARC
 	def_bool y
 	select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
+	select ARCH_32BIT_OFF_T
 	select BUILDTIME_EXTABLE_SORT
 	select CLKSRC_OF
 	select CLONE_BACKWARDS
arch/arm/Kconfig +1 -0
index 90542db..d84122a 100644
@@ -1,6 +1,7 @@
 config ARM
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ELF_RANDOMIZE
arch/blackfin/Kconfig +1 -0
index 28c63fe..097e7a5 100644
@@ -12,6 +12,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
arch/cris/Kconfig +1 -0
index deba266..b1376a9 100644
@@ -50,6 +50,7 @@ config LOCKDEP_SUPPORT
 config CRIS
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select HAVE_IDE
 	select GENERIC_ATOMIC64
 	select HAVE_UID16
arch/frv/Kconfig +1 -0
index eefd9a4..2f14904 100644
@@ -1,6 +1,7 @@
 config FRV
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select HAVE_IDE
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_PERF_EVENTS
arch/h8300/Kconfig +1 -0
index 3ae8525..29bbcb1 100644
@@ -1,5 +1,6 @@
 config H8300
         def_bool y
+	select ARCH_32BIT_OFF_T
 	select GENERIC_ATOMIC64
 	select HAVE_UID16
 	select VIRT_TO_BUS
arch/hexagon/Kconfig +1 -0
index 57298e7..df84602 100644
@@ -3,6 +3,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
arch/m32r/Kconfig +1 -0
index 3cc8498..efa10d3 100644
@@ -1,6 +1,7 @@
 config M32R
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select INIT_ALL_POSSIBLE
arch/m68k/Kconfig +1 -0
index 498b567..e9897e4 100644
@@ -1,6 +1,7 @@
 config M68K
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
 	select HAVE_IDE
 	select HAVE_AOUT if MMU
arch/metag/Kconfig +1 -0
index 5b7a45d..c337192 100644
@@ -1,5 +1,6 @@
 config METAG
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select EMBEDDED
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
arch/microblaze/Kconfig +1 -0
index 636e072..3c5f3d6 100644
@@ -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_WANT_IPC_PARSE_VERSION
arch/mips/Kconfig +1 -0
index ac91939..231b519 100644
@@ -1,6 +1,7 @@
 config MIPS
 	bool
 	default y
+	select ARCH_32BIT_OFF_T if !64BIT
 	select ARCH_SUPPORTS_UPROBES
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
arch/mn10300/Kconfig +1 -0
index 9627e81..002b06f 100644
@@ -1,6 +1,7 @@
 config MN10300
 	def_bool y
 	select HAVE_EXIT_THREAD
+	select ARCH_32BIT_OFF_T
 	select HAVE_OPROFILE
 	select HAVE_UID16
 	select GENERIC_IRQ_SHOW
arch/nios2/Kconfig +1 -0
index 51a56c8..f9273c9 100644
@@ -1,5 +1,6 @@
 config NIOS2
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select CLKSRC_OF
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
arch/openrisc/Kconfig +1 -0
index 142cb05..499649a 100644
@@ -5,6 +5,7 @@
 
 config OPENRISC
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select OF
 	select OF_EARLY_FLATTREE
 	select IRQ_DOMAIN
arch/parisc/Kconfig +1 -0
index dc11738..1cd0e29 100644
@@ -1,5 +1,6 @@
 config PARISC
 	def_bool y
+	select ARCH_32BIT_OFF_T if !64BIT
 	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select HAVE_IDE
arch/powerpc/Kconfig +1 -0
index 01f7464..4d589ae 100644
@@ -85,6 +85,7 @@ config ARCH_HAS_DMA_SET_COHERENT_MASK
 config PPC
 	bool
 	default y
+	select ARCH_32BIT_OFF_T if PPC32
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select BINFMT_ELF
arch/score/Kconfig +1 -0
index 507d631..0a9484b 100644
@@ -2,6 +2,7 @@ menu "Machine selection"
 
 config SCORE
        def_bool y
+       select ARCH_32BIT_OFF_T
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
        select GENERIC_ATOMIC64
arch/sh/Kconfig +1 -0
index e803a83..8f5f753 100644
@@ -54,6 +54,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
arch/sparc/Kconfig +1 -0
index 546293d..f8f6cfe 100644
@@ -46,6 +46,7 @@ config SPARC
 
 config SPARC32
 	def_bool !64BIT
+	select ARCH_32BIT_OFF_T
 	select GENERIC_ATOMIC64
 	select CLZ_TAB
 	select HAVE_UID16
arch/tile/Kconfig +1 -0
index 4820a02..79434be 100644
@@ -4,6 +4,7 @@
 config TILE
 	def_bool y
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+	select ARCH_32BIT_OFF_T if !64BIT
 	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
arch/unicore32/Kconfig +1 -0
index e5602ee..b995104 100644
@@ -1,6 +1,7 @@
 config UNICORE32
 	def_bool y
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
+	select ARCH_32BIT_OFF_T
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select HAVE_MEMBLOCK
arch/x86/Kconfig +1 -0
index 0a7b885..406b8d3 100644
@@ -20,6 +20,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_ATOMIC64_DEC_IF_POSITIVE
arch/x86/um/Kconfig +1 -0
index ed56a1c..8436bcd 100644
@@ -21,6 +21,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
arch/xtensa/Kconfig +1 -0
index 64336f6..1eeca06 100644
@@ -3,6 +3,7 @@ config ZONE_DMA
 
 config XTENSA
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select ARCH_WANT_FRAME_POINTERS
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select BUILDTIME_EXTABLE_SORT
include/linux/fcntl.h +1 -1
index 76ce329..46960a1 100644
@@ -5,7 +5,7 @@
 
 
 #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
Signature · 1 line
2.7.4
author
#7 lore raw

PATCH v7 3/19 arm64: ilp32: add documentation on the ILP32 ABI for ARM64

In reply to Yury Norov

Based on Andrew Pinski's patch-series.

---
 Documentation/arm64/ilp32.txt | 54 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 Documentation/arm64/ilp32.txt
Documentation/arm64/ilp32.txt new file +54 -0
new file mode 100644
index 0000000..d5faa31
@@ -0,0 +1,54 @@
+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 potentially access top halves of registers that
+are passed as syscall arguments, so such registers (w0-w7) are deloused.
+
+AARCH64/ILP32 provides next types turned to 64-bit (comparing to AARCH32):
+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.
+
+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 64bit values are handled by the code shared from
+AARCH32 and pass that value as a pair. Next syscalls are affected:
+fadvise64_64()
+fallocate()
+ftruncate64()		
+pread64	()
+pwrite64()
+readahead()
+sync_file_range()
+truncate64()
+sys_mmap()
+
+ptrace() syscall is handled by compat version.
+
+fcntl64() syscall is handled by non-compat handler as struct flock for ilp32
+is the same as for lp64
+
+shmat() syscall is handled by non-compat handler as aarch64/ilp32 has no
+limitation on 4-pages alignement for shared memory.
+
+Syscalls which take a pointer to stat, stat64, statfs, statfs64
+structures are now routed to native handlers directly, as aarch64/ilp32
+defines userspace ino_t, off_t, blkcnt_t, fsblkcnt_t, fsfilcnt_t types
+as 64-bit and it makes that structures have same layout as lp64.
+Next syscalls are affected:
+fstatat64()
+fstat64()
+statfs64()
+fstatfs64()
+
+struct rt_sigframe is redefined and contains struct compat_siginfo,
+as compat syscalls expects, and struct ilp32_sigframe, to handle
+AARCH64 register set and 32-bit userspace register representation.h
+
+elf_gregset_t is taken from lp64 to handle registers properly.
Signature · 1 line
2.7.4
author
#8 lore raw

PATCH v7 4/19 arm64: ensure the kernel is compiled for LP64

In reply to Yury Norov

From: Andrew Pinski <[email protected]>

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

---
 arch/arm64/Makefile | 5 +++++
 1 file changed, 5 insertions(+)
arch/arm64/Makefile +5 -0
index 7085e32..51c5293 100644
@@ -35,14 +35,19 @@ KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables
 KBUILD_CFLAGS	+= $(call cc-option, -mpc-relative-literal-loads)
 KBUILD_AFLAGS	+= $(lseinstr)
 
+KBUILD_CFLAGS	+= $(call cc-option,-mabi=lp64)
+KBUILD_AFLAGS	+= $(call cc-option,-mabi=lp64)
+
 ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
 KBUILD_CPPFLAGS	+= -mbig-endian
 AS		+= -EB
 LD		+= -EB
+LDFLAGS		+= -maarch64linuxb
 else
 KBUILD_CPPFLAGS	+= -mlittle-endian
 AS		+= -EL
 LD		+= -EL
+LDFLAGS		+= -maarch64linux
 endif
 
 CHECKFLAGS	+= -D__aarch64__
Signature · 1 line
2.7.4
author
#9 lore raw

PATCH v7 5/19 arm64: rename COMPAT to AARCH32_EL0 in Kconfig

In reply to Yury Norov

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, ARM64_ILP32 - support of ILP32 ABI (see next 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

---
 arch/arm64/Kconfig                   | 10 ++++++++--
 arch/arm64/include/asm/fpsimd.h      |  2 +-
 arch/arm64/include/asm/hwcap.h       |  4 ++--
 arch/arm64/include/asm/processor.h   |  6 +++---
 arch/arm64/include/asm/ptrace.h      |  2 +-
 arch/arm64/include/asm/signal32.h    |  6 ++++--
 arch/arm64/include/asm/unistd.h      |  2 +-
 arch/arm64/kernel/Makefile           |  2 +-
 arch/arm64/kernel/asm-offsets.c      |  2 +-
 arch/arm64/kernel/cpufeature.c       |  8 ++++----
 arch/arm64/kernel/cpuinfo.c          | 20 +++++++++++---------
 arch/arm64/kernel/entry.S            |  6 +++---
 arch/arm64/kernel/head.S             |  2 +-
 arch/arm64/kernel/ptrace.c           |  8 ++++----
 arch/arm64/kernel/traps.c            |  2 +-
 arch/arm64/kernel/vdso.c             |  4 ++--
 drivers/clocksource/arm_arch_timer.c |  2 +-
 17 files changed, 49 insertions(+), 39 deletions(-)
arch/arm64/Kconfig +8 -2
index 5a0a691..aea8e61 100644
@@ -385,7 +385,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
@@ -701,7 +701,7 @@ config FORCE_MAX_ZONEORDER
 
 menuconfig ARMV8_DEPRECATED
 	bool "Emulate deprecated/obsolete ARMv8 instructions"
-	depends on COMPAT
+	depends on AARCH32_EL0
 	help
 	  Legacy software support may require certain instructions
 	  that have been deprecated or obsoleted in the architecture.
@@ -971,8 +971,14 @@ menu "Userspace binary formats"
 source "fs/Kconfig.binfmt"
 
 config COMPAT
+	bool
+	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
 	select COMPAT_BINFMT_ELF
 	select HAVE_UID16
 	select OLD_SIGSUSPEND3
arch/arm64/include/asm/fpsimd.h +1 -1
index 50f559f..63b19f1 100644
@@ -52,7 +52,7 @@ struct fpsimd_partial_state {
 };
 
 
-#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+#if defined(__KERNEL__) && defined(CONFIG_AARCH32_EL0)
 /* Masks for extracting the FPSR and FPCR from the FPSCR */
 #define VFP_FPSCR_STAT_MASK	0xf800009f
 #define VFP_FPSCR_CTRL_MASK	0x07f79f00
arch/arm64/include/asm/hwcap.h +2 -2
index 400b80b..2c7fc5d 100644
@@ -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
arch/arm64/include/asm/processor.h +3 -3
index cef1cf3..5bbdbb4 100644
@@ -81,7 +81,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;
@@ -90,7 +90,7 @@ struct thread_struct {
 	struct debug_info	debug;		/* debugging */
 };
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define task_user_tls(t)						\
 ({									\
 	unsigned long *__tls;						\
@@ -121,7 +121,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)
 {
arch/arm64/include/asm/ptrace.h +1 -1
index a307eb6..4c730c3 100644
@@ -121,7 +121,7 @@ struct pt_regs {
 
 #define arch_has_single_step()	(1)
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define compat_thumb_mode(regs) \
 	(((regs)->pstate & COMPAT_PSR_T_BIT))
 #else
arch/arm64/include/asm/signal32.h +4 -2
index eeaa975..e68fcce 100644
@@ -17,7 +17,9 @@
 #define __ASM_SIGNAL32_H
 
 #ifdef __KERNEL__
-#ifdef CONFIG_COMPAT
+
+#ifdef CONFIG_AARCH32_EL0
+
 #include <linux/compat.h>
 
 #define AARCH32_KERN_SIGRET_CODE_OFFSET	0x500
@@ -47,6 +49,6 @@ static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t
 static inline void compat_setup_restart_syscall(struct pt_regs *regs)
 {
 }
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */
 #endif /* __KERNEL__ */
 #endif /* __ASM_SIGNAL32_H */
arch/arm64/include/asm/unistd.h +1 -1
index e78ac26..fe9d6c1 100644
@@ -13,7 +13,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
arch/arm64/kernel/Makefile +1 -1
index 2173149..631a118 100644
@@ -25,7 +25,7 @@ OBJCOPYFLAGS := --prefix-symbols=__efistub_
 $(obj)/%.stub.o: $(obj)/%.o FORCE
 	$(call if_changed,objcopy)
 
-arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
+arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
arch/arm64/kernel/asm-offsets.c +1 -1
index f8e5d47..06090db 100644
@@ -53,7 +53,7 @@ int main(void)
   DEFINE(S_X7,			offsetof(struct pt_regs, regs[7]));
   DEFINE(S_LR,			offsetof(struct pt_regs, regs[30]));
   DEFINE(S_SP,			offsetof(struct pt_regs, sp));
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
   DEFINE(S_COMPAT_SP,		offsetof(struct pt_regs, compat_sp));
 #endif
   DEFINE(S_PSTATE,		offsetof(struct pt_regs, pstate));
arch/arm64/kernel/cpufeature.c +4 -4
index 811773d..9f2fd84 100644
@@ -32,7 +32,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|\
@@ -834,7 +834,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),
@@ -850,7 +850,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;
@@ -873,7 +873,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;
arch/arm64/kernel/cpuinfo.c +11 -9
index c173d32..af200a8 100644
@@ -134,15 +134,17 @@ static int c_show(struct seq_file *m, void *v)
 		 */
 		seq_puts(m, "Features\t:");
 		if (compat) {
-#ifdef CONFIG_COMPAT
-			for (j = 0; compat_hwcap_str[j]; j++)
-				if (compat_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))
-					seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#ifdef CONFIG_AARCH32_EL0
+			if (personality(current->personality) == PER_LINUX32) {
+				for (j = 0; compat_hwcap_str[j]; j++)
+					if (compat_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))
+						seq_printf(m, " %s", compat_hwcap2_str[j]);
+			}
+#endif /* CONFIG_AARCH32_EL0 */
 		} else {
 			for (j = 0; hwcap_str[j]; j++)
 				if (elf_hwcap & (1 << j))
arch/arm64/kernel/entry.S +3 -3
index ec8bb48..21a0624 100644
@@ -260,7 +260,7 @@ ENTRY(vectors)
 	ventry	el0_fiq_invalid			// FIQ 64-bit EL0
 	ventry	el0_error_invalid		// Error 64-bit EL0
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	ventry	el0_sync_compat			// Synchronous 32-bit EL0
 	ventry	el0_irq_compat			// IRQ 32-bit EL0
 	ventry	el0_fiq_invalid_compat		// FIQ 32-bit EL0
@@ -300,7 +300,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)
@@ -463,7 +463,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
arch/arm64/kernel/head.S +1 -1
index 2c6e598..4d16787 100644
@@ -567,7 +567,7 @@ CPU_LE(	movk	x0, #0x30d0, lsl #16	)	// Clear EE and E0E on LE systems
 	msr	cptr_el2, x0			// Disable copro. traps to EL2
 1:
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	msr	hstr_el2, xzr			// Disable CP15 traps to EL2
 #endif
 
arch/arm64/kernel/ptrace.c +4 -4
index 3f6cd5c..aa79e81 100644
@@ -82,7 +82,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 		.si_addr	= (void __user *)(bkpt->trigger),
 	};
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	int i;
 
 	if (!is_compat_task())
@@ -657,7 +657,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 {
@@ -1192,11 +1192,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
arch/arm64/kernel/traps.c +1 -1
index ab066d1..973faec 100644
@@ -409,7 +409,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);
arch/arm64/kernel/vdso.c +2 -2
index 9fefb00..2a0de6f 100644
@@ -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 struct vm_special_mapping vdso_spec[2];
 
drivers/clocksource/arm_arch_timer.c +1 -1
index 4814446..bc5f13d 100644
@@ -321,7 +321,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
 }
Signature · 1 line
2.7.4
#10 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Hi, Yury

Quoted 17 lines · Yury Norov

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, ARM64_ILP32 - support of ILP32 ABI (see next 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

...

Quoted 8 lines
arch/arm64/kernel/cpuinfo.c +0 -0
index c173d32..af200a8 100644
@@ -134,15 +134,17 @@ static int c_show(struct seq_file *m, void *v)
  		 */
  		seq_puts(m, "Features\t:");
  		if (compat) {

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 137

Quoted 10 lines
arch/arm64/kernel/cpuinfo.c +1 -9
-#ifdef CONFIG_COMPAT
-			for (j = 0; compat_hwcap_str[j]; j++)
-				if (compat_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))
-					seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#ifdef CONFIG_AARCH32_EL0

I saw that compat_hwcap_str and compat_hwcap2_str is defined when "CONFIG_COMPAT" is true. Why we only change it to CONFIG_AARCH32_EL0 in c show()?

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 138

Quoted 1 line
arch/arm64/kernel/cpuinfo.c +1 -0
+			if (personality(current->personality) == PER_LINUX32) {

And "compat" is "personality(current->personality) == PER_LINUX32;", it seems that there is no need to add this twice.

Regards

Bamvor

Quoted 12 lines
arch/arm64/kernel/cpuinfo.c +9 -0
+				for (j = 0; compat_hwcap_str[j]; j++)
+					if (compat_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))
+						seq_printf(m, " %s", compat_hwcap2_str[j]);
+			}
+#endif /* CONFIG_AARCH32_EL0 */
  		} else {
  			for (j = 0; hwcap_str[j]; j++)
  				if (elf_hwcap & (1 << j))
maintainer
#11 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 40 lines · CEST Zhangjian (Bamvor)
Quoted 17 lines · Yury Norov

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, ARM64_ILP32 - support of ILP32 ABI (see next 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

...

Quoted 8 lines
arch/arm64/kernel/cpuinfo.c +0 -0
index c173d32..af200a8 100644
@@ -134,15 +134,17 @@ static int c_show(struct seq_file *m, void *v)
  		 */
  		seq_puts(m, "Features\t:");
  		if (compat) {

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 137

Quoted 10 lines
arch/arm64/kernel/cpuinfo.c +1 -9
-#ifdef CONFIG_COMPAT
-			for (j = 0; compat_hwcap_str[j]; j++)
-				if (compat_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))
-					seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#ifdef CONFIG_AARCH32_EL0

I saw that compat_hwcap_str and compat_hwcap2_str is defined when "CONFIG_COMPAT" is true. Why we only change it to CONFIG_AARCH32_EL0 in c show()?

Quoted 3 lines

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 138

Quoted 1 line
arch/arm64/kernel/cpuinfo.c +1 -0
+			if (personality(current->personality) == PER_LINUX32) {

And "compat" is "personality(current->personality) == PER_LINUX32;", it seems that there is no need to add this twice.

I think it would be best to remove the #ifdef here completely, the PER_LINUX32 concept is not strictly tied to the emulation of ARM binaries, it literally just changes the output of /proc/cpuinfo and 'uname', and you can have ARM binaries with PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

Arnd

maintainer
#12 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 41 lines · Arnd Bergmann
Quoted 40 lines · CEST Zhangjian (Bamvor)
Quoted 17 lines · Yury Norov

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, ARM64_ILP32 - support of ILP32 ABI (see next 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

...

Quoted 8 lines
arch/arm64/kernel/cpuinfo.c +0 -0
index c173d32..af200a8 100644
@@ -134,15 +134,17 @@ static int c_show(struct seq_file *m, void *v)
  		 */
  		seq_puts(m, "Features\t:");
  		if (compat) {

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 137

Quoted 10 lines
arch/arm64/kernel/cpuinfo.c +1 -9
-#ifdef CONFIG_COMPAT
-			for (j = 0; compat_hwcap_str[j]; j++)
-				if (compat_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))
-					seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#ifdef CONFIG_AARCH32_EL0

I saw that compat_hwcap_str and compat_hwcap2_str is defined when "CONFIG_COMPAT" is true. Why we only change it to CONFIG_AARCH32_EL0 in c show()?

Quoted 8 lines
Quoted 3 lines

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 138

Quoted 1 line
arch/arm64/kernel/cpuinfo.c +1 -0
+			if (personality(current->personality) == PER_LINUX32) {

And "compat" is "personality(current->personality) == PER_LINUX32;", it seems that there is no need to add this twice.

I think it would be best to remove the #ifdef here completely, the PER_LINUX32 concept is not strictly tied to the emulation of ARM binaries, it literally just changes the output of /proc/cpuinfo and 'uname',

It's not strictly related to ARM binaries, however it is related to AArch32 CPU features being supported and detected by the kernel. Currently, with CONFIG_COMPAT disabled, we won't have access to a (meaningful) compat_elf_hwcap.

Quoted 3 lines

and you can have ARM binaries with
PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

I was actually looking to enforce the 32-bit binaries to only see PER_LINUX32, though with a risk of breaking the ABI. OTOH, people are abusing this and write 32-bit apps relying on the 64-bit /proc/cpuinfo:

http://lkml.kernel.org/g/[email protected]

(you were summoned on that discussion couple of times ;))

Signature · 1 line
Catalin
maintainer
#13 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 51 lines · CEST Catalin Marinas
Quoted 41 lines · Arnd Bergmann
Quoted 40 lines · CEST Zhangjian (Bamvor)
Quoted 17 lines · Yury Norov

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, ARM64_ILP32 - support of ILP32 ABI (see next 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

...

Quoted 8 lines
arch/arm64/kernel/cpuinfo.c +0 -0
index c173d32..af200a8 100644
@@ -134,15 +134,17 @@ static int c_show(struct seq_file *m, void *v)
  		 */
  		seq_puts(m, "Features\t:");
  		if (compat) {

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 137

Quoted 10 lines
arch/arm64/kernel/cpuinfo.c +1 -9
-#ifdef CONFIG_COMPAT
-			for (j = 0; compat_hwcap_str[j]; j++)
-				if (compat_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))
-					seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#ifdef CONFIG_AARCH32_EL0

I saw that compat_hwcap_str and compat_hwcap2_str is defined when "CONFIG_COMPAT" is true. Why we only change it to CONFIG_AARCH32_EL0 in c show()?

Quoted 8 lines
Quoted 3 lines

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 138

Quoted 1 line
arch/arm64/kernel/cpuinfo.c +1 -0
+			if (personality(current->personality) == PER_LINUX32) {

And "compat" is "personality(current->personality) == PER_LINUX32;", it seems that there is no need to add this twice.

I think it would be best to remove the #ifdef here completely, the PER_LINUX32 concept is not strictly tied to the emulation of ARM binaries, it literally just changes the output of /proc/cpuinfo and 'uname',

Quoted 4 lines

It's not strictly related to ARM binaries, however it is related to AArch32 CPU features being supported and detected by the kernel. Currently, with CONFIG_COMPAT disabled, we won't have access to a (meaningful) compat_elf_hwcap.

Ah, makes sense. In that case, using CONFIG_AARCH32_EL0 sounds like the right thing to do here, though I guess we can just drop the "if (compat)" check, as we specifically want to print the supported features of the CPU, and they are still present even if a process with PER_LINUX reads them.

Quoted 11 lines
Quoted 3 lines

and you can have ARM binaries with
PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

I was actually looking to enforce the 32-bit binaries to only see PER_LINUX32, though with a risk of breaking the ABI. OTOH, people are abusing this and write 32-bit apps relying on the 64-bit /proc/cpuinfo:

http://lkml.kernel.org/g/1464706504-25224-3-git-send-email-catalin.marinas at arm.com

(you were summoned on that discussion couple of times ;))

Hmm, I thought I saw the thread and didn't have any good idea for the uname information, but didn't notice it was for /proc/cpuinfo.

What's wrong with always showing both the 32-bit and the 64-bit hwcap strings here (minus the duplicates, which hopefully have the same meaning here)?

Arnd

maintainer
#14 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 57 lines · Arnd Bergmann
Quoted 51 lines · CEST Catalin Marinas
Quoted 41 lines · Arnd Bergmann
Quoted 40 lines · CEST Zhangjian (Bamvor)
Quoted 17 lines · Yury Norov

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, ARM64_ILP32 - support of ILP32 ABI (see next 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

...

Quoted 8 lines
arch/arm64/kernel/cpuinfo.c +0 -0
index c173d32..af200a8 100644
@@ -134,15 +134,17 @@ static int c_show(struct seq_file *m, void *v)
  		 */
  		seq_puts(m, "Features\t:");
  		if (compat) {

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 137

Quoted 10 lines
arch/arm64/kernel/cpuinfo.c +1 -9
-#ifdef CONFIG_COMPAT
-			for (j = 0; compat_hwcap_str[j]; j++)
-				if (compat_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))
-					seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#ifdef CONFIG_AARCH32_EL0

I saw that compat_hwcap_str and compat_hwcap2_str is defined when "CONFIG_COMPAT" is true. Why we only change it to CONFIG_AARCH32_EL0 in c show()?

Quoted 8 lines
Quoted 3 lines

arch/arm64/kernel/cpuinfo.c static int c_show(struct seq_file *m, void *v) · line 138

Quoted 1 line
arch/arm64/kernel/cpuinfo.c +1 -0
+			if (personality(current->personality) == PER_LINUX32) {

And "compat" is "personality(current->personality) == PER_LINUX32;", it seems that there is no need to add this twice.

I think it would be best to remove the #ifdef here completely, the PER_LINUX32 concept is not strictly tied to the emulation of ARM binaries, it literally just changes the output of /proc/cpuinfo and 'uname',

Quoted 4 lines

It's not strictly related to ARM binaries, however it is related to AArch32 CPU features being supported and detected by the kernel. Currently, with CONFIG_COMPAT disabled, we won't have access to a (meaningful) compat_elf_hwcap.

Quoted 5 lines

Ah, makes sense. In that case, using CONFIG_AARCH32_EL0 sounds like the right thing to do here, though I guess we can just drop the "if (compat)" check, as we specifically want to print the supported features of the CPU, and they are still present even if a process with PER_LINUX reads them.

Do you mean always printing both compat and native hwcaps in /proc/cpuinfo? We discussed this in the past and it's not something we can easily fix at this stage without breaking the ABI. If we noticed this before, we could have used distinct feature strings for AArch32 and AArch64 (e.g. crypto stuff like aes32 and aes64 but we only have aes for both).

Quoted 10 lines
Quoted 10 lines
Quoted 3 lines

and you can have ARM binaries with
PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

I was actually looking to enforce the 32-bit binaries to only see PER_LINUX32, though with a risk of breaking the ABI. OTOH, people are abusing this and write 32-bit apps relying on the 64-bit /proc/cpuinfo:

http://lkml.kernel.org/g/[email protected]

Quoted 8 lines
Quoted 1 line

(you were summoned on that discussion couple of times ;))

Hmm, I thought I saw the thread and didn't have any good idea for the uname information, but didn't notice it was for /proc/cpuinfo.

What's wrong with always showing both the 32-bit and the 64-bit hwcap strings here (minus the duplicates, which hopefully have the same meaning here)?

As I said above, some of them have the same name (which may be a good thing at a first look) but we don't have an architecture guarantee that the feature is present in both AArch32 and AArch64 modes (e.g. AES may only be available in AArch64).

Signature · 1 line
Catalin
maintainer
#15 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 15 lines · CEST Catalin Marinas
Quoted 15 lines
Quoted 11 lines
Quoted 3 lines

and you can have ARM binaries with
PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

I was actually looking to enforce the 32-bit binaries to only see PER_LINUX32, though with a risk of breaking the ABI. OTOH, people are abusing this and write 32-bit apps relying on the 64-bit /proc/cpuinfo:

http://lkml.kernel.org/g/[email protected]

(you were summoned on that discussion couple of times ;))

Hmm, I thought I saw the thread and didn't have any good idea for the uname information, but didn't notice it was for /proc/cpuinfo.

Quoted 8 lines
Quoted 3 lines

What's wrong with always showing both the 32-bit and the 64-bit hwcap strings here (minus the duplicates, which hopefully have the same meaning here)?

As I said above, some of them have the same name (which may be a good thing at a first look) but we don't have an architecture guarantee that the feature is present in both AArch32 and AArch64 modes (e.g. AES may only be available in AArch64).

Is this the case on actual implementations that exist today? If they are actually always both present, we might be able to get away with it.

Arnd

maintainer
#16 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 20 lines · Arnd Bergmann
Quoted 19 lines · CEST Catalin Marinas
Quoted 18 lines
Quoted 11 lines
Quoted 3 lines

and you can have ARM binaries with
PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

I was actually looking to enforce the 32-bit binaries to only see PER_LINUX32, though with a risk of breaking the ABI. OTOH, people are abusing this and write 32-bit apps relying on the 64-bit /proc/cpuinfo:

http://lkml.kernel.org/g/[email protected]

(you were summoned on that discussion couple of times ;))

Hmm, I thought I saw the thread and didn't have any good idea for the uname information, but didn't notice it was for /proc/cpuinfo.

What's wrong with always showing both the 32-bit and the 64-bit hwcap strings here (minus the duplicates, which hopefully have the same meaning here)?

Quoted 7 lines
Quoted 4 lines

As I said above, some of them have the same name (which may be a good thing at a first look) but we don't have an architecture guarantee that the feature is present in both AArch32 and AArch64 modes (e.g. AES may only be available in AArch64).

Is this the case on actual implementations that exist today? If they are actually always both present, we might be able to get away with it.

It may be fine on current implementations but what would we do when/if we actually find such discrepancy? It's not just ARM Ltd designing the chips, so as long as the architecture doesn't mandate it you may find strange implementations.

Imposing such restriction in the architecture doesn't make sense if the only reason is the /proc/cpuinfo file (and I can't think of any other reason why this should be enforced).

What I'm worried about is 32-bit apps running on an arm64 kernel and making use of the 64-bit /proc/cpuinfo without any guarantee that the AArch32 state has such features. In my patch proposal linked above I wanted to always force the compat /proc/cpuinfo for 32-bit tasks.

Signature · 1 line
Catalin
author
#17 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 34 lines · Catalin Marinas
Quoted 20 lines · Arnd Bergmann
Quoted 19 lines · CEST Catalin Marinas
Quoted 18 lines
Quoted 11 lines
Quoted 3 lines

and you can have ARM binaries with
PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

I was actually looking to enforce the 32-bit binaries to only see PER_LINUX32, though with a risk of breaking the ABI. OTOH, people are abusing this and write 32-bit apps relying on the 64-bit /proc/cpuinfo:

http://lkml.kernel.org/g/1464706504-25224-3-git-send-email-catalin.marinas at arm.com

(you were summoned on that discussion couple of times ;))

Hmm, I thought I saw the thread and didn't have any good idea for the uname information, but didn't notice it was for /proc/cpuinfo.

What's wrong with always showing both the 32-bit and the 64-bit hwcap strings here (minus the duplicates, which hopefully have the same meaning here)?

Quoted 7 lines
Quoted 4 lines

As I said above, some of them have the same name (which may be a good thing at a first look) but we don't have an architecture guarantee that the feature is present in both AArch32 and AArch64 modes (e.g. AES may only be available in AArch64).

Is this the case on actual implementations that exist today? If they are actually always both present, we might be able to get away with it.

It may be fine on current implementations but what would we do when/if we actually find such discrepancy? It's not just ARM Ltd designing the chips, so as long as the architecture doesn't mandate it you may find strange implementations.

Quoted 8 lines

Imposing such restriction in the architecture doesn't make sense if the only reason is the /proc/cpuinfo file (and I can't think of any other reason why this should be enforced).

What I'm worried about is 32-bit apps running on an arm64 kernel and making use of the 64-bit /proc/cpuinfo without any guarantee that the AArch32 state has such features. In my patch proposal linked above I wanted to always force the compat /proc/cpuinfo for 32-bit tasks.

The link doesn't work for me. Is there other link, or what's the maillist there?

So, what we decided finally? Is my understanding correct that we leave everything as is in ilp32 series, and it will be resolved separately?

Yury.

Quoted 3 lines
Signature · 2 lines
-- 
Catalin
maintainer
#18 lore raw

Re: [PATCH 05/19] arm64: rename COMPAT to AARCH32_EL0 in Kconfig

Quoted 39 lines · Yury Norov
Quoted 38 lines · Catalin Marinas
Quoted 20 lines · Arnd Bergmann
Quoted 19 lines · CEST Catalin Marinas
Quoted 18 lines
Quoted 11 lines
Quoted 3 lines

and you can have ARM binaries with
PER_LINUX (using the arm64 uname) just like you can have arm64 binaries running with PER_LINUX32.

I was actually looking to enforce the 32-bit binaries to only see PER_LINUX32, though with a risk of breaking the ABI. OTOH, people are abusing this and write 32-bit apps relying on the 64-bit /proc/cpuinfo:

http://lkml.kernel.org/g/1464706504-25224-3-git-send-email-catalin.marinas at arm.com

(you were summoned on that discussion couple of times ;))

Hmm, I thought I saw the thread and didn't have any good idea for the uname information, but didn't notice it was for /proc/cpuinfo.

What's wrong with always showing both the 32-bit and the 64-bit hwcap strings here (minus the duplicates, which hopefully have the same meaning here)?

Quoted 7 lines
Quoted 4 lines

As I said above, some of them have the same name (which may be a good thing at a first look) but we don't have an architecture guarantee that the feature is present in both AArch32 and AArch64 modes (e.g. AES may only be available in AArch64).

Is this the case on actual implementations that exist today? If they are actually always both present, we might be able to get away with it.

It may be fine on current implementations but what would we do when/if we actually find such discrepancy? It's not just ARM Ltd designing the chips, so as long as the architecture doesn't mandate it you may find strange implementations.

Imposing such restriction in the architecture doesn't make sense if the only reason is the /proc/cpuinfo file (and I can't think of any other reason why this should be enforced).

Quoted 7 lines
Quoted 4 lines

What I'm worried about is 32-bit apps running on an arm64 kernel and making use of the 64-bit /proc/cpuinfo without any guarantee that the AArch32 state has such features. In my patch proposal linked above I wanted to always force the compat /proc/cpuinfo for 32-bit tasks.

The link doesn't work for me. Is there other link, or what's the maillist there?

With lkml.kernel.org, just change the 'g' with an 'r':

http://lkml.kernel.org/r/1464706504-25224-3-git-send-email-catalin.marinas at arm.com

It was on linux-arm-kernel.

Quoted 2 lines

So, what we decided finally? Is my understanding correct that we leave everything as is in ilp32 series, and it will be resolved separately?

ILP32 is not affected by this since the hwcap for ILP32 should match native. It was more a question about whether AArch32 tasks should ever have access to AArch64 hwcaps (and potential misuse).

Signature · 1 line
Catalin
author
#19 lore raw

PATCH v7 6/19 arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64

In reply to Yury Norov

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.

---
 arch/arm64/include/uapi/asm/bitsperlong.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
arch/arm64/include/uapi/asm/bitsperlong.h +8 -1
index fce9c29..4265243 100644
@@ -16,7 +16,14 @@
 #ifndef __ASM_BITSPERLONG_H
 #define __ASM_BITSPERLONG_H
 
-#define __BITS_PER_LONG 64
+#if defined(__LP64__)
+/* Assuming __LP64__ will be defined for native ELF64's and not for ILP32. */
+#  define __BITS_PER_LONG 64
+#elif defined(__ILP32__)
+#  define __BITS_PER_LONG 32
+#else
+#  error "Neither LP64 nor ILP32: unsupported ABI in asm/bitsperlong.h"
+#endif
 
 #include <asm-generic/bitsperlong.h>
 
Signature · 1 line
2.7.4
author
#20 lore raw

PATCH v7 7/19 thread: move thread bits accessors to separated file

In reply to Yury Norov

They may be accessed from low-level code, so isolating is a measure to avoid circular dependencies in header files.

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

---
 include/linux/thread_bits.h | 55 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/thread_info.h | 44 +-----------------------------------
 2 files changed, 56 insertions(+), 43 deletions(-)
 create mode 100644 include/linux/thread_bits.h
include/linux/thread_bits.h new file +55 -0
new file mode 100644
index 0000000..0d05d16
@@ -0,0 +1,55 @@
+
+/* thread_bits.h: common low-level thread bits accessors */
+
+#ifndef _LINUX_THREAD_BITS_H
+#define _LINUX_THREAD_BITS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bitops.h>
+#include <asm/thread_info.h>
+
+/*
+ * flag set/clear/test wrappers
+ * - pass TIF_xxxx constants to these functions
+ */
+
+static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	set_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	clear_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_set_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_clear_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_bit(flag, (unsigned long *)&ti->flags);
+}
+
+#define set_thread_flag(flag) \
+	set_ti_thread_flag(current_thread_info(), flag)
+#define clear_thread_flag(flag) \
+	clear_ti_thread_flag(current_thread_info(), flag)
+#define test_and_set_thread_flag(flag) \
+	test_and_set_ti_thread_flag(current_thread_info(), flag)
+#define test_and_clear_thread_flag(flag) \
+	test_and_clear_ti_thread_flag(current_thread_info(), flag)
+#define test_thread_flag(flag) \
+	test_ti_thread_flag(current_thread_info(), flag)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _LINUX_THREAD_BITS_H */
+
include/linux/thread_info.h +1 -43

56 lines not on this page · raw message

Signature · 1 line
2.7.4
author
#21 lore raw

PATCH v7 8/19 arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)

In reply to Yury Norov

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.

---
 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   | 64 ++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/memory.h      |  5 +--
 arch/arm64/include/asm/processor.h   |  5 +--
 arch/arm64/include/asm/syscall.h     |  2 +-
 arch/arm64/include/asm/thread_info.h |  2 +-
 arch/arm64/kernel/hw_breakpoint.c    | 10 +++---
 arch/arm64/kernel/perf_regs.c        |  2 +-
 arch/arm64/kernel/process.c          |  7 ++--
 arch/arm64/kernel/ptrace.c           | 11 +++----
 arch/arm64/kernel/signal.c           |  4 +--
 arch/arm64/kernel/traps.c            |  3 +-
 14 files changed, 98 insertions(+), 48 deletions(-)
 create mode 100644 arch/arm64/include/asm/is_compat.h
arch/arm64/include/asm/compat.h +2 -17
index eb8432b..df2f72d 100644
@@ -24,6 +24,8 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
+#include <asm/is_compat.h>
+
 #define COMPAT_USER_HZ		100
 #ifdef __AARCH64EB__
 #define COMPAT_UTS_MACHINE	"armv8b\0\0"
@@ -298,23 +300,6 @@ struct compat_shmid64_ds {
 	compat_ulong_t __unused5;
 };
 
-static inline int is_compat_task(void)
-{
-	return test_thread_flag(TIF_32BIT);
-}
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
-	return test_ti_thread_flag(thread, TIF_32BIT);
-}
-
-#else /* !CONFIG_COMPAT */
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
-	return 0;
-}
-
 #endif /* CONFIG_COMPAT */
 #endif /* __KERNEL__ */
 #endif /* __ASM_COMPAT_H */
arch/arm64/include/asm/elf.h +5 -5
index 579b6e6..bef2d90 100644
@@ -16,6 +16,10 @@
 #ifndef __ASM_ELF_H
 #define __ASM_ELF_H
 
+#ifndef __ASSEMBLY__
+#include <linux/compat.h>
+#endif
+
 #include <asm/hwcap.h>
 
 /*
@@ -152,13 +156,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")
arch/arm64/include/asm/ftrace.h +1 -1
index caa955f..0feb28a 100644
@@ -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__ */
 
arch/arm64/include/asm/is_compat.h new file +64 -0

64 lines not on this page · raw message

arch/arm64/include/asm/memory.h +3 -2
index 31b7322..4d734a1 100644
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <asm/bug.h>
 #include <asm/sizes.h>
+#include <asm/is_compat.h>
 
 /*
  * Allow for constants defined here to be used from assembly code
@@ -78,9 +79,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
arch/arm64/include/asm/processor.h +3 -2
index 5bbdbb4..1eccf47 100644
@@ -30,6 +30,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>
@@ -41,7 +42,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
@@ -94,7 +95,7 @@ struct thread_struct {
 #define task_user_tls(t)						\
 ({									\
 	unsigned long *__tls;						\
-	if (is_compat_thread(task_thread_info(t)))			\
+	if (is_a32_compat_thread(task_thread_info(t)))			\
 		__tls = &(t)->thread.tp2_value;				\
 	else								\
 		__tls = &(t)->thread.tp_value;				\
arch/arm64/include/asm/syscall.h +1 -1
index 709a574..ce09641 100644
@@ -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;
arch/arm64/include/asm/thread_info.h +1 -1
index abd64bd..4daa559 100644
@@ -118,7 +118,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_FREEZE		19
 #define TIF_RESTORE_SIGMASK	20
 #define TIF_SINGLESTEP		21
-#define TIF_32BIT		22	/* 32bit process */
+#define TIF_32BIT		22	/* AARCH32 process */
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
arch/arm64/kernel/hw_breakpoint.c +5 -5
index ce21aa8..d67f518 100644
@@ -164,7 +164,7 @@ enum hw_breakpoint_ops {
 	HW_BREAKPOINT_RESTORE
 };
 
-static int is_compat_bp(struct perf_event *bp)
+static int is_a32_compat_bp(struct perf_event *bp)
 {
 	struct task_struct *tsk = bp->hw.target;
 
@@ -175,7 +175,7 @@ static int is_compat_bp(struct perf_event *bp)
 	 * deprecated behaviour if we use unaligned watchpoints in
 	 * AArch64 state.
 	 */
-	return tsk && is_compat_thread(task_thread_info(tsk));
+	return tsk && is_a32_compat_thread(task_thread_info(tsk));
 }
 
 /**
@@ -435,7 +435,7 @@ static int arch_build_bp_info(struct perf_event *bp)
 	 * Watchpoints can be of length 1, 2, 4 or 8 bytes.
 	 */
 	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
-		if (is_compat_bp(bp)) {
+		if (is_a32_compat_bp(bp)) {
 			if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
 			    info->ctrl.len != ARM_BREAKPOINT_LEN_4)
 				return -EINVAL;
@@ -492,7 +492,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 	 * AArch32 tasks expect some simple alignment fixups, so emulate
 	 * that here.
 	 */
-	if (is_compat_bp(bp)) {
+	if (is_a32_compat_bp(bp)) {
 		if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
 			alignment_mask = 0x7;
 		else
@@ -679,7 +679,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
 
 		info = counter_arch_bp(wp);
 		/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
-		if (is_compat_task()) {
+		if (is_a32_compat_task()) {
 			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
 				alignment_mask = 0x7;
 			else
arch/arm64/kernel/perf_regs.c +1 -1
index 3f62b35..a79058f 100644
@@ -45,7 +45,7 @@ int perf_reg_validate(u64 mask)
 
 u64 perf_reg_abi(struct task_struct *task)
 {
-	if (is_compat_thread(task_thread_info(task)))
+	if (is_a32_compat_thread(task_thread_info(task)))
 		return PERF_SAMPLE_REGS_ABI_32;
 	else
 		return PERF_SAMPLE_REGS_ABI_64;
arch/arm64/kernel/process.c +3 -4
index 6cd2612..c008ec8 100644
@@ -47,7 +47,6 @@
 #include <trace/events/power.h>
 
 #include <asm/alternative.h>
-#include <asm/compat.h>
 #include <asm/cacheflush.h>
 #include <asm/fpsimd.h>
 #include <asm/mmu_context.h>
@@ -204,7 +203,7 @@ static void tls_thread_flush(void)
 {
 	asm ("msr tpidr_el0, xzr");
 
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
 		current->thread.tp_value = 0;
 
 		/*
@@ -256,7 +255,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
 		asm("mrs %0, tpidr_el0" : "=r" (*task_user_tls(p)));
 
 		if (stack_start) {
-			if (is_compat_thread(task_thread_info(p)))
+			if (is_a32_compat_thread(task_thread_info(p)))
 				childregs->compat_sp = stack_start;
 			else
 				childregs->sp = stack_start;
@@ -293,7 +292,7 @@ static void tls_thread_switch(struct task_struct *next)
 	*task_user_tls(current) = tpidr;
 
 	tpidr = *task_user_tls(next);
-	tpidrro = is_compat_thread(task_thread_info(next)) ?
+	tpidrro = is_a32_compat_thread(task_thread_info(next)) ?
 		  next->thread.tp_value : 0;
 
 	asm(
arch/arm64/kernel/ptrace.c +5 -6
index aa79e81..38a09338 100644
@@ -38,7 +38,6 @@
 #include <linux/tracehook.h>
 #include <linux/elf.h>
 
-#include <asm/compat.h>
 #include <asm/debug-monitors.h>
 #include <asm/pgtable.h>
 #include <asm/syscall.h>
@@ -85,7 +84,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 #ifdef CONFIG_AARCH32_EL0
 	int i;
 
-	if (!is_compat_task())
+	if (!is_a32_compat_task())
 		goto send_sig;
 
 	for (i = 0; i < ARM_MAX_BRP; ++i) {
@@ -1203,9 +1202,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;
@@ -1232,7 +1231,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;
 
@@ -1343,7 +1342,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);
arch/arm64/kernel/signal.c +2 -2
index a8eafdb..be02f65 100644
@@ -276,7 +276,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
 
 static void setup_restart_syscall(struct pt_regs *regs)
 {
-	if (is_compat_task())
+	if (is_a32_compat_task())
 		compat_setup_restart_syscall(regs);
 	else
 		regs->regs[8] = __NR_restart_syscall;
@@ -295,7 +295,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 	/*
 	 * Set up the stack frame
 	 */
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
 		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
 			ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
 		else
arch/arm64/kernel/traps.c +2 -1
index 973faec..d77be17 100644
@@ -18,6 +18,7 @@
  */
 
 #include <linux/bug.h>
+#include <linux/compat.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
 #include <linux/kallsyms.h>
@@ -411,7 +412,7 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs)
 {
 #ifdef CONFIG_AARCH32_EL0
 	long ret;
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
 		ret = compat_arm_syscall(regs);
 		if (ret != -ENOSYS)
 			return ret;
Signature · 1 line
2.7.4
#22 lore raw

Re: [PATCH 08/19] arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)

Hi,

Quoted 197 lines · Yury Norov

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.

---
  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   | 64 ++++++++++++++++++++++++++++++++++++
  arch/arm64/include/asm/memory.h      |  5 +--
  arch/arm64/include/asm/processor.h   |  5 +--
  arch/arm64/include/asm/syscall.h     |  2 +-
  arch/arm64/include/asm/thread_info.h |  2 +-
  arch/arm64/kernel/hw_breakpoint.c    | 10 +++---
  arch/arm64/kernel/perf_regs.c        |  2 +-
  arch/arm64/kernel/process.c          |  7 ++--
  arch/arm64/kernel/ptrace.c           | 11 +++----
  arch/arm64/kernel/signal.c           |  4 +--
  arch/arm64/kernel/traps.c            |  3 +-
  14 files changed, 98 insertions(+), 48 deletions(-)

create mode 100644 arch/arm64/include/asm/is_compat.h

arch/arm64/include/asm/compat.h +2 -17
index eb8432b..df2f72d 100644
@@ -24,6 +24,8 @@
  #include <linux/types.h>
  #include <linux/sched.h>
 
+#include <asm/is_compat.h>
+
  #define COMPAT_USER_HZ		100
  #ifdef __AARCH64EB__
  #define COMPAT_UTS_MACHINE	"armv8b\0\0"
@@ -298,23 +300,6 @@ struct compat_shmid64_ds {
  	compat_ulong_t __unused5;
  };
 
-static inline int is_compat_task(void)
-{
-	return test_thread_flag(TIF_32BIT);
-}
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
-	return test_ti_thread_flag(thread, TIF_32BIT);
-}
-
-#else /* !CONFIG_COMPAT */
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
-	return 0;
-}
-
  #endif /* CONFIG_COMPAT */
  #endif /* __KERNEL__ */
  #endif /* __ASM_COMPAT_H */
arch/arm64/include/asm/elf.h +5 -5
index 579b6e6..bef2d90 100644
@@ -16,6 +16,10 @@
  #ifndef __ASM_ELF_H
  #define __ASM_ELF_H
 
+#ifndef __ASSEMBLY__
+#include <linux/compat.h>
+#endif
+
  #include <asm/hwcap.h>
 
  /*
@@ -152,13 +156,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")
arch/arm64/include/asm/ftrace.h +1 -1
index caa955f..0feb28a 100644
@@ -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__ */
 
arch/arm64/include/asm/is_compat.h new file +64 -0
new file mode 100644
index 0000000..8dba5ca
@@ -0,0 +1,64 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_IS_COMPAT_H
+#define __ASM_IS_COMPAT_H
+#ifndef __ASSEMBLY__
+
+#include <linux/thread_bits.h>
+
+#ifdef CONFIG_AARCH32_EL0
+
+static inline int is_a32_compat_task(void)
+{
+	return test_thread_flag(TIF_32BIT);
+}
+
+static inline int is_a32_compat_thread(struct thread_info *thread)
+{
+	return test_ti_thread_flag(thread, TIF_32BIT);
+}
+
+#else
+
+static inline int is_a32_compat_task(void)
+
+{
+	return 0;
+}
+
+static inline int is_a32_compat_thread(struct thread_info *thread)
+{
+	return 0;
+}
+
+#endif /* CONFIG_AARCH32_EL0 */
+
+#ifdef CONFIG_COMPAT
+
+static inline int is_compat_task(void)
+{
+	return is_a32_compat_task();
+}
+
+#endif /* CONFIG_COMPAT */
+
+static inline int is_compat_thread(struct thread_info *thread)
+{
+	return is_a32_compat_thread(thread);
+}
+
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_IS_COMPAT_H */
arch/arm64/include/asm/memory.h +1 -0
index 31b7322..4d734a1 100644
@@ -26,6 +26,7 @@
  #include <linux/types.h>
  #include <asm/bug.h>
  #include <asm/sizes.h>
+#include <asm/is_compat.h>
 
  /*
   * Allow for constants defined here to be used from assembly code

arch/arm64/include/asm/memory.h line 84

Quoted 8 lines
arch/arm64/include/asm/memory.h +2 -2
@@ -78,9 +79,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) ? \

It should be
+#define TASK_SIZE_OF(tsk) (is_compat_thread(task_thread_info(tsk)) ? \
is_compat_thread takes "struct thread_info *thread" while TASK_SIZE_OF takes "struct task_struct *tsk"tsk.

Regards

Bamvor

Quoted 255 lines
arch/arm64/include/asm/memory.h +0 -0
  				TASK_SIZE_32 : TASK_SIZE_64)
  #else
  #define TASK_SIZE		TASK_SIZE_64
arch/arm64/include/asm/processor.h +3 -2
index 5bbdbb4..1eccf47 100644
@@ -30,6 +30,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>
@@ -41,7 +42,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
@@ -94,7 +95,7 @@ struct thread_struct {
  #define task_user_tls(t)						\
  ({									\
  	unsigned long *__tls;						\
-	if (is_compat_thread(task_thread_info(t)))			\
+	if (is_a32_compat_thread(task_thread_info(t)))			\
  		__tls = &(t)->thread.tp2_value;				\
  	else								\
  		__tls = &(t)->thread.tp_value;				\
arch/arm64/include/asm/syscall.h +1 -1
index 709a574..ce09641 100644
@@ -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;
arch/arm64/include/asm/thread_info.h +1 -1
index abd64bd..4daa559 100644
@@ -118,7 +118,7 @@ static inline struct thread_info *current_thread_info(void)
  #define TIF_FREEZE		19
  #define TIF_RESTORE_SIGMASK	20
  #define TIF_SINGLESTEP		21
-#define TIF_32BIT		22	/* 32bit process */
+#define TIF_32BIT		22	/* AARCH32 process */
 
  #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
  #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
arch/arm64/kernel/hw_breakpoint.c +5 -5
index ce21aa8..d67f518 100644
@@ -164,7 +164,7 @@ enum hw_breakpoint_ops {
  	HW_BREAKPOINT_RESTORE
  };
 
-static int is_compat_bp(struct perf_event *bp)
+static int is_a32_compat_bp(struct perf_event *bp)
  {
  	struct task_struct *tsk = bp->hw.target;
 
@@ -175,7 +175,7 @@ static int is_compat_bp(struct perf_event *bp)
  	 * deprecated behaviour if we use unaligned watchpoints in
  	 * AArch64 state.
  	 */
-	return tsk && is_compat_thread(task_thread_info(tsk));
+	return tsk && is_a32_compat_thread(task_thread_info(tsk));
  }
 
  /**
@@ -435,7 +435,7 @@ static int arch_build_bp_info(struct perf_event *bp)
  	 * Watchpoints can be of length 1, 2, 4 or 8 bytes.
  	 */
  	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
-		if (is_compat_bp(bp)) {
+		if (is_a32_compat_bp(bp)) {
  			if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
  			    info->ctrl.len != ARM_BREAKPOINT_LEN_4)
  				return -EINVAL;
@@ -492,7 +492,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
  	 * AArch32 tasks expect some simple alignment fixups, so emulate
  	 * that here.
  	 */
-	if (is_compat_bp(bp)) {
+	if (is_a32_compat_bp(bp)) {
  		if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
  			alignment_mask = 0x7;
  		else
@@ -679,7 +679,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
 
  		info = counter_arch_bp(wp);
  		/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
-		if (is_compat_task()) {
+		if (is_a32_compat_task()) {
  			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
  				alignment_mask = 0x7;
  			else
arch/arm64/kernel/perf_regs.c +1 -1
index 3f62b35..a79058f 100644
@@ -45,7 +45,7 @@ int perf_reg_validate(u64 mask)
 
  u64 perf_reg_abi(struct task_struct *task)
  {
-	if (is_compat_thread(task_thread_info(task)))
+	if (is_a32_compat_thread(task_thread_info(task)))
  		return PERF_SAMPLE_REGS_ABI_32;
  	else
  		return PERF_SAMPLE_REGS_ABI_64;
arch/arm64/kernel/process.c +3 -4
index 6cd2612..c008ec8 100644
@@ -47,7 +47,6 @@
  #include <trace/events/power.h>
 
  #include <asm/alternative.h>
-#include <asm/compat.h>
  #include <asm/cacheflush.h>
  #include <asm/fpsimd.h>
  #include <asm/mmu_context.h>
@@ -204,7 +203,7 @@ static void tls_thread_flush(void)
  {
  	asm ("msr tpidr_el0, xzr");
 
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
  		current->thread.tp_value = 0;
 
  		/*
@@ -256,7 +255,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
  		asm("mrs %0, tpidr_el0" : "=r" (*task_user_tls(p)));
 
  		if (stack_start) {
-			if (is_compat_thread(task_thread_info(p)))
+			if (is_a32_compat_thread(task_thread_info(p)))
  				childregs->compat_sp = stack_start;
  			else
  				childregs->sp = stack_start;
@@ -293,7 +292,7 @@ static void tls_thread_switch(struct task_struct *next)
  	*task_user_tls(current) = tpidr;
 
  	tpidr = *task_user_tls(next);
-	tpidrro = is_compat_thread(task_thread_info(next)) ?
+	tpidrro = is_a32_compat_thread(task_thread_info(next)) ?
  		  next->thread.tp_value : 0;
 
  	asm(
arch/arm64/kernel/ptrace.c +5 -6
index aa79e81..38a09338 100644
@@ -38,7 +38,6 @@
  #include <linux/tracehook.h>
  #include <linux/elf.h>
 
-#include <asm/compat.h>
  #include <asm/debug-monitors.h>
  #include <asm/pgtable.h>
  #include <asm/syscall.h>
@@ -85,7 +84,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
  #ifdef CONFIG_AARCH32_EL0
  	int i;
 
-	if (!is_compat_task())
+	if (!is_a32_compat_task())
  		goto send_sig;
 
  	for (i = 0; i < ARM_MAX_BRP; ++i) {
@@ -1203,9 +1202,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;
@@ -1232,7 +1231,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;
 
@@ -1343,7 +1342,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);
arch/arm64/kernel/signal.c +2 -2
index a8eafdb..be02f65 100644
@@ -276,7 +276,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
 
  static void setup_restart_syscall(struct pt_regs *regs)
  {
-	if (is_compat_task())
+	if (is_a32_compat_task())
  		compat_setup_restart_syscall(regs);
  	else
  		regs->regs[8] = __NR_restart_syscall;
@@ -295,7 +295,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
  	/*
  	 * Set up the stack frame
  	 */
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
  		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
  			ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
  		else
arch/arm64/kernel/traps.c +2 -1
index 973faec..d77be17 100644
@@ -18,6 +18,7 @@
   */
 
  #include <linux/bug.h>
+#include <linux/compat.h>
  #include <linux/signal.h>
  #include <linux/personality.h>
  #include <linux/kallsyms.h>
@@ -411,7 +412,7 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs)
  {
  #ifdef CONFIG_AARCH32_EL0
  	long ret;
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
  		ret = compat_arm_syscall(regs);
  		if (ret != -ENOSYS)
  			return ret;
#23 lore raw

Re: [PATCH 08/19] arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)

Quoted 13 lines · Zhangjian (Bamvor)

arch/arm64/include/asm/memory.h line 84

Quoted 9 lines
arch/arm64/include/asm/memory.h +2 -2
@@ -78,9 +79,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) ? \

It should be
+#define TASK_SIZE_OF(tsk) (is_compat_thread(task_thread_info(tsk)) ? \
is_compat_thread takes "struct thread_info *thread" while TASK_SIZE_OF takes "struct task_struct *tsk"tsk.

If that doesn't throw an error does that mean that TASK_SIZE_OF is unused?

Andreas.

Signature · 3 lines
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."
maintainer
#24 lore raw

Re: [PATCH 08/19] arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)

Quoted 16 lines · CEST Andreas Schwab
Quoted 13 lines · Zhangjian (Bamvor)

arch/arm64/include/asm/memory.h line 84

Quoted 9 lines
arch/arm64/include/asm/memory.h +2 -2
@@ -78,9 +79,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) ? \

It should be
+#define TASK_SIZE_OF(tsk) (is_compat_thread(task_thread_info(tsk)) ? \
is_compat_thread takes "struct thread_info *thread" while TASK_SIZE_OF takes "struct task_struct *tsk"tsk.

Quoted 2 lines

If that doesn't throw an error does that mean that TASK_SIZE_OF is unused?

I think that is correct. On some architectures, TASK_SIZE (which is used) is defined as TASK_SIZE_OF(current), but the definition above doesn't do that and there are no other users.

Arnd

author
#25 lore raw

PATCH v7 9/19 arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64

In reply to Yury Norov

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.

---
 arch/arm64/include/asm/elf.h         | 13 +++++++++++--
 arch/arm64/include/asm/is_compat.h   | 30 ++++++++++++++++++++++++++++--
 arch/arm64/include/asm/thread_info.h |  2 ++
 3 files changed, 41 insertions(+), 4 deletions(-)
arch/arm64/include/asm/elf.h +11 -2
index bef2d90..a967726 100644
@@ -142,7 +142,11 @@ typedef struct user_fpsimd_state elf_fpregset_t;
  */
 #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
 
-#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
+#define SET_PERSONALITY(ex)		\
+do {						\
+	clear_thread_flag(TIF_32BIT_AARCH64);	\
+	clear_thread_flag(TIF_32BIT);		\
+} while (0)
 
 #define ARCH_DLINFO							\
 do {									\
@@ -182,7 +186,12 @@ typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
 					 ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread		compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
+#define COMPAT_SET_PERSONALITY(ex)		\
+do {						\
+	clear_thread_flag(TIF_32BIT_AARCH64);	\
+	set_thread_flag(TIF_32BIT);		\
+} while (0)
+
 #define COMPAT_ARCH_DLINFO
 extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
 				      int uses_interp);
arch/arm64/include/asm/is_compat.h +28 -2
index 8dba5ca..7726beb 100644
@@ -45,18 +45,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);
 }
 
 
arch/arm64/include/asm/thread_info.h +2 -0
index 4daa559..8802645 100644
@@ -119,6 +119,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_RESTORE_SIGMASK	20
 #define TIF_SINGLESTEP		21
 #define TIF_32BIT		22	/* AARCH32 process */
+#define TIF_32BIT_AARCH64	23	/* 32 bit process on AArch64(ILP32) */
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
@@ -130,6 +131,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_32BIT		(1 << TIF_32BIT)
+#define _TIF_32BIT_AARCH64	(1 << TIF_32BIT_AARCH64)
 
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
 				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
Signature · 1 line
2.7.4
author
#26 lore raw

PATCH v7 10/19 arm64: introduce binfmt_elf32.c

In reply to Yury Norov

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.

---
 arch/arm64/Kconfig               |  1 -
 arch/arm64/include/asm/hwcap.h   |  2 --
 arch/arm64/kernel/Makefile       |  2 +-
 arch/arm64/kernel/binfmt_elf32.c | 31 +++++++++++++++++++++++++++++++
 4 files changed, 32 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm64/kernel/binfmt_elf32.c
arch/arm64/Kconfig +0 -1
index aea8e61..f5735ec 100644
@@ -979,7 +979,6 @@ config AARCH32_EL0
 	def_bool y
 	depends on ARM64_4K_PAGES || EXPERT
 	select COMPAT
-	select COMPAT_BINFMT_ELF
 	select HAVE_UID16
 	select OLD_SIGSUSPEND3
 	select COMPAT_OLD_SIGACTION
arch/arm64/include/asm/hwcap.h +0 -2
index 2c7fc5d..99dfd92 100644
@@ -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
 
arch/arm64/kernel/Makefile +1 -1
index 631a118..60d59cb 100644
@@ -27,7 +27,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
-					   ../../arm/kernel/opcodes.o
+					   ../../arm/kernel/opcodes.o binfmt_elf32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
arch/arm64/kernel/binfmt_elf32.c new file +31 -0
new file mode 100644
index 0000000..aec1c8a
@@ -0,0 +1,31 @@
+/*
+ * Support for AArch32 Linux ELF binaries.
+ */
+
+/* AArch32 EABI. */
+#define EF_ARM_EABI_MASK		0xff000000
+
+#define compat_start_thread		compat_start_thread
+#define COMPAT_SET_PERSONALITY(ex)		\
+do {						\
+	clear_thread_flag(TIF_32BIT_AARCH64);	\
+	set_thread_flag(TIF_32BIT);		\
+} while (0)
+
+#define COMPAT_ARCH_DLINFO
+#define COMPAT_ELF_HWCAP		(compat_elf_hwcap)
+#define COMPAT_ELF_HWCAP2		(compat_elf_hwcap2)
+
+#ifdef __AARCH64EB__
+#define COMPAT_ELF_PLATFORM		("v8b")
+#else
+#define COMPAT_ELF_PLATFORM		("v8l")
+#endif
+
+#define compat_arch_setup_additional_pages \
+					aarch32_setup_vectors_page
+struct linux_binprm;
+extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
+				      int uses_interp);
+
+#include "../../../fs/compat_binfmt_elf.c"
Signature · 1 line
2.7.4
author
#27 lore raw

PATCH v7 11/19 arm64: ilp32: introduce binfmt_ilp32.c

In reply to Yury Norov

to handle ILP32 binaries

---
 arch/arm64/include/asm/elf.h     |  6 +++
 arch/arm64/kernel/Makefile       |  1 +
 arch/arm64/kernel/binfmt_ilp32.c | 96 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+)
 create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
arch/arm64/include/asm/elf.h +6 -0
index a967726..4dcbcec 100644
@@ -174,10 +174,16 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 
 #define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
 
+#ifndef USE_AARCH64_GREG
 /* 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];
+#else /* AArch64 registers for AARCH64/ILP32 */
+#define COMPAT_ELF_NGREG	ELF_NGREG
+#define compat_elf_greg_t	elf_greg_t
+#define compat_elf_gregset_t	elf_gregset_t
+#endif
 
 /* AArch32 EABI. */
 #define EF_ARM_EABI_MASK		0xff000000
arch/arm64/kernel/Makefile +1 -0
index 60d59cb..bcdd4b2 100644
@@ -28,6 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
arch/arm64/kernel/binfmt_ilp32.c new file +96 -0

96 lines not on this page · raw message

Signature · 1 line
2.7.4
author
#28 lore raw

PATCH v7 12/19 arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32

In reply to Yury Norov

Here new aarch32 ptrace syscall handler is introsuced to avoid run-time detection of the task type.

---
 arch/arm64/include/asm/unistd32.h |  2 +-
 arch/arm64/kernel/ptrace.c        | 50 ++++++++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/sys32.c         |  1 +
 include/linux/ptrace.h            |  6 +++++
 kernel/ptrace.c                   | 10 ++++----
 5 files changed, 62 insertions(+), 7 deletions(-)
arch/arm64/include/asm/unistd32.h +1 -1
index b7e8ef1..6da7cbd 100644
@@ -74,7 +74,7 @@ __SYSCALL(__NR_getuid, sys_getuid16)
 			/* 25 was sys_stime */
 __SYSCALL(25, sys_ni_syscall)
 #define __NR_ptrace 26
-__SYSCALL(__NR_ptrace, compat_sys_ptrace)
+__SYSCALL(__NR_ptrace, compat_sys_aarch32_ptrace)
 			/* 27 was sys_alarm */
 __SYSCALL(27, sys_ni_syscall)
 			/* 28 was sys_fstat */
arch/arm64/kernel/ptrace.c +49 -1

70 lines not on this page · raw message

arch/arm64/kernel/sys32.c +1 -0
index a40b134..3752443 100644
@@ -38,6 +38,7 @@ asmlinkage long compat_sys_fadvise64_64_wrapper(void);
 asmlinkage long compat_sys_sync_file_range2_wrapper(void);
 asmlinkage long compat_sys_fallocate_wrapper(void);
 asmlinkage long compat_sys_mmap2_wrapper(void);
+asmlinkage long compat_sys_aarch32_ptrace(void);
 
 #undef __SYSCALL
 #define __SYSCALL(nr, sym)	[nr] = sym,
include/linux/ptrace.h +6 -0
index 504c98a..75887a0 100644
@@ -97,6 +97,12 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
 			    unsigned long data);
 int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
 			    unsigned long data);
+int ptrace_traceme(void);
+struct task_struct *ptrace_get_task_struct(pid_t pid);
+int ptrace_attach(struct task_struct *task, long request,
+			 unsigned long addr, unsigned long flags);
+int ptrace_check_attach(struct task_struct *child, bool ignore_state);
+void ptrace_unfreeze_traced(struct task_struct *task);
 
 /**
  * ptrace_parent - return the task that is tracing the given task
kernel/ptrace.c +5 -5
index d49bfa1..cadf24c 100644
@@ -136,7 +136,7 @@ static bool ptrace_freeze_traced(struct task_struct *task)
 	return ret;
 }
 
-static void ptrace_unfreeze_traced(struct task_struct *task)
+void ptrace_unfreeze_traced(struct task_struct *task)
 {
 	if (task->state != __TASK_TRACED)
 		return;
@@ -168,7 +168,7 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
  * RETURNS:
  * 0 on success, -ESRCH if %child is not ready.
  */
-static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
+int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 {
 	int ret = -ESRCH;
 
@@ -292,7 +292,7 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 	return !err;
 }
 
-static int ptrace_attach(struct task_struct *task, long request,
+int ptrace_attach(struct task_struct *task, long request,
 			 unsigned long addr,
 			 unsigned long flags)
 {
@@ -406,7 +406,7 @@ out:
  * Performs checks and sets PT_PTRACED.
  * Should be used by all ptrace implementations for PTRACE_TRACEME.
  */
-static int ptrace_traceme(void)
+ int ptrace_traceme(void)
 {
 	int ret = -EPERM;
 
@@ -1056,7 +1056,7 @@ int ptrace_request(struct task_struct *child, long request,
 	return ret;
 }
 
-static struct task_struct *ptrace_get_task_struct(pid_t pid)
+struct task_struct *ptrace_get_task_struct(pid_t pid)
 {
 	struct task_struct *child;
 
Signature · 1 line
2.7.4
#29 lore raw

Re: [PATCH 12/19] arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32

The {GET,SET}SIGMASK request of ptrace on ilp32 is wrong, it's handled by ptrace_request(like aarch64). So I write a patch to fix it(just for ilp32). I will send the patch next.

Thanks!

Quoted 180 lines · Yury Norov

Here new aarch32 ptrace syscall handler is introsuced to avoid run-time detection of the task type.

---
  arch/arm64/include/asm/unistd32.h |  2 +-
  arch/arm64/kernel/ptrace.c        | 50 ++++++++++++++++++++++++++++++++++++++-
  arch/arm64/kernel/sys32.c         |  1 +
  include/linux/ptrace.h            |  6 +++++
  kernel/ptrace.c                   | 10 ++++----
  5 files changed, 62 insertions(+), 7 deletions(-)
arch/arm64/include/asm/unistd32.h +1 -1
index b7e8ef1..6da7cbd 100644
@@ -74,7 +74,7 @@ __SYSCALL(__NR_getuid, sys_getuid16)
  			/* 25 was sys_stime */
  __SYSCALL(25, sys_ni_syscall)
  #define __NR_ptrace 26
-__SYSCALL(__NR_ptrace, compat_sys_ptrace)
+__SYSCALL(__NR_ptrace, compat_sys_aarch32_ptrace)
  			/* 27 was sys_alarm */
  __SYSCALL(27, sys_ni_syscall)
  			/* 28 was sys_fstat */
arch/arm64/kernel/ptrace.c +49 -1
index 38a09338..a861105 100644
@@ -29,6 +29,7 @@
  #include<linux/user.h>
  #include<linux/seccomp.h>
  #include<linux/security.h>
+#include<linux/syscalls.h>
  #include<linux/init.h>
  #include<linux/signal.h>
  #include<linux/uaccess.h>
@@ -1114,7 +1115,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;
@@ -1191,8 +1192,55 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
  	return ret;
  }
+
+COMPAT_SYSCALL_DEFINE4(aarch32_ptrace, compat_long_t, request, compat_long_t, pid,
+		       compat_long_t, addr, compat_long_t, data)
+{
+	struct task_struct *child;
+	long ret;
+
+	if (request == PTRACE_TRACEME) {
+		ret = ptrace_traceme();
+		goto out;
+	}
+
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
+		goto out;
+	}
+
+	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
+		ret = ptrace_attach(child, request, addr, data);
+		goto out_put_task_struct;
+	}
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
+				  request == PTRACE_INTERRUPT);
+	if (!ret) {
+		ret = compat_a32_ptrace(child, request, addr, data);
+		if (ret || request != PTRACE_DETACH)
+			ptrace_unfreeze_traced(child);
+	}
+
+ out_put_task_struct:
+	put_task_struct(child);
+ out:
+	return ret;
+}
+
  #endif /* CONFIG_AARCH32_EL0 */
 
+#ifdef CONFIG_COMPAT
+
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+			compat_ulong_t caddr, compat_ulong_t cdata)
+{
+	return compat_ptrace_request(child, request, caddr, cdata);
+}
+
+#endif /* CONFIG_COMPAT */
+
  const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  {
  #ifdef CONFIG_AARCH32_EL0
arch/arm64/kernel/sys32.c +1 -0
index a40b134..3752443 100644
@@ -38,6 +38,7 @@ asmlinkage long compat_sys_fadvise64_64_wrapper(void);
  asmlinkage long compat_sys_sync_file_range2_wrapper(void);
  asmlinkage long compat_sys_fallocate_wrapper(void);
  asmlinkage long compat_sys_mmap2_wrapper(void);
+asmlinkage long compat_sys_aarch32_ptrace(void);
 
  #undef __SYSCALL
  #define __SYSCALL(nr, sym)	[nr] = sym,
include/linux/ptrace.h +6 -0
index 504c98a..75887a0 100644
@@ -97,6 +97,12 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
  			    unsigned long data);
  int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
  			    unsigned long data);
+int ptrace_traceme(void);
+struct task_struct *ptrace_get_task_struct(pid_t pid);
+int ptrace_attach(struct task_struct *task, long request,
+			 unsigned long addr, unsigned long flags);
+int ptrace_check_attach(struct task_struct *child, bool ignore_state);
+void ptrace_unfreeze_traced(struct task_struct *task);
 
  /**
   * ptrace_parent - return the task that is tracing the given task
kernel/ptrace.c +5 -5
index d49bfa1..cadf24c 100644
@@ -136,7 +136,7 @@ static bool ptrace_freeze_traced(struct task_struct *task)
  	return ret;
  }
 
-static void ptrace_unfreeze_traced(struct task_struct *task)
+void ptrace_unfreeze_traced(struct task_struct *task)
  {
  	if (task->state != __TASK_TRACED)
  		return;
@@ -168,7 +168,7 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
   * RETURNS:
   * 0 on success, -ESRCH if %child is not ready.
   */
-static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
+int ptrace_check_attach(struct task_struct *child, bool ignore_state)
  {
  	int ret = -ESRCH;
 
@@ -292,7 +292,7 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
  	return !err;
  }
 
-static int ptrace_attach(struct task_struct *task, long request,
+int ptrace_attach(struct task_struct *task, long request,
  			 unsigned long addr,
  			 unsigned long flags)
  {
@@ -406,7 +406,7 @@ out:
   * Performs checks and sets PT_PTRACED.
   * Should be used by all ptrace implementations for PTRACE_TRACEME.
   */
-static int ptrace_traceme(void)
+ int ptrace_traceme(void)
  {
  	int ret = -EPERM;
 
@@ -1056,7 +1056,7 @@ int ptrace_request(struct task_struct *child, long request,
  	return ret;
  }
 
-static struct task_struct *ptrace_get_task_struct(pid_t pid)
+struct task_struct *ptrace_get_task_struct(pid_t pid)
  {
  	struct task_struct *child;
 
#30 lore raw

PATCH 1/1 ilp32: fix {GET,SET}SIGMASK request for ptrace

In reply to Yury Norov

The function compat_ptrace_request(used by ilp32) don't handle {GET,SET}SIGMASK request, so it will be handled by ptrace_request. But it's wrong because the compat_sigset_t of ilp32 differs from the sigset_t of aarch64. The patch fixes it.

---
  arch/arm64/include/asm/signal_ilp32.h |   22 ++++++++++++
  arch/arm64/kernel/ptrace.c            |   62 
+++++++++++++++++++++++++++++++++
  arch/arm64/kernel/signal_ilp32.c      |   23 +------------
  3 files changed, 85 insertions(+), 22 deletions(-)
(quoted diff) +0 -0

b/arch/arm64/include/asm/signal_ilp32.h
index 30eff23..ed52607 100644

arch/arm64/include/asm/signal_ilp32.h +22 -0
@@ -21,6 +21,28 @@
  int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
  			  struct pt_regs *regs);
 
+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;
+}
+
  #else
 
  static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, 

sigset_t *set,

arch/arm64/kernel/ptrace.c +1 -0
index a861105..8d4cad1 100644
@@ -44,6 +44,7 @@
  #include <asm/syscall.h>
  #include <asm/traps.h>
  #include <asm/system_misc.h>
+#include <asm/signal_ilp32.h>
 
  #define CREATE_TRACE_POINTS
  #include <trace/events/syscalls.h>
@@ -1231,12 +1232,73 @@ COMPAT_SYSCALL_DEFINE4(aarch32_ptrace, 

compat_long_t, request, compat_long_t, pi

  #endif /* CONFIG_AARCH32_EL0 */

+#ifdef CONFIG_ARM64_ILP32
+
+static int compat_ilp32_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t addr, compat_ulong_t data)
+{
+ compat_ulong_t __user *datap = compat_ptr(data);
+ int ret;
+
+ switch (request) {
+ case PTRACE_GETSIGMASK:
+ if (addr != sizeof(compat_sigset_t)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (put_sigset_t((compat_sigset_t __user *)datap, &child->blocked))
+ ret = -EFAULT;
+ else
+ ret = 0;
+ break;
+
+ case PTRACE_SETSIGMASK: {
+ sigset_t new_set;
+ if (addr != sizeof(compat_sigset_t)) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (get_sigset_t(&new_set, (compat_sigset_t __user *)datap)) {
+ ret = -EFAULT;
+ 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;
+ break;
+ }
+
+ default:
+ ret = compat_ptrace_request(child, request, addr, data);
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
#ifdef CONFIG_COMPAT

long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
compat_ulong_t caddr, compat_ulong_t cdata)
{
+#ifdef CONFIG_ARM64_ILP32
+ return compat_ilp32_ptrace(child, request, caddr, cdata);
+#else
return compat_ptrace_request(child, request, caddr, cdata);
+#endif
}

#endif /* CONFIG_COMPAT */

(quoted diff) +0 -0

b/arch/arm64/kernel/signal_ilp32.c
index 8ca64b9..3ef2749 100644

arch/arm64/kernel/signal_ilp32.c +1 -22
@@ -28,6 +28,7 @@
  #include <asm/fpsimd.h>
  #include <asm/signal32_common.h>
  #include <asm/signal_common.h>
+#include <asm/signal_ilp32.h>
  #include <asm/uaccess.h>
  #include <asm/unistd.h>
  #include <asm/ucontext.h>
@@ -58,28 +59,6 @@ struct ilp32_rt_sigframe {
  	struct ilp32_sigframe sig;
  };
 
-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;
-}
-
  static int restore_ilp32_sigframe(struct pt_regs *regs,
                              struct ilp32_sigframe __user *sf)
  {
Signature · 1 line
1.7.7
author
#31 lore raw

Re: [PATCH] ilp32: fix {GET,SET}SIGMASK request for ptrace

Hi Zhou,

Thank you for the patch. The idea is ok, but patch format got broken for some reason. Could you re-send it?

Yury.

Quoted 9 lines · zhouchengming

atus: RO
Content-Length: 4732
Lines: 181

The function compat_ptrace_request(used by ilp32) don't handle {GET,SET}SIGMASK request, so it will be handled by ptrace_request. But it's wrong because the compat_sigset_t of ilp32 differs from the sigset_t of aarch64. The patch fixes it.

Quoted 5 lines
---
 arch/arm64/include/asm/signal_ilp32.h |   22 ++++++++++++
 arch/arm64/kernel/ptrace.c            |   62

+++++++++++++++++++++++++++++++++

Here - unneeded line break

arch/arm64/include/asm/signal_ilp32.h

Quoted 5 lines
 arch/arm64/kernel/signal_ilp32.c      |   23 +------------
 3 files changed, 85 insertions(+), 22 deletions(-)
arch/arm64/include/asm/signal_ilp32.h +0 -0

and here

Quoted 32 lines

index 30eff23..ed52607 100644

arch/arm64/include/asm/signal_ilp32.h +22 -0
@@ -21,6 +21,28 @@
 int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
 			  struct pt_regs *regs);
 
+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;
+}
+
 #else
 
 static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig,
Quoted 1 line

sigset_t *set,

and here

Quoted 13 lines
arch/arm64/kernel/ptrace.c +1 -0
index a861105..8d4cad1 100644
@@ -44,6 +44,7 @@
 #include <asm/syscall.h>
 #include <asm/traps.h>
 #include <asm/system_misc.h>
+#include <asm/signal_ilp32.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
@@ -1231,12 +1232,73 @@ COMPAT_SYSCALL_DEFINE4(aarch32_ptrace,
Quoted 1 line

compat_long_t, request, compat_long_t, pi

and later on the patch

Quoted 115 lines

#endif /* CONFIG_AARCH32_EL0 */

arch/arm64/kernel/ptrace.c +3 -0
+#ifdef CONFIG_ARM64_ILP32
+
+static int compat_ilp32_ptrace(struct task_struct *child, compat_long_t

request,

arch/arm64/kernel/ptrace.c +58 -0
+			compat_ulong_t addr, compat_ulong_t data)
+{
+	compat_ulong_t __user *datap = compat_ptr(data);
+	int ret;
+
+	switch (request) {
+	case PTRACE_GETSIGMASK:
+		if (addr != sizeof(compat_sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (put_sigset_t((compat_sigset_t __user *)datap, &child->blocked))
+			ret = -EFAULT;
+		else
+			ret = 0;
+		break;
+
+	case PTRACE_SETSIGMASK: {
+		sigset_t new_set;
+		if (addr != sizeof(compat_sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (get_sigset_t(&new_set, (compat_sigset_t __user *)datap)) {
+			ret = -EFAULT;
+			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;
+		break;
+	}
+
+	default:
+		ret = compat_ptrace_request(child, request, addr, data);
+	}
+
+	return ret;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
 #ifdef CONFIG_COMPAT
 
 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 			compat_ulong_t caddr, compat_ulong_t cdata)
 {
+#ifdef CONFIG_ARM64_ILP32
+	return compat_ilp32_ptrace(child, request, caddr, cdata);
+#else
 	return compat_ptrace_request(child, request, caddr, cdata);
+#endif
 }
 
 #endif /* CONFIG_COMPAT */
arch/arm64/kernel/signal_ilp32.c +1 -22
index 8ca64b9..3ef2749 100644
@@ -28,6 +28,7 @@
 #include <asm/fpsimd.h>
 #include <asm/signal32_common.h>
 #include <asm/signal_common.h>
+#include <asm/signal_ilp32.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/ucontext.h>
@@ -58,28 +59,6 @@ struct ilp32_rt_sigframe {
 	struct ilp32_sigframe sig;
 };
 
-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;
-}
-
 static int restore_ilp32_sigframe(struct pt_regs *regs,
                             struct
#32 lore raw

Re: [PATCH] ilp32: fix {GET,SET}SIGMASK request for ptrace

Quoted 6 lines · Yury Norov

Hi Zhou,

Thank you for the patch. The idea is ok, but patch format got broken for some reason. Could you re-send it?

Yury.

Sorry for the broken patch, maybe my mail guest has some problems. So I send the patch as an attachment.

Thanks!

Quoted 189 lines · zhouchengming
Quoted 9 lines

atus: RO
Content-Length: 4732
Lines: 181

The function compat_ptrace_request(used by ilp32) don't handle {GET,SET}SIGMASK request, so it will be handled by ptrace_request. But it's wrong because the compat_sigset_t of ilp32 differs from the sigset_t of aarch64. The patch fixes it.

Quoted 5 lines
---
  arch/arm64/include/asm/signal_ilp32.h |   22 ++++++++++++
  arch/arm64/kernel/ptrace.c            |   62

+++++++++++++++++++++++++++++++++

Here - unneeded line break

arch/arm64/include/asm/signal_ilp32.h

Quoted 5 lines
  arch/arm64/kernel/signal_ilp32.c      |   23 +------------
  3 files changed, 85 insertions(+), 22 deletions(-)
arch/arm64/include/asm/signal_ilp32.h +0 -0

and here

Quoted 32 lines

index 30eff23..ed52607 100644

arch/arm64/include/asm/signal_ilp32.h +22 -0
@@ -21,6 +21,28 @@
  int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
  			  struct pt_regs *regs);
 
+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;
+}
+
  #else
 
  static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig,
Quoted 1 line

sigset_t *set,

and here

Quoted 13 lines
arch/arm64/kernel/ptrace.c +1 -0
index a861105..8d4cad1 100644
@@ -44,6 +44,7 @@
  #include<asm/syscall.h>
  #include<asm/traps.h>
  #include<asm/system_misc.h>
+#include<asm/signal_ilp32.h>
 
  #define CREATE_TRACE_POINTS
  #include<trace/events/syscalls.h>
@@ -1231,12 +1232,73 @@ COMPAT_SYSCALL_DEFINE4(aarch32_ptrace,
Quoted 1 line

compat_long_t, request, compat_long_t, pi

and later on the patch

Quoted 109 lines
  #endif /* CONFIG_AARCH32_EL0 */
arch/arm64/kernel/ptrace.c +3 -0
+#ifdef CONFIG_ARM64_ILP32
+
+static int compat_ilp32_ptrace(struct task_struct *child, compat_long_t

request,

arch/arm64/kernel/ptrace.c +58 -0
+			compat_ulong_t addr, compat_ulong_t data)
+{
+	compat_ulong_t __user *datap = compat_ptr(data);
+	int ret;
+
+	switch (request) {
+	case PTRACE_GETSIGMASK:
+		if (addr != sizeof(compat_sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (put_sigset_t((compat_sigset_t __user *)datap,&child->blocked))
+			ret = -EFAULT;
+		else
+			ret = 0;
+		break;
+
+	case PTRACE_SETSIGMASK: {
+		sigset_t new_set;
+		if (addr != sizeof(compat_sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (get_sigset_t(&new_set, (compat_sigset_t __user *)datap)) {
+			ret = -EFAULT;
+			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;
+		break;
+	}
+
+	default:
+		ret = compat_ptrace_request(child, request, addr, data);
+	}
+
+	return ret;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
  #ifdef CONFIG_COMPAT
 
  long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
  			compat_ulong_t caddr, compat_ulong_t cdata)
  {
+#ifdef CONFIG_ARM64_ILP32
+	return compat_ilp32_ptrace(child, request, caddr, cdata);
+#else
  	return compat_ptrace_request(child, request, caddr, cdata);
+#endif
  }
 
  #endif /* CONFIG_COMPAT */
arch/arm64/kernel/signal_ilp32.c +1 -18
index 8ca64b9..3ef2749 100644
@@ -28,6 +28,7 @@
  #include<asm/fpsimd.h>
  #include<asm/signal32_common.h>
  #include<asm/signal_common.h>
+#include<asm/signal_ilp32.h>
  #include<asm/uaccess.h>
  #include<asm/unistd.h>
  #include<asm/ucontext.h>
@@ -58,28 +59,6 @@ struct ilp32_rt_sigframe {
  	struct ilp32_sigframe sig;
  };
 
-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;
-
Quoted 9 lines

arch/arm64/kernel/signal_ilp32.c struct ilp32_rt_sigframe { · line 63

Quoted 6 lines
arch/arm64/kernel/signal_ilp32.c +0 -4
-	set->sig[0] = s32.sig[0] | (((long)s32.sig[1])<<  32);
-	return 0;
-}
-
  static int restore_ilp32_sigframe(struct pt_regs *regs,
                              struct

.

-------------- next part --------------

Quoted 1 line

From 06f5abeca59069cb41b0b4fdfa06240d3f78910d Mon Sep 17 00:00:00 2001

From: Zhou Chengming <[email protected]>
Date: Mon, 27 Jun 2016 12:57:02 +0800
Subject: [PATCH] ilp32: fix {GET,SET}SIGMASK request for ptrace

The function compat_ptrace_request(used by ilp32) don't handle {GET,SET}SIGMASK request, so it will be handled by ptrace_request. But it's wrong because the compat_sigset_t of ilp32 differs from the sigset_t of aarch64. The patch fixes it.

---
 arch/arm64/include/asm/signal_ilp32.h |   22 ++++++++++++
 arch/arm64/kernel/ptrace.c            |   62 +++++++++++++++++++++++++++++++++
 arch/arm64/kernel/signal_ilp32.c      |   23 +------------
 3 files changed, 85 insertions(+), 22 deletions(-)
arch/arm64/include/asm/signal_ilp32.h +22 -0
index 30eff23..ed52607 100644
@@ -21,6 +21,28 @@
 int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
 			  struct pt_regs *regs);
 
+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;
+}
+
 #else
 
 static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
arch/arm64/kernel/ptrace.c +62 -0

80 lines not on this page · raw message

arch/arm64/kernel/signal_ilp32.c +1 -22
index 8ca64b9..3ef2749 100644
@@ -28,6 +28,7 @@
 #include <asm/fpsimd.h>
 #include <asm/signal32_common.h>
 #include <asm/signal_common.h>
+#include <asm/signal_ilp32.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/ucontext.h>
@@ -58,28 +59,6 @@ struct ilp32_rt_sigframe {
 	struct ilp32_sigframe sig;
 };
 
-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;
-}
-
 static int restore_ilp32_sigframe(struct pt_regs *regs,
                             struct ilp32_sigframe __user *sf)
 {
Signature · 1 line
1.7.7
author
#33 lore raw

Re: [PATCH] ilp32: fix {GET,SET}SIGMASK request for ptrace

In reply to zhouchengming
Quoted 4 lines · zhouchengming

The function compat_ptrace_request(used by ilp32) don't handle {GET,SET}SIGMASK request, so it will be handled by ptrace_request. But it's wrong because the compat_sigset_t of ilp32 differs from the sigset_t of aarch64. The patch fixes it.

Hi Zhou, all,

Reviewing your patch I found that we have 2 identical declarations of put_sigset_t() and get_sigset_t(). So I moved it under arch/arm64/include/asm/signal32_common.h

I also reworked related code to remove unneeded function and variable declarations. With all that your patch is looking like below. You can try latest series here: https://github.com/norov/linux/tree/ilp32-4.8

It's based on v4.8, and addresses some comments. I'm going to meld this patch with current patchset as it basicly the bugfux and update submission when I'll finish with all comments.

Yury.

From 6a023da977713e9eade0a404c4f000d432d1fd67 Mon Sep 17 00:00:00 2001
From: Yury Norov <[email protected]>
Date: Sat, 13 Aug 2016 17:36:59 +0300
Subject: [PATCH] aaa

---
 arch/arm64/include/asm/signal32.h        |  3 ++
 arch/arm64/include/asm/signal32_common.h |  3 ++
 arch/arm64/include/asm/signal_ilp32.h    |  4 +++
 arch/arm64/kernel/ptrace.c               | 47 ++++++++++++++++++++++++++++++--
 arch/arm64/kernel/signal32.c             | 22 ---------------
 arch/arm64/kernel/signal32_common.c      | 21 ++++++++++++++
 arch/arm64/kernel/signal_ilp32.c         | 25 +----------------
 7 files changed, 76 insertions(+), 49 deletions(-)
arch/arm64/include/asm/signal32.h +3 -0
index e68fcce..1c4ede7 100644
@@ -13,6 +13,9 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#include <asm/signal32_common.h>
+
 #ifndef __ASM_SIGNAL32_H
 #define __ASM_SIGNAL32_H
 
arch/arm64/include/asm/signal32_common.h +3 -0
index b4f2099..e3e2d01 100644
@@ -19,6 +19,9 @@
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from);
 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from);
 
+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 */
arch/arm64/include/asm/signal_ilp32.h +4 -0
index 30eff23..3c6d737 100644
@@ -11,6 +11,10 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#include <asm/signal32_common.h>
+#include <asm/signal_common.h>
+
 #ifndef __ASM_SIGNAL_ILP32_H
 #define __ASM_SIGNAL_ILP32_H
 
arch/arm64/kernel/ptrace.c +44 -3

65 lines not on this page · raw message

arch/arm64/kernel/signal32.c +0 -22
index b103af3..f2c1a38 100644
@@ -103,28 +103,6 @@ struct compat_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.
  *
arch/arm64/kernel/signal32_common.c +21 -0
index 8fbb609..4a45aa6 100644
@@ -28,6 +28,27 @@
 #include <asm/uaccess.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;
+}
+
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
 {
 	int err;
arch/arm64/kernel/signal_ilp32.c +1 -24
index 8ca64b9..7cc9122 100644
@@ -26,8 +26,7 @@
 
 #include <asm/esr.h>
 #include <asm/fpsimd.h>
-#include <asm/signal32_common.h>
-#include <asm/signal_common.h>
+#include <asm/signal_ilp32.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/ucontext.h>
@@ -58,28 +57,6 @@ struct ilp32_rt_sigframe {
 	struct ilp32_sigframe sig;
 };
 
-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;
-}
-
 static int restore_ilp32_sigframe(struct pt_regs *regs,
                             struct ilp32_sigframe __user *sf)
 {
Signature · 1 line
2.7.4
author
#34 lore raw

PATCH v7 13/19 arm64: ilp32: share aarch32 syscall handlers

In reply to Yury Norov

off_t is passed in register pair just like in aarch32. In this patch corresponding aarch32 handlers are shared to ilp32 code.

---
 arch/arm64/kernel/Makefile         |  1 +
 arch/arm64/kernel/entry32.S        | 65 --------------------------
 arch/arm64/kernel/entry32_common.S | 93 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+), 65 deletions(-)
 create mode 100644 arch/arm64/kernel/entry32_common.S
arch/arm64/kernel/Makefile +1 -0
index bcdd4b2..d11572d 100644
@@ -29,6 +29,7 @@ arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
 arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
+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
arch/arm64/kernel/entry32.S +0 -65

68 lines not on this page · raw message

arch/arm64/kernel/entry32_common.S new file +93 -0

93 lines not on this page · raw message

Signature · 1 line
2.7.4
author
#35 lore raw

PATCH v7 14/19 arm64: ilp32: add sys_ilp32.c and a separate table (in entry.S) to use it

In reply to Yury Norov

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.

---
 arch/arm64/include/asm/unistd.h |  6 ++-
 arch/arm64/kernel/Makefile      |  2 +-
 arch/arm64/kernel/entry.S       | 29 +++++++++++++-
 arch/arm64/kernel/sys_ilp32.c   | 84 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm64/kernel/sys_ilp32.c
arch/arm64/include/asm/unistd.h +5 -1
index fe9d6c1..250654c 100644
@@ -13,13 +13,17 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#ifdef CONFIG_COMPAT
+#define __ARCH_WANT_SYS_LLSEEK
+#endif
+
 #ifdef CONFIG_AARCH32_EL0
 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
arch/arm64/kernel/Makefile +1 -1
index d11572d..205bc03 100644
@@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
 arm64-obj-$(CONFIG_COMPAT)		+= entry32_common.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
arch/arm64/kernel/entry.S +27 -2
index 21a0624..b2b9725 100644
@@ -239,6 +239,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.
  */
@@ -501,6 +518,7 @@ el0_svc_compat:
 	 * AArch32 syscall handling
 	 */
 	adrp	stbl, compat_sys_call_table	// load compat syscall table pointer
+	ldr     x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w7			// syscall number in w7 (r7)
 	mov     sc_nr, #__NR_compat_syscalls
 	b	el0_svc_naked
@@ -717,15 +735,22 @@ ENDPROC(ret_from_fork)
 	.align	6
 el0_svc:
 	adrp	stbl, sys_call_table		// load syscall table pointer
+	ldr	x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w8			// syscall number in w8
 	mov	sc_nr, #__NR_syscalls
+#ifdef CONFIG_ARM64_ILP32
+	adrp	x17, sys_call_ilp32_table	// load ilp32 syscall table pointer
+	tst	x16, #_TIF_32BIT_AARCH64
+	b.eq	el0_svc_naked			// We are using LP64  syscall table
+	mov	stbl, x17			// We are using ILP32 syscall table
+	delouse_input_regs
+#endif
 el0_svc_naked:					// compat entry point
 	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
 	ct_user_exit 1
 
-	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
-	tst	x16, #_TIF_SYSCALL_WORK
+	tst	x16, #_TIF_SYSCALL_WORK		// check for syscall hooks
 	b.ne	__sys_trace
 	cmp     scno, sc_nr                     // check upper syscall limit
 	b.hs	ni_sys
arch/arm64/kernel/sys_ilp32.c new file +84 -0

84 lines not on this page · raw message

Signature · 1 line
2.7.4
author
#36 lore raw

Re: [PATCH 14/19] arm64: ilp32: add sys_ilp32.c and a separate table (in entry.S) to use it

Quoted 91 lines · Yury Norov

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.

---
 arch/arm64/include/asm/unistd.h |  6 ++-
 arch/arm64/kernel/Makefile      |  2 +-
 arch/arm64/kernel/entry.S       | 29 +++++++++++++-
 arch/arm64/kernel/sys_ilp32.c   | 84 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm64/kernel/sys_ilp32.c
arch/arm64/include/asm/unistd.h +5 -1
index fe9d6c1..250654c 100644
@@ -13,13 +13,17 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#ifdef CONFIG_COMPAT
+#define __ARCH_WANT_SYS_LLSEEK
+#endif
+
 #ifdef CONFIG_AARCH32_EL0
 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
arch/arm64/kernel/Makefile +1 -1
index d11572d..205bc03 100644
@@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
 arm64-obj-$(CONFIG_COMPAT)		+= entry32_common.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
arch/arm64/kernel/entry.S +18 -0
index 21a0624..b2b9725 100644
@@ -239,6 +239,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.
  */
@@ -501,6 +518,7 @@ el0_svc_compat:
 	 * AArch32 syscall handling
 	 */
 	adrp	stbl, compat_sys_call_table	// load compat syscall table pointer
+	ldr     x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w7			// syscall number in w7 (r7)
 	mov     sc_nr, #__NR_compat_syscalls
 	b	el0_svc_naked
@@ -717,15 +735,22 @@ ENDPROC(ret_from_fork)
 	.align	6
 el0_svc:
 	adrp	stbl, sys_call_table		// load syscall table pointer

arch/arm64/kernel/entry.S ENDPROC(ret_from_fork) · line 747

Quoted 10 lines
arch/arm64/kernel/entry.S +8 -0
+	ldr	x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w8			// syscall number in w8
 	mov	sc_nr, #__NR_syscalls
+#ifdef CONFIG_ARM64_ILP32
+	adrp	x17, sys_call_ilp32_table	// load ilp32 syscall table pointer
+	tst	x16, #_TIF_32BIT_AARCH64
+	b.eq	el0_svc_naked			// We are using LP64  syscall table
+	mov	stbl, x17			// We are using ILP32 syscall table
+	delouse_input_regs
+#endif

It should be like this:
#ifdef CONFIG_ARM64_ILP32

        tst     x16, #_TIF_32BIT_AARCH64
        b.eq    el0_svc_naked                   // We are using LP64  syscall table
        adrp    stbl, sys_call_ilp32_table      // load ilp32 syscall table pointer

delouse_input_regs
#endif

Quoted 103 lines
arch/arm64/kernel/entry.S +1 -2
 el0_svc_naked:					// compat entry point
 	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
 	ct_user_exit 1
 
-	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
-	tst	x16, #_TIF_SYSCALL_WORK
+	tst	x16, #_TIF_SYSCALL_WORK		// check for syscall hooks
 	b.ne	__sys_trace
 	cmp     scno, sc_nr                     // check upper syscall limit
 	b.hs	ni_sys
arch/arm64/kernel/sys_ilp32.c new file +84 -0
new file mode 100644
index 0000000..00c4d4b
@@ -0,0 +1,84 @@
+/*
+ * AArch64- ILP32 specific system calls implementation
+ *
+ * Copyright (C) 2016 Cavium Inc.
+ * Author: Andrew Pinski <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#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>
+
+/*
+ * Using aarch32 syscall handlerss where off_t is passed.
+ */
+#define compat_sys_fadvise64_64		compat_sys_fadvise64_64_wrapper
+#define compat_sys_fallocate		compat_sys_fallocate_wrapper
+#define compat_sys_fcntl64		sys_fcntl
+#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_shmat		sys_shmat
+#define compat_sys_sync_file_range	compat_sys_sync_file_range2_wrapper
+#define compat_sys_truncate64		compat_sys_truncate64_wrapper
+#define sys_mmap2			compat_sys_mmap2_wrapper
+#define sys_ptrace			compat_sys_ptrace
+
+/*
+ * Use non-compat syscall handlerss where stat and statfs structure
+ * pointers are passed, as their layout is identical to LP64.
+ */
+#define compat_sys_fstatfs64		sys_fstatfs
+#define compat_sys_statfs64		sys_statfs
+#define sys_fstat64			sys_newfstat
+#define sys_fstatat64			sys_newfstatat
+
+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);
+#define compat_sys_rt_sigreturn        ilp32_sys_rt_sigreturn_wrapper
+
+#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>
+};
Signature · 1 line
2.7.4
author
#37 lore raw

PATCH v7 15/19 arm64: signal: share lp64 signal routines to ilp32

In reply to Yury Norov

After that, it will be possible to reuse it in ilp32.

---
 arch/arm64/include/asm/signal_common.h | 33 ++++++++++++
 arch/arm64/kernel/signal.c             | 93 +++++++++++++++++++++-------------
 2 files changed, 92 insertions(+), 34 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal_common.h
arch/arm64/include/asm/signal_common.h new file +33 -0
new file mode 100644
index 0000000..756ed2c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2016 Cavium Networks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_SIGNAL_COMMON_H
+#define __ASM_SIGNAL_COMMON_H
+
+#include <linux/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/fpsimd.h>
+
+int preserve_fpsimd_context(struct fpsimd_context __user *ctx);
+int restore_fpsimd_context(struct fpsimd_context __user *ctx);
+int setup_sigcontext(struct sigcontext __user *uc_mcontext, struct pt_regs *regs);
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sf);
+void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+			void __user *frame, off_t sigframe_off, int usig);
+
+#endif /* __ASM_SIGNAL_COMMON_H */
arch/arm64/kernel/signal.c +59 -34

174 lines not on this page · raw message

Signature · 1 line
2.7.4
author
#38 lore raw

PATCH v7 16/19 arm64: signal32: move ilp32 and aarch32 common code to separated file

In reply to Yury Norov
---
 arch/arm64/include/asm/signal32_common.h |  25 +++++++
 arch/arm64/kernel/Makefile               |   2 +-
 arch/arm64/kernel/signal32.c             |  85 -----------------------
 arch/arm64/kernel/signal32_common.c      | 115 +++++++++++++++++++++++++++++++
 4 files changed, 141 insertions(+), 86 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal32_common.h
 create mode 100644 arch/arm64/kernel/signal32_common.c
arch/arm64/include/asm/signal32_common.h new file +25 -0
new file mode 100644
index 0000000..b4f2099
@@ -0,0 +1,25 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGNAL32_COMMON_H
+#define __ASM_SIGNAL32_COMMON_H
+
+#ifdef CONFIG_COMPAT
+
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from);
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from);
+
+#endif /* CONFIG_COMPAT*/
+
+#endif /* __ASM_SIGNAL32_COMMON_H */
+
arch/arm64/kernel/Makefile +1 -1
index 205bc03..d69bd40 100644
@@ -29,7 +29,7 @@ arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
 arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
-arm64-obj-$(CONFIG_COMPAT)		+= 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
arch/arm64/kernel/signal32.c +0 -85

91 lines not on this page · raw message

arch/arm64/kernel/signal32_common.c new file +115 -0

115 lines not on this page · raw message

Signature · 1 line
2.7.4
author
#39 lore raw

PATCH v7 17/19 arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext

In reply to Yury Norov

From: Andrew Pinski <[email protected]>

ILP32 uses AARCH32 compat structures and syscall handlers for signals. But ILP32 struct rt_sigframe and ucontext differs from both LP64 and AARCH32. So some specific mechanism is needed to take care of it.

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

194 lines not on this page · raw message

Signature · 1 line
2.7.4
author
#40 lore raw

PATCH v7 18/19 arm64:ilp32: add vdso-ilp32 and use for signal return

In reply to Yury Norov

From: Philipp Tomsich <[email protected]>

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

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

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

---
 arch/arm64/include/asm/vdso.h                 |  6 ++
 arch/arm64/kernel/Makefile                    |  7 ++
 arch/arm64/kernel/asm-offsets.c               |  7 ++
 arch/arm64/kernel/signal.c                    |  2 +
 arch/arm64/kernel/vdso-ilp32/.gitignore       |  2 +
 arch/arm64/kernel/vdso-ilp32/Makefile         | 74 +++++++++++++++++++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S     | 33 ++++++++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++++++++++
 arch/arm64/kernel/vdso.c                      | 61 ++++++++++++++---
 arch/arm64/kernel/vdso/gettimeofday.S         | 20 +++++-
 10 files changed, 294 insertions(+), 13 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
arch/arm64/include/asm/vdso.h +6 -0
index 839ce00..649a9a4 100644
@@ -29,6 +29,12 @@
 
 #include <generated/vdso-offsets.h>
 
+#ifdef CONFIG_ARM64_ILP32
+#include <generated/vdso-ilp32-offsets.h>
+#else
+#define vdso_offset_sigtramp_ilp32
+#endif
+
 #define VDSO_SYMBOL(base, name)						   \
 ({									   \
 	(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
arch/arm64/kernel/Makefile +7 -0
index ae8aacb..15fc0b2 100644
@@ -51,6 +51,7 @@ arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
 arm64-obj-$(CONFIG_HIBERNATION)		+= hibernate.o hibernate-asm.o
 
 obj-y					+= $(arm64-obj-y) vdso/
+obj-$(CONFIG_ARM64_ILP32)		+= vdso-ilp32/
 obj-m					+= $(arm64-obj-m)
 head-y					:= head.o
 extra-y					+= $(head-y) vmlinux.lds
@@ -58,3 +59,9 @@ extra-y					+= $(head-y) vmlinux.lds
 # vDSO - this must be built first to generate the symbol offsets
 $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
 $(obj)/vdso/vdso-offsets.h: $(obj)/vdso
+
+ifeq ($(CONFIG_ARM64_ILP32),y)
+# vDSO - this must be built first to generate the symbol offsets
+$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h
+$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32
+endif
arch/arm64/kernel/asm-offsets.c +7 -0
index 06090db..0eb55fe 100644
@@ -102,6 +102,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();
arch/arm64/kernel/signal.c +2 -0
index 241bfeb..7142b12 100644
@@ -267,6 +267,8 @@ void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 
 	if (ka->sa.sa_flags & SA_RESTORER)
 		sigtramp = ka->sa.sa_restorer;
+	else if (is_ilp32_compat_task())
+		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32);
 	else
 		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
 
arch/arm64/kernel/vdso-ilp32/.gitignore new file +2 -0
new file mode 100644
index 0000000..61806c3
@@ -0,0 +1,2 @@
+vdso-ilp32.lds
+vdso-ilp32-offsets.h
arch/arm64/kernel/vdso-ilp32/Makefile new file +74 -0

74 lines not on this page · raw message

arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S new file +33 -0
new file mode 100644
index 0000000..46ac072
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <[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
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S new file +95 -0

95 lines not on this page · raw message

arch/arm64/kernel/vdso.c +51 -10

118 lines not on this page · raw message

arch/arm64/kernel/vdso/gettimeofday.S +17 -3
index efa79e8..a2d8a70 100644
@@ -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
 use_syscall	.req	w7
 seqcnt		.req	w8
@@ -51,6 +61,8 @@ seqcnt		.req	w8
 /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
 ENTRY(__kernel_gettimeofday)
 	.cfi_startproc
+	DELOUSE(0)
+	DELOUSE(1)
 	mov	x2, x30
 	.cfi_register x30, x2
 
@@ -68,7 +80,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
@@ -88,6 +100,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, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
 	b.ne	2f
@@ -159,7 +172,7 @@ ENTRY(__kernel_clock_gettime)
 
 6:	/* Store to the user timespec. */
 	lsr	x11, x11, x12
-	stp	x10, x11, [x1, #TSPEC_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)]
 	mov	x0, xzr
 	ret
 7:
@@ -174,6 +187,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
 	b.ne	1f
@@ -187,7 +201,7 @@ ENTRY(__kernel_clock_getres)
 	ldr	x2, 6f
 2:
 	cbz	w1, 3f
-	stp	xzr, x2, [x1]
+	stp	PTR_REG(zr), PTR_REG(2), [x1]
 
 3:	/* res == NULL. */
 	mov	w0, wzr
Signature · 1 line
2.7.4
#41 lore raw

Re: [PATCH 18/19] arm64:ilp32: add vdso-ilp32 and use for signal return

Quoted 18 lines · Yury Norov
arch/arm64/kernel/vdso.c +6 -0
index 2a0de6f..e48ea34 100644
@@ -40,6 +40,12 @@ extern char vdso_start, vdso_end;
 static unsigned long vdso_pages;
 static struct page **vdso_pagelist;
 
+#ifdef CONFIG_ARM64_ILP32
+extern char vdso_ilp32_start, vdso_ilp32_end;
+static unsigned long vdso_ilp32_pages;
+static struct page **vdso_ilp32_pagelist;
+#endif
+
 /*
  * The vDSO data page.
  */

arch/arm64/kernel/vdso.c int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) · line 119

Quoted 7 lines
arch/arm64/kernel/vdso.c +1 -3
@@ -110,24 +116,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 }
 #endif /* CONFIG_AARCH32_EL0 */
 
-static struct vm_special_mapping vdso_spec[2];
-
-static int __init vdso_init(void)
+static int __init vdso_init_common(char *vdso_start, char *vdso_end,

Using the same name for the parameter as for the global variable is dangerous ....

arch/arm64/kernel/vdso.c int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) · line 128

Quoted 10 lines
arch/arm64/kernel/vdso.c +6 -1
+					  unsigned long *vdso_pagesp,
+					  struct page ***vdso_pagelistp,
+					  struct vm_special_mapping* vdso_spec)
 {
 	int i;
+	unsigned long vdso_pages;
+	struct page **vdso_pagelist;
 
-	if (memcmp(&vdso_start, "\177ELF", 4)) {
+	if (memcmp(vdso_start, "\177ELF", 4)) {

... because forgetting to remove & can be fatal, and your compiler may not even warn you.

Andreas.

Signature · 3 lines
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."
author
#42 lore raw

Re: [PATCH 18/19] arm64:ilp32: add vdso-ilp32 and use for signal return

Quoted 39 lines · Andreas Schwab
Quoted 18 lines · Yury Norov
arch/arm64/kernel/vdso.c +6 -0
index 2a0de6f..e48ea34 100644
@@ -40,6 +40,12 @@ extern char vdso_start, vdso_end;
 static unsigned long vdso_pages;
 static struct page **vdso_pagelist;
 
+#ifdef CONFIG_ARM64_ILP32
+extern char vdso_ilp32_start, vdso_ilp32_end;
+static unsigned long vdso_ilp32_pages;
+static struct page **vdso_ilp32_pagelist;
+#endif
+
 /*
  * The vDSO data page.
  */

arch/arm64/kernel/vdso.c int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) · line 119

Quoted 7 lines
arch/arm64/kernel/vdso.c +1 -3
@@ -110,24 +116,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 }
 #endif /* CONFIG_AARCH32_EL0 */
 
-static struct vm_special_mapping vdso_spec[2];
-
-static int __init vdso_init(void)
+static int __init vdso_init_common(char *vdso_start, char *vdso_end,

Using the same name for the parameter as for the global variable is dangerous ....

Quoted 8 lines
arch/arm64/kernel/vdso.c +5 -0
+					  unsigned long *vdso_pagesp,
+					  struct page ***vdso_pagelistp,
+					  struct vm_special_mapping* vdso_spec)
 {
 	int i;
+	unsigned long vdso_pages;
+	struct page **vdso_pagelist;
 
Quoted 7 lines

arch/arm64/kernel/vdso.c int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp) · line 128

Quoted 2 lines
arch/arm64/kernel/vdso.c +1 -1
-	if (memcmp(&vdso_start, "\177ELF", 4)) {
+	if (memcmp(vdso_start, "\177ELF", 4)) {

... because forgetting to remove & can be fatal, and your compiler may not even warn you.

Andreas.

Fixed. See here: https://github.com/norov/linux/tree/ilp32-4.8
Thanks.

Yury.

author
#43 lore raw

PATCH v7 19/19 arm64:ilp32: add ARM64_ILP32 to Kconfig

In reply to Yury Norov

From: Andrew Pinski <[email protected]>

This patch adds the config option for ILP32.

---
 arch/arm64/Kconfig | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
arch/arm64/Kconfig +9 -1
index f5735ec..2897648 100644
@@ -972,7 +972,7 @@ source "fs/Kconfig.binfmt"
 
 config COMPAT
 	bool
-	depends on AARCH32_EL0
+	depends on AARCH32_EL0 || ARM64_ILP32
 
 config AARCH32_EL0
 	bool "Kernel support for 32-bit EL0"
@@ -994,6 +994,14 @@ config AARCH32_EL0
 
 	  If you want to execute 32-bit userspace applications, say Y.
 
+config ARM64_ILP32
+	bool "Kernel support for ILP32"
+	select COMPAT
+	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
Signature · 1 line
2.7.4