[PATCH v2] arm64: mm: fix booting with 52-bit address space

Anshuman Khandual anshuman.khandual at arm.com
Thu Jun 30 20:29:51 PDT 2022



On 6/30/22 19:37, Ard Biesheuvel wrote:
> Joey reports that booting 52-bit VA capable builds on 52-bit VA capable
> CPUs is broken since commit 0d9b1ffefabe ("arm64: mm: make vabits_actual
> a build time constant if possible"). This is due to the fact that the
> primary CPU reads the vabits_actual variable before it has been
> assigned.
> 
> The reason for deferring the assignment of vabits_actual was that we try
> to perform as few stores to memory as we can with the MMU and caches
> off, due to the cache coherency issues it creates.
> 
> Since __cpu_setup() [which is where the read of vabits_actual occurs] is
> also called on the secondary boot path, we cannot just read the CPU ID
> registers directly, given that the size of the VA space is decided by
> the capabilities of the primary CPU. So let's read vabits_actual only on
> the secondary boot path, and read the CPU ID registers directly on the
> primary boot path, by making it a function parameter of __cpu_setup().
> 
> Cc: Will Deacon <will at kernel.org>
> Cc: Anshuman Khandual <anshuman.khandual at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Fixes: 0d9b1ffefabe ("arm64: mm: make vabits_actual a build time constant if possible")
> Reported-by: Joey Gouly <joey.gouly at arm.com>
> Co-developed-by: Joey Gouly <joey.gouly at arm.com>
> Signed-off-by: Joey Gouly <joey.gouly at arm.com>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>

Tested-by: Anshuman Khandual <anshuman.khandual at arm.com>

> ---
> This is a follow-up to Joey's v1, after discussing over IRC
> 
> https://lore.kernel.org/linux-arm-kernel/20220630110016.31441-1-joey.gouly@arm.com/
> 
>  arch/arm64/kernel/head.S | 10 ++++++++++
>  arch/arm64/mm/proc.S     |  5 +++--
>  2 files changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index cea86b982e6a..ad67386df598 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -107,6 +107,13 @@ SYM_CODE_START(primary_entry)
>  	 * On return, the CPU will be ready for the MMU to be turned on and
>  	 * the TCR will have been set.
>  	 */
> +#if VA_BITS > 48
> +	mrs_s	x0, SYS_ID_AA64MMFR2_EL1
> +	tst	x0, #0xf << ID_AA64MMFR2_LVA_SHIFT
> +	mov	x0, #VA_BITS_MIN
> +	mov	x1, #VA_BITS
> +	csel	x0, x0, x1, eq
> +#endif
>  	bl	__cpu_setup			// initialise processor
>  	b	__primary_switch
>  SYM_CODE_END(primary_entry)
> @@ -587,6 +594,9 @@ SYM_FUNC_START_LOCAL(secondary_startup)
>  	mov	x20, x0				// preserve boot mode
>  	bl	switch_to_vhe
>  	bl	__cpu_secondary_check52bitva
> +#if VA_BITS > 48
> +	ldr_l	x0, vabits_actual
> +#endif
>  	bl	__cpu_setup			// initialise processor
>  	adrp	x1, swapper_pg_dir
>  	adrp	x2, idmap_pg_dir
> diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
> index 5d6c494070d1..656c78f82a17 100644
> --- a/arch/arm64/mm/proc.S
> +++ b/arch/arm64/mm/proc.S
> @@ -397,6 +397,8 @@ SYM_FUNC_END(idmap_kpti_install_ng_mappings)
>   *
>   *	Initialise the processor for turning the MMU on.
>   *
> + * Input:
> + *	x0 - actual number of VA bits (ignored unless VA_BITS > 48)
>   * Output:
>   *	Return in x0 the value of the SCTLR_EL1 register.
>   */
> @@ -466,8 +468,7 @@ SYM_FUNC_START(__cpu_setup)
>  	tcr_clear_errata_bits tcr, x9, x5
>  
>  #ifdef CONFIG_ARM64_VA_BITS_52
> -	ldr_l		x9, vabits_actual
> -	sub		x9, xzr, x9
> +	sub		x9, xzr, x0
>  	add		x9, x9, #64
>  	tcr_set_t1sz	tcr, x9
>  #else



More information about the linux-arm-kernel mailing list