Skip to content

Commit 0aaa685

Browse files
ardbiesheuvelwilldeacon
authored andcommitted
arm64: mm: fix booting with 52-bit address space
Joey reports that booting 52-bit VA capable builds on 52-bit VA capable CPUs is broken since commit 0d9b1ff ("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(). To ensure that all users of vabits_actual (including kasan_early_init()) observe the correct value, move the assignment of vabits_actual back into asm code, but still defer it to after the MMU and caches have been enabled. Cc: Will Deacon <[email protected]> Cc: Anshuman Khandual <[email protected]> Cc: Mark Rutland <[email protected]> Fixes: 0d9b1ff ("arm64: mm: make vabits_actual a build time constant if possible") Reported-by: Joey Gouly <[email protected]> Co-developed-by: Joey Gouly <[email protected]> Signed-off-by: Joey Gouly <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent bdbcd22 commit 0aaa685

File tree

3 files changed

+22
-16
lines changed

3 files changed

+22
-16
lines changed

arch/arm64/kernel/head.S

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
* x22 create_idmap() .. start_kernel() ID map VA of the DT blob
8383
* x23 primary_entry() .. start_kernel() physical misalignment/KASLR offset
8484
* x24 __primary_switch() linear map KASLR seed
85+
* x25 primary_entry() .. start_kernel() supported VA size
8586
* x28 create_idmap() callee preserved temp register
8687
*/
8788
SYM_CODE_START(primary_entry)
@@ -96,6 +97,14 @@ SYM_CODE_START(primary_entry)
9697
* On return, the CPU will be ready for the MMU to be turned on and
9798
* the TCR will have been set.
9899
*/
100+
#if VA_BITS > 48
101+
mrs_s x0, SYS_ID_AA64MMFR2_EL1
102+
tst x0, #0xf << ID_AA64MMFR2_LVA_SHIFT
103+
mov x0, #VA_BITS
104+
mov x25, #VA_BITS_MIN
105+
csel x25, x25, x0, eq
106+
mov x0, x25
107+
#endif
99108
bl __cpu_setup // initialise processor
100109
b __primary_switch
101110
SYM_CODE_END(primary_entry)
@@ -434,6 +443,12 @@ SYM_FUNC_START_LOCAL(__primary_switched)
434443
bl __pi_memset
435444
dsb ishst // Make zero page visible to PTW
436445

446+
#if VA_BITS > 48
447+
adr_l x8, vabits_actual // Set this early so KASAN early init
448+
str x25, [x8] // ... observes the correct value
449+
dc civac, x8 // Make visible to booting secondaries
450+
#endif
451+
437452
#ifdef CONFIG_RANDOMIZE_BASE
438453
adrp x5, memstart_offset_seed // Save KASLR linear map seed
439454
strh w24, [x5, :lo12:memstart_offset_seed]
@@ -579,6 +594,9 @@ SYM_FUNC_START_LOCAL(secondary_startup)
579594
mov x20, x0 // preserve boot mode
580595
bl switch_to_vhe
581596
bl __cpu_secondary_check52bitva
597+
#if VA_BITS > 48
598+
ldr_l x0, vabits_actual
599+
#endif
582600
bl __cpu_setup // initialise processor
583601
adrp x1, swapper_pg_dir
584602
adrp x2, idmap_pg_dir

arch/arm64/mm/init.c

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -265,20 +265,7 @@ early_param("mem", early_mem);
265265

266266
void __init arm64_memblock_init(void)
267267
{
268-
s64 linear_region_size;
269-
270-
#if VA_BITS > 48
271-
if (cpuid_feature_extract_unsigned_field(
272-
read_sysreg_s(SYS_ID_AA64MMFR2_EL1),
273-
ID_AA64MMFR2_LVA_SHIFT))
274-
vabits_actual = VA_BITS;
275-
276-
/* make the variable visible to secondaries with the MMU off */
277-
dcache_clean_inval_poc((u64)&vabits_actual,
278-
(u64)&vabits_actual + sizeof(vabits_actual));
279-
#endif
280-
281-
linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual);
268+
s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual);
282269

283270
/*
284271
* Corner case: 52-bit VA capable systems running KVM in nVHE mode may

arch/arm64/mm/proc.S

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ SYM_FUNC_END(idmap_kpti_install_ng_mappings)
397397
*
398398
* Initialise the processor for turning the MMU on.
399399
*
400+
* Input:
401+
* x0 - actual number of VA bits (ignored unless VA_BITS > 48)
400402
* Output:
401403
* Return in x0 the value of the SCTLR_EL1 register.
402404
*/
@@ -466,8 +468,7 @@ SYM_FUNC_START(__cpu_setup)
466468
tcr_clear_errata_bits tcr, x9, x5
467469

468470
#ifdef CONFIG_ARM64_VA_BITS_52
469-
ldr_l x9, vabits_actual
470-
sub x9, xzr, x9
471+
sub x9, xzr, x0
471472
add x9, x9, #64
472473
tcr_set_t1sz tcr, x9
473474
#else

0 commit comments

Comments
 (0)