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

Alexander Graf agraf at suse.de
Fri Jun 3 09:26:27 CEST 2016



On 03.06.16 05:11, Huan Wang wrote:
>> On 26.05.16 10:41, Alison Wang 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 at nxp.com>
>>> Signed-off-by: Alison Wang <alison.wang at nxp.com>
>>> Signed-off-by: Chenhui Zhao <chenhui.zhao at nxp.com>
>>> ---
>>> 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/transition.S |   8 +-
>>>  arch/arm/include/asm/macro.h    | 174 ++++++++++++++++++++++++++++++-
>> ---------
>>>  arch/arm/include/asm/system.h   | 118 ++++++++++++++++++++++++++-
>>>  arch/arm/lib/bootm.c            |  19 ++++-
>>>  common/image-fit.c              |  14 +++-
>>>  6 files changed, 287 insertions(+), 52 deletions(-)
>>>
>>> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index
>>> 729b181..794cb4f 100644
>>> --- a/arch/arm/Kconfig
>>> +++ b/arch/arm/Kconfig
>>> @@ -77,6 +77,12 @@ config SYS_L2CACHE_OFF
>>>  	  If SoC does not support L2CACHE or one do not want to enable
>>>  	  L2CACHE, choose this option.
>>>
>>> +config ARM64_SUPPORT_AARCH32
>>> +	bool "ARM64 system support AArch32 execution state"
>>> +	default y if ARM64 && !CONFIG_THUNDERX
>>
>> I don't think that works. In Kconfig you need to omit the CONFIG_ parts.
>> It's "ARM64" also, not "CONFIG_ARM64".
>>
>> Please just try to run a local make defconfig on the thunderx reference
>> system and see whether it includes the option or not.
> [Alison Wang] Yes, I missed it. Will change in the next version.
>>
>>> +	help
>>> +	  This ARM64 system supports AArch32 execution state.
>>> +
>>>  choice
>>>  	prompt "Target select"
>>>  	default TARGET_HIKEY
>>> diff --git a/arch/arm/cpu/armv8/transition.S
>>> b/arch/arm/cpu/armv8/transition.S index 253a39b..417e8b4 100644
>>> --- a/arch/arm/cpu/armv8/transition.S
>>> +++ b/arch/arm/cpu/armv8/transition.S
>>> @@ -11,13 +11,13 @@
>>>  #include <asm/macro.h>
>>>
>>>  ENTRY(armv8_switch_to_el2)
>>> -	switch_el x0, 1f, 0f, 0f
>>> +	switch_el x4, 1f, 0f, 0f
>>>  0:	ret
>>> -1:	armv8_switch_to_el2_m x0
>>> +1:	armv8_switch_to_el2_m x0, x1, x2, x3, x4
>>>  ENDPROC(armv8_switch_to_el2)
>>>
>>>  ENTRY(armv8_switch_to_el1)
>>> -	switch_el x0, 0f, 1f, 0f
>>> +	switch_el x4, 0f, 1f, 0f
>>>  0:	ret
>>> -1:	armv8_switch_to_el1_m x0, x1
>>> +1:	armv8_switch_to_el1_m x0, x1, x2, x3, x4
>>>  ENDPROC(armv8_switch_to_el1)
>>> diff --git a/arch/arm/include/asm/macro.h
>>> b/arch/arm/include/asm/macro.h index 9bb0efa..dd2c510 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,18 @@ 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
>>> + * @arch:   machine nr
>>> + * @ftaddr: fdt address
>>> + * @flag:   The execution state flag for lower exception
>>> + *          level, ES_TO_AARCH64 or ES_TO_AARCH32
>>> + */
>>> +.macro armv8_switch_to_el2_m, ep, arch, ftaddr, flag, xreg5
>>
>> You're never really using the arch and ftaddr arguments. Just describe
>> in the macro header that they need to be in x1 and x2 respectively and
>> leave them out of the argument list for the macro.
> [Alison Wang] Do you mean rename arch and ftaddr to x1 and x2 here?

I mean omit arch and ftaddr from the macro arguments and instead mention
that x1 and x2 get passed as x1 and x2 to the guest and are usually
"ftaddr" and "arch".

Also it would make the code more consistent to always use ep.


+/*
+ * Switch from EL3 to EL2 for ARMv8 and jump to @ep.
+ *
+ * @flag:   The execution state flag for lower exception
+ *          level, ES_TO_AARCH64 or ES_TO_AARCH32
+ *
+ * When flag == ES_TO_AARCH32:
+ * @ep:     location to jump to in AArch32 EL2 mode
+ * x1:      "Machine ID" for Linux payloads
+ * x2:      "DT Address" for Linux payloads
+ *
+ * When flag == ES_TO_AARCH64:
+ * @ep:     location to jump to in AArch64 EL2 mode
+ * x1:      "DT Address" for Linux payloads
+ */
+.macro armv8_switch_to_el2_m, ep, flag, tmpreg


>>
>> Also please rename "xreg5" to something like "scratchreg" or "tmp" or
>> "tmpreg". Then it's more obvious what this argument is about.
> [Alison Wang] Ok.
>>
>>>  	msr	cptr_el3, xzr		/* Disable coprocessor traps to EL3
>> */
>>> -	mov	\xreg1, #0x33ff
>>> -	msr	cptr_el2, \xreg1	/* Disable coprocessor traps to EL2 */
>>> +	mov	\xreg5, #(CPTR_EL2_BIT13_12_RES1 | CPTR_EL2_BIT9_0_RES1)
>>> +	msr	cptr_el2, \xreg5	/* Disable coprocessor traps to EL2 */
>>>
>>>  	/* Initialize Generic Timers */
>>>  	msr	cntvoff_el2, xzr
>>> @@ -152,45 +160,92 @@ 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	\xreg5, =(SCTLR_EL2_BIT29_28_RES1 | SCTLR_EL2_EE_LE |\
>>> +			  SCTLR_EL2_BIT23_22_RES1 | SCTLR_EL2_WXN_DIS |\
>>> +			  SCTLR_EL2_BIT18_RES1 | SCTLR_EL2_BIT16_RES1 |\
>>> +			  SCTLR_EL2_BIT11_RES1 | SCTLR_EL2_BIT5_4_RES1 |\
>>> +			  SCTLR_EL2_SA_DIS | SCTLR_EL2_DCACHE_DIS |\
>>> +			  SCTLR_EL2_ALIGN_DIS | SCTLR_EL2_MMU_DIS)
>>
>> Do you think you could just define something like SCTLR_EL2_RES1 in the
>> header file that combines all RES1 fields already?
> [Alison Wang] Ok, I think so.
>>
>>> +	msr	sctlr_el2, \xreg5
>>> +
>>> +	mov	\xreg5, sp
>>> +	msr	sp_el2, \xreg5		/* Migrate SP */
>>> +	mrs	\xreg5, vbar_el3
>>> +	msr	vbar_el2, \xreg5	/* Migrate VBAR */
>>> +
>>> +	/* Check switch to AArch64 EL2 or AArch32 Hypervisor mode */
>>> +	ldr	\xreg5, =ES_TO_AARCH32
>>> +	cmp	\flag, \xreg5
>>
>> This can be an immediate cmp, no?
>>
>>   cmp \flag, #ES_TO_AARCH32
> [Alison Wang] Yes, it can. Will change in the next version.
>>
>>> +	b.eq	1f
>>> +
>>> +	/*
>>> +	 * The next lower exception level is AArch64, 64bit EL2 | HCE |
>>> +	 * SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1.
>>> +	 */
>>> +	ldr	\xreg5, =(SCR_EL3_RW_AARCH64 | SCR_EL3_HCE_EN |\
>>> +			  SCR_EL3_SMD_DIS | SCR_EL3_BIT5_4_RES1 |\
>>> +			  SCR_EL3_NS_EN)
>>
>> Same here - just define a single mask for SCR_EL3_RES1.
> [Alison Wang] Ok.
>>
>>> +	msr	scr_el3, \xreg5
>>>
>>>  	/* 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 */
>>> +	ldr	\xreg5, =(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, \xreg5
>>>  	msr	elr_el3, lr
>>>  	eret
>>> +
>>> +1:
>>> +	/*
>>> +	 * The next lower exception level is AArch32, 32bit EL2 | HCE |
>>> +	 * SMD | RES1 (Bits[5:4]) | Non-secure EL0/EL1.
>>> +	 */
>>> +	ldr	\xreg5, =(SCR_EL3_RW_AARCH32 | SCR_EL3_HCE_EN |\
>>> +			  SCR_EL3_SMD_DIS | SCR_EL3_BIT5_4_RES1 |\
>>> +			  SCR_EL3_NS_EN)
>>> +	msr	scr_el3, \xreg5
>>> +
>>> +	/* Return to AArch32 Hypervisor mode */
>>> +	ldr     \xreg5, =(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, \xreg5
>>> +	msr     elr_el3, \ep
>>> +
>>> +	mov	\ep, #0
>>> +	eret
>>>  .endm
>>>
>>> -.macro armv8_switch_to_el1_m, xreg1, xreg2
>>> +/*
>>> + * Switch from EL2 to EL1 for ARMv8
>>> + * @ep:     kernel entry point
>>> + * @arch:   machine nr
>>> + * @ftaddr: fdt address
>>> + * @flag:   The execution state flag for lower exception
>>> + *          level, ES_TO_AARCH64 or ES_TO_AARCH32
>>> + */
>>> +.macro armv8_switch_to_el1_m, ep, arch, ftaddr, flag, xreg5
>>
>> All the comments to the function above apply here too :).
> [Alison Wang] Ok.
>>
>>>  	/* Initialize Generic Timers */
>>> -	mrs	\xreg1, cnthctl_el2
>>> -	orr	\xreg1, \xreg1, #0x3	/* Enable EL1 access to timers */
>>> -	msr	cnthctl_el2, \xreg1
>>> +	mrs	\xreg5, cnthctl_el2
>>> +	/* Enable EL1 access to timers */
>>> +	orr	\xreg5, \xreg5, #(CNTHCTL_EL2_EL1PCEN_EN |\
>>> +		CNTHCTL_EL2_EL1PCTEN_EN)
>>> +	msr	cnthctl_el2, \xreg5
>>>  	msr	cntvoff_el2, xzr
>>>
>>>  	/* Initilize MPID/MPIDR registers */
>>> -	mrs	\xreg1, midr_el1
>>> -	mrs	\xreg2, mpidr_el1
>>> -	msr	vpidr_el2, \xreg1
>>> -	msr	vmpidr_el2, \xreg2
>>> +	mrs	\xreg5, midr_el1
>>> +	msr	vpidr_el2, \xreg5
>>> +	mrs	\xreg5, mpidr_el1
>>> +	msr	vmpidr_el2, \xreg5
>>>
>>>  	/* Disable coprocessor traps */
>>> -	mov	\xreg1, #0x33ff
>>> -	msr	cptr_el2, \xreg1	/* Disable coprocessor traps to EL2 */
>>> +	mov	\xreg5, #(CPTR_EL2_BIT13_12_RES1 | CPTR_EL2_BIT9_0_RES1)
>>> +	msr	cptr_el2, \xreg5	/* Disable coprocessor traps to EL2 */
>>>  	msr	hstr_el2, xzr		/* Disable coprocessor traps to EL2
>> */
>>> -	mov	\xreg1, #3 << 20
>>> -	msr	cpacr_el1, \xreg1	/* Enable FP/SIMD at EL1 */
>>> -
>>> -	/* Initialize HCR_EL2 */
>>> -	mov	\xreg1, #(1 << 31)		/* 64bit EL1 */
>>> -	orr	\xreg1, \xreg1, #(1 << 29)	/* Disable HVC */
>>> -	msr	hcr_el2, \xreg1
>>> +	mov	\xreg5, #(CPACR_EL1_FPEN_EN)
>>> +	msr	cpacr_el1, \xreg5	/* Enable FP/SIMD at EL1 */
>>>
>>>  	/* SCTLR_EL1 initialization
>>>  	 *
>>> @@ -199,19 +254,56 @@ lr	.req	x30
>>>  	 * UCI,EE,EOE,WXN,nTWE,nTWI,UCT,DZE,I,UMA,SED,ITD,
>>>  	 * CP15BEN,SA0,SA,C,A,M to 0
>>>  	 */
>>> -	mov	\xreg1, #0x0800
>>> -	movk	\xreg1, #0x30d0, lsl #16
>>> -	msr	sctlr_el1, \xreg1
>>> +	ldr	\xreg5, =(SCTLR_EL1_BIT29_28_RES1 | SCTLR_EL1_UCI_DIS |\
>>> +			  SCTLR_EL1_EE_LE | SCTLR_EL1_BIT23_22_RES1 |\
>>> +			  SCTLR_EL1_BIT20_RES1 | SCTLR_EL1_WXN_DIS |\
>>> +			  SCTLR_EL1_NTWE_DIS | SCTLR_EL1_NTWI_DIS |\
>>> +			  SCTLR_EL1_UCT_DIS | SCTLR_EL1_DZE_DIS |\
>>> +			  SCTLR_EL1_ICACHE_DIS | SCTLR_EL1_BIT11_RES1 |\
>>> +			  SCTLR_EL1_UMA_DIS | SCTLR_EL1_SED_EN |\
>>> +			  SCTLR_EL1_ITD_EN | SCTLR_EL1_CP15BEN_DIS |\
>>> +			  SCTLR_EL1_SA0_DIS | SCTLR_EL1_SA_DIS |\
>>> +			  SCTLR_EL1_DCACHE_DIS | SCTLR_EL1_ALIGN_DIS |\
>>> +			  SCTLR_EL1_MMU_DIS)
>>
>> Why are the caches getting disabled? Or did you just convert the old
>> value to the define list?
> [Alison Wang] Yes, I just convert the old value to the define list.
>>
>>> +	msr	sctlr_el1, \xreg5
>>> +
>>> +	mov	\xreg5, sp
>>> +	msr	sp_el1, \xreg5		/* Migrate SP */
>>> +	mrs	\xreg5, vbar_el2
>>> +	msr	vbar_el1, \xreg5	/* Migrate VBAR */
>>> +
>>> +	/* Check switch to AArch64 EL1 or AArch32 Supervisor mode */
>>> +	ldr	\xreg5, =ES_TO_AARCH32
>>> +	cmp	\flag, \xreg5
>>> +	b.eq	1f
>>> +
>>> +	/* Initialize HCR_EL2 */
>>> +	ldr	\xreg5, =(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS)
>>> +	msr	hcr_el2, \xreg5
>>>
>>>  	/* Return to the EL1_SP1 mode from EL2 */
>>> -	mov	\xreg1, sp
>>> -	msr	sp_el1, \xreg1		/* Migrate SP */
>>> -	mrs	\xreg1, vbar_el2
>>> -	msr	vbar_el1, \xreg1	/* Migrate VBAR */
>>> -	mov	\xreg1, #0x3c5
>>> -	msr	spsr_el2, \xreg1	/* EL1_SP1 | D | A | I | F */
>>> +	ldr	\xreg5, =(SPSR_EL_DEBUG_MASK | SPSR_EL_SERR_MASK |\
>>> +			  SPSR_EL_IRQ_MASK | SPSR_EL_FIQ_MASK |\
>>> +			  SPSR_EL_M_AARCH64 | SPSR_EL_M_EL1H)
>>> +	msr	spsr_el2, \xreg5
>>>  	msr	elr_el2, lr
>>>  	eret
>>> +
>>> +1:
>>> +	/* Initialize HCR_EL2 */
>>> +	ldr	\xreg5, =(HCR_EL2_RW_AARCH32 | HCR_EL2_HCD_DIS)
>>> +	msr	hcr_el2, \xreg5
>>> +
>>> +	/* Return to AArch32 Supervisor mode from EL2 */
>>> +	ldr	\xreg5, =(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_SVC)
>>> +	msr     spsr_el2, \xreg5
>>> +	msr     elr_el2, \ep
>>> +
>>> +	mov	\ep, #0
>>> +	eret
>>>  .endm
>>>
>>>  #if defined(CONFIG_GICV3)
>>> diff --git a/arch/arm/include/asm/system.h
>>> b/arch/arm/include/asm/system.h index 9ae890a..0271ddb 100644
>>> --- a/arch/arm/include/asm/system.h
>>> +++ b/arch/arm/include/asm/system.h
>>> @@ -17,6 +17,102 @@
>>>  #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_BIT5_4_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_BIT13_12_RES1	(3 << 12) /* Reserved, RES1
>> */
>>> +#define CPTR_EL2_BIT9_0_RES1	(0x3ff)   /* Reserved, RES1
>> */
>>> +
>>> +/*
>>> + * SCTLR_EL2 bits definitions
>>> + */
>>> +#define SCTLR_EL2_BIT29_28_RES1	(3 << 28) /* Reserved, RES1
>> */
>>> +#define SCTLR_EL2_EE_LE		(0 << 25) /* Exception Little-endian
>> */
>>> +#define SCTLR_EL2_BIT23_22_RES1	(3 << 22) /* Reserved, RES1
>> */
>>> +#define SCTLR_EL2_WXN_DIS	(0 << 19) /* Write permission is not XN
>> */
>>> +#define SCTLR_EL2_BIT18_RES1	(1 << 18) /* Reserved, RES1
>> */
>>> +#define SCTLR_EL2_BIT16_RES1	(1 << 16) /* Reserved, RES1
>> */
>>> +#define SCTLR_EL2_ICACHE_DIS	(0 << 12) /* Instruction cache
>> disabled       */
>>> +#define SCTLR_EL2_BIT11_RES1	(1 << 11) /* Reserved, RES1
>> */
>>> +#define SCTLR_EL2_BIT5_4_RES1	(3 << 4)  /* Reserved, RES1
>> */
>>> +#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_BIT29_28_RES1	(3 << 28) /* 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_BIT23_22_RES1	(3 << 22) /* Reserved, RES1
>> */
>>> +#define SCTLR_EL1_BIT20_RES1	(1 << 20) /* Reserved, RES1
>> */
>>> +#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_BIT11_RES1	(1 << 11) /* Reserved, RES1
>> */
>>> +#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,8 +196,26 @@ 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);
>>> -void armv8_switch_to_el1(void);
>>> +/*
>>> + * Switch from EL3 to EL2 for ARMv8
>>> + *
>>> + * @entry_point: kernel entry point
>>> + * @mach_nr:     machine nr
>>> + * @fdt_addr:    fdt address
>>> + * @es_flag:     execution state flag, ES_TO_AARCH64 or ES_TO_AARCH32
>>> + */
>>> +void armv8_switch_to_el2(u64 entry_point, u64 mach_nr, u64 fdt_addr,
>>> +			 u64 es_flag);
>>> +/*
>>> + * Switch from EL2 to EL1 for ARMv8
>>> + *
>>> + * @entry_point: kernel entry point
>>> + * @mach_nr:     machine nr
>>> + * @fdt_addr:    fdt address
>>> + * @es_flag:     execution state flag, ES_TO_AARCH64 or ES_TO_AARCH32
>>> + */
>>> +void armv8_switch_to_el1(u64 entry_point, u64 mach_nr, u64 fdt_addr,
>>> +			 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
>>> 0838d89..1bbf85c 100644
>>> --- a/arch/arm/lib/bootm.c
>>> +++ b/arch/arm/lib/bootm.c
>>> @@ -189,13 +189,19 @@ static void setup_end_tag(bd_t *bd)  __weak void
>>> setup_board_tags(struct tag **in_params) {}
>>>
>>>  #ifdef CONFIG_ARM64
>>> -static void do_nonsec_virt_switch(void)
>>> +static void do_nonsec_virt_switch(bootm_headers_t *images, int flag)
>>>  {
>>>  	smp_kick_all_cpus();
>>>  	dcache_disable();	/* flush cache before swtiching to EL2 */
>>> -	armv8_switch_to_el2();
>>> +
>>>  #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
>>> -	armv8_switch_to_el1();
>>> +	armv8_switch_to_el2((u64)images->ep, (u64)gd->bd->bi_arch_number,
>>> +			    (u64)images->ft_addr, ES_TO_AARCH64);
>>> +	armv8_switch_to_el1((u64)images->ep, (u64)gd->bd->bi_arch_number,
>>> +			    (u64)images->ft_addr, flag);
>>> +#else
>>> +	armv8_switch_to_el2((u64)images->ep, (u64)gd->bd->bi_arch_number,
>>> +			    (u64)images->ft_addr, flag);
>>>  #endif
>>>  }
>>>  #endif
>>> @@ -275,6 +281,7 @@ static void boot_jump_linux(bootm_headers_t
>> *images, int flag)
>>>  	void (*kernel_entry)(void *fdt_addr, void *res0, void *res1,
>>>  			void *res2);
>>>  	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
>>> +	int es_flag = ES_TO_AARCH64;
>>>
>>>  	kernel_entry = (void (*)(void *fdt_addr, void *res0, void *res1,
>>>  				void *res2))images->ep;
>>> @@ -286,7 +293,11 @@ static void boot_jump_linux(bootm_headers_t
>> *images, int flag)
>>>  	announce_and_cleanup(fake);
>>>
>>>  	if (!fake) {
>>> -		do_nonsec_virt_switch();
>>> +		if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
>>> +		    (images->os.arch == IH_ARCH_ARM))
>>> +			es_flag = ES_TO_AARCH32;
>>> +
>>> +		do_nonsec_virt_switch(images, es_flag);
>>>  		kernel_entry(images->ft_addr, NULL, NULL, NULL);
>>>  	}
>>>  #else
>>> diff --git a/common/image-fit.c b/common/image-fit.c index
>>> 9873957..982021b 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 */
>>> @@ -1164,7 +1165,9 @@ int fit_image_check_arch(const void *fit, int
>> noffset, uint8_t arch)
>>>  	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 &&
>>> +		 CONFIG_ARM64_SUPPORT_AARCH32);
>>
>> Uh, I think this define is simply not defined for non-compatible systems
>> (including non-arm64). This really needs to go into an #ifdef.
> [Alison Wang] I think arch == IH_ARCH_ARM64 will check for non-arm64 system.
> I can't understand your concern. Please explain more.

You either get a

#define CONFIG_ARM64_SUPPORT_AARCH32 1

in the config header if the option is set or simply nothing at all. If
there's nothing, compiling this code will result in an unresolved symbol.


Alex


More information about the U-Boot mailing list