diff options
author | Suzuki K Poulose <suzuki.poulose@arm.com> | 2016-04-18 05:28:37 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2016-04-20 07:22:42 -0400 |
commit | 643d703d2d2dbf8e2f16efa0a6a32b1eca101d02 (patch) | |
tree | 5dc230cc9dc4d09fd679570c2090bec3c952b97a | |
parent | 042446a31e3803d81c7e618dd80928dc3dce70c5 (diff) |
arm64: compat: Check for AArch32 state
Make sure we have AArch32 state available for running COMPAT
binaries and also for switching the personality to PER_LINUX32.
Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
[ Added cap bit, checks for HWCAP, personality ]
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Tested-by: Yury Norov <ynorov@caviumnetworks.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | arch/arm64/include/asm/elf.h | 3 | ||||
-rw-r--r-- | arch/arm64/kernel/cpufeature.c | 7 | ||||
-rw-r--r-- | arch/arm64/kernel/sys.c | 10 |
3 files changed, 17 insertions, 3 deletions
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 24ed037f09fd..7a09c48c0475 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h | |||
@@ -177,7 +177,8 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; | |||
177 | 177 | ||
178 | /* AArch32 EABI. */ | 178 | /* AArch32 EABI. */ |
179 | #define EF_ARM_EABI_MASK 0xff000000 | 179 | #define EF_ARM_EABI_MASK 0xff000000 |
180 | #define compat_elf_check_arch(x) (((x)->e_machine == EM_ARM) && \ | 180 | #define compat_elf_check_arch(x) (system_supports_32bit_el0() && \ |
181 | ((x)->e_machine == EM_ARM) && \ | ||
181 | ((x)->e_flags & EF_ARM_EABI_MASK)) | 182 | ((x)->e_flags & EF_ARM_EABI_MASK)) |
182 | 183 | ||
183 | #define compat_start_thread compat_start_thread | 184 | #define compat_start_thread compat_start_thread |
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 40a23f24559d..8e62d61f6c42 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c | |||
@@ -987,7 +987,8 @@ void verify_local_cpu_capabilities(void) | |||
987 | 987 | ||
988 | verify_local_cpu_features(arm64_features); | 988 | verify_local_cpu_features(arm64_features); |
989 | verify_local_elf_hwcaps(arm64_elf_hwcaps); | 989 | verify_local_elf_hwcaps(arm64_elf_hwcaps); |
990 | verify_local_elf_hwcaps(compat_elf_hwcaps); | 990 | if (system_supports_32bit_el0()) |
991 | verify_local_elf_hwcaps(compat_elf_hwcaps); | ||
991 | } | 992 | } |
992 | 993 | ||
993 | static void __init setup_feature_capabilities(void) | 994 | static void __init setup_feature_capabilities(void) |
@@ -1004,7 +1005,9 @@ void __init setup_cpu_features(void) | |||
1004 | /* Set the CPU feature capabilies */ | 1005 | /* Set the CPU feature capabilies */ |
1005 | setup_feature_capabilities(); | 1006 | setup_feature_capabilities(); |
1006 | setup_elf_hwcaps(arm64_elf_hwcaps); | 1007 | setup_elf_hwcaps(arm64_elf_hwcaps); |
1007 | setup_elf_hwcaps(compat_elf_hwcaps); | 1008 | |
1009 | if (system_supports_32bit_el0()) | ||
1010 | setup_elf_hwcaps(compat_elf_hwcaps); | ||
1008 | 1011 | ||
1009 | /* Advertise that we have computed the system capabilities */ | 1012 | /* Advertise that we have computed the system capabilities */ |
1010 | set_sys_caps_initialised(); | 1013 | set_sys_caps_initialised(); |
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c index 75151aaf1a52..26fe8ea93ea2 100644 --- a/arch/arm64/kernel/sys.c +++ b/arch/arm64/kernel/sys.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/syscalls.h> | 27 | #include <linux/syscalls.h> |
28 | #include <asm/cpufeature.h> | ||
28 | 29 | ||
29 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | 30 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, |
30 | unsigned long prot, unsigned long flags, | 31 | unsigned long prot, unsigned long flags, |
@@ -36,11 +37,20 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | |||
36 | return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); | 37 | return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); |
37 | } | 38 | } |
38 | 39 | ||
40 | SYSCALL_DEFINE1(arm64_personality, unsigned int, personality) | ||
41 | { | ||
42 | if (personality(personality) == PER_LINUX32 && | ||
43 | !system_supports_32bit_el0()) | ||
44 | return -EINVAL; | ||
45 | return sys_personality(personality); | ||
46 | } | ||
47 | |||
39 | /* | 48 | /* |
40 | * Wrappers to pass the pt_regs argument. | 49 | * Wrappers to pass the pt_regs argument. |
41 | */ | 50 | */ |
42 | asmlinkage long sys_rt_sigreturn_wrapper(void); | 51 | asmlinkage long sys_rt_sigreturn_wrapper(void); |
43 | #define sys_rt_sigreturn sys_rt_sigreturn_wrapper | 52 | #define sys_rt_sigreturn sys_rt_sigreturn_wrapper |
53 | #define sys_personality sys_arm64_personality | ||
44 | 54 | ||
45 | #undef __SYSCALL | 55 | #undef __SYSCALL |
46 | #define __SYSCALL(nr, sym) [nr] = sym, | 56 | #define __SYSCALL(nr, sym) [nr] = sym, |