From a774e70e50f898c7380f6cfb368d55a99ed71956 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:18:55 -0700 Subject: ARM64: Force LP64 to compile the kernel Sometimes the compiler is set to default to ILP32 ABI so we want to make sure the kernel can compile in that case. Signed-off-by: Andrew Pinski --- arch/arm64/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 20901ffed182..f3ef4a32bd9a 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -20,14 +20,18 @@ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) KBUILD_DEFCONFIG := defconfig KBUILD_CFLAGS += -mgeneral-regs-only +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__ -- cgit v1.2.3 From b82c6e533186cab8617838c403a2406961b1f73b Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:18:56 -0700 Subject: ARM64: Rename COMPAT to AARCH32_EL0 in Kconfig We want to split CONFIG_COMPAT so we can use the COMPAT interface in some cases including for compat binfmt. Signed-off-by: Andrew Pinski --- arch/arm64/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 9532f8d5857e..f28af3f3c604 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -408,9 +408,13 @@ menu "Userspace binary formats" source "fs/Kconfig.binfmt" config COMPAT + def_bool y + depends on AARCH32_EL0 + select COMPAT_BINFMT_ELF + +config AARCH32_EL0 bool "Kernel support for 32-bit EL0" depends on !ARM64_64K_PAGES - select COMPAT_BINFMT_ELF select HAVE_UID16 select OLD_SIGSUSPEND3 select COMPAT_OLD_SIGACTION @@ -424,7 +428,7 @@ config COMPAT config SYSVIPC_COMPAT def_bool y - depends on COMPAT && SYSVIPC + depends on AARCH32_EL0 && SYSVIPC endmenu -- cgit v1.2.3 From 1b07bd82e000daf0755b0671cd7763bde5d76473 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:18:57 -0700 Subject: ARM64: Change some CONFIG_COMPAT over to use CONFIG_AARCH32_EL0 instead This patch changes CONFIG_COMPAT checks inside the arm64 which are AARCH32 specific Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/elf.h | 20 +++++++++++++++++--- arch/arm64/include/asm/fpsimd.h | 2 +- arch/arm64/include/asm/ptrace.h | 2 +- arch/arm64/include/asm/signal32.h | 4 ++-- arch/arm64/include/asm/stat.h | 4 ++-- arch/arm64/include/asm/unistd.h | 2 +- arch/arm64/kernel/Makefile | 2 +- arch/arm64/kernel/asm-offsets.c | 2 +- arch/arm64/kernel/entry.S | 6 +++--- arch/arm64/kernel/head.S | 2 +- arch/arm64/kernel/ptrace.c | 34 ++++++++++++++++++++++++++++------ arch/arm64/kernel/signal.c | 15 +++++++++++++++ arch/arm64/kernel/traps.c | 2 +- arch/arm64/kernel/vdso.c | 5 +++-- drivers/clocksource/arm_arch_timer.c | 2 +- 15 files changed, 78 insertions(+), 26 deletions(-) diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 1f65be393139..afa0f432ae87 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -171,14 +171,16 @@ 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 +#define COMPAT_A32_ELF_NGREG 18 typedef unsigned int compat_elf_greg_t; -typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; +typedef compat_elf_greg_t compat_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 @@ -189,6 +191,18 @@ extern int aarch32_setup_vectors_page(struct linux_binprm *bprm, #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_SET_PERSONALITY(ex) +#define COMPAT_ARCH_DLINFO + +#endif + +#define compat_elf_check_arch(x) compat_a32_elf_check_arch(x) + #endif /* CONFIG_COMPAT */ #endif 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/ptrace.h b/arch/arm64/include/asm/ptrace.h index 41ed9e13795e..690a380e2cdf 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -113,7 +113,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 #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 -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 #include @@ -57,5 +57,5 @@ struct stat64 { compat_u64 st_ino; }; -#endif +#endif /* CONFIG_AARCH32_EL0 */ #endif diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 6d2bf419431d..70e55598c7dd 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_COMPAT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 5bd029b43644..f59d113b7a58 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -17,7 +17,7 @@ arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ hyp-stub.o psci.o cpu_ops.o insn.o return_address.o \ cpuinfo.o -arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ +arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \ sys_compat.o arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 9a9fce090d58..d9c429c073e7 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -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)); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 726b910fe6ec..5a1430c8ced8 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -196,7 +196,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 @@ -236,7 +236,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) @@ -398,7 +398,7 @@ el0_sync: b.ge el0_dbg b el0_inv -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 .align 6 el0_sync_compat: kernel_entry 0, 32 diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 0a6e4f924df8..1934bc802bc4 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -323,7 +323,7 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems mov x0, #0x33ff msr cptr_el2, x0 // Disable copro. traps to EL2 -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 msr hstr_el2, xzr // Disable CP15 traps to EL2 #endif diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 8a4ae8e73213..04f32d73477f 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -75,7 +76,7 @@ static void ptrace_hbptriggered(struct perf_event *bp, .si_addr = (void __user *)(bkpt->trigger), }; -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 int i; if (!is_compat_task()) @@ -617,6 +618,7 @@ static const struct user_regset_view user_aarch64_view = { #ifdef CONFIG_COMPAT #include +#ifdef CONFIG_AARCH32_EL0 enum compat_regset { REGSET_COMPAT_GPR, @@ -793,7 +795,7 @@ static int compat_vfp_set(struct task_struct *target, static const struct user_regset aarch32_regsets[] = { [REGSET_COMPAT_GPR] = { .core_note_type = NT_PRSTATUS, - .n = COMPAT_ELF_NGREG, + .n = COMPAT_A32_ELF_NGREG, .size = sizeof(compat_elf_greg_t), .align = sizeof(compat_elf_greg_t), .get = compat_gpr_get, @@ -991,8 +993,8 @@ 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, - compat_ulong_t caddr, compat_ulong_t cdata) +long compat_a32_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { unsigned long addr = caddr; unsigned long data = cdata; @@ -1068,11 +1070,31 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, return ret; } -#endif /* CONFIG_COMPAT */ +#else /* !CONFIG_AARCH32_EL0 */ +long compat_a32_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) +{ + return -EINVAL; +} +#endif /* !CONFIG_AARCH32_EL0 */ + +/* + * In ILP32, compat_arch_ptrace is used via the compat syscall, we don't need + * to do anything special for ILP32 though; only for AARCH32. + */ +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) +{ + if (is_compat_task()) + return compat_a32_arch_ptrace(child, request, caddr, cdata); + return compat_ptrace_request(child, request, caddr, cdata); +} +#endif + const struct user_regset_view *task_user_regset_view(struct task_struct *task) { -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 if (is_compat_thread(task_thread_info(task))) return &user_aarch32_view; #endif diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 6fa792137eda..8527d999bc86 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -421,3 +421,18 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, fpsimd_restore_current_state(); } + +/* + * Some functions are needed for compat ptrace but we don't define + * them if we don't have AARCH32 support compiled in + */ +#if defined CONFIG_COMPAT && !defined CONFIG_AARCH32_EL0 +int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) +{ + return -EFAULT; +} +int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) +{ + return -EFAULT; +} +#endif diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index de1b085e7963..4fd16f383621 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -287,7 +287,7 @@ long compat_arm_syscall(struct pt_regs *regs); asmlinkage long do_ni_syscall(struct pt_regs *regs) { -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 long ret; if (is_compat_task()) { ret = compat_arm_syscall(regs); diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 32aeea083d93..a777ac3d0a05 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -35,6 +35,7 @@ #include #include #include +#include extern char vdso_start, vdso_end; static unsigned long vdso_pages; @@ -49,7 +50,7 @@ static union { } vdso_data_store __page_aligned_data; struct vdso_data *vdso_data = &vdso_data_store.data; -#ifdef CONFIG_COMPAT +#ifdef CONFIG_AARCH32_EL0 /* * Create and map the vectors page for AArch32 tasks. */ @@ -107,7 +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]; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 43005d4d3348..9d4e24c627db 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -309,7 +309,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 } -- cgit v1.2.3 From d95606261541cbd57ecf8a16d5b36541a12edaac Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:18:58 -0700 Subject: ARM64:ILP32: Set kernel_long to long long so we can reuse most of the same syscalls as LP64 Since we want time_t and some other userland types to be the same between ILP32 and LP64, we define __kernel_long_t to be long long. Signed-off-by: Andrew Pinski --- arch/arm64/include/uapi/asm/posix_types.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 -#endif /* __ASM_POSIX_TYPES_H */ +#endif /* __ASM_POSIX_TYPES_H */ -- cgit v1.2.3 From 77cac67f6e71bfe42253aaf674d5a49e17a5812e Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:18:59 -0700 Subject: ARM64:UAPI: Set the correct __BITS_PER_LONG for ILP32 We need to say to the userland API that bits per long is 32bits for ILP32. Signed-off-by: Andrew Pinski --- arch/arm64/include/uapi/asm/bitsperlong.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/uapi/asm/bitsperlong.h b/arch/arm64/include/uapi/asm/bitsperlong.h index 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 -- cgit v1.2.3 From 22cc53f5d94dcc75af3e900e223dd870146490ae Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:00 -0700 Subject: Allow for some signal structures to be the same between a 32bit ABI and the 64bit ABI In ARM64, we want to allow the signal related structures to be same between the 32bit (ILP32) and the 64bit ABIs (LP64). We still want to use the generic include files so we need some new defines that are used in UAPI; they default to the same as it is before. Signed-off-by: Andrew Pinski --- include/uapi/asm-generic/siginfo.h | 17 +++++++++++++---- include/uapi/asm-generic/signal.h | 27 +++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h index ba5be7fdbdfe..cb44f86932d2 100644 --- a/include/uapi/asm-generic/siginfo.h +++ b/include/uapi/asm-generic/siginfo.h @@ -4,9 +4,17 @@ #include #include +#ifndef __SIGINFO_VOIDPTR +#define __SIGINFO_VOIDPTR(field) void __user *field +#endif + +#ifndef __SIGINFO_BAND +#define __SIGINFO_BAND(field) __ARCH_SI_BAND_T field +#endif + typedef union sigval { int sival_int; - void __user *sival_ptr; + __SIGINFO_VOIDPTR(sival_ptr); } sigval_t; /* @@ -86,7 +94,7 @@ typedef struct siginfo { /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ struct { - void __user *_addr; /* faulting insn/memory ref. */ + __SIGINFO_VOIDPTR(_addr); /* faulting insn/memory ref. */ #ifdef __ARCH_SI_TRAPNO int _trapno; /* TRAP # which caused the signal */ #endif @@ -95,13 +103,13 @@ typedef struct siginfo { /* SIGPOLL */ struct { - __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + __SIGINFO_BAND(_band); /* POLL_IN, POLL_OUT, POLL_MSG */ int _fd; } _sigpoll; /* SIGSYS */ struct { - void __user *_call_addr; /* calling user insn */ + __SIGINFO_VOIDPTR(_call_addr); /* calling user insn */ int _syscall; /* triggering system call number */ unsigned int _arch; /* AUDIT_ARCH_* of syscall */ } _sigsys; @@ -283,6 +291,7 @@ typedef struct sigevent { int _pad[SIGEV_PAD_SIZE]; int _tid; + /* Note these two are handled only in userspace */ struct { void (*_function)(sigval_t); void *_attribute; /* really pthread_attr_t */ diff --git a/include/uapi/asm-generic/signal.h b/include/uapi/asm-generic/signal.h index 9df61f1edb0f..c4ce2387fe9b 100644 --- a/include/uapi/asm-generic/signal.h +++ b/include/uapi/asm-generic/signal.h @@ -4,7 +4,9 @@ #include #define _NSIG 64 +#ifndef _NSIG_BPW #define _NSIG_BPW __BITS_PER_LONG +#endif #define _NSIG_WORDS (_NSIG / _NSIG_BPW) #define SIGHUP 1 @@ -83,9 +85,13 @@ #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 +#ifndef __SIGSET_INNER_TYPE +#define __SIGSET_INNER_TYPE unsigned long +#endif + #ifndef __ASSEMBLY__ typedef struct { - unsigned long sig[_NSIG_WORDS]; + __SIGSET_INNER_TYPE sig[_NSIG_WORDS]; } sigset_t; /* not actually used, but required for linux/syscalls.h */ @@ -98,11 +104,24 @@ typedef unsigned long old_sigset_t; #endif #ifndef __KERNEL__ + +#ifndef __SIGACTION_HANDLER +#define __SIGACTION_HANDLER(field) __sighandler_t field +#endif + +#ifndef __SIGACTION_FLAGS +#define __SIGACTION_FLAGS(field) unsigned long field +#endif + +#ifndef __SIGACTION_RESTORER +#define __SIGACTION_RESTORER(field) __sigrestore_t field +#endif + struct sigaction { - __sighandler_t sa_handler; - unsigned long sa_flags; + __SIGACTION_HANDLER(sa_handler); + __SIGACTION_FLAGS(sa_flags); #ifdef SA_RESTORER - __sigrestore_t sa_restorer; + __SIGACTION_RESTORER(sa_restorer); #endif sigset_t sa_mask; /* mask last for extensibility */ }; -- cgit v1.2.3 From d3813d97d5face12f9762a394e845fff7774c0dc Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:01 -0700 Subject: ARM64:ILP32: Use the same size and layout of the signal structures for ILP32 as for LP64 Defines the macros which allow the signal structures to be the same between ILP32 and LP64. Signed-off-by: Andrew Pinski --- arch/arm64/include/uapi/asm/siginfo.h | 33 +++++++++++++++++++++++++++++++++ arch/arm64/include/uapi/asm/signal.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) 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 #endif diff --git a/arch/arm64/include/uapi/asm/signal.h b/arch/arm64/include/uapi/asm/signal.h index 8d1e7236431b..d33a5f77ec44 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 + /* 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 #endif -- cgit v1.2.3 From f7185bf731efd1015821f4153ac17d653dbd23c9 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:02 -0700 Subject: Allow a 32bit ABI to use the naming of the 64bit ABI syscalls to avoid confusion of not splitting the registers In the ARM64 ILP32 case, we want to say the syscalls that normally would pass 64bit as two arguments are now passing as one so want to use the 64bit naming scheme. Signed-off-by: Andrew Pinski --- include/uapi/asm-generic/unistd.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 22749c134117..599616671558 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -883,8 +883,12 @@ __SYSCALL(__NR_fork, sys_ni_syscall) * they take different names. * Here we map the numbers so that both versions * use the same syscall table layout. + * For 32bit abis where 64bit can be passed via one + * register, use the same naming as the 64bit ones + * as they will only have a 64 bit off_t. */ -#if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT) +#if (__BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)) || \ + defined(__ARCH_WANT_64BIT_SYSCALLS) #define __NR_fcntl __NR3264_fcntl #define __NR_statfs __NR3264_statfs #define __NR_fstatfs __NR3264_fstatfs -- cgit v1.2.3 From ed722513a020c655797eb855c2d6ccf525d1c10c Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:03 -0700 Subject: ARM64:ILP32: Use the same syscall names as LP64 Define __SYSCALL_NONCOMPAT so we use the 64bit naming scheme for ILP32. Signed-off-by: Andrew Pinski --- arch/arm64/include/uapi/asm/unistd.h | 6 ++++++ 1 file changed, 6 insertions(+) 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 . */ + +/* For ILP32, we want to use the non compat names. */ +#if defined(__ILP32__) +#define __ARCH_WANT_64BIT_SYSCALLS +#endif + #include -- cgit v1.2.3 From bfe2beb3a5384b06868a0ff6cff23a94825b81b7 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:04 -0700 Subject: ARM64: Introduce is_a32_task/is_a32_thread and TIF_AARCH32 and use them in the correct locations 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. Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/compat.h | 21 +++++++++++++++++++++ arch/arm64/include/asm/elf.h | 12 ++++++++++-- arch/arm64/include/asm/thread_info.h | 1 + arch/arm64/kernel/hw_breakpoint.c | 7 ++++--- arch/arm64/kernel/process.c | 6 +++--- arch/arm64/kernel/ptrace.c | 8 ++++---- arch/arm64/kernel/signal.c | 5 +++-- arch/arm64/kernel/traps.c | 2 +- 8 files changed, 47 insertions(+), 15 deletions(-) diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 56de5aadede2..91ccca63f6da 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -311,5 +311,26 @@ 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 + #endif /* __KERNEL__ */ #endif /* __ASM_COMPAT_H */ diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index afa0f432ae87..69291a0b68c6 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -135,7 +135,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 { \ @@ -184,7 +188,11 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_A32_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 { \ + set_thread_flag(TIF_AARCH32); \ + set_thread_flag(TIF_32BIT); \ +} while (0) #define COMPAT_ARCH_DLINFO extern int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp); diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 459bf8e53208..a1851057162b 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -119,6 +119,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/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index df1cf15377b4..8e46a67a28d1 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -433,7 +434,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_task()) { + if (is_a32_compat_task()) { if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 && info->ctrl.len != ARM_BREAKPOINT_LEN_4) return -EINVAL; @@ -490,7 +491,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) * AArch32 tasks expect some simple alignment fixups, so emulate * that here. */ - if (is_compat_task()) { + if (is_a32_compat_task()) { if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) alignment_mask = 0x7; else @@ -677,7 +678,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr, info = counter_arch_bp(wp); /* AArch32 watchpoints are either 4 or 8 bytes aligned. */ - if (is_compat_task()) { + if (is_a32_compat_task()) { if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) alignment_mask = 0x7; else diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index fde9923af859..4ae5562ba6e6 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -253,7 +253,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, if (likely(!(p->flags & PF_KTHREAD))) { *childregs = *current_pt_regs(); childregs->regs[0] = 0; - if (is_compat_thread(task_thread_info(p))) { + if (is_a32_compat_thread(task_thread_info(p))) { if (stack_start) childregs->compat_sp = stack_start; } else { @@ -294,12 +294,12 @@ static void tls_thread_switch(struct task_struct *next) { unsigned long tpidr, tpidrro; - if (!is_compat_task()) { + if (!is_a32_compat_task()) { asm("mrs %0, tpidr_el0" : "=r" (tpidr)); current->thread.tp_value = tpidr; } - if (is_compat_thread(task_thread_info(next))) { + if (is_a32_compat_thread(task_thread_info(next))) { tpidr = 0; tpidrro = next->thread.tp_value; } else { diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 04f32d73477f..6d6f62dc81dc 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -79,7 +79,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) { @@ -1085,7 +1085,7 @@ long compat_a32_arch_ptrace(struct task_struct *child, compat_long_t request, long compat_arch_ptrace(struct task_struct *child, compat_long_t request, compat_ulong_t caddr, compat_ulong_t cdata) { - if (is_compat_task()) + if (is_a32_compat_task()) return compat_a32_arch_ptrace(child, request, caddr, cdata); return compat_ptrace_request(child, request, caddr, cdata); } @@ -1095,7 +1095,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, const struct user_regset_view *task_user_regset_view(struct task_struct *task) { #ifdef CONFIG_AARCH32_EL0 - if (is_compat_thread(task_thread_info(task))) + if (is_a32_compat_thread(task_thread_info(task))) return &user_aarch32_view; #endif return &user_aarch64_view; @@ -1122,7 +1122,7 @@ static void tracehook_report_syscall(struct pt_regs *regs, * A scratch register (ip(r12) on AArch32, x7 on AArch64) is * used to denote syscall entry/exit: */ - regno = (is_compat_task() ? 12 : 7); + regno = (is_a32_compat_task() ? 12 : 7); saved_reg = regs->regs[regno]; regs->regs[regno] = dir; diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 8527d999bc86..f47c064ff6c9 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -276,7 +277,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; @@ -302,7 +303,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) /* * Set up the stack frame */ - if (is_compat_task()) { + if (is_a32_compat_task()) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) ret = compat_setup_rt_frame(usig, ksig, oldset, regs); else diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 4fd16f383621..dd2192070816 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -289,7 +289,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; -- cgit v1.2.3 From a7324076e52f254064f913d48b0ba75edfabbff7 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:05 -0700 Subject: ARM64: Add is_ilp32_compat_task and is_ilp32_compat_thread This patch adds the functions which returns if the current task is an ILP32 task and one returns if the thread is an ILP32 thread. Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/compat.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 91ccca63f6da..fe390b77e7c3 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -332,5 +332,27 @@ static inline int is_a32_compat_thread(struct thread_info *thread) } #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 */ -- cgit v1.2.3 From b0eeee72d3cb1ae38c676c3bb13e19928b0c5033 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:06 -0700 Subject: ARM64:ILP32: COMPAT_USE_64BIT_TIME is true for ILP32 tasks Since __kernel_long_t (time_t) is long long, we need to tell the rest of kernel that we use 64bit time_t for compat when the task is not an AARCH32 task. The reason why we check AARCH32 rather than ILP32 here is because if we don't have AARCH32 compiled in (which is going to be the common case due to AARCH32 requiring 4k pages). Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/compat.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index fe390b77e7c3..074bcc31c791 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; -- cgit v1.2.3 From d2848980dd76673d626b81acd23989bbcceb4fd4 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:07 -0700 Subject: ARM64:ILP32: Use the non compat HWCAP for ILP32 Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/compat.h | 10 ++++++++++ arch/arm64/include/asm/hwcap.h | 2 -- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 074bcc31c791..0f4ecfea4546 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -296,6 +296,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); diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h index 024c46183c3c..31e7e02d6f91 100644 --- a/arch/arm64/include/asm/hwcap.h +++ b/arch/arm64/include/asm/hwcap.h @@ -46,8 +46,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 -- cgit v1.2.3 From f2211ab8a3053b89db4ec8d1e9dbe8a2eaebde3b Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:08 -0700 Subject: ARM64:ILP32 use the standard start_thread for ILP32 so the processor state is not AARCH32 If we have both ILP32 and AARCH32 compiled in, we need use the non compat start thread for ILP32. Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/processor.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 286b1bec547c..7bd9f3200240 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -104,6 +104,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) -- cgit v1.2.3 From 22718fe0b2005d61399c73be4d65c162d4a4cd6e Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:09 -0700 Subject: compat_binfmt_elf: coredump: Allow some core dump macros be overridden for compat. On some targets (x86 [32bit and x32] and arm64 [aarch32 and ilp32]), there are two compat elf abis. This adds a few more "#define * COMPAT_*" for compat targets to define if needed. Signed-off-by: Andrew Pinski --- fs/compat_binfmt_elf.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index 4d24d17bcfc1..83079272ec85 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -130,6 +130,23 @@ static void cputime_to_compat_timeval(const cputime_t cputime, #define arch_setup_additional_pages compat_arch_setup_additional_pages #endif + +#ifdef COMPAT_PR_REG_SIZE +#define PR_REG_SIZE COMPAT_PR_REG_SIZE +#endif + +#ifdef COMPAT_PRSTATUS_SIZE +#define PRSTATUS_SIZE COMPAT_PRSTATUS_SIZE +#endif + +#ifdef COMPAT_PR_REG_PTR +#define PR_REG_PTR COMPAT_PR_REG_PTR +#endif + +#ifdef COMPAT_SET_PR_FPVALID +#define SET_PR_FPVALID COMPAT_SET_PR_FPVALID +#endif + /* * Rename a few of the symbols that binfmt_elf.c will define. * These are all local so the names don't really matter, but it -- cgit v1.2.3 From 4aaf156c46c2a751aeeff02b2387a12cc5d34d97 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:10 -0700 Subject: ARM64:ILP32: Support core dump for ILP32 This patch supports core dumping on ILP32. We need a few extra macros (COMPAT_PR_REG_SIZE and COMPAT_PRSTATUS_SIZE) due to size differences of the register sets. Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/elf.h | 23 +++++++++++++++++++++-- arch/arm64/kernel/ptrace.c | 12 ++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 69291a0b68c6..fdd3fdbc90fd 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -179,8 +179,8 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm); /* AArch32 registers. */ #define COMPAT_A32_ELF_NGREG 18 -typedef unsigned int compat_elf_greg_t; -typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_A32_ELF_NGREG]; +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 @@ -209,6 +209,25 @@ typedef elf_gregset_t compat_elf_gregset_t; #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 + #define compat_elf_check_arch(x) compat_a32_elf_check_arch(x) #endif /* CONFIG_COMPAT */ diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 6d6f62dc81dc..6a9d39576c58 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -796,8 +796,8 @@ static const struct user_regset aarch32_regsets[] = { [REGSET_COMPAT_GPR] = { .core_note_type = NT_PRSTATUS, .n = COMPAT_A32_ELF_NGREG, - .size = sizeof(compat_elf_greg_t), - .align = sizeof(compat_elf_greg_t), + .size = sizeof(compat_a32_elf_greg_t), + .align = sizeof(compat_a32_elf_greg_t), .get = compat_gpr_get, .set = compat_gpr_set }, @@ -830,7 +830,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, tmp = tsk->mm->start_data; else if (off == COMPAT_PT_TEXT_END_ADDR) tmp = tsk->mm->end_code; - else if (off < sizeof(compat_elf_gregset_t)) + else if (off < sizeof(compat_a32_elf_gregset_t)) return copy_regset_to_user(tsk, &user_aarch32_view, REGSET_COMPAT_GPR, off, sizeof(compat_ulong_t), ret); @@ -851,7 +851,7 @@ static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off, if (off & 3 || off >= COMPAT_USER_SZ) return -EIO; - if (off >= sizeof(compat_elf_gregset_t)) + if (off >= sizeof(compat_a32_elf_gregset_t)) return 0; set_fs(KERNEL_DS); @@ -1014,7 +1014,7 @@ long compat_a32_arch_ptrace(struct task_struct *child, compat_long_t request, ret = copy_regset_to_user(child, &user_aarch32_view, REGSET_COMPAT_GPR, - 0, sizeof(compat_elf_gregset_t), + 0, sizeof(compat_a32_elf_gregset_t), datap); break; @@ -1022,7 +1022,7 @@ long compat_a32_arch_ptrace(struct task_struct *child, compat_long_t request, ret = copy_regset_from_user(child, &user_aarch32_view, REGSET_COMPAT_GPR, - 0, sizeof(compat_elf_gregset_t), + 0, sizeof(compat_a32_elf_gregset_t), datap); break; -- cgit v1.2.3 From 942b8485587dedca256087f5f5dff54eb9793169 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:11 -0700 Subject: ARM64: Add loading of ILP32 binaries Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/elf.h | 59 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index fdd3fdbc90fd..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 #include /* @@ -188,25 +189,26 @@ typedef compat_a32_elf_greg_t compat_a32_elf_gregset_t[COMPAT_A32_ELF_NGREG]; ((x)->e_flags & EF_ARM_EABI_MASK)) #define compat_start_thread compat_start_thread -#define COMPAT_SET_PERSONALITY(ex) \ +#define COMPAT_A32_SET_PERSONALITY(ex) \ do { \ set_thread_flag(TIF_AARCH32); \ set_thread_flag(TIF_32BIT); \ } while (0) -#define COMPAT_ARCH_DLINFO +#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_SET_PERSONALITY(ex) -#define COMPAT_ARCH_DLINFO - +#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 /* @@ -228,7 +230,46 @@ typedef compat_a32_elf_greg_t compat_elf_greg_t; typedef compat_a32_elf_gregset_t compat_elf_gregset_t; #endif -#define compat_elf_check_arch(x) compat_a32_elf_check_arch(x) +#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 */ -- cgit v1.2.3 From 31c359a223b271aa7ae1f06caebee50ae1e8c39e Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:12 -0700 Subject: ARM64: Add vdso for ILP32 and use it for the signal return This patch adds the VDSO for ILP32. We need to use a different VDSO than LP64 since ILP32 uses ELF32 while LP64 uses ELF64. After this patch, signal handling works mostly. In that signals go through their action and then returned correctly. Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/vdso.h | 4 ++ arch/arm64/kernel/Makefile | 5 ++ arch/arm64/kernel/signal.c | 4 ++ arch/arm64/kernel/vdso-ilp32/.gitignore | 2 + arch/arm64/kernel/vdso-ilp32/Makefile | 72 ++++++++++++++++++++ arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 +++++++++ arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 98 +++++++++++++++++++++++++++ arch/arm64/kernel/vdso.c | 69 +++++++++++++++---- 8 files changed, 274 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 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 +#ifdef CONFIG_ARM64_ILP32 +#include +#endif + #define VDSO_SYMBOL(base, name) \ ({ \ (void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index f59d113b7a58..ceb9bf785605 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -33,6 +33,7 @@ arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o arm64-obj-$(CONFIG_PCI) += pci.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 @@ -40,3 +41,7 @@ extra-y := $(head-y) vmlinux.lds # vDSO - this must be built first to generate the symbol offsets $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h $(obj)/vdso/vdso-offsets.h: $(obj)/vdso + +# vDSO - this must be built first to generate the symbol offsets +$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h +$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32 diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index f47c064ff6c9..5311147ba764 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -242,6 +242,10 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_RESTORER) sigtramp = ka->sa.sa_restorer; +#ifdef CONFIG_ARM64_ILP32 + else if (is_ilp32_compat_task()) + sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32); +#endif else sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp); diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore new file mode 100644 index 000000000000..61806c3fd68b --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/.gitignore @@ -0,0 +1,2 @@ +vdso-ilp32.lds +vdso-ilp32-offsets.h diff --git a/arch/arm64/kernel/vdso-ilp32/Makefile b/arch/arm64/kernel/vdso-ilp32/Makefile new file mode 100644 index 000000000000..c8f54727fbb2 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/Makefile @@ -0,0 +1,72 @@ +# +# Building a vDSO image for AArch64. +# +# Author: Will Deacon +# Heavily based on the vDSO Makefiles for other archs. +# + +obj-ilp32-vdso := gettimeofday-ilp32.o note-ilp32.o sigreturn-ilp32.o + +# Build rules +targets := $(obj-ilp32-vdso) vdso-ilp32.so vdso-ilp32.so.dbg +obj-ilp32-vdso := $(addprefix $(obj)/, $(obj-ilp32-vdso)) + +ccflags-y := -shared -fno-common -fno-builtin +ccflags-y += -nostdlib -Wl,-soname=linux-ilp32-vdso.so.1 \ + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) + +obj-y += vdso-ilp32.o +extra-y += vdso-ilp32.lds vdso-ilp32-offsets.h +CPPFLAGS_vdso-ilp32.lds += -P -C -U$(ARCH) -mabi=ilp32 + +# Force dependency (incbin is bad) +$(obj)/vdso-ilp32.o : $(obj)/vdso-ilp32.so + +# Link rule for the .so file, .lds has to be first +$(obj)/vdso-ilp32.so.dbg: $(src)/vdso-ilp32.lds $(obj-ilp32-vdso) + $(call if_changed,vdso-ilp32ld) + +# Strip rule for the .so file +$(obj)/%.so: OBJCOPYFLAGS := -S +$(obj)/%.so: $(obj)/%.so.dbg FORCE + $(call if_changed,objcopy) + +# Generate VDSO offsets using helper script +gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh +quiet_cmd_vdsosym = VDSOSYM $@ +define cmd_vdsosym + $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \ + cp $@ include/generated/ +endef + +$(obj)/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32.so.dbg FORCE + $(call if_changed,vdsosym) + +# Assembly rules for the .S files +#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S) +# $(call if_changed_dep,vdso-ilp32as) + +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S + $(call if_changed_dep,vdso-ilp32as) + +$(obj)/note-ilp32.o: $(src)/../vdso/note.S + $(call if_changed_dep,vdso-ilp32as) + +$(obj)/sigreturn-ilp32.o: $(src)/../vdso/sigreturn.S + $(call if_changed_dep,vdso-ilp32as) + +# Actual build commands +quiet_cmd_vdso-ilp32ld = VDSOILP32L $@ + cmd_vdso-ilp32ld = $(CC) $(c_flags) -mabi=ilp32 -Wl,-n -Wl,-T $^ -o $@ +quiet_cmd_vdso-ilp32as = VDSOILP32A $@ + cmd_vdso-ilp32as = $(CC) $(a_flags) -mabi=ilp32 -c -o $@ $< + +# Install commands for the unstripped file +quiet_cmd_vdso_install = INSTALL $@ + cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ + +vdso-ilp32.so: $(obj)/vdso-ilp32.so.dbg + @mkdir -p $(MODLIB)/vdso + $(call cmd,vdso_install) + +vdso_install: vdso-ilp32.so diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S new file mode 100644 index 000000000000..46ac0728443c --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Will Deacon + */ + +#include +#include +#include +#include + + __PAGE_ALIGNED_DATA + + .globl vdso_ilp32_start, vdso_ilp32_end + .balign PAGE_SIZE +vdso_ilp32_start: + .incbin "arch/arm64/kernel/vdso-ilp32/vdso-ilp32.so" + .balign PAGE_SIZE +vdso_ilp32_end: + + .previous diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S new file mode 100644 index 000000000000..ac8029bb03c8 --- /dev/null +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S @@ -0,0 +1,98 @@ +/* + * GNU linker script for the VDSO library. + * + * Copyright (C) 2012 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Will Deacon + * Heavily based on the vDSO linker scripts for other archs. + */ + +#include +#include +#include + +/*OUTPUT_FORMAT("elf32-littleaarch64", "elf32-bigaarch64", "elf32-littleaarch64") +OUTPUT_ARCH(aarch64) +*/ +SECTIONS +{ + PROVIDE(_vdso_data = . - PAGE_SIZE); + . = VDSO_LBASE + SIZEOF_HEADERS; + + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + .note : { *(.note.*) } :text :note + + . = ALIGN(16); + + .text : { *(.text*) } :text =0xd503201f + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + + .dynamic : { *(.dynamic) } :text :dynamic + + .rodata : { *(.rodata*) } :text + + _end = .; + PROVIDE(end = .); + + /DISCARD/ : { + *(.note.GNU-stack) + *(.data .data.* .gnu.linkonce.d.* .sdata*) + *(.bss .sbss .dynbss .dynsbss) + } +} + +/* + * We must supply the ELF program headers explicitly to get just one + * PT_LOAD segment, and set the flags explicitly to make segments read-only. + */ +PHDRS +{ + text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + note PT_NOTE FLAGS(4); /* PF_R */ + eh_frame_hdr PT_GNU_EH_FRAME; +} + +/* + * This controls what symbols we export from the DSO. + */ +VERSION +{ + LINUX_2.6.39 { + global: + __kernel_rt_sigreturn; + __kernel_gettimeofday; + __kernel_clock_gettime; + __kernel_clock_getres; + local: *; + }; +} + +/* + * Make the sigreturn code visible to the kernel. + */ +VDSO_sigtramp_ilp32 = __kernel_rt_sigreturn; diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index a777ac3d0a05..21b3726bd751 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -41,6 +41,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. */ @@ -110,24 +116,31 @@ 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 struct vm_special_mapping vdso_spec[2][2]; -static int __init vdso_init(void) +static inline int __init vdso_init_common(char *vdso_start, char *vdso_end, + unsigned long *vdso_pagesp, + struct page ***vdso_pagelistp, + bool ilp32) { int i; + unsigned long vdso_pages; + struct page **vdso_pagelist; - if (memcmp(&vdso_start, "\177ELF", 4)) { + if (memcmp(vdso_start, "\177ELF", 4)) { pr_err("vDSO is not a valid ELF object!\n"); return -EINVAL; } - vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT; + vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT; + *vdso_pagesp = vdso_pages; pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n", - vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data); + vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data); /* Allocate the vDSO pagelist, plus a page for the data. */ vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *), GFP_KERNEL); + *vdso_pagelistp = vdso_pagelist; if (vdso_pagelist == NULL) return -ENOMEM; @@ -136,33 +149,63 @@ static int __init vdso_init(void) /* Grab the vDSO code pages. */ for (i = 0; i < vdso_pages; i++) - vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE); + vdso_pagelist[i + 1] = virt_to_page(vdso_start + i * PAGE_SIZE); /* Populate the special mapping structures */ - vdso_spec[0] = (struct vm_special_mapping) { + vdso_spec[ilp32][0] = (struct vm_special_mapping) { .name = "[vvar]", .pages = vdso_pagelist, }; - vdso_spec[1] = (struct vm_special_mapping) { + vdso_spec[ilp32][1] = (struct vm_special_mapping) { .name = "[vdso]", .pages = &vdso_pagelist[1], }; return 0; } + +static int __init vdso_init(void) +{ + return vdso_init_common(&vdso_start, &vdso_end, + &vdso_pages, &vdso_pagelist, 0); +} arch_initcall(vdso_init); +#ifdef CONFIG_ARM64_ILP32 +static int __init vdso_ilp32_init(void) +{ + return vdso_init_common(&vdso_ilp32_start, &vdso_ilp32_end, + &vdso_ilp32_pages, &vdso_ilp32_pagelist, 1); +} +arch_initcall(vdso_ilp32_init); +#endif + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; unsigned long vdso_base, vdso_text_len, vdso_mapping_len; void *ret; - - vdso_text_len = vdso_pages << PAGE_SHIFT; + struct page **pagelist; + unsigned long pages; + bool ilp32; + +#ifdef CONFIG_ARM64_ILP32 + ilp32 = is_ilp32_compat_task(); + if (is_ilp32_compat_task()) { + pages = vdso_ilp32_pages; + pagelist = vdso_ilp32_pagelist; + } else +#endif + { + ilp32 = false; + pages = vdso_pages; + pagelist = vdso_pagelist; + } + vdso_text_len = pages << PAGE_SHIFT; /* Be sure to map the data page */ - vdso_mapping_len = vdso_text_len + PAGE_SIZE; + vdso_mapping_len = (pages + 1) << PAGE_SHIFT; down_write(&mm->mmap_sem); vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0); @@ -172,7 +215,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, } ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE, VM_READ|VM_MAYREAD, - &vdso_spec[0]); + &vdso_spec[ilp32][0]); if (IS_ERR(ret)) goto up_fail; @@ -181,7 +224,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, ret = _install_special_mapping(mm, vdso_base, vdso_text_len, VM_READ|VM_EXEC| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, - &vdso_spec[1]); + &vdso_spec[ilp32][1]); if (IS_ERR(ret)) goto up_fail; -- cgit v1.2.3 From 13737c6712659357fde2e64fa6ed6830ea700dc0 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:13 -0700 Subject: ptrace: Allow compat to use the native siginfo With ARM64 ILP32 ABI, we want to use the non-compat siginfo as we want to simplify signal handling for this new ABI. This patch just adds a new define COMPAT_USE_NATIVE_SIGINFO and if it is true then read/write in the compat case as it was the non-compat case. Signed-off-by: Andrew Pinski --- include/linux/compat.h | 4 ++++ kernel/ptrace.c | 25 ++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/linux/compat.h b/include/linux/compat.h index e6494261eaff..2d8c53541a0c 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -24,6 +24,10 @@ #define COMPAT_USE_64BIT_TIME 0 #endif +#ifndef COMPAT_USE_NATIVE_SIGINFO +#define COMPAT_USE_NATIVE_SIGINFO 0 +#endif + #ifndef __SC_DELOUSE #define __SC_DELOUSE(t,v) ((t)(unsigned long)(v)) #endif diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 54e75226c2c4..40ae023d20dd 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -657,7 +657,7 @@ static int ptrace_peek_siginfo(struct task_struct *child, break; #ifdef CONFIG_COMPAT - if (unlikely(is_compat_task())) { + if (unlikely(is_compat_task() && !COMPAT_USE_NATIVE_SIGINFO)) { compat_siginfo_t __user *uinfo = compat_ptr(data); if (copy_siginfo_to_user32(uinfo, &info) || @@ -1126,16 +1126,27 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request, case PTRACE_GETSIGINFO: ret = ptrace_getsiginfo(child, &siginfo); - if (!ret) - ret = copy_siginfo_to_user32( - (struct compat_siginfo __user *) datap, - &siginfo); + if (!ret) { + if (COMPAT_USE_NATIVE_SIGINFO) + ret = copy_siginfo_to_user( + (struct siginfo __user *) datap, + &siginfo); + else + ret = copy_siginfo_to_user32( + (struct compat_siginfo __user *) datap, + &siginfo); + } break; case PTRACE_SETSIGINFO: memset(&siginfo, 0, sizeof siginfo); - if (copy_siginfo_from_user32( - &siginfo, (struct compat_siginfo __user *) datap)) + if (COMPAT_USE_NATIVE_SIGINFO) + ret = copy_from_user(&siginfo, datap, sizeof(siginfo)); + else + ret = copy_siginfo_from_user32( + &siginfo, + (struct compat_siginfo __user *) datap); + if (ret) ret = -EFAULT; else ret = ptrace_setsiginfo(child, &siginfo); -- cgit v1.2.3 From 3a33f13ccf73bf00fcbd5afc90ec22793c1c3d29 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:14 -0700 Subject: ARM64:ILP32: The native siginfo is used instead of the compat siginfo Set COMPAT_USE_NATIVE_SIGINFO to be true for non AARCH32 tasks. Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/compat.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 0f4ecfea4546..a8c4caf0c084 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -211,6 +211,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 -- cgit v1.2.3 From c167810daa92daa4dfcec57e3f9f996ee34ee000 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:15 -0700 Subject: ARM64:ILP32: Use a seperate syscall table as a few syscalls need to be using the compat syscalls Some syscalls are still need to use the compat versions. So we need to have a seperate syscall table for ILP32. This patch adds them including documentation on why we need to use each one. This list is based on the list from https://lkml.org/lkml/2013/9/11/478. Signed-off-by: Andrew Pinski --- arch/arm64/include/asm/syscalls.h | 4 + arch/arm64/include/asm/unistd.h | 4 + arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/entry.S | 13 ++- arch/arm64/kernel/sys_ilp32.c | 195 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/kernel/sys_ilp32.c diff --git a/arch/arm64/include/asm/syscalls.h b/arch/arm64/include/asm/syscalls.h index 48fe7c600e98..b58dad785c29 100644 --- a/arch/arm64/include/asm/syscalls.h +++ b/arch/arm64/include/asm/syscalls.h @@ -25,6 +25,10 @@ */ asmlinkage long sys_rt_sigreturn_wrapper(void); +#ifdef CONFIG_ARM64_ILP32 +long ilp32_sys_sigaltstack(const stack_t __user *, stack_t __user *); +#endif + #include #endif /* __ASM_SYSCALLS_H */ diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 70e55598c7dd..c99815ab64f1 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -13,6 +13,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#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 diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index ceb9bf785605..98c6c85f6765 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -19,6 +19,7 @@ arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \ sys_compat.o +arm64-obj-$(CONFIG_ARM64_ILP32) += sys_ilp32.o arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 5a1430c8ced8..537be149c6e4 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -642,9 +642,14 @@ ENDPROC(ret_from_fork) */ .align 6 el0_svc: - adrp stbl, sys_call_table // load syscall table pointer uxtw scno, w8 // syscall number in w8 mov sc_nr, #__NR_syscalls +#ifdef CONFIG_ARM64_ILP32 + get_thread_info tsk + ldr x16, [tsk, #TI_FLAGS] + tbnz x16, #TIF_32BIT, el0_ilp32_svc // We are using ILP32 +#endif + adrp stbl, sys_call_table // load syscall table pointer el0_svc_naked: // compat entry point stp x0, scno, [sp, #S_ORIG_X0] // save the original x0 and syscall number enable_dbg_and_irq @@ -663,6 +668,12 @@ ni_sys: b do_ni_syscall ENDPROC(el0_svc) +#ifdef CONFIG_ARM64_ILP32 +el0_ilp32_svc: + adrp stbl, sys_call_ilp32_table // load syscall table pointer + b el0_svc_naked +#endif + /* * This is the really slow path. We're going to be doing context * switches, and waiting for our parent to respond. diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c new file mode 100644 index 000000000000..893f7d6a28c8 --- /dev/null +++ b/arch/arm64/kernel/sys_ilp32.c @@ -0,0 +1,195 @@ +/* + * AArch64- ILP32 specific system calls implementation + * + * Copyright (C) 2013 Cavium Inc. + * Author: Andrew Pinski + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Wrappers to pass the pt_regs argument. + */ +#define sys_rt_sigreturn sys_rt_sigreturn_wrapper + +/* + * Note places where mention unsigned long bitmaps, could + * use the non compat version for little-endian but big-endian + * has issues to do layout of the bits in the bitmaps. + */ + +/* Using Compat syscalls where necessary */ +#define sys_ioctl compat_sys_ioctl +/* iovec */ +#define sys_readv compat_sys_readv +#define sys_writev compat_sys_writev +#define sys_preadv compat_sys_preadv64 +#define sys_pwritev compat_sys_pwritev64 +#define sys_vmsplice compat_sys_vmsplice +/* robust_list_head */ +#define sys_set_robust_list compat_sys_set_robust_list +#define sys_get_robust_list compat_sys_get_robust_list + +/* kexec_segment */ +#define sys_kexec_load compat_sys_kexec_load + +/* Ptrace has some structures which are different between ILP32 and LP64 */ +#define sys_ptrace compat_sys_ptrace + +/* struct msghdr */ +#define sys_recvfrom compat_sys_recvfrom +#define sys_recvmmsg compat_sys_recvmmsg +#define sys_sendmmsg compat_sys_sendmmsg +#define sys_sendmsg compat_sys_sendmsg +#define sys_recvmsg compat_sys_recvmsg + +/* + * Note the timeval is taken care by COMPAT_USE_64BIT_TIME + * being true. + */ +#define sys_setsockopt compat_sys_setsockopt +#define sys_getsockopt compat_sys_getsockopt + +/* Array of pointers */ +#define sys_execve compat_sys_execve +#define sys_move_pages compat_sys_move_pages + +/* iovec */ +#define sys_process_vm_readv compat_sys_process_vm_readv +#define sys_process_vm_writev compat_sys_process_vm_writev + +/* + * The NFSv4 and ncpfs structures are depend on the long and + * pointer sizes. + */ +#define sys_mount compat_sys_mount + +/* NUMA */ +/* unsigned long bitmaps */ +#define sys_get_mempolicy compat_sys_get_mempolicy +#define sys_set_mempolicy compat_sys_set_mempolicy +#define sys_mbind compat_sys_mbind + +/* array of pointers */ +/* unsigned long bitmaps */ +#define sys_migrate_pages compat_sys_migrate_pages + +/* Scheduler */ +/* unsigned long bitmaps */ +#define sys_sched_setaffinity compat_sys_sched_setaffinity +#define sys_sched_getaffinity compat_sys_sched_getaffinity + +/* iov usage */ +#define sys_keyctl compat_sys_keyctl + +/* aio */ +/* Array of pointers (iocb's) */ +#define sys_io_submit compat_sys_io_submit + +/* We need to make sure the pointer gets copied correctly. */ +asmlinkage long ilp32_sys_mq_notify(mqd_t mqdes, + const struct sigevent __user *u_notification) +{ + struct sigevent __user *p = NULL; + + if (u_notification) { + struct sigevent n; + + p = compat_alloc_user_space(sizeof(*p)); + if (copy_from_user(&n, u_notification, sizeof(*p))) + return -EFAULT; + if (n.sigev_notify == SIGEV_THREAD) + n.sigev_value.sival_ptr = compat_ptr((uintptr_t)n.sigev_value.sival_ptr); + if (copy_to_user(p, &n, sizeof(*p))) + return -EFAULT; + } + return sys_mq_notify(mqdes, p); +} + +/* + * sigevent contains sigval_t which is now 64bit always + * but need special handling due to padding for SIGEV_THREAD. + */ +#define sys_mq_notify ilp32_sys_mq_notify + + +/* + * sigaltstack needs some special handling as the + * padding for stack_t might not be non-zero. + */ +long ilp32_sys_sigaltstack(const stack_t __user *uss_ptr, + stack_t __user *uoss_ptr) +{ + stack_t uss, uoss; + int ret; + mm_segment_t seg; + + if (uss_ptr) { + if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr))) + return -EFAULT; + if (__get_user(uss.ss_sp, &uss_ptr->ss_sp) | + __get_user(uss.ss_flags, &uss_ptr->ss_flags) | + __get_user(uss.ss_size, &uss_ptr->ss_size)) + return -EFAULT; + /* Zero extend the sp address and the size. */ + uss.ss_sp = (void *)(uintptr_t)(unsigned int)(uintptr_t)uss.ss_sp; + uss.ss_size = (size_t)(unsigned int)uss.ss_size; + } + seg = get_fs(); + set_fs(KERNEL_DS); + /* + * Note we need to use uoss as we have changed the segment to the + * kernel one so passing an user one around is wrong. + */ + ret = sys_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), + (stack_t __force __user *) &uoss); + set_fs(seg); + if (ret >= 0 && uoss_ptr) { + if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_t)) || + __put_user(uoss.ss_sp, &uoss_ptr->ss_sp) || + __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || + __put_user(uoss.ss_size, &uoss_ptr->ss_size)) + ret = -EFAULT; + } + return ret; +} + +/* + * sigaltstack needs some special handling as the padding + * for stack_t might not be non-zero. + */ +#define sys_sigaltstack ilp32_sys_sigaltstack + +#include + +#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 +}; -- cgit v1.2.3 From 83c39e04015427c69d2f48735095a56c4aa63259 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:16 -0700 Subject: ARM64:ILP32: Fix signal return for ILP32 when the user modified the signal stack If the user decided to change the stack_t that was on the stack when returning from the signal handler, the stack_t's padding for ILP32 might be not zero. So we need to use the syscall version of restore_altstack (ilp32_sys_sigaltstack). Signed-off-by: Andrew Pinski --- arch/arm64/kernel/signal.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 5311147ba764..6316d54b8875 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * Do a signal return; undo the signal stack. These are aligned to 128-bit. @@ -149,6 +150,19 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigframe(regs, frame)) goto badframe; +#ifdef CONFIG_ARM64_ILP32 + /* + * ILP32 has to be handled "special" due to maybe not zeroing out + * the upper 32bits of the pointer if the user changed the frame. + */ + if (is_ilp32_compat_task()) { + if (ilp32_sys_sigaltstack(&frame->uc.uc_stack, + NULL) == -EFAULT) + goto badframe; + return regs->regs[0]; + } +#endif + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; -- cgit v1.2.3 From b5f1db849f9c2773d318f27091bb42dd0941af7b Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:17 -0700 Subject: ARM64: Add ARM64_ILP32 to Kconfig This patch adds the config option for ILP32. Signed-off-by: Andrew Pinski --- arch/arm64/Kconfig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index f28af3f3c604..9b92318296a6 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -409,7 +409,7 @@ source "fs/Kconfig.binfmt" config COMPAT def_bool y - depends on AARCH32_EL0 + depends on AARCH32_EL0 || ARM64_ILP32 select COMPAT_BINFMT_ELF config AARCH32_EL0 @@ -426,6 +426,13 @@ config AARCH32_EL0 If you want to execute 32-bit userspace applications, say Y. +config ARM64_ILP32 + bool "Kernel support for ILP32" + help + This option enables support for AArch64 ILP32 user space. ILP32 + is an ABI where long and pointers are 32bits but it uses the AARCH64 + instruction set. + config SYSVIPC_COMPAT def_bool y depends on AARCH32_EL0 && SYSVIPC -- cgit v1.2.3 From 912465ff3a6c600fbd9315533cf8d4ec8c570b63 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 3 Sep 2014 14:19:18 -0700 Subject: Add documentation about ARM64 ILP32 ABI This adds the documentation about the ILP32 ABI and what is difference between it and the normal generic 32bit ABI. Signed-off-by: Andrew Pinski --- Documentation/arm64/ilp32.txt | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Documentation/arm64/ilp32.txt diff --git a/Documentation/arm64/ilp32.txt b/Documentation/arm64/ilp32.txt new file mode 100644 index 000000000000..0863aa4eac36 --- /dev/null +++ b/Documentation/arm64/ilp32.txt @@ -0,0 +1,57 @@ + ILP32 AARCH64 SYSCALL ABI + ===================== + +Author: Andrew Pinski +Date: May 23, 2014 + +This document describes the ILP32 syscall ABI and where it differs +from the generic linux syscall interface. +ILP32 sets __kernel_long_t and __kernel_ulong_t both to 64bit +(long long). This effects the following types: +* time_t: unsigned long long +* clock_t: unsigned long long +* fsword_t: long long +* suseconds_t: long long +* swblk_t: long long +* fd_mask_t: long long + +Some structures are changed to reduce the difference in the code path +for both ILP32 and LP64 ABIs for signal handling. + +The following structures have been changed so the layout of the structures are the same between ILP32 and LP64 ABIs. +* timespec: Uses time_t and suseconds_t +* timeval: Uses time_t and suseconds_t +* stat: Uses timespec/time_t. +* semid64_ds: Uses time_t. +* msqid64_ds: Uses time_t. +* shmid64_ds: Uses time_t. +* rt_sigframe: Uses siginfo and ucontext. +* siginfo_t: Uses clock_t and sigval_t +* ucontext: Uses stack_t and sigset_t +* stack_t: NOTE special handling inside the kernel is done to make sure + the pointers are zero extended +* sigval_t: Contains pointers +* sigevent: Uses sigval_t which causes it to be the same. Special + handing is needed for reading; in the mq_notify syscall +* sigaction: NOTE the userland structure inside glibc does + not match the kernel structure here (this causes issues with LTP). + Uses sigset_t. +* fd_set: This is done to avoid endian issues between ILP32 and LP64 + Also the syscall which uses fd_set uses timespec + + +Also the syscalls which normally would pass 64bit values as two +arguments; now pass the 64bit value as one argument. Also they have +been renamed (removing the 64 from the name) to avoid confusion. +The list of these syscalls: +* fcntl +* statfs +* fstatfs +* truncate +* ftruncate +* lseek +* sendfile +* newfstatat +* fstat +* mmap +* fadvise64 -- cgit v1.2.3 From a33d84566e90cc279db7cc54de45ab92ce10bdf6 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 15 Oct 2014 14:49:53 +0400 Subject: ARM64:ILP32: fix the compilation error due to mistyped header file name There is a misprint in the v3 patch "ARM64:ILP32: Use the same size and layout of the signal structures for ILP32 as for LP64". Signed-off-by: Andrey Konovalov --- arch/arm64/include/uapi/asm/signal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/include/uapi/asm/signal.h b/arch/arm64/include/uapi/asm/signal.h index d33a5f77ec44..f378ff4f93d7 100644 --- a/arch/arm64/include/uapi/asm/signal.h +++ b/arch/arm64/include/uapi/asm/signal.h @@ -16,7 +16,7 @@ #ifndef __ASM_SIGNAL_H #define __ASM_SIGNAL_H -#include +#include /* Required for AArch32 compatibility. */ #define SA_RESTORER 0x04000000 -- cgit v1.2.3