[U-Boot] [PATCH v5 0/2] armv8: Support loading 32-bit OS in AArch32 execution state

This series is to support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel. The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Spin-table method is used for secondary cores to load 32-bit OS. The architecture information will be got through checking FIT image and saved in the os_arch element of spin-table, then the secondary cores will check os_arch and jump to 32-bit OS or 64-bit OS automatically.
--------------------------------------- Changes in v5: - Modified armv8_switch_to_el2(). It will always jump to ep when switching to AArch64 or AArch32 modes. - Make secondary_switch_to_el2() always jump to ep when switching to AArch64 or AArch32 modes.
Changes in v4: - Correct config ARM64_SUPPORT_AARCH32. - Omit arch and ftaddr arguments. - Rename "xreg5" to "tmp". - Use xxx_RES1 to combine all RES1 fields in xxx register. - Use an immediate cmp directly. - Use #ifdef for CONFIG_ARM64_SUPPORT_AARCH32.
Changes in v3: - Comments the functions and the arguments. - Rename the real parameters. - Use the macros instead of the magic values. - Remove the redundant codes. - Clean up all of the mess in boot_jump_linux(). - Add CONFIG_ARM64_SUPPORT_AARCH32 to detect for some ARM64 system doesn't support AArch32 state. - Adjust the arguments for armv8_switch_to_el2_m and armv8_switch_to_el1_m.
Changes in v2: - armv8_switch_to_el2_aarch32() is removed. armv8_switch_to_el2_m is used to switch to AArch64 EL2 or AArch32 Hyp. - armv8_switch_to_el1_aarch32() is removed. armv8_switch_to_el1_m is used to switch to AArch64 EL1 or AArch32 SVC. - Support to call armv8_switch_to_el2_m and armv8_switch_to_el1_m.
---------------------------------------------------------------- Alison Wang (2): armv8: Support loading 32-bit OS in AArch32 execution state armv8: fsl-layerscape: SMP support for loading 32-bit OS
arch/arm/Kconfig | 6 ++++++ arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 23 +++++++++++++++----- arch/arm/cpu/armv8/fsl-layerscape/mp.c | 10 +++++++++ arch/arm/cpu/armv8/start.S | 1 + arch/arm/cpu/armv8/transition.S | 4 ++-- arch/arm/include/asm/arch-fsl-layerscape/mp.h | 6 ++++++ arch/arm/include/asm/macro.h | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- arch/arm/include/asm/system.h | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- arch/arm/lib/bootm.c | 19 ++++++++++++++-- common/image-fit.c | 19 +++++++++++++++- 10 files changed, 245 insertions(+), 27 deletions(-)

To support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel.
The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Signed-off-by: Ebony Zhu ebony.zhu@nxp.com Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com --- Changes in v5: - Modified armv8_switch_to_el2(). It will always jump to ep when switching to AArch64 or AArch32 modes.
Changes in v4: - Correct config ARM64_SUPPORT_AARCH32. - Omit arch and ftaddr arguments. - Rename "xreg5" to "tmp". - Use xxx_RES1 to combine all RES1 fields in xxx register. - Use an immediate cmp directly. - Use #ifdef for CONFIG_ARM64_SUPPORT_AARCH32.
Changes in v3: - Comments the functions and the arguments. - Rename the real parameters. - Use the macros instead of the magic values. - Remove the redundant codes. - Clean up all of the mess in boot_jump_linux(). - Add CONFIG_ARM64_SUPPORT_AARCH32 to detect for some ARM64 system doesn't support AArch32 state.
Changes in v2: - armv8_switch_to_el2_aarch32() is removed. armv8_switch_to_el2_m is used to switch to AArch64 EL2 or AArch32 Hyp. - armv8_switch_to_el1_aarch32() is removed. armv8_switch_to_el1_m is used to switch to AArch64 EL1 or AArch32 SVC.
arch/arm/Kconfig | 6 +++ arch/arm/cpu/armv8/start.S | 2 + arch/arm/cpu/armv8/transition.S | 4 +- arch/arm/include/asm/macro.h | 80 ++++++++++++++++++++++++------- arch/arm/include/asm/system.h | 104 +++++++++++++++++++++++++++++++++++++++- arch/arm/lib/bootm.c | 13 ++++- common/image-fit.c | 19 +++++++- 7 files changed, 206 insertions(+), 22 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3237a74..1b30447 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -99,6 +99,12 @@ config ENABLE_ARM_SOC_BOOT0_HOOK ARM_SOC_BOOT0_HOOK which contains the required assembler preprocessor code.
+config ARM64_SUPPORT_AARCH32 + bool "ARM64 system support AArch32 execution state" + default y if ARM64 && !TARGET_THUNDERX_88XX + help + This ARM64 system supports AArch32 execution state. + choice prompt "Target select" default TARGET_HIKEY diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index ab434a6..a0c55d7 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -244,6 +244,8 @@ WEAK(lowlevel_init) /* * All slaves will enter EL2. */ + mov x3, lr + ldr x4, =ES_TO_AARCH64 bl armv8_switch_to_el2
#endif /* CONFIG_ARMV8_MULTIENTRY */ diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S index 209d5c8..62d54b3 100644 --- a/arch/arm/cpu/armv8/transition.S +++ b/arch/arm/cpu/armv8/transition.S @@ -11,7 +11,7 @@ #include <asm/macro.h>
ENTRY(armv8_switch_to_el2) - switch_el x0, 1f, 0f, 0f + switch_el x5, 1f, 0f, 0f 0: ret -1: armv8_switch_to_el2_m x0 +1: armv8_switch_to_el2_m x3, x4, x5 ENDPROC(armv8_switch_to_el2) diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index c1b3452..5108900 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -8,6 +8,9 @@
#ifndef __ASM_ARM_MACRO_H__ #define __ASM_ARM_MACRO_H__ + +#include <asm/system.h> + #ifdef __ASSEMBLY__
/* @@ -135,13 +138,21 @@ lr .req x30 #endif .endm
-.macro armv8_switch_to_el2_m, xreg1 - /* 64bit EL2 | HCE | SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1 */ - mov \xreg1, #0x5b1 - msr scr_el3, \xreg1 +/* + * Switch from EL3 to EL2 for ARMv8 + * @ep: kernel entry point + * @flag: The execution state flag for lower exception + * level, ES_TO_AARCH64 or ES_TO_AARCH32 + * @tmp: temporary register + * + * For loading 32-bit OS, x1 is machine nr and x2 is ftaddr. + * For loading 64-bit OS, x0 is physical address to the FDT blob. + * They will be passed to the guest. + */ +.macro armv8_switch_to_el2_m, ep, flag, tmp msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */ - mov \xreg1, #0x33ff - msr cptr_el2, \xreg1 /* Disable coprocessor traps to EL2 */ + mov \tmp, #CPTR_EL2_RES1 + msr cptr_el2, \tmp /* Disable coprocessor traps to EL2 */
/* Initialize Generic Timers */ msr cntvoff_el2, xzr @@ -152,18 +163,55 @@ lr .req x30 * and RES0 bits (31,30,27,26,24,21,20,17,15-13,10-6) + * EE,WXN,I,SA,C,A,M to 0 */ - mov \xreg1, #0x0830 - movk \xreg1, #0x30C5, lsl #16 - msr sctlr_el2, \xreg1 + ldr \tmp, =(SCTLR_EL2_RES1 | SCTLR_EL2_EE_LE |\ + SCTLR_EL2_WXN_DIS | SCTLR_EL2_ICACHE_DIS |\ + SCTLR_EL2_SA_DIS | SCTLR_EL2_DCACHE_DIS |\ + SCTLR_EL2_ALIGN_DIS | SCTLR_EL2_MMU_DIS) + msr sctlr_el2, \tmp + + mov \tmp, sp + msr sp_el2, \tmp /* Migrate SP */ + mrs \tmp, vbar_el3 + msr vbar_el2, \tmp /* Migrate VBAR */ + + /* Check switch to AArch64 EL2 or AArch32 Hypervisor mode */ + cmp \flag, #ES_TO_AARCH32 + b.eq 1f + + /* + * The next lower exception level is AArch64, 64bit EL2 | HCE | + * SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1. + */ + ldr \tmp, =(SCR_EL3_RW_AARCH64 | SCR_EL3_HCE_EN |\ + SCR_EL3_SMD_DIS | SCR_EL3_RES1 |\ + SCR_EL3_NS_EN) + msr scr_el3, \tmp
/* Return to the EL2_SP2 mode from EL3 */ - mov \xreg1, sp - msr sp_el2, \xreg1 /* Migrate SP */ - mrs \xreg1, vbar_el3 - msr vbar_el2, \xreg1 /* Migrate VBAR */ - mov \xreg1, #0x3c9 - msr spsr_el3, \xreg1 /* EL2_SP2 | D | A | I | F */ - msr elr_el3, lr + ldr \tmp, =(SPSR_EL_DEBUG_MASK | SPSR_EL_SERR_MASK |\ + SPSR_EL_IRQ_MASK | SPSR_EL_FIQ_MASK |\ + SPSR_EL_M_AARCH64 | SPSR_EL_M_EL2H) + msr spsr_el3, \tmp + msr elr_el3, \ep + eret + +1: + /* + * The next lower exception level is AArch32, 32bit EL2 | HCE | + * SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1. + */ + ldr \tmp, =(SCR_EL3_RW_AARCH32 | SCR_EL3_HCE_EN |\ + SCR_EL3_SMD_DIS | SCR_EL3_RES1 |\ + SCR_EL3_NS_EN) + msr scr_el3, \tmp + + /* Return to AArch32 Hypervisor mode */ + ldr \tmp, =(SPSR_EL_END_LE | SPSR_EL_ASYN_MASK |\ + SPSR_EL_IRQ_MASK | SPSR_EL_FIQ_MASK |\ + SPSR_EL_T_A32 | SPSR_EL_M_AARCH32 |\ + SPSR_EL_M_HYP) + msr spsr_el3, \tmp + msr elr_el3, \ep eret .endm
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 3a22661..edb842b 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -17,6 +17,95 @@ #define CR_WXN (1 << 19) /* Write Permision Imply XN */ #define CR_EE (1 << 25) /* Exception (Big) Endian */
+#define ES_TO_AARCH64 1 +#define ES_TO_AARCH32 0 + +/* + * SCR_EL3 bits definitions + */ +#define SCR_EL3_RW_AARCH64 (1 << 10) /* Next lower level is AArch64 */ +#define SCR_EL3_RW_AARCH32 (0 << 10) /* Lower lowers level are AArch32 */ +#define SCR_EL3_HCE_EN (1 << 8) /* Hypervisor Call enable */ +#define SCR_EL3_SMD_DIS (1 << 7) /* Secure Monitor Call disable */ +#define SCR_EL3_RES1 (3 << 4) /* Reserved, RES1 */ +#define SCR_EL3_NS_EN (1 << 0) /* EL0 and EL1 in Non-scure state */ + +/* + * SPSR_EL3/SPSR_EL2 bits definitions + */ +#define SPSR_EL_END_LE (0 << 9) /* Exception Little-endian */ +#define SPSR_EL_DEBUG_MASK (1 << 9) /* Debug exception masked */ +#define SPSR_EL_ASYN_MASK (1 << 8) /* Asynchronous data abort masked */ +#define SPSR_EL_SERR_MASK (1 << 8) /* System Error exception masked */ +#define SPSR_EL_IRQ_MASK (1 << 7) /* IRQ exception masked */ +#define SPSR_EL_FIQ_MASK (1 << 6) /* FIQ exception masked */ +#define SPSR_EL_T_A32 (0 << 5) /* AArch32 instruction set A32 */ +#define SPSR_EL_M_AARCH64 (0 << 4) /* Exception taken from AArch64 */ +#define SPSR_EL_M_AARCH32 (1 << 4) /* Exception taken from AArch32 */ +#define SPSR_EL_M_SVC (0x3) /* Exception taken from SVC mode */ +#define SPSR_EL_M_HYP (0xa) /* Exception taken from HYP mode */ +#define SPSR_EL_M_EL1H (5) /* Exception taken from EL1h mode */ +#define SPSR_EL_M_EL2H (9) /* Exception taken from EL2h mode */ + +/* + * CPTR_EL2 bits definitions + */ +#define CPTR_EL2_RES1 (3 << 12 | 0x3ff) /* Reserved, RES1 */ + +/* + * SCTLR_EL2 bits definitions + */ +#define SCTLR_EL2_RES1 (3 << 28 | 3 << 22 | 1 << 18 | 1 << 16 |\ + 1 << 11 | 3 << 4) /* Reserved, RES1 */ +#define SCTLR_EL2_EE_LE (0 << 25) /* Exception Little-endian */ +#define SCTLR_EL2_WXN_DIS (0 << 19) /* Write permission is not XN */ +#define SCTLR_EL2_ICACHE_DIS (0 << 12) /* Instruction cache disabled */ +#define SCTLR_EL2_SA_DIS (0 << 3) /* Stack Alignment Check disabled */ +#define SCTLR_EL2_DCACHE_DIS (0 << 2) /* Data cache disabled */ +#define SCTLR_EL2_ALIGN_DIS (0 << 1) /* Alignment check disabled */ +#define SCTLR_EL2_MMU_DIS (0) /* MMU disabled */ + +/* + * CNTHCTL_EL2 bits definitions + */ +#define CNTHCTL_EL2_EL1PCEN_EN (1 << 1) /* Physical timer regs accessible */ +#define CNTHCTL_EL2_EL1PCTEN_EN (1 << 0) /* Physical counter accessible */ + +/* + * HCR_EL2 bits definitions + */ +#define HCR_EL2_RW_AARCH64 (1 << 31) /* EL1 is AArch64 */ +#define HCR_EL2_RW_AARCH32 (0 << 31) /* Lower levels are AArch32 */ +#define HCR_EL2_HCD_DIS (1 << 29) /* Hypervisor Call disabled */ + +/* + * CPACR_EL1 bits definitions + */ +#define CPACR_EL1_FPEN_EN (3 << 20) /* SIMD and FP instruction enabled */ + +/* + * SCTLR_EL1 bits definitions + */ +#define SCTLR_EL1_RES1 (3 << 28 | 3 << 22 | 1 << 20 |\ + 1 << 11) /* Reserved, RES1 */ +#define SCTLR_EL1_UCI_DIS (0 << 26) /* Cache instruction disabled */ +#define SCTLR_EL1_EE_LE (0 << 25) /* Exception Little-endian */ +#define SCTLR_EL1_WXN_DIS (0 << 19) /* Write permission is not XN */ +#define SCTLR_EL1_NTWE_DIS (0 << 18) /* WFE instruction disabled */ +#define SCTLR_EL1_NTWI_DIS (0 << 16) /* WFI instruction disabled */ +#define SCTLR_EL1_UCT_DIS (0 << 15) /* CTR_EL0 access disabled */ +#define SCTLR_EL1_DZE_DIS (0 << 14) /* DC ZVA instruction disabled */ +#define SCTLR_EL1_ICACHE_DIS (0 << 12) /* Instruction cache disabled */ +#define SCTLR_EL1_UMA_DIS (0 << 9) /* User Mask Access disabled */ +#define SCTLR_EL1_SED_EN (0 << 8) /* SETEND instruction enabled */ +#define SCTLR_EL1_ITD_EN (0 << 7) /* IT instruction enabled */ +#define SCTLR_EL1_CP15BEN_DIS (0 << 5) /* CP15 barrier operation disabled */ +#define SCTLR_EL1_SA0_DIS (0 << 4) /* Stack Alignment EL0 disabled */ +#define SCTLR_EL1_SA_DIS (0 << 3) /* Stack Alignment EL1 disabled */ +#define SCTLR_EL1_DCACHE_DIS (0 << 2) /* Data cache disabled */ +#define SCTLR_EL1_ALIGN_DIS (0 << 1) /* Alignment check disabled */ +#define SCTLR_EL1_MMU_DIS (0) /* MMU disabled */ + #ifndef __ASSEMBLY__
u64 get_page_table_size(void); @@ -100,7 +189,20 @@ void __asm_invalidate_icache_all(void); int __asm_flush_l3_cache(void); void __asm_switch_ttbr(u64 new_ttbr);
-void armv8_switch_to_el2(void); +/* + * Switch from EL3 to EL2 for ARMv8 + * + * @args: For loading 64-bit OS, fdt address. + * For loading 32-bit OS, zero. + * @mach_nr: For loading 64-bit OS, zero. + * For loading 32-bit OS, machine nr + * @fdt_addr: For loading 64-bit OS, zero. + * For loading 32-bit OS, fdt address. + * @entry_point: kernel entry point + * @es_flag: execution state flag, ES_TO_AARCH64 or ES_TO_AARCH32 + */ +void armv8_switch_to_el2(u64 args, u64 mach_nr, u64 fdt_addr, + u64 entry_point, u64 es_flag); void gic_init(void); void gic_send_sgi(unsigned long sgino); void wait_for_wakeup(void); diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index e3c9832..59adab8 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -193,7 +193,6 @@ static void do_nonsec_virt_switch(void) { smp_kick_all_cpus(); dcache_disable(); /* flush cache before swtiching to EL2 */ - armv8_switch_to_el2(); } #endif
@@ -284,7 +283,17 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
if (!fake) { do_nonsec_virt_switch(); - kernel_entry(images->ft_addr, NULL, NULL, NULL); + + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && + (images->os.arch == IH_ARCH_ARM)) + armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number, + (u64)images->ft_addr, + (u64)images->ep, + ES_TO_AARCH32); + else + armv8_switch_to_el2((u64)images->ft_addr, 0, 0, + images->ep, + ES_TO_AARCH64); } #else unsigned long machid = gd->bd->bi_arch_number; diff --git a/common/image-fit.c b/common/image-fit.c index 6f920da..c28e8fa 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -26,6 +26,7 @@ DECLARE_GLOBAL_DATA_PTR; #include <u-boot/md5.h> #include <u-boot/sha1.h> #include <u-boot/sha256.h> +#include <generated/autoconf.h>
/*****************************************************************************/ /* New uImage format routines */ @@ -1160,11 +1161,18 @@ int fit_image_check_os(const void *fit, int noffset, uint8_t os) int fit_image_check_arch(const void *fit, int noffset, uint8_t arch) { uint8_t image_arch; + int aarch32_support = 0; + +#ifdef CONFIG_ARM64_SUPPORT_AARCH32 + aarch32_support = 1; +#endif
if (fit_image_get_arch(fit, noffset, &image_arch)) return 0; return (arch == image_arch) || - (arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64); + (arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64) || + (arch == IH_ARCH_ARM64 && image_arch == IH_ARCH_ARM && + aarch32_support); }
/** @@ -1593,6 +1601,9 @@ int fit_image_load(bootm_headers_t *images, ulong addr, int type_ok, os_ok; ulong load, data, len; uint8_t os; +#ifndef USE_HOSTCC + uint8_t os_arch; +#endif const char *prop_name; int ret;
@@ -1676,6 +1687,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr, return -ENOEXEC; } #endif + +#ifndef USE_HOSTCC + fit_image_get_arch(fit, noffset, &os_arch); + images->os.arch = os_arch; +#endif + if (image_type == IH_TYPE_FLATDT && !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { puts("FDT image is compressed");

On 7 July 2016 at 07:30, Alison Wang b18965@freescale.com wrote:
To support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel.
The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Signed-off-by: Ebony Zhu ebony.zhu@nxp.com Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com
Unfortunately, this patch fails to boot for me.
On FVP Foundation models, I see this error before the model hangs:
[snip] Starting kernel ...
resetting ... [snip]
And I see the same output on AEMv8 Base models and Juno boards, only they reset continuously rather than hang.
I think the problem is that I see this from ARM Trusted Firmware on boot:
INFO: BL31: Preparing for EL3 exit to normal world
Looking at the patch, it appears to be changing everything to boot in EL2.
The title of the patch is "armv8: Support loading 32-bit OS in AArch32 execution state", which implies it only makes changes to AArch32 code execution paths, however, it is clearly changing AArch64 boot too, so I'm not happy with the title or description of the patch either.
Changes in v5:
- Modified armv8_switch_to_el2(). It will always jump to ep when switching to AArch64 or AArch32 modes.
Changes in v4:
- Correct config ARM64_SUPPORT_AARCH32.
- Omit arch and ftaddr arguments.
- Rename "xreg5" to "tmp".
- Use xxx_RES1 to combine all RES1 fields in xxx register.
- Use an immediate cmp directly.
- Use #ifdef for CONFIG_ARM64_SUPPORT_AARCH32.
Changes in v3:
- Comments the functions and the arguments.
- Rename the real parameters.
- Use the macros instead of the magic values.
- Remove the redundant codes.
- Clean up all of the mess in boot_jump_linux().
- Add CONFIG_ARM64_SUPPORT_AARCH32 to detect for some ARM64 system doesn't support AArch32 state.
Changes in v2:
- armv8_switch_to_el2_aarch32() is removed. armv8_switch_to_el2_m is used to switch to AArch64 EL2 or AArch32 Hyp.
- armv8_switch_to_el1_aarch32() is removed. armv8_switch_to_el1_m is used to switch to AArch64 EL1 or AArch32 SVC.
arch/arm/Kconfig | 6 +++ arch/arm/cpu/armv8/start.S | 2 + arch/arm/cpu/armv8/transition.S | 4 +- arch/arm/include/asm/macro.h | 80 ++++++++++++++++++++++++------- arch/arm/include/asm/system.h | 104 +++++++++++++++++++++++++++++++++++++++- arch/arm/lib/bootm.c | 13 ++++- common/image-fit.c | 19 +++++++- 7 files changed, 206 insertions(+), 22 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3237a74..1b30447 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -99,6 +99,12 @@ config ENABLE_ARM_SOC_BOOT0_HOOK ARM_SOC_BOOT0_HOOK which contains the required assembler preprocessor code.
+config ARM64_SUPPORT_AARCH32
bool "ARM64 system support AArch32 execution state"
default y if ARM64 && !TARGET_THUNDERX_88XX
help
This ARM64 system supports AArch32 execution state.
choice prompt "Target select" default TARGET_HIKEY diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index ab434a6..a0c55d7 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -244,6 +244,8 @@ WEAK(lowlevel_init) /* * All slaves will enter EL2. */
mov x3, lr
ldr x4, =ES_TO_AARCH64 bl armv8_switch_to_el2
#endif /* CONFIG_ARMV8_MULTIENTRY */ diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S index 209d5c8..62d54b3 100644 --- a/arch/arm/cpu/armv8/transition.S +++ b/arch/arm/cpu/armv8/transition.S @@ -11,7 +11,7 @@ #include <asm/macro.h>
ENTRY(armv8_switch_to_el2)
switch_el x0, 1f, 0f, 0f
switch_el x5, 1f, 0f, 0f
0: ret -1: armv8_switch_to_el2_m x0 +1: armv8_switch_to_el2_m x3, x4, x5 ENDPROC(armv8_switch_to_el2) diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index c1b3452..5108900 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -8,6 +8,9 @@
#ifndef __ASM_ARM_MACRO_H__ #define __ASM_ARM_MACRO_H__
+#include <asm/system.h>
#ifdef __ASSEMBLY__
/* @@ -135,13 +138,21 @@ lr .req x30 #endif .endm
-.macro armv8_switch_to_el2_m, xreg1
/* 64bit EL2 | HCE | SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1 */
mov \xreg1, #0x5b1
msr scr_el3, \xreg1
+/*
- Switch from EL3 to EL2 for ARMv8
- @ep: kernel entry point
- @flag: The execution state flag for lower exception
level, ES_TO_AARCH64 or ES_TO_AARCH32
- @tmp: temporary register
- For loading 32-bit OS, x1 is machine nr and x2 is ftaddr.
- For loading 64-bit OS, x0 is physical address to the FDT blob.
- They will be passed to the guest.
- */
+.macro armv8_switch_to_el2_m, ep, flag, tmp msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */
mov \xreg1, #0x33ff
msr cptr_el2, \xreg1 /* Disable coprocessor traps to EL2 */
mov \tmp, #CPTR_EL2_RES1
msr cptr_el2, \tmp /* Disable coprocessor traps to EL2 */ /* Initialize Generic Timers */ msr cntvoff_el2, xzr
@@ -152,18 +163,55 @@ lr .req x30 * and RES0 bits (31,30,27,26,24,21,20,17,15-13,10-6) + * EE,WXN,I,SA,C,A,M to 0 */
mov \xreg1, #0x0830
movk \xreg1, #0x30C5, lsl #16
msr sctlr_el2, \xreg1
ldr \tmp, =(SCTLR_EL2_RES1 | SCTLR_EL2_EE_LE |\
SCTLR_EL2_WXN_DIS | SCTLR_EL2_ICACHE_DIS |\
SCTLR_EL2_SA_DIS | SCTLR_EL2_DCACHE_DIS |\
SCTLR_EL2_ALIGN_DIS | SCTLR_EL2_MMU_DIS)
msr sctlr_el2, \tmp
mov \tmp, sp
msr sp_el2, \tmp /* Migrate SP */
mrs \tmp, vbar_el3
msr vbar_el2, \tmp /* Migrate VBAR */
/* Check switch to AArch64 EL2 or AArch32 Hypervisor mode */
cmp \flag, #ES_TO_AARCH32
b.eq 1f
/*
* The next lower exception level is AArch64, 64bit EL2 | HCE |
* SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1.
*/
ldr \tmp, =(SCR_EL3_RW_AARCH64 | SCR_EL3_HCE_EN |\
SCR_EL3_SMD_DIS | SCR_EL3_RES1 |\
SCR_EL3_NS_EN)
msr scr_el3, \tmp /* Return to the EL2_SP2 mode from EL3 */
mov \xreg1, sp
msr sp_el2, \xreg1 /* Migrate SP */
mrs \xreg1, vbar_el3
msr vbar_el2, \xreg1 /* Migrate VBAR */
mov \xreg1, #0x3c9
msr spsr_el3, \xreg1 /* EL2_SP2 | D | A | I | F */
msr elr_el3, lr
ldr \tmp, =(SPSR_EL_DEBUG_MASK | SPSR_EL_SERR_MASK |\
SPSR_EL_IRQ_MASK | SPSR_EL_FIQ_MASK |\
SPSR_EL_M_AARCH64 | SPSR_EL_M_EL2H)
msr spsr_el3, \tmp
msr elr_el3, \ep
eret
+1:
/*
* The next lower exception level is AArch32, 32bit EL2 | HCE |
* SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1.
*/
ldr \tmp, =(SCR_EL3_RW_AARCH32 | SCR_EL3_HCE_EN |\
SCR_EL3_SMD_DIS | SCR_EL3_RES1 |\
SCR_EL3_NS_EN)
msr scr_el3, \tmp
/* Return to AArch32 Hypervisor mode */
ldr \tmp, =(SPSR_EL_END_LE | SPSR_EL_ASYN_MASK |\
SPSR_EL_IRQ_MASK | SPSR_EL_FIQ_MASK |\
SPSR_EL_T_A32 | SPSR_EL_M_AARCH32 |\
SPSR_EL_M_HYP)
msr spsr_el3, \tmp
msr elr_el3, \ep eret
.endm
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 3a22661..edb842b 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -17,6 +17,95 @@ #define CR_WXN (1 << 19) /* Write Permision Imply XN */ #define CR_EE (1 << 25) /* Exception (Big) Endian */
+#define ES_TO_AARCH64 1 +#define ES_TO_AARCH32 0
+/*
- SCR_EL3 bits definitions
- */
+#define SCR_EL3_RW_AARCH64 (1 << 10) /* Next lower level is AArch64 */ +#define SCR_EL3_RW_AARCH32 (0 << 10) /* Lower lowers level are AArch32 */ +#define SCR_EL3_HCE_EN (1 << 8) /* Hypervisor Call enable */ +#define SCR_EL3_SMD_DIS (1 << 7) /* Secure Monitor Call disable */ +#define SCR_EL3_RES1 (3 << 4) /* Reserved, RES1 */ +#define SCR_EL3_NS_EN (1 << 0) /* EL0 and EL1 in Non-scure state */
+/*
- SPSR_EL3/SPSR_EL2 bits definitions
- */
+#define SPSR_EL_END_LE (0 << 9) /* Exception Little-endian */ +#define SPSR_EL_DEBUG_MASK (1 << 9) /* Debug exception masked */ +#define SPSR_EL_ASYN_MASK (1 << 8) /* Asynchronous data abort masked */ +#define SPSR_EL_SERR_MASK (1 << 8) /* System Error exception masked */ +#define SPSR_EL_IRQ_MASK (1 << 7) /* IRQ exception masked */ +#define SPSR_EL_FIQ_MASK (1 << 6) /* FIQ exception masked */ +#define SPSR_EL_T_A32 (0 << 5) /* AArch32 instruction set A32 */ +#define SPSR_EL_M_AARCH64 (0 << 4) /* Exception taken from AArch64 */ +#define SPSR_EL_M_AARCH32 (1 << 4) /* Exception taken from AArch32 */ +#define SPSR_EL_M_SVC (0x3) /* Exception taken from SVC mode */ +#define SPSR_EL_M_HYP (0xa) /* Exception taken from HYP mode */ +#define SPSR_EL_M_EL1H (5) /* Exception taken from EL1h mode */ +#define SPSR_EL_M_EL2H (9) /* Exception taken from EL2h mode */
+/*
- CPTR_EL2 bits definitions
- */
+#define CPTR_EL2_RES1 (3 << 12 | 0x3ff) /* Reserved, RES1 */
+/*
- SCTLR_EL2 bits definitions
- */
+#define SCTLR_EL2_RES1 (3 << 28 | 3 << 22 | 1 << 18 | 1 << 16 |\
1 << 11 | 3 << 4) /* Reserved, RES1 */
+#define SCTLR_EL2_EE_LE (0 << 25) /* Exception Little-endian */ +#define SCTLR_EL2_WXN_DIS (0 << 19) /* Write permission is not XN */ +#define SCTLR_EL2_ICACHE_DIS (0 << 12) /* Instruction cache disabled */ +#define SCTLR_EL2_SA_DIS (0 << 3) /* Stack Alignment Check disabled */ +#define SCTLR_EL2_DCACHE_DIS (0 << 2) /* Data cache disabled */ +#define SCTLR_EL2_ALIGN_DIS (0 << 1) /* Alignment check disabled */ +#define SCTLR_EL2_MMU_DIS (0) /* MMU disabled */
+/*
- CNTHCTL_EL2 bits definitions
- */
+#define CNTHCTL_EL2_EL1PCEN_EN (1 << 1) /* Physical timer regs accessible */ +#define CNTHCTL_EL2_EL1PCTEN_EN (1 << 0) /* Physical counter accessible */
+/*
- HCR_EL2 bits definitions
- */
+#define HCR_EL2_RW_AARCH64 (1 << 31) /* EL1 is AArch64 */ +#define HCR_EL2_RW_AARCH32 (0 << 31) /* Lower levels are AArch32 */ +#define HCR_EL2_HCD_DIS (1 << 29) /* Hypervisor Call disabled */
+/*
- CPACR_EL1 bits definitions
- */
+#define CPACR_EL1_FPEN_EN (3 << 20) /* SIMD and FP instruction enabled */
+/*
- SCTLR_EL1 bits definitions
- */
+#define SCTLR_EL1_RES1 (3 << 28 | 3 << 22 | 1 << 20 |\
1 << 11) /* Reserved, RES1 */
+#define SCTLR_EL1_UCI_DIS (0 << 26) /* Cache instruction disabled */ +#define SCTLR_EL1_EE_LE (0 << 25) /* Exception Little-endian */ +#define SCTLR_EL1_WXN_DIS (0 << 19) /* Write permission is not XN */ +#define SCTLR_EL1_NTWE_DIS (0 << 18) /* WFE instruction disabled */ +#define SCTLR_EL1_NTWI_DIS (0 << 16) /* WFI instruction disabled */ +#define SCTLR_EL1_UCT_DIS (0 << 15) /* CTR_EL0 access disabled */ +#define SCTLR_EL1_DZE_DIS (0 << 14) /* DC ZVA instruction disabled */ +#define SCTLR_EL1_ICACHE_DIS (0 << 12) /* Instruction cache disabled */ +#define SCTLR_EL1_UMA_DIS (0 << 9) /* User Mask Access disabled */ +#define SCTLR_EL1_SED_EN (0 << 8) /* SETEND instruction enabled */ +#define SCTLR_EL1_ITD_EN (0 << 7) /* IT instruction enabled */ +#define SCTLR_EL1_CP15BEN_DIS (0 << 5) /* CP15 barrier operation disabled */ +#define SCTLR_EL1_SA0_DIS (0 << 4) /* Stack Alignment EL0 disabled */ +#define SCTLR_EL1_SA_DIS (0 << 3) /* Stack Alignment EL1 disabled */ +#define SCTLR_EL1_DCACHE_DIS (0 << 2) /* Data cache disabled */ +#define SCTLR_EL1_ALIGN_DIS (0 << 1) /* Alignment check disabled */ +#define SCTLR_EL1_MMU_DIS (0) /* MMU disabled */
#ifndef __ASSEMBLY__
u64 get_page_table_size(void); @@ -100,7 +189,20 @@ void __asm_invalidate_icache_all(void); int __asm_flush_l3_cache(void); void __asm_switch_ttbr(u64 new_ttbr);
-void armv8_switch_to_el2(void); +/*
- Switch from EL3 to EL2 for ARMv8
- @args: For loading 64-bit OS, fdt address.
For loading 32-bit OS, zero.
- @mach_nr: For loading 64-bit OS, zero.
For loading 32-bit OS, machine nr
- @fdt_addr: For loading 64-bit OS, zero.
For loading 32-bit OS, fdt address.
- @entry_point: kernel entry point
- @es_flag: execution state flag, ES_TO_AARCH64 or ES_TO_AARCH32
- */
+void armv8_switch_to_el2(u64 args, u64 mach_nr, u64 fdt_addr,
u64 entry_point, u64 es_flag);
void gic_init(void); void gic_send_sgi(unsigned long sgino); void wait_for_wakeup(void); diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index e3c9832..59adab8 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -193,7 +193,6 @@ static void do_nonsec_virt_switch(void) { smp_kick_all_cpus(); dcache_disable(); /* flush cache before swtiching to EL2 */
armv8_switch_to_el2();
} #endif
@@ -284,7 +283,17 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
if (!fake) { do_nonsec_virt_switch();
kernel_entry(images->ft_addr, NULL, NULL, NULL);
if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
(images->os.arch == IH_ARCH_ARM))
armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number,
(u64)images->ft_addr,
(u64)images->ep,
ES_TO_AARCH32);
else
armv8_switch_to_el2((u64)images->ft_addr, 0, 0,
images->ep,
ES_TO_AARCH64); }
#else unsigned long machid = gd->bd->bi_arch_number; diff --git a/common/image-fit.c b/common/image-fit.c index 6f920da..c28e8fa 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -26,6 +26,7 @@ DECLARE_GLOBAL_DATA_PTR; #include <u-boot/md5.h> #include <u-boot/sha1.h> #include <u-boot/sha256.h> +#include <generated/autoconf.h>
/*****************************************************************************/ /* New uImage format routines */ @@ -1160,11 +1161,18 @@ int fit_image_check_os(const void *fit, int noffset, uint8_t os) int fit_image_check_arch(const void *fit, int noffset, uint8_t arch) { uint8_t image_arch;
int aarch32_support = 0;
+#ifdef CONFIG_ARM64_SUPPORT_AARCH32
aarch32_support = 1;
+#endif
if (fit_image_get_arch(fit, noffset, &image_arch)) return 0; return (arch == image_arch) ||
(arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64);
(arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64) ||
(arch == IH_ARCH_ARM64 && image_arch == IH_ARCH_ARM &&
aarch32_support);
}
/** @@ -1593,6 +1601,9 @@ int fit_image_load(bootm_headers_t *images, ulong addr, int type_ok, os_ok; ulong load, data, len; uint8_t os; +#ifndef USE_HOSTCC
uint8_t os_arch;
+#endif const char *prop_name; int ret;
@@ -1676,6 +1687,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr, return -ENOEXEC; } #endif
+#ifndef USE_HOSTCC
fit_image_get_arch(fit, noffset, &os_arch);
images->os.arch = os_arch;
+#endif
if (image_type == IH_TYPE_FLATDT && !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { puts("FDT image is compressed");
-- 2.1.0.27.g96db324

On 07/07/2016 02:16 PM, Ryan Harkin wrote:
On 7 July 2016 at 07:30, Alison Wang b18965@freescale.com wrote:
To support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel.
The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Signed-off-by: Ebony Zhu ebony.zhu@nxp.com Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com
Unfortunately, this patch fails to boot for me.
On FVP Foundation models, I see this error before the model hangs:
[snip] Starting kernel ...
resetting ... [snip]
And I see the same output on AEMv8 Base models and Juno boards, only they reset continuously rather than hang.
I think the problem is that I see this from ARM Trusted Firmware on boot:
INFO: BL31: Preparing for EL3 exit to normal world
Looking at the patch, it appears to be changing everything to boot in EL2.
That was the case before the patch (with the removal of the EL1 boot thing) already. Linux can't run in EL3, that's why it has to boot in EL2 (or EL1, but that really should be limited to VMs).
Alex

On 7 July 2016 at 13:30, Alexander Graf agraf@suse.de wrote:
On 07/07/2016 02:16 PM, Ryan Harkin wrote:
On 7 July 2016 at 07:30, Alison Wang b18965@freescale.com wrote:
To support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel.
The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Signed-off-by: Ebony Zhu ebony.zhu@nxp.com Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com
Unfortunately, this patch fails to boot for me.
On FVP Foundation models, I see this error before the model hangs:
[snip] Starting kernel ...
resetting ... [snip]
And I see the same output on AEMv8 Base models and Juno boards, only they reset continuously rather than hang.
I think the problem is that I see this from ARM Trusted Firmware on boot:
INFO: BL31: Preparing for EL3 exit to normal world
Looking at the patch, it appears to be changing everything to boot in EL2.
That was the case before the patch (with the removal of the EL1 boot thing) already. Linux can't run in EL3, that's why it has to boot in EL2 (or EL1, but that really should be limited to VMs).
Pah! I misread the patch, specifically this hunk (and the one before it, I suppose):
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index e3c9832..59adab8 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -193,7 +193,6 @@ static void do_nonsec_virt_switch(void) { smp_kick_all_cpus(); dcache_disable(); /* flush cache before swtiching to EL2 */ - armv8_switch_to_el2(); } #endif
That's a "-", not a "+" on the call to armv8_switch_to_el2().
Either way, all my platforms are dead with this patch.
Alex

On 07/07/2016 02:35 PM, Ryan Harkin wrote:
On 7 July 2016 at 13:30, Alexander Graf agraf@suse.de wrote:
On 07/07/2016 02:16 PM, Ryan Harkin wrote:
On 7 July 2016 at 07:30, Alison Wang b18965@freescale.com wrote:
To support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel.
The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Signed-off-by: Ebony Zhu ebony.zhu@nxp.com Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com
Unfortunately, this patch fails to boot for me.
On FVP Foundation models, I see this error before the model hangs:
[snip] Starting kernel ...
resetting ... [snip]
And I see the same output on AEMv8 Base models and Juno boards, only they reset continuously rather than hang.
I think the problem is that I see this from ARM Trusted Firmware on boot:
INFO: BL31: Preparing for EL3 exit to normal world
Looking at the patch, it appears to be changing everything to boot in EL2.
That was the case before the patch (with the removal of the EL1 boot thing) already. Linux can't run in EL3, that's why it has to boot in EL2 (or EL1, but that really should be limited to VMs).
Pah! I misread the patch, specifically this hunk (and the one before it, I suppose):
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index e3c9832..59adab8 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -193,7 +193,6 @@ static void do_nonsec_virt_switch(void) { smp_kick_all_cpus(); dcache_disable(); /* flush cache before swtiching to EL2 */
- armv8_switch_to_el2(); } #endif
That's a "-", not a "+" on the call to armv8_switch_to_el2().
Either way, all my platforms are dead with this patch.
Since you're running in software models, can you try to figure out where exactly it breaks? I'm slightly confused that it's resetting. The switch to EL2 shouldn't matter in your setup, because you're executing U-Boot in EL2 already, since you're running ATF in EL3.
Alex

On 7 July 2016 at 13:41, Alexander Graf agraf@suse.de wrote:
On 07/07/2016 02:35 PM, Ryan Harkin wrote:
On 7 July 2016 at 13:30, Alexander Graf agraf@suse.de wrote:
On 07/07/2016 02:16 PM, Ryan Harkin wrote:
On 7 July 2016 at 07:30, Alison Wang b18965@freescale.com wrote:
To support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel.
The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Signed-off-by: Ebony Zhu ebony.zhu@nxp.com Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com
Unfortunately, this patch fails to boot for me.
On FVP Foundation models, I see this error before the model hangs:
[snip] Starting kernel ...
resetting ... [snip]
And I see the same output on AEMv8 Base models and Juno boards, only they reset continuously rather than hang.
I think the problem is that I see this from ARM Trusted Firmware on boot:
INFO: BL31: Preparing for EL3 exit to normal world
Looking at the patch, it appears to be changing everything to boot in EL2.
That was the case before the patch (with the removal of the EL1 boot thing) already. Linux can't run in EL3, that's why it has to boot in EL2 (or EL1, but that really should be limited to VMs).
Pah! I misread the patch, specifically this hunk (and the one before it, I suppose):
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index e3c9832..59adab8 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -193,7 +193,6 @@ static void do_nonsec_virt_switch(void) { smp_kick_all_cpus(); dcache_disable(); /* flush cache before swtiching to EL2 */
- armv8_switch_to_el2(); } #endif
That's a "-", not a "+" on the call to armv8_switch_to_el2().
Either way, all my platforms are dead with this patch.
Since you're running in software models, can you try to figure out where exactly it breaks?
You assume that because I have a model that I have the ability to debug it ;-)
ARM's FVP Foundation model is publicly available and free to use. So if you want to give it a spin, it's there for the taking.
I'm slightly confused that it's resetting. The switch to EL2 shouldn't matter in your setup, because you're executing U-Boot in EL2 already, since you're running ATF in EL3.
Alex

On 07/07/2016 02:46 PM, Ryan Harkin wrote:
On 7 July 2016 at 13:41, Alexander Graf agraf@suse.de wrote:
On 07/07/2016 02:35 PM, Ryan Harkin wrote:
On 7 July 2016 at 13:30, Alexander Graf agraf@suse.de wrote:
On 07/07/2016 02:16 PM, Ryan Harkin wrote:
On 7 July 2016 at 07:30, Alison Wang b18965@freescale.com wrote:
To support loading a 32-bit OS, the execution state will change from AArch64 to AArch32 when jumping to kernel.
The architecture information will be got through checking FIT image, then U-Boot will load 32-bit OS or 64-bit OS automatically.
Signed-off-by: Ebony Zhu ebony.zhu@nxp.com Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com
Unfortunately, this patch fails to boot for me.
On FVP Foundation models, I see this error before the model hangs:
[snip] Starting kernel ...
resetting ... [snip]
And I see the same output on AEMv8 Base models and Juno boards, only they reset continuously rather than hang.
I think the problem is that I see this from ARM Trusted Firmware on boot:
INFO: BL31: Preparing for EL3 exit to normal world
Looking at the patch, it appears to be changing everything to boot in EL2.
That was the case before the patch (with the removal of the EL1 boot thing) already. Linux can't run in EL3, that's why it has to boot in EL2 (or EL1, but that really should be limited to VMs).
Pah! I misread the patch, specifically this hunk (and the one before it, I suppose):
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index e3c9832..59adab8 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -193,7 +193,6 @@ static void do_nonsec_virt_switch(void) { smp_kick_all_cpus(); dcache_disable(); /* flush cache before swtiching to EL2 */
- armv8_switch_to_el2(); } #endif
That's a "-", not a "+" on the call to armv8_switch_to_el2().
Either way, all my platforms are dead with this patch.
Since you're running in software models, can you try to figure out where exactly it breaks?
You assume that because I have a model that I have the ability to debug it ;-)
ARM's FVP Foundation model is publicly available and free to use. So if you want to give it a spin, it's there for the taking.
I thought the Foundation model doesn't support external debugging? I'd basically want to put a breakpoint at the point where the kernel exit print goes and then trace it from there :).
But since Alison wrote the patches, I'm sure he can do that too :).
Alex

Spin-table method is used for secondary cores to load 32-bit OS. The architecture information will be got through checking FIT image and saved in the os_arch element of spin-table, then the secondary cores will check os_arch and jump to 32-bit OS or 64-bit OS automatically.
Signed-off-by: Alison Wang alison.wang@nxp.com Signed-off-by: Chenhui Zhao chenhui.zhao@nxp.com --- Changes in v5: - Make secondary_switch_to_el2() always jump to ep when switching to AArch64 or AArch32 modes.
Changes in v4: - Omit arch and ftaddr arguments.
Changes in v3: - Adjust the arguments for armv8_switch_to_el2_m and armv8_switch_to_el1_m.
Changes in v2: - Support to call armv8_switch_to_el2_m and armv8_switch_to_el1_m.
arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 23 ++++++++++++++++++----- arch/arm/cpu/armv8/fsl-layerscape/mp.c | 10 ++++++++++ arch/arm/include/asm/arch-fsl-layerscape/mp.h | 6 ++++++ arch/arm/lib/bootm.c | 6 ++++++ 4 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S index d3a0117..9535350 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S +++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S @@ -13,6 +13,8 @@ #ifdef CONFIG_MP #include <asm/arch/mp.h> #endif +#include <asm/u-boot.h> +#include <asm/system.h>
ENTRY(lowlevel_init) mov x29, lr /* Save LR */ @@ -324,8 +326,6 @@ ENTRY(secondary_boot_func) gic_wait_for_interrupt_m x0, w1 #endif
- bl secondary_switch_to_el2 - slave_cpu: wfe ldr x0, [x11] @@ -334,13 +334,26 @@ slave_cpu: tbz x1, #25, cpu_is_le rev x0, x0 /* BE to LE conversion */ cpu_is_le: - br x0 /* branch to the given address */ + + ldr x5, [x11, #24] + ldr x6, =IH_ARCH_DEFAULT + cmp x6, x5 + b.eq 1f + + ldr x3, [x11] + ldr x4, =ES_TO_AARCH32 + bl secondary_switch_to_el2 + +1: + ldr x3, [x11] + ldr x4, =ES_TO_AARCH64 + bl secondary_switch_to_el2 ENDPROC(secondary_boot_func)
ENTRY(secondary_switch_to_el2) - switch_el x0, 1f, 0f, 0f + switch_el x5, 1f, 0f, 0f 0: ret -1: armv8_switch_to_el2_m x0 +1: armv8_switch_to_el2_m x3, x4, x5 ENDPROC(secondary_switch_to_el2)
/* Ensure that the literals used by the secondary boot code are diff --git a/arch/arm/cpu/armv8/fsl-layerscape/mp.c b/arch/arm/cpu/armv8/fsl-layerscape/mp.c index df7ffb8..dd91550 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/mp.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/mp.c @@ -22,6 +22,16 @@ phys_addr_t determine_mp_bootpg(void) return (phys_addr_t)&secondary_boot_code; }
+void update_os_arch_secondary_cores(uint8_t os_arch) +{ + u64 *table = get_spin_tbl_addr(); + int i; + + for (i = 1; i < CONFIG_MAX_CPUS; i++) + table[i * WORDS_PER_SPIN_TABLE_ENTRY + + SPIN_TABLE_ELEM_OS_ARCH_IDX] = os_arch; +} + int fsl_layerscape_wake_seconday_cores(void) { struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); diff --git a/arch/arm/include/asm/arch-fsl-layerscape/mp.h b/arch/arm/include/asm/arch-fsl-layerscape/mp.h index e46e076..55f0e0c 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/mp.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/mp.h @@ -13,6 +13,7 @@ * uint64_t entry_addr; * uint64_t status; * uint64_t lpid; +* uint64_t os_arch; * }; * we pad this struct to 64 bytes so each entry is in its own cacheline * the actual spin table is an array of these structures @@ -20,6 +21,7 @@ #define SPIN_TABLE_ELEM_ENTRY_ADDR_IDX 0 #define SPIN_TABLE_ELEM_STATUS_IDX 1 #define SPIN_TABLE_ELEM_LPID_IDX 2 +#define SPIN_TABLE_ELEM_OS_ARCH_IDX 3 #define WORDS_PER_SPIN_TABLE_ENTRY 8 /* pad to 64 bytes */ #define SPIN_TABLE_ELEM_SIZE 64
@@ -35,4 +37,8 @@ phys_addr_t determine_mp_bootpg(void); void secondary_boot_func(void); int is_core_online(u64 cpu_id); #endif + +#define IH_ARCH_ARM 2 /* ARM */ +#define IH_ARCH_ARM64 22 /* ARM64 */ + #endif /* _FSL_LAYERSCAPE_MP_H */ diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 59adab8..56052c1 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -264,6 +264,10 @@ bool armv7_boot_nonsec(void) } #endif
+__weak void update_os_arch_secondary_cores(uint8_t os_arch) +{ +} + /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) { @@ -284,6 +288,8 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) if (!fake) { do_nonsec_virt_switch();
+ update_os_arch_secondary_cores(images->os.arch); + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && (images->os.arch == IH_ARCH_ARM)) armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number,
participants (3)
-
Alexander Graf
-
Alison Wang
-
Ryan Harkin