arm64: compat: Check for AArch32 state
authorSuzuki K Poulose <suzuki.poulose@arm.com>
Mon, 18 Apr 2016 09:28:37 +0000 (10:28 +0100)
committerWill Deacon <will.deacon@arm.com>
Wed, 20 Apr 2016 11:22:42 +0000 (12:22 +0100)
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>
arch/arm64/include/asm/elf.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/sys.c

index 24ed037f09fd32385b9ccfb0e8d380b5c0d5c7ed..7a09c48c04752d2b1790c1777dd1b72dd39dd117 100644 (file)
@@ -177,7 +177,8 @@ typedef compat_elf_greg_t           compat_elf_gregset_t[COMPAT_ELF_NGREG];
 
 /* AArch32 EABI. */
 #define EF_ARM_EABI_MASK               0xff000000
-#define compat_elf_check_arch(x)       (((x)->e_machine == EM_ARM) && \
+#define compat_elf_check_arch(x)       (system_supports_32bit_el0() && \
+                                        ((x)->e_machine == EM_ARM) && \
                                         ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread            compat_start_thread
index 40a23f24559d4c355713410f50dd7411c474a1ee..8e62d61f6c4217e8d0fb21678a8ed9a3d7a1df44 100644 (file)
@@ -987,7 +987,8 @@ void verify_local_cpu_capabilities(void)
 
        verify_local_cpu_features(arm64_features);
        verify_local_elf_hwcaps(arm64_elf_hwcaps);
-       verify_local_elf_hwcaps(compat_elf_hwcaps);
+       if (system_supports_32bit_el0())
+               verify_local_elf_hwcaps(compat_elf_hwcaps);
 }
 
 static void __init setup_feature_capabilities(void)
@@ -1004,7 +1005,9 @@ void __init setup_cpu_features(void)
        /* Set the CPU feature capabilies */
        setup_feature_capabilities();
        setup_elf_hwcaps(arm64_elf_hwcaps);
-       setup_elf_hwcaps(compat_elf_hwcaps);
+
+       if (system_supports_32bit_el0())
+               setup_elf_hwcaps(compat_elf_hwcaps);
 
        /* Advertise that we have computed the system capabilities */
        set_sys_caps_initialised();
index 75151aaf1a52025237be5e0becc8ffac514bae2c..26fe8ea93ea2b18d7f87e45203bfd9633cdfe5bc 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
+#include <asm/cpufeature.h>
 
 asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
                         unsigned long prot, unsigned long flags,
@@ -36,11 +37,20 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
        return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 }
 
+SYSCALL_DEFINE1(arm64_personality, unsigned int, personality)
+{
+       if (personality(personality) == PER_LINUX32 &&
+               !system_supports_32bit_el0())
+               return -EINVAL;
+       return sys_personality(personality);
+}
+
 /*
  * Wrappers to pass the pt_regs argument.
  */
 asmlinkage long sys_rt_sigreturn_wrapper(void);
 #define sys_rt_sigreturn       sys_rt_sigreturn_wrapper
+#define sys_personality                sys_arm64_personality
 
 #undef __SYSCALL
 #define __SYSCALL(nr, sym)     [nr] = sym,