diff options
author | Andrey Konovalov <andrey.konovalov@linaro.org> | 2015-04-14 17:42:45 +0300 |
---|---|---|
committer | Andrey Konovalov <andrey.konovalov@linaro.org> | 2015-04-14 17:42:45 +0300 |
commit | 3aec0b300e0f65d4467ca9c951da919938c36e7c (patch) | |
tree | 387d5eaeb5907b4d37ddfc923132cbac36a8caf8 /arch/arm64/include | |
parent | 29dfbd875f09ec67d28033da496c7e4613fabbc9 (diff) | |
parent | 9b4db147ac19c2320edec431d93193f42e32d425 (diff) |
Merge branch 'tracking-ilp32' into merge-linux-linaroll-20150414.0
Diffstat (limited to 'arch/arm64/include')
-rw-r--r-- | arch/arm64/include/asm/compat.h | 59 | ||||
-rw-r--r-- | arch/arm64/include/asm/elf.h | 100 | ||||
-rw-r--r-- | arch/arm64/include/asm/fpsimd.h | 2 | ||||
-rw-r--r-- | arch/arm64/include/asm/hwcap.h | 2 | ||||
-rw-r--r-- | arch/arm64/include/asm/processor.h | 11 | ||||
-rw-r--r-- | arch/arm64/include/asm/ptrace.h | 2 | ||||
-rw-r--r-- | arch/arm64/include/asm/signal32.h | 4 | ||||
-rw-r--r-- | arch/arm64/include/asm/stat.h | 4 | ||||
-rw-r--r-- | arch/arm64/include/asm/thread_info.h | 1 | ||||
-rw-r--r-- | arch/arm64/include/asm/unistd.h | 6 | ||||
-rw-r--r-- | arch/arm64/include/asm/vdso.h | 4 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/bitsperlong.h | 9 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/posix_types.h | 8 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/siginfo.h | 33 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/signal.h | 34 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/unistd.h | 6 |
16 files changed, 265 insertions, 20 deletions
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 7fbed6919b54..58e97c6a4628 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -76,6 +76,9 @@ struct compat_timeval { s32 tv_usec; }; +/* ILP32 uses 64bit time_t and not the above compat structures */ +#define COMPAT_USE_64BIT_TIME (!is_a32_compat_task()) + struct compat_stat { #ifdef __AARCH64EB__ short st_dev; @@ -214,6 +217,9 @@ typedef struct compat_siginfo { } _sifields; } compat_siginfo_t; +/* ILP32 uses the native siginfo and not the compat struct */ +#define COMPAT_USE_NATIVE_SIGINFO (!is_a32_compat_task()) + #define COMPAT_OFF_T_MAX 0x7fffffff #define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL @@ -299,6 +305,16 @@ struct compat_shmid64_ds { compat_ulong_t __unused5; }; +#define COMPAT_ELF_HWCAP \ + (is_a32_compat_task() \ + ? compat_elf_hwcap \ + : elf_hwcap) + +#define COMPAT_ELF_HWCAP2 \ + (is_a32_compat_task() \ + ? compat_elf_hwcap2 \ + : 0) + static inline int is_compat_task(void) { return test_thread_flag(TIF_32BIT); @@ -317,5 +333,48 @@ static inline int is_compat_thread(struct thread_info *thread) } #endif /* CONFIG_COMPAT */ + +#ifdef CONFIG_AARCH32_EL0 +static inline int is_a32_compat_task(void) +{ + return test_thread_flag(TIF_AARCH32); +} +static inline int is_a32_compat_thread(struct thread_info *thread) +{ + return test_ti_thread_flag(thread, TIF_AARCH32); +} +#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 + +#ifdef CONFIG_ARM64_ILP32 +static inline int is_ilp32_compat_task(void) +{ + return test_thread_flag(TIF_32BIT) && !is_a32_compat_task(); +} +static inline int is_ilp32_compat_thread(struct thread_info *thread) +{ + return test_ti_thread_flag(thread, TIF_32BIT) && + !is_a32_compat_thread(thread); +} +#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 + + #endif /* __KERNEL__ */ #endif /* __ASM_COMPAT_H */ diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 1f65be393139..e9f3891fd68a 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -16,6 +16,7 @@ #ifndef __ASM_ELF_H #define __ASM_ELF_H +#include <asm/errno.h> #include <asm/hwcap.h> /* @@ -135,7 +136,11 @@ extern unsigned long randomize_et_dyn(unsigned long base); */ #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_AARCH32); \ + clear_thread_flag(TIF_32BIT); \ +} while (0) #define ARCH_DLINFO \ do { \ @@ -171,23 +176,100 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm); #define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3) +#ifdef CONFIG_AARCH32_EL0 + /* AArch32 registers. */ -#define COMPAT_ELF_NGREG 18 -typedef unsigned int compat_elf_greg_t; -typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; +#define COMPAT_A32_ELF_NGREG 18 +typedef unsigned int compat_a32_elf_greg_t; +typedef compat_a32_elf_greg_t compat_a32_elf_gregset_t[COMPAT_A32_ELF_NGREG]; /* AArch32 EABI. */ #define EF_ARM_EABI_MASK 0xff000000 -#define compat_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \ +#define compat_a32_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \ ((x)->e_flags & EF_ARM_EABI_MASK)) #define compat_start_thread compat_start_thread -#define COMPAT_SET_PERSONALITY(ex) set_thread_flag(TIF_32BIT); -#define COMPAT_ARCH_DLINFO +#define COMPAT_A32_SET_PERSONALITY(ex) \ +do { \ + set_thread_flag(TIF_AARCH32); \ + set_thread_flag(TIF_32BIT); \ +} while (0) +#define COMPAT_A32_ARCH_DLINFO do {} while (0) extern int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp); -#define compat_arch_setup_additional_pages \ - aarch32_setup_vectors_page + +#else +typedef elf_greg_t compat_elf_greg_t; +typedef elf_gregset_t compat_elf_gregset_t; +#define compat_a32_elf_check_arch(x) 0 +#define COMPAT_A32_SET_PERSONALITY(ex) do {} while (0) +#define COMPAT_A32_ARCH_DLINFO do {} while (0) +static inline int aarch32_setup_vectors_page(struct linux_binprm *bprm, + int uses_interp) +{ + return -EINVAL; +} +#endif + +/* + * If ILP32 is turned on, we want to define the compat_elf_greg_t to the non compat + * one and define PR_REG_SIZE/PRSTATUS_SIZE/SET_PR_FPVALID so we pick up the correct + * ones for AARCH32. + */ +#ifdef CONFIG_ARM64_ILP32 +typedef elf_greg_t compat_elf_greg_t; +typedef elf_gregset_t compat_elf_gregset_t; +#define COMPAT_PR_REG_SIZE(S) (is_a32_compat_task() ? 72 : 272) +#define COMPAT_PRSTATUS_SIZE(S) (is_a32_compat_task() ? 124 : 352) +#define COMPAT_SET_PR_FPVALID(S, V) \ +do { \ + *(int *) (((void *) &((S)->pr_reg)) + PR_REG_SIZE((S)->pr_reg)) = (V); \ +} while (0) +#else +typedef compat_a32_elf_greg_t compat_elf_greg_t; +typedef compat_a32_elf_gregset_t compat_elf_gregset_t; +#endif + +#ifdef CONFIG_ARM64_ILP32 +#define compat_ilp32_elf_check_arch(x) ((x)->e_machine == EM_AARCH64) +#define COMPAT_ILP32_SET_PERSONALITY(ex) \ +do { \ + clear_thread_flag(TIF_AARCH32); \ + set_thread_flag(TIF_32BIT); \ +} while (0) +#define COMPAT_ILP32_ARCH_DLINFO \ +do { \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, \ + (elf_addr_t)(long)current->mm->context.vdso); \ +} while (0) +#else +#define compat_ilp32_elf_check_arch(x) 0 +#define COMPAT_ILP32_SET_PERSONALITY(ex) do {} while (0) +#define COMPAT_ILP32_ARCH_DLINFO do {} while (0) +#endif + +#define compat_elf_check_arch(x) (compat_a32_elf_check_arch(x) || compat_ilp32_elf_check_arch(x)) +#define COMPAT_SET_PERSONALITY(ex) \ +do { \ + if (compat_a32_elf_check_arch(&ex)) \ + COMPAT_A32_SET_PERSONALITY(ex); \ + else \ + COMPAT_ILP32_SET_PERSONALITY(ex); \ +} while (0) + +/* ILP32 uses the "LP64-like" vdso pages */ +#define compat_arch_setup_additional_pages \ + (is_a32_compat_task() \ + ? &aarch32_setup_vectors_page \ + : &(arch_setup_additional_pages)) + +#define COMPAT_ARCH_DLINFO \ +do { \ + if (is_a32_compat_task()) \ + COMPAT_A32_ARCH_DLINFO; \ + else \ + COMPAT_ILP32_ARCH_DLINFO; \ +} while (0) #endif /* CONFIG_COMPAT */ diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h index 50f559f574fe..63b19f128c6c 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -52,7 +52,7 @@ struct fpsimd_partial_state { }; -#if defined(__KERNEL__) && defined(CONFIG_COMPAT) +#if defined(__KERNEL__) && defined(CONFIG_AARCH32_EL0) /* Masks for extracting the FPSR and FPCR from the FPSCR */ #define VFP_FPSCR_STAT_MASK 0xf800009f #define VFP_FPSCR_CTRL_MASK 0x07f79f00 diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h index 0ad735166d9f..8b09fd1620dd 100644 --- a/arch/arm64/include/asm/hwcap.h +++ b/arch/arm64/include/asm/hwcap.h @@ -47,8 +47,6 @@ #define ELF_HWCAP (elf_hwcap) #ifdef CONFIG_COMPAT -#define COMPAT_ELF_HWCAP (compat_elf_hwcap) -#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2) extern unsigned int compat_elf_hwcap, compat_elf_hwcap2; #endif diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 42ca271b6c60..8ad0308a3601 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -106,6 +106,17 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc, static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { +#ifdef CONFIG_ARM64_ILP32 + /* + * ILP32 thread are started the same way as LP64 threads. + * Note we cannot use is_ilp32_compat_task here as that + * would introduce a header depency issue. + */ + if (!test_thread_flag(TIF_AARCH32)) { + start_thread(regs, pc, sp); + return; + } +#endif start_thread_common(regs, pc); regs->pstate = COMPAT_PSR_MODE_USR; if (pc & 1) diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index d6dd9fdbc3be..a379596e0888 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -120,7 +120,7 @@ struct pt_regs { #define arch_has_single_step() (1) -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 #define compat_thumb_mode(regs) \ (((regs)->pstate & COMPAT_PSR_T_BIT)) #else diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h index eeaa97559bab..522c3456141e 100644 --- a/arch/arm64/include/asm/signal32.h +++ b/arch/arm64/include/asm/signal32.h @@ -17,7 +17,7 @@ #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 +47,6 @@ static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t static inline void compat_setup_restart_syscall(struct pt_regs *regs) { } -#endif /* CONFIG_COMPAT */ +#endif /* CONFIG_AARCH32_EL0 */ #endif /* __KERNEL__ */ #endif /* __ASM_SIGNAL32_H */ diff --git a/arch/arm64/include/asm/stat.h b/arch/arm64/include/asm/stat.h index 15e35598ac40..e3b5865be66d 100644 --- a/arch/arm64/include/asm/stat.h +++ b/arch/arm64/include/asm/stat.h @@ -18,7 +18,7 @@ #include <uapi/asm/stat.h> -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 #include <asm/compat.h> @@ -57,5 +57,5 @@ struct stat64 { compat_u64 st_ino; }; -#endif +#endif /* CONFIG_AARCH32_EL0 */ #endif diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 702e1e6a0d80..a1b5b124588c 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -115,6 +115,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_SINGLESTEP 21 #define TIF_32BIT 22 /* 32bit process */ #define TIF_SWITCH_MM 23 /* deferred switch_mm */ +#define TIF_AARCH32 24 /* AARCH32 process */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 3bc498c250dc..10397e852b54 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -13,7 +13,11 @@ * 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_ARM64_ILP32 +#define __ARCH_WANT_COMPAT_SYS_PREADV64 +#define __ARCH_WANT_COMPAT_SYS_PWRITEV64 +#endif +#ifdef CONFIG_AARCH32_EL0 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_COMPAT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h index 839ce0031bd5..84050c613cc3 100644 --- a/arch/arm64/include/asm/vdso.h +++ b/arch/arm64/include/asm/vdso.h @@ -29,6 +29,10 @@ #include <generated/vdso-offsets.h> +#ifdef CONFIG_ARM64_ILP32 +#include <generated/vdso-ilp32-offsets.h> +#endif + #define VDSO_SYMBOL(base, name) \ ({ \ (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ diff --git a/arch/arm64/include/uapi/asm/bitsperlong.h b/arch/arm64/include/uapi/asm/bitsperlong.h index fce9c2924fa3..bb716d04a9b5 100644 --- a/arch/arm64/include/uapi/asm/bitsperlong.h +++ b/arch/arm64/include/uapi/asm/bitsperlong.h @@ -16,7 +16,14 @@ #ifndef __ASM_BITSPERLONG_H #define __ASM_BITSPERLONG_H -#define __BITS_PER_LONG 64 +/* Assuming __LP64__ will be defined for native ELF64's and not for ILP32. */ +#ifdef __LP64__ +# define __BITS_PER_LONG 64 +#elif defined(__ILP32__) +# define __BITS_PER_LONG 32 +#else +# error "Unknown ABI; not ILP32 or LP64" +#endif #include <asm-generic/bitsperlong.h> diff --git a/arch/arm64/include/uapi/asm/posix_types.h b/arch/arm64/include/uapi/asm/posix_types.h index 7985ff60ca3f..09619459bb1a 100644 --- a/arch/arm64/include/uapi/asm/posix_types.h +++ b/arch/arm64/include/uapi/asm/posix_types.h @@ -5,6 +5,12 @@ typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; #define __kernel_old_uid_t __kernel_old_uid_t +#ifdef __ILP32__ +typedef long long __kernel_long_t; +typedef unsigned long long __kernel_ulong_t; +#define __kernel_long_t __kernel_long_t +#endif + #include <asm-generic/posix_types.h> -#endif /* __ASM_POSIX_TYPES_H */ +#endif /* __ASM_POSIX_TYPES_H */ diff --git a/arch/arm64/include/uapi/asm/siginfo.h b/arch/arm64/include/uapi/asm/siginfo.h index 5a74a0853db0..c80c612885ae 100644 --- a/arch/arm64/include/uapi/asm/siginfo.h +++ b/arch/arm64/include/uapi/asm/siginfo.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 ARM Ltd. + * Copyright (C) 2014 Cavium Inc. * * 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 @@ -18,6 +19,38 @@ #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +#ifdef __ILP32__ + +/* + * For ILP32, the siginfo structures should share the same layout and + * alignement requirements as LP64 ABI. + * To do this, use an extra pad field and add aligned attribute + * to the structure. + */ + +# ifdef __AARCH64EB__ +# define __SIGINFO_INNER(type, field) \ + int __pad#field; \ + type field +# else +# define __SIGINFO_INNER(type, field) \ + type field; \ + int __pad#field +# endif + +# undef __SIGINFO_VOIDPTR +# define __SIGINFO_VOIDPTR(field) \ + __SIGINFO_INNER(void __user*, field) +# undef __SIGINFO_BAND + +# define __SIGINFO_BAND(field) \ + __SIGINFO_INNER(long, field) + +/* Make the alignment of siginfo always 8 byte aligned. */ +#define __ARCH_SI_ATTRIBUTES __attribute__((aligned(8))) + +#endif + #include <asm-generic/siginfo.h> #endif diff --git a/arch/arm64/include/uapi/asm/signal.h b/arch/arm64/include/uapi/asm/signal.h index 8d1e7236431b..f378ff4f93d7 100644 --- a/arch/arm64/include/uapi/asm/signal.h +++ b/arch/arm64/include/uapi/asm/signal.h @@ -16,9 +16,43 @@ #ifndef __ASM_SIGNAL_H #define __ASM_SIGNAL_H +#include <asm/posix_types.h> + /* Required for AArch32 compatibility. */ #define SA_RESTORER 0x04000000 +/* + * Since sigset is a bitmask, we need the same size fields for ILP32 + * and LP64. With big-endian, 32bit bitmask does not match up to + * 64bit bitmask (unlike with little-endian). + */ +#ifdef __ILP32__ + +#define __SIGSET_INNER_TYPE __kernel_ulong_t +#define _NSIG_BPW 64 + +# ifdef __AARCH64EB__ +# define __SIGNAL_INNER(type, field) \ + int __pad_##field; \ + type field; +# else +# define __SIGNAL_INNER(type, field) \ + type field; \ + int __pad_##field; +# endif + +# define __SIGACTION_HANDLER(field) \ + __SIGNAL_INNER(__sighandler_t, field) + + +#define __SIGACTION_FLAGS(field) \ + __kernel_ulong_t field + +#define __SIGACTION_RESTORER(field) \ + __SIGNAL_INNER(__sigrestore_t, field) + +#endif + #include <asm-generic/signal.h> #endif diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h index 1caadc24e3fe..13cbf8d6cdd0 100644 --- a/arch/arm64/include/uapi/asm/unistd.h +++ b/arch/arm64/include/uapi/asm/unistd.h @@ -13,4 +13,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/>. */ + +/* For ILP32, we want to use the non compat names. */ +#if defined(__ILP32__) +#define __ARCH_WANT_64BIT_SYSCALLS +#endif + #include <asm-generic/unistd.h> |