From: Ruslan Ruslichenko <[email protected]> The path add possibility to bind to QEMU block backends via the blockdev-node-name property.
This enables support for the modern -blockdev command line option. Signed-off-by: Ruslan Ruslichenko <[email protected]> --- hw/core/fdt_generic_util.c | 82 ++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/hw/core/fdt_generic_util.c b/hw/core/fdt_generic_util.c index 4ed9602d47..68dfeee096 100644 --- a/hw/core/fdt_generic_util.c +++ b/hw/core/fdt_generic_util.c @@ -75,6 +75,8 @@ static void fdt_get_irq_info_from_intc(FDTMachineInfo *fdti, qemu_irq *ret, char *intc_node_path, uint32_t *cells, uint32_t num_cells, uint32_t max, Error **errp); +static bool fdt_attach_blockdev(FDTMachineInfo *fdti, + const char *node_path, Object *dev); typedef struct QEMUIRQSharedState { qemu_irq sink; @@ -241,6 +243,8 @@ FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq) current_machine->smp.cpus = fdt_generic_num_cpus; current_machine->smp.max_cpus = fdt_generic_num_cpus; + bdrv_drain_all(); + DB_PRINT(0, "FDT: Device tree scan complete\n"); return fdti; } @@ -987,6 +991,52 @@ static void fdt_init_qdev_array_prop(Object *obj, DB_PRINT_NP(0, "set property %s propname to <list>\n", propname); } +/* + * Try to attach by matching drive created by '-blockdev node-name=LABEL' + * iff the FDT node contains property 'blockdev-node-name=LABEL'. + * + * Return false unless the given node_path has the property. + * + * Presence of the property also disables the node from ever attached + * to any drive created by the legacy '-drive' QEMU option. + * + * For more on '-blockdev', see: + * http://events17.linuxfoundation.org/sites/events/files/slides/talk_11.pdf + */ +static bool fdt_attach_blockdev(FDTMachineInfo *fdti, + const char *node_path, Object *dev) +{ + static const char propname[] = "blockdev-node-name"; + const char *label; + + /* Inspect FDT node for blockdev-only binding */ + label = qemu_fdt_getprop(fdti->fdt, node_path, propname, + NULL, NULL); + + /* Skip legacy node */ + if (!label) { + return false; + } + + /* + * Missing matching bdev is not an error: attachment is optional. + * + * error_setg() aborts, never returns: 'goto ret' is just sanity. + */ + if (!label[0]) { + error_setg(&error_abort, "FDT-node '%s': property '%s' = <empty>", + node_path, propname); + return false; + } + + if (!bdrv_find_node(label)) { + return false; + } + + object_property_set_str(OBJECT(dev), "drive", label, NULL); + return true; +} + static void fdt_parse_node_reg_prop(FDTMachineInfo *fdti, char *node_path, Object *dev) { @@ -1173,6 +1223,7 @@ static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat) char *dev_type = NULL; QEMUDevtreeProp *prop, *props; char parent_node_path[DT_PATH_LENGTH]; + bool defer_realize = false; if (!compat) { return 1; @@ -1289,6 +1340,11 @@ static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat) continue; } + if (!strcmp(propname, "drive")) { + defer_realize = true; + continue; + } + fdt_init_qdev_scalar_prop(OBJECT(dev), p, fdti, node_path, prop); } @@ -1307,18 +1363,30 @@ static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat) */ fdt_init_register_user_cpu_cluster(fdti, OBJECT(dev)); } else { - object_property_set_bool(OBJECT(dev), "realized", true, - &error_fatal); - if (dc->legacy_reset) { - qemu_register_reset((void (*)(void *))dc->legacy_reset, - dev); + if (defer_realize) { + FDTDeferredNode *dnode = g_new0(FDTDeferredNode, 1); + *dnode = (FDTDeferredNode) { + .dev = DEVICE(dev), + .node_path = g_strdup(node_path), + .next = fdti->deferred + }; + fdti->deferred = dnode; + } else { + object_property_set_bool(OBJECT(dev), "realized", true, + &error_fatal); + if (dc->legacy_reset) { + qemu_register_reset((void (*)(void *))dc->legacy_reset, + dev); + } } } } - fdt_parse_node_reg_prop(fdti, node_path, dev); + if (!defer_realize) { + fdt_parse_node_reg_prop(fdti, node_path, dev); - fdt_parse_node_irq_prop(fdti, node_path, dev); + fdt_parse_node_irq_prop(fdti, node_path, dev); + } g_free(dev_type); g_free(props); -- 2.43.0
