From patchwork Thu Dec 2 07:04:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 1562563 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=G0N+VYeX; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4J4SPv0sXXz9s1l for ; Thu, 2 Dec 2021 18:34:10 +1100 (AEDT) Received: from localhost ([::1]:44288 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1msgbV-0001A8-RA for incoming@patchwork.ozlabs.org; Thu, 02 Dec 2021 02:34:05 -0500 Received: from eggs.gnu.org ([209.51.188.92]:39726) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1msg9Y-0005Wc-2b for qemu-devel@nongnu.org; Thu, 02 Dec 2021 02:05:12 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:27385) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1msg9S-0006GW-8t for qemu-devel@nongnu.org; Thu, 02 Dec 2021 02:05:11 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1638428705; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UzbvYN56df4LIB93KRQZmMV/XvEkPHi500j7K31YoB0=; b=G0N+VYeXTtHLOt79aZw4gqGB2TQw+DraJ3FwQQDlgXEB9Jj+zQdywc6WekFrwMzQe6p8PD 4Pa59MrV88nCSmzaS5yaIdDTRMCwT1fh+rdHwbX8X2Mj6vO97B32E+LhDFC/ajVq1vckJ5 ao0jNiyVxS0yxtpE+QUcgJNIBws0LIo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-344-xIF6AqeQNsuWhvVYK2ymSg-1; Thu, 02 Dec 2021 02:04:58 -0500 X-MC-Unique: xIF6AqeQNsuWhvVYK2ymSg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CA7E483DD20; Thu, 2 Dec 2021 07:04:56 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-112-7.ams2.redhat.com [10.36.112.7]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 95F1F60C05; Thu, 2 Dec 2021 07:04:51 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 119211138606; Thu, 2 Dec 2021 08:04:50 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Subject: [PATCH RFC 01/11] vl: Cut off the CLI with an axe Date: Thu, 2 Dec 2021 08:04:40 +0100 Message-Id: <20211202070450.264743-2-armbru@redhat.com> In-Reply-To: <20211202070450.264743-1-armbru@redhat.com> References: <20211202070450.264743-1-armbru@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=armbru@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.719, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: damien.hedde@greensocs.com, berrange@redhat.com, mark.burton@greensocs.com, edgar.iglesias@gmail.co, mirela.grujic@greensocs.com, marcandre.lureau@redhat.com, pbonzini@redhat.com, jsnow@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" qemu-system-FOO starts up like this: 0. Basic, configuration-independent initialization 1. Parse and partially process CLI left to right 2. Startup with the remaining CLI processing mixed in With -preconfig, some of this is delayed until QMP command x-exit-preconfig. 3. Run main loop Monitors (if any) become available here. Note: * CLI is processed out of order. Few people understand the order, and only while starting at the code. Pretty much every time we mess with the order, we break something. * Without -preconfig, QMP becomes available only after startup is complete. Precludes use for initial configuration. -preconfig gives QMP one hook into startup, right before machine initialization. That's too early for cold-plugging devices. One hook doesn't fit all. * With -preconfig, CLI processing is interleaved with (in-order) QMP execution. I'm going to explore cleaner and more flexible startup code and CLI processing. The intertwined nature of the two makes this hard. So I start with cutting off the CLI entirely. I cut with an axe: certainly not enough (there's plenty of now unused CLI processing left, mostly in other files), and possibly too much (startup work might hide in the code I cut). Signed-off-by: Markus Armbruster --- softmmu/vl.c | 2694 +------------------------------------------------- 1 file changed, 13 insertions(+), 2681 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 620a1f1367..2bad7a437e 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -129,89 +129,14 @@ #include "config-host.h" -#define MAX_VIRTIO_CONSOLES 1 - -typedef struct BlockdevOptionsQueueEntry { - BlockdevOptions *bdo; - Location loc; - QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry; -} BlockdevOptionsQueueEntry; - -typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue; - -typedef struct ObjectOption { - ObjectOptions *opts; - QTAILQ_ENTRY(ObjectOption) next; -} ObjectOption; - -typedef struct DeviceOption { - QDict *opts; - Location loc; - QTAILQ_ENTRY(DeviceOption) next; -} DeviceOption; - -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 QTAILQ_HEAD(, DeviceOption) device_opts = QTAILQ_HEAD_INITIALIZER(device_opts); static ram_addr_t maxram_size; static uint64_t ram_slots; static int display_remote; -static int snapshot; static bool preconfig_requested; -static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); -static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); -static bool nographic = false; -static int mem_prealloc; /* force preallocation of physical target memory */ static ram_addr_t ram_size; -static const char *vga_model = NULL; static DisplayOptions dpy; -static int num_serial_hds; -static Chardev **serial_hds; -static const char *log_mask; -static const char *log_file; -static bool list_data_dirs; -static const char *watchdog; -static const char *qtest_chrdev; -static const char *qtest_log; - -static int has_defaults = 1; -static int default_serial = 1; -static int default_parallel = 1; -static int default_monitor = 1; -static int default_floppy = 1; -static int default_cdrom = 1; -static int default_sdcard = 1; -static int default_vga = 1; -static int default_net = 1; - -static struct { - const char *driver; - int *flag; -} default_list[] = { - { .driver = "isa-serial", .flag = &default_serial }, - { .driver = "isa-parallel", .flag = &default_parallel }, - { .driver = "isa-fdc", .flag = &default_floppy }, - { .driver = "floppy", .flag = &default_floppy }, - { .driver = "ide-cd", .flag = &default_cdrom }, - { .driver = "ide-hd", .flag = &default_cdrom }, - { .driver = "scsi-cd", .flag = &default_cdrom }, - { .driver = "scsi-hd", .flag = &default_cdrom }, - { .driver = "VGA", .flag = &default_vga }, - { .driver = "isa-vga", .flag = &default_vga }, - { .driver = "cirrus-vga", .flag = &default_vga }, - { .driver = "isa-cirrus-vga", .flag = &default_vga }, - { .driver = "vmware-svga", .flag = &default_vga }, - { .driver = "qxl-vga", .flag = &default_vga }, - { .driver = "virtio-vga", .flag = &default_vga }, - { .driver = "ati-vga", .flag = &default_vga }, - { .driver = "vhost-user-vga", .flag = &default_vga }, - { .driver = "virtio-vga-gl", .flag = &default_vga }, -}; static QemuOptsList qemu_rtc_opts = { .name = "rtc", @@ -501,214 +426,9 @@ const char *qemu_get_vm_name(void) return qemu_name; } -static void default_driver_disable(const char *driver) -{ - int i; - - if (!driver) { - return; - } - - for (i = 0; i < ARRAY_SIZE(default_list); i++) { - if (strcmp(default_list[i].driver, driver) != 0) - continue; - *(default_list[i].flag) = 0; - } -} - -static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp) -{ - const char *driver = qemu_opt_get(opts, "driver"); - - default_driver_disable(driver); - return 0; -} - -static void default_driver_check_json(void) -{ - DeviceOption *opt; - - QTAILQ_FOREACH(opt, &device_opts, next) { - const char *driver = qdict_get_try_str(opt->opts, "driver"); - default_driver_disable(driver); - } -} - -static int parse_name(void *opaque, QemuOpts *opts, Error **errp) -{ - const char *proc_name; - - if (qemu_opt_get(opts, "debug-threads")) { - qemu_thread_naming(qemu_opt_get_bool(opts, "debug-threads", false)); - } - qemu_name = qemu_opt_get(opts, "guest"); - - proc_name = qemu_opt_get(opts, "process"); - if (proc_name) { - os_set_proc_name(proc_name); - } - - return 0; -} - bool defaults_enabled(void) { - return has_defaults; -} - -#ifndef _WIN32 -static int parse_add_fd(void *opaque, QemuOpts *opts, Error **errp) -{ - int fd, dupfd, flags; - int64_t fdset_id; - const char *fd_opaque = NULL; - AddfdInfo *fdinfo; - - fd = qemu_opt_get_number(opts, "fd", -1); - fdset_id = qemu_opt_get_number(opts, "set", -1); - fd_opaque = qemu_opt_get(opts, "opaque"); - - if (fd < 0) { - error_setg(errp, "fd option is required and must be non-negative"); - return -1; - } - - if (fd <= STDERR_FILENO) { - error_setg(errp, "fd cannot be a standard I/O stream"); - return -1; - } - - /* - * All fds inherited across exec() necessarily have FD_CLOEXEC - * clear, while qemu sets FD_CLOEXEC on all other fds used internally. - */ - flags = fcntl(fd, F_GETFD); - if (flags == -1 || (flags & FD_CLOEXEC)) { - error_setg(errp, "fd is not valid or already in use"); - return -1; - } - - if (fdset_id < 0) { - error_setg(errp, "set option is required and must be non-negative"); - return -1; - } - -#ifdef F_DUPFD_CLOEXEC - dupfd = fcntl(fd, F_DUPFD_CLOEXEC, 0); -#else - dupfd = dup(fd); - if (dupfd != -1) { - qemu_set_cloexec(dupfd); - } -#endif - if (dupfd == -1) { - error_setg(errp, "error duplicating fd: %s", strerror(errno)); - return -1; - } - - /* add the duplicate fd, and optionally the opaque string, to the fd set */ - fdinfo = monitor_fdset_add_fd(dupfd, true, fdset_id, !!fd_opaque, fd_opaque, - &error_abort); - g_free(fdinfo); - - return 0; -} - -static int cleanup_add_fd(void *opaque, QemuOpts *opts, Error **errp) -{ - int fd; - - fd = qemu_opt_get_number(opts, "fd", -1); - close(fd); - - return 0; -} -#endif - -/***********************************************************/ -/* QEMU Block devices */ - -#define HD_OPTS "media=disk" -#define CDROM_OPTS "media=cdrom" -#define FD_OPTS "" -#define PFLASH_OPTS "" -#define MTD_OPTS "" -#define SD_OPTS "" - -static int drive_init_func(void *opaque, QemuOpts *opts, Error **errp) -{ - BlockInterfaceType *block_default_type = opaque; - - return drive_new(opts, *block_default_type, errp) == NULL; -} - -static int drive_enable_snapshot(void *opaque, QemuOpts *opts, Error **errp) -{ - if (qemu_opt_get(opts, "snapshot") == NULL) { - qemu_opt_set(opts, "snapshot", "on", &error_abort); - } - return 0; -} - -static void default_drive(int enable, int snapshot, BlockInterfaceType type, - int index, const char *optstr) -{ - QemuOpts *opts; - DriveInfo *dinfo; - - if (!enable || drive_get_by_index(type, index)) { - return; - } - - opts = drive_add(type, index, NULL, optstr); - if (snapshot) { - drive_enable_snapshot(NULL, opts, NULL); - } - - dinfo = drive_new(opts, type, &error_abort); - dinfo->is_default = true; - -} - -static void configure_blockdev(BlockdevOptionsQueue *bdo_queue, - MachineClass *machine_class, int snapshot) -{ - /* - * If the currently selected machine wishes to override the - * units-per-bus property of its default HBA interface type, do so - * now. - */ - if (machine_class->units_per_default_bus) { - override_max_devs(machine_class->block_default_type, - machine_class->units_per_default_bus); - } - - /* open the virtual block devices */ - while (!QSIMPLEQ_EMPTY(bdo_queue)) { - BlockdevOptionsQueueEntry *bdo = QSIMPLEQ_FIRST(bdo_queue); - - QSIMPLEQ_REMOVE_HEAD(bdo_queue, entry); - loc_push_restore(&bdo->loc); - qmp_blockdev_add(bdo->bdo, &error_fatal); - loc_pop(&bdo->loc); - qapi_free_BlockdevOptions(bdo->bdo); - g_free(bdo); - } - if (snapshot) { - qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, - NULL, NULL); - } - if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, - &machine_class->block_default_type, &error_fatal)) { - /* We printed help */ - exit(0); - } - - default_drive(default_cdrom, snapshot, machine_class->block_default_type, 2, - CDROM_OPTS); - default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS); - default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS); - + return false; } static QemuOptsList qemu_smp_opts = { @@ -751,41 +471,6 @@ static void realtime_init(void) } -static void configure_msg(QemuOpts *opts) -{ - message_with_timestamp = qemu_opt_get_bool(opts, "timestamp", false); - error_with_guestname = qemu_opt_get_bool(opts, "guest-name", false); -} - - -/***********************************************************/ -/* USB devices */ - -static int usb_device_add(const char *devname) -{ - USBDevice *dev = NULL; - - if (!machine_usb(current_machine)) { - return -1; - } - - dev = usbdevice_create(devname); - if (!dev) - return -1; - - return 0; -} - -static int usb_parse(const char *cmdline) -{ - int r; - r = usb_device_add(cmdline); - if (r < 0) { - error_report("could not add USB device '%s'", cmdline); - } - return r; -} - /***********************************************************/ /* machine registration */ @@ -821,64 +506,6 @@ static MachineClass *find_default_machine(GSList *machines) return default_machineclass; } -static void version(void) -{ - printf("QEMU emulator version " QEMU_FULL_VERSION "\n" - QEMU_COPYRIGHT "\n"); -} - -static void help(int exitcode) -{ - version(); - printf("usage: %s [options] [disk_image]\n\n" - "'disk_image' is a raw hard disk image for IDE hard disk 0\n\n", - error_get_progname()); - -#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \ - if ((arch_mask) & arch_type) \ - fputs(opt_help, stdout); - -#define ARCHHEADING(text, arch_mask) \ - if ((arch_mask) & arch_type) \ - puts(stringify(text)); - -#define DEFHEADING(text) ARCHHEADING(text, QEMU_ARCH_ALL) - -#include "qemu-options.def" - - printf("\nDuring emulation, the following keys are useful:\n" - "ctrl-alt-f toggle full screen\n" - "ctrl-alt-n switch to virtual console 'n'\n" - "ctrl-alt toggle mouse and keyboard grab\n" - "\n" - "When using -nographic, press 'ctrl-a h' to get some help.\n" - "\n" - QEMU_HELP_BOTTOM "\n"); - - exit(exitcode); -} - -#define HAS_ARG 0x0001 - -typedef struct QEMUOption { - const char *name; - int flags; - int index; - uint32_t arch_mask; -} QEMUOption; - -static const QEMUOption qemu_options[] = { - { "h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL }, - -#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \ - { option, opt_arg, opt_enum, arch_mask }, -#define DEFHEADING(text) -#define ARCHHEADING(text, arch_mask) - -#include "qemu-options.def" - { NULL }, -}; - typedef struct VGAInterfaceInfo { const char *opt_name; /* option name */ const char *name; /* human-readable name */ @@ -887,540 +514,13 @@ typedef struct VGAInterfaceInfo { const char *class_names[2]; } VGAInterfaceInfo; -static const VGAInterfaceInfo vga_interfaces[VGA_TYPE_MAX] = { - [VGA_NONE] = { - .opt_name = "none", - .name = "no graphic card", - }, - [VGA_STD] = { - .opt_name = "std", - .name = "standard VGA", - .class_names = { "VGA", "isa-vga" }, - }, - [VGA_CIRRUS] = { - .opt_name = "cirrus", - .name = "Cirrus VGA", - .class_names = { "cirrus-vga", "isa-cirrus-vga" }, - }, - [VGA_VMWARE] = { - .opt_name = "vmware", - .name = "VMWare SVGA", - .class_names = { "vmware-svga" }, - }, - [VGA_VIRTIO] = { - .opt_name = "virtio", - .name = "Virtio VGA", - .class_names = { "virtio-vga" }, - }, - [VGA_QXL] = { - .opt_name = "qxl", - .name = "QXL VGA", - .class_names = { "qxl-vga" }, - }, - [VGA_TCX] = { - .opt_name = "tcx", - .name = "TCX framebuffer", - .class_names = { "sun-tcx" }, - }, - [VGA_CG3] = { - .opt_name = "cg3", - .name = "CG3 framebuffer", - .class_names = { "cgthree" }, - }, - [VGA_XENFB] = { - .opt_name = "xenfb", - .name = "Xen paravirtualized framebuffer", - }, -}; - -static bool vga_interface_available(VGAInterfaceType t) -{ - const VGAInterfaceInfo *ti = &vga_interfaces[t]; - - assert(t < VGA_TYPE_MAX); - return !ti->class_names[0] || - module_object_class_by_name(ti->class_names[0]) || - module_object_class_by_name(ti->class_names[1]); -} - -static const char * -get_default_vga_model(const MachineClass *machine_class) -{ - if (machine_class->default_display) { - return machine_class->default_display; - } else if (vga_interface_available(VGA_CIRRUS)) { - return "cirrus"; - } else if (vga_interface_available(VGA_STD)) { - return "std"; - } - - return NULL; -} - -static void select_vgahw(const MachineClass *machine_class, const char *p) -{ - const char *opts; - int t; - - if (g_str_equal(p, "help")) { - const char *def = get_default_vga_model(machine_class); - - for (t = 0; t < VGA_TYPE_MAX; t++) { - const VGAInterfaceInfo *ti = &vga_interfaces[t]; - - if (vga_interface_available(t) && ti->opt_name) { - printf("%-20s %s%s\n", ti->opt_name, ti->name ?: "", - g_str_equal(ti->opt_name, def) ? " (default)" : ""); - } - } - exit(0); - } - - assert(vga_interface_type == VGA_NONE); - for (t = 0; t < VGA_TYPE_MAX; t++) { - const VGAInterfaceInfo *ti = &vga_interfaces[t]; - if (ti->opt_name && strstart(p, ti->opt_name, &opts)) { - if (!vga_interface_available(t)) { - error_report("%s not available", ti->name); - exit(1); - } - vga_interface_type = t; - break; - } - } - if (t == VGA_TYPE_MAX) { - invalid_vga: - error_report("unknown vga type: %s", p); - exit(1); - } - while (*opts) { - const char *nextopt; - - if (strstart(opts, ",retrace=", &nextopt)) { - opts = nextopt; - if (strstart(opts, "dumb", &nextopt)) - vga_retrace_method = VGA_RETRACE_DUMB; - else if (strstart(opts, "precise", &nextopt)) - vga_retrace_method = VGA_RETRACE_PRECISE; - else goto invalid_vga; - } else goto invalid_vga; - opts = nextopt; - } -} - -static void parse_display_qapi(const char *optarg) -{ - DisplayOptions *opts; - Visitor *v; - - v = qobject_input_visitor_new_str(optarg, "type", &error_fatal); - - visit_type_DisplayOptions(v, NULL, &opts, &error_fatal); - QAPI_CLONE_MEMBERS(DisplayOptions, &dpy, opts); - - qapi_free_DisplayOptions(opts); - visit_free(v); -} - DisplayOptions *qmp_query_display_options(Error **errp) { return QAPI_CLONE(DisplayOptions, &dpy); } -static void parse_display(const char *p) -{ - const char *opts; - - if (is_help_option(p)) { - qemu_display_help(); - exit(0); - } - - if (strstart(p, "sdl", &opts)) { - /* - * sdl DisplayType needs hand-crafted parser instead of - * parse_display_qapi() due to some options not in - * DisplayOptions, specifically: - * - ctrl_grab + alt_grab - * They can't be moved into the QAPI since they use underscores, - * thus they will get replaced by "grab-mod" in the long term - */ -#if defined(CONFIG_SDL) - dpy.type = DISPLAY_TYPE_SDL; - while (*opts) { - const char *nextopt; - - if (strstart(opts, ",grab-mod=", &nextopt)) { - opts = nextopt; - if (strstart(opts, "lshift-lctrl-lalt", &nextopt)) { - alt_grab = 1; - } else if (strstart(opts, "rctrl", &nextopt)) { - ctrl_grab = 1; - } else { - goto invalid_sdl_args; - } - } else if (strstart(opts, ",alt_grab=", &nextopt)) { - opts = nextopt; - if (strstart(opts, "on", &nextopt)) { - alt_grab = 1; - } else if (strstart(opts, "off", &nextopt)) { - alt_grab = 0; - } else { - goto invalid_sdl_args; - } - warn_report("alt_grab is deprecated, use grab-mod instead."); - } else if (strstart(opts, ",ctrl_grab=", &nextopt)) { - opts = nextopt; - if (strstart(opts, "on", &nextopt)) { - ctrl_grab = 1; - } else if (strstart(opts, "off", &nextopt)) { - ctrl_grab = 0; - } else { - goto invalid_sdl_args; - } - warn_report("ctrl_grab is deprecated, use grab-mod instead."); - } else if (strstart(opts, ",window_close=", &nextopt) || - strstart(opts, ",window-close=", &nextopt)) { - if (strstart(opts, ",window_close=", NULL)) { - warn_report("window_close with an underscore is deprecated," - " please use window-close instead."); - } - opts = nextopt; - dpy.has_window_close = true; - if (strstart(opts, "on", &nextopt)) { - dpy.window_close = true; - } else if (strstart(opts, "off", &nextopt)) { - dpy.window_close = false; - } else { - goto invalid_sdl_args; - } - } else if (strstart(opts, ",show-cursor=", &nextopt)) { - opts = nextopt; - dpy.has_show_cursor = true; - if (strstart(opts, "on", &nextopt)) { - dpy.show_cursor = true; - } else if (strstart(opts, "off", &nextopt)) { - dpy.show_cursor = false; - } else { - goto invalid_sdl_args; - } - } else if (strstart(opts, ",gl=", &nextopt)) { - opts = nextopt; - dpy.has_gl = true; - if (strstart(opts, "on", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_ON; - } else if (strstart(opts, "core", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_CORE; - } else if (strstart(opts, "es", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_ES; - } else if (strstart(opts, "off", &nextopt)) { - dpy.gl = DISPLAYGL_MODE_OFF; - } else { - goto invalid_sdl_args; - } - } else { - invalid_sdl_args: - error_report("invalid SDL option string"); - exit(1); - } - opts = nextopt; - } -#else - error_report("SDL display supported is not available in this binary"); - exit(1); -#endif - } else if (strstart(p, "vnc", &opts)) { - /* - * vnc isn't a (local) DisplayType but a protocol for remote - * display access. - */ - if (*opts == '=') { - vnc_parse(opts + 1); - } else { - error_report("VNC requires a display argument vnc="); - exit(1); - } - } else { - parse_display_qapi(p); - } -} - -static inline bool nonempty_str(const char *str) -{ - return str && *str; -} - -static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) -{ - gchar *buf; - size_t size; - const char *name, *file, *str, *gen_id; - FWCfgState *fw_cfg = (FWCfgState *) opaque; - - if (fw_cfg == NULL) { - error_setg(errp, "fw_cfg device not available"); - return -1; - } - name = qemu_opt_get(opts, "name"); - file = qemu_opt_get(opts, "file"); - str = qemu_opt_get(opts, "string"); - gen_id = qemu_opt_get(opts, "gen_id"); - - /* we need the name, and exactly one of: file, content string, gen_id */ - if (!nonempty_str(name) || - nonempty_str(file) + nonempty_str(str) + nonempty_str(gen_id) != 1) { - error_setg(errp, "name, plus exactly one of file," - " string and gen_id, are needed"); - return -1; - } - if (strlen(name) > FW_CFG_MAX_FILE_PATH - 1) { - error_setg(errp, "name too long (max. %d char)", - FW_CFG_MAX_FILE_PATH - 1); - return -1; - } - if (nonempty_str(gen_id)) { - /* - * In this particular case where the content is populated - * internally, the "etc/" namespace protection is relaxed, - * so do not emit a warning. - */ - } else if (strncmp(name, "opt/", 4) != 0) { - warn_report("externally provided fw_cfg item names " - "should be prefixed with \"opt/\""); - } - if (nonempty_str(str)) { - size = strlen(str); /* NUL terminator NOT included in fw_cfg blob */ - buf = g_memdup(str, size); - } else if (nonempty_str(gen_id)) { - if (!fw_cfg_add_from_generator(fw_cfg, name, gen_id, errp)) { - return -1; - } - return 0; - } else { - GError *err = NULL; - if (!g_file_get_contents(file, &buf, &size, &err)) { - error_setg(errp, "can't load %s: %s", file, err->message); - g_error_free(err); - return -1; - } - } - /* For legacy, keep user files in a specific global order. */ - fw_cfg_set_order_override(fw_cfg, FW_CFG_ORDER_OVERRIDE_USER); - fw_cfg_add_file(fw_cfg, name, buf, size); - fw_cfg_reset_order_override(fw_cfg); - return 0; -} - -static int device_help_func(void *opaque, QemuOpts *opts, Error **errp) -{ - return qdev_device_help(opts); -} - -static int device_init_func(void *opaque, QemuOpts *opts, Error **errp) -{ - DeviceState *dev; - - dev = qdev_device_add(opts, errp); - if (!dev && *errp) { - error_report_err(*errp); - return -1; - } else if (dev) { - object_unref(OBJECT(dev)); - } - return 0; -} - -static int chardev_init_func(void *opaque, QemuOpts *opts, Error **errp) -{ - Error *local_err = NULL; - - if (!qemu_chr_new_from_opts(opts, NULL, &local_err)) { - if (local_err) { - error_propagate(errp, local_err); - return -1; - } - exit(0); - } - return 0; -} - -#ifdef CONFIG_VIRTFS -static int fsdev_init_func(void *opaque, QemuOpts *opts, Error **errp) -{ - return qemu_fsdev_add(opts, errp); -} -#endif - -static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp) -{ - return monitor_init_opts(opts, errp); -} - -static void monitor_parse(const char *optarg, const char *mode, bool pretty) -{ - static int monitor_device_index = 0; - QemuOpts *opts; - const char *p; - char label[32]; - - if (strstart(optarg, "chardev:", &p)) { - snprintf(label, sizeof(label), "%s", p); - } else { - snprintf(label, sizeof(label), "compat_monitor%d", - monitor_device_index); - opts = qemu_chr_parse_compat(label, optarg, true); - if (!opts) { - error_report("parse error: %s", optarg); - exit(1); - } - } - - opts = qemu_opts_create(qemu_find_opts("mon"), label, 1, &error_fatal); - qemu_opt_set(opts, "mode", mode, &error_abort); - qemu_opt_set(opts, "chardev", label, &error_abort); - if (!strcmp(mode, "control")) { - qemu_opt_set_bool(opts, "pretty", pretty, &error_abort); - } else { - assert(pretty == false); - } - monitor_device_index++; -} - -struct device_config { - enum { - DEV_USB, /* -usbdevice */ - DEV_SERIAL, /* -serial */ - DEV_PARALLEL, /* -parallel */ - DEV_DEBUGCON, /* -debugcon */ - DEV_GDB, /* -gdb, -s */ - DEV_SCLP, /* s390 sclp */ - } type; - const char *cmdline; - Location loc; - QTAILQ_ENTRY(device_config) next; -}; - -static QTAILQ_HEAD(, device_config) device_configs = - QTAILQ_HEAD_INITIALIZER(device_configs); - -static void add_device_config(int type, const char *cmdline) -{ - struct device_config *conf; - - conf = g_malloc0(sizeof(*conf)); - conf->type = type; - conf->cmdline = cmdline; - loc_save(&conf->loc); - QTAILQ_INSERT_TAIL(&device_configs, conf, next); -} - -static int foreach_device_config(int type, int (*func)(const char *cmdline)) -{ - struct device_config *conf; - int rc; - - QTAILQ_FOREACH(conf, &device_configs, next) { - if (conf->type != type) - continue; - loc_push_restore(&conf->loc); - rc = func(conf->cmdline); - loc_pop(&conf->loc); - if (rc) { - return rc; - } - } - return 0; -} - -static void qemu_disable_default_devices(void) -{ - MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); - - default_driver_check_json(); - qemu_opts_foreach(qemu_find_opts("device"), - default_driver_check, NULL, NULL); - qemu_opts_foreach(qemu_find_opts("global"), - default_driver_check, NULL, NULL); - - if (!vga_model && !default_vga) { - vga_interface_type = VGA_DEVICE; - } - if (!has_defaults || machine_class->no_serial) { - default_serial = 0; - } - if (!has_defaults || machine_class->no_parallel) { - default_parallel = 0; - } - if (!has_defaults || machine_class->no_floppy) { - default_floppy = 0; - } - if (!has_defaults || machine_class->no_cdrom) { - default_cdrom = 0; - } - if (!has_defaults || machine_class->no_sdcard) { - default_sdcard = 0; - } - if (!has_defaults) { - default_monitor = 0; - default_net = 0; - default_vga = 0; - } -} - static void qemu_create_default_devices(void) { - MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); - - if (is_daemonized()) { - /* According to documentation and historically, -nographic redirects - * serial port, parallel port and monitor to stdio, which does not work - * with -daemonize. We can redirect these to null instead, but since - * -nographic is legacy, let's just error out. - * We disallow -nographic only if all other ports are not redirected - * explicitly, to not break existing legacy setups which uses - * -nographic _and_ redirects all ports explicitly - this is valid - * usage, -nographic is just a no-op in this case. - */ - if (nographic - && (default_parallel || default_serial || default_monitor)) { - error_report("-nographic cannot be used with -daemonize"); - exit(1); - } - } - - if (nographic) { - if (default_parallel) - add_device_config(DEV_PARALLEL, "null"); - if (default_serial && default_monitor) { - add_device_config(DEV_SERIAL, "mon:stdio"); - } else { - if (default_serial) - add_device_config(DEV_SERIAL, "stdio"); - if (default_monitor) - monitor_parse("stdio", "readline", false); - } - } else { - if (default_serial) - add_device_config(DEV_SERIAL, "vc:80Cx24C"); - if (default_parallel) - add_device_config(DEV_PARALLEL, "vc:80Cx24C"); - if (default_monitor) - monitor_parse("vc:80Cx24C", "readline", false); - } - - if (default_net) { - QemuOptsList *net = qemu_find_opts("net"); - qemu_opts_parse(net, "nic", true, &error_abort); -#ifdef CONFIG_SLIRP - qemu_opts_parse(net, "user", true, &error_abort); -#endif - } - -#if defined(CONFIG_VNC) - if (!QTAILQ_EMPTY(&(qemu_find_opts("vnc")->head))) { - display_remote++; - } -#endif if (dpy.type == DISPLAY_TYPE_DEFAULT && !display_remote) { if (!qemu_display_find_default(&dpy)) { dpy.type = DISPLAY_TYPE_NONE; @@ -1432,175 +532,13 @@ static void qemu_create_default_devices(void) if (dpy.type == DISPLAY_TYPE_DEFAULT) { dpy.type = DISPLAY_TYPE_NONE; } - - /* If no default VGA is requested, the default is "none". */ - if (default_vga) { - vga_model = get_default_vga_model(machine_class); - } - if (vga_model) { - select_vgahw(machine_class, vga_model); - } -} - -static int serial_parse(const char *devname) -{ - int index = num_serial_hds; - char label[32]; - - if (strcmp(devname, "none") == 0) - return 0; - snprintf(label, sizeof(label), "serial%d", index); - serial_hds = g_renew(Chardev *, serial_hds, index + 1); - - serial_hds[index] = qemu_chr_new_mux_mon(label, devname, NULL); - if (!serial_hds[index]) { - error_report("could not connect serial device" - " to character backend '%s'", devname); - return -1; - } - num_serial_hds++; - return 0; } Chardev *serial_hd(int i) { - assert(i >= 0); - if (i < num_serial_hds) { - return serial_hds[i]; - } return NULL; } -static int parallel_parse(const char *devname) -{ - static int index = 0; - char label[32]; - - if (strcmp(devname, "none") == 0) - return 0; - if (index == MAX_PARALLEL_PORTS) { - error_report("too many parallel ports"); - exit(1); - } - snprintf(label, sizeof(label), "parallel%d", index); - parallel_hds[index] = qemu_chr_new_mux_mon(label, devname, NULL); - if (!parallel_hds[index]) { - error_report("could not connect parallel device" - " to character backend '%s'", devname); - return -1; - } - index++; - return 0; -} - -static int debugcon_parse(const char *devname) -{ - QemuOpts *opts; - - if (!qemu_chr_new_mux_mon("debugcon", devname, NULL)) { - error_report("invalid character backend '%s'", devname); - exit(1); - } - opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL); - if (!opts) { - error_report("already have a debugcon device"); - exit(1); - } - qemu_opt_set(opts, "driver", "isa-debugcon", &error_abort); - qemu_opt_set(opts, "chardev", "debugcon", &error_abort); - return 0; -} - -static gint machine_class_cmp(gconstpointer a, gconstpointer b) -{ - const MachineClass *mc1 = a, *mc2 = b; - int res; - - if (mc1->family == NULL) { - if (mc2->family == NULL) { - /* Compare standalone machine types against each other; they sort - * in increasing order. - */ - return strcmp(object_class_get_name(OBJECT_CLASS(mc1)), - object_class_get_name(OBJECT_CLASS(mc2))); - } - - /* Standalone machine types sort after families. */ - return 1; - } - - if (mc2->family == NULL) { - /* Families sort before standalone machine types. */ - return -1; - } - - /* Families sort between each other alphabetically increasingly. */ - res = strcmp(mc1->family, mc2->family); - if (res != 0) { - return res; - } - - /* Within the same family, machine types sort in decreasing order. */ - return strcmp(object_class_get_name(OBJECT_CLASS(mc2)), - object_class_get_name(OBJECT_CLASS(mc1))); -} - -static void machine_help_func(const QDict *qdict) -{ - GSList *machines, *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; - } - } - - 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)" : ""); - } -} - -static void -machine_merge_property(const char *propname, QDict *prop, Error **errp) -{ - QDict *opts; - - opts = qdict_new(); - /* Preserve the caller's reference to prop. */ - qobject_ref(prop); - qdict_put(opts, propname, prop); - keyval_merge(machine_opts_dict, opts, errp); - qobject_unref(opts); -} - -static void -machine_parse_property_opt(QemuOptsList *opts_list, const char *propname, - const char *arg) -{ - QDict *prop = NULL; - bool help = false; - - prop = keyval_parse(arg, opts_list->implied_opt_name, &help, &error_fatal); - if (help) { - qemu_opts_print_help(opts_list, true); - exit(0); - } - machine_merge_property(propname, prop, &error_fatal); - qobject_unref(prop); -} - static const char *pid_file; static Notifier qemu_unlink_pidfile_notifier; @@ -1611,56 +549,15 @@ static void qemu_unlink_pidfile(Notifier *n, void *data) } } -static const QEMUOption *lookup_opt(int argc, char **argv, - const char **poptarg, int *poptind) +static MachineClass *select_machine(Error **errp) { - const QEMUOption *popt; - int optind = *poptind; - char *r = argv[optind]; - const char *optarg; - - loc_set_cmdline(argv, optind, 1); - optind++; - /* Treat --foo the same as -foo. */ - if (r[1] == '-') - r++; - popt = qemu_options; - for(;;) { - if (!popt->name) { - error_report("invalid option"); - exit(1); - } - if (!strcmp(popt->name, r + 1)) - break; - popt++; - } - if (popt->flags & HAS_ARG) { - if (optind >= argc) { - error_report("requires an argument"); - exit(1); - } - optarg = argv[optind++]; - loc_set_cmdline(argv, optind - 2, 2); - } else { - optarg = NULL; - } - - *poptarg = optarg; - *poptind = optind; - - return popt; -} - -static MachineClass *select_machine(QDict *qdict, Error **errp) -{ - const char *optarg = qdict_get_try_str(qdict, "type"); + const char *optarg = NULL; GSList *machines = object_class_get_list(TYPE_MACHINE, false); MachineClass *machine_class; Error *local_err = NULL; if (optarg) { machine_class = find_machine(optarg, machines); - qdict_del(qdict, "type"); if (!machine_class) { error_setg(&local_err, "unsupported machine type"); } @@ -1679,227 +576,16 @@ static MachineClass *select_machine(QDict *qdict, Error **errp) return machine_class; } -static int object_parse_property_opt(Object *obj, - const char *name, const char *value, - const char *skip, Error **errp) -{ - if (g_str_equal(name, skip)) { - return 0; - } - - if (!object_property_parse(obj, name, value, errp)) { - return -1; - } - - return 0; -} - -/* *Non*recursively replace underscores with dashes in QDict keys. */ -static void keyval_dashify(QDict *qdict, Error **errp) -{ - const QDictEntry *ent, *next; - char *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. */ - value = qdict_get_try_str(qdict, "accel"); - if (value) { - accelerators = g_strdup(value); - qdict_del(qdict, "accel"); - } - - 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 *)) -{ - ObjectOption *opt, *next; - - QTAILQ_FOREACH_SAFE(opt, &object_opts, next, next) { - const char *type = ObjectType_str(opt->opts->qom_type); - if (type_opt_predicate(type)) { - user_creatable_add_qapi(opt->opts, &error_fatal); - qapi_free_ObjectOptions(opt->opts); - QTAILQ_REMOVE(&object_opts, opt, next); - g_free(opt); - } - } -} - -static void object_option_add_visitor(Visitor *v) -{ - ObjectOption *opt = g_new0(ObjectOption, 1); - visit_type_ObjectOptions(v, NULL, &opt->opts, &error_fatal); - QTAILQ_INSERT_TAIL(&object_opts, opt, next); -} - -static void object_option_parse(const char *optarg) -{ - QemuOpts *opts; - const char *type; - Visitor *v; - - if (optarg[0] == '{') { - QObject *obj = qobject_from_json(optarg, &error_fatal); - - v = qobject_input_visitor_new(obj); - qobject_unref(obj); - } else { - opts = qemu_opts_parse_noisily(qemu_find_opts("object"), - optarg, true); - if (!opts) { - exit(1); - } - - type = qemu_opt_get(opts, "qom-type"); - if (!type) { - error_setg(&error_fatal, QERR_MISSING_PARAMETER, "qom-type"); - } - if (user_creatable_print_help(type, opts)) { - exit(0); - } - - v = opts_visitor_new(opts); - } - - object_option_add_visitor(v); - visit_free(v); -} - -/* - * Initial object creation happens before all other - * QEMU data types are created. The majority of objects - * can be created at this point. The rng-egd object - * cannot be created here, as it depends on the chardev - * already existing. - */ -static bool object_create_early(const char *type) -{ - /* - * Objects should not be made "delayed" without a reason. If you - * add one, state the reason in a comment! - */ - - /* Reason: property "chardev" */ - if (g_str_equal(type, "rng-egd") || - g_str_equal(type, "qtest")) { - return false; - } - -#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX) - /* Reason: cryptodev-vhost-user property "chardev" */ - if (g_str_equal(type, "cryptodev-vhost-user")) { - return false; - } -#endif - - /* Reason: vhost-user-blk-server property "node-name" */ - if (g_str_equal(type, "vhost-user-blk-server")) { - return false; - } - /* - * Reason: filter-* property "netdev" etc. - */ - if (g_str_equal(type, "filter-buffer") || - g_str_equal(type, "filter-dump") || - g_str_equal(type, "filter-mirror") || - g_str_equal(type, "filter-redirector") || - g_str_equal(type, "colo-compare") || - g_str_equal(type, "filter-rewriter") || - g_str_equal(type, "filter-replay")) { - return false; - } - - /* - * Allocation of large amounts of memory may delay - * chardev initialization for too long, and trigger timeouts - * on software that waits for a monitor socket to be created - * (e.g. libvirt). - */ - if (g_str_has_prefix(type, "memory-backend-")) { - return false; - } - - return true; -} - static void qemu_apply_machine_options(QDict *qdict) { MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); const char *boot_order = NULL; const char *boot_once = NULL; - QemuOpts *opts; - 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; - opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); - if (opts) { - boot_order = qemu_opt_get(opts, "order"); - if (boot_order) { - validate_bootdevices(boot_order, &error_fatal); - } - - boot_once = qemu_opt_get(opts, "once"); - if (boot_once) { - validate_bootdevices(boot_once, &error_fatal); - } - - boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); - boot_strict = qemu_opt_get_bool(opts, "strict", false); - } - if (!boot_order) { boot_order = machine_class->default_boot_order; } @@ -1907,11 +593,6 @@ static void qemu_apply_machine_options(QDict *qdict) current_machine->boot_order = boot_order; current_machine->boot_once = boot_once; - if (semihosting_enabled() && !semihosting_get_argc()) { - /* fall back to the -kernel/-append */ - semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline); - } - if (current_machine->smp.cpus > 1) { Error *blocker = NULL; error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp"); @@ -1921,27 +602,6 @@ static void qemu_apply_machine_options(QDict *qdict) static void qemu_create_early_backends(void) { - MachineClass *machine_class = MACHINE_GET_CLASS(current_machine); -#if defined(CONFIG_SDL) - const bool use_sdl = (dpy.type == DISPLAY_TYPE_SDL); -#else - const bool use_sdl = false; -#endif -#if defined(CONFIG_GTK) - const bool use_gtk = (dpy.type == DISPLAY_TYPE_GTK); -#else - const bool use_gtk = false; -#endif - - if ((alt_grab || ctrl_grab) && !use_sdl) { - error_report("-alt-grab and -ctrl-grab are only valid " - "for SDL, ignoring option"); - } - if (dpy.has_window_close && !use_gtk && !use_sdl) { - error_report("-no-quit is only valid for GTK and SDL, " - "ignoring option"); - } - qemu_display_early_init(&dpy); qemu_console_early_init(); @@ -1954,63 +614,21 @@ static void qemu_create_early_backends(void) exit(1); } - object_option_foreach_add(object_create_early); - /* spice needs the timers to be initialized by this point */ /* spice must initialize before audio as it changes the default auiodev */ /* spice must initialize before chardevs (for spicevmc and spiceport) */ qemu_spice.init(); - - qemu_opts_foreach(qemu_find_opts("chardev"), - chardev_init_func, NULL, &error_fatal); - -#ifdef CONFIG_VIRTFS - qemu_opts_foreach(qemu_find_opts("fsdev"), - fsdev_init_func, NULL, &error_fatal); -#endif - - /* - * Note: we need to create audio and block backends before - * setting machine properties, so they can be referred to. - */ - configure_blockdev(&bdo_queue, machine_class, snapshot); - audio_init_audiodevs(); } -/* - * The remainder of object creation happens after the - * creation of chardev, fsdev, net clients and device data types. - */ -static bool object_create_late(const char *type) -{ - return !object_create_early(type); -} - static void qemu_create_late_backends(void) { - if (qtest_chrdev) { - qtest_server_init(qtest_chrdev, qtest_log, &error_fatal); - } - net_init_clients(&error_fatal); - object_option_foreach_add(object_create_late); - if (tpm_init() < 0) { exit(1); } - qemu_opts_foreach(qemu_find_opts("mon"), - mon_init_func, NULL, &error_fatal); - - if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) - exit(1); - if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) - exit(1); - if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0) - exit(1); - /* now chardevs have been created we may have semihosting to connect */ qemu_semihosting_connect_chardevs(); qemu_semihosting_console_init(); @@ -2018,8 +636,7 @@ static void qemu_create_late_backends(void) static bool have_custom_ram_size(void) { - QemuOpts *opts = qemu_find_opts_singleton("memory"); - return !!qemu_opt_get_size(opts, "size", 0); + return false; } static void qemu_resolve_machine_memdev(void) @@ -2041,11 +658,6 @@ static void qemu_resolve_machine_memdev(void) "explicitly specified 'memory-backend' property"); exit(EXIT_FAILURE); } - if (mem_path) { - error_report("'-mem-path' can't be used together with" - "'-machine memory-backend'"); - exit(EXIT_FAILURE); - } ram_size = backend_size; } @@ -2061,35 +673,9 @@ static void qemu_resolve_machine_memdev(void) static void set_memory_options(MachineClass *mc) { uint64_t sz; - const char *mem_str; const ram_addr_t default_ram_size = mc->default_ram_size; - QemuOpts *opts = qemu_find_opts_singleton("memory"); - Location loc; - - loc_push_none(&loc); - qemu_opts_loc_restore(opts); sz = 0; - mem_str = qemu_opt_get(opts, "size"); - if (mem_str) { - if (!*mem_str) { - error_report("missing 'size' option value"); - exit(EXIT_FAILURE); - } - - sz = qemu_opt_get_size(opts, "size", ram_size); - - /* Fix up legacy suffix-less format */ - if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) { - uint64_t overflow_check = sz; - - sz *= MiB; - if (sz / MiB != overflow_check) { - error_report("too large 'size' option value"); - exit(EXIT_FAILURE); - } - } - } /* backward compatibility behaviour for case "-m 0" */ if (sz == 0) { @@ -2107,39 +693,11 @@ static void set_memory_options(MachineClass *mc) } maxram_size = ram_size; - - if (qemu_opt_get(opts, "maxmem")) { - uint64_t slots; - - sz = qemu_opt_get_size(opts, "maxmem", 0); - slots = qemu_opt_get_number(opts, "slots", 0); - if (sz < ram_size) { - error_report("invalid value of -m option maxmem: " - "maximum memory size (0x%" PRIx64 ") must be at least " - "the initial memory size (0x" RAM_ADDR_FMT ")", - sz, ram_size); - exit(EXIT_FAILURE); - } else if (slots && sz == ram_size) { - error_report("invalid value of -m option maxmem: " - "memory slots were specified but maximum memory size " - "(0x%" PRIx64 ") is equal to the initial memory size " - "(0x" RAM_ADDR_FMT ")", sz, ram_size); - exit(EXIT_FAILURE); - } - - maxram_size = sz; - ram_slots = slots; - } else if (qemu_opt_get(opts, "slots")) { - error_report("invalid -m option value: missing 'maxmem' option"); - exit(EXIT_FAILURE); - } - - loc_pop(&loc); } -static void qemu_create_machine(QDict *qdict) +static void qemu_create_machine(void) { - MachineClass *machine_class = select_machine(qdict, &error_fatal); + MachineClass *machine_class = select_machine(&error_fatal); object_set_machine_compat_props(machine_class->compat_props); set_memory_options(machine_class); @@ -2175,152 +733,12 @@ static void qemu_create_machine(QDict *qdict) QDict *default_opts = keyval_parse(machine_class->default_machine_opts, NULL, NULL, &error_abort); - qemu_apply_legacy_machine_options(default_opts); object_set_properties_from_keyval(OBJECT(current_machine), default_opts, false, &error_abort); qobject_unref(default_opts); } } -static int global_init_func(void *opaque, QemuOpts *opts, Error **errp) -{ - GlobalProperty *g; - - g = g_malloc0(sizeof(*g)); - g->driver = qemu_opt_get(opts, "driver"); - g->property = qemu_opt_get(opts, "property"); - g->value = qemu_opt_get(opts, "value"); - qdev_prop_register_global(g); - return 0; -} - -/* - * Return whether configuration group @group is stored in QemuOpts, or - * recorded as one or more QDicts by qemu_record_config_group. - */ -static bool is_qemuopts_group(const char *group) -{ - if (g_str_equal(group, "object") || - g_str_equal(group, "machine") || - g_str_equal(group, "smp-opts")) { - return false; - } - return true; -} - -static void qemu_record_config_group(const char *group, QDict *dict, - bool from_json, Error **errp) -{ - if (g_str_equal(group, "object")) { - 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 if (g_str_equal(group, "smp-opts")) { - machine_merge_property("smp", dict, &error_fatal); - } else { - abort(); - } -} - -/* - * Parse non-QemuOpts config file groups, pass the rest to - * qemu_config_do_parse. - */ -static void qemu_parse_config_group(const char *group, QDict *qdict, - void *opaque, Error **errp) -{ - QObject *crumpled; - if (is_qemuopts_group(group)) { - qemu_config_do_parse(group, qdict, opaque, errp); - return; - } - - crumpled = qdict_crumple(qdict, errp); - if (!crumpled) { - return; - } - switch (qobject_type(crumpled)) { - case QTYPE_QDICT: - qemu_record_config_group(group, qobject_to(QDict, crumpled), false, errp); - break; - case QTYPE_QLIST: - error_setg(errp, "Lists cannot be at top level of a configuration section"); - break; - default: - g_assert_not_reached(); - } - qobject_unref(crumpled); -} - -static void qemu_read_default_config_file(Error **errp) -{ - ERRP_GUARD(); - int ret; - g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf"); - - ret = qemu_read_config_file(file, qemu_parse_config_group, errp); - if (ret < 0) { - if (ret == -ENOENT) { - error_free(*errp); - *errp = NULL; - } - } -} - -static void qemu_set_option(const char *str, Error **errp) -{ - char group[64], id[64], arg[64]; - QemuOptsList *list; - QemuOpts *opts; - int rc, offset; - - rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); - if (rc < 3 || str[offset] != '=') { - error_setg(errp, "can't parse: \"%s\"", str); - return; - } - - if (!is_qemuopts_group(group)) { - error_setg(errp, "-set is not supported with %s", group); - } else { - list = qemu_find_opts_err(group, errp); - if (list) { - opts = qemu_opts_find(list, id); - if (!opts) { - error_setg(errp, "there is no %s \"%s\" defined", group, id); - return; - } - qemu_opt_set(opts, arg, str + offset + 1, errp); - } - } -} - -static void user_register_global_props(void) -{ - qemu_opts_foreach(qemu_find_opts("global"), - global_init_func, NULL, NULL); -} - -static int do_configure_icount(void *opaque, QemuOpts *opts, Error **errp) -{ - icount_configure(opts, errp); - return 0; -} - -static int accelerator_set_property(void *opaque, - const char *name, const char *value, - Error **errp) -{ - return object_parse_property_opt(opaque, name, value, "accel", errp); -} - static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp) { bool *p_init_failed = opaque; @@ -2330,7 +748,7 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp) int ret; bool qtest_with_kvm; - qtest_with_kvm = g_str_equal(acc, "kvm") && qtest_chrdev != NULL; + qtest_with_kvm = false; if (!ac) { *p_init_failed = true; @@ -2341,9 +759,6 @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp) } accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac))); object_apply_compat_props(OBJECT(accel)); - qemu_opt_foreach(opts, accelerator_set_property, - accel, - &error_fatal); ret = accel_init_machine(accel, current_machine); if (ret < 0) { @@ -2361,9 +776,6 @@ static void configure_accelerators(const char *progname) { bool init_failed = false; - qemu_opts_foreach(qemu_find_opts("icount"), - do_configure_icount, NULL, &error_fatal); - if (QTAILQ_EMPTY(&qemu_accel_opts.head)) { char **accel_list, **tmp; @@ -2419,7 +831,7 @@ static void configure_accelerators(const char *progname) exit(1); } - if (init_failed && !qtest_chrdev) { + if (init_failed) { AccelClass *ac = ACCEL_GET_CLASS(current_accel()); error_report("falling back to %s", ac->name); } @@ -2451,153 +863,13 @@ static void create_default_memdev(MachineState *ms, const char *path) &error_fatal); } -static void qemu_validate_options(const QDict *machine_opts) -{ - 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) { - error_report("-append only allowed with -kernel option"); - exit(1); - } - - if (initrd_filename != NULL) { - error_report("-initrd only allowed with -kernel option"); - exit(1); - } - } - - if (loadvm && preconfig_requested) { - error_report("'preconfig' and 'loadvm' options are " - "mutually exclusive"); - exit(EXIT_FAILURE); - } - if (incoming && preconfig_requested && strcmp(incoming, "defer") != 0) { - error_report("'preconfig' supports '-incoming defer' only"); - exit(EXIT_FAILURE); - } - -#ifdef CONFIG_CURSES - if (is_daemonized() && dpy.type == DISPLAY_TYPE_CURSES) { - error_report("curses display cannot be used with -daemonize"); - exit(1); - } -#endif -} - -static void qemu_process_sugar_options(void) -{ - if (mem_prealloc) { - QObject *smp = qdict_get(machine_opts_dict, "smp"); - if (smp && qobject_type(smp) == QTYPE_QDICT) { - QObject *cpus = qdict_get(qobject_to(QDict, smp), "cpus"); - if (cpus && qobject_type(cpus) == QTYPE_QSTRING) { - const char *val = qstring_get_str(qobject_to(QString, cpus)); - object_register_sugar_prop("memory-backend", "prealloc-threads", - val, false); - } - } - object_register_sugar_prop("memory-backend", "prealloc", "on", false); - } - - if (watchdog) { - int i = select_watchdog(watchdog); - if (i > 0) - exit (i == 1 ? 1 : 0); - } -} - -/* -action processing */ - -/* - * Process all the -action parameters parsed from cmdline. - */ -static int process_runstate_actions(void *opaque, QemuOpts *opts, Error **errp) -{ - Error *local_err = NULL; - QDict *qdict = qemu_opts_to_qdict(opts, NULL); - QObject *ret = NULL; - qmp_marshal_set_action(qdict, &ret, &local_err); - qobject_unref(ret); - qobject_unref(qdict); - if (local_err) { - error_propagate(errp, local_err); - return 1; - } - return 0; -} - static void qemu_process_early_options(void) { -#ifdef CONFIG_SECCOMP - QemuOptsList *olist = qemu_find_opts_err("sandbox", NULL); - if (olist) { - qemu_opts_foreach(olist, parse_sandbox, NULL, &error_fatal); - } -#endif - - qemu_opts_foreach(qemu_find_opts("name"), - parse_name, NULL, &error_fatal); - - if (qemu_opts_foreach(qemu_find_opts("action"), - process_runstate_actions, NULL, &error_fatal)) { - exit(1); - } - -#ifndef _WIN32 - qemu_opts_foreach(qemu_find_opts("add-fd"), - parse_add_fd, NULL, &error_fatal); - - qemu_opts_foreach(qemu_find_opts("add-fd"), - cleanup_add_fd, NULL, &error_fatal); -#endif - - /* Open the logfile at this point and set the log mask if necessary. */ - if (log_file) { - qemu_set_log_filename(log_file, &error_fatal); - } - if (log_mask) { - int mask; - mask = qemu_str_to_log_mask(log_mask); - if (!mask) { - qemu_print_log_usage(stdout); - exit(1); - } - qemu_set_log(mask); - } else { - qemu_set_log(0); - } + qemu_set_log(0); qemu_add_default_firmwarepath(); } -static void qemu_process_help_options(void) -{ - /* - * Check for -cpu help and -device help before we call select_machine(), - * which will return an error if the architecture has no default machine - * type and the user did not specify one, so that the user doesn't need - * to say '-cpu help -machine something'. - */ - if (cpu_option && is_help_option(cpu_option)) { - list_cpus(cpu_option); - exit(0); - } - - if (qemu_opts_foreach(qemu_find_opts("device"), - device_help_func, NULL, NULL)) { - exit(0); - } - - /* -L help lists the data directories and exits. */ - if (list_data_dirs) { - qemu_list_data_dirs(); - exit(0); - } -} - static void qemu_maybe_daemonize(const char *pid_file) { Error *err = NULL; @@ -2625,12 +897,6 @@ static void qemu_init_displays(void) /* must be after terminal init, SDL library changes signal handlers */ os_setup_signal_handling(); - /* init remote displays */ -#ifdef CONFIG_VNC - qemu_opts_foreach(qemu_find_opts("vnc"), - vnc_init_func, NULL, &error_fatal); -#endif - if (using_spice) { qemu_spice.display_init(); } @@ -2642,12 +908,9 @@ static void qemu_init_board(void) if (machine_class->default_ram_id && current_machine->ram_size && numa_uses_legacy_mem() && !current_machine->ram_memdev_id) { - create_default_memdev(current_machine, mem_path); + create_default_memdev(current_machine, NULL); } - /* process plugin before CPUs are created, but once -smp has been parsed */ - qemu_plugin_load_list(&plugin_list, &error_fatal); - /* From here on we enter MACHINE_PHASE_INITIALIZED. */ machine_run_board_init(current_machine); @@ -2661,40 +924,6 @@ static void qemu_init_board(void) } } -static void qemu_create_cli_devices(void) -{ - DeviceOption *opt; - - soundhw_init(); - - qemu_opts_foreach(qemu_find_opts("fw_cfg"), - parse_fw_cfg, fw_cfg_find(), &error_fatal); - - /* init USB devices */ - if (machine_usb(current_machine)) { - if (foreach_device_config(DEV_USB, usb_parse) < 0) - exit(1); - } - - /* init generic devices */ - rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE); - qemu_opts_foreach(qemu_find_opts("device"), - device_init_func, NULL, &error_fatal); - QTAILQ_FOREACH(opt, &device_opts, next) { - loc_push_restore(&opt->loc); - /* - * TODO Eventually we should call qmp_device_add() here to make sure it - * behaves the same, but QMP still has to accept incorrectly typed - * options until libvirt is fixed and we want to be strict on the CLI - * from the start, so call qdev_device_add_from_qdict() directly for - * now. - */ - qdev_device_add_from_qdict(opt->opts, true, &error_fatal); - loc_pop(&opt->loc); - } - rom_reset_order_override(); -} - static void qemu_machine_creation_done(void) { MachineState *machine = MACHINE(qdev_get_machine()); @@ -2702,17 +931,7 @@ static void qemu_machine_creation_done(void) /* Did we create any drives that we failed to create a device for? */ drive_check_orphaned(); - /* Don't warn about the default network setup that you get if - * no command line -net or -netdev options are specified. There - * are two cases that we would otherwise complain about: - * (1) board doesn't support a NIC but the implicit "-net nic" - * requested one - * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic" - * sets up a nic that isn't connected to anything. - */ - if (!default_net && (!qtest_enabled() || has_defaults)) { - net_check_clients(); - } + net_check_clients(); qdev_prop_check_globals(); @@ -2724,10 +943,6 @@ static void qemu_machine_creation_done(void) */ assert(machine->cgs->ready); } - - if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { - exit(1); - } } void qmp_x_exit_preconfig(Error **errp) @@ -2738,12 +953,8 @@ void qmp_x_exit_preconfig(Error **errp) } qemu_init_board(); - qemu_create_cli_devices(); qemu_machine_creation_done(); - if (loadvm) { - load_snapshot(loadvm, NULL, false, NULL, &error_fatal); - } if (replay_mode != REPLAY_MODE_NONE) { replay_vmstate_init(); } @@ -2764,13 +975,7 @@ void qmp_x_exit_preconfig(Error **errp) void qemu_init(int argc, char **argv, char **envp) { - QemuOpts *opts; - QemuOpts *icount_opts = NULL, *accel_opts = NULL; - QemuOptsList *olist; - int optind; - const char *optarg; MachineClass *machine_class; - bool userconfig = true; FILE *vmstate_dump_file = NULL; qemu_add_opts(&qemu_drive_opts); @@ -2816,871 +1021,8 @@ void qemu_init(int argc, char **argv, char **envp) qemu_init_subsystems(); - /* first pass of option parsing */ - optind = 1; - while (optind < argc) { - if (argv[optind][0] != '-') { - /* disk image */ - optind++; - } else { - const QEMUOption *popt; - - popt = lookup_opt(argc, argv, &optarg, &optind); - switch (popt->index) { - case QEMU_OPTION_nouserconfig: - userconfig = false; - break; - } - } - } - - machine_opts_dict = qdict_new(); - if (userconfig) { - qemu_read_default_config_file(&error_fatal); - } - - /* second pass of option parsing */ - optind = 1; - for(;;) { - if (optind >= argc) - break; - if (argv[optind][0] != '-') { - loc_set_cmdline(argv, optind, 1); - drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS); - } else { - const QEMUOption *popt; - - popt = lookup_opt(argc, argv, &optarg, &optind); - if (!(popt->arch_mask & arch_type)) { - error_report("Option not supported for this target"); - exit(1); - } - switch(popt->index) { - case QEMU_OPTION_cpu: - /* hw initialization will check this */ - cpu_option = optarg; - break; - case QEMU_OPTION_hda: - case QEMU_OPTION_hdb: - case QEMU_OPTION_hdc: - case QEMU_OPTION_hdd: - drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg, - HD_OPTS); - break; - case QEMU_OPTION_blockdev: - { - Visitor *v; - BlockdevOptionsQueueEntry *bdo; - - v = qobject_input_visitor_new_str(optarg, "driver", - &error_fatal); - - bdo = g_new(BlockdevOptionsQueueEntry, 1); - visit_type_BlockdevOptions(v, NULL, &bdo->bdo, - &error_fatal); - visit_free(v); - loc_save(&bdo->loc); - QSIMPLEQ_INSERT_TAIL(&bdo_queue, bdo, entry); - break; - } - case QEMU_OPTION_drive: - if (drive_def(optarg) == NULL) { - exit(1); - } - break; - case QEMU_OPTION_set: - qemu_set_option(optarg, &error_fatal); - break; - case QEMU_OPTION_global: - if (qemu_global_option(optarg) != 0) - exit(1); - break; - case QEMU_OPTION_mtdblock: - drive_add(IF_MTD, -1, optarg, MTD_OPTS); - break; - case QEMU_OPTION_sd: - drive_add(IF_SD, -1, optarg, SD_OPTS); - break; - case QEMU_OPTION_pflash: - drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS); - break; - case QEMU_OPTION_snapshot: - { - Error *blocker = NULL; - snapshot = 1; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, - "-snapshot"); - replay_add_blocker(blocker); - } - break; - case QEMU_OPTION_numa: - opts = qemu_opts_parse_noisily(qemu_find_opts("numa"), - optarg, true); - if (!opts) { - exit(1); - } - break; - case QEMU_OPTION_display: - parse_display(optarg); - break; - case QEMU_OPTION_nographic: - qdict_put_str(machine_opts_dict, "graphics", "off"); - nographic = true; - dpy.type = DISPLAY_TYPE_NONE; - break; - case QEMU_OPTION_curses: - warn_report("-curses is deprecated, " - "use -display curses instead."); -#ifdef CONFIG_CURSES - dpy.type = DISPLAY_TYPE_CURSES; -#else - error_report("curses or iconv support is disabled"); - exit(1); -#endif - break; - case QEMU_OPTION_portrait: - graphic_rotate = 90; - break; - case QEMU_OPTION_rotate: - graphic_rotate = strtol(optarg, (char **) &optarg, 10); - if (graphic_rotate != 0 && graphic_rotate != 90 && - graphic_rotate != 180 && graphic_rotate != 270) { - error_report("only 90, 180, 270 deg rotation is available"); - exit(1); - } - break; - case QEMU_OPTION_kernel: - qdict_put_str(machine_opts_dict, "kernel", optarg); - break; - case QEMU_OPTION_initrd: - qdict_put_str(machine_opts_dict, "initrd", optarg); - break; - case QEMU_OPTION_append: - qdict_put_str(machine_opts_dict, "append", optarg); - break; - case QEMU_OPTION_dtb: - qdict_put_str(machine_opts_dict, "dtb", optarg); - break; - case QEMU_OPTION_cdrom: - drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS); - break; - case QEMU_OPTION_boot: - opts = qemu_opts_parse_noisily(qemu_find_opts("boot-opts"), - optarg, true); - if (!opts) { - exit(1); - } - break; - case QEMU_OPTION_fda: - case QEMU_OPTION_fdb: - drive_add(IF_FLOPPY, popt->index - QEMU_OPTION_fda, - optarg, FD_OPTS); - break; - case QEMU_OPTION_no_fd_bootchk: - fd_bootchk = 0; - break; - case QEMU_OPTION_netdev: - default_net = 0; - if (net_client_parse(qemu_find_opts("netdev"), optarg) == -1) { - exit(1); - } - break; - case QEMU_OPTION_nic: - default_net = 0; - if (net_client_parse(qemu_find_opts("nic"), optarg) == -1) { - exit(1); - } - break; - case QEMU_OPTION_net: - default_net = 0; - if (net_client_parse(qemu_find_opts("net"), optarg) == -1) { - exit(1); - } - break; -#ifdef CONFIG_LIBISCSI - case QEMU_OPTION_iscsi: - opts = qemu_opts_parse_noisily(qemu_find_opts("iscsi"), - optarg, false); - if (!opts) { - exit(1); - } - break; -#endif - case QEMU_OPTION_audio_help: - audio_legacy_help(); - exit (0); - break; - case QEMU_OPTION_audiodev: - audio_parse_option(optarg); - break; - case QEMU_OPTION_soundhw: - select_soundhw (optarg); - break; - case QEMU_OPTION_h: - help(0); - break; - case QEMU_OPTION_version: - version(); - exit(0); - break; - case QEMU_OPTION_m: - opts = qemu_opts_parse_noisily(qemu_find_opts("memory"), - optarg, true); - if (!opts) { - exit(EXIT_FAILURE); - } - break; -#ifdef CONFIG_TPM - case QEMU_OPTION_tpmdev: - if (tpm_config_parse(qemu_find_opts("tpmdev"), optarg) < 0) { - exit(1); - } - break; -#endif - case QEMU_OPTION_mempath: - mem_path = optarg; - break; - case QEMU_OPTION_mem_prealloc: - mem_prealloc = 1; - break; - case QEMU_OPTION_d: - log_mask = optarg; - break; - case QEMU_OPTION_D: - log_file = optarg; - break; - case QEMU_OPTION_DFILTER: - qemu_set_dfilter_ranges(optarg, &error_fatal); - break; - case QEMU_OPTION_seed: - qemu_guest_random_seed_main(optarg, &error_fatal); - break; - case QEMU_OPTION_s: - add_device_config(DEV_GDB, "tcp::" DEFAULT_GDBSTUB_PORT); - break; - case QEMU_OPTION_gdb: - add_device_config(DEV_GDB, optarg); - break; - case QEMU_OPTION_L: - if (is_help_option(optarg)) { - list_data_dirs = true; - } else { - qemu_add_data_dir(g_strdup(optarg)); - } - break; - case QEMU_OPTION_bios: - qdict_put_str(machine_opts_dict, "firmware", optarg); - break; - case QEMU_OPTION_singlestep: - singlestep = 1; - break; - case QEMU_OPTION_S: - autostart = 0; - break; - case QEMU_OPTION_k: - keyboard_layout = optarg; - break; - case QEMU_OPTION_vga: - vga_model = optarg; - default_vga = 0; - break; - case QEMU_OPTION_g: - { - const char *p; - int w, h, depth; - p = optarg; - w = strtol(p, (char **)&p, 10); - if (w <= 0) { - graphic_error: - error_report("invalid resolution or depth"); - exit(1); - } - if (*p != 'x') - goto graphic_error; - p++; - h = strtol(p, (char **)&p, 10); - if (h <= 0) - goto graphic_error; - if (*p == 'x') { - p++; - depth = strtol(p, (char **)&p, 10); - if (depth != 1 && depth != 2 && depth != 4 && - depth != 8 && depth != 15 && depth != 16 && - depth != 24 && depth != 32) - goto graphic_error; - } else if (*p == '\0') { - depth = graphic_depth; - } else { - goto graphic_error; - } - - graphic_width = w; - graphic_height = h; - graphic_depth = depth; - } - break; - case QEMU_OPTION_echr: - { - char *r; - term_escape_char = strtol(optarg, &r, 0); - if (r == optarg) - printf("Bad argument to echr\n"); - break; - } - case QEMU_OPTION_monitor: - default_monitor = 0; - if (strncmp(optarg, "none", 4)) { - monitor_parse(optarg, "readline", false); - } - break; - case QEMU_OPTION_qmp: - monitor_parse(optarg, "control", false); - default_monitor = 0; - break; - case QEMU_OPTION_qmp_pretty: - monitor_parse(optarg, "control", true); - default_monitor = 0; - break; - case QEMU_OPTION_mon: - opts = qemu_opts_parse_noisily(qemu_find_opts("mon"), optarg, - true); - if (!opts) { - exit(1); - } - default_monitor = 0; - break; - case QEMU_OPTION_chardev: - opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), - optarg, true); - if (!opts) { - exit(1); - } - break; - case QEMU_OPTION_fsdev: - olist = qemu_find_opts("fsdev"); - if (!olist) { - error_report("fsdev support is disabled"); - exit(1); - } - opts = qemu_opts_parse_noisily(olist, optarg, true); - if (!opts) { - exit(1); - } - break; - case QEMU_OPTION_virtfs: { - QemuOpts *fsdev; - QemuOpts *device; - const char *writeout, *sock_fd, *socket, *path, *security_model, - *multidevs; - - olist = qemu_find_opts("virtfs"); - if (!olist) { - error_report("virtfs support is disabled"); - exit(1); - } - opts = qemu_opts_parse_noisily(olist, optarg, true); - if (!opts) { - exit(1); - } - - if (qemu_opt_get(opts, "fsdriver") == NULL || - qemu_opt_get(opts, "mount_tag") == NULL) { - error_report("Usage: -virtfs fsdriver,mount_tag=tag"); - exit(1); - } - fsdev = qemu_opts_create(qemu_find_opts("fsdev"), - qemu_opts_id(opts) ?: - qemu_opt_get(opts, "mount_tag"), - 1, NULL); - if (!fsdev) { - error_report("duplicate or invalid fsdev id: %s", - qemu_opt_get(opts, "mount_tag")); - exit(1); - } - - writeout = qemu_opt_get(opts, "writeout"); - if (writeout) { -#ifdef CONFIG_SYNC_FILE_RANGE - qemu_opt_set(fsdev, "writeout", writeout, &error_abort); -#else - error_report("writeout=immediate not supported " - "on this platform"); - exit(1); -#endif - } - qemu_opt_set(fsdev, "fsdriver", - qemu_opt_get(opts, "fsdriver"), &error_abort); - path = qemu_opt_get(opts, "path"); - if (path) { - qemu_opt_set(fsdev, "path", path, &error_abort); - } - security_model = qemu_opt_get(opts, "security_model"); - if (security_model) { - qemu_opt_set(fsdev, "security_model", security_model, - &error_abort); - } - socket = qemu_opt_get(opts, "socket"); - if (socket) { - qemu_opt_set(fsdev, "socket", socket, &error_abort); - } - sock_fd = qemu_opt_get(opts, "sock_fd"); - if (sock_fd) { - qemu_opt_set(fsdev, "sock_fd", sock_fd, &error_abort); - } - - qemu_opt_set_bool(fsdev, "readonly", - qemu_opt_get_bool(opts, "readonly", 0), - &error_abort); - multidevs = qemu_opt_get(opts, "multidevs"); - if (multidevs) { - qemu_opt_set(fsdev, "multidevs", multidevs, &error_abort); - } - device = qemu_opts_create(qemu_find_opts("device"), NULL, 0, - &error_abort); - qemu_opt_set(device, "driver", "virtio-9p-pci", &error_abort); - qemu_opt_set(device, "fsdev", - qemu_opts_id(fsdev), &error_abort); - qemu_opt_set(device, "mount_tag", - qemu_opt_get(opts, "mount_tag"), &error_abort); - break; - } - case QEMU_OPTION_serial: - add_device_config(DEV_SERIAL, optarg); - default_serial = 0; - if (strncmp(optarg, "mon:", 4) == 0) { - default_monitor = 0; - } - break; - case QEMU_OPTION_watchdog: - if (watchdog) { - error_report("only one watchdog option may be given"); - exit(1); - } - warn_report("-watchdog is deprecated; use -device instead."); - watchdog = optarg; - break; - case QEMU_OPTION_action: - olist = qemu_find_opts("action"); - if (!qemu_opts_parse_noisily(olist, optarg, false)) { - exit(1); - } - break; - case QEMU_OPTION_watchdog_action: { - QemuOpts *opts; - opts = qemu_opts_create(qemu_find_opts("action"), NULL, 0, &error_abort); - qemu_opt_set(opts, "watchdog", optarg, &error_abort); - break; - } - case QEMU_OPTION_parallel: - add_device_config(DEV_PARALLEL, optarg); - default_parallel = 0; - if (strncmp(optarg, "mon:", 4) == 0) { - default_monitor = 0; - } - break; - case QEMU_OPTION_debugcon: - add_device_config(DEV_DEBUGCON, optarg); - break; - case QEMU_OPTION_loadvm: - loadvm = optarg; - break; - case QEMU_OPTION_full_screen: - dpy.has_full_screen = true; - dpy.full_screen = true; - break; - case QEMU_OPTION_alt_grab: - alt_grab = 1; - warn_report("-alt-grab is deprecated, please use " - "-display sdl,grab-mod=lshift-lctrl-lalt instead."); - break; - case QEMU_OPTION_ctrl_grab: - ctrl_grab = 1; - warn_report("-ctrl-grab is deprecated, please use " - "-display sdl,grab-mod=rctrl instead."); - break; - case QEMU_OPTION_no_quit: - dpy.has_window_close = true; - dpy.window_close = false; - warn_report("-no-quit is deprecated, please use " - "-display ...,window-close=off instead."); - break; - case QEMU_OPTION_sdl: - warn_report("-sdl is deprecated, use -display sdl instead."); -#ifdef CONFIG_SDL - dpy.type = DISPLAY_TYPE_SDL; - break; -#else - error_report("SDL support is disabled"); - exit(1); -#endif - case QEMU_OPTION_pidfile: - pid_file = optarg; - break; - case QEMU_OPTION_win2k_hack: - win2k_install_hack = 1; - break; - case QEMU_OPTION_acpitable: - opts = qemu_opts_parse_noisily(qemu_find_opts("acpi"), - optarg, true); - if (!opts) { - exit(1); - } - acpi_table_add(opts, &error_fatal); - break; - case QEMU_OPTION_smbios: - opts = qemu_opts_parse_noisily(qemu_find_opts("smbios"), - optarg, false); - if (!opts) { - exit(1); - } - smbios_entry_add(opts, &error_fatal); - break; - case QEMU_OPTION_fwcfg: - opts = qemu_opts_parse_noisily(qemu_find_opts("fw_cfg"), - optarg, true); - if (opts == NULL) { - exit(1); - } - break; - case QEMU_OPTION_preconfig: - preconfig_requested = true; - break; - case QEMU_OPTION_enable_kvm: - qdict_put_str(machine_opts_dict, "accel", "kvm"); - break; - case QEMU_OPTION_M: - case QEMU_OPTION_machine: - { - 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; - } - case QEMU_OPTION_accel: - accel_opts = qemu_opts_parse_noisily(qemu_find_opts("accel"), - optarg, true); - optarg = qemu_opt_get(accel_opts, "accel"); - if (!optarg || is_help_option(optarg)) { - printf("Accelerators supported in QEMU binary:\n"); - GSList *el, *accel_list = object_class_get_list(TYPE_ACCEL, - false); - for (el = accel_list; el; el = el->next) { - gchar *typename = g_strdup(object_class_get_name( - OBJECT_CLASS(el->data))); - /* omit qtest which is used for tests only */ - if (g_strcmp0(typename, ACCEL_CLASS_NAME("qtest")) && - g_str_has_suffix(typename, ACCEL_CLASS_SUFFIX)) { - gchar **optname = g_strsplit(typename, - ACCEL_CLASS_SUFFIX, 0); - printf("%s\n", optname[0]); - g_strfreev(optname); - } - g_free(typename); - } - g_slist_free(accel_list); - exit(0); - } - break; - case QEMU_OPTION_usb: - qdict_put_str(machine_opts_dict, "usb", "on"); - break; - case QEMU_OPTION_usbdevice: - qdict_put_str(machine_opts_dict, "usb", "on"); - add_device_config(DEV_USB, optarg); - break; - case QEMU_OPTION_device: - if (optarg[0] == '{') { - QObject *obj = qobject_from_json(optarg, &error_fatal); - DeviceOption *opt = g_new0(DeviceOption, 1); - opt->opts = qobject_to(QDict, obj); - loc_save(&opt->loc); - assert(opt->opts != NULL); - QTAILQ_INSERT_TAIL(&device_opts, opt, next); - } else { - if (!qemu_opts_parse_noisily(qemu_find_opts("device"), - optarg, true)) { - exit(1); - } - } - break; - case QEMU_OPTION_smp: - machine_parse_property_opt(qemu_find_opts("smp-opts"), - "smp", optarg); - break; - case QEMU_OPTION_vnc: - vnc_parse(optarg); - break; - case QEMU_OPTION_no_acpi: - qdict_put_str(machine_opts_dict, "acpi", "off"); - break; - case QEMU_OPTION_no_hpet: - qdict_put_str(machine_opts_dict, "hpet", "off"); - break; - case QEMU_OPTION_no_reboot: - olist = qemu_find_opts("action"); - qemu_opts_parse_noisily(olist, "reboot=shutdown", false); - break; - case QEMU_OPTION_no_shutdown: - olist = qemu_find_opts("action"); - qemu_opts_parse_noisily(olist, "shutdown=pause", false); - break; - case QEMU_OPTION_uuid: - if (qemu_uuid_parse(optarg, &qemu_uuid) < 0) { - error_report("failed to parse UUID string: wrong format"); - exit(1); - } - qemu_uuid_set = true; - break; - case QEMU_OPTION_option_rom: - if (nb_option_roms >= MAX_OPTION_ROMS) { - error_report("too many option ROMs"); - exit(1); - } - opts = qemu_opts_parse_noisily(qemu_find_opts("option-rom"), - optarg, true); - if (!opts) { - exit(1); - } - option_rom[nb_option_roms].name = qemu_opt_get(opts, "romfile"); - option_rom[nb_option_roms].bootindex = - qemu_opt_get_number(opts, "bootindex", -1); - if (!option_rom[nb_option_roms].name) { - error_report("Option ROM file is not specified"); - exit(1); - } - nb_option_roms++; - break; - case QEMU_OPTION_semihosting: - qemu_semihosting_enable(); - break; - case QEMU_OPTION_semihosting_config: - if (qemu_semihosting_config_options(optarg) != 0) { - exit(1); - } - break; - case QEMU_OPTION_name: - opts = qemu_opts_parse_noisily(qemu_find_opts("name"), - optarg, true); - if (!opts) { - exit(1); - } - /* Capture guest name if -msg guest-name is used later */ - error_guest_name = qemu_opt_get(opts, "guest"); - break; - case QEMU_OPTION_prom_env: - if (nb_prom_envs >= MAX_PROM_ENVS) { - error_report("too many prom variables"); - exit(1); - } - prom_envs[nb_prom_envs] = optarg; - nb_prom_envs++; - break; - case QEMU_OPTION_old_param: - old_param = 1; - break; - case QEMU_OPTION_rtc: - opts = qemu_opts_parse_noisily(qemu_find_opts("rtc"), optarg, - false); - if (!opts) { - exit(1); - } - break; - case QEMU_OPTION_icount: - icount_opts = qemu_opts_parse_noisily(qemu_find_opts("icount"), - optarg, true); - if (!icount_opts) { - exit(1); - } - break; - case QEMU_OPTION_incoming: - if (!incoming) { - runstate_set(RUN_STATE_INMIGRATE); - } - incoming = optarg; - break; - case QEMU_OPTION_only_migratable: - only_migratable = 1; - break; - case QEMU_OPTION_nodefaults: - has_defaults = 0; - break; - case QEMU_OPTION_xen_domid: - if (!(accel_find("xen"))) { - error_report("Option not supported for this target"); - exit(1); - } - xen_domid = atoi(optarg); - break; - case QEMU_OPTION_xen_attach: - if (!(accel_find("xen"))) { - error_report("Option not supported for this target"); - exit(1); - } - xen_mode = XEN_ATTACH; - break; - case QEMU_OPTION_xen_domid_restrict: - if (!(accel_find("xen"))) { - error_report("Option not supported for this target"); - exit(1); - } - xen_domid_restrict = true; - break; - case QEMU_OPTION_trace: - trace_opt_parse(optarg); - break; - case QEMU_OPTION_plugin: - qemu_plugin_opt_parse(optarg, &plugin_list); - break; - case QEMU_OPTION_readconfig: - qemu_read_config_file(optarg, qemu_parse_config_group, &error_fatal); - break; - case QEMU_OPTION_spice: - olist = qemu_find_opts_err("spice", NULL); - if (!olist) { - error_report("spice support is disabled"); - exit(1); - } - opts = qemu_opts_parse_noisily(olist, optarg, false); - if (!opts) { - exit(1); - } - display_remote++; - break; - case QEMU_OPTION_writeconfig: - { - FILE *fp; - warn_report("-writeconfig is deprecated and will go away without a replacement"); - if (strcmp(optarg, "-") == 0) { - fp = stdout; - } else { - fp = fopen(optarg, "w"); - if (fp == NULL) { - error_report("open %s: %s", optarg, - strerror(errno)); - exit(1); - } - } - qemu_config_write(fp); - if (fp != stdout) { - fclose(fp); - } - break; - } - case QEMU_OPTION_qtest: - qtest_chrdev = optarg; - break; - case QEMU_OPTION_qtest_log: - qtest_log = optarg; - break; - case QEMU_OPTION_sandbox: - olist = qemu_find_opts("sandbox"); - if (!olist) { -#ifndef CONFIG_SECCOMP - error_report("-sandbox support is not enabled " - "in this QEMU binary"); -#endif - exit(1); - } - - opts = qemu_opts_parse_noisily(olist, optarg, true); - if (!opts) { - exit(1); - } - break; - case QEMU_OPTION_add_fd: -#ifndef _WIN32 - opts = qemu_opts_parse_noisily(qemu_find_opts("add-fd"), - optarg, false); - if (!opts) { - exit(1); - } -#else - error_report("File descriptor passing is disabled on this " - "platform"); - exit(1); -#endif - break; - case QEMU_OPTION_object: - object_option_parse(optarg); - break; - case QEMU_OPTION_overcommit: - opts = qemu_opts_parse_noisily(qemu_find_opts("overcommit"), - optarg, false); - if (!opts) { - exit(1); - } - enable_mlock = qemu_opt_get_bool(opts, "mem-lock", false); - enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", false); - break; - case QEMU_OPTION_compat: - { - CompatPolicy *opts; - Visitor *v; - - v = qobject_input_visitor_new_str(optarg, NULL, - &error_fatal); - - visit_type_CompatPolicy(v, NULL, &opts, &error_fatal); - QAPI_CLONE_MEMBERS(CompatPolicy, &compat_policy, opts); - - qapi_free_CompatPolicy(opts); - visit_free(v); - break; - } - case QEMU_OPTION_msg: - opts = qemu_opts_parse_noisily(qemu_find_opts("msg"), optarg, - false); - if (!opts) { - exit(1); - } - configure_msg(opts); - break; - case QEMU_OPTION_dump_vmstate: - if (vmstate_dump_file) { - error_report("only one '-dump-vmstate' " - "option may be given"); - exit(1); - } - vmstate_dump_file = fopen(optarg, "w"); - if (vmstate_dump_file == NULL) { - error_report("open %s: %s", optarg, strerror(errno)); - exit(1); - } - break; - case QEMU_OPTION_enable_sync_profile: - qsp_enable(); - break; - case QEMU_OPTION_nouserconfig: - /* Nothing to be parsed here. Especially, do not error out below. */ - break; - default: - if (os_parse_cmd_args(popt->index, optarg)) { - error_report("Option not supported in this build"); - exit(1); - } - } - } - } - /* - * Clear error location left behind by the loop. - * Best done right after the loop. Do not insert code here! - */ - loc_set_none(); - - qemu_validate_options(machine_opts_dict); - qemu_process_sugar_options(); - - /* - * These options affect everything else and should be processed - * before daemonizing. - */ qemu_process_early_options(); - qemu_process_help_options(); qemu_maybe_daemonize(pid_file); /* @@ -3699,22 +1041,16 @@ void qemu_init(int argc, char **argv, char **envp) qemu_init_main_loop(&error_fatal); cpu_timers_init(); - user_register_global_props(); - replay_configure(icount_opts); - configure_rtc(qemu_find_opts_singleton("rtc")); - qemu_create_machine(machine_opts_dict); + qemu_create_machine(); suspend_mux_open(); - qemu_disable_default_devices(); qemu_create_default_devices(); qemu_create_early_backends(); - qemu_apply_legacy_machine_options(machine_opts_dict); - qemu_apply_machine_options(machine_opts_dict); - qobject_unref(machine_opts_dict); + qemu_apply_machine_options(NULL); phase_advance(PHASE_MACHINE_CREATED); /* @@ -3756,13 +1092,9 @@ void qemu_init(int argc, char **argv, char **envp) /* parse features once if machine provides default cpu_type */ current_machine->cpu_type = machine_class->default_cpu_type; - if (cpu_option) { - current_machine->cpu_type = parse_cpu_option(cpu_option); - } /* NB: for machine none cpu_type could STILL be NULL here! */ qemu_resolve_machine_memdev(); - parse_numa_opts(current_machine); if (vmstate_dump_file) { /* dump and exit */