Match -machine $target_arch-$machine_name against registered machine names and aliases. Also accept -machine $machine_name when it uniquely identifies a machine; report architecture-qualified choices when it is ambiguous.
This do not change single-target behavior. Signed-off-by: Yonggang Luo <[email protected]> --- system/vl.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 9 deletions(-) diff --git a/system/vl.c b/system/vl.c index e2bd65ebd40..5d6ba08b591 100644 --- a/system/vl.c +++ b/system/vl.c @@ -1205,6 +1205,77 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) return 0; } +static bool machine_target_matches(MachineClass *mc, const TargetInfo *ti, + const char *name) +{ + const char *names[] = { mc->name, mc->alias }; + + for (unsigned i = 0; i < ARRAY_SIZE(names); i++) { + if (names[i]) { + if (!strcmp(name, names[i])) { + return true; + } + g_autofree char *qualified = + g_strdup_printf("%s-%s", ti->target_name, names[i]); + + if (!strcmp(name, qualified)) { + return true; + } + } + } + return false; +} + +static MachineClass *machine_target_select(GSList *machines, GSList **targets, + const char *name, Error **errp) +{ + ERRP_GUARD(); + MachineClass *machine = NULL; + const TargetInfo *target = NULL; + g_autoptr(GString) hints = g_string_new(NULL); + unsigned count = 0; + GSList *el; + GSList *tel; + + *targets = object_class_get_list(TYPE_TARGET_INFO, false); + if (!name) { + return NULL; + } + + for (el = machines; el; el = el->next) { + MachineClass *mc = el->data; + + for (tel = *targets; tel; tel = tel->next) { + const TargetInfo *ti = TARGET_INFO_CLASS(tel->data)->target_info; + + if ((mc->targets & QEMU_ARCH_BIT(ti->target_arch)) && + machine_target_matches(mc, ti, name)) { + count++; + machine = mc; + target = ti; + g_string_append_printf(hints, " -machine %s-%s\n", + ti->target_name, mc->name); + } + } + } + if (!count) { + error_setg(errp, "unsupported machine type: \"%s\"", name); + error_append_hint(errp, "Use -machine help to list supported names, " + "then select <arch>-<machine-name> or an " + "unambiguous <machine-name>\n"); + return NULL; + } + if (count != 1) { + error_setg(errp, "machine name '%s' is ambiguous", name); + error_append_hint(errp, "Select an architecture-prefixed name:\n%s", + hints->str); + return NULL; + } + + target_info_qom_set_target_info(target); + return machine; +} + static int device_help_func(void *opaque, QemuOpts *opts, Error **errp) { return qdev_device_help(opts); @@ -1565,16 +1636,23 @@ static gint machine_class_cmp(gconstpointer a, gconstpointer b, gpointer d) static void machine_help_func(const QDict *qdict) { g_autoptr(GSList) machines = NULL; + g_autoptr(GSList) targets = NULL; GSList *el; + GSList *tel; const char *type = qdict_get_try_str(qdict, "type"); + MachineClass *machine_class = NULL; machines = object_class_get_list(TYPE_MACHINE, false); - if (type) { - ObjectClass *machine_class = OBJECT_CLASS(find_machine(type, machines)); - if (machine_class) { - type_print_class_properties(object_class_get_name(machine_class)); - return; - } + if (target_combined_binary()) { + machine_class = machine_target_select(machines, &targets, type, + &error_fatal); + } else if (type) { + machine_class = find_machine(type, machines); + } + if (machine_class) { + type_print_class_properties( + object_class_get_name(OBJECT_CLASS(machine_class))); + return; } printf("Supported machines are:\n"); @@ -1585,9 +1663,20 @@ static void machine_help_func(const QDict *qdict) printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->name); } printf("%-20s %s%s%s%s\n", mc->name, mc->desc, - mc->is_default ? " (default)" : "", + mc->is_default && !target_combined_binary() ? " (default)" : "", mc->deprecation_reason ? " (deprecated)" : "", object_class_is_secure(OBJECT_CLASS(mc)) ? " (secure)" : ""); + for (tel = targets; tel; tel = tel->next) { + const TargetInfo *ti = TARGET_INFO_CLASS(tel->data)->target_info; + + if (mc->targets & QEMU_ARCH_BIT(ti->target_arch)) { + printf(" %s-%s\n", ti->target_name, mc->name); + if (mc->alias && strcmp(mc->name, mc->alias)) { + printf(" %s-%s (alias)\n", + ti->target_name, mc->alias); + } + } + } } } @@ -1684,6 +1773,26 @@ static MachineClass *select_machine(QDict *qdict, Error **errp) g_autoptr(GSList) machines = object_class_get_list(TYPE_MACHINE, false); MachineClass *machine_class = NULL; + if (target_combined_binary()) { + g_autoptr(GSList) targets = NULL; + + if (!machine_type) { + error_setg(errp, "No machine specified; combined binaries " + "have no default machine"); + error_append_hint(errp, + "Use -machine help to list supported names, " + "then select <arch>-<machine-name> or an " + "unambiguous <machine-name>\n"); + return NULL; + } + machine_class = machine_target_select(machines, &targets, machine_type, + errp); + if (machine_class) { + qdict_del(qdict, "type"); + } + return machine_class; + } + if (machine_type) { machine_class = find_machine(machine_type, machines); if (!machine_class) { @@ -2913,10 +3022,16 @@ void qemu_init(int argc, char **argv) os_setup_limits(); target_info_qom_init(); - target_info_qom_set_target(); + if (!target_combined_binary()) { + target_info_qom_set_target(); + } module_init_info(qemu_modinfo); - module_allow_arch(target_name()); + if (target_combined_binary()) { + module_allow_all_arch(); + } else { + module_allow_arch(target_name()); + } qemu_init_subsystems(); -- 2.55.0.windows.3
