mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
16579c5503
commit
a010efd323
3 files changed
+43
-12
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||