mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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) [<ffff82d040323f9c>] R common/ubsan/ubsan.c#ubsan_epilogue+0xa/0xd5 (XEN) [<ffff82d040324d91>] F __ubsan_handle_out_of_bounds+0x9d/0xd4 (XEN) [<ffff82d04029265a>] F radix_tree_insert+0x24d/0x570 (XEN) [<ffff82d04037ac3e>] F drivers/passthrough/pci.c#alloc_pseg+0xc4/0x165 (XEN) [<ffff82d040a3b526>] F pci_add_segment+0xc/0x1b (XEN) [<ffff82d040a5ad1b>] F acpi_parse_mcfg+0x29b/0x344 (XEN) [<ffff82d040a3f612>] F acpi_table_parse+0x5d/0x92 (XEN) [<ffff82d040a5bf55>] F acpi_mmcfg_init+0x3a2/0x71d (XEN) [<ffff82d040a71ba6>] F pci_setup+0x17/0x29 (XEN) [<ffff82d040a784d0>] F __start_xen+0x394c/0x4ed8 (XEN) [<ffff82d040423057>] F __high_start+0xb7/0xb8 Fixes:21844b0e32("PCI multi-seg: introduce notion of PCI segments") Fixes:8dc6738dbb("Update radix-tree.[ch] from upstream Linux to gain RCU awareness") Reported-by: Andrew Cooper <andrew.cooper3@citrix.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> master commit:1077a93425master date: 2026-08-05 12:00:17 +0200
This commit is contained in:
1 parent
fc203d45b6
commit
cd91b44b57
1 file changed
+10
-31
+10
-31
@@ -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);
|
||||