[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PULL 36/40] vl: switch -M parsing to keyval
From: |
Jason Andryuk |
Subject: |
Re: [PULL 36/40] vl: switch -M parsing to keyval |
Date: |
Thu, 8 Jul 2021 12:31:36 -0400 |
On Tue, Jul 6, 2021 at 6:43 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> 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=val) 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 <pbonzini@redhat.com>
> ---
> softmmu/vl.c | 315 ++++++++++++++++++++++++---------------------------
> 1 file changed, 146 insertions(+), 169 deletions(-)
Xen's osstest bisector found this commit breaks starting a Xen vm:
https://lore.kernel.org/xen-devel/E1m1HlC-0005Ra-Ff@osstest.test-lab.xenproject.org/
qemu fails to start with:
Unexpected error in object_property_find_err() at
../qemu-xen-dir-remote/qom/object.c:1299:
qemu-system-i386: Property 'xenfv-3.1-machine.accel' not found
The Xen machines have `default_machine_opts =
"accel=xen,suppress-vmdesc=on"` which may be the problem?
Regards,
Jason
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 7dd2d72d0b..f848abd31a 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 =
> 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 = {
> },
> };
>
> -static QemuOptsList qemu_machine_opts = {
> - .name = "machine",
> - .implied_opt_name = "type",
> - .merge_lists = true,
> - .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
> - .desc = {
> - /*
> - * no elements => accept any
> - * sanity checking will happen later
> - * when setting machine properties
> - */
> - { }
> - },
> -};
> -
> static QemuOptsList qemu_accel_opts = {
> .name = "accel",
> .implied_opt_name = "accel",
> @@ -498,16 +485,6 @@ static QemuOptsList qemu_action_opts = {
> },
> };
>
> -/**
> - * 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
> *machines)
> return default_machineclass;
> }
>
> -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 = object_property_iter_next(&iter))) {
> - if (!prop->set) {
> - continue;
> - }
> -
> - printf("%s.%s=%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"
> @@ -1554,33 +1504,31 @@ static gint machine_class_cmp(gconstpointer a,
> gconstpointer b)
> object_class_get_name(OBJECT_CLASS(mc1)));
> }
>
> -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 = qdict_get_try_str(qdict, "type");
>
> - if (is_help_option(name)) {
> - printf("Supported machines are:\n");
> - machines = g_slist_sort(machines, machine_class_cmp);
> - for (el = machines; el; el = el->next) {
> - MachineClass *mc = 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 = 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;
> }
> - exit(0);
> }
>
> - mc = 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 = g_slist_sort(machines, machine_class_cmp);
> + for (el = machines; el; el = el->next) {
> + MachineClass *mc = 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)" : "");
> }
> - return mc;
> }
>
> static const char *pid_file;
> @@ -1633,32 +1581,31 @@ static const QEMUOption *lookup_opt(int argc, char
> **argv,
> return popt;
> }
>
> -static MachineClass *select_machine(void)
> +static MachineClass *select_machine(QDict *qdict, Error **errp)
> {
> + const char *optarg = qdict_get_try_str(qdict, "type");
> GSList *machines = object_class_get_list(TYPE_MACHINE, false);
> - MachineClass *machine_class = find_default_machine(machines);
> - const char *optarg;
> - QemuOpts *opts;
> - Location loc;
> + MachineClass *machine_class;
> + Error *local_err = NULL;
>
> - loc_push_none(&loc);
> -
> - opts = qemu_get_machine_opts();
> - qemu_opts_loc_restore(opts);
> -
> - optarg = qemu_opt_get(opts, "type");
> if (optarg) {
> - machine_class = machine_parse(optarg, machines);
> + machine_class = find_machine(optarg, machines);
> + qdict_del(qdict, "type");
> + if (!machine_class) {
> + error_setg(&local_err, "unsupported machine type");
> + }
> + } else {
> + machine_class = find_default_machine(machines);
> + if (!machine_class) {
> + error_setg(&local_err, "No machine specified, and there is no
> default");
> + }
> }
>
> - 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);
> - }
> -
> - 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;
> }
>
> @@ -1677,42 +1624,70 @@ static int object_parse_property_opt(Object *obj,
> return 0;
> }
>
> -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 = g_strdup(name);
> + const QDictEntry *ent, *next;
> char *p;
>
> - for (p = qom_name; *p; p++) {
> - if (*p == '_') {
> - *p = '-';
> + for (ent = qdict_first(qdict); ent; ent = next) {
> + g_autofree char *new_key = NULL;
> +
> + next = qdict_next(qdict, ent);
> + if (!strchr(ent->key, '_')) {
> + continue;
> }
> + new_key = g_strdup(ent->key);
> + for (p = new_key; *p; p++) {
> + if (*p == '_') {
> + *p = '-';
> + }
> + }
> + if (qdict_haskey(qdict, new_key)) {
> + error_setg(errp, "Conflict between '%s' and '%s'", ent->key,
> new_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);
>
> /* Legacy options do not correspond to MachineState properties. */
> - if (g_str_equal(qom_name, "accel")) {
> - return 0;
> - }
> - if (g_str_equal(qom_name, "igd-passthru")) {
> - object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), qom_name, value,
> - false);
> - return 0;
> - }
> - if (g_str_equal(qom_name, "kvm-shadow-mem")) {
> - object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value,
> - false);
> - return 0;
> - }
> - if (g_str_equal(qom_name, "kernel-irqchip")) {
> - object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value,
> - false);
> - object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), qom_name, value,
> - false);
> - return 0;
> + value = qdict_get_try_str(qdict, "accel");
> + if (value) {
> + accelerators = g_strdup(value);
> + qdict_del(qdict, "accel");
> }
>
> - return object_parse_property_opt(opaque, name, value, "type", errp);
> + value = qdict_get_try_str(qdict, "igd-passthru");
> + if (value) {
> + object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), "igd-passthru",
> value,
> + false);
> + qdict_del(qdict, "igd-passthru");
> + }
> +
> + value = qdict_get_try_str(qdict, "kvm-shadow-mem");
> + if (value) {
> + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"),
> "kvm-shadow-mem", value,
> + false);
> + qdict_del(qdict, "kvm-shadow-mem");
> + }
> +
> + value = qdict_get_try_str(qdict, "kernel-irqchip");
> + if (value) {
> + object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"),
> "kernel-irqchip", value,
> + false);
> + object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"),
> "kernel-irqchip", value,
> + false);
> + qdict_del(qdict, "kernel-irqchip");
> + }
> }
>
> static void object_option_foreach_add(bool (*type_opt_predicate)(const char
> *))
> @@ -1827,16 +1802,14 @@ static bool object_create_early(const char *type)
> return true;
> }
>
> -static void qemu_apply_machine_options(void)
> +static void qemu_apply_machine_options(QDict *qdict)
> {
> MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
> - QemuOpts *machine_opts = qemu_get_machine_opts();
> const char *boot_order = NULL;
> const char *boot_once = NULL;
> QemuOpts *opts;
>
> - qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
> - &error_fatal);
> + object_set_properties_from_keyval(OBJECT(current_machine), qdict, false,
> &error_fatal);
> current_machine->ram_size = ram_size;
> current_machine->maxram_size = maxram_size;
> current_machine->ram_slots = ram_slots;
> @@ -1865,10 +1838,8 @@ static void qemu_apply_machine_options(void)
> current_machine->boot_once = boot_once;
>
> if (semihosting_enabled() && !semihosting_get_argc()) {
> - const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
> - const char *kernel_cmdline = 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);
> }
> }
>
> @@ -1924,8 +1895,7 @@ static void qemu_create_early_backends(void)
>
> /*
> * 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();
> @@ -2091,16 +2061,14 @@ static void set_memory_options(MachineClass *mc)
> loc_pop(&loc);
> }
>
> -static void qemu_create_machine(MachineClass *machine_class)
> +static void qemu_create_machine(QDict *qdict)
> {
> + MachineClass *machine_class = select_machine(qdict, &error_fatal);
> object_set_machine_compat_props(machine_class->compat_props);
>
> set_memory_options(machine_class);
>
> current_machine =
> 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),
> @@ -2131,8 +2099,12 @@ static void qemu_create_machine(MachineClass
> *machine_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 =
> + 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);
> }
> }
>
> @@ -2154,7 +2126,8 @@ static int global_init_func(void *opaque, QemuOpts
> *opts, 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;
> @@ -2167,6 +2140,13 @@ static void qemu_record_config_group(const char
> *group, QDict *dict,
> Visitor *v = 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();
> }
> @@ -2297,13 +2277,11 @@ static int do_configure_accelerator(void *opaque,
> QemuOpts *opts, Error **errp)
>
> static void configure_accelerators(const char *progname)
> {
> - const char *accelerators;
> bool init_failed = false;
>
> qemu_opts_foreach(qemu_find_opts("icount"),
> do_configure_icount, NULL, &error_fatal);
>
> - accelerators = qemu_opt_get(qemu_get_machine_opts(), "accel");
> if (QTAILQ_EMPTY(&qemu_accel_opts.head)) {
> char **accel_list, **tmp;
>
> @@ -2391,12 +2369,11 @@ static void create_default_memdev(MachineState *ms,
> const char *path)
> &error_fatal);
> }
>
> -static void qemu_validate_options(void)
> +static void qemu_validate_options(const QDict *machine_opts)
> {
> - QemuOpts *machine_opts = qemu_get_machine_opts();
> - const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
> - const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
> - const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
> + const char *kernel_filename = qdict_get_try_str(machine_opts, "kernel");
> + const char *initrd_filename = qdict_get_try_str(machine_opts, "initrd");
> + const char *kernel_cmdline = qdict_get_try_str(machine_opts, "append");
>
> if (kernel_filename == NULL) {
> if (kernel_cmdline != NULL) {
> @@ -2736,7 +2713,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);
> @@ -2777,6 +2753,7 @@ void qemu_init(int argc, char **argv, char **envp)
> }
> }
>
> + machine_opts_dict = qdict_new();
> if (userconfig) {
> qemu_read_default_config_file(&error_fatal);
> }
> @@ -2866,8 +2843,7 @@ void qemu_init(int argc, char **argv, char **envp)
> parse_display(optarg);
> break;
> case QEMU_OPTION_nographic:
> - olist = qemu_find_opts("machine");
> - qemu_opts_parse_noisily(olist, "graphics=off", false);
> + qdict_put_str(machine_opts_dict, "graphics", "off");
> nographic = true;
> dpy.type = DISPLAY_TYPE_NONE;
> break;
> @@ -2891,16 +2867,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,
> &error_abort);
> + qdict_put_str(machine_opts_dict, "dtb", optarg);
> break;
> case QEMU_OPTION_cdrom:
> drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
> @@ -3010,7 +2986,7 @@ void qemu_init(int argc, char **argv, char **envp)
> }
> break;
> case QEMU_OPTION_bios:
> - qemu_opts_set(qemu_find_opts("machine"), "firmware", optarg,
> &error_abort);
> + qdict_put_str(machine_opts_dict, "firmware", optarg);
> break;
> case QEMU_OPTION_singlestep:
> singlestep = 1;
> @@ -3281,17 +3257,20 @@ void qemu_init(int argc, char **argv, char **envp)
> preconfig_requested = true;
> break;
> case QEMU_OPTION_enable_kvm:
> - olist = qemu_find_opts("machine");
> - qemu_opts_parse_noisily(olist, "accel=kvm", false);
> + qdict_put_str(machine_opts_dict, "accel", "kvm");
> break;
> case QEMU_OPTION_M:
> case QEMU_OPTION_machine:
> - olist = qemu_find_opts("machine");
> - opts = 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 = qemu_opts_parse_noisily(qemu_find_opts("accel"),
> optarg, true);
> @@ -3318,12 +3297,10 @@ void qemu_init(int argc, char **argv, char **envp)
> }
> break;
> case QEMU_OPTION_usb:
> - olist = qemu_find_opts("machine");
> - qemu_opts_parse_noisily(olist, "usb=on", false);
> + qdict_put_str(machine_opts_dict, "usb", "on");
> break;
> case QEMU_OPTION_usbdevice:
> - olist = qemu_find_opts("machine");
> - qemu_opts_parse_noisily(olist, "usb=on", false);
> + qdict_put_str(machine_opts_dict, "usb", "on");
> add_device_config(DEV_USB, optarg);
> break;
> case QEMU_OPTION_device:
> @@ -3342,12 +3319,10 @@ void qemu_init(int argc, char **argv, char **envp)
> vnc_parse(optarg);
> break;
> case QEMU_OPTION_no_acpi:
> - olist = qemu_find_opts("machine");
> - qemu_opts_parse_noisily(olist, "acpi=off", false);
> + qdict_put_str(machine_opts_dict, "acpi", "off");
> break;
> case QEMU_OPTION_no_hpet:
> - olist = qemu_find_opts("machine");
> - qemu_opts_parse_noisily(olist, "hpet=off", false);
> + qdict_put_str(machine_opts_dict, "hpet", "off");
> break;
> case QEMU_OPTION_no_reboot:
> olist = qemu_find_opts("action");
> @@ -3600,7 +3575,7 @@ void qemu_init(int argc, char **argv, char **envp)
> */
> loc_set_none();
>
> - qemu_validate_options();
> + qemu_validate_options(machine_opts_dict);
> qemu_process_sugar_options();
>
> /*
> @@ -3633,7 +3608,7 @@ void qemu_init(int argc, char **argv, char **envp)
>
> configure_rtc(qemu_find_opts_singleton("rtc"));
>
> - qemu_create_machine(select_machine());
> + qemu_create_machine(machine_opts_dict);
>
> suspend_mux_open();
>
> @@ -3641,12 +3616,14 @@ void qemu_init(int argc, char **argv, char **envp)
> qemu_create_default_devices();
> qemu_create_early_backends();
>
> - 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);
>
> /*
> * 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);
> --
> 2.31.1
>
>
>
- [PULL 34/40] keyval: introduce keyval_merge, (continued)
- [PULL 34/40] keyval: introduce keyval_merge, Paolo Bonzini, 2021/07/06
- [PULL 24/40] meson: store dependency('threads') in a variable, Paolo Bonzini, 2021/07/06
- [PULL 28/40] configure: convert compiler tests to meson, part 2, Paolo Bonzini, 2021/07/06
- [PULL 29/40] configure: convert compiler tests to meson, part 3, Paolo Bonzini, 2021/07/06
- [PULL 31/40] configure: convert compiler tests to meson, part 5, Paolo Bonzini, 2021/07/06
- [PULL 30/40] configure: convert compiler tests to meson, part 4, Paolo Bonzini, 2021/07/06
- [PULL 33/40] qom: export more functions for use with non-UserCreatable objects, Paolo Bonzini, 2021/07/06
- [PULL 40/40] config-host.mak: remove unused compiler-related lines, Paolo Bonzini, 2021/07/06
- [PULL 35/40] keyval: introduce keyval_parse_into, Paolo Bonzini, 2021/07/06
- [PULL 36/40] vl: switch -M parsing to keyval, Paolo Bonzini, 2021/07/06
- Re: [PULL 36/40] vl: switch -M parsing to keyval,
Jason Andryuk <=
- Re: [PULL 36/40] vl: switch -M parsing to keyval, Volker RĂ¼melin, 2021/07/12
- Re: [PULL 36/40] vl: switch -M parsing to keyval, Alex Williamson, 2021/07/13
Re: [PULL 36/40] vl: switch -M parsing to keyval, Peter Krempa, 2021/07/22