diff options
author | Amit Pundir <amit.pundir@linaro.org> | 2015-02-20 12:17:40 +0530 |
---|---|---|
committer | Amit Pundir <amit.pundir@linaro.org> | 2015-02-20 13:21:54 +0530 |
commit | 7ffdd3fae2e1917268ed35b76ec905ed5b166aa6 (patch) | |
tree | 5b45c802ffc3ce5d97b8f990bb2b69996bdac478 /arch/arm64/include | |
parent | 37d37744341e65b39bf6e8141ba3b46c8a0772f0 (diff) | |
parent | eec2486674b53d8ca576677cae60bc3f380d33c1 (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.h | 59 | ||||
-rw-r--r-- | arch/arm64/include/asm/cpufeature.h | 3 | ||||
-rw-r--r-- | arch/arm64/include/asm/cputype.h | 50 | ||||
-rw-r--r-- | arch/arm64/include/asm/insn.h | 10 | ||||
-rw-r--r-- | arch/arm64/include/asm/opcodes.h | 232 | ||||
-rw-r--r-- | arch/arm64/include/asm/ptrace.h | 15 | ||||
-rw-r--r-- | arch/arm64/include/asm/traps.h | 9 |
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) { |