[PATCH v7 13/16] arm64: head.S: el2_setup() to accept sctlr_el1 as an argument
Catalin Marinas
catalin.marinas at arm.com
Wed Apr 20 10:12:04 PDT 2016
On Fri, Apr 01, 2016 at 05:53:37PM +0100, James Morse wrote:
> el2_setup() doesn't just configure el2, it configures el1 too. This
> means we can't use it to re-configure el2 after resume from hibernate,
> as we will be returned to el1 with the MMU turned off.
>
> Split the sctlr_el1 setting code up, so that el2_setup() accepts an
> initial value as an argument. This value will be ignored if el2_setup()
> is called at el1: the running value will be preserved with endian
> correction.
>
> Hibernate can now call el2_setup() to re-configure el2, passing the
> current sctlr_el1 as an argument.
I don't fully understand the description. The first paragraph says we
can't use el2_setup to re-configure el2 after resume from hibernate
while the last paragraph says that we can.
> diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
> index a04fd7a9c102..627d66efec68 100644
> --- a/arch/arm64/include/asm/assembler.h
> +++ b/arch/arm64/include/asm/assembler.h
> @@ -311,6 +311,16 @@ lr .req x30 // link register
> .endm
>
> /*
> + * Generate the initial sctlr_el1 value for el2_setup to set if we boot at EL2.
> + */
> + .macro init_sctlr_el1 reg
> + mov \reg, #0x0800 // Set/clear RES{1,0} bits
> +CPU_BE( movk \reg, #0x33d0, lsl #16) // Set EE and E0E on BE systems
> +CPU_LE( movk \reg, #0x30d0, lsl #16) // Clear EE and E0E on LE systems
> + .endm
I can see, at least in this patch, that all places where this macro is
invoked are immediately followed by a call to el2_setup. Can we not just
place this at the beginning of el2_setup?
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index 1217262b5210..097986152203 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -208,6 +208,7 @@ section_table:
>
> ENTRY(stext)
> bl preserve_boot_args
> + init_sctlr_el1 x0
> bl el2_setup // Drop to EL1, w20=cpu_boot_mode
> mov x23, xzr // KASLR offset, defaults to 0
> adrp x24, __PHYS_OFFSET
> @@ -514,8 +515,12 @@ ENTRY(kimage_vaddr)
> *
> * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in x20 if
> * booted in EL1 or EL2 respectively.
> + *
> + * If booted in EL2, SCTLR_EL1 will be initialised with the value in x0
> + * (otherwise the existing value will be preserved, with endian correction).
> */
> ENTRY(el2_setup)
> + mov x1, x0 // preserve passed-in sctlr_el1
> mrs x0, CurrentEL
> cmp x0, #CurrentEL_EL2
> b.ne 1f
> @@ -524,7 +529,7 @@ CPU_BE( orr x0, x0, #(1 << 25) ) // Set the EE bit for EL2
> CPU_LE( bic x0, x0, #(1 << 25) ) // Clear the EE bit for EL2
> msr sctlr_el2, x0
> b 2f
> -1: mrs x0, sctlr_el1
> +1: mrs x0, sctlr_el1 // ignore passed-in sctlr_el1
> CPU_BE( orr x0, x0, #(3 << 24) ) // Set the EE and E0E bits for EL1
> CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
> msr sctlr_el1, x0
BTW, I wonder whether we need this read-modify-write sequence at all
rather than always setting a pre-set sane value (as per the
init_sctlr_el1 macro). This way we can always do this at the beginning
of el2_setup independent of whether we run in EL1 or EL2.
> @@ -578,6 +583,10 @@ set_hcr:
>
> 3:
> #endif
> + /* use sctlr_el1 value we were provided with */
> +CPU_BE( orr x1, x1, #(3 << 24) ) // Set the EE and E0E bits for EL1
> +CPU_LE( bic x1, x1, #(3 << 24) ) // Clear the EE and E0E bits for EL1
> + msr sctlr_el1, x1
I don't think we need this here, the value passed already has the EE/E0E
bits set accordingly by the init_sctlr_el1 macro.
--
Catalin
More information about the linux-arm-kernel
mailing list