xen/dom0less: introduce next_phandle in struct kernel_info

There are cases where it is necessary to know the next available phandle
number in order to generate phandles for guest device nodes.

When a partial FDT (pfdt) is provided, special care is needed during
initialization of next_phandle, as the pfdt may already contain a dummy
interrupt controller node with a phandle assigned to it. next_phandle
must therefore be initialized to one past the highest phandle already
present in the pfdt, to avoid collisions.

Since next_phandle may be needed for the very first guest node generated,
domain_handle_dtb_boot_module() is moved earlier in prepare_dtb_domU().
The new call site also aligns better with the existing comment stating
that domain_handle_dtb_boot_module() must be called before the rest of
the device tree is generated.

Introduce alloc_phandle() to ensure that phandles allocated for guest
nodes do not overlap the Xen-reserved phandle range.  This helper will
be used by subsequent patches (by RISC-V at the moment).

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
This commit is contained in:
Oleksii Kurochko authored and Michal Orzel committed 2026-04-29 07:39:07 +02:00
1 parent 16579c5503
commit a010efd323
3 files changed
+43 -12

No files matched your search

+31 -12
View File
@@ -389,6 +389,24 @@ static int __init domain_handle_dtb_boot_module(struct domain *d,
if ( res < 0 )
goto out;
/*
* Find the highest phandle in the partial FDT so next_phandle starts
* above it, avoiding collisions with pfdt's own phandle assignments.
*/
res = fdt_generate_phandle(pfdt, &kinfo->next_phandle);
if ( res )
{
res = (res == -FDT_ERR_NOPHANDLES) ? -EOVERFLOW : -EINVAL;
goto out;
}
if ( kinfo->next_phandle >= GUEST_PHANDLE_GIC )
{
dprintk(XENLOG_ERR, "Phandle allocation overlaps Xen reserved range\n");
res = -EOVERFLOW;
goto out;
}
for ( node_next = fdt_first_subnode(pfdt, 0);
node_next > 0;
node_next = fdt_next_subnode(pfdt, node_next) )
@@ -459,6 +477,7 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
BUILD_BUG_ON(DOMU_DTB_SIZE > SZ_2M);
kinfo->phandle_intc = GUEST_PHANDLE_GIC;
kinfo->next_phandle = 1;
#ifdef CONFIG_GRANT_TABLE
kinfo->gnttab_start = GUEST_GNTTAB_BASE;
@@ -499,6 +518,18 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
if ( ret )
goto err;
/*
* domain_handle_dtb_boot_module() must be called before the rest of the
* device tree is generated because it sets phandle_intc and next_phandle,
* which subsequent node generation depends on.
*/
if ( kinfo->dtb )
{
ret = domain_handle_dtb_boot_module(d, kinfo);
if ( ret )
goto err;
}
ret = make_chosen_node(kinfo);
if ( ret )
goto err;
@@ -516,18 +547,6 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
if ( ret )
goto err;
/*
* domain_handle_dtb_boot_module has to be called before the rest of
* the device tree is generated because it depends on the value of
* the field phandle_intc.
*/
if ( kinfo->dtb )
{
ret = domain_handle_dtb_boot_module(d, kinfo);
if ( ret )
goto err;
}
ret = make_intc_domU_node(kinfo);
if ( ret )
goto err;
+6
View File
@@ -63,6 +63,12 @@ int find_unallocated_memory(const struct kernel_info *kinfo,
unsigned long e_gfn,
void *data));
/* Return 0 (invalid phandle) if the Xen-reserved range has been reached */
static inline uint32_t alloc_phandle(struct kernel_info *kinfo)
{
return kinfo->next_phandle >= GUEST_PHANDLE_GIC ? 0 : kinfo->next_phandle++;
}
#endif /* __XEN_FDT_DOMAIN_BUILD_H__ */
/*
+6
View File
@@ -44,6 +44,12 @@ struct kernel_info {
/* Interrupt controller phandle */
uint32_t phandle_intc;
/*
* Next free phandle for guest device nodes; do not access directly, use
* alloc_phandle().
*/
uint32_t next_phandle;
/* loader to use for this kernel */
void (*load)(struct kernel_info *info);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.