Skip to content

Commit d575951

Browse files
committed
x86/alternative: delay freeing of smp_locks section
On SMP systems alternative_instructions() frees memory occupied by smp_locks section immediately after patching the lock instructions. The memory is freed using free_init_pages() that calls free_reserved_area() that essentially does __free_page() for every page in the range. Up until recently it didn't update memblock state so in cases when CONFIG_ARCH_KEEP_MEMBLOCK is enabled (on x86 it is selected by INTEL_TDX_HOST), the state of memblock and the memory map would be inconsistent. Additionally, with CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled, freeing of smp_locks happens before the memory map is fully initialized and freeing reserved memory may cause an access to not-yet-initialized struct page when __free_page() searches for a buddy page. Following the discussion in [1], implementation of memblock_free_late() and free_reserved_area() was unified to ensure that reserved memory that's freed after memblock transfers the pages to the buddy allocator is actually freed and that the memblock and the memory map are consistent. As a part of these changes, free_reserved_area() now WARN()s when it is called before the initialization of the memory map is complete. The memory map is fully initialized in page_alloc_init_late() that completes before initcalls are executed, so it is safe to free reserved memory in any initcall except early_initcall(). Move freeing of smp_locks section to an initcall to ensure it will happen after the memory map is fully initialized. Since it does not matter which exactly initcall to use and the code lives in arch/, pick arch_initcall. [1] https://lore.kernel.org/all/ec2aaef14783869b3be6e3c253b2dcbf67dbc12a.camel@kernel.crashing.org Reported-By: Bert Karwatzki <spasswolf@web.de> Reported-by: kernel test robot <oliver.sang@intel.com> Closes: https://lore.kernel.org/oe-lkp/202603302154.b50adaf1-lkp@intel.com Tested-By: Bert Karwatzki <spasswolf@web.de> Link: https://lore.kernel.org/r/20260327140109.7561-1-spasswolf@web.de Acked-by: Borislav Petkov (AMD) <bp@alien8.de> Fixes: b2129a3 ("memblock: make free_reserved_area() update memblock if ARCH_KEEP_MEMBLOCK=y") Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
1 parent 59bd1d9 commit d575951

1 file changed

Lines changed: 17 additions & 5 deletions

File tree

arch/x86/kernel/alternative.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,19 +2448,31 @@ void __init alternative_instructions(void)
24482448
__smp_locks, __smp_locks_end,
24492449
_text, _etext);
24502450
}
2451+
#endif
24512452

2453+
restart_nmi();
2454+
alternatives_patched = 1;
2455+
2456+
alt_reloc_selftest();
2457+
}
2458+
2459+
#ifdef CONFIG_SMP
2460+
/*
2461+
* With CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled we can free_init_pages() only
2462+
* after the deferred initialization of the memory map is complete.
2463+
*/
2464+
static int __init free_smp_locks(void)
2465+
{
24522466
if (!uniproc_patched || num_possible_cpus() == 1) {
24532467
free_init_pages("SMP alternatives",
24542468
(unsigned long)__smp_locks,
24552469
(unsigned long)__smp_locks_end);
24562470
}
2457-
#endif
24582471

2459-
restart_nmi();
2460-
alternatives_patched = 1;
2461-
2462-
alt_reloc_selftest();
2472+
return 0;
24632473
}
2474+
arch_initcall(free_smp_locks);
2475+
#endif
24642476

24652477
/**
24662478
* text_poke_early - Update instructions on a live kernel at boot time

0 commit comments

Comments
 (0)