vl: switch -M parsing to keyval
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>
This commit is contained in:
parent
c445909e1f
commit
d8fb7d0969
293
softmmu/vl.c
293
softmmu/vl.c
@ -145,6 +145,8 @@ static const char *cpu_option;
|
|||||||
static const char *mem_path;
|
static const char *mem_path;
|
||||||
static const char *incoming;
|
static const char *incoming;
|
||||||
static const char *loadvm;
|
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 QTAILQ_HEAD(, ObjectOption) object_opts = QTAILQ_HEAD_INITIALIZER(object_opts);
|
||||||
static ram_addr_t maxram_size;
|
static ram_addr_t maxram_size;
|
||||||
static uint64_t ram_slots;
|
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 = {
|
static QemuOptsList qemu_accel_opts = {
|
||||||
.name = "accel",
|
.name = "accel",
|
||||||
.implied_opt_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)
|
const char *qemu_get_vm_name(void)
|
||||||
{
|
{
|
||||||
return qemu_name;
|
return qemu_name;
|
||||||
@ -815,33 +792,6 @@ static MachineClass *find_default_machine(GSList *machines)
|
|||||||
return default_machineclass;
|
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)
|
static void version(void)
|
||||||
{
|
{
|
||||||
printf("QEMU emulator version " QEMU_FULL_VERSION "\n"
|
printf("QEMU emulator version " QEMU_FULL_VERSION "\n"
|
||||||
@ -1554,12 +1504,20 @@ static gint machine_class_cmp(gconstpointer a, gconstpointer b)
|
|||||||
object_class_get_name(OBJECT_CLASS(mc1)));
|
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 *machines, *el;
|
||||||
GSList *el;
|
const char *type = qdict_get_try_str(qdict, "type");
|
||||||
|
|
||||||
|
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 (is_help_option(name)) {
|
|
||||||
printf("Supported machines are:\n");
|
printf("Supported machines are:\n");
|
||||||
machines = g_slist_sort(machines, machine_class_cmp);
|
machines = g_slist_sort(machines, machine_class_cmp);
|
||||||
for (el = machines; el; el = el->next) {
|
for (el = machines; el; el = el->next) {
|
||||||
@ -1571,16 +1529,6 @@ static MachineClass *machine_parse(const char *name, GSList *machines)
|
|||||||
mc->is_default ? " (default)" : "",
|
mc->is_default ? " (default)" : "",
|
||||||
mc->deprecation_reason ? " (deprecated)" : "");
|
mc->deprecation_reason ? " (deprecated)" : "");
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
}
|
|
||||||
return mc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *pid_file;
|
static const char *pid_file;
|
||||||
@ -1633,32 +1581,31 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
|
|||||||
return popt;
|
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);
|
GSList *machines = object_class_get_list(TYPE_MACHINE, false);
|
||||||
MachineClass *machine_class = find_default_machine(machines);
|
MachineClass *machine_class;
|
||||||
const char *optarg;
|
Error *local_err = NULL;
|
||||||
QemuOpts *opts;
|
|
||||||
Location loc;
|
|
||||||
|
|
||||||
loc_push_none(&loc);
|
|
||||||
|
|
||||||
opts = qemu_get_machine_opts();
|
|
||||||
qemu_opts_loc_restore(opts);
|
|
||||||
|
|
||||||
optarg = qemu_opt_get(opts, "type");
|
|
||||||
if (optarg) {
|
if (optarg) {
|
||||||
machine_class = machine_parse(optarg, machines);
|
machine_class = find_machine(optarg, machines);
|
||||||
}
|
qdict_del(qdict, "type");
|
||||||
|
|
||||||
if (!machine_class) {
|
if (!machine_class) {
|
||||||
error_report("No machine specified, and there is no default");
|
error_setg(&local_err, "unsupported machine type");
|
||||||
error_printf("Use -machine help to list supported machines\n");
|
}
|
||||||
exit(1);
|
} else {
|
||||||
|
machine_class = find_default_machine(machines);
|
||||||
|
if (!machine_class) {
|
||||||
|
error_setg(&local_err, "No machine specified, and there is no default");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loc_pop(&loc);
|
|
||||||
g_slist_free(machines);
|
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;
|
return machine_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1677,42 +1624,70 @@ static int object_parse_property_opt(Object *obj,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int machine_set_property(void *opaque,
|
/* *Non*recursively replace underscores with dashes in QDict keys. */
|
||||||
const char *name, const char *value,
|
static void keyval_dashify(QDict *qdict, Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
g_autofree char *qom_name = g_strdup(name);
|
const QDictEntry *ent, *next;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
for (p = qom_name; *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 == '_') {
|
if (*p == '_') {
|
||||||
*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. */
|
/* Legacy options do not correspond to MachineState properties. */
|
||||||
if (g_str_equal(qom_name, "accel")) {
|
value = qdict_get_try_str(qdict, "accel");
|
||||||
return 0;
|
if (value) {
|
||||||
}
|
accelerators = g_strdup(value);
|
||||||
if (g_str_equal(qom_name, "igd-passthru")) {
|
qdict_del(qdict, "accel");
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *))
|
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;
|
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);
|
MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
|
||||||
QemuOpts *machine_opts = qemu_get_machine_opts();
|
|
||||||
const char *boot_order = NULL;
|
const char *boot_order = NULL;
|
||||||
const char *boot_once = NULL;
|
const char *boot_once = NULL;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
|
|
||||||
qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
|
object_set_properties_from_keyval(OBJECT(current_machine), qdict, false, &error_fatal);
|
||||||
&error_fatal);
|
|
||||||
current_machine->ram_size = ram_size;
|
current_machine->ram_size = ram_size;
|
||||||
current_machine->maxram_size = maxram_size;
|
current_machine->maxram_size = maxram_size;
|
||||||
current_machine->ram_slots = ram_slots;
|
current_machine->ram_slots = ram_slots;
|
||||||
@ -1865,10 +1838,8 @@ static void qemu_apply_machine_options(void)
|
|||||||
current_machine->boot_once = boot_once;
|
current_machine->boot_once = boot_once;
|
||||||
|
|
||||||
if (semihosting_enabled() && !semihosting_get_argc()) {
|
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 */
|
/* 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
|
* Note: we need to create audio and block backends before
|
||||||
* machine_set_property(), so machine properties can refer to
|
* setting machine properties, so they can be referred to.
|
||||||
* them.
|
|
||||||
*/
|
*/
|
||||||
configure_blockdev(&bdo_queue, machine_class, snapshot);
|
configure_blockdev(&bdo_queue, machine_class, snapshot);
|
||||||
audio_init_audiodevs();
|
audio_init_audiodevs();
|
||||||
@ -2091,16 +2061,14 @@ static void set_memory_options(MachineClass *mc)
|
|||||||
loc_pop(&loc);
|
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);
|
object_set_machine_compat_props(machine_class->compat_props);
|
||||||
|
|
||||||
set_memory_options(machine_class);
|
set_memory_options(machine_class);
|
||||||
|
|
||||||
current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(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_property_add_child(object_get_root(), "machine",
|
||||||
OBJECT(current_machine));
|
OBJECT(current_machine));
|
||||||
object_property_add_child(container_get(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.
|
* specified either by the configuration file or by the command line.
|
||||||
*/
|
*/
|
||||||
if (machine_class->default_machine_opts) {
|
if (machine_class->default_machine_opts) {
|
||||||
qemu_opts_set_defaults(qemu_find_opts("machine"),
|
QDict *default_opts =
|
||||||
machine_class->default_machine_opts, 0);
|
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)
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
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));
|
Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict));
|
||||||
object_option_add_visitor(v);
|
object_option_add_visitor(v);
|
||||||
visit_free(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 {
|
} else {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -2297,13 +2277,11 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
|
|||||||
|
|
||||||
static void configure_accelerators(const char *progname)
|
static void configure_accelerators(const char *progname)
|
||||||
{
|
{
|
||||||
const char *accelerators;
|
|
||||||
bool init_failed = false;
|
bool init_failed = false;
|
||||||
|
|
||||||
qemu_opts_foreach(qemu_find_opts("icount"),
|
qemu_opts_foreach(qemu_find_opts("icount"),
|
||||||
do_configure_icount, NULL, &error_fatal);
|
do_configure_icount, NULL, &error_fatal);
|
||||||
|
|
||||||
accelerators = qemu_opt_get(qemu_get_machine_opts(), "accel");
|
|
||||||
if (QTAILQ_EMPTY(&qemu_accel_opts.head)) {
|
if (QTAILQ_EMPTY(&qemu_accel_opts.head)) {
|
||||||
char **accel_list, **tmp;
|
char **accel_list, **tmp;
|
||||||
|
|
||||||
@ -2391,12 +2369,11 @@ static void create_default_memdev(MachineState *ms, const char *path)
|
|||||||
&error_fatal);
|
&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 = qdict_get_try_str(machine_opts, "kernel");
|
||||||
const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
const char *initrd_filename = qdict_get_try_str(machine_opts, "initrd");
|
||||||
const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
|
const char *kernel_cmdline = qdict_get_try_str(machine_opts, "append");
|
||||||
const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
|
||||||
|
|
||||||
if (kernel_filename == NULL) {
|
if (kernel_filename == NULL) {
|
||||||
if (kernel_cmdline != 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_add_opts(&qemu_trace_opts);
|
||||||
qemu_plugin_add_opts();
|
qemu_plugin_add_opts();
|
||||||
qemu_add_opts(&qemu_option_rom_opts);
|
qemu_add_opts(&qemu_option_rom_opts);
|
||||||
qemu_add_opts(&qemu_machine_opts);
|
|
||||||
qemu_add_opts(&qemu_accel_opts);
|
qemu_add_opts(&qemu_accel_opts);
|
||||||
qemu_add_opts(&qemu_mem_opts);
|
qemu_add_opts(&qemu_mem_opts);
|
||||||
qemu_add_opts(&qemu_smp_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) {
|
if (userconfig) {
|
||||||
qemu_read_default_config_file(&error_fatal);
|
qemu_read_default_config_file(&error_fatal);
|
||||||
}
|
}
|
||||||
@ -2866,8 +2843,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
parse_display(optarg);
|
parse_display(optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_nographic:
|
case QEMU_OPTION_nographic:
|
||||||
olist = qemu_find_opts("machine");
|
qdict_put_str(machine_opts_dict, "graphics", "off");
|
||||||
qemu_opts_parse_noisily(olist, "graphics=off", false);
|
|
||||||
nographic = true;
|
nographic = true;
|
||||||
dpy.type = DISPLAY_TYPE_NONE;
|
dpy.type = DISPLAY_TYPE_NONE;
|
||||||
break;
|
break;
|
||||||
@ -2891,16 +2867,16 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_kernel:
|
case QEMU_OPTION_kernel:
|
||||||
qemu_opts_set(qemu_find_opts("machine"), "kernel", optarg, &error_abort);
|
qdict_put_str(machine_opts_dict, "kernel", optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_initrd:
|
case QEMU_OPTION_initrd:
|
||||||
qemu_opts_set(qemu_find_opts("machine"), "initrd", optarg, &error_abort);
|
qdict_put_str(machine_opts_dict, "initrd", optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_append:
|
case QEMU_OPTION_append:
|
||||||
qemu_opts_set(qemu_find_opts("machine"), "append", optarg, &error_abort);
|
qdict_put_str(machine_opts_dict, "append", optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_dtb:
|
case QEMU_OPTION_dtb:
|
||||||
qemu_opts_set(qemu_find_opts("machine"), "dtb", optarg, &error_abort);
|
qdict_put_str(machine_opts_dict, "dtb", optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_cdrom:
|
case QEMU_OPTION_cdrom:
|
||||||
drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
|
drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
|
||||||
@ -3010,7 +2986,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_bios:
|
case QEMU_OPTION_bios:
|
||||||
qemu_opts_set(qemu_find_opts("machine"), "firmware", optarg, &error_abort);
|
qdict_put_str(machine_opts_dict, "firmware", optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_singlestep:
|
case QEMU_OPTION_singlestep:
|
||||||
singlestep = 1;
|
singlestep = 1;
|
||||||
@ -3281,17 +3257,20 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
preconfig_requested = true;
|
preconfig_requested = true;
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_enable_kvm:
|
case QEMU_OPTION_enable_kvm:
|
||||||
olist = qemu_find_opts("machine");
|
qdict_put_str(machine_opts_dict, "accel", "kvm");
|
||||||
qemu_opts_parse_noisily(olist, "accel=kvm", false);
|
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_M:
|
case QEMU_OPTION_M:
|
||||||
case QEMU_OPTION_machine:
|
case QEMU_OPTION_machine:
|
||||||
olist = qemu_find_opts("machine");
|
{
|
||||||
opts = qemu_opts_parse_noisily(olist, optarg, true);
|
bool help;
|
||||||
if (!opts) {
|
|
||||||
exit(1);
|
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:
|
case QEMU_OPTION_accel:
|
||||||
accel_opts = qemu_opts_parse_noisily(qemu_find_opts("accel"),
|
accel_opts = qemu_opts_parse_noisily(qemu_find_opts("accel"),
|
||||||
optarg, true);
|
optarg, true);
|
||||||
@ -3318,12 +3297,10 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_usb:
|
case QEMU_OPTION_usb:
|
||||||
olist = qemu_find_opts("machine");
|
qdict_put_str(machine_opts_dict, "usb", "on");
|
||||||
qemu_opts_parse_noisily(olist, "usb=on", false);
|
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_usbdevice:
|
case QEMU_OPTION_usbdevice:
|
||||||
olist = qemu_find_opts("machine");
|
qdict_put_str(machine_opts_dict, "usb", "on");
|
||||||
qemu_opts_parse_noisily(olist, "usb=on", false);
|
|
||||||
add_device_config(DEV_USB, optarg);
|
add_device_config(DEV_USB, optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_device:
|
case QEMU_OPTION_device:
|
||||||
@ -3342,12 +3319,10 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
vnc_parse(optarg);
|
vnc_parse(optarg);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_no_acpi:
|
case QEMU_OPTION_no_acpi:
|
||||||
olist = qemu_find_opts("machine");
|
qdict_put_str(machine_opts_dict, "acpi", "off");
|
||||||
qemu_opts_parse_noisily(olist, "acpi=off", false);
|
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_no_hpet:
|
case QEMU_OPTION_no_hpet:
|
||||||
olist = qemu_find_opts("machine");
|
qdict_put_str(machine_opts_dict, "hpet", "off");
|
||||||
qemu_opts_parse_noisily(olist, "hpet=off", false);
|
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_no_reboot:
|
case QEMU_OPTION_no_reboot:
|
||||||
olist = qemu_find_opts("action");
|
olist = qemu_find_opts("action");
|
||||||
@ -3600,7 +3575,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
*/
|
*/
|
||||||
loc_set_none();
|
loc_set_none();
|
||||||
|
|
||||||
qemu_validate_options();
|
qemu_validate_options(machine_opts_dict);
|
||||||
qemu_process_sugar_options();
|
qemu_process_sugar_options();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3633,7 +3608,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
|
|
||||||
configure_rtc(qemu_find_opts_singleton("rtc"));
|
configure_rtc(qemu_find_opts_singleton("rtc"));
|
||||||
|
|
||||||
qemu_create_machine(select_machine());
|
qemu_create_machine(machine_opts_dict);
|
||||||
|
|
||||||
suspend_mux_open();
|
suspend_mux_open();
|
||||||
|
|
||||||
@ -3641,12 +3616,14 @@ void qemu_init(int argc, char **argv, char **envp)
|
|||||||
qemu_create_default_devices();
|
qemu_create_default_devices();
|
||||||
qemu_create_early_backends();
|
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);
|
phase_advance(PHASE_MACHINE_CREATED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: uses machine properties such as kernel-irqchip, must run
|
* Note: uses machine properties such as kernel-irqchip, must run
|
||||||
* after machine_set_property().
|
* after qemu_apply_machine_options.
|
||||||
*/
|
*/
|
||||||
configure_accelerators(argv[0]);
|
configure_accelerators(argv[0]);
|
||||||
phase_advance(PHASE_ACCEL_CREATED);
|
phase_advance(PHASE_ACCEL_CREATED);
|
||||||
|
Loading…
Reference in New Issue
Block a user