From cd91b44b57870de2b39714c47d0c492b74773c35 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 24 Aug 2026 11:51:45 +0200 Subject: [PATCH] radix-tree: drop radix_tree_init_maxindex() Radix trees are in principle usable as soon as memory allocation works. (Radix trees with only index 0 populated are usable even earlier.) If only there wasn't height_to_maxindex[], which is filled only by a pre-SMP initcall. The benefit of this array is rather limited - the calculations done by __maxindex() can as well be done by radix_tree_maxindex(); the overhead isn't all this high. This was found by UBSAN on a multi-segment system: (XEN) UBSAN: Undefined behaviour in common/radix-tree.c:83:27 (XEN) index 12 is out of range for type 'long unsigned int [12]' ... (XEN) Xen call trace: (XEN) [] R common/ubsan/ubsan.c#ubsan_epilogue+0xa/0xd5 (XEN) [] F __ubsan_handle_out_of_bounds+0x9d/0xd4 (XEN) [] F radix_tree_insert+0x24d/0x570 (XEN) [] F drivers/passthrough/pci.c#alloc_pseg+0xc4/0x165 (XEN) [] F pci_add_segment+0xc/0x1b (XEN) [] F acpi_parse_mcfg+0x29b/0x344 (XEN) [] F acpi_table_parse+0x5d/0x92 (XEN) [] F acpi_mmcfg_init+0x3a2/0x71d (XEN) [] F pci_setup+0x17/0x29 (XEN) [] F __start_xen+0x394c/0x4ed8 (XEN) [] F __high_start+0xb7/0xb8 Fixes: 21844b0e32e7 ("PCI multi-seg: introduce notion of PCI segments") Fixes: 8dc6738dbb3c ("Update radix-tree.[ch] from upstream Linux to gain RCU awareness") Reported-by: Andrew Cooper Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper master commit: 1077a93425d2dcca894883cf8565ee9ecf1672cc master date: 2026-08-05 12:00:17 +0200 --- xen/common/radix-tree.c | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/xen/common/radix-tree.c b/xen/common/radix-tree.c index ca610d36fc..bc1e8d0c04 100644 --- a/xen/common/radix-tree.c +++ b/xen/common/radix-tree.c @@ -32,12 +32,6 @@ struct radix_tree_path { #define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \ RADIX_TREE_MAP_SHIFT)) -/* - * The height_to_maxindex array needs to be one deeper than the maximum - * path as height 0 holds only 1 entry. - */ -static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH + 1] __read_mostly; - static inline void *ptr_to_indirect(void *ptr) { return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR); @@ -80,7 +74,16 @@ static void radix_tree_node_free(struct radix_tree_node *node) */ static inline unsigned long radix_tree_maxindex(unsigned int height) { - return height_to_maxindex[height]; + unsigned int width = height * RADIX_TREE_MAP_SHIFT; + int shift = RADIX_TREE_INDEX_BITS - width; + + if (shift < 0) + return ~0UL; + + if (shift >= BITS_PER_LONG) + return 0UL; + + return ~0UL >> shift; } /* @@ -705,27 +708,3 @@ void radix_tree_init(struct radix_tree_root *root) { *root = (struct radix_tree_root)RADIX_TREE_INIT(); } - -static __init unsigned long __maxindex(unsigned int height) -{ - unsigned int width = height * RADIX_TREE_MAP_SHIFT; - int shift = RADIX_TREE_INDEX_BITS - width; - - if (shift < 0) - return ~0UL; - if (shift >= BITS_PER_LONG) - return 0UL; - return ~0UL >> shift; -} - -static int __init cf_check radix_tree_init_maxindex(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++) - height_to_maxindex[i] = __maxindex(i); - - return 0; -} -/* pre-SMP just so it runs before 'normal' initcalls */ -presmp_initcall(radix_tree_init_maxindex);