From nobody Mon Jul 7 04:22:09 2025 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 16233324165481006.635569171571; Thu, 10 Jun 2021 06:40:16 -0700 (PDT) Received: from localhost ([::1]:57494 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lrKut-0001mL-BG for importer2@patchew.org; Thu, 10 Jun 2021 09:40:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47486) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lrKqd-0001bm-Nd for qemu-devel@nongnu.org; Thu, 10 Jun 2021 09:35:51 -0400 Received: from mail-wr1-x429.google.com ([2a00:1450:4864:20::429]:42735) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lrKqW-0005dh-TA for qemu-devel@nongnu.org; Thu, 10 Jun 2021 09:35:47 -0400 Received: by mail-wr1-x429.google.com with SMTP id c5so2349074wrq.9 for ; Thu, 10 Jun 2021 06:35:44 -0700 (PDT) Received: from avogadro.redhat.com ([2001:b07:6468:f312:63a7:c72e:ea0e:6045]) by smtp.gmail.com with ESMTPSA id v8sm4032519wrc.29.2021.06.10.06.35.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jun 2021 06:35:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=QSwUNkz7C/UE/bqWbkhtH7ZO8Rrhf/r+2D/bB3t4bOs=; b=Vl39U09vyKe/LrRNiRRsDcm6AnMrppgjBOqsp5M/4XRiJhBRQT/OT76SgvZwG/Ztoq guph3PDa0QY3ihDL1NQ1uDaHTUKjTLcLu1Jj1sID0CnuiR7qMHpcc4OdLczn8125zu3N 6Vlu2OxXhvlTeyo1l+FqNjG2mzd/GOz8FPCDQw4iaOG32ycK7K8LpKrit0y6Yzamz/Jf 0DLC4D/dUPxzwZwrsfr8KZfH/7nPgzWA6oN4vn6pgjund1kTyra/xC0u7pINoi5ERVu+ 7YsUAZ6WrdmR4OR1rwrDwF7gZfEYVgB6cUNwcbsaMMJFkyiOdhE+/zVwkxzEC/uJcCnX cBxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=QSwUNkz7C/UE/bqWbkhtH7ZO8Rrhf/r+2D/bB3t4bOs=; b=r/I/bvmhGz756DaOgwijjbCVgA3i5HVgai5DYmVkcx80wNENtQa7Ye1AHEKGVQL4g/ TYYipCblBWmlhoBAHBBrlBLY4e/IfuCuUoaRUR+3QUta0x2l0jD5QsSym0djEwVLIlzb Ivfmy3JrTZ4bMGx2VJJhDpVZLMi8X/xnBoeuIyGNWv7reSDSZJlQ2vVxxWKo0ABIbe+r KULCVvfsayslv9hiatL5i/X6XGKI8d+WKjB+mxn3SE4RoeMH4Uw0pKqyBL9tzsReL5cq cJGALm4SBTL//wxw6R6HRdsVPKFluxskTwmvNTPrPCg4HG/1QP5Ml9TaUpnH5nvN/d3E IU2A== X-Gm-Message-State: AOAM532WgKz5kHHu6CuRd5q60lwqsYuqujBnIymDM594khRldPwgeREh AgbqcMgH8VDTOqGzvOsbK3G0XG2PpFbjDw== X-Google-Smtp-Source: ABdhPJwRytIVWCnugUnhSUGAduz0prJ9ZNPD5ZgUMl3Dj3llFaaL/7xJK6e1it01q+IarWxnHPgW0Q== X-Received: by 2002:a5d:5182:: with SMTP id k2mr5476978wrv.381.1623332143441; Thu, 10 Jun 2021 06:35:43 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Subject: [PATCH 04/11] vl: switch -M parsing to keyval Date: Thu, 10 Jun 2021 15:35:31 +0200 Message-Id: <20210610133538.608390-5-pbonzini@redhat.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210610133538.608390-1-pbonzini@redhat.com> References: <20210610133538.608390-1-pbonzini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::429; envelope-from=paolo.bonzini@gmail.com; helo=mail-wr1-x429.google.com X-Spam_score_int: -14 X-Spam_score: -1.5 X-Spam_bar: - X-Spam_report: (-1.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.249, FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: berrange@redhat.com, armbru@redhat.com Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Switch from QemuOpts to keyval. This enables the introduction of non-scalar machine properties, and JSON syntax in the future. For JSON syntax to be supported right now, we would have to consider what would happen if string-based dictionaries (produced by -M key=3Dval) were to be merged with strongly-typed dictionaries (produced by -M {'key': 123}). The simplest way out is to never enter the situation, and only allow one -M option when JSON syntax is in use. However, we want options such as -smp to become syntactic sugar for -M, and this is a problem; as soon as -smp becomes a shortcut for -M, QEMU would forbid using -M '{....}' together with -smp. Therefore, allowing JSON syntax right now for -M would be a forward-compatibility nightmare and it would be impossible anyway to introduce -M incrementally in tools. Instead, support for JSON syntax is delayed until after the main options are converted to QOM compound properties. These include -boot, -acpitable, -smbios, -m, -semihosting-config, -rtc and -fw_cfg. Once JSON syntax is introduced, these options will _also_ be forbidden together with -M '{...}'. Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 303 ++++++++++++++++++++++++--------------------------- 1 file changed, 140 insertions(+), 163 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index feb4d201f3..01bcb16560 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -145,6 +145,8 @@ static const char *cpu_option; static const char *mem_path; static const char *incoming; static const char *loadvm; +static const char *accelerators; +static QDict *machine_opts_dict; static QTAILQ_HEAD(, ObjectOption) object_opts =3D QTAILQ_HEAD_INITIALIZER= (object_opts); static ram_addr_t maxram_size; static uint64_t ram_slots; @@ -235,21 +237,6 @@ static QemuOptsList qemu_option_rom_opts =3D { }, }; =20 -static QemuOptsList qemu_machine_opts =3D { - .name =3D "machine", - .implied_opt_name =3D "type", - .merge_lists =3D true, - .head =3D QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head), - .desc =3D { - /* - * no elements =3D> accept any - * sanity checking will happen later - * when setting machine properties - */ - { } - }, -}; - static QemuOptsList qemu_accel_opts =3D { .name =3D "accel", .implied_opt_name =3D "accel", @@ -498,16 +485,6 @@ static QemuOptsList qemu_action_opts =3D { }, }; =20 -/** - * Get machine options - * - * Returns: machine options (never null). - */ -static QemuOpts *qemu_get_machine_opts(void) -{ - return qemu_find_opts_singleton("machine"); -} - const char *qemu_get_vm_name(void) { return qemu_name; @@ -815,33 +792,6 @@ static MachineClass *find_default_machine(GSList *mach= ines) return default_machineclass; } =20 -static int machine_help_func(QemuOpts *opts, MachineState *machine) -{ - ObjectProperty *prop; - ObjectPropertyIterator iter; - - if (!qemu_opt_has_help_opt(opts)) { - return 0; - } - - object_property_iter_init(&iter, OBJECT(machine)); - while ((prop =3D object_property_iter_next(&iter))) { - if (!prop->set) { - continue; - } - - printf("%s.%s=3D%s", MACHINE_GET_CLASS(machine)->name, - prop->name, prop->type); - if (prop->description) { - printf(" (%s)\n", prop->description); - } else { - printf("\n"); - } - } - - return 1; -} - static void version(void) { printf("QEMU emulator version " QEMU_FULL_VERSION "\n" @@ -1546,33 +1496,31 @@ static gint machine_class_cmp(gconstpointer a, gcon= stpointer b) object_class_get_name(OBJECT_CLASS(mc1))); } =20 -static MachineClass *machine_parse(const char *name, GSList *machines) +static void machine_help_func(const QDict *qdict) { - MachineClass *mc; - GSList *el; + GSList *machines, *el; + const char *type =3D qdict_get_try_str(qdict, "type"); =20 - if (is_help_option(name)) { - printf("Supported machines are:\n"); - machines =3D g_slist_sort(machines, machine_class_cmp); - for (el =3D machines; el; el =3D el->next) { - MachineClass *mc =3D el->data; - if (mc->alias) { - printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc= ->name); - } - printf("%-20s %s%s%s\n", mc->name, mc->desc, - mc->is_default ? " (default)" : "", - mc->deprecation_reason ? " (deprecated)" : ""); + machines =3D object_class_get_list(TYPE_MACHINE, false); + if (type) { + ObjectClass *machine_class =3D OBJECT_CLASS(find_machine(type, mac= hines)); + if (machine_class) { + type_print_class_properties(object_class_get_name(machine_clas= s)); + return; } - exit(0); } =20 - mc =3D find_machine(name, machines); - if (!mc) { - error_report("unsupported machine type"); - error_printf("Use -machine help to list supported machines\n"); - exit(1); + printf("Supported machines are:\n"); + machines =3D g_slist_sort(machines, machine_class_cmp); + for (el =3D machines; el; el =3D el->next) { + MachineClass *mc =3D el->data; + if (mc->alias) { + printf("%-20s %s (alias of %s)\n", mc->alias, mc->desc, mc->na= me); + } + printf("%-20s %s%s%s\n", mc->name, mc->desc, + mc->is_default ? " (default)" : "", + mc->deprecation_reason ? " (deprecated)" : ""); } - return mc; } =20 static const char *pid_file; @@ -1625,32 +1573,31 @@ static const QEMUOption *lookup_opt(int argc, char = **argv, return popt; } =20 -static MachineClass *select_machine(void) +static MachineClass *select_machine(QDict *qdict, Error **errp) { + const char *optarg =3D qdict_get_try_str(qdict, "type"); GSList *machines =3D object_class_get_list(TYPE_MACHINE, false); - MachineClass *machine_class =3D find_default_machine(machines); - const char *optarg; - QemuOpts *opts; - Location loc; - - loc_push_none(&loc); - - opts =3D qemu_get_machine_opts(); - qemu_opts_loc_restore(opts); + MachineClass *machine_class; + Error *local_err =3D NULL; =20 - optarg =3D qemu_opt_get(opts, "type"); if (optarg) { - machine_class =3D machine_parse(optarg, machines); - } - - if (!machine_class) { - error_report("No machine specified, and there is no default"); - error_printf("Use -machine help to list supported machines\n"); - exit(1); + machine_class =3D find_machine(optarg, machines); + qdict_del(qdict, "type"); + if (!machine_class) { + error_setg(&local_err, "unsupported machine type"); + } + } else { + machine_class =3D find_default_machine(machines); + if (!machine_class) { + error_setg(&local_err, "No machine specified, and there is no = default"); + } } =20 - loc_pop(&loc); g_slist_free(machines); + if (local_err) { + error_append_hint(&local_err, "Use -machine help to list supported= machines\n"); + error_propagate(errp, local_err); + } return machine_class; } =20 @@ -1669,42 +1616,70 @@ static int object_parse_property_opt(Object *obj, return 0; } =20 -static int machine_set_property(void *opaque, - const char *name, const char *value, - Error **errp) +/* *Non*recursively replace underscores with dashes in QDict keys. */ +static void keyval_dashify(QDict *qdict, Error **errp) { - g_autofree char *qom_name =3D g_strdup(name); + const QDictEntry *ent, *next; char *p; =20 - for (p =3D qom_name; *p; p++) { - if (*p =3D=3D '_') { - *p =3D '-'; + for (ent =3D qdict_first(qdict); ent; ent =3D next) { + g_autofree char *new_key =3D NULL; + + next =3D qdict_next(qdict, ent); + if (!strchr(ent->key, '_')) { + continue; } + new_key =3D g_strdup(ent->key); + for (p =3D new_key; *p; p++) { + if (*p =3D=3D '_') { + *p =3D '-'; + } + } + if (qdict_haskey(qdict, new_key)) { + error_setg(errp, "Conflict between '%s' and '%s'", ent->key, n= ew_key); + return; + } + qobject_ref(ent->value); + qdict_put_obj(qdict, new_key, ent->value); + qdict_del(qdict, ent->key); } +} + +static void qemu_apply_legacy_machine_options(QDict *qdict) +{ + const char *value; + + keyval_dashify(qdict, &error_fatal); =20 /* Legacy options do not correspond to MachineState properties. */ - if (g_str_equal(qom_name, "accel")) { - return 0; + value =3D qdict_get_try_str(qdict, "accel"); + if (value) { + accelerators =3D g_strdup(value); + qdict_del(qdict, "accel"); } - if (g_str_equal(qom_name, "igd-passthru")) { - object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), qom_name, valu= e, + + value =3D qdict_get_try_str(qdict, "igd-passthru"); + if (value) { + object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), "igd-passthru"= , value, false); - return 0; + qdict_del(qdict, "igd-passthru"); } - if (g_str_equal(qom_name, "kvm-shadow-mem")) { - object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, valu= e, + + value =3D qdict_get_try_str(qdict, "kvm-shadow-mem"); + if (value) { + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kvm-shadow-me= m", value, false); - return 0; + qdict_del(qdict, "kvm-shadow-mem"); } - if (g_str_equal(qom_name, "kernel-irqchip")) { - object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, valu= e, + + value =3D qdict_get_try_str(qdict, "kernel-irqchip"); + if (value) { + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), "kernel-irqchi= p", value, false); - object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), qom_name, val= ue, + object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), "kernel-irqch= ip", value, false); - return 0; + qdict_del(qdict, "kernel-irqchip"); } - - return object_parse_property_opt(opaque, name, value, "type", errp); } =20 static void object_option_foreach_add(bool (*type_opt_predicate)(const cha= r *)) @@ -1819,16 +1794,14 @@ static bool object_create_early(const char *type) return true; } =20 -static void qemu_apply_machine_options(void) +static void qemu_apply_machine_options(QDict *qdict) { MachineClass *machine_class =3D MACHINE_GET_CLASS(current_machine); - QemuOpts *machine_opts =3D qemu_get_machine_opts(); const char *boot_order =3D NULL; const char *boot_once =3D NULL; QemuOpts *opts; =20 - qemu_opt_foreach(machine_opts, machine_set_property, current_machine, - &error_fatal); + object_set_properties_from_keyval(OBJECT(current_machine), qdict, fals= e, &error_fatal); current_machine->ram_size =3D ram_size; current_machine->maxram_size =3D maxram_size; current_machine->ram_slots =3D ram_slots; @@ -1857,10 +1830,8 @@ static void qemu_apply_machine_options(void) current_machine->boot_once =3D boot_once; =20 if (semihosting_enabled() && !semihosting_get_argc()) { - const char *kernel_filename =3D qemu_opt_get(machine_opts, "kernel= "); - const char *kernel_cmdline =3D qemu_opt_get(machine_opts, "append"= ) ?: ""; /* fall back to the -kernel/-append */ - semihosting_arg_fallback(kernel_filename, kernel_cmdline); + semihosting_arg_fallback(current_machine->kernel_filename, current= _machine->kernel_cmdline); } } =20 @@ -1907,8 +1878,7 @@ static void qemu_create_early_backends(void) =20 /* * Note: we need to create audio and block backends before - * machine_set_property(), so machine properties can refer to - * them. + * setting machine properties, so they can be referred to. */ configure_blockdev(&bdo_queue, machine_class, snapshot); audio_init_audiodevs(); @@ -2074,16 +2044,14 @@ static void set_memory_options(MachineClass *mc) loc_pop(&loc); } =20 -static void qemu_create_machine(MachineClass *machine_class) +static void qemu_create_machine(QDict *qdict) { + MachineClass *machine_class =3D select_machine(qdict, &error_fatal); object_set_machine_compat_props(machine_class->compat_props); =20 set_memory_options(machine_class); =20 current_machine =3D MACHINE(object_new_with_class(OBJECT_CLASS(machine= _class))); - if (machine_help_func(qemu_get_machine_opts(), current_machine)) { - exit(0); - } object_property_add_child(object_get_root(), "machine", OBJECT(current_machine)); object_property_add_child(container_get(OBJECT(current_machine), @@ -2114,8 +2082,12 @@ static void qemu_create_machine(MachineClass *machin= e_class) * specified either by the configuration file or by the command line. */ if (machine_class->default_machine_opts) { - qemu_opts_set_defaults(qemu_find_opts("machine"), - machine_class->default_machine_opts, 0); + QDict *default_opts =3D + keyval_parse(machine_class->default_machine_opts, NULL, NULL, + &error_abort); + object_set_properties_from_keyval(OBJECT(current_machine), default= _opts, + false, &error_abort); + qobject_unref(default_opts); } } =20 @@ -2137,7 +2109,8 @@ static int global_init_func(void *opaque, QemuOpts *o= pts, Error **errp) */ static bool is_qemuopts_group(const char *group) { - if (g_str_equal(group, "object")) { + if (g_str_equal(group, "object") || + g_str_equal(group, "machine")) { return false; } return true; @@ -2150,6 +2123,13 @@ static void qemu_record_config_group(const char *gro= up, QDict *dict, Visitor *v =3D qobject_input_visitor_new_keyval(QOBJECT(dict)); object_option_add_visitor(v); visit_free(v); + } else if (g_str_equal(group, "machine")) { + /* + * Cannot merge string-valued and type-safe dictionaries, so JSON + * is not accepted yet for -M. + */ + assert(!from_json); + keyval_merge(machine_opts_dict, dict, errp); } else { abort(); } @@ -2280,13 +2260,11 @@ static int do_configure_accelerator(void *opaque, Q= emuOpts *opts, Error **errp) =20 static void configure_accelerators(const char *progname) { - const char *accelerators; bool init_failed =3D false; =20 qemu_opts_foreach(qemu_find_opts("icount"), do_configure_icount, NULL, &error_fatal); =20 - accelerators =3D qemu_opt_get(qemu_get_machine_opts(), "accel"); if (QTAILQ_EMPTY(&qemu_accel_opts.head)) { char **accel_list, **tmp; =20 @@ -2374,12 +2352,11 @@ static void create_default_memdev(MachineState *ms,= const char *path) &error_fatal); } =20 -static void qemu_validate_options(void) +static void qemu_validate_options(const QDict *machine_opts) { - QemuOpts *machine_opts =3D qemu_get_machine_opts(); - const char *kernel_filename =3D qemu_opt_get(machine_opts, "kernel"); - const char *initrd_filename =3D qemu_opt_get(machine_opts, "initrd"); - const char *kernel_cmdline =3D qemu_opt_get(machine_opts, "append"); + const char *kernel_filename =3D qdict_get_try_str(machine_opts, "kerne= l"); + const char *initrd_filename =3D qdict_get_try_str(machine_opts, "initr= d"); + const char *kernel_cmdline =3D qdict_get_try_str(machine_opts, "append= "); =20 if (kernel_filename =3D=3D NULL) { if (kernel_cmdline !=3D NULL) { @@ -2719,7 +2696,6 @@ void qemu_init(int argc, char **argv, char **envp) qemu_add_opts(&qemu_trace_opts); qemu_plugin_add_opts(); qemu_add_opts(&qemu_option_rom_opts); - qemu_add_opts(&qemu_machine_opts); qemu_add_opts(&qemu_accel_opts); qemu_add_opts(&qemu_mem_opts); qemu_add_opts(&qemu_smp_opts); @@ -2760,6 +2736,7 @@ void qemu_init(int argc, char **argv, char **envp) } } =20 + machine_opts_dict =3D qdict_new(); if (userconfig) { qemu_read_default_config_file(&error_fatal); } @@ -2849,8 +2826,7 @@ void qemu_init(int argc, char **argv, char **envp) parse_display(optarg); break; case QEMU_OPTION_nographic: - olist =3D qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "graphics=3Doff", false); + qdict_put_str(machine_opts_dict, "graphics", "off"); nographic =3D true; dpy.type =3D DISPLAY_TYPE_NONE; break; @@ -2874,16 +2850,16 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_kernel: - qemu_opts_set(qemu_find_opts("machine"), "kernel", optarg,= &error_abort); + qdict_put_str(machine_opts_dict, "kernel", optarg); break; case QEMU_OPTION_initrd: - qemu_opts_set(qemu_find_opts("machine"), "initrd", optarg,= &error_abort); + qdict_put_str(machine_opts_dict, "initrd", optarg); break; case QEMU_OPTION_append: - qemu_opts_set(qemu_find_opts("machine"), "append", optarg,= &error_abort); + qdict_put_str(machine_opts_dict, "append", optarg); break; case QEMU_OPTION_dtb: - qemu_opts_set(qemu_find_opts("machine"), "dtb", optarg, &e= rror_abort); + qdict_put_str(machine_opts_dict, "dtb", optarg); break; case QEMU_OPTION_cdrom: drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS); @@ -2993,7 +2969,7 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_bios: - qemu_opts_set(qemu_find_opts("machine"), "firmware", optar= g, &error_abort); + qdict_put_str(machine_opts_dict, "firmware", optarg); break; case QEMU_OPTION_singlestep: singlestep =3D 1; @@ -3262,17 +3238,20 @@ void qemu_init(int argc, char **argv, char **envp) preconfig_requested =3D true; break; case QEMU_OPTION_enable_kvm: - olist =3D qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "accel=3Dkvm", false); + qdict_put_str(machine_opts_dict, "accel", "kvm"); break; case QEMU_OPTION_M: case QEMU_OPTION_machine: - olist =3D qemu_find_opts("machine"); - opts =3D qemu_opts_parse_noisily(olist, optarg, true); - if (!opts) { - exit(1); + { + bool help; + + keyval_parse_into(machine_opts_dict, optarg, "type", &= help, &error_fatal); + if (help) { + machine_help_func(machine_opts_dict); + exit(EXIT_SUCCESS); + } + break; } - break; case QEMU_OPTION_accel: accel_opts =3D qemu_opts_parse_noisily(qemu_find_opts("acc= el"), optarg, true); @@ -3299,12 +3278,10 @@ void qemu_init(int argc, char **argv, char **envp) } break; case QEMU_OPTION_usb: - olist =3D qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "usb=3Don", false); + qdict_put_str(machine_opts_dict, "usb", "on"); break; case QEMU_OPTION_usbdevice: - olist =3D qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "usb=3Don", false); + qdict_put_str(machine_opts_dict, "usb", "on"); add_device_config(DEV_USB, optarg); break; case QEMU_OPTION_device: @@ -3323,12 +3300,10 @@ void qemu_init(int argc, char **argv, char **envp) vnc_parse(optarg); break; case QEMU_OPTION_no_acpi: - olist =3D qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "acpi=3Doff", false); + qdict_put_str(machine_opts_dict, "acpi", "off"); break; case QEMU_OPTION_no_hpet: - olist =3D qemu_find_opts("machine"); - qemu_opts_parse_noisily(olist, "hpet=3Doff", false); + qdict_put_str(machine_opts_dict, "hpet", "off"); break; case QEMU_OPTION_no_reboot: olist =3D qemu_find_opts("action"); @@ -3581,7 +3556,7 @@ void qemu_init(int argc, char **argv, char **envp) */ loc_set_none(); =20 - qemu_validate_options(); + qemu_validate_options(machine_opts_dict); qemu_process_sugar_options(); =20 /* @@ -3614,7 +3589,7 @@ void qemu_init(int argc, char **argv, char **envp) =20 configure_rtc(qemu_find_opts_singleton("rtc")); =20 - qemu_create_machine(select_machine()); + qemu_create_machine(machine_opts_dict); =20 suspend_mux_open(); =20 @@ -3622,12 +3597,14 @@ void qemu_init(int argc, char **argv, char **envp) qemu_create_default_devices(); qemu_create_early_backends(); =20 - qemu_apply_machine_options(); + qemu_apply_legacy_machine_options(machine_opts_dict); + qemu_apply_machine_options(machine_opts_dict); + qobject_unref(machine_opts_dict); phase_advance(PHASE_MACHINE_CREATED); =20 /* * Note: uses machine properties such as kernel-irqchip, must run - * after machine_set_property(). + * after qemu_apply_machine_options. */ configure_accelerators(argv[0]); phase_advance(PHASE_ACCEL_CREATED); --=20 2.31.1