liveupdate: kho: two regression fixes

* fix order calculation for kho_unpreserve_pages() to make sure sure that
   the order calculation in kho_unpreserve_pages() mathes the order
   calculation in kho_preserve_pages().
 * fix math in calculation of KHO_TREE_MAX_DEPTH to make it work with 16KB
   pages.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEeOVYVaWZL5900a/pOQOGJssO/ZEFAmobGd4ACgkQOQOGJssO
 /ZGaRQf/a0vTak489XqXhddHkulyMnif1UEEYsltxQ8bJkC0SRx+v/PcC0Uf2g7+
 n/1vQZxWGUlLawjMDhubCWp2JawRZh9/rzPfb96z3nsjUckaQI3sKdEe7fK9jIVL
 2y2QHa26RJj7dlEcJbUToSgVbRrP8qJbiUVjo1i3ViVFsevj1gaNBo8h8oJa694z
 S1wXndBz7HYdSNuRgMc5rGUbzgVu9rl2rdTHR6ecRUfTVuQr1ZYrb7v6wi4AI3XL
 KZp6TXmDuvPikJwoWsQtBRK5VmLQxsCa5ryu4M+GEBOwezNZex29Yi2TrZWZ2KZk
 ViCFzYQLHY7RUrlhL7+tGN2SiLYKqg==
 =LtZL
 -----END PGP SIGNATURE-----

Merge tag 'liveupdate-fixes-2026-05-30' of git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux

Pull liveupdate fixes from Mike Rapoport:
 "Two kexec handover regression fixes:

   - fix order calculation for kho_unpreserve_pages() to make sure sure
     that the order calculation in kho_unpreserve_pages() mathes the
     order calculation in kho_preserve_pages().

   - fix math in calculation of KHO_TREE_MAX_DEPTH to make it work with
     16KB pages"

* tag 'liveupdate-fixes-2026-05-30' of git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux:
  kho: fix order calculation for kho_unpreserve_pages()
  kho: fix KHO_TREE_MAX_DEPTH for non-4KB page sizes
This commit is contained in:
Linus Torvalds 2026-05-30 15:39:47 -07:00
commit 9d87d0fc8c
2 changed files with 33 additions and 25 deletions

View File

@ -274,7 +274,7 @@ enum kho_radix_consts {
* and 1 bitmap level.
*/
KHO_TREE_MAX_DEPTH =
DIV_ROUND_UP(KHO_ORDER_0_LOG2 - KHO_BITMAP_SIZE_LOG2,
DIV_ROUND_UP(KHO_ORDER_0_LOG2 - KHO_BITMAP_SIZE_LOG2 + 1,
KHO_TABLE_SIZE_LOG2) + 1,
};

View File

@ -357,20 +357,6 @@ int kho_radix_walk_tree(struct kho_radix_tree *tree,
}
EXPORT_SYMBOL_GPL(kho_radix_walk_tree);
static void __kho_unpreserve(struct kho_radix_tree *tree,
unsigned long pfn, unsigned long end_pfn)
{
unsigned int order;
while (pfn < end_pfn) {
order = min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn));
kho_radix_del_page(tree, pfn, order);
pfn += 1 << order;
}
}
/* For physically contiguous 0-order pages. */
static void kho_init_pages(struct page *page, unsigned long nr_pages)
{
@ -860,6 +846,37 @@ void kho_unpreserve_folio(struct folio *folio)
}
EXPORT_SYMBOL_GPL(kho_unpreserve_folio);
static unsigned int __kho_preserve_pages_order(unsigned long start_pfn,
unsigned long end_pfn)
{
unsigned int order = min(count_trailing_zeros(start_pfn),
ilog2(end_pfn - start_pfn));
/*
* Make sure all the pages in a single preservation are in the same NUMA
* node. The restore machinery can not cope with a preservation spanning
* multiple NUMA nodes.
*/
while (pfn_to_nid(start_pfn) != pfn_to_nid(start_pfn + (1UL << order) - 1))
order--;
return order;
}
static void __kho_unpreserve(struct kho_radix_tree *tree,
unsigned long pfn, unsigned long end_pfn)
{
unsigned int order;
while (pfn < end_pfn) {
order = __kho_preserve_pages_order(pfn, end_pfn);
kho_radix_del_page(tree, pfn, order);
pfn += 1 << order;
}
}
/**
* kho_preserve_pages - preserve contiguous pages across kexec
* @page: first page in the list.
@ -885,16 +902,7 @@ int kho_preserve_pages(struct page *page, unsigned long nr_pages)
}
while (pfn < end_pfn) {
unsigned int order =
min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn));
/*
* Make sure all the pages in a single preservation are in the
* same NUMA node. The restore machinery can not cope with a
* preservation spanning multiple NUMA nodes.
*/
while (pfn_to_nid(pfn) != pfn_to_nid(pfn + (1UL << order) - 1))
order--;
unsigned int order = __kho_preserve_pages_order(pfn, end_pfn);
err = kho_radix_add_page(tree, pfn, order);
if (err) {