From 16b021a270c9a9f7c40bfc095f5b49aafb23c118 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:36 +0100 Subject: ARM: pass architecture flag for SMCC also to PBL compilation unit Signed-off-by: Lucas Stach Signed-off-by: Sascha Hauer --- arch/arm/cpu/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 874d723e2c..374b7cda4c 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -23,6 +23,7 @@ endif obj-$(CONFIG_ARM_PSCI) += psci.o obj-pbl-$(CONFIG_ARM_SMCCC) += smccc-call$(S64).o AFLAGS_smccc-call$(S64).o :=-Wa,-march=armv$(if $(S64),8,7)-a +AFLAGS_pbl-smccc-call$(S64).o :=-Wa,-march=armv$(if $(S64),8,7)-a obj-$(CONFIG_ARM_SECURE_MONITOR) += sm.o sm_as.o AFLAGS_sm_as.o :=-Wa,-march=armv7-a -- cgit v1.2.3 From d34e8630185179ebf7ccbdbd15f2dc7d44486476 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:37 +0100 Subject: ARM: import opcode helpers from Linux kernel Those are needed to generate some of the ARM SEC and VIRT opcodes in a portable way. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/include/asm/opcodes-virt.h | 39 ++++++ arch/arm/include/asm/opcodes.h | 231 ++++++++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 arch/arm/include/asm/opcodes-virt.h create mode 100644 arch/arm/include/asm/opcodes.h diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h new file mode 100644 index 0000000000..efcfdf92d9 --- /dev/null +++ b/arch/arm/include/asm/opcodes-virt.h @@ -0,0 +1,39 @@ +/* + * opcodes-virt.h: Opcode definitions for the ARM virtualization extensions + * Copyright (C) 2012 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef __ASM_ARM_OPCODES_VIRT_H +#define __ASM_ARM_OPCODES_VIRT_H + +#include + +#define __HVC(imm16) __inst_arm_thumb32( \ + 0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F), \ + 0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \ +) + +#define __ERET __inst_arm_thumb32( \ + 0xE160006E, \ + 0xF3DE8F00 \ +) + +#define __MSR_ELR_HYP(regnum) __inst_arm_thumb32( \ + 0xE12EF300 | regnum, \ + 0xF3808E30 | (regnum << 16) \ +) + +#endif /* ! __ASM_ARM_OPCODES_VIRT_H */ diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h new file mode 100644 index 0000000000..a78bf5d2c5 --- /dev/null +++ b/arch/arm/include/asm/opcodes.h @@ -0,0 +1,231 @@ +/* + * 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 +extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 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 +#include + +#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 + +#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_BAREBOX +#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 */ -- cgit v1.2.3 From 41292192c01bc17b7c53642d66e434ce24eb3f25 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:38 +0100 Subject: ARM: safely switch from HYP to SVC mode if required This is a port of the Linux safe_svcmode_maskall macro to the Barebox lowlevel init. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/cpu/lowlevel.S | 18 +++++++++++++++--- arch/arm/include/asm/system.h | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/arch/arm/cpu/lowlevel.S b/arch/arm/cpu/lowlevel.S index 7696a198e7..43665981e4 100644 --- a/arch/arm/cpu/lowlevel.S +++ b/arch/arm/cpu/lowlevel.S @@ -1,16 +1,28 @@ #include #include #include +#include .section ".text_bare_init_","ax" ENTRY(arm_cpu_lowlevel_init) /* save lr, since it may be banked away with a processor mode change */ mov r2, lr + /* set the cpu to SVC32 mode, mask irq and fiq */ mrs r12, cpsr - bic r12, r12, #0x1f - orr r12, r12, #0xd3 - msr cpsr, r12 + eor r12, r12, #HYP_MODE + tst r12, #MODE_MASK + bic r12, r12, #MODE_MASK + orr r12, r12, #(PSR_I_BIT | PSR_F_BIT | SVC_MODE) +THUMB( orr r12, r12, #PSR_T_BIT ) + bne 1f + orr r12, r12, #PSR_A_BIT + adr lr, 2f + msr spsr_cxsf, r12 + __MSR_ELR_HYP(14) + __ERET +1: msr cpsr_c, r12 +2: #if __LINUX_ARM_ARCH__ >= 6 /* diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 5cf828ea36..48242ab473 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -60,6 +60,32 @@ #define CR_AFE (1 << 29) /* Access flag enable */ #define CR_TE (1 << 30) /* Thumb exception enable */ +/* + * PSR bits + */ +#define USR_MODE 0x00000010 +#define FIQ_MODE 0x00000011 +#define IRQ_MODE 0x00000012 +#define SVC_MODE 0x00000013 +#define ABT_MODE 0x00000017 +#define HYP_MODE 0x0000001a +#define UND_MODE 0x0000001b +#define SYSTEM_MODE 0x0000001f +#define MODE32_BIT 0x00000010 +#define MODE_MASK 0x0000001f + +#define PSR_T_BIT 0x00000020 +#define PSR_F_BIT 0x00000040 +#define PSR_I_BIT 0x00000080 +#define PSR_A_BIT 0x00000100 +#define PSR_E_BIT 0x00000200 +#define PSR_J_BIT 0x01000000 +#define PSR_Q_BIT 0x08000000 +#define PSR_V_BIT 0x10000000 +#define PSR_C_BIT 0x20000000 +#define PSR_Z_BIT 0x40000000 +#define PSR_N_BIT 0x80000000 + #ifndef __ASSEMBLY__ #if __LINUX_ARM_ARCH__ >= 7 static inline unsigned int current_el(void) -- cgit v1.2.3 From 3c2b8f3ef0832ec6da320e70c44af62401d216d7 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:39 +0100 Subject: ARM: allow secure monitor code to be built without PSCI The hyp mode handling added in the secure monitor code is also useful when Barebox doesn't have PSCI control. Allow to build without PSCI. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/cpu/sm_as.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/cpu/sm_as.S b/arch/arm/cpu/sm_as.S index 09580e75de..0d01e1bf24 100644 --- a/arch/arm/cpu/sm_as.S +++ b/arch/arm/cpu/sm_as.S @@ -129,7 +129,9 @@ secure_monitor: sub sp, sp, #4*4 @ allocate result structure on stack mov r12, sp push {r4-r6, r12} +#ifdef CONFIG_ARM_PSCI bl psci_entry +#endif pop {r4-r6, r12} ldm r12, {r0-r3} add sp, sp, #4*4 @@ -163,6 +165,8 @@ ENTRY(psci_cpu_entry) mcr p15, 0, r0, c1, c0, 1 @ ACTLR bl secure_monitor_stack_setup +#ifdef CONFIG_ARM_PSCI bl psci_cpu_entry_c +#endif ENDPROC(psci_cpu_entry) -- cgit v1.2.3 From 296fa431f9725334f2057039e015f6fc537c0aa0 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:40 +0100 Subject: ARM: add file for HYP mode related setup This adds routines to add hyp mode vectors and switch back to HYP mode from SVC. This is needed in both the PBL and Barebox proper. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/cpu/Makefile | 3 ++ arch/arm/cpu/hyp.S | 116 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/cpu/sm_as.S | 11 ---- arch/arm/include/asm/secure.h | 3 ++ 4 files changed, 122 insertions(+), 11 deletions(-) create mode 100644 arch/arm/cpu/hyp.S diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 374b7cda4c..a35db435c1 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -4,6 +4,9 @@ obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions$(S64).o interrupts$(S64).o obj-$(CONFIG_MMU) += mmu$(S64).o lwl-y += lowlevel$(S64).o obj-pbl-$(CONFIG_MMU) += mmu-early$(S64).o +obj-pbl-$(CONFIG_CPU_32v7) += hyp.o +AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all +AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all obj-y += start.o entry.o diff --git a/arch/arm/cpu/hyp.S b/arch/arm/cpu/hyp.S new file mode 100644 index 0000000000..1314b56eab --- /dev/null +++ b/arch/arm/cpu/hyp.S @@ -0,0 +1,116 @@ +#include +#include +#include +#include + +.arch_extension sec +.arch_extension virt + +__BARE_INIT + +.data + .align 2 +ENTRY(__boot_cpu_mode) + .long 0 +.text + +ENTRY(__hyp_install) + mrs r12, cpsr + and r12, r12, #MODE_MASK + + @ Save the initial CPU state + adr r0, .L__boot_cpu_mode_offset + ldr r1, [r0] + str r12, [r0, r1] + + cmp r12, #HYP_MODE + movne pc, lr @ give up if the CPU is not in HYP mode + + @ Now install the hypervisor stub: + adr r12, __hyp_vectors + mcr p15, 4, r12, c12, c0, 0 @ set hypervisor vector base (HVBAR) + + @ Disable all traps, so we don't get any nasty surprise + mov r12, #0 + mcr p15, 4, r12, c1, c1, 0 @ HCR + mcr p15, 4, r12, c1, c1, 2 @ HCPTR + mcr p15, 4, r12, c1, c1, 3 @ HSTR + +THUMB( orr r12, #(1 << 30) ) @ HSCTLR.TE + mcr p15, 4, r12, c1, c0, 0 @ HSCTLR + + mrc p15, 4, r12, c1, c1, 1 @ HDCR + and r12, #0x1f @ Preserve HPMN + mcr p15, 4, r12, c1, c1, 1 @ HDCR + + @ Make sure NS-SVC is initialised appropriately + mrc p15, 0, r12, c1, c0, 0 @ SCTLR + orr r12, #(1 << 5) @ CP15 barriers enabled + bic r12, #(3 << 7) @ Clear SED/ITD for v8 (RES0 for v7) + bic r12, #(3 << 19) @ WXN and UWXN disabled + mcr p15, 0, r12, c1, c0, 0 @ SCTLR + + mrc p15, 0, r12, c0, c0, 0 @ MIDR + mcr p15, 4, r12, c0, c0, 0 @ VPIDR + + mrc p15, 0, r12, c0, c0, 5 @ MPIDR + mcr p15, 4, r12, c0, c0, 5 @ VMPIDR + bx lr +ENDPROC(__hyp_install) + +ENTRY(armv7_hyp_install) + mov r2, lr + + bl __hyp_install + + /* set the cpu to SVC32 mode, mask irq and fiq */ + mrs r12, cpsr + eor r12, r12, #HYP_MODE + tst r12, #MODE_MASK + bic r12, r12, #MODE_MASK + orr r12, r12, #(PSR_I_BIT | PSR_F_BIT | SVC_MODE) +THUMB( orr r12, r12, #PSR_T_BIT ) + bne 1f + orr r12, r12, #PSR_A_BIT + adr lr, 2f + msr spsr_cxsf, r12 + __MSR_ELR_HYP(14) + __ERET +1: msr cpsr_c, r12 +2: + mov pc, r2 +ENDPROC(armv7_hyp_install) + +ENTRY(armv7_switch_to_hyp) + mov r0, lr + mov r1, sp @ save SVC copy of LR and SP + isb + hvc #0 @ for older asm: .byte 0x70, 0x00, 0x40, 0xe1 + mov sp, r1 + mov lr, r0 @ restore SVC copy of LR and SP + + bx lr +ENDPROC(armv7_switch_to_hyp) + +.align 2 +.L__boot_cpu_mode_offset: + .long __boot_cpu_mode - . + +/* The HYP trap is crafted to match armv7_switch_to_hyp() */ +__hyp_do_trap: + mov lr, r0 + mov sp, r1 + bx lr +ENDPROC(__hyp_do_trap) + +.align 5 +__hyp_vectors: +__hyp_reset: W(b) . +__hyp_und: W(b) . +__hyp_svc: W(b) . +__hyp_pabort: W(b) . +__hyp_dabort: W(b) . +__hyp_trap: W(b) __hyp_do_trap +__hyp_irq: W(b) . +__hyp_fiq: W(b) . +ENDPROC(__hyp_vectors) diff --git a/arch/arm/cpu/sm_as.S b/arch/arm/cpu/sm_as.S index 0d01e1bf24..de6cd0406f 100644 --- a/arch/arm/cpu/sm_as.S +++ b/arch/arm/cpu/sm_as.S @@ -148,17 +148,6 @@ hyp_trap: mov pc, lr @ do no switch modes, but @ return to caller -ENTRY(armv7_switch_to_hyp) - mov r0, lr - mov r1, sp @ save SVC copy of LR and SP - isb - hvc #0 @ for older asm: .byte 0x70, 0x00, 0x40, 0xe1 - mov sp, r1 - mov lr, r0 @ restore SVC copy of LR and SP - - bx lr -ENDPROC(armv7_switch_to_hyp) - ENTRY(psci_cpu_entry) mrc p15, 0, r0, c1, c0, 1 @ ACTLR orr r0, r0, #(1 << 6) @ Set SMP bit diff --git a/arch/arm/include/asm/secure.h b/arch/arm/include/asm/secure.h index a4cb1f6c1c..663d81ea27 100644 --- a/arch/arm/include/asm/secure.h +++ b/arch/arm/include/asm/secure.h @@ -5,9 +5,12 @@ int armv7_secure_monitor_install(void); int __armv7_secure_monitor_install(void); + void armv7_switch_to_hyp(void); +void armv7_hyp_install(void); extern unsigned char secure_monitor_init_vectors[]; +extern int __boot_cpu_mode; enum arm_security_state { ARM_STATE_SECURE, -- cgit v1.2.3 From 245550bce79a6af34e767ebb0ed844a7e7eb582e Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:41 +0100 Subject: ARM: don't try to install secure monitor when entered in HYP mode When Barebox has been entered in HYP mode, the CPU is already switched to the non-secure world and it's not possible for Barebox to install it's own secure monitor. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/cpu/sm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/cpu/sm.c b/arch/arm/cpu/sm.c index cb0bac106b..1246d8e3a4 100644 --- a/arch/arm/cpu/sm.c +++ b/arch/arm/cpu/sm.c @@ -184,6 +184,9 @@ int armv7_secure_monitor_install(void) return -EINVAL; } + if (__boot_cpu_mode == HYP_MODE) + return 0; + mmuon = get_cr() & CR_M; vbar = get_vbar(); -- cgit v1.2.3 From 45ea4b2008613121df466e14c58c7d090f1b44a4 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:42 +0100 Subject: ARM: default to starting kernel in HYP mode when entered in HYP When Barebox has been entered in HYP mode, there is a high chance that the kernel is intended to be started in HYP mode also. Get this default into place. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/cpu/sm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/cpu/sm.c b/arch/arm/cpu/sm.c index 1246d8e3a4..6fad30adab 100644 --- a/arch/arm/cpu/sm.c +++ b/arch/arm/cpu/sm.c @@ -262,6 +262,9 @@ static int sm_init(void) bootm_secure_state_names, ARRAY_SIZE(bootm_secure_state_names)); + if (__boot_cpu_mode == HYP_MODE) + bootm_secure_state = ARM_STATE_HYP; + return 0; } device_initcall(sm_init); \ No newline at end of file -- cgit v1.2.3 From 6189e2546414830b2700eab7b09f4a6848d88850 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:43 +0100 Subject: ARM: install HYP vectors at PBL and Barebox entry If the CPU was already in HYP mode when entering the PBL, install a simple trap handler to allow to get back from SVC to HYP before switching to HYP mode. As the vectors are part of the currently running binary, we need to do the same setup when starting the real Barebox binary, as the PBL setup vectors might get overwritten. To do this we trap into HYP mode just before jumping to Barebox and then re-do the vector setup and SVC switch as the first thing in Barebox proper. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/cpu/lowlevel.S | 5 +++++ arch/arm/cpu/start-pbl.c | 4 ++++ arch/arm/cpu/start.c | 5 +++++ arch/arm/cpu/uncompress.c | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/arch/arm/cpu/lowlevel.S b/arch/arm/cpu/lowlevel.S index 43665981e4..3b52644e43 100644 --- a/arch/arm/cpu/lowlevel.S +++ b/arch/arm/cpu/lowlevel.S @@ -8,6 +8,11 @@ ENTRY(arm_cpu_lowlevel_init) /* save lr, since it may be banked away with a processor mode change */ mov r2, lr +#ifdef CONFIG_CPU_32v7 + /* careful: the hyp install corrupts r0 and r1 */ + bl __hyp_install +#endif + /* set the cpu to SVC32 mode, mask irq and fiq */ mrs r12, cpsr eor r12, r12, #HYP_MODE diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c index 16159d7f9d..48a8086456 100644 --- a/arch/arm/cpu/start-pbl.c +++ b/arch/arm/cpu/start-pbl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -98,5 +99,8 @@ __noreturn void barebox_single_pbl_start(unsigned long membase, else barebox = (void *)barebox_base; + if (IS_ENABLED(CONFIG_CPU_V7) && __boot_cpu_mode == HYP_MODE) + armv7_switch_to_hyp(); + barebox(membase, memsize, boarddata); } diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index 64bd942ad7..a79d64eaa6 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -147,6 +148,10 @@ __noreturn void barebox_non_pbl_start(unsigned long membase, unsigned long barebox_base = arm_mem_barebox_image(membase, endmem, barebox_size); + + if (IS_ENABLED(CONFIG_CPU_V7)) + armv7_hyp_install(); + if (IS_ENABLED(CONFIG_RELOCATABLE)) relocate_to_adr(barebox_base); diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c index 43b49b4212..048bca0c95 100644 --- a/arch/arm/cpu/uncompress.c +++ b/arch/arm/cpu/uncompress.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -105,5 +106,8 @@ void __noreturn barebox_multi_pbl_start(unsigned long membase, pr_debug("jumping to uncompressed image at 0x%p\n", barebox); + if (IS_ENABLED(CONFIG_CPU_V7) && __boot_cpu_mode == HYP_MODE) + armv7_switch_to_hyp(); + barebox(membase, memsize, boarddata); } -- cgit v1.2.3 From 5db9fdc66f3d60792fc537fad503f8c89a5fd61f Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Thu, 1 Nov 2018 10:18:44 +0100 Subject: ARM: rpi: add revision IDs for Pi 3 Model B and Pi Zero Signed-off-by: Enrico Joerns Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/boards/raspberry-pi/rpi-common.c | 2 ++ arch/arm/mach-bcm283x/include/mach/mbox.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/boards/raspberry-pi/rpi-common.c b/arch/arm/boards/raspberry-pi/rpi-common.c index 6e375bc984..3baed65255 100644 --- a/arch/arm/boards/raspberry-pi/rpi-common.c +++ b/arch/arm/boards/raspberry-pi/rpi-common.c @@ -174,6 +174,8 @@ const struct rpi_model rpi_models_old_scheme[] = { const struct rpi_model rpi_models_new_scheme[] = { RPI_MODEL(0, "Unknown model", NULL), RPI_MODEL(BCM2836_BOARD_REV_2_B, "2 Model B", rpi_b_plus_init), + RPI_MODEL(BCM2837_BOARD_REV_3_B, "3 Model B", rpi_b_plus_init), + RPI_MODEL(BCM2835_BOARD_REV_ZERO, "Zero", rpi_b_plus_init), }; static int rpi_board_rev = 0; diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h index 2b5aea88ee..0d1ac074e3 100644 --- a/arch/arm/mach-bcm283x/include/mach/mbox.h +++ b/arch/arm/mach-bcm283x/include/mach/mbox.h @@ -129,6 +129,10 @@ struct bcm2835_mbox_tag_hdr { /* RPi 2 */ #define BCM2836_BOARD_REV_2_B 0x4 +/* RPi 3 */ +#define BCM2837_BOARD_REV_3_B 0x8 +/* Zero */ +#define BCM2835_BOARD_REV_ZERO 0x9 /* * 0x2..0xf from: -- cgit v1.2.3 From 94f6a7149a7835c3fd28a447954f840457bc4f13 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:45 +0100 Subject: ARM: rpi: add raspberry pi 3 support This adds basic support at the same feature level as the other supported raspberry pi boards. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/boards/raspberry-pi/lowlevel.c | 14 ++++++++++++-- arch/arm/configs/rpi_defconfig | 2 ++ arch/arm/dts/Makefile | 1 + arch/arm/dts/bcm2837-rpi-3.dts | 16 ++++++++++++++++ arch/arm/mach-bcm283x/Kconfig | 6 ++++++ arch/arm/mach-bcm283x/core.c | 1 + images/Makefile.bcm283x | 4 ++++ 7 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 arch/arm/dts/bcm2837-rpi-3.dts diff --git a/arch/arm/boards/raspberry-pi/lowlevel.c b/arch/arm/boards/raspberry-pi/lowlevel.c index cbc6caa4b9..34c9350920 100644 --- a/arch/arm/boards/raspberry-pi/lowlevel.c +++ b/arch/arm/boards/raspberry-pi/lowlevel.c @@ -1,7 +1,7 @@ +#include +#include #include #include -#include -#include #include extern char __dtb_bcm2835_rpi_start[]; @@ -23,3 +23,13 @@ ENTRY_FUNCTION(start_raspberry_pi2, r0, r1, r2) barebox_arm_entry(BCM2835_SDRAM_BASE, SZ_512M, fdt); } + +extern char __dtb_bcm2837_rpi_3_start[]; +ENTRY_FUNCTION(start_raspberry_pi3, r0, r1, r2) +{ + void *fdt = __dtb_bcm2837_rpi_3_start + get_runtime_offset(); + + arm_cpu_lowlevel_init(); + + barebox_arm_entry(BCM2835_SDRAM_BASE, SZ_512M, fdt); +} diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig index f3aef42904..cd88b4ac75 100644 --- a/arch/arm/configs/rpi_defconfig +++ b/arch/arm/configs/rpi_defconfig @@ -1,9 +1,11 @@ CONFIG_ARCH_BCM283X=y CONFIG_MACH_RPI=y CONFIG_MACH_RPI2=y +CONFIG_MACH_RPI3=y CONFIG_AEABI=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_ARM_UNWIND=y +CONFIG_IMAGE_COMPRESSION_NONE=y CONFIG_MMU=y CONFIG_MALLOC_TLSF=y CONFIG_KALLSYMS=y diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 1caeca35b4..4e063902c6 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -71,6 +71,7 @@ pbl-dtb-$(CONFIG_MACH_PHYTEC_SOM_RK3288) += rk3288-phycore-som.dtb.o pbl-dtb-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o pbl-dtb-$(CONFIG_MACH_RPI) += bcm2835-rpi.dtb.o pbl-dtb-$(CONFIG_MACH_RPI2) += bcm2836-rpi-2.dtb.o +pbl-dtb-$(CONFIG_MACH_RPI3) += bcm2837-rpi-3.dtb.o pbl-dtb-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o pbl-dtb-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o pbl-dtb-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += imx6sx-sdb.dtb.o diff --git a/arch/arm/dts/bcm2837-rpi-3.dts b/arch/arm/dts/bcm2837-rpi-3.dts new file mode 100644 index 0000000000..d6ffc36912 --- /dev/null +++ b/arch/arm/dts/bcm2837-rpi-3.dts @@ -0,0 +1,16 @@ +#include + +/ { + chosen { + stdout-path = &uart0; + }; + + memory { + reg = <0x0 0x0>; + }; +}; + +&uart0 { + status = "okay"; + /delete-node/ bluetooth; +}; diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig index 1457f114cc..af2f88c47a 100644 --- a/arch/arm/mach-bcm283x/Kconfig +++ b/arch/arm/mach-bcm283x/Kconfig @@ -19,6 +19,12 @@ config MACH_RPI2 select CPU_V7 select MACH_RPI_COMMON +config MACH_RPI3 + bool "RaspberryPi 3 (BCM2837/CORTEX-A53)" + select CPU_V7 + select MACH_RPI_COMMON + select ARM_SECURE_MONITOR + endmenu config MACH_RPI_DEBUG_UART_BASE diff --git a/arch/arm/mach-bcm283x/core.c b/arch/arm/mach-bcm283x/core.c index fddcb0d1a1..26f0996b1c 100644 --- a/arch/arm/mach-bcm283x/core.c +++ b/arch/arm/mach-bcm283x/core.c @@ -41,6 +41,7 @@ static int bcm2835_clk_init(void) clk = clk_fixed("uart0-pl0110", 3 * 1000 * 1000); clk_register_clkdev(clk, NULL, "uart0-pl0110"); clk_register_clkdev(clk, NULL, "20201000.serial"); + clk_register_clkdev(clk, NULL, "3f201000.serial"); clk = clk_fixed("bcm2835-cs", 1 * 1000 * 1000); clk_register_clkdev(clk, NULL, "bcm2835-cs"); diff --git a/images/Makefile.bcm283x b/images/Makefile.bcm283x index d59ef043f0..d14e648926 100644 --- a/images/Makefile.bcm283x +++ b/images/Makefile.bcm283x @@ -9,3 +9,7 @@ image-$(CONFIG_MACH_RPI) += barebox-raspberry-pi-1.img pblx-$(CONFIG_MACH_RPI2) += start_raspberry_pi2 FILE_barebox-raspberry-pi-2.img = start_raspberry_pi2.pblx image-$(CONFIG_MACH_RPI2) += barebox-raspberry-pi-2.img + +pblx-$(CONFIG_MACH_RPI3) += start_raspberry_pi3 +FILE_barebox-raspberry-pi-3.img = start_raspberry_pi3.pblx +image-$(CONFIG_MACH_RPI3) += barebox-raspberry-pi-3.img \ No newline at end of file -- cgit v1.2.3 From c60aa1f01393807660fbe7b67d49b48c3c37eae2 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 1 Nov 2018 10:18:46 +0100 Subject: ARM: rpi: autosize malloc area Autosize the malloc area according to the available RAM size. Signed-off-by: Lucas Stach Tested-by: Roland Hieber Signed-off-by: Sascha Hauer --- arch/arm/configs/rpi_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig index cd88b4ac75..2bb6158493 100644 --- a/arch/arm/configs/rpi_defconfig +++ b/arch/arm/configs/rpi_defconfig @@ -7,6 +7,7 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_ARM_UNWIND=y CONFIG_IMAGE_COMPRESSION_NONE=y CONFIG_MMU=y +CONFIG_MALLOC_SIZE=0x0 CONFIG_MALLOC_TLSF=y CONFIG_KALLSYMS=y CONFIG_PROMPT="R-Pi> " -- cgit v1.2.3