[PATCH 06/12] kho: allow early-boot usage of the KHO radix tree
Pratyush Yadav
pratyush at kernel.org
Wed Apr 29 06:39:08 PDT 2026
From: "Pratyush Yadav (Google)" <pratyush at kernel.org>
The KHO radix tree allocates memory for table pages from the buddy
allocator using get_zeroed_page(). This is not available in early boot
when memblock is still active.
Using the radix tree in early boot is useful for KHO to track metadata
about its memory. One such example is for tracking free blocks for
memory allocation when scratch runs out of space. This feature will be
added in the following commits.
Add kho_radix_{alloc,free}_node() which allocate and free the table
pages. They use slab_is_available() to decide which allocator to use.
While slab_is_available() indicates availability of the slab allocator,
it gets initialized right before buddy so it serves the same practical
purpose.
Signed-off-by: Pratyush Yadav (Google) <pratyush at kernel.org>
---
kernel/liveupdate/kexec_handover.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index d0a4f78eccfe..47f7c4a2865e 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -143,6 +143,26 @@ static unsigned long kho_radix_get_table_index(unsigned long key,
return (key >> s) % (1 << KHO_TABLE_SIZE_LOG2);
}
+static void __ref *kho_radix_alloc_node(void)
+{
+ struct kho_radix_node *node;
+
+ if (slab_is_available())
+ node = (struct kho_radix_node *)get_zeroed_page(GFP_KERNEL);
+ else
+ node = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+
+ return node;
+}
+
+static void __ref kho_radix_free_node(struct kho_radix_node *node)
+{
+ if (slab_is_available())
+ free_page((unsigned long)node);
+ else
+ memblock_free(node, PAGE_SIZE);
+}
+
/**
* kho_radix_add_key - Add a key to the radix tree.
* @tree: The KHO radix tree.
@@ -183,7 +203,7 @@ int kho_radix_add_key(struct kho_radix_tree *tree, unsigned long key)
}
/* Next node is empty, create a new node for it */
- new_node = (struct kho_radix_node *)get_zeroed_page(GFP_KERNEL);
+ new_node = kho_radix_alloc_node();
if (!new_node) {
err = -ENOMEM;
goto err_free_nodes;
@@ -214,7 +234,7 @@ int kho_radix_add_key(struct kho_radix_tree *tree, unsigned long key)
err_free_nodes:
for (i = KHO_TREE_MAX_DEPTH - 1; i > 0; i--) {
if (intermediate_nodes[i])
- free_page((unsigned long)intermediate_nodes[i]);
+ kho_radix_free_node(intermediate_nodes[i]);
}
if (anchor_node)
anchor_node->table[anchor_idx] = 0;
--
2.54.0.545.g6539524ca2-goog
More information about the kexec
mailing list