From: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
Add a mechanism to defer device initialization
until after the main FDT traversal.
This introduces a deferred queue in FDTMachineInfo.
Devices in this queue are processed in fdt_init_deferred(),
which handles their realization, reset registration,
and resource parsing (interrupts and memory regions).
This allows resolving initialization where devices need to
be realized on latest stages or outside of co-routine context.
Signed-off-by: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
---
hw/core/fdt_generic_util.c | 28 ++++++++++++++++++++++++++++
include/hw/core/fdt_generic.h | 8 ++++++++
2 files changed, 36 insertions(+)
diff --git a/hw/core/fdt_generic_util.c b/hw/core/fdt_generic_util.c
index c92b5c287b..ae54ada11d 100644
--- a/hw/core/fdt_generic_util.c
+++ b/hw/core/fdt_generic_util.c
@@ -93,6 +93,13 @@ static bool qemu_irq_shared_or_handler(bool *inputs, int n)
return false;
}
+static void fdt_parse_node_reg_prop(FDTMachineInfo *fdti, char *node_path,
+ Object *dev);
+static void fdt_parse_node_irq_prop(FDTMachineInfo *fdti, char *node_path,
+ Object *dev);
+static void fdt_init_device_realize(FDTMachineInfo *fdti, char *node_path,
+ Object *dev);
+
static void qemu_irq_shared_handler(void *opaque, int n, int level)
{
QEMUIRQSharedState *s = opaque;
@@ -162,6 +169,26 @@ static void fdt_init_cpu_clusters(FDTMachineInfo *fdti)
}
}
+static void fdt_init_deferred(FDTMachineInfo *fdti)
+{
+ while (fdti->deferred) {
+ FDTDeferredNode *dnode = fdti->deferred;
+
+ fdt_debug("FDT: Deferred realize node: %s\n",
+ dnode->node_path);
+
+ fdt_init_device_realize(fdti, dnode->node_path, OBJECT(dnode->dev));
+
+ fdt_parse_node_reg_prop(fdti, dnode->node_path, OBJECT(dnode->dev));
+
+ fdt_parse_node_irq_prop(fdti, dnode->node_path, OBJECT(dnode->dev));
+
+ fdti->deferred = dnode->next;
+ g_free(dnode->node_path);
+ g_free(dnode);
+ }
+}
+
FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq)
{
FDTMachineInfo *fdti = fdt_init_new_fdti(fdt);
@@ -175,6 +202,7 @@ FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq)
while (qemu_co_enter_next(fdti->cq, NULL)) {
;
}
+ fdt_init_deferred(fdti);
fdt_init_cpu_clusters(fdti);
fdt_init_all_irqs(fdti);
memory_region_transaction_commit();
diff --git a/include/hw/core/fdt_generic.h b/include/hw/core/fdt_generic.h
index 3961615a9c..2d507392fa 100644
--- a/include/hw/core/fdt_generic.h
+++ b/include/hw/core/fdt_generic.h
@@ -35,6 +35,12 @@ typedef struct FDTIRQConnection {
void *next;
} FDTIRQConnection;
+typedef struct FDTDeferredNode {
+ DeviceState *dev;
+ char *node_path;
+ void *next;
+} FDTDeferredNode;
+
typedef struct FDTMachineInfo {
/* the fdt blob */
void *fdt;
@@ -48,6 +54,8 @@ typedef struct FDTMachineInfo {
FDTIRQConnection *irqs;
/* list of all CPU clusters */
FDTCPUCluster *clusters;
+ /* list of devices for deferred init */
+ FDTDeferredNode *deferred;
} FDTMachineInfo;
/*
--
2.43.0