Message ID | 20210329142847.402167-1-pasha.tatashin@soleen.com |
---|---|
State | New |
Headers | show |
Series | [Backport,for,5.11] arm64: mm: correct the inside linear map boundaries during hotplug check | expand |
On Mon, Mar 29, 2021 at 10:28:47AM -0400, Pavel Tatashin wrote: >commit ee7febce051945be28ad86d16a15886f878204de upstream. > >Memory hotplug may fail on systems with CONFIG_RANDOMIZE_BASE because the >linear map range is not checked correctly. > >The start physical address that linear map covers can be actually at the >end of the range because of randomization. Check that and if so reduce it >to 0. > >This can be verified on QEMU with setting kaslr-seed to ~0ul: > >memstart_offset_seed = 0xffff >START: __pa(_PAGE_OFFSET(vabits_actual)) = ffff9000c0000000 >END: __pa(PAGE_END - 1) = 1000bfffffff > >Fixes: 58284a901b42 ("arm64/mm: Validate hotplug range before creating linear mapping") >Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com> >Tested-by: Tyler Hicks <tyhicks@linux.microsoft.com> >Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com> Queued up, thanks!
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 6f0648777d34..ee01f421e1e4 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1445,14 +1445,30 @@ static void __remove_pgd_mapping(pgd_t *pgdir, unsigned long start, u64 size) static bool inside_linear_region(u64 start, u64 size) { + u64 start_linear_pa = __pa(_PAGE_OFFSET(vabits_actual)); + u64 end_linear_pa = __pa(PAGE_END - 1); + + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { + /* + * Check for a wrap, it is possible because of randomized linear + * mapping the start physical address is actually bigger than + * the end physical address. In this case set start to zero + * because [0, end_linear_pa] range must still be able to cover + * all addressable physical addresses. + */ + if (start_linear_pa > end_linear_pa) + start_linear_pa = 0; + } + + WARN_ON(start_linear_pa > end_linear_pa); + /* * Linear mapping region is the range [PAGE_OFFSET..(PAGE_END - 1)] * accommodating both its ends but excluding PAGE_END. Max physical * range which can be mapped inside this linear mapping range, must * also be derived from its end points. */ - return start >= __pa(_PAGE_OFFSET(vabits_actual)) && - (start + size - 1) <= __pa(PAGE_END - 1); + return start >= start_linear_pa && (start + size - 1) <= end_linear_pa; } int arch_add_memory(int nid, u64 start, u64 size,