[PATCH v3 02/21] kho: make radix max key width more obvious
From: Pratyush Yadav
Date: Thu Jul 09 2026 - 13:39:18 EST
From: "Pratyush Yadav (Google)" <pratyush@xxxxxxxxxx>
The KHO radix tree constants are somewhat hard to understand. The tree
depth essentially comes from the max key width. The max key width comes
from the need to store a 52-bit PFN plus one more bit for the order.
All this is very obscure with the corrent code. The PFN width is defined
as KHO_ORDER_0_LOG2, which makes very little sense to a new reader not
already familiar with what the value means. Then the fact that an extra
bit is needed is hidden in the KHO_TREE_MAX_DEPTH calculation.
Simplify this by removing KHO_ORDER_0_LOG2 and replace it with
KHO_RADIX_KEY_WIDTH. Update the comment to explain why this value is
used. This moves the +1 from KHO_TREE_MAX_DEPTH to KHO_RADIX_KEY_WIDTH,
making things clearer.
Update kho_{encode,decode}_radix_key() to not use KHO_ORDER_0_LOG2.
Instead, refactor the code and comments to make it clearer how the
encoding and decoding is done.
In kho_encode_radix_key(), add a new variable for the shift for phys.
Use that in calculating where the order bit goes and in calculating the
shifted PFN. Update comments to make this clearer.
In kho_radix_decode_key(), turn order_bit to 0-indexed to simplify the
eventual calculation for order. Touch up comments to make the
computation clearer.
Signed-off-by: Pratyush Yadav (Google) <pratyush@xxxxxxxxxx>
---
include/linux/kho/abi/kexec_handover.h | 9 +++------
kernel/liveupdate/kexec_handover.c | 19 +++++++++++--------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/include/linux/kho/abi/kexec_handover.h b/include/linux/kho/abi/kexec_handover.h
index 5e2eb8519bda..2f4fb9c63942 100644
--- a/include/linux/kho/abi/kexec_handover.h
+++ b/include/linux/kho/abi/kexec_handover.h
@@ -257,11 +257,8 @@ struct kho_vmalloc {
* memory. These constants govern the indexing, sizing, and depth of the tree.
*/
enum kho_radix_consts {
- /*
- * The bit position of the order bit (and also the length of the
- * shifted physical address) for an order-0 page.
- */
- KHO_ORDER_0_LOG2 = 64 - PAGE_SHIFT,
+ /* Need to store the PFN, plus one bit for order. */
+ KHO_RADIX_KEY_WIDTH = 64 - PAGE_SHIFT + 1,
/* Size of the table in kho_radix_node, in log2 */
KHO_TABLE_SIZE_LOG2 = const_ilog2(PAGE_SIZE / sizeof(phys_addr_t)),
@@ -274,7 +271,7 @@ enum kho_radix_consts {
* and 1 bitmap level.
*/
KHO_TREE_MAX_DEPTH =
- DIV_ROUND_UP(KHO_ORDER_0_LOG2 - KHO_BITMAP_SIZE_LOG2 + 1,
+ DIV_ROUND_UP(KHO_RADIX_KEY_WIDTH - KHO_BITMAP_SIZE_LOG2,
KHO_TABLE_SIZE_LOG2) + 1,
};
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 7349cc82f6dc..ea24f23ce292 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -97,10 +97,12 @@ static struct kho_out kho_out = {
*/
static unsigned long kho_encode_radix_key(phys_addr_t phys, unsigned int order)
{
- /* Order bits part */
- unsigned long h = 1UL << (KHO_ORDER_0_LOG2 - order);
- /* Shifted physical address part */
- unsigned long l = phys >> (PAGE_SHIFT + order);
+ /* The physical address is encoded by shifting the PFN by its order. */
+ unsigned long shift = PAGE_SHIFT + order;
+ /* Order bit goes right before the shifted PFN. */
+ unsigned long h = 1UL << (64 - shift);
+ /* Shifted PFN. */
+ unsigned long l = phys >> shift;
return h | l;
}
@@ -118,12 +120,13 @@ static unsigned long kho_encode_radix_key(phys_addr_t phys, unsigned int order)
*/
static phys_addr_t kho_decode_radix_key(unsigned long key, unsigned int *order)
{
- unsigned int order_bit = fls64(key);
+ /* fls64() indexes starting from 1. */
+ unsigned int order_bit = fls64(key) - 1;
phys_addr_t phys;
- /* order_bit is numbered starting at 1 from fls64 */
- *order = KHO_ORDER_0_LOG2 - order_bit + 1;
- /* The order is discarded by the shift */
+ /* order bit goes right before the shifted PFN. */
+ *order = 64 - (PAGE_SHIFT + order_bit);
+ /* The order bit is discarded by the shift */
phys = key << (PAGE_SHIFT + *order);
return phys;
--
2.55.0.141.g00534a21ce-goog