aboutsummaryrefslogtreecommitdiff
path: root/arch/arm64/include
diff options
context:
space:
mode:
authorAmit Pundir <amit.pundir@linaro.org>2015-02-20 12:17:40 +0530
committerAmit Pundir <amit.pundir@linaro.org>2015-02-20 13:21:54 +0530
commit7ffdd3fae2e1917268ed35b76ec905ed5b166aa6 (patch)
tree5b45c802ffc3ce5d97b8f990bb2b69996bdac478 /arch/arm64/include
parent37d37744341e65b39bf6e8141ba3b46c8a0772f0 (diff)
parenteec2486674b53d8ca576677cae60bc3f380d33c1 (diff)
Merge branch 'linaro-android-3.14-lsk' into linux-linaro-lsk-v3.14-android
* linaro-android-3.14-lsk: (52 commits) xt_qtaguid: use sock_gen_put() instead of xt_socket_put_sk() android: base-cfg: enable ARMV8_DEPRECATED and subfeatures arm64: kconfig: move emulation option under kernel features kbuild: make it possible to specify the module output dir arm64: Emulate SETEND for AArch32 tasks arm64: Consolidate hotplug notifier for instruction emulation arm64: kernel: explicitly add include in armv8_deprecated arm64: Track system support for mixed endian EL0 arm64: Fix up /proc/cpuinfo arm64: cpuinfo: record cpu system register values arm64: add MIDR_EL1 field accessors arm64: fix return code check when changing emulation handler arm64: Trace emulation of AArch32 legacy instructions arm64: Emulate CP15 Barrier instructions arm64: barriers: add dmb barrier arm64: Port SWP/SWPB emulation support from arm arm64: Add framework for legacy instruction emulation arm64: Add AArch32 instruction set condition code checks arm64: Add support for hooks to handle undefined instructions arm64: kernel: Explicitly add include in traps.c ... Signed-off-by: Amit Pundir <amit.pundir@linaro.org> Conflicts: arch/arm64/include/asm/barrier.h arch/arm64/include/asm/cputype.h arch/arm64/include/asm/insn.h arch/arm64/kernel/Makefile arch/arm64/kernel/setup.c
Diffstat (limited to 'arch/arm64/include')
-rw-r--r--arch/arm64/include/asm/cpu.h59
-rw-r--r--arch/arm64/include/asm/cpufeature.h3
-rw-r--r--arch/arm64/include/asm/cputype.h50
-rw-r--r--arch/arm64/include/asm/insn.h10
-rw-r--r--arch/arm64/include/asm/opcodes.h232
-rw-r--r--arch/arm64/include/asm/ptrace.h15
-rw-r--r--arch/arm64/include/asm/traps.h9
7 files changed, 129 insertions, 249 deletions
diff --git a/arch/arm64/include/asm/cpu.h b/arch/arm64/include/asm/cpu.h
new file mode 100644
index 000000000000..056443086019
--- /dev/null
+++ b/arch/arm64/include/asm/cpu.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CPU_H
+#define __ASM_CPU_H
+
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+
+/*
+ * Records attributes of an individual CPU.
+ */
+struct cpuinfo_arm64 {
+ struct cpu cpu;
+ u32 reg_ctr;
+ u32 reg_cntfrq;
+ u32 reg_dczid;
+ u32 reg_midr;
+
+ u64 reg_id_aa64isar0;
+ u64 reg_id_aa64isar1;
+ u64 reg_id_aa64mmfr0;
+ u64 reg_id_aa64mmfr1;
+ u64 reg_id_aa64pfr0;
+ u64 reg_id_aa64pfr1;
+
+ u32 reg_id_isar0;
+ u32 reg_id_isar1;
+ u32 reg_id_isar2;
+ u32 reg_id_isar3;
+ u32 reg_id_isar4;
+ u32 reg_id_isar5;
+ u32 reg_id_mmfr0;
+ u32 reg_id_mmfr1;
+ u32 reg_id_mmfr2;
+ u32 reg_id_mmfr3;
+ u32 reg_id_pfr0;
+ u32 reg_id_pfr1;
+};
+
+DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data);
+
+void cpuinfo_store_cpu(void);
+void __init cpuinfo_store_boot_cpu(void);
+
+#endif /* __ASM_CPU_H */
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index cd4ac0516488..7db3c63ec2e3 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -26,4 +26,7 @@ static inline bool cpu_have_feature(unsigned int num)
return elf_hwcap & (1UL << num);
}
+bool cpu_supports_mixed_endian_el0(void);
+bool system_supports_mixed_endian_el0(void);
+
#endif
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 27f54a7cc81b..39636a426c56 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -36,15 +36,46 @@
__val; \
})
+#define MIDR_REVISION_MASK 0xf
+#define MIDR_REVISION(midr) ((midr) & MIDR_REVISION_MASK)
+#define MIDR_PARTNUM_SHIFT 4
+#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT)
+#define MIDR_PARTNUM(midr) \
+ (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT)
+#define MIDR_ARCHITECTURE_SHIFT 16
+#define MIDR_ARCHITECTURE_MASK (0xf << MIDR_ARCHITECTURE_SHIFT)
+#define MIDR_ARCHITECTURE(midr) \
+ (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT)
+#define MIDR_VARIANT_SHIFT 20
+#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT)
+#define MIDR_VARIANT(midr) \
+ (((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT)
+#define MIDR_IMPLEMENTOR_SHIFT 24
+#define MIDR_IMPLEMENTOR_MASK (0xff << MIDR_IMPLEMENTOR_SHIFT)
+#define MIDR_IMPLEMENTOR(midr) \
+ (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
+
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_IMP_APM 0x50
-#define ARM_CPU_PART_AEM_V8 0xD0F0
-#define ARM_CPU_PART_FOUNDATION 0xD000
-#define ARM_CPU_PART_CORTEX_A53 0xD030
-#define ARM_CPU_PART_CORTEX_A57 0xD070
+#define ARM_CPU_PART_AEM_V8 0xD0F
+#define ARM_CPU_PART_FOUNDATION 0xD00
+#define ARM_CPU_PART_CORTEX_A57 0xD07
+#define ARM_CPU_PART_CORTEX_A53 0xD03
+
+#define APM_CPU_PART_POTENZA 0x000
+
+#define ID_AA64MMFR0_BIGENDEL0_SHIFT 16
+#define ID_AA64MMFR0_BIGENDEL0_MASK (0xf << ID_AA64MMFR0_BIGENDEL0_SHIFT)
+#define ID_AA64MMFR0_BIGENDEL0(mmfr0) \
+ (((mmfr0) & ID_AA64MMFR0_BIGENDEL0_MASK) >> ID_AA64MMFR0_BIGENDEL0_SHIFT)
+#define ID_AA64MMFR0_BIGEND_SHIFT 8
+#define ID_AA64MMFR0_BIGEND_MASK (0xf << ID_AA64MMFR0_BIGEND_SHIFT)
+#define ID_AA64MMFR0_BIGEND(mmfr0) \
+ (((mmfr0) & ID_AA64MMFR0_BIGEND_MASK) >> ID_AA64MMFR0_BIGEND_SHIFT)
-#define APM_CPU_PART_POTENZA 0x0000
+#define SCTLR_EL1_CP15BEN (0x1 << 5)
+#define SCTLR_EL1_SED (0x1 << 8)
#ifndef __ASSEMBLY__
@@ -65,12 +96,12 @@ static inline u64 __attribute_const__ read_cpuid_mpidr(void)
static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
{
- return (read_cpuid_id() & 0xFF000000) >> 24;
+ return MIDR_IMPLEMENTOR(read_cpuid_id());
}
static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
{
- return (read_cpuid_id() & 0xFFF0);
+ return MIDR_PARTNUM(read_cpuid_id());
}
static inline u32 __attribute_const__ read_cpuid_cachetype(void)
@@ -78,6 +109,11 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void)
return read_cpuid(CTR_EL0);
}
+static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
+{
+ return (ID_AA64MMFR0_BIGEND(mmfr0) == 0x1) ||
+ (ID_AA64MMFR0_BIGENDEL0(mmfr0) == 0x1);
+}
#endif /* __ASSEMBLY__ */
#endif
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 62e7b8bcd2dc..95da2f2ebc6b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -110,4 +110,14 @@ int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
#endif /* __ASSEMBLY__ */
+bool aarch32_insn_is_wide(u32 insn);
+
+#define A32_RN_OFFSET 16
+#define A32_RT_OFFSET 12
+#define A32_RT2_OFFSET 0
+
+u32 aarch32_insn_extract_reg_num(u32 insn, int offset);
+u32 aarch32_insn_mcr_extract_opc2(u32 insn);
+u32 aarch32_insn_mcr_extract_crm(u32 insn);
+
#endif /* __ASM_INSN_H */
diff --git a/arch/arm64/include/asm/opcodes.h b/arch/arm64/include/asm/opcodes.h
index fd189a522aee..4e603ea36ad3 100644
--- a/arch/arm64/include/asm/opcodes.h
+++ b/arch/arm64/include/asm/opcodes.h
@@ -1,231 +1 @@
-/*
- * Copied from arch/arm/include/asm/opcodes.h
- *
- * 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.
- */
-
-#ifndef __ASM_ARM_OPCODES_H
-#define __ASM_ARM_OPCODES_H
-
-#ifndef __ASSEMBLY__
-#include <linux/linkage.h>
-extern asmlinkage unsigned int arm_check_condition(u32 opcode, u64 psr);
-#endif
-
-#define ARM_OPCODE_CONDTEST_FAIL 0
-#define ARM_OPCODE_CONDTEST_PASS 1
-#define ARM_OPCODE_CONDTEST_UNCOND 2
-
-
-/*
- * Assembler opcode byteswap helpers.
- * These are only intended for use by this header: don't use them directly,
- * because they will be suboptimal in most cases.
- */
-#define ___asm_opcode_swab32(x) ( \
- (((x) << 24) & 0xFF000000) \
- | (((x) << 8) & 0x00FF0000) \
- | (((x) >> 8) & 0x0000FF00) \
- | (((x) >> 24) & 0x000000FF) \
-)
-#define ___asm_opcode_swab16(x) ( \
- (((x) << 8) & 0xFF00) \
- | (((x) >> 8) & 0x00FF) \
-)
-#define ___asm_opcode_swahb32(x) ( \
- (((x) << 8) & 0xFF00FF00) \
- | (((x) >> 8) & 0x00FF00FF) \
-)
-#define ___asm_opcode_swahw32(x) ( \
- (((x) << 16) & 0xFFFF0000) \
- | (((x) >> 16) & 0x0000FFFF) \
-)
-#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
-#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
-
-
-/*
- * Opcode byteswap helpers
- *
- * These macros help with converting instructions between a canonical integer
- * format and in-memory representation, in an endianness-agnostic manner.
- *
- * __mem_to_opcode_*() convert from in-memory representation to canonical form.
- * __opcode_to_mem_*() convert from canonical form to in-memory representation.
- *
- *
- * Canonical instruction representation:
- *
- * ARM: 0xKKLLMMNN
- * Thumb 16-bit: 0x0000KKLL, where KK < 0xE8
- * Thumb 32-bit: 0xKKLLMMNN, where KK >= 0xE8
- *
- * There is no way to distinguish an ARM instruction in canonical representation
- * from a Thumb instruction (just as these cannot be distinguished in memory).
- * Where this distinction is important, it needs to be tracked separately.
- *
- * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
- * represent any valid Thumb-2 instruction. For this range,
- * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
- *
- * The ___asm variants are intended only for use by this header, in situations
- * involving inline assembler. For .S files, the normal __opcode_*() macros
- * should do the right thing.
- */
-#ifdef __ASSEMBLY__
-
-#define ___opcode_swab32(x) ___asm_opcode_swab32(x)
-#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
-#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
-#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
-#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
-#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
-
-#else /* ! __ASSEMBLY__ */
-
-#include <linux/types.h>
-#include <linux/swab.h>
-
-#define ___opcode_swab32(x) swab32(x)
-#define ___opcode_swab16(x) swab16(x)
-#define ___opcode_swahb32(x) swahb32(x)
-#define ___opcode_swahw32(x) swahw32(x)
-#define ___opcode_identity32(x) ((u32)(x))
-#define ___opcode_identity16(x) ((u16)(x))
-
-#endif /* ! __ASSEMBLY__ */
-
-
-#ifdef CONFIG_CPU_ENDIAN_BE8
-
-#define __opcode_to_mem_arm(x) ___opcode_swab32(x)
-#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
-#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
-#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
-#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
-#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
-
-#else /* ! CONFIG_CPU_ENDIAN_BE8 */
-
-#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
-#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
-#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
-#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
-#ifndef CONFIG_CPU_ENDIAN_BE32
-/*
- * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
- * work in all cases, due to alignment constraints. For now, a correct
- * version is not provided for BE32.
- */
-#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
-#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
-#endif
-
-#endif /* ! CONFIG_CPU_ENDIAN_BE8 */
-
-#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
-#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
-#ifndef CONFIG_CPU_ENDIAN_BE32
-#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
-#endif
-
-/* Operations specific to Thumb opcodes */
-
-/* Instruction size checks: */
-#define __opcode_is_thumb32(x) ( \
- ((x) & 0xF8000000) == 0xE8000000 \
- || ((x) & 0xF0000000) == 0xF0000000 \
-)
-#define __opcode_is_thumb16(x) ( \
- ((x) & 0xFFFF0000) == 0 \
- && !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \
-)
-
-/* Operations to construct or split 32-bit Thumb instructions: */
-#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
-#define __opcode_thumb32_second(x) (___opcode_identity16(x))
-#define __opcode_thumb32_compose(first, second) ( \
- (___opcode_identity32(___opcode_identity16(first)) << 16) \
- | ___opcode_identity32(___opcode_identity16(second)) \
-)
-#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
-#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
-#define ___asm_opcode_thumb32_compose(first, second) ( \
- (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
- | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
-)
-
-/*
- * Opcode injection helpers
- *
- * In rare cases it is necessary to assemble an opcode which the
- * assembler does not support directly, or which would normally be
- * rejected because of the CFLAGS or AFLAGS used to build the affected
- * file.
- *
- * Before using these macros, consider carefully whether it is feasible
- * instead to change the build flags for your file, or whether it really
- * makes sense to support old assembler versions when building that
- * particular kernel feature.
- *
- * The macros defined here should only be used where there is no viable
- * alternative.
- *
- *
- * __inst_arm(x): emit the specified ARM opcode
- * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
- * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
- *
- * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
- * 16-bit Thumb opcode, depending on whether an ARM or Thumb-2
- * kernel is being built
- *
- * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
- * 32-bit Thumb opcode, depending on whether an ARM or Thumb-2
- * kernel is being built
- *
- *
- * Note that using these macros directly is poor practice. Instead, you
- * should use them to define human-readable wrapper macros to encode the
- * instructions that you care about. In code which might run on ARMv7 or
- * above, you can usually use the __inst_arm_thumb{16,32} macros to
- * specify the ARM and Thumb alternatives at the same time. This ensures
- * that the correct opcode gets emitted depending on the instruction set
- * used for the kernel build.
- *
- * Look at opcodes-virt.h for an example of how to use these macros.
- */
-#include <linux/stringify.h>
-
-#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
-#define __inst_thumb32(x) ___inst_thumb32( \
- ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \
- ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \
-)
-#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
-
-#ifdef CONFIG_THUMB2_KERNEL
-#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
- __inst_thumb16(thumb_opcode)
-#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
- __inst_thumb32(thumb_opcode)
-#else
-#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
-#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
-#endif
-
-/* Helpers for the helpers. Don't use these directly. */
-#ifdef __ASSEMBLY__
-#define ___inst_arm(x) .long x
-#define ___inst_thumb16(x) .short x
-#define ___inst_thumb32(first, second) .short first, second
-#else
-#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
-#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
-#define ___inst_thumb32(first, second) \
- ".short " __stringify(first) ", " __stringify(second) "\n\t"
-#endif
-
-#endif /* __ASM_ARM_OPCODES_H */
+#include <../../arm/include/asm/opcodes.h>
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index c29d88526405..904d936bbab5 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -54,6 +54,13 @@
#define COMPAT_PSR_Z_BIT 0x40000000
#define COMPAT_PSR_N_BIT 0x80000000
#define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define COMPAT_PSR_ENDSTATE COMPAT_PSR_E_BIT
+#else
+#define COMPAT_PSR_ENDSTATE 0
+#endif
+
/*
* These are 'magic' values for PTRACE_PEEKUSR that return info about where a
* process is located in memory.
@@ -187,13 +194,5 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define profile_pc(regs) instruction_pointer(regs)
#endif
-/*
- * True if instr is a 32-bit thumb instruction. This works if instr
- * is the first or only half-word of a thumb instruction. It also works
- * when instr holds all 32-bits of a wide thumb instruction if stored
- * in the form (first_half<<16)|(second_half)
- */
-#define is_wide_instruction(instr) ((unsigned)(instr) >= 0xe800)
-
#endif /* __ASSEMBLY__ */
#endif
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index 75f51eadb9eb..232e4ba5d314 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -20,16 +20,19 @@
#include <linux/list.h>
+struct pt_regs;
+
struct undef_hook {
struct list_head node;
u32 instr_mask;
u32 instr_val;
- u32 pstate_mask;
- u32 pstate_val;
- int (*fn)(struct pt_regs *regs, unsigned int instr);
+ u64 pstate_mask;
+ u64 pstate_val;
+ int (*fn)(struct pt_regs *regs, u32 instr);
};
void register_undef_hook(struct undef_hook *hook);
+void unregister_undef_hook(struct undef_hook *hook);
static inline int in_exception_text(unsigned long ptr)
{