All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing
@ 2020-11-23 14:13 Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 01/36] vl: extract validation of -smp to machine.c Paolo Bonzini
                   ` (37 more replies)
  0 siblings, 38 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:13 UTC (permalink / raw)
  To: qemu-devel

Incompatible changes WRT 5.x:

- "-incoming defer" will not generate a MIGRATION event until
  the migrate-incoming command is sent

- the "preconfig" runstate is not reported anymore, and is replaced
  with "prelaunch"

Since the patches build on a bunch of more mechanical changes to
remove the ram_size and bios_name global variables, which affect
all targets, I have already placed the result in the for-6.0 branch of
my gitlab repository.  The branch has also passed CI already.

Thanks,

Paolo

Paolo Bonzini (36):
  vl: extract validation of -smp to machine.c
  vl: remove bogus check
  vl: split various early command line options to a separate function
  vl: move various initialization routines out of qemu_init
  vl: extract qemu_init_subsystems
  vl: move prelaunch part of qemu_init to new functions
  vl: extract various command line validation snippets to a new function
  vl: preconfig and loadvm are mutually exclusive
  vl: extract various command line desugaring snippets to a new function
  qemu-option: restrict qemu_opts_set to merge-lists QemuOpts
  vl: create "-net nic -net user" default earlier
  vl: load plugins as late as possible
  vl: move semihosting command line fallback to qemu_init_board
  vl: extract default devices to separate functions
  vl: move CHECKPOINT_INIT after preconfig
  vl: separate qemu_create_early_backends
  vl: separate qemu_create_late_backends
  vl: separate qemu_create_machine
  vl: separate qemu_apply_machine_options
  vl: separate qemu_resolve_machine_memdev
  vl: initialize displays before preconfig loop
  vl: move -global check earlier
  migration, vl: start migration via qmp_migrate_incoming
  vl: start VM via qmp_cont
  hmp: introduce cmd_available
  remove preconfig state
  vl: remove separate preconfig main_loop
  vl: allow -incoming defer with -preconfig
  vl: extract softmmu/datadir.c
  vl: extract machine done notifiers
  vl: extract softmmu/rtc.c
  vl: extract softmmu/runstate.c
  vl: extract softmmu/globals.c
  vl: remove serial_max_hds
  vl: clean up -boot variables
  vl: move all generic initialization out of vl.c

 hw/alpha/dp264.c              |    1 +
 hw/arm/boot.c                 |    1 +
 hw/arm/digic_boards.c         |    1 +
 hw/arm/highbank.c             |    1 +
 hw/arm/npcm7xx_boards.c       |    1 +
 hw/arm/sbsa-ref.c             |    1 +
 hw/arm/vexpress.c             |    1 +
 hw/arm/virt.c                 |    1 +
 hw/avr/boot.c                 |    1 +
 hw/core/loader.c              |    1 +
 hw/core/machine-qmp-cmds.c    |    5 +-
 hw/core/machine.c             |  103 ++
 hw/core/qdev.c                |   12 +-
 hw/display/cg3.c              |    1 +
 hw/display/tcx.c              |    1 +
 hw/hppa/machine.c             |    1 +
 hw/i386/x86.c                 |    1 +
 hw/lm32/milkymist.c           |    1 +
 hw/m68k/mcf5208.c             |    1 +
 hw/m68k/q800.c                |    1 +
 hw/microblaze/boot.c          |    1 +
 hw/mips/fuloong2e.c           |    1 +
 hw/mips/jazz.c                |    1 +
 hw/mips/malta.c               |    1 +
 hw/mips/mipssim.c             |    1 +
 hw/nios2/boot.c               |    1 +
 hw/nvram/fw_cfg.c             |    1 +
 hw/pci-host/prep.c            |    1 +
 hw/pci/pci.c                  |    1 +
 hw/ppc/e500.c                 |    1 +
 hw/ppc/mac_newworld.c         |    1 +
 hw/ppc/mac_oldworld.c         |    1 +
 hw/ppc/pnv.c                  |    1 +
 hw/ppc/ppc405_boards.c        |    1 +
 hw/ppc/ppc440_bamboo.c        |    1 +
 hw/ppc/sam460ex.c             |    1 +
 hw/ppc/spapr.c                |    7 +-
 hw/ppc/virtex_ml507.c         |    1 +
 hw/riscv/boot.c               |    1 +
 hw/s390x/ipl.c                |    1 +
 hw/sparc/leon3.c              |    1 +
 hw/sparc/sun4m.c              |    1 +
 hw/sparc64/sun4u.c            |    1 +
 include/exec/cpu-common.h     |    3 +
 include/exec/exec-all.h       |    3 -
 include/hw/boards.h           |    2 +
 include/hw/qdev-core.h        |    9 +-
 include/migration/misc.h      |    1 -
 include/qapi/qmp/dispatch.h   |    1 +
 include/qemu-common.h         |   21 -
 include/qemu/datadir.h        |   28 +
 include/qemu/option.h         |    3 +-
 include/sysemu/runstate.h     |    1 -
 include/sysemu/sysemu.h       |   12 +-
 migration/migration.c         |   37 +-
 monitor/hmp.c                 |   23 +-
 monitor/qmp-cmds.c            |   10 -
 qapi/qmp-dispatch.c           |    5 +-
 qapi/run-state.json           |    5 +-
 softmmu/datadir.c             |  129 ++
 softmmu/globals.c             |   74 +
 softmmu/meson.build           |    4 +
 softmmu/qdev-monitor.c        |   18 +-
 softmmu/rtc.c                 |  190 +++
 softmmu/runstate.c            |  800 ++++++++++
 softmmu/vl.c                  | 2761 ++++++++++-----------------------
 stubs/meson.build             |    1 +
 stubs/qmp-command-available.c |    7 +
 tests/qtest/fuzz/fuzz.c       |    1 +
 tests/qtest/qmp-test.c        |    2 +-
 tests/test-qemu-opts.c        |   20 +-
 ui/keymaps.c                  |    1 +
 util/qemu-option.c            |    9 +-
 73 files changed, 2311 insertions(+), 2036 deletions(-)
 create mode 100644 include/qemu/datadir.h
 create mode 100644 softmmu/datadir.c
 create mode 100644 softmmu/globals.c
 create mode 100644 softmmu/rtc.c
 create mode 100644 softmmu/runstate.c
 create mode 100644 stubs/qmp-command-available.c

-- 
2.26.2



^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH 01/36] vl: extract validation of -smp to machine.c
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 02/36] vl: remove bogus check Paolo Bonzini
                   ` (36 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Once smp_parse is done, the validation operates on the MachineState.
There is no reason for that code to be in vl.c.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine.c   | 23 +++++++++++++++++++++++
 include/hw/boards.h |  1 +
 softmmu/vl.c        | 20 ++------------------
 3 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index d0408049b5..cd298fac13 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -1074,6 +1074,29 @@ MemoryRegion *machine_consume_memdev(MachineState *machine,
     return ret;
 }
 
+bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp)
+{
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+    mc->smp_parse(ms, opts);
+
+    /* sanity-check smp_cpus and max_cpus against mc */
+    if (ms->smp.cpus < mc->min_cpus) {
+        error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
+                   "supported by machine '%s' is %d",
+                   ms->smp.cpus,
+                   mc->name, mc->min_cpus);
+        return false;
+    } else if (ms->smp.max_cpus > mc->max_cpus) {
+        error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
+                   "supported by machine '%s' is %d",
+                   current_machine->smp.max_cpus,
+                   mc->name, mc->max_cpus);
+        return false;
+    }
+    return true;
+}
+
 void machine_run_board_init(MachineState *machine)
 {
     MachineClass *machine_class = MACHINE_GET_CLASS(machine);
diff --git a/include/hw/boards.h b/include/hw/boards.h
index a49e3a6b44..4537cfb5c6 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -26,6 +26,7 @@ OBJECT_DECLARE_TYPE(MachineState, MachineClass, MACHINE)
 extern MachineState *current_machine;
 
 void machine_run_board_init(MachineState *machine);
+bool machine_smp_parse(MachineState *ms, QemuOpts *opts, Error **errp);
 bool machine_usb(MachineState *machine);
 int machine_phandle_start(MachineState *machine);
 bool machine_dump_guest_core(MachineState *machine);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index aaea88f599..fae72a9071 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3972,24 +3972,8 @@ void qemu_init(int argc, char **argv, char **envp)
         exit(0);
     }
 
-    machine_class->smp_parse(current_machine,
-        qemu_opts_find(qemu_find_opts("smp-opts"), NULL));
-
-    /* sanity-check smp_cpus and max_cpus against machine_class */
-    if (current_machine->smp.cpus < machine_class->min_cpus) {
-        error_report("Invalid SMP CPUs %d. The min CPUs "
-                     "supported by machine '%s' is %d",
-                     current_machine->smp.cpus,
-                     machine_class->name, machine_class->min_cpus);
-        exit(1);
-    }
-    if (current_machine->smp.max_cpus > machine_class->max_cpus) {
-        error_report("Invalid SMP CPUs %d. The max CPUs "
-                     "supported by machine '%s' is %d",
-                     current_machine->smp.max_cpus,
-                     machine_class->name, machine_class->max_cpus);
-        exit(1);
-    }
+    machine_smp_parse(current_machine,
+        qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal);
 
     if (mem_prealloc) {
         char *val;
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 02/36] vl: remove bogus check
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 01/36] vl: extract validation of -smp to machine.c Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 03/36] vl: split various early command line options to a separate function Paolo Bonzini
                   ` (35 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

There is no reason to prevent -preconfig -daemonize.  Of course if
no monitor is defined there will be no way to start the VM,
but that is a user error.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index fae72a9071..c45a99a2bf 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4028,12 +4028,6 @@ void qemu_init(int argc, char **argv, char **envp)
     }
 
     if (is_daemonized()) {
-        if (!preconfig_exit_requested) {
-            error_report("'preconfig' and 'daemonize' options are "
-                         "mutually exclusive");
-            exit(EXIT_FAILURE);
-        }
-
         /* 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
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 03/36] vl: split various early command line options to a separate function
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 01/36] vl: extract validation of -smp to machine.c Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 02/36] vl: remove bogus check Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 16:47   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 04/36] vl: move various initialization routines out of qemu_init Paolo Bonzini
                   ` (34 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Various options affect the global state of QEMU including the rest of
qemu_init, and they need to be called very early.  Group them together
in a function that is called at the beginning.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 200 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 112 insertions(+), 88 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index c45a99a2bf..07378301d5 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -117,6 +117,7 @@
 
 #define MAX_VIRTIO_CONSOLES 1
 
+static const char *cpu_option;
 static const char *data_dir[16];
 static int data_dir_idx;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
@@ -142,6 +143,9 @@ int vga_interface_type = VGA_NONE;
 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;
 Chardev *parallel_hds[MAX_PARALLEL_PORTS];
 int win2k_install_hack = 0;
 int singlestep = 0;
@@ -2862,6 +2866,105 @@ static char *find_datadir(void)
     return get_relocated_path(CONFIG_QEMU_DATADIR);
 }
 
+static void qemu_process_early_options(void)
+{
+    char **dirs;
+    int i;
+
+#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);
+
+#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
+
+    if (!trace_init_backends()) {
+        exit(1);
+    }
+    trace_init_file();
+
+    /* Open the logfile at this point and set the log mask if necessary.  */
+    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);
+    }
+
+    /* add configured firmware directories */
+    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
+    for (i = 0; dirs[i] != NULL; i++) {
+        qemu_add_data_dir(get_relocated_path(dirs[i]));
+    }
+    g_strfreev(dirs);
+
+    /* try to find datadir relative to the executable path */
+    qemu_add_data_dir(find_datadir());
+}
+
+static void qemu_process_help_options(void)
+{
+    int i;
+
+    /*
+     * 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) {
+        for (i = 0; i < data_dir_idx; i++) {
+            printf("%s\n", data_dir[i]);
+        }
+        exit(0);
+    }
+}
+
+static void qemu_maybe_daemonize(const char *pid_file)
+{
+    Error *err;
+
+    os_daemonize();
+    rcu_disable_atfork();
+
+    if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
+        error_reportf_err(err, "cannot create PID file: ");
+        exit(1);
+    }
+
+    qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
+    qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
+}
+
+
 void qemu_init(int argc, char **argv, char **envp)
 {
     int i;
@@ -2878,21 +2981,16 @@ void qemu_init(int argc, char **argv, char **envp)
     const char *optarg;
     const char *loadvm = NULL;
     MachineClass *machine_class;
-    const char *cpu_option;
     const char *vga_model = NULL;
     const char *incoming = NULL;
     bool userconfig = true;
     bool nographic = false;
     int display_remote = 0;
-    const char *log_mask = NULL;
-    const char *log_file = NULL;
     ram_addr_t maxram_size;
     uint64_t ram_slots = 0;
     FILE *vmstate_dump_file = NULL;
     Error *main_loop_err = NULL;
     Error *err = NULL;
-    bool list_data_dirs = false;
-    char **dirs;
     const char *mem_path = NULL;
     bool have_custom_ram_size;
     BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
@@ -3842,19 +3940,17 @@ void qemu_init(int argc, char **argv, char **envp)
     loc_set_none();
 
     /*
-     * 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'.
+     * These options affect everything else and should be processed
+     * before daemonizing.
      */
-    if (cpu_option && is_help_option(cpu_option)) {
-        list_cpus(cpu_option);
-        exit(0);
-    }
+    qemu_process_early_options();
 
-    if (qemu_opts_foreach(qemu_find_opts("device"),
-                          device_help_func, NULL, NULL)) {
-        exit(0);
+    qemu_process_help_options();
+    qemu_maybe_daemonize(pid_file);
+
+    if (qemu_init_main_loop(&main_loop_err)) {
+        error_report_err(main_loop_err);
+        exit(1);
     }
 
     user_register_global_props();
@@ -3875,40 +3971,6 @@ void qemu_init(int argc, char **argv, char **envp)
     have_custom_ram_size = set_memory_options(&ram_slots, &maxram_size,
                                               machine_class);
 
-    os_daemonize();
-    rcu_disable_atfork();
-
-    if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
-        error_reportf_err(err, "cannot create PID file: ");
-        exit(1);
-    }
-
-    qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
-    qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
-
-    if (qemu_init_main_loop(&main_loop_err)) {
-        error_report_err(main_loop_err);
-        exit(1);
-    }
-
-#ifdef CONFIG_SECCOMP
-    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);
-
-#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
-
     current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
     if (machine_help_func(qemu_get_machine_opts(), current_machine)) {
         exit(0);
@@ -3934,44 +3996,6 @@ void qemu_init(int argc, char **argv, char **envp)
         qemu_set_hw_version(machine_class->hw_version);
     }
 
-    if (!trace_init_backends()) {
-        exit(1);
-    }
-    trace_init_file();
-
-    /* Open the logfile at this point and set the log mask if necessary.
-     */
-    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);
-    }
-
-    /* add configured firmware directories */
-    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
-    for (i = 0; dirs[i] != NULL; i++) {
-        qemu_add_data_dir(get_relocated_path(dirs[i]));
-    }
-    g_strfreev(dirs);
-
-    /* try to find datadir relative to the executable path */
-    qemu_add_data_dir(find_datadir());
-
-    /* -L help lists the data directories and exits. */
-    if (list_data_dirs) {
-        for (i = 0; i < data_dir_idx; i++) {
-            printf("%s\n", data_dir[i]);
-        }
-        exit(0);
-    }
-
     machine_smp_parse(current_machine,
         qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal);
 
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 04/36] vl: move various initialization routines out of qemu_init
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (2 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 03/36] vl: split various early command line options to a separate function Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 05/36] vl: extract qemu_init_subsystems Paolo Bonzini
                   ` (33 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Some very simple initialization routines can be nested in existing
subsystem-level functions, do that to simplify qemu_init.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine.c      | 3 +++
 include/hw/qdev-core.h | 8 --------
 migration/migration.c  | 4 ++++
 softmmu/qdev-monitor.c | 6 ------
 softmmu/vl.c           | 5 -----
 5 files changed, 7 insertions(+), 19 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index cd298fac13..5260155962 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -874,6 +874,9 @@ static void machine_initfn(Object *obj)
     MachineState *ms = MACHINE(obj);
     MachineClass *mc = MACHINE_GET_CLASS(obj);
 
+    container_get(obj, "/peripheral");
+    container_get(obj, "/peripheral-anon");
+
     ms->dump_guest_core = true;
     ms->mem_merge = true;
     ms->enable_graphics = true;
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 5e737195b5..b77a2f1da7 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -785,14 +785,6 @@ BusState *sysbus_get_default(void);
 char *qdev_get_fw_dev_path(DeviceState *dev);
 char *qdev_get_own_fw_dev_path_from_handler(BusState *bus, DeviceState *dev);
 
-/**
- * @qdev_machine_init
- *
- * Initialize platform devices before machine init.  This is a hack until full
- * support for composition is added.
- */
-void qdev_machine_init(void);
-
 /**
  * device_legacy_reset:
  *
diff --git a/migration/migration.c b/migration/migration.c
index 87a9b59f83..d9e94f4080 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -182,6 +182,10 @@ void migration_object_init(void)
         error_report_err(err);
         exit(1);
     }
+
+    blk_mig_init();
+    ram_mig_init();
+    dirty_bitmap_mig_init();
 }
 
 void migration_shutdown(void)
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index bf79d0bbcd..d060e765da 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -943,12 +943,6 @@ BlockBackend *blk_by_qdev_id(const char *id, Error **errp)
     return blk;
 }
 
-void qdev_machine_init(void)
-{
-    qdev_get_peripheral_anon();
-    qdev_get_peripheral();
-}
-
 QemuOptsList qemu_device_opts = {
     .name = "device",
     .implied_opt_name = "driver",
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 07378301d5..b8d65ac532 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4276,10 +4276,6 @@ void qemu_init(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    blk_mig_init();
-    ram_mig_init();
-    dirty_bitmap_mig_init();
-
     qemu_opts_foreach(qemu_find_opts("mon"),
                       mon_init_func, NULL, &error_fatal);
 
@@ -4312,7 +4308,6 @@ void qemu_init(int argc, char **argv, char **envp)
        reading from the other reads, because timer polling functions query
        clock values from the log. */
     replay_checkpoint(CHECKPOINT_INIT);
-    qdev_machine_init();
 
     current_machine->boot_order = boot_order;
 
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 05/36] vl: extract qemu_init_subsystems
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (3 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 04/36] vl: move various initialization routines out of qemu_init Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 06/36] vl: move prelaunch part of qemu_init to new functions Paolo Bonzini
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Group a bunch of subsystem initializations that can be done right
after command line parsing.  Remove initializations that can be done
simply as global variable initializers.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 94 ++++++++++++++++++++++++----------------------------
 1 file changed, 43 insertions(+), 51 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index b8d65ac532..2832ab937e 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -128,7 +128,7 @@ bool enable_mlock = false;
 bool enable_cpu_pm = false;
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
-int autostart;
+int autostart = 1;
 static enum {
     RTC_BASE_UTC,
     RTC_BASE_LOCALTIME,
@@ -1228,7 +1228,8 @@ struct VMChangeStateEntry {
     int priority;
 };
 
-static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head;
+static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
+    QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
 
 /**
  * qemu_add_vm_change_state_handler_prio:
@@ -2964,11 +2965,44 @@ static void qemu_maybe_daemonize(const char *pid_file)
     qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
 }
 
+static void qemu_init_subsystems(void)
+{
+    Error *err;
+
+    os_set_line_buffering();
+
+    module_call_init(MODULE_INIT_TRACE);
+
+    qemu_init_cpu_list();
+    qemu_init_cpu_loop();
+    qemu_mutex_lock_iothread();
+
+    atexit(qemu_run_exit_notifiers);
+
+    module_call_init(MODULE_INIT_QOM);
+    module_call_init(MODULE_INIT_MIGRATION);
+
+    runstate_init();
+    precopy_infrastructure_init();
+    postcopy_infrastructure_init();
+    monitor_init_globals();
+
+    if (qcrypto_init(&err) < 0) {
+        error_reportf_err(err, "cannot initialize crypto: ");
+        exit(1);
+    }
+
+    os_setup_early_signal_handling();
+
+    bdrv_init_with_whitelist();
+    socket_init();
+}
 
 void qemu_init(int argc, char **argv, char **envp)
 {
     int i;
-    int snapshot, linux_boot;
+    int snapshot = 0;
+    int linux_boot;
     const char *initrd_filename;
     const char *kernel_filename, *kernel_cmdline;
     const char *boot_order = NULL;
@@ -2989,7 +3023,6 @@ void qemu_init(int argc, char **argv, char **envp)
     ram_addr_t maxram_size;
     uint64_t ram_slots = 0;
     FILE *vmstate_dump_file = NULL;
-    Error *main_loop_err = NULL;
     Error *err = NULL;
     const char *mem_path = NULL;
     bool have_custom_ram_size;
@@ -2997,22 +3030,6 @@ void qemu_init(int argc, char **argv, char **envp)
     QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
     int mem_prealloc = 0; /* force preallocation of physical target memory */
 
-    os_set_line_buffering();
-
-    error_init(argv[0]);
-    module_call_init(MODULE_INIT_TRACE);
-
-    qemu_init_cpu_list();
-    qemu_init_cpu_loop();
-
-    qemu_mutex_lock_iothread();
-
-    atexit(qemu_run_exit_notifiers);
-    qemu_init_exec_dir(argv[0]);
-
-    module_call_init(MODULE_INIT_QOM);
-    module_call_init(MODULE_INIT_MIGRATION);
-
     qemu_add_opts(&qemu_drive_opts);
     qemu_add_drive_opts(&qemu_legacy_drive_opts);
     qemu_add_drive_opts(&qemu_common_drive_opts);
@@ -3047,27 +3064,10 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_add_opts(&qemu_fw_cfg_opts);
     module_call_init(MODULE_INIT_OPTS);
 
-    runstate_init();
-    precopy_infrastructure_init();
-    postcopy_infrastructure_init();
-    monitor_init_globals();
-
-    if (qcrypto_init(&err) < 0) {
-        error_reportf_err(err, "cannot initialize crypto: ");
-        exit(1);
-    }
-
-    QTAILQ_INIT(&vm_change_state_head);
-    os_setup_early_signal_handling();
-
-    cpu_option = NULL;
-    snapshot = 0;
-
-    nb_nics = 0;
-
-    bdrv_init_with_whitelist();
+    error_init(argv[0]);
+    qemu_init_exec_dir(argv[0]);
 
-    autostart = 1;
+    qemu_init_subsystems();
 
     /* first pass of option parsing */
     optind = 1;
@@ -3948,13 +3948,10 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_process_help_options();
     qemu_maybe_daemonize(pid_file);
 
-    if (qemu_init_main_loop(&main_loop_err)) {
-        error_report_err(main_loop_err);
-        exit(1);
-    }
+    qemu_init_main_loop(&error_fatal);
+    cpu_timers_init();
 
     user_register_global_props();
-
     replay_configure(icount_opts);
 
     if (incoming && !preconfig_exit_requested) {
@@ -3991,6 +3988,7 @@ void qemu_init(int argc, char **argv, char **envp)
     }
 
     cpu_exec_init_all();
+    page_size_init();
 
     if (machine_class->hw_version) {
         qemu_set_hw_version(machine_class->hw_version);
@@ -4133,9 +4131,6 @@ void qemu_init(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    page_size_init();
-    socket_init();
-
     qemu_opts_foreach(qemu_find_opts("object"),
                       user_creatable_add_opts_foreach,
                       object_create_initial, &error_fatal);
@@ -4252,9 +4247,6 @@ void qemu_init(int argc, char **argv, char **envp)
         semihosting_arg_fallback(kernel_filename, kernel_cmdline);
     }
 
-    /* initialize cpu timers and VCPU throttle modules */
-    cpu_timers_init();
-
     if (default_net) {
         QemuOptsList *net = qemu_find_opts("net");
         qemu_opts_set(net, NULL, "type", "nic", &error_abort);
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 06/36] vl: move prelaunch part of qemu_init to new functions
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (4 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 05/36] vl: extract qemu_init_subsystems Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 07/36] vl: extract various command line validation snippets to a new function Paolo Bonzini
                   ` (31 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

The final part of qemu_init, starting with the completion of
board init, is already relatively clean.  Split it out of
qemu_init so that qemu_init keeps only the messy parts.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 249 +++++++++++++++++++++++++++------------------------
 1 file changed, 134 insertions(+), 115 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 2832ab937e..8ceef00a27 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -120,6 +120,9 @@
 static const char *cpu_option;
 static const char *data_dir[16];
 static int data_dir_idx;
+static const char *mem_path;
+static const char *boot_order;
+static const char *boot_once;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 int display_opengl;
 const char* keyboard_layout = NULL;
@@ -2998,6 +3001,134 @@ static void qemu_init_subsystems(void)
     socket_init();
 }
 
+/*
+ * Called after leaving preconfig state.  From here on runstate is
+ * RUN_STATE_PRELAUNCH or RUN_STATE_INMIGRATE.
+ */
+static void qemu_init_board(void)
+{
+    MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
+
+    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);
+    }
+
+    machine_run_board_init(current_machine);
+
+    /*
+     * TODO To drop support for deprecated bogus if=..., move
+     * drive_check_orphaned() here, replacing this call.  Also drop
+     * its deprecation warning, along with DriveInfo member
+     * @claimed_by_board.
+     */
+    drive_mark_claimed_by_board();
+
+    realtime_init();
+
+    if (hax_enabled()) {
+        /* FIXME: why isn't cpu_synchronize_all_post_init enough? */
+        hax_sync_vcpus();
+    }
+}
+
+static void qemu_create_cli_devices(void)
+{
+    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);
+    rom_reset_order_override();
+}
+
+static void qemu_machine_creation_done(void)
+{
+    DisplayState *ds;
+
+    cpu_synchronize_all_post_init();
+
+    /* 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();
+    }
+
+    if (boot_once) {
+        qemu_boot_set(boot_once, &error_fatal);
+        qemu_register_reset(restore_boot_order, g_strdup(boot_order));
+    }
+
+    /* init local displays */
+    ds = init_displaystate();
+    qemu_display_init(ds, &dpy);
+
+    /* 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();
+    }
+
+    if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
+        exit(1);
+    }
+
+    qdev_machine_creation_done();
+
+    /* TODO: once all bus devices are qdevified, this should be done
+     * when bus is created by qdev.c */
+    /*
+     * TODO: If we had a main 'reset container' that the whole system
+     * lived in, we could reset that using the multi-phase reset
+     * APIs. For the moment, we just reset the sysbus, which will cause
+     * all devices hanging off it (and all their child buses, recursively)
+     * to be reset. Note that this will *not* reset any Device objects
+     * which are not attached to some part of the qbus tree!
+     */
+    qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
+    qemu_run_machine_init_done_notifiers();
+
+    if (rom_check_and_register_reset() != 0) {
+        error_report("rom check and register reset failed");
+        exit(1);
+    }
+
+    replay_start();
+
+    /* This checkpoint is required by replay to separate prior clock
+       reading from the other reads, because timer polling functions query
+       clock values from the log. */
+    replay_checkpoint(CHECKPOINT_RESET);
+    qemu_system_reset(SHUTDOWN_CAUSE_NONE);
+    register_global_state();
+}
+
 void qemu_init(int argc, char **argv, char **envp)
 {
     int i;
@@ -3005,9 +3136,6 @@ void qemu_init(int argc, char **argv, char **envp)
     int linux_boot;
     const char *initrd_filename;
     const char *kernel_filename, *kernel_cmdline;
-    const char *boot_order = NULL;
-    const char *boot_once = NULL;
-    DisplayState *ds;
     QemuOpts *opts, *machine_opts;
     QemuOpts *icount_opts = NULL, *accel_opts = NULL;
     QemuOptsList *olist;
@@ -3024,7 +3152,6 @@ void qemu_init(int argc, char **argv, char **envp)
     uint64_t ram_slots = 0;
     FILE *vmstate_dump_file = NULL;
     Error *err = NULL;
-    const char *mem_path = NULL;
     bool have_custom_ram_size;
     BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
     QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
@@ -4347,117 +4474,10 @@ void qemu_init(int argc, char **argv, char **envp)
     /* do monitor/qmp handling at preconfig state if requested */
     qemu_main_loop();
 
-    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);
-    }
-
-    /* from here on runstate is RUN_STATE_PRELAUNCH */
-    machine_run_board_init(current_machine);
-
-    /*
-     * TODO To drop support for deprecated bogus if=..., move
-     * drive_check_orphaned() here, replacing this call.  Also drop
-     * its deprecation warning, along with DriveInfo member
-     * @claimed_by_board.
-     */
-    drive_mark_claimed_by_board();
-
-    realtime_init();
-
-    soundhw_init();
-
-    if (hax_enabled()) {
-        hax_sync_vcpus();
-    }
-
-    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);
-
-    cpu_synchronize_all_post_init();
-
-    rom_reset_order_override();
-
-    /* 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();
-    }
-
-    if (boot_once) {
-        qemu_boot_set(boot_once, &error_fatal);
-        qemu_register_reset(restore_boot_order, g_strdup(boot_order));
-    }
-
-    /* init local displays */
-    ds = init_displaystate();
-    qemu_display_init(ds, &dpy);
-
-    /* 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();
-    }
-
-    if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
-        exit(1);
-    }
-
-    qdev_machine_creation_done();
-
-    /* TODO: once all bus devices are qdevified, this should be done
-     * when bus is created by qdev.c */
-    /*
-     * TODO: If we had a main 'reset container' that the whole system
-     * lived in, we could reset that using the multi-phase reset
-     * APIs. For the moment, we just reset the sysbus, which will cause
-     * all devices hanging off it (and all their child buses, recursively)
-     * to be reset. Note that this will *not* reset any Device objects
-     * which are not attached to some part of the qbus tree!
-     */
-    qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
-    qemu_run_machine_init_done_notifiers();
+    qemu_init_board();
+    qemu_create_cli_devices();
+    qemu_machine_creation_done();
 
-    if (rom_check_and_register_reset() != 0) {
-        error_report("rom check and register reset failed");
-        exit(1);
-    }
-
-    replay_start();
-
-    /* This checkpoint is required by replay to separate prior clock
-       reading from the other reads, because timer polling functions query
-       clock values from the log. */
-    replay_checkpoint(CHECKPOINT_RESET);
-    qemu_system_reset(SHUTDOWN_CAUSE_NONE);
-    register_global_state();
     if (loadvm) {
         Error *local_err = NULL;
         if (load_snapshot(loadvm, &local_err) < 0) {
@@ -4476,7 +4496,6 @@ void qemu_init(int argc, char **argv, char **envp)
         dump_vmstate_json_to_file(vmstate_dump_file);
         exit(0);
     }
-
     if (incoming) {
         Error *local_err = NULL;
         qemu_start_incoming_migration(incoming, &local_err);
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 07/36] vl: extract various command line validation snippets to a new function
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (5 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 06/36] vl: move prelaunch part of qemu_init to new functions Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 08/36] vl: preconfig and loadvm are mutually exclusive Paolo Bonzini
                   ` (30 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine.c |  1 +
 softmmu/vl.c      | 78 +++++++++++++++++++++++------------------------
 2 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 5260155962..7ef3de5ce5 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -880,6 +880,7 @@ static void machine_initfn(Object *obj)
     ms->dump_guest_core = true;
     ms->mem_merge = true;
     ms->enable_graphics = true;
+    ms->kernel_cmdline = g_strdup("");
 
     if (mc->nvdimm_supported) {
         Object *obj = OBJECT(ms);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 8ceef00a27..6699c23a16 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -123,6 +123,7 @@ static int data_dir_idx;
 static const char *mem_path;
 static const char *boot_order;
 static const char *boot_once;
+static const char *incoming;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 int display_opengl;
 const char* keyboard_layout = NULL;
@@ -2870,6 +2871,39 @@ static char *find_datadir(void)
     return get_relocated_path(CONFIG_QEMU_DATADIR);
 }
 
+static void qemu_validate_options(void)
+{
+    QemuOpts *machine_opts = qemu_get_machine_opts();
+    const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
+    const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
+    const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
+
+    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 (incoming && !preconfig_exit_requested) {
+        error_report("'preconfig' and 'incoming' options are "
+                     "mutually exclusive");
+        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_early_options(void)
 {
     char **dirs;
@@ -3133,9 +3167,6 @@ void qemu_init(int argc, char **argv, char **envp)
 {
     int i;
     int snapshot = 0;
-    int linux_boot;
-    const char *initrd_filename;
-    const char *kernel_filename, *kernel_cmdline;
     QemuOpts *opts, *machine_opts;
     QemuOpts *icount_opts = NULL, *accel_opts = NULL;
     QemuOptsList *olist;
@@ -3144,7 +3175,6 @@ void qemu_init(int argc, char **argv, char **envp)
     const char *loadvm = NULL;
     MachineClass *machine_class;
     const char *vga_model = NULL;
-    const char *incoming = NULL;
     bool userconfig = true;
     bool nographic = false;
     int display_remote = 0;
@@ -4066,6 +4096,8 @@ void qemu_init(int argc, char **argv, char **envp)
      */
     loc_set_none();
 
+    qemu_validate_options();
+
     /*
      * These options affect everything else and should be processed
      * before daemonizing.
@@ -4081,12 +4113,6 @@ void qemu_init(int argc, char **argv, char **envp)
     user_register_global_props();
     replay_configure(icount_opts);
 
-    if (incoming && !preconfig_exit_requested) {
-        error_report("'preconfig' and 'incoming' options are "
-                     "mutually exclusive");
-        exit(EXIT_FAILURE);
-    }
-
     configure_rtc(qemu_find_opts_singleton("rtc"));
 
     machine_class = select_machine();
@@ -4191,12 +4217,6 @@ void qemu_init(int argc, char **argv, char **envp)
             error_report("-nographic cannot be used with -daemonize");
             exit(1);
         }
-#ifdef CONFIG_CURSES
-        if (dpy.type == DISPLAY_TYPE_CURSES) {
-            error_report("curses display cannot be used with -daemonize");
-            exit(1);
-        }
-#endif
     }
 
     if (nographic) {
@@ -4327,11 +4347,6 @@ void qemu_init(int argc, char **argv, char **envp)
         qtest_server_init(qtest_chrdev, qtest_log, &error_fatal);
     }
 
-    machine_opts = qemu_get_machine_opts();
-    kernel_filename = qemu_opt_get(machine_opts, "kernel");
-    initrd_filename = qemu_opt_get(machine_opts, "initrd");
-    kernel_cmdline = qemu_opt_get(machine_opts, "append");
-
     opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL);
     if (opts) {
         boot_order = qemu_opt_get(opts, "order");
@@ -4352,24 +4367,9 @@ void qemu_init(int argc, char **argv, char **envp)
         boot_order = machine_class->default_boot_order;
     }
 
-    if (!kernel_cmdline) {
-        kernel_cmdline = "";
-        current_machine->kernel_cmdline = (char *)kernel_cmdline;
-    }
-
-    linux_boot = (kernel_filename != NULL);
-
-    if (!linux_boot && *kernel_cmdline != '\0') {
-        error_report("-append only allowed with -kernel option");
-        exit(1);
-    }
-
-    if (!linux_boot && initrd_filename != NULL) {
-        error_report("-initrd only allowed with -kernel option");
-        exit(1);
-    }
-
-    if (semihosting_enabled() && !semihosting_get_argc() && kernel_filename) {
+    if (semihosting_enabled() && !semihosting_get_argc()) {
+        const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
+        const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
         /* fall back to the -kernel/-append */
         semihosting_arg_fallback(kernel_filename, kernel_cmdline);
     }
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 08/36] vl: preconfig and loadvm are mutually exclusive
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (6 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 07/36] vl: extract various command line validation snippets to a new function Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 09/36] vl: extract various command line desugaring snippets to a new function Paolo Bonzini
                   ` (29 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Just like -incoming.  Later we will add support for "-incoming defer
-preconfig", because there are cases (Xen, block layer) that want
to look at RUNSTATE_INMIGRATE.  -loadvm will remain mutually exclusive
with preconfig; the plan is to just do loadvm in the monitor, since
the user is already going to interact with it for preconfiguration.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 6699c23a16..acea4286e9 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -124,6 +124,7 @@ static const char *mem_path;
 static const char *boot_order;
 static const char *boot_once;
 static const char *incoming;
+static const char *loadvm;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 int display_opengl;
 const char* keyboard_layout = NULL;
@@ -2890,6 +2891,11 @@ static void qemu_validate_options(void)
           }
     }
 
+    if (loadvm && !preconfig_exit_requested) {
+        error_report("'preconfig' and 'loadvm' options are "
+                     "mutually exclusive");
+        exit(EXIT_FAILURE);
+    }
     if (incoming && !preconfig_exit_requested) {
         error_report("'preconfig' and 'incoming' options are "
                      "mutually exclusive");
@@ -3172,7 +3178,6 @@ void qemu_init(int argc, char **argv, char **envp)
     QemuOptsList *olist;
     int optind;
     const char *optarg;
-    const char *loadvm = NULL;
     MachineClass *machine_class;
     const char *vga_model = NULL;
     bool userconfig = true;
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 09/36] vl: extract various command line desugaring snippets to a new function
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (7 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 08/36] vl: preconfig and loadvm are mutually exclusive Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 10/36] qemu-option: restrict qemu_opts_set to merge-lists QemuOpts Paolo Bonzini
                   ` (28 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Keep the machine initialization sequence free of miscellaneous command
line parsing actions.

The only difference is that preallocation will always be done with one
thread if -smp is not provided; previously it was using mc->default_cpus,
which is almost always 1 anyway.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index acea4286e9..1c08505f3a 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -126,6 +126,7 @@ static const char *boot_once;
 static const char *incoming;
 static const char *loadvm;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
+static int mem_prealloc; /* force preallocation of physical target memory */
 int display_opengl;
 const char* keyboard_layout = NULL;
 static ram_addr_t ram_size;
@@ -158,7 +159,7 @@ int fd_bootchk = 1;
 static int no_reboot;
 int no_shutdown = 0;
 int graphic_rotate = 0;
-const char *watchdog;
+static const char *watchdog;
 QEMUOptionRom option_rom[MAX_OPTION_ROMS];
 int nb_option_roms;
 int old_param = 0;
@@ -2910,6 +2911,25 @@ static void qemu_validate_options(void)
 #endif
 }
 
+static void qemu_process_sugar_options(void)
+{
+    if (mem_prealloc) {
+        char *val;
+
+        val = g_strdup_printf("%d",
+                 (uint32_t) qemu_opt_get_number(qemu_find_opts_singleton("smp-opts"), "cpus", 1));
+        object_register_sugar_prop("memory-backend", "prealloc-threads", val);
+        g_free(val);
+        object_register_sugar_prop("memory-backend", "prealloc", "on");
+    }
+
+    if (watchdog) {
+        int i = select_watchdog(watchdog);
+        if (i > 0)
+            exit (i == 1 ? 1 : 0);
+    }
+}
+
 static void qemu_process_early_options(void)
 {
     char **dirs;
@@ -3171,7 +3191,6 @@ static void qemu_machine_creation_done(void)
 
 void qemu_init(int argc, char **argv, char **envp)
 {
-    int i;
     int snapshot = 0;
     QemuOpts *opts, *machine_opts;
     QemuOpts *icount_opts = NULL, *accel_opts = NULL;
@@ -3190,7 +3209,6 @@ void qemu_init(int argc, char **argv, char **envp)
     bool have_custom_ram_size;
     BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
     QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
-    int mem_prealloc = 0; /* force preallocation of physical target memory */
 
     qemu_add_opts(&qemu_drive_opts);
     qemu_add_drive_opts(&qemu_legacy_drive_opts);
@@ -4102,6 +4120,7 @@ void qemu_init(int argc, char **argv, char **envp)
     loc_set_none();
 
     qemu_validate_options();
+    qemu_process_sugar_options();
 
     /*
      * These options affect everything else and should be processed
@@ -4155,15 +4174,6 @@ void qemu_init(int argc, char **argv, char **envp)
     machine_smp_parse(current_machine,
         qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal);
 
-    if (mem_prealloc) {
-        char *val;
-
-        val = g_strdup_printf("%d", current_machine->smp.cpus);
-        object_register_sugar_prop("memory-backend", "prealloc-threads", val);
-        g_free(val);
-        object_register_sugar_prop("memory-backend", "prealloc", "on");
-    }
-
     /*
      * Get the default machine options from the machine if it is not already
      * specified either by the configuration file or by the command line.
@@ -4422,12 +4432,6 @@ void qemu_init(int argc, char **argv, char **envp)
         select_vgahw(machine_class, vga_model);
     }
 
-    if (watchdog) {
-        i = select_watchdog(watchdog);
-        if (i > 0)
-            exit (i == 1 ? 1 : 0);
-    }
-
     /* This checkpoint is required by replay to separate prior clock
        reading from the other reads, because timer polling functions query
        clock values from the log. */
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 10/36] qemu-option: restrict qemu_opts_set to merge-lists QemuOpts
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (8 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 09/36] vl: extract various command line desugaring snippets to a new function Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 11/36] vl: create "-net nic -net user" default earlier Paolo Bonzini
                   ` (27 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

qemu_opts_set is used to create default network backends and to
parse sugar options -kernel, -initrd, -append, -bios and -dtb.
These are very different uses:

I would *expect* a function named qemu_opts_set to set an option in a
merge-lists QemuOptsList, such as -kernel, and possibly to set an option
in a non-merge-lists QemuOptsList with non-NULL id, similar to -set.

However, it wouldn't *work* to use qemu_opts_set for the latter
because qemu_opts_set uses fail_if_exists==1. So, for non-merge-lists
QemuOptsList and non-NULL id, the semantics of qemu_opts_set (fail if the
(QemuOptsList, id) pair already exists) are debatable.

On the other hand, I would not expect qemu_opts_set to create a
non-merge-lists QemuOpts with a single option; which it does, though.
For this case of non-merge-lists QemuOptsList and NULL id, qemu_opts_set
hardly adds value over qemu_opts_parse.  It does skip some parsing and
unescaping, but that's not needed when creating default network
backends.

So qemu_opts_set has warty behavior for non-merge-lists QemuOptsList
if id is non-NULL, and it's mostly pointless if id is NULL.  My
solution to keeping the API as simple as possible is to limit
qemu_opts_set to merge-lists QemuOptsList.  For them, it's useful (we
don't want comma-unescaping for -kernel) *and* has sane semantics.
Network backend creation is switched to qemu_opts_parse.

qemu_opts_set is now only used on merge-lists QemuOptsList... except
in the testcase, which is changed to use a merge-list QemuOptsList.

With this change we can also remove the id parameter.  With the
parameter always NULL, we know that qemu_opts_create cannot fail
and can pass &error_abort to it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/qemu/option.h  |  3 +--
 softmmu/vl.c           | 19 +++++++------------
 tests/test-qemu-opts.c | 20 +++++++++++++++++---
 util/qemu-option.c     |  9 +++------
 4 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index ac69352e0e..f73e0dc7d9 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -119,8 +119,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
                            int fail_if_exists, Error **errp);
 void qemu_opts_reset(QemuOptsList *list);
 void qemu_opts_loc_restore(QemuOpts *opts);
-bool qemu_opts_set(QemuOptsList *list, const char *id,
-                   const char *name, const char *value, Error **errp);
+bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp);
 const char *qemu_opts_id(QemuOpts *opts);
 void qemu_opts_set_id(QemuOpts *opts, char *id);
 void qemu_opts_del(QemuOpts *opts);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 1c08505f3a..10b6152e36 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3384,20 +3384,16 @@ void qemu_init(int argc, char **argv, char **envp)
                 }
                 break;
             case QEMU_OPTION_kernel:
-                qemu_opts_set(qemu_find_opts("machine"), NULL, "kernel", optarg,
-                              &error_abort);
+                qemu_opts_set(qemu_find_opts("machine"), "kernel", optarg, &error_abort);
                 break;
             case QEMU_OPTION_initrd:
-                qemu_opts_set(qemu_find_opts("machine"), NULL, "initrd", optarg,
-                              &error_abort);
+                qemu_opts_set(qemu_find_opts("machine"), "initrd", optarg, &error_abort);
                 break;
             case QEMU_OPTION_append:
-                qemu_opts_set(qemu_find_opts("machine"), NULL, "append", optarg,
-                              &error_abort);
+                qemu_opts_set(qemu_find_opts("machine"), "append", optarg, &error_abort);
                 break;
             case QEMU_OPTION_dtb:
-                qemu_opts_set(qemu_find_opts("machine"), NULL, "dtb", optarg,
-                              &error_abort);
+                qemu_opts_set(qemu_find_opts("machine"), "dtb", optarg, &error_abort);
                 break;
             case QEMU_OPTION_cdrom:
                 drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
@@ -3507,8 +3503,7 @@ void qemu_init(int argc, char **argv, char **envp)
                 }
                 break;
             case QEMU_OPTION_bios:
-                qemu_opts_set(qemu_find_opts("machine"), NULL, "firmware", optarg,
-                              &error_abort);
+                qemu_opts_set(qemu_find_opts("machine"), "firmware", optarg, &error_abort);
                 break;
             case QEMU_OPTION_singlestep:
                 singlestep = 1;
@@ -4391,9 +4386,9 @@ void qemu_init(int argc, char **argv, char **envp)
 
     if (default_net) {
         QemuOptsList *net = qemu_find_opts("net");
-        qemu_opts_set(net, NULL, "type", "nic", &error_abort);
+        qemu_opts_parse(net, "nic", true, &error_abort);
 #ifdef CONFIG_SLIRP
-        qemu_opts_set(net, NULL, "type", "user", &error_abort);
+        qemu_opts_parse(net, "user", true, &error_abort);
 #endif
     }
 
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index 297ffe79dd..2aab831d10 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -84,11 +84,25 @@ static QemuOptsList opts_list_03 = {
     },
 };
 
+static QemuOptsList opts_list_04 = {
+    .name = "opts_list_04",
+    .head = QTAILQ_HEAD_INITIALIZER(opts_list_04.head),
+    .merge_lists = true,
+    .desc = {
+        {
+            .name = "str3",
+            .type = QEMU_OPT_STRING,
+        },
+        { /* end of list */ }
+    },
+};
+
 static void register_opts(void)
 {
     qemu_add_opts(&opts_list_01);
     qemu_add_opts(&opts_list_02);
     qemu_add_opts(&opts_list_03);
+    qemu_add_opts(&opts_list_04);
 }
 
 static void test_find_unknown_opts(void)
@@ -402,17 +416,17 @@ static void test_qemu_opts_set(void)
     QemuOpts *opts;
     const char *opt;
 
-    list = qemu_find_opts("opts_list_01");
+    list = qemu_find_opts("opts_list_04");
     g_assert(list != NULL);
     g_assert(QTAILQ_EMPTY(&list->head));
-    g_assert_cmpstr(list->name, ==, "opts_list_01");
+    g_assert_cmpstr(list->name, ==, "opts_list_04");
 
     /* should not find anything at this point */
     opts = qemu_opts_find(list, NULL);
     g_assert(opts == NULL);
 
     /* implicitly create opts and set str3 value */
-    qemu_opts_set(list, NULL, "str3", "value", &error_abort);
+    qemu_opts_set(list, "str3", "value", &error_abort);
     g_assert(!QTAILQ_EMPTY(&list->head));
 
     /* get the just created opts */
diff --git a/util/qemu-option.c b/util/qemu-option.c
index acefbc23fa..25792159ba 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -670,15 +670,12 @@ void qemu_opts_loc_restore(QemuOpts *opts)
     loc_restore(&opts->loc);
 }
 
-bool qemu_opts_set(QemuOptsList *list, const char *id,
-                   const char *name, const char *value, Error **errp)
+bool qemu_opts_set(QemuOptsList *list, const char *name, const char *value, Error **errp)
 {
     QemuOpts *opts;
 
-    opts = qemu_opts_create(list, id, 1, errp);
-    if (!opts) {
-        return false;
-    }
+    assert(list->merge_lists);
+    opts = qemu_opts_create(list, NULL, 0, &error_abort);
     return qemu_opt_set(opts, name, value, errp);
 }
 
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 11/36] vl: create "-net nic -net user" default earlier
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (9 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 10/36] qemu-option: restrict qemu_opts_set to merge-lists QemuOpts Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 12/36] vl: load plugins as late as possible Paolo Bonzini
                   ` (26 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Create it together with other default backends, even though the processing is
done later.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 10b6152e36..87c10f625c 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4249,6 +4249,14 @@ void qemu_init(int argc, char **argv, char **envp)
             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++;
@@ -4384,14 +4392,6 @@ void qemu_init(int argc, char **argv, char **envp)
         semihosting_arg_fallback(kernel_filename, kernel_cmdline);
     }
 
-    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 (net_init_clients(&err) < 0) {
         error_report_err(err);
         exit(1);
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 12/36] vl: load plugins as late as possible
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (10 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 11/36] vl: create "-net nic -net user" default earlier Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 16:54   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board Paolo Bonzini
                   ` (25 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé

There is no need to load plugins in the middle of default device processing,
move -plugin handling just before preconfig is entered.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 87c10f625c..ab08a0290c 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -125,6 +125,7 @@ static const char *boot_order;
 static const char *boot_once;
 static const char *incoming;
 static const char *loadvm;
+static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static int mem_prealloc; /* force preallocation of physical target memory */
 int display_opengl;
@@ -3074,6 +3075,11 @@ static void qemu_init_board(void)
         create_default_memdev(current_machine, mem_path);
     }
 
+    /* process plugin before CPUs are created, but once -smp has been parsed */
+    if (qemu_plugin_load_list(&plugin_list)) {
+        exit(1);
+    }
+
     machine_run_board_init(current_machine);
 
     /*
@@ -3208,7 +3214,6 @@ void qemu_init(int argc, char **argv, char **envp)
     Error *err = NULL;
     bool have_custom_ram_size;
     BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
-    QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
 
     qemu_add_opts(&qemu_drive_opts);
     qemu_add_drive_opts(&qemu_legacy_drive_opts);
@@ -4178,11 +4183,6 @@ void qemu_init(int argc, char **argv, char **envp)
                                machine_class->default_machine_opts, 0);
     }
 
-    /* process plugin before CPUs are created, but once -smp has been parsed */
-    if (qemu_plugin_load_list(&plugin_list)) {
-        exit(1);
-    }
-
     qemu_opts_foreach(qemu_find_opts("device"),
                       default_driver_check, NULL, NULL);
     qemu_opts_foreach(qemu_find_opts("global"),
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (11 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 12/36] vl: load plugins as late as possible Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 17:10   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 14/36] vl: extract default devices to separate functions Paolo Bonzini
                   ` (24 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Move more sane parts of the huge qemu_init function out of it.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index ab08a0290c..5d68cf828c 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3070,6 +3070,11 @@ static void qemu_init_board(void)
 {
     MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
 
+    if (semihosting_enabled() && !semihosting_get_argc() && current_machine->kernel_filename) {
+        /* fall back to the -kernel/-append */
+        semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline);
+    }
+
     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);
@@ -4385,13 +4390,6 @@ void qemu_init(int argc, char **argv, char **envp)
         boot_order = machine_class->default_boot_order;
     }
 
-    if (semihosting_enabled() && !semihosting_get_argc()) {
-        const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
-        const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
-        /* fall back to the -kernel/-append */
-        semihosting_arg_fallback(kernel_filename, kernel_cmdline);
-    }
-
     if (net_init_clients(&err) < 0) {
         error_report_err(err);
         exit(1);
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 14/36] vl: extract default devices to separate functions
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (12 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 17:29   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 15/36] vl: move CHECKPOINT_INIT after preconfig Paolo Bonzini
                   ` (23 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 216 +++++++++++++++++++++++++++------------------------
 1 file changed, 114 insertions(+), 102 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 5d68cf828c..b6c62e1e4f 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -125,7 +125,9 @@ static const char *boot_order;
 static const char *boot_once;
 static const char *incoming;
 static const char *loadvm;
+static int display_remote;
 static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
+static bool nographic = false;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static int mem_prealloc; /* force preallocation of physical target memory */
 int display_opengl;
@@ -147,6 +149,7 @@ static int rtc_host_datetime_offset = -1; /* valid & used only with
                                              RTC_BASE_DATETIME */
 QEMUClockType rtc_clock;
 int vga_interface_type = VGA_NONE;
+static const char *vga_model = NULL;
 static DisplayOptions dpy;
 static int num_serial_hds;
 static Chardev **serial_hds;
@@ -2224,6 +2227,115 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline))
     return 0;
 }
 
+static void qemu_disable_default_devices(void)
+{
+    MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
+
+    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;
+#if defined(CONFIG_VNC)
+            vnc_parse("localhost:0,to=99,id=default", &error_abort);
+#endif
+        }
+    }
+    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;
@@ -3209,10 +3321,7 @@ void qemu_init(int argc, char **argv, char **envp)
     int optind;
     const char *optarg;
     MachineClass *machine_class;
-    const char *vga_model = NULL;
     bool userconfig = true;
-    bool nographic = false;
-    int display_remote = 0;
     ram_addr_t maxram_size;
     uint64_t ram_slots = 0;
     FILE *vmstate_dump_file = NULL;
@@ -4188,97 +4297,8 @@ void qemu_init(int argc, char **argv, char **envp)
                                machine_class->default_machine_opts, 0);
     }
 
-    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;
-    }
-
-    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;
-#if defined(CONFIG_VNC)
-            vnc_parse("localhost:0,to=99,id=default", &error_abort);
-#endif
-        }
-    }
-    if (dpy.type == DISPLAY_TYPE_DEFAULT) {
-        dpy.type = DISPLAY_TYPE_NONE;
-    }
-
+    qemu_disable_default_devices();
+    qemu_create_default_devices();
     if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
         error_report("-alt-grab and -ctrl-grab are only valid "
                      "for SDL, ignoring option");
@@ -4417,14 +4437,6 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_semihosting_connect_chardevs();
     qemu_semihosting_console_init();
 
-    /* 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);
-    }
-
     /* This checkpoint is required by replay to separate prior clock
        reading from the other reads, because timer polling functions query
        clock values from the log. */
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 15/36] vl: move CHECKPOINT_INIT after preconfig
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (13 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 14/36] vl: extract default devices to separate functions Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 17:36   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 16/36] vl: separate qemu_create_early_backends Paolo Bonzini
                   ` (22 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé

Move CHECKPOINT_INIT right before the machine initialization is
completed.  Everything before is essentially an extension of
command line parsing.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine.c | 5 +++++
 softmmu/vl.c      | 5 -----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 7ef3de5ce5..a5cfbcc7cb 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -1107,6 +1107,11 @@ void machine_run_board_init(MachineState *machine)
     ObjectClass *oc = object_class_by_name(machine->cpu_type);
     CPUClass *cc;
 
+    /* This checkpoint is required by replay to separate prior clock
+       reading from the other reads, because timer polling functions query
+       clock values from the log. */
+    replay_checkpoint(CHECKPOINT_INIT);
+
     if (machine->ram_memdev_id) {
         Object *o;
         o = object_resolve_path_type(machine->ram_memdev_id,
diff --git a/softmmu/vl.c b/softmmu/vl.c
index b6c62e1e4f..dc0cdc3417 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -4437,11 +4437,6 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_semihosting_connect_chardevs();
     qemu_semihosting_console_init();
 
-    /* This checkpoint is required by replay to separate prior clock
-       reading from the other reads, because timer polling functions query
-       clock values from the log. */
-    replay_checkpoint(CHECKPOINT_INIT);
-
     current_machine->boot_order = boot_order;
 
     /* parse features once if machine provides default cpu_type */
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 16/36] vl: separate qemu_create_early_backends
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (14 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 15/36] vl: move CHECKPOINT_INIT after preconfig Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 17/36] vl: separate qemu_create_late_backends Paolo Bonzini
                   ` (21 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

"Early" backends are created before the machine and can be used as
machine options.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 123 +++++++++++++++++++++++++++------------------------
 1 file changed, 65 insertions(+), 58 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index dc0cdc3417..0a61df55b8 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -117,6 +117,14 @@
 
 #define MAX_VIRTIO_CONSOLES 1
 
+typedef struct BlockdevOptionsQueueEntry {
+    BlockdevOptions *bdo;
+    Location loc;
+    QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry;
+} BlockdevOptionsQueueEntry;
+
+typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue;
+
 static const char *cpu_option;
 static const char *data_dir[16];
 static int data_dir_idx;
@@ -126,7 +134,9 @@ static const char *boot_once;
 static const char *incoming;
 static const char *loadvm;
 static int display_remote;
+static int snapshot;
 static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
+static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
 static bool nographic = false;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static int mem_prealloc; /* force preallocation of physical target memory */
@@ -1043,14 +1053,6 @@ static void default_drive(int enable, int snapshot, BlockInterfaceType type,
 
 }
 
-typedef struct BlockdevOptionsQueueEntry {
-    BlockdevOptions *bdo;
-    Location loc;
-    QSIMPLEQ_ENTRY(BlockdevOptionsQueueEntry) entry;
-} BlockdevOptionsQueueEntry;
-
-typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue;
-
 static void configure_blockdev(BlockdevOptionsQueue *bdo_queue,
                                MachineClass *machine_class, int snapshot)
 {
@@ -2640,7 +2642,7 @@ static int machine_set_property(void *opaque,
  * cannot be created here, as it depends on the chardev
  * already existing.
  */
-static bool object_create_initial(const char *type, QemuOpts *opts)
+static bool object_create_early(const char *type, QemuOpts *opts)
 {
     if (user_creatable_print_help(type, opts)) {
         exit(0);
@@ -2696,6 +2698,58 @@ static bool object_create_initial(const char *type, QemuOpts *opts)
     return true;
 }
 
+static void qemu_create_early_backends(void)
+{
+    MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
+
+    if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
+        error_report("-alt-grab and -ctrl-grab are only valid "
+                     "for SDL, ignoring option");
+    }
+    if (dpy.has_window_close &&
+        (dpy.type != DISPLAY_TYPE_GTK && dpy.type != DISPLAY_TYPE_SDL)) {
+        error_report("-no-quit is only valid for GTK and SDL, "
+                     "ignoring option");
+    }
+
+    qemu_display_early_init(&dpy);
+    qemu_console_early_init();
+
+    if (dpy.has_gl && dpy.gl != DISPLAYGL_MODE_OFF && display_opengl == 0) {
+#if defined(CONFIG_OPENGL)
+        error_report("OpenGL is not supported by the display");
+#else
+        error_report("OpenGL support is disabled");
+#endif
+        exit(1);
+    }
+
+    qemu_opts_foreach(qemu_find_opts("object"),
+                      user_creatable_add_opts_foreach,
+                      object_create_early, &error_fatal);
+
+    /* 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
+     * machine_set_property(), so machine properties can refer to
+     * them.
+     */
+    configure_blockdev(&bdo_queue, machine_class, snapshot);
+    audio_init_audiodevs();
+}
+
 
 /*
  * The remainder of object creation happens after the
@@ -2703,7 +2757,7 @@ static bool object_create_initial(const char *type, QemuOpts *opts)
  */
 static bool object_create_delayed(const char *type, QemuOpts *opts)
 {
-    return !object_create_initial(type, opts);
+    return !object_create_early(type, opts);
 }
 
 
@@ -3314,7 +3368,6 @@ static void qemu_machine_creation_done(void)
 
 void qemu_init(int argc, char **argv, char **envp)
 {
-    int snapshot = 0;
     QemuOpts *opts, *machine_opts;
     QemuOpts *icount_opts = NULL, *accel_opts = NULL;
     QemuOptsList *olist;
@@ -3327,7 +3380,6 @@ void qemu_init(int argc, char **argv, char **envp)
     FILE *vmstate_dump_file = NULL;
     Error *err = NULL;
     bool have_custom_ram_size;
-    BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
 
     qemu_add_opts(&qemu_drive_opts);
     qemu_add_drive_opts(&qemu_legacy_drive_opts);
@@ -4299,52 +4351,7 @@ void qemu_init(int argc, char **argv, char **envp)
 
     qemu_disable_default_devices();
     qemu_create_default_devices();
-    if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
-        error_report("-alt-grab and -ctrl-grab are only valid "
-                     "for SDL, ignoring option");
-    }
-    if (dpy.has_window_close &&
-        (dpy.type != DISPLAY_TYPE_GTK && dpy.type != DISPLAY_TYPE_SDL)) {
-        error_report("-no-quit is only valid for GTK and SDL, "
-                     "ignoring option");
-    }
-
-    qemu_display_early_init(&dpy);
-    qemu_console_early_init();
-
-    if (dpy.has_gl && dpy.gl != DISPLAYGL_MODE_OFF && display_opengl == 0) {
-#if defined(CONFIG_OPENGL)
-        error_report("OpenGL is not supported by the display");
-#else
-        error_report("OpenGL support is disabled");
-#endif
-        exit(1);
-    }
-
-    qemu_opts_foreach(qemu_find_opts("object"),
-                      user_creatable_add_opts_foreach,
-                      object_create_initial, &error_fatal);
-
-    /* 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
-     * machine_set_property(), so machine properties can refer to
-     * them.
-     */
-    configure_blockdev(&bdo_queue, machine_class, snapshot);
-    audio_init_audiodevs();
+    qemu_create_early_backends();
 
     machine_opts = qemu_get_machine_opts();
     qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 17/36] vl: separate qemu_create_late_backends
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (15 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 16/36] vl: separate qemu_create_early_backends Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 18/36] vl: separate qemu_create_machine Paolo Bonzini
                   ` (20 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

"Late" backends are created after the machine.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 64 ++++++++++++++++++++++++++--------------------------
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 0a61df55b8..b2ec2ba8ef 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2755,11 +2755,41 @@ static void qemu_create_early_backends(void)
  * The remainder of object creation happens after the
  * creation of chardev, fsdev, net clients and device data types.
  */
-static bool object_create_delayed(const char *type, QemuOpts *opts)
+static bool object_create_late(const char *type, QemuOpts *opts)
 {
     return !object_create_early(type, opts);
 }
 
+static void qemu_create_late_backends(void)
+{
+    if (qtest_chrdev) {
+        qtest_server_init(qtest_chrdev, qtest_log, &error_fatal);
+    }
+
+    net_init_clients(&error_fatal);
+
+    qemu_opts_foreach(qemu_find_opts("object"),
+                      user_creatable_add_opts_foreach,
+                      object_create_late, &error_fatal);
+
+    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();
+}
 
 static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
                                MachineClass *mc)
@@ -3378,7 +3408,6 @@ void qemu_init(int argc, char **argv, char **envp)
     ram_addr_t maxram_size;
     uint64_t ram_slots = 0;
     FILE *vmstate_dump_file = NULL;
-    Error *err = NULL;
     bool have_custom_ram_size;
 
     qemu_add_opts(&qemu_drive_opts);
@@ -4393,10 +4422,6 @@ void qemu_init(int argc, char **argv, char **envp)
      */
     migration_object_init();
 
-    if (qtest_chrdev) {
-        qtest_server_init(qtest_chrdev, qtest_log, &error_fatal);
-    }
-
     opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL);
     if (opts) {
         boot_order = qemu_opt_get(opts, "order");
@@ -4417,32 +4442,7 @@ void qemu_init(int argc, char **argv, char **envp)
         boot_order = machine_class->default_boot_order;
     }
 
-    if (net_init_clients(&err) < 0) {
-        error_report_err(err);
-        exit(1);
-    }
-
-    qemu_opts_foreach(qemu_find_opts("object"),
-                      user_creatable_add_opts_foreach,
-                      object_create_delayed, &error_fatal);
-
-    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();
+    qemu_create_late_backends();
 
     current_machine->boot_order = boot_order;
 
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 18/36] vl: separate qemu_create_machine
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (16 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 17/36] vl: separate qemu_create_late_backends Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 19/36] vl: separate qemu_apply_machine_options Paolo Bonzini
                   ` (19 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 113 +++++++++++++++++++++++++++------------------------
 1 file changed, 60 insertions(+), 53 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index b2ec2ba8ef..c1eaa1e448 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -133,6 +133,8 @@ static const char *boot_order;
 static const char *boot_once;
 static const char *incoming;
 static const char *loadvm;
+static ram_addr_t maxram_size;
+static uint64_t ram_slots;
 static int display_remote;
 static int snapshot;
 static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
@@ -2791,8 +2793,13 @@ static void qemu_create_late_backends(void)
     qemu_semihosting_console_init();
 }
 
-static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
-                               MachineClass *mc)
+static bool have_custom_ram_size(void)
+{
+    QemuOpts *opts = qemu_find_opts_singleton("memory");
+    return !!qemu_opt_get_size(opts, "size", 0);
+}
+
+static void set_memory_options(MachineClass *mc)
 {
     uint64_t sz;
     const char *mem_str;
@@ -2842,7 +2849,7 @@ static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
 
     /* store value for the future use */
     qemu_opt_set_number(opts, "size", ram_size, &error_abort);
-    *maxram_size = ram_size;
+    maxram_size = ram_size;
 
     if (qemu_opt_get(opts, "maxmem")) {
         uint64_t slots;
@@ -2863,15 +2870,59 @@ static bool set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
             exit(EXIT_FAILURE);
         }
 
-        *maxram_size = sz;
-        *ram_slots = slots;
+        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);
-    return !!mem_str;
+}
+
+static void qemu_create_machine(MachineClass *machine_class)
+{
+    object_set_machine_compat_props(machine_class->compat_props);
+
+    set_memory_options(machine_class);
+
+    current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
+    if (machine_help_func(qemu_get_machine_opts(), current_machine)) {
+        exit(0);
+    }
+    object_property_add_child(object_get_root(), "machine",
+                              OBJECT(current_machine));
+    object_property_add_child(container_get(OBJECT(current_machine),
+                                            "/unattached"),
+                              "sysbus", OBJECT(sysbus_get_default()));
+
+    if (machine_class->minimum_page_bits) {
+        if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) {
+            /* This would be a board error: specifying a minimum smaller than
+             * a target's compile-time fixed setting.
+             */
+            g_assert_not_reached();
+        }
+    }
+
+    cpu_exec_init_all();
+    page_size_init();
+
+    if (machine_class->hw_version) {
+        qemu_set_hw_version(machine_class->hw_version);
+    }
+
+    machine_smp_parse(current_machine,
+        qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal);
+
+    /*
+     * Get the default machine options from the machine if it is not already
+     * specified either by the configuration file or by the command line.
+     */
+    if (machine_class->default_machine_opts) {
+        qemu_opts_set_defaults(qemu_find_opts("machine"),
+                               machine_class->default_machine_opts, 0);
+    }
 }
 
 static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
@@ -3405,10 +3456,7 @@ void qemu_init(int argc, char **argv, char **envp)
     const char *optarg;
     MachineClass *machine_class;
     bool userconfig = true;
-    ram_addr_t maxram_size;
-    uint64_t ram_slots = 0;
     FILE *vmstate_dump_file = NULL;
-    bool have_custom_ram_size;
 
     qemu_add_opts(&qemu_drive_opts);
     qemu_add_drive_opts(&qemu_legacy_drive_opts);
@@ -4334,49 +4382,7 @@ void qemu_init(int argc, char **argv, char **envp)
 
     configure_rtc(qemu_find_opts_singleton("rtc"));
 
-    machine_class = select_machine();
-    object_set_machine_compat_props(machine_class->compat_props);
-
-    have_custom_ram_size = set_memory_options(&ram_slots, &maxram_size,
-                                              machine_class);
-
-    current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
-    if (machine_help_func(qemu_get_machine_opts(), current_machine)) {
-        exit(0);
-    }
-    object_property_add_child(object_get_root(), "machine",
-                              OBJECT(current_machine));
-    object_property_add_child(container_get(OBJECT(current_machine),
-                                            "/unattached"),
-                              "sysbus", OBJECT(sysbus_get_default()));
-
-    if (machine_class->minimum_page_bits) {
-        if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) {
-            /* This would be a board error: specifying a minimum smaller than
-             * a target's compile-time fixed setting.
-             */
-            g_assert_not_reached();
-        }
-    }
-
-    cpu_exec_init_all();
-    page_size_init();
-
-    if (machine_class->hw_version) {
-        qemu_set_hw_version(machine_class->hw_version);
-    }
-
-    machine_smp_parse(current_machine,
-        qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal);
-
-    /*
-     * Get the default machine options from the machine if it is not already
-     * specified either by the configuration file or by the command line.
-     */
-    if (machine_class->default_machine_opts) {
-        qemu_opts_set_defaults(qemu_find_opts("machine"),
-                               machine_class->default_machine_opts, 0);
-    }
+    qemu_create_machine(select_machine());
 
     qemu_disable_default_devices();
     qemu_create_default_devices();
@@ -4411,6 +4417,7 @@ void qemu_init(int argc, char **argv, char **envp)
      * called from configure_accelerator().
      */
 
+    machine_class = MACHINE_GET_CLASS(current_machine);
     if (!qtest_enabled() && machine_class->deprecation_reason) {
         error_report("Machine type '%s' is deprecated: %s",
                      machine_class->name, machine_class->deprecation_reason);
@@ -4464,7 +4471,7 @@ void qemu_init(int argc, char **argv, char **envp)
             exit(EXIT_FAILURE);
         }
         backend_size = object_property_get_uint(backend, "size",  &error_abort);
-        if (have_custom_ram_size && backend_size != ram_size) {
+        if (have_custom_ram_size() && backend_size != ram_size) {
                 error_report("Size specified by -m option must match size of "
                              "explicitly specified 'memory-backend' property");
                 exit(EXIT_FAILURE);
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 19/36] vl: separate qemu_apply_machine_options
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (17 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 18/36] vl: separate qemu_create_machine Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 20/36] vl: separate qemu_resolve_machine_memdev Paolo Bonzini
                   ` (18 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 66 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 37 insertions(+), 29 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index c1eaa1e448..741a800114 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2700,6 +2700,41 @@ static bool object_create_early(const char *type, QemuOpts *opts)
     return true;
 }
 
+static void qemu_apply_machine_options(void)
+{
+    MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
+    QemuOpts *machine_opts = qemu_get_machine_opts();
+    QemuOpts *opts;
+
+    qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
+                     &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;
+    }
+
+    current_machine->boot_order = boot_order;
+}
+
 static void qemu_create_early_backends(void)
 {
     MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
@@ -3449,7 +3484,7 @@ static void qemu_machine_creation_done(void)
 
 void qemu_init(int argc, char **argv, char **envp)
 {
-    QemuOpts *opts, *machine_opts;
+    QemuOpts *opts;
     QemuOpts *icount_opts = NULL, *accel_opts = NULL;
     QemuOptsList *olist;
     int optind;
@@ -4388,12 +4423,7 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_create_default_devices();
     qemu_create_early_backends();
 
-    machine_opts = qemu_get_machine_opts();
-    qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
-                     &error_fatal);
-    current_machine->ram_size = ram_size;
-    current_machine->maxram_size = maxram_size;
-    current_machine->ram_slots = ram_slots;
+    qemu_apply_machine_options();
 
     /*
      * Note: uses machine properties such as kernel-irqchip, must run
@@ -4429,30 +4459,8 @@ void qemu_init(int argc, char **argv, char **envp)
      */
     migration_object_init();
 
-    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;
-    }
-
     qemu_create_late_backends();
 
-    current_machine->boot_order = boot_order;
-
     /* parse features once if machine provides default cpu_type */
     current_machine->cpu_type = machine_class->default_cpu_type;
     if (cpu_option) {
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 20/36] vl: separate qemu_resolve_machine_memdev
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (18 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 19/36] vl: separate qemu_apply_machine_options Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 17:39   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 21/36] vl: initialize displays before preconfig loop Paolo Bonzini
                   ` (17 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

This is a bit nasty: the machine is storing a string and later
resolving it.  We probably want to make the memdev property a
normal link, and handle "-M memdev" as a legacy option that is
special cased by machine_set_property.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 70 +++++++++++++++++++++++++++-------------------------
 1 file changed, 37 insertions(+), 33 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 741a800114..6c8a103178 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2834,6 +2834,42 @@ static bool have_custom_ram_size(void)
     return !!qemu_opt_get_size(opts, "size", 0);
 }
 
+static void qemu_resolve_machine_memdev(void)
+{
+    if (current_machine->ram_memdev_id) {
+        Object *backend;
+        ram_addr_t backend_size;
+
+        backend = object_resolve_path_type(current_machine->ram_memdev_id,
+                                           TYPE_MEMORY_BACKEND, NULL);
+        if (!backend) {
+            error_report("Memory backend '%s' not found",
+                         current_machine->ram_memdev_id);
+            exit(EXIT_FAILURE);
+        }
+        backend_size = object_property_get_uint(backend, "size",  &error_abort);
+        if (have_custom_ram_size() && backend_size != ram_size) {
+                error_report("Size specified by -m option must match size of "
+                             "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;
+    }
+
+    if (!xen_enabled()) {
+        /* On 32-bit hosts, QEMU is limited by virtual address space */
+        if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
+            error_report("at most 2047 MB RAM can be simulated");
+            exit(1);
+        }
+    }
+}
+
 static void set_memory_options(MachineClass *mc)
 {
     uint64_t sz;
@@ -4467,39 +4503,7 @@ void qemu_init(int argc, char **argv, char **envp)
         current_machine->cpu_type = parse_cpu_option(cpu_option);
     }
 
-    if (current_machine->ram_memdev_id) {
-        Object *backend;
-        ram_addr_t backend_size;
-
-        backend = object_resolve_path_type(current_machine->ram_memdev_id,
-                                           TYPE_MEMORY_BACKEND, NULL);
-        if (!backend) {
-            error_report("Memory backend '%s' not found",
-                         current_machine->ram_memdev_id);
-            exit(EXIT_FAILURE);
-        }
-        backend_size = object_property_get_uint(backend, "size",  &error_abort);
-        if (have_custom_ram_size() && backend_size != ram_size) {
-                error_report("Size specified by -m option must match size of "
-                             "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;
-    }
-
-    if (!xen_enabled()) {
-        /* On 32-bit hosts, QEMU is limited by virtual address space */
-        if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
-            error_report("at most 2047 MB RAM can be simulated");
-            exit(1);
-        }
-    }
-
+    qemu_resolve_machine_memdev();
     parse_numa_opts(current_machine);
 
     /* do monitor/qmp handling at preconfig state if requested */
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 21/36] vl: initialize displays before preconfig loop
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (19 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 20/36] vl: separate qemu_resolve_machine_memdev Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 17:51   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 22/36] vl: move -global check earlier Paolo Bonzini
                   ` (16 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Displays should be available before the monitor starts, so that
it is possible to use the graphical console to interact with
the monitor itself.

This patch is quite ugly, but all this is temporary.  The double
call to qemu_init_displays will go away as soon we can unify machine
initialization between the preconfig and "normal" flows, and so will
the preconfig_exit_requested variable (that is only preconfig_requested
remains).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 57 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 21 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 6c8a103178..073d7412ad 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -137,6 +137,7 @@ 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;
@@ -3211,12 +3212,12 @@ static void qemu_validate_options(void)
           }
     }
 
-    if (loadvm && !preconfig_exit_requested) {
+    if (loadvm && preconfig_requested) {
         error_report("'preconfig' and 'loadvm' options are "
                      "mutually exclusive");
         exit(EXIT_FAILURE);
     }
-    if (incoming && !preconfig_exit_requested) {
+    if (incoming && preconfig_requested) {
         error_report("'preconfig' and 'incoming' options are "
                      "mutually exclusive");
         exit(EXIT_FAILURE);
@@ -3380,6 +3381,28 @@ static void qemu_init_subsystems(void)
     socket_init();
 }
 
+static void qemu_init_displays(void)
+{
+    DisplayState *ds;
+
+    /* init local displays */
+    ds = init_displaystate();
+    qemu_display_init(ds, &dpy);
+
+    /* 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();
+    }
+}
+
 /*
  * Called after leaving preconfig state.  From here on runstate is
  * RUN_STATE_PRELAUNCH or RUN_STATE_INMIGRATE.
@@ -3443,8 +3466,6 @@ static void qemu_create_cli_devices(void)
 
 static void qemu_machine_creation_done(void)
 {
-    DisplayState *ds;
-
     cpu_synchronize_all_post_init();
 
     /* Did we create any drives that we failed to create a device for? */
@@ -3467,23 +3488,6 @@ static void qemu_machine_creation_done(void)
         qemu_register_reset(restore_boot_order, g_strdup(boot_order));
     }
 
-    /* init local displays */
-    ds = init_displaystate();
-    qemu_display_init(ds, &dpy);
-
-    /* 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();
-    }
-
     if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
         exit(1);
     }
@@ -4083,6 +4087,7 @@ void qemu_init(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_preconfig:
                 preconfig_exit_requested = false;
+                preconfig_requested = true;
                 break;
             case QEMU_OPTION_enable_kvm:
                 olist = qemu_find_opts("machine");
@@ -4506,11 +4511,21 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_resolve_machine_memdev();
     parse_numa_opts(current_machine);
 
+    if (preconfig_requested) {
+        qemu_init_displays();
+    }
+
     /* do monitor/qmp handling at preconfig state if requested */
     qemu_main_loop();
 
     qemu_init_board();
+
     qemu_create_cli_devices();
+
+    /* initialize displays after all errors have been reported */
+    if (!preconfig_requested) {
+        qemu_init_displays();
+    }
     qemu_machine_creation_done();
 
     if (loadvm) {
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 22/36] vl: move -global check earlier
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (20 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 21/36] vl: initialize displays before preconfig loop Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 17:55   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 23/36] migration, vl: start migration via qmp_migrate_incoming Paolo Bonzini
                   ` (15 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

The check has the same effect here, it only matters that it is performed
once all devices, both builtin and user-specified, have been created.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index 073d7412ad..ccc3b8e838 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3483,6 +3483,8 @@ static void qemu_machine_creation_done(void)
         net_check_clients();
     }
 
+    qdev_prop_check_globals();
+
     if (boot_once) {
         qemu_boot_set(boot_once, &error_fatal);
         qemu_register_reset(restore_boot_order, g_strdup(boot_order));
@@ -4540,7 +4542,6 @@ void qemu_init(int argc, char **argv, char **envp)
         replay_vmstate_init();
     }
 
-    qdev_prop_check_globals();
     if (vmstate_dump_file) {
         /* dump and exit */
         dump_vmstate_json_to_file(vmstate_dump_file);
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 23/36] migration, vl: start migration via qmp_migrate_incoming
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (21 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 22/36] vl: move -global check earlier Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 18:04   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 24/36] vl: start VM via qmp_cont Paolo Bonzini
                   ` (14 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Make qemu_start_incoming_migration local to migration/migration.c.
By using the runstate instead of a separate flag, vl need not do
anything to setup deferred incoming migration.

qmp_migrate_incoming also does not need the deferred_incoming flag
anymore, because "-incoming PROTOCOL" will clear the "once" flag
before the main loop starts.  Therefore, later invocations of
the migrate-incoming command will fail with the existing
"The incoming migration has already been started" error message.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/migration/misc.h |  1 -
 migration/migration.c    | 33 ++++++++-------------------------
 softmmu/vl.c             | 11 +++++++----
 3 files changed, 15 insertions(+), 30 deletions(-)

diff --git a/include/migration/misc.h b/include/migration/misc.h
index 34e7d75713..bccc1b6b44 100644
--- a/include/migration/misc.h
+++ b/include/migration/misc.h
@@ -58,7 +58,6 @@ void dump_vmstate_json_to_file(FILE *out_fp);
 /* migration/migration.c */
 void migration_object_init(void);
 void migration_shutdown(void);
-void qemu_start_incoming_migration(const char *uri, Error **errp);
 bool migration_is_idle(void);
 bool migration_is_active(MigrationState *);
 void add_migration_state_change_notifier(Notifier *notify);
diff --git a/migration/migration.c b/migration/migration.c
index d9e94f4080..e0dbde4091 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -118,8 +118,6 @@
 static NotifierList migration_state_notifiers =
     NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
 
-static bool deferred_incoming;
-
 /* Messages sent on the return path from destination to source */
 enum mig_rp_message_type {
     MIG_RP_MSG_INVALID = 0,  /* Must be 0 */
@@ -275,19 +273,6 @@ static bool migrate_late_block_activate(void)
         MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
 }
 
-/*
- * Called on -incoming with a defer: uri.
- * The migration can be started later after any parameters have been
- * changed.
- */
-static void deferred_incoming_migration(Error **errp)
-{
-    if (deferred_incoming) {
-        error_setg(errp, "Incoming migration already deferred");
-    }
-    deferred_incoming = true;
-}
-
 /*
  * Send a message on the return channel back to the source
  * of the migration.
@@ -429,16 +414,14 @@ void migrate_add_address(SocketAddress *address)
     addrs->value = QAPI_CLONE(SocketAddress, address);
 }
 
-void qemu_start_incoming_migration(const char *uri, Error **errp)
+static void qemu_start_incoming_migration(const char *uri, Error **errp)
 {
     const char *p = NULL;
 
     qapi_event_send_migration(MIGRATION_STATUS_SETUP);
-    if (!strcmp(uri, "defer")) {
-        deferred_incoming_migration(errp);
-    } else if (strstart(uri, "tcp:", &p) ||
-               strstart(uri, "unix:", NULL) ||
-               strstart(uri, "vsock:", NULL)) {
+    if (strstart(uri, "tcp:", &p) ||
+        strstart(uri, "unix:", NULL) ||
+        strstart(uri, "vsock:", NULL)) {
         socket_start_incoming_migration(p ? p : uri, errp);
 #ifdef CONFIG_RDMA
     } else if (strstart(uri, "rdma:", &p)) {
@@ -1988,14 +1971,14 @@ void qmp_migrate_incoming(const char *uri, Error **errp)
     Error *local_err = NULL;
     static bool once = true;
 
-    if (!deferred_incoming) {
-        error_setg(errp, "For use with '-incoming defer'");
-        return;
-    }
     if (!once) {
         error_setg(errp, "The incoming migration has already been started");
         return;
     }
+    if (!runstate_check(RUN_STATE_INMIGRATE)) {
+        error_setg(errp, "'-incoming' was not specified on the command line");
+        return;
+    }
 
     qemu_start_incoming_migration(uri, &local_err);
 
diff --git a/softmmu/vl.c b/softmmu/vl.c
index ccc3b8e838..d548c31ba0 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -109,6 +109,7 @@
 #include "qapi/qapi-visit-block-core.h"
 #include "qapi/qapi-visit-ui.h"
 #include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-commands-migration.h"
 #include "qapi/qapi-commands-run-state.h"
 #include "qapi/qapi-commands-ui.h"
 #include "qapi/qmp/qerror.h"
@@ -4549,10 +4550,12 @@ void qemu_init(int argc, char **argv, char **envp)
     }
     if (incoming) {
         Error *local_err = NULL;
-        qemu_start_incoming_migration(incoming, &local_err);
-        if (local_err) {
-            error_reportf_err(local_err, "-incoming %s: ", incoming);
-            exit(1);
+        if (strcmp(incoming, "defer") != 0) {
+            qmp_migrate_incoming(incoming, &local_err);
+            if (local_err) {
+                error_reportf_err(local_err, "-incoming %s: ", incoming);
+                exit(1);
+            }
         }
     } else if (autostart) {
         vm_start();
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 24/36] vl: start VM via qmp_cont
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (22 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 23/36] migration, vl: start migration via qmp_migrate_incoming Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 25/36] hmp: introduce cmd_available Paolo Bonzini
                   ` (13 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Complement the previous patch by starting the VM with a QMP command.
The plan is that the user will be able to do the same, invoking two
commands "finish-machine-init" and "cont" instead of
"x-exit-preconfig".

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index d548c31ba0..ecfe16c4c4 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -110,6 +110,7 @@
 #include "qapi/qapi-visit-ui.h"
 #include "qapi/qapi-commands-block-core.h"
 #include "qapi/qapi-commands-migration.h"
+#include "qapi/qapi-commands-misc.h"
 #include "qapi/qapi-commands-run-state.h"
 #include "qapi/qapi-commands-ui.h"
 #include "qapi/qmp/qerror.h"
@@ -4558,7 +4559,7 @@ void qemu_init(int argc, char **argv, char **envp)
             }
         }
     } else if (autostart) {
-        vm_start();
+        qmp_cont(NULL);
     }
 
     accel_setup_post(current_machine);
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 25/36] hmp: introduce cmd_available
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (23 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 24/36] vl: start VM via qmp_cont Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-23 14:14 ` [PATCH 26/36] remove preconfig state Paolo Bonzini
                   ` (12 subsequent siblings)
  37 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov

Combine the RUN_STATE_PRECONFIG and cmd_can_preconfig checks
into a single function, to avoid repeating the same expression
(or its negation after applying DeMorgan's rule) over and
over again.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 monitor/hmp.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/monitor/hmp.c b/monitor/hmp.c
index 1204233999..d40f4f4391 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -213,6 +213,11 @@ static bool cmd_can_preconfig(const HMPCommand *cmd)
     return strchr(cmd->flags, 'p');
 }
 
+static bool cmd_available(const HMPCommand *cmd)
+{
+    return !runstate_check(RUN_STATE_PRECONFIG) || cmd_can_preconfig(cmd);
+}
+
 static void help_cmd_dump_one(Monitor *mon,
                               const HMPCommand *cmd,
                               char **prefix_args,
@@ -220,7 +225,7 @@ static void help_cmd_dump_one(Monitor *mon,
 {
     int i;
 
-    if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) {
+    if (!cmd_available(cmd)) {
         return;
     }
 
@@ -248,8 +253,7 @@ static void help_cmd_dump(Monitor *mon, const HMPCommand *cmds,
     /* Find one entry to dump */
     for (cmd = cmds; cmd->name != NULL; cmd++) {
         if (hmp_compare_cmd(args[arg_index], cmd->name) &&
-            ((!runstate_check(RUN_STATE_PRECONFIG) ||
-                cmd_can_preconfig(cmd)))) {
+            cmd_available(cmd)) {
             if (cmd->sub_table) {
                 /* continue with next arg */
                 help_cmd_dump(mon, cmd->sub_table,
@@ -653,7 +657,7 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon,
                        (int)(p - cmdp_start), cmdp_start);
         return NULL;
     }
-    if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) {
+    if (!cmd_available(cmd)) {
         monitor_printf(mon, "Command '%.*s' not available with -preconfig "
                             "until after exit_preconfig.\n",
                        (int)(p - cmdp_start), cmdp_start);
@@ -1225,8 +1229,7 @@ static void monitor_find_completion_by_table(MonitorHMP *mon,
         }
         readline_set_completion_index(mon->rs, strlen(cmdname));
         for (cmd = cmd_table; cmd->name != NULL; cmd++) {
-            if (!runstate_check(RUN_STATE_PRECONFIG) ||
-                 cmd_can_preconfig(cmd)) {
+            if (cmd_available(cmd)) {
                 cmd_completion(mon, cmdname, cmd->name);
             }
         }
@@ -1234,8 +1237,7 @@ static void monitor_find_completion_by_table(MonitorHMP *mon,
         /* find the command */
         for (cmd = cmd_table; cmd->name != NULL; cmd++) {
             if (hmp_compare_cmd(args[0], cmd->name) &&
-                (!runstate_check(RUN_STATE_PRECONFIG) ||
-                 cmd_can_preconfig(cmd))) {
+                cmd_available(cmd)) {
                 break;
             }
         }
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 26/36] remove preconfig state
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (24 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 25/36] hmp: introduce cmd_available Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-26 18:55   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 27/36] vl: remove separate preconfig main_loop Paolo Bonzini
                   ` (11 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

The preconfig state is only used if -incoming is not specified, which
makes the RunState state machine more tricky than it need be.  However
there is already an equivalent condition which works even with -incoming,
namely qdev_hotplug.  Use it instead of a separate runstate.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine-qmp-cmds.c    |  5 ++---
 include/qapi/qmp/dispatch.h   |  1 +
 monitor/hmp.c                 |  7 ++++---
 monitor/qmp-cmds.c            |  5 ++---
 qapi/qmp-dispatch.c           |  5 +----
 qapi/run-state.json           |  5 +----
 softmmu/qdev-monitor.c        | 12 ++++++++++++
 softmmu/vl.c                  | 13 ++-----------
 stubs/meson.build             |  1 +
 stubs/qmp-command-available.c |  7 +++++++
 tests/qtest/qmp-test.c        |  2 +-
 11 files changed, 34 insertions(+), 29 deletions(-)
 create mode 100644 stubs/qmp-command-available.c

diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index 5362c80a18..cb9387c5f5 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -286,9 +286,8 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
 
 void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
 {
-    if (!runstate_check(RUN_STATE_PRECONFIG)) {
-        error_setg(errp, "The command is permitted only in '%s' state",
-                   RunState_str(RUN_STATE_PRECONFIG));
+    if (qdev_hotplug) {
+         error_setg(errp, "The command is permitted only before the machine has been created");
          return;
     }
 
diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index af8d96c570..1486cac3ef 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -48,6 +48,7 @@ void qmp_disable_command(QmpCommandList *cmds, const char *name);
 void qmp_enable_command(QmpCommandList *cmds, const char *name);
 
 bool qmp_command_is_enabled(const QmpCommand *cmd);
+bool qmp_command_available(const QmpCommand *cmd, Error **errp);
 const char *qmp_command_name(const QmpCommand *cmd);
 bool qmp_has_success_response(const QmpCommand *cmd);
 QDict *qmp_error_response(Error *err);
diff --git a/monitor/hmp.c b/monitor/hmp.c
index d40f4f4391..f2fe192d69 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include <dirent.h>
+#include "hw/qdev-core.h"
 #include "monitor-internal.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
@@ -215,7 +216,7 @@ static bool cmd_can_preconfig(const HMPCommand *cmd)
 
 static bool cmd_available(const HMPCommand *cmd)
 {
-    return !runstate_check(RUN_STATE_PRECONFIG) || cmd_can_preconfig(cmd);
+    return qdev_hotplug || cmd_can_preconfig(cmd);
 }
 
 static void help_cmd_dump_one(Monitor *mon,
@@ -658,8 +659,8 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon,
         return NULL;
     }
     if (!cmd_available(cmd)) {
-        monitor_printf(mon, "Command '%.*s' not available with -preconfig "
-                            "until after exit_preconfig.\n",
+        monitor_printf(mon, "Command '%.*s' not available "
+                            "until machine initialization has completed.\n",
                        (int)(p - cmdp_start), cmdp_start);
         return NULL;
     }
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 6299c0c8c7..501a3024c7 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -104,9 +104,8 @@ void qmp_system_powerdown(Error **errp)
 
 void qmp_x_exit_preconfig(Error **errp)
 {
-    if (!runstate_check(RUN_STATE_PRECONFIG)) {
-        error_setg(errp, "The command is permitted only in '%s' state",
-                   RunState_str(RUN_STATE_PRECONFIG));
+    if (qdev_hotplug) {
+        error_setg(errp, "The command is permitted only before machine initialization");
         return;
     }
     qemu_exit_preconfig_request();
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 9a2d7dd29a..0a2b20a4e4 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -167,10 +167,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
         goto out;
     }
 
-    if (runstate_check(RUN_STATE_PRECONFIG) &&
-        !(cmd->options & QCO_ALLOW_PRECONFIG)) {
-        error_setg(&err, "The command '%s' isn't permitted in '%s' state",
-                   cmd->name, RunState_str(RUN_STATE_PRECONFIG));
+    if (!qmp_command_available(cmd, &err)) {
         goto out;
     }
 
diff --git a/qapi/run-state.json b/qapi/run-state.json
index 964c8ef391..38194b0e44 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -50,15 +50,12 @@
 # @colo: guest is paused to save/restore VM state under colo checkpoint,
 #        VM can not get into this state unless colo capability is enabled
 #        for migration. (since 2.8)
-# @preconfig: QEMU is paused before board specific init callback is executed.
-#             The state is reachable only if the --preconfig CLI option is used.
-#             (Since 3.0)
 ##
 { 'enum': 'RunState',
   'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
             'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
             'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
-            'guest-panicked', 'colo', 'preconfig' ] }
+            'guest-panicked', 'colo' ] }
 
 ##
 # @ShutdownCause:
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index d060e765da..e967d13bd0 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -25,6 +25,7 @@
 #include "sysemu/arch_init.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-qdev.h"
+#include "qapi/qmp/dispatch.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/config-file.h"
@@ -997,3 +998,14 @@ int qemu_global_option(const char *str)
 
     return 0;
 }
+
+bool qmp_command_available(const QmpCommand *cmd, Error **errp)
+{
+    if (!qdev_hotplug &&
+        !(cmd->options & QCO_ALLOW_PRECONFIG)) {
+        error_setg(errp, "The command '%s' is permitted only after machine initialization has completed",
+                   cmd->name);
+        return false;
+    }
+    return true;
+}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index ecfe16c4c4..95c62bdad4 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -573,7 +573,7 @@ static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp)
 /***********************************************************/
 /* QEMU state */
 
-static RunState current_run_state = RUN_STATE_PRECONFIG;
+static RunState current_run_state = RUN_STATE_PRELAUNCH;
 
 /* We use RUN_STATE__MAX but any invalid value will do */
 static RunState vmstop_requested = RUN_STATE__MAX;
@@ -585,13 +585,7 @@ typedef struct {
 } RunStateTransition;
 
 static const RunStateTransition runstate_transitions_def[] = {
-    /*     from      ->     to      */
-    { RUN_STATE_PRECONFIG, RUN_STATE_PRELAUNCH },
-      /* Early switch to inmigrate state to allow  -incoming CLI option work
-       * as it used to. TODO: delay actual switching to inmigrate state to
-       * the point after machine is built and remove this hack.
-       */
-    { RUN_STATE_PRECONFIG, RUN_STATE_INMIGRATE },
+    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
 
     { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
     { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
@@ -1633,9 +1627,6 @@ static bool main_loop_should_exit(void)
     ShutdownCause request;
 
     if (preconfig_exit_requested) {
-        if (runstate_check(RUN_STATE_PRECONFIG)) {
-            runstate_set(RUN_STATE_PRELAUNCH);
-        }
         preconfig_exit_requested = false;
         return true;
     }
diff --git a/stubs/meson.build b/stubs/meson.build
index 82b7ba60ab..cc56c83063 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -29,6 +29,7 @@ stub_ss.add(files('pci-bus.c'))
 stub_ss.add(files('pci-host-piix.c'))
 stub_ss.add(files('qemu-timer-notify-cb.c'))
 stub_ss.add(files('qmp_memory_device.c'))
+stub_ss.add(files('qmp-command-available.c'))
 stub_ss.add(files('qtest.c'))
 stub_ss.add(files('ram-block.c'))
 stub_ss.add(files('ramfb.c'))
diff --git a/stubs/qmp-command-available.c b/stubs/qmp-command-available.c
new file mode 100644
index 0000000000..46540af7bf
--- /dev/null
+++ b/stubs/qmp-command-available.c
@@ -0,0 +1,7 @@
+#include "qemu/osdep.h"
+#include "qapi/qmp/dispatch.h"
+
+bool qmp_command_available(const QmpCommand *cmd, Error **errp)
+{
+    return true;
+}
diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c
index eb1cd8abb8..11614bf63f 100644
--- a/tests/qtest/qmp-test.c
+++ b/tests/qtest/qmp-test.c
@@ -295,7 +295,7 @@ static void test_qmp_preconfig(void)
     rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }");
     ret = qdict_get_qdict(rsp, "return");
     g_assert(ret);
-    g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "preconfig");
+    g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "prelaunch");
     qobject_unref(rsp);
 
     /* exit preconfig state */
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 27/36] vl: remove separate preconfig main_loop
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (25 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 26/36] remove preconfig state Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-30 12:46   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 28/36] vl: allow -incoming defer with -preconfig Paolo Bonzini
                   ` (10 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Move post-preconfig initialization to the x-exit-preconfig.  If preconfig
is not requested, just exit preconfig mode immediately with the QMP
command.

As a result, the preconfig loop will run with accel_setup_post
and os_setup_post restrictions (xen_restrict, chroot, etc.)
already done.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/sysemu/runstate.h |  1 -
 monitor/qmp-cmds.c        |  9 ----
 softmmu/vl.c              | 95 +++++++++++++++++----------------------
 3 files changed, 41 insertions(+), 64 deletions(-)

diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h
index f760094858..e557f470d4 100644
--- a/include/sysemu/runstate.h
+++ b/include/sysemu/runstate.h
@@ -41,7 +41,6 @@ typedef enum WakeupReason {
     QEMU_WAKEUP_REASON_OTHER,
 } WakeupReason;
 
-void qemu_exit_preconfig_request(void);
 void qemu_system_reset_request(ShutdownCause reason);
 void qemu_system_suspend_request(void);
 void qemu_register_suspend_notifier(Notifier *notifier);
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 501a3024c7..7ced7eb3e8 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -102,15 +102,6 @@ void qmp_system_powerdown(Error **errp)
     qemu_system_powerdown_request();
 }
 
-void qmp_x_exit_preconfig(Error **errp)
-{
-    if (qdev_hotplug) {
-        error_setg(errp, "The command is permitted only before machine initialization");
-        return;
-    }
-    qemu_exit_preconfig_request();
-}
-
 void qmp_cont(Error **errp)
 {
     BlockBackend *blk;
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 95c62bdad4..aa11fc4871 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -1313,7 +1313,6 @@ static pid_t shutdown_pid;
 static int powerdown_requested;
 static int debug_requested;
 static int suspend_requested;
-static bool preconfig_exit_requested = true;
 static WakeupReason wakeup_reason;
 static NotifierList powerdown_notifiers =
     NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
@@ -1400,11 +1399,6 @@ static int qemu_debug_requested(void)
     return r;
 }
 
-void qemu_exit_preconfig_request(void)
-{
-    preconfig_exit_requested = true;
-}
-
 /*
  * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
  */
@@ -1626,10 +1620,6 @@ static bool main_loop_should_exit(void)
     RunState r;
     ShutdownCause request;
 
-    if (preconfig_exit_requested) {
-        preconfig_exit_requested = false;
-        return true;
-    }
     if (qemu_debug_requested()) {
         vm_stop(RUN_STATE_DEBUG);
     }
@@ -3517,6 +3507,43 @@ static void qemu_machine_creation_done(void)
     register_global_state();
 }
 
+void qmp_x_exit_preconfig(Error **errp)
+{
+    if (qdev_hotplug) {
+        error_setg(errp, "The command is permitted only before machine initialization");
+        return;
+    }
+
+    qemu_init_board();
+    qemu_create_cli_devices();
+    qemu_machine_creation_done();
+
+    if (loadvm) {
+        Error *local_err = NULL;
+        if (load_snapshot(loadvm, &local_err) < 0) {
+            error_report_err(local_err);
+            autostart = 0;
+            exit(1);
+        }
+    }
+    if (replay_mode != REPLAY_MODE_NONE) {
+        replay_vmstate_init();
+    }
+
+    if (incoming) {
+        Error *local_err = NULL;
+        if (strcmp(incoming, "defer") != 0) {
+            qmp_migrate_incoming(incoming, &local_err);
+            if (local_err) {
+                error_reportf_err(local_err, "-incoming %s: ", incoming);
+                exit(1);
+            }
+        }
+    } else if (autostart) {
+        qmp_cont(NULL);
+    }
+}
+
 void qemu_init(int argc, char **argv, char **envp)
 {
     QemuOpts *opts;
@@ -4081,7 +4108,6 @@ void qemu_init(int argc, char **argv, char **envp)
                 }
                 break;
             case QEMU_OPTION_preconfig:
-                preconfig_exit_requested = false;
                 preconfig_requested = true;
                 break;
             case QEMU_OPTION_enable_kvm:
@@ -4506,57 +4532,18 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_resolve_machine_memdev();
     parse_numa_opts(current_machine);
 
-    if (preconfig_requested) {
-        qemu_init_displays();
-    }
-
-    /* do monitor/qmp handling at preconfig state if requested */
-    qemu_main_loop();
-
-    qemu_init_board();
-
-    qemu_create_cli_devices();
-
-    /* initialize displays after all errors have been reported */
-    if (!preconfig_requested) {
-        qemu_init_displays();
-    }
-    qemu_machine_creation_done();
-
-    if (loadvm) {
-        Error *local_err = NULL;
-        if (load_snapshot(loadvm, &local_err) < 0) {
-            error_report_err(local_err);
-            autostart = 0;
-            exit(1);
-        }
-    }
-    if (replay_mode != REPLAY_MODE_NONE) {
-        replay_vmstate_init();
-    }
-
     if (vmstate_dump_file) {
         /* dump and exit */
         dump_vmstate_json_to_file(vmstate_dump_file);
         exit(0);
     }
-    if (incoming) {
-        Error *local_err = NULL;
-        if (strcmp(incoming, "defer") != 0) {
-            qmp_migrate_incoming(incoming, &local_err);
-            if (local_err) {
-                error_reportf_err(local_err, "-incoming %s: ", incoming);
-                exit(1);
-            }
-        }
-    } else if (autostart) {
-        qmp_cont(NULL);
-    }
 
+    qemu_init_displays();
+    if (!preconfig_requested) {
+        qmp_x_exit_preconfig(&error_fatal);
+    }
     accel_setup_post(current_machine);
     os_setup_post();
-
-    return;
 }
 
 void qemu_cleanup(void)
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 28/36] vl: allow -incoming defer with -preconfig
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (26 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 27/36] vl: remove separate preconfig main_loop Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 10:51   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 29/36] vl: extract softmmu/datadir.c Paolo Bonzini
                   ` (9 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Now that there is no RUN_STATE_PRECONFIG anymore that can conflict with
RUN_STATE_INMIGRATE, we can allow -incoming defer with -preconfig.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 softmmu/vl.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/softmmu/vl.c b/softmmu/vl.c
index aa11fc4871..0ba1fcdb3d 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3200,9 +3200,8 @@ static void qemu_validate_options(void)
                      "mutually exclusive");
         exit(EXIT_FAILURE);
     }
-    if (incoming && preconfig_requested) {
-        error_report("'preconfig' and 'incoming' options are "
-                     "mutually exclusive");
+    if (incoming && preconfig_requested && strcmp(incoming, "defer") != 0) {
+        error_report("'preconfig' supports '-incoming defer' only");
         exit(EXIT_FAILURE);
     }
 
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 29/36] vl: extract softmmu/datadir.c
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (27 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 28/36] vl: allow -incoming defer with -preconfig Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 12:06   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 30/36] vl: extract machine done notifiers Paolo Bonzini
                   ` (8 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/alpha/dp264.c        |   1 +
 hw/arm/boot.c           |   1 +
 hw/arm/digic_boards.c   |   1 +
 hw/arm/highbank.c       |   1 +
 hw/arm/npcm7xx_boards.c |   1 +
 hw/arm/sbsa-ref.c       |   1 +
 hw/arm/vexpress.c       |   1 +
 hw/arm/virt.c           |   1 +
 hw/avr/boot.c           |   1 +
 hw/core/loader.c        |   1 +
 hw/display/cg3.c        |   1 +
 hw/display/tcx.c        |   1 +
 hw/hppa/machine.c       |   1 +
 hw/i386/x86.c           |   1 +
 hw/lm32/milkymist.c     |   1 +
 hw/m68k/mcf5208.c       |   1 +
 hw/m68k/q800.c          |   1 +
 hw/microblaze/boot.c    |   1 +
 hw/mips/fuloong2e.c     |   1 +
 hw/mips/jazz.c          |   1 +
 hw/mips/malta.c         |   1 +
 hw/mips/mipssim.c       |   1 +
 hw/nios2/boot.c         |   1 +
 hw/nvram/fw_cfg.c       |   1 +
 hw/pci-host/prep.c      |   1 +
 hw/pci/pci.c            |   1 +
 hw/ppc/e500.c           |   1 +
 hw/ppc/mac_newworld.c   |   1 +
 hw/ppc/mac_oldworld.c   |   1 +
 hw/ppc/pnv.c            |   1 +
 hw/ppc/ppc405_boards.c  |   1 +
 hw/ppc/ppc440_bamboo.c  |   1 +
 hw/ppc/sam460ex.c       |   1 +
 hw/ppc/spapr.c          |   1 +
 hw/ppc/virtex_ml507.c   |   1 +
 hw/riscv/boot.c         |   1 +
 hw/s390x/ipl.c          |   1 +
 hw/sparc/leon3.c        |   1 +
 hw/sparc/sun4m.c        |   1 +
 hw/sparc64/sun4u.c      |   1 +
 include/qemu-common.h   |  21 -------
 include/qemu/datadir.h  |  28 +++++++++
 include/sysemu/sysemu.h |   2 -
 softmmu/datadir.c       | 129 ++++++++++++++++++++++++++++++++++++++++
 softmmu/meson.build     |   1 +
 softmmu/vl.c            |  95 +----------------------------
 tests/qtest/fuzz/fuzz.c |   1 +
 ui/keymaps.c            |   1 +
 48 files changed, 203 insertions(+), 115 deletions(-)
 create mode 100644 include/qemu/datadir.h
 create mode 100644 softmmu/datadir.c

diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index c4d407a9f1..c8e300d93f 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -21,6 +21,7 @@
 #include "hw/dma/i8257.h"
 #include "net/net.h"
 #include "qemu/cutils.h"
+#include "qemu/datadir.h"
 #include "net/net.h"
 
 #define MAX_IDE_BUS 2
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index cf97600a91..4d9d47ba1c 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -9,6 +9,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include <libfdt.h>
diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
index fd228fa96f..be12873673 100644
--- a/hw/arm/digic_boards.c
+++ b/hw/arm/digic_boards.c
@@ -26,6 +26,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/boards.h"
 #include "exec/address-spaces.h"
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index fd3429720e..bf7b8f4c64 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index 9821013bc6..306260fa67 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -23,6 +23,7 @@
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "sysemu/sysemu.h"
 
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index c3a31f5b8b..b1fa3779d8 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "qemu/units.h"
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 1adb663d77..ac098375c1 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -24,6 +24,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/sysbus.h"
 #include "hw/arm/boot.h"
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 9c54eea585..82cb9c95cf 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -30,6 +30,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qemu/option.h"
 #include "monitor/qdev.h"
diff --git a/hw/avr/boot.c b/hw/avr/boot.c
index d16bb3dbe1..cbede775ce 100644
--- a/hw/avr/boot.c
+++ b/hw/avr/boot.c
@@ -10,6 +10,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "hw/loader.h"
 #include "elf.h"
 #include "boot.h"
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 8bbb1797a4..fea22d265c 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -44,6 +44,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "trace.h"
 #include "hw/hw.h"
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index 42fcf40010..4b7e78d919 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -25,6 +25,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "ui/console.h"
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 3799d29b75..965f92ff6b 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 7e41cb2462..f2b71db9bd 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -5,6 +5,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "elf.h"
 #include "hw/loader.h"
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 836d388248..f3a2425f37 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -26,6 +26,7 @@
 #include "qemu/cutils.h"
 #include "qemu/units.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/qapi-visit-common.h"
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 93ca8bc2ac..72d1326531 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -21,6 +21,7 @@
 #include "qemu/units.h"
 #include "qemu/error-report.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/sysbus.h"
 #include "hw/irq.h"
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 2205145ecc..7a03c71059 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -12,6 +12,7 @@
 #include "qemu/log.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/irq.h"
 #include "hw/m68k/mcf.h"
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 6ebcddcfb2..4db2b9bbc7 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -23,6 +23,7 @@
 #include "qemu/osdep.h"
 #include "qemu/units.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "sysemu/sysemu.h"
 #include "cpu.h"
 #include "hw/hw.h"
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index e1f56f83f9..6715ba2ff9 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -26,6 +26,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c
index 84a2132f85..45c596f4fe 100644
--- a/hw/mips/fuloong2e.c
+++ b/hw/mips/fuloong2e.c
@@ -20,6 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qapi/error.h"
 #include "cpu.h"
diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
index aa95c6a3d3..f9442731dd 100644
--- a/hw/mips/jazz.c
+++ b/hw/mips/jazz.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "hw/clock.h"
 #include "hw/mips/mips.h"
 #include "hw/mips/cpudevs.h"
diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index 467b21849e..5c11eecec1 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -25,6 +25,7 @@
 #include "qemu/osdep.h"
 #include "qemu/units.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/clock.h"
 #include "hw/southbridge/piix.h"
diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c
index cc9b0934b3..f2e6273525 100644
--- a/hw/mips/mipssim.c
+++ b/hw/mips/mipssim.c
@@ -28,6 +28,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/clock.h"
 #include "hw/mips/mips.h"
diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
index 3cb864914b..95a8697906 100644
--- a/hw/nios2/boot.c
+++ b/hw/nios2/boot.c
@@ -31,6 +31,7 @@
 #include "qemu/osdep.h"
 #include "qemu/units.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 08539a1aab..9e80633d6e 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 #include "sysemu/reset.h"
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index d0323fefb1..0469db8c1d 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -25,6 +25,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qapi/error.h"
 #include "hw/pci/pci.h"
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 0131d9d02c..9424231542 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "hw/irq.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bridge.h"
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 153a74c98c..6a64eb31ab 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -16,6 +16,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qapi/error.h"
 #include "e500.h"
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 61c63819df..c0accda592 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -48,6 +48,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "hw/ppc/ppc.h"
 #include "hw/qdev-properties.h"
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 11623e8e67..04f98a4d81 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -26,6 +26,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qapi/error.h"
 #include "hw/ppc/ppc.h"
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index 53a5121cab..14fc9758a9 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qapi/error.h"
 #include "sysemu/qtest.h"
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index c867e46330..b7249f21cf 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -26,6 +26,7 @@
 #include "qemu/units.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/ppc/ppc.h"
 #include "hw/qdev-properties.h"
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 74028dc986..665bc1784e 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -15,6 +15,7 @@
 #include "qemu/units.h"
 #include "qemu/error-report.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/error-report.h"
 #include "net/net.h"
 #include "hw/pci/pci.h"
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 7e59a91981..14e6583eb0 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -14,6 +14,7 @@
 #include "qemu/osdep.h"
 #include "qemu/units.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index cd8be98caf..049efa0bbf 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -26,6 +26,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index c790c1113f..7f1bca928c 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "cpu.h"
 #include "hw/sysbus.h"
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 70a9bf8f5d..d62f3dc758 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qemu/error-report.h"
 #include "exec/cpu-defs.h"
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index bddbaffac6..ff6b55e816 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -14,6 +14,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "sysemu/reset.h"
 #include "sysemu/runstate.h"
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 1c50b02f81..4bc4ebea84 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -27,6 +27,7 @@
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/irq.h"
 #include "qemu/timer.h"
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 0f9cd2bf52..8686371318 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -25,6 +25,7 @@
 #include "qemu/osdep.h"
 #include "qemu/units.h"
 #include "qapi/error.h"
+#include "qemu/datadir.h"
 #include "qemu-common.h"
 #include "cpu.h"
 #include "hw/sysbus.h"
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 8bee7dd2f4..0fa13a7330 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -27,6 +27,7 @@
 #include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "cpu.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bridge.h"
diff --git a/include/qemu-common.h b/include/qemu-common.h
index fda7dc6ca7..654621444e 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -108,27 +108,6 @@ void qemu_progress_end(void);
 void qemu_progress_print(float delta, int max);
 const char *qemu_get_vm_name(void);
 
-#define QEMU_FILE_TYPE_BIOS   0
-#define QEMU_FILE_TYPE_KEYMAP 1
-/**
- * qemu_find_file:
- * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS)
- *        or QEMU_FILE_TYPE_KEYMAP (for keymaps).
- * @name: Relative or absolute file name
- *
- * If @name exists on disk as an absolute path, or a path relative
- * to the current directory, then returns @name unchanged.
- * Otherwise searches for @name file in the data directories, either
- * configured at build time (DATADIR) or registered with the -L command
- * line option.
- *
- * The caller must use g_free() to free the returned data when it is
- * no longer required.
- *
- * Returns: a path that can access @name, or NULL if no matching file exists.
- */
-char *qemu_find_file(int type, const char *name);
-
 /* OS specific functions */
 void os_setup_early_signal_handling(void);
 int os_parse_cmd_args(int index, const char *optarg);
diff --git a/include/qemu/datadir.h b/include/qemu/datadir.h
new file mode 100644
index 0000000000..21f9097f58
--- /dev/null
+++ b/include/qemu/datadir.h
@@ -0,0 +1,28 @@
+#ifndef QEMU_DATADIR_H
+#define QEMU_DATADIR_H
+
+#define QEMU_FILE_TYPE_BIOS   0
+#define QEMU_FILE_TYPE_KEYMAP 1
+/**
+ * qemu_find_file:
+ * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS)
+ *        or QEMU_FILE_TYPE_KEYMAP (for keymaps).
+ * @name: Relative or absolute file name
+ *
+ * If @name exists on disk as an absolute path, or a path relative
+ * to the current directory, then returns @name unchanged.
+ * Otherwise searches for @name file in the data directories, either
+ * configured at build time (DATADIR) or registered with the -L command
+ * line option.
+ *
+ * The caller must use g_free() to free the returned data when it is
+ * no longer required.
+ *
+ * Returns: a path that can access @name, or NULL if no matching file exists.
+ */
+char *qemu_find_file(int type, const char *name);
+void qemu_add_default_firmwarepath(void);
+void qemu_add_data_dir(char *path);
+void qemu_list_data_dirs(void);
+
+#endif
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 1336b4264a..c94b2e7159 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -13,8 +13,6 @@ extern const char *qemu_name;
 extern QemuUUID qemu_uuid;
 extern bool qemu_uuid_set;
 
-void qemu_add_data_dir(char *path);
-
 void qemu_add_exit_notifier(Notifier *notify);
 void qemu_remove_exit_notifier(Notifier *notify);
 
diff --git a/softmmu/datadir.c b/softmmu/datadir.c
new file mode 100644
index 0000000000..504c4665be
--- /dev/null
+++ b/softmmu/datadir.c
@@ -0,0 +1,129 @@
+/*
+ * QEMU firmware and keymap file search
+ *
+ * Copyright (c) 2003-2020 QEMU contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/datadir.h"
+#include "qemu/cutils.h"
+#include "trace.h"
+
+static const char *data_dir[16];
+static int data_dir_idx;
+
+char *qemu_find_file(int type, const char *name)
+{
+    int i;
+    const char *subdir;
+    char *buf;
+
+    /* Try the name as a straight path first */
+    if (access(name, R_OK) == 0) {
+        trace_load_file(name, name);
+        return g_strdup(name);
+    }
+
+    switch (type) {
+    case QEMU_FILE_TYPE_BIOS:
+        subdir = "";
+        break;
+    case QEMU_FILE_TYPE_KEYMAP:
+        subdir = "keymaps/";
+        break;
+    default:
+        abort();
+    }
+
+    for (i = 0; i < data_dir_idx; i++) {
+        buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
+        if (access(buf, R_OK) == 0) {
+            trace_load_file(name, buf);
+            return buf;
+        }
+        g_free(buf);
+    }
+    return NULL;
+}
+
+void qemu_add_data_dir(char *path)
+{
+    int i;
+
+    if (path == NULL) {
+        return;
+    }
+    if (data_dir_idx == ARRAY_SIZE(data_dir)) {
+        return;
+    }
+    for (i = 0; i < data_dir_idx; i++) {
+        if (strcmp(data_dir[i], path) == 0) {
+            g_free(path); /* duplicate */
+            return;
+        }
+    }
+    data_dir[data_dir_idx++] = path;
+}
+
+/*
+ * Find a likely location for support files using the location of the binary.
+ * When running from the build tree this will be "$bindir/pc-bios".
+ * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated).
+ *
+ * The caller must use g_free() to free the returned data when it is
+ * no longer required.
+ */
+static char *find_datadir(void)
+{
+    g_autofree char *dir = NULL;
+
+    dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL);
+    if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
+        return g_steal_pointer(&dir);
+    }
+
+    return get_relocated_path(CONFIG_QEMU_DATADIR);
+}
+
+void qemu_add_default_firmwarepath(void)
+{
+    char **dirs;
+    size_t i;
+
+    /* add configured firmware directories */
+    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
+    for (i = 0; dirs[i] != NULL; i++) {
+        qemu_add_data_dir(get_relocated_path(dirs[i]));
+    }
+    g_strfreev(dirs);
+
+    /* try to find datadir relative to the executable path */
+    qemu_add_data_dir(find_datadir());
+}
+
+void qemu_list_data_dirs(void)
+{
+    int i;
+    for (i = 0; i < data_dir_idx; i++) {
+        printf("%s\n", data_dir[i]);
+    }
+}
diff --git a/softmmu/meson.build b/softmmu/meson.build
index 8f7210b4f0..7b52339e7a 100644
--- a/softmmu/meson.build
+++ b/softmmu/meson.build
@@ -3,6 +3,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
   'balloon.c',
   'cpus.c',
   'cpu-throttle.c',
+  'datadir.c',
   'physmem.c',
   'ioport.c',
   'memory.c',
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 0ba1fcdb3d..86ace29f98 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "hw/boards.h"
 #include "hw/qdev-properties.h"
@@ -128,8 +129,6 @@ typedef struct BlockdevOptionsQueueEntry {
 typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue;
 
 static const char *cpu_option;
-static const char *data_dir[16];
-static int data_dir_idx;
 static const char *mem_path;
 static const char *boot_order;
 static const char *boot_once;
@@ -1975,59 +1974,6 @@ static void parse_display(const char *p)
     }
 }
 
-char *qemu_find_file(int type, const char *name)
-{
-    int i;
-    const char *subdir;
-    char *buf;
-
-    /* Try the name as a straight path first */
-    if (access(name, R_OK) == 0) {
-        trace_load_file(name, name);
-        return g_strdup(name);
-    }
-
-    switch (type) {
-    case QEMU_FILE_TYPE_BIOS:
-        subdir = "";
-        break;
-    case QEMU_FILE_TYPE_KEYMAP:
-        subdir = "keymaps/";
-        break;
-    default:
-        abort();
-    }
-
-    for (i = 0; i < data_dir_idx; i++) {
-        buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
-        if (access(buf, R_OK) == 0) {
-            trace_load_file(name, buf);
-            return buf;
-        }
-        g_free(buf);
-    }
-    return NULL;
-}
-
-void qemu_add_data_dir(char *path)
-{
-    int i;
-
-    if (path == NULL) {
-        return;
-    }
-    if (data_dir_idx == ARRAY_SIZE(data_dir)) {
-        return;
-    }
-    for (i = 0; i < data_dir_idx; i++) {
-        if (strcmp(data_dir[i], path) == 0) {
-            g_free(path); /* duplicate */
-            return;
-        }
-    }
-    data_dir[data_dir_idx++] = path;
-}
-
 static inline bool nonempty_str(const char *str)
 {
     return str && *str;
@@ -3156,26 +3102,6 @@ static void create_default_memdev(MachineState *ms, const char *path)
                             &error_fatal);
 }
 
-/*
- * Find a likely location for support files using the location of the binary.
- * When running from the build tree this will be "$bindir/pc-bios".
- * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated).
- *
- * The caller must use g_free() to free the returned data when it is
- * no longer required.
- */
-static char *find_datadir(void)
-{
-    g_autofree char *dir = NULL;
-
-    dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL);
-    if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
-        return g_steal_pointer(&dir);
-    }
-
-    return get_relocated_path(CONFIG_QEMU_DATADIR);
-}
-
 static void qemu_validate_options(void)
 {
     QemuOpts *machine_opts = qemu_get_machine_opts();
@@ -3234,9 +3160,6 @@ static void qemu_process_sugar_options(void)
 
 static void qemu_process_early_options(void)
 {
-    char **dirs;
-    int i;
-
 #ifdef CONFIG_SECCOMP
     QemuOptsList *olist = qemu_find_opts_err("sandbox", NULL);
     if (olist) {
@@ -3274,21 +3197,11 @@ static void qemu_process_early_options(void)
         qemu_set_log(0);
     }
 
-    /* add configured firmware directories */
-    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
-    for (i = 0; dirs[i] != NULL; i++) {
-        qemu_add_data_dir(get_relocated_path(dirs[i]));
-    }
-    g_strfreev(dirs);
-
-    /* try to find datadir relative to the executable path */
-    qemu_add_data_dir(find_datadir());
+    qemu_add_default_firmwarepath();
 }
 
 static void qemu_process_help_options(void)
 {
-    int i;
-
     /*
      * Check for -cpu help and -device help before we call select_machine(),
      * which will return an error if the architecture has no default machine
@@ -3307,9 +3220,7 @@ static void qemu_process_help_options(void)
 
     /* -L help lists the data directories and exits. */
     if (list_data_dirs) {
-        for (i = 0; i < data_dir_idx; i++) {
-            printf("%s\n", data_dir[i]);
-        }
+        qemu_list_data_dirs();
         exit(0);
     }
 }
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
index 7be7226bc0..238866a037 100644
--- a/tests/qtest/fuzz/fuzz.c
+++ b/tests/qtest/fuzz/fuzz.c
@@ -15,6 +15,7 @@
 
 #include <wordexp.h>
 
+#include "qemu/datadir.h"
 #include "sysemu/qtest.h"
 #include "sysemu/runstate.h"
 #include "sysemu/sysemu.h"
diff --git a/ui/keymaps.c b/ui/keymaps.c
index 4e5fca57a8..d4a647464b 100644
--- a/ui/keymaps.c
+++ b/ui/keymaps.c
@@ -24,6 +24,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/datadir.h"
 #include "keymaps.h"
 #include "trace.h"
 #include "qemu/ctype.h"
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 30/36] vl: extract machine done notifiers
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (28 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 29/36] vl: extract softmmu/datadir.c Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 12:14   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 31/36] vl: extract softmmu/rtc.c Paolo Bonzini
                   ` (7 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine.c       | 24 ++++++++++++++++++++++++
 include/sysemu/sysemu.h |  1 +
 softmmu/vl.c            | 24 ------------------------
 3 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index a5cfbcc7cb..745531c9d9 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -1166,6 +1166,30 @@ void machine_run_board_init(MachineState *machine)
     machine_class->init(machine);
 }
 
+static NotifierList machine_init_done_notifiers =
+    NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
+
+bool machine_init_done;
+
+void qemu_add_machine_init_done_notifier(Notifier *notify)
+{
+    notifier_list_add(&machine_init_done_notifiers, notify);
+    if (machine_init_done) {
+        notify->notify(notify, NULL);
+    }
+}
+
+void qemu_remove_machine_init_done_notifier(Notifier *notify)
+{
+    notifier_remove(notify);
+}
+
+void qemu_run_machine_init_done_notifiers(void)
+{
+    machine_init_done = true;
+    notifier_list_notify(&machine_init_done_notifiers, NULL);
+}
+
 static const TypeInfo machine_info = {
     .name = TYPE_MACHINE,
     .parent = TYPE_OBJECT,
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index c94b2e7159..1b62deaf2b 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -18,6 +18,7 @@ void qemu_remove_exit_notifier(Notifier *notify);
 
 extern bool machine_init_done;
 
+void qemu_run_machine_init_done_notifiers(void);
 void qemu_add_machine_init_done_notifier(Notifier *notify);
 void qemu_remove_machine_init_done_notifier(Notifier *notify);
 
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 86ace29f98..7e13bb4a59 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -204,9 +204,6 @@ bool qemu_uuid_set;
 static NotifierList exit_notifiers =
     NOTIFIER_LIST_INITIALIZER(exit_notifiers);
 
-static NotifierList machine_init_done_notifiers =
-    NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
-
 uint32_t xen_domid;
 enum xen_mode xen_mode = XEN_EMULATE;
 bool xen_domid_restrict;
@@ -2432,27 +2429,6 @@ static void qemu_unlink_pidfile(Notifier *n, void *data)
     }
 }
 
-bool machine_init_done;
-
-void qemu_add_machine_init_done_notifier(Notifier *notify)
-{
-    notifier_list_add(&machine_init_done_notifiers, notify);
-    if (machine_init_done) {
-        notify->notify(notify, NULL);
-    }
-}
-
-void qemu_remove_machine_init_done_notifier(Notifier *notify)
-{
-    notifier_remove(notify);
-}
-
-static void qemu_run_machine_init_done_notifiers(void)
-{
-    machine_init_done = true;
-    notifier_list_notify(&machine_init_done_notifiers, NULL);
-}
-
 static const QEMUOption *lookup_opt(int argc, char **argv,
                                     const char **poptarg, int *poptind)
 {
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 31/36] vl: extract softmmu/rtc.c
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (29 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 30/36] vl: extract machine done notifiers Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 12:43   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 32/36] vl: extract softmmu/runstate.c Paolo Bonzini
                   ` (6 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/sysemu/sysemu.h |   2 +
 softmmu/meson.build     |   1 +
 softmmu/rtc.c           | 190 ++++++++++++++++++++++++++++++++++++++++
 softmmu/vl.c            | 156 ---------------------------------
 4 files changed, 193 insertions(+), 156 deletions(-)
 create mode 100644 softmmu/rtc.c

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 1b62deaf2b..18cf586cd0 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -22,6 +22,8 @@ void qemu_run_machine_init_done_notifiers(void);
 void qemu_add_machine_init_done_notifier(Notifier *notify);
 void qemu_remove_machine_init_done_notifier(Notifier *notify);
 
+void configure_rtc(QemuOpts *opts);
+
 extern int autostart;
 
 typedef enum {
diff --git a/softmmu/meson.build b/softmmu/meson.build
index 7b52339e7a..d098d89653 100644
--- a/softmmu/meson.build
+++ b/softmmu/meson.build
@@ -6,6 +6,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
   'datadir.c',
   'physmem.c',
   'ioport.c',
+  'rtc.c',
   'memory.c',
   'memory_mapping.c',
   'qtest.c',
diff --git a/softmmu/rtc.c b/softmmu/rtc.c
new file mode 100644
index 0000000000..e1e15ef613
--- /dev/null
+++ b/softmmu/rtc.c
@@ -0,0 +1,190 @@
+/*
+ * RTC configuration and clock read
+ *
+ * Copyright (c) 2003-2020 QEMU contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
+#include "qemu/error-report.h"
+#include "qemu/option.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+#include "sysemu/replay.h"
+#include "sysemu/sysemu.h"
+
+static enum {
+    RTC_BASE_UTC,
+    RTC_BASE_LOCALTIME,
+    RTC_BASE_DATETIME,
+} rtc_base_type = RTC_BASE_UTC;
+static time_t rtc_ref_start_datetime;
+static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
+static int rtc_host_datetime_offset = -1; /* valid & used only with
+                                             RTC_BASE_DATETIME */
+QEMUClockType rtc_clock;
+/***********************************************************/
+/* RTC reference time/date access */
+static time_t qemu_ref_timedate(QEMUClockType clock)
+{
+    time_t value = qemu_clock_get_ms(clock) / 1000;
+    switch (clock) {
+    case QEMU_CLOCK_REALTIME:
+        value -= rtc_realtime_clock_offset;
+        /* fall through */
+    case QEMU_CLOCK_VIRTUAL:
+        value += rtc_ref_start_datetime;
+        break;
+    case QEMU_CLOCK_HOST:
+        if (rtc_base_type == RTC_BASE_DATETIME) {
+            value -= rtc_host_datetime_offset;
+        }
+        break;
+    default:
+        assert(0);
+    }
+    return value;
+}
+
+void qemu_get_timedate(struct tm *tm, int offset)
+{
+    time_t ti = qemu_ref_timedate(rtc_clock);
+
+    ti += offset;
+
+    switch (rtc_base_type) {
+    case RTC_BASE_DATETIME:
+    case RTC_BASE_UTC:
+        gmtime_r(&ti, tm);
+        break;
+    case RTC_BASE_LOCALTIME:
+        localtime_r(&ti, tm);
+        break;
+    }
+}
+
+int qemu_timedate_diff(struct tm *tm)
+{
+    time_t seconds;
+
+    switch (rtc_base_type) {
+    case RTC_BASE_DATETIME:
+    case RTC_BASE_UTC:
+        seconds = mktimegm(tm);
+        break;
+    case RTC_BASE_LOCALTIME:
+    {
+        struct tm tmp = *tm;
+        tmp.tm_isdst = -1; /* use timezone to figure it out */
+        seconds = mktime(&tmp);
+        break;
+    }
+    default:
+        abort();
+    }
+
+    return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST);
+}
+
+static void configure_rtc_base_datetime(const char *startdate)
+{
+    time_t rtc_start_datetime;
+    struct tm tm;
+
+    if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon,
+               &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
+        /* OK */
+    } else if (sscanf(startdate, "%d-%d-%d",
+                      &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) {
+        tm.tm_hour = 0;
+        tm.tm_min = 0;
+        tm.tm_sec = 0;
+    } else {
+        goto date_fail;
+    }
+    tm.tm_year -= 1900;
+    tm.tm_mon--;
+    rtc_start_datetime = mktimegm(&tm);
+    if (rtc_start_datetime == -1) {
+    date_fail:
+        error_report("invalid datetime format");
+        error_printf("valid formats: "
+                     "'2006-06-17T16:01:21' or '2006-06-17'\n");
+        exit(1);
+    }
+    rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime;
+    rtc_ref_start_datetime = rtc_start_datetime;
+}
+
+void configure_rtc(QemuOpts *opts)
+{
+    const char *value;
+
+    /* Set defaults */
+    rtc_clock = QEMU_CLOCK_HOST;
+    rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
+    rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
+
+    value = qemu_opt_get(opts, "base");
+    if (value) {
+        if (!strcmp(value, "utc")) {
+            rtc_base_type = RTC_BASE_UTC;
+        } else if (!strcmp(value, "localtime")) {
+            Error *blocker = NULL;
+            rtc_base_type = RTC_BASE_LOCALTIME;
+            error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
+                      "-rtc base=localtime");
+            replay_add_blocker(blocker);
+        } else {
+            rtc_base_type = RTC_BASE_DATETIME;
+            configure_rtc_base_datetime(value);
+        }
+    }
+    value = qemu_opt_get(opts, "clock");
+    if (value) {
+        if (!strcmp(value, "host")) {
+            rtc_clock = QEMU_CLOCK_HOST;
+        } else if (!strcmp(value, "rt")) {
+            rtc_clock = QEMU_CLOCK_REALTIME;
+        } else if (!strcmp(value, "vm")) {
+            rtc_clock = QEMU_CLOCK_VIRTUAL;
+        } else {
+            error_report("invalid option value '%s'", value);
+            exit(1);
+        }
+    }
+    value = qemu_opt_get(opts, "driftfix");
+    if (value) {
+        if (!strcmp(value, "slew")) {
+            object_register_sugar_prop("mc146818rtc",
+                                       "lost_tick_policy",
+                                       "slew");
+        } else if (!strcmp(value, "none")) {
+            /* discard is default */
+        } else {
+            error_report("invalid option value '%s'", value);
+            exit(1);
+        }
+    }
+}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 7e13bb4a59..c9bb205c42 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -152,16 +152,6 @@ bool enable_cpu_pm = false;
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int autostart = 1;
-static enum {
-    RTC_BASE_UTC,
-    RTC_BASE_LOCALTIME,
-    RTC_BASE_DATETIME,
-} rtc_base_type = RTC_BASE_UTC;
-static time_t rtc_ref_start_datetime;
-static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
-static int rtc_host_datetime_offset = -1; /* valid & used only with
-                                             RTC_BASE_DATETIME */
-QEMUClockType rtc_clock;
 int vga_interface_type = VGA_NONE;
 static const char *vga_model = NULL;
 static DisplayOptions dpy;
@@ -766,152 +756,6 @@ void qemu_system_vmstop_request(RunState state)
     qemu_mutex_unlock(&vmstop_lock);
     qemu_notify_event();
 }
-
-/***********************************************************/
-/* RTC reference time/date access */
-static time_t qemu_ref_timedate(QEMUClockType clock)
-{
-    time_t value = qemu_clock_get_ms(clock) / 1000;
-    switch (clock) {
-    case QEMU_CLOCK_REALTIME:
-        value -= rtc_realtime_clock_offset;
-        /* fall through */
-    case QEMU_CLOCK_VIRTUAL:
-        value += rtc_ref_start_datetime;
-        break;
-    case QEMU_CLOCK_HOST:
-        if (rtc_base_type == RTC_BASE_DATETIME) {
-            value -= rtc_host_datetime_offset;
-        }
-        break;
-    default:
-        assert(0);
-    }
-    return value;
-}
-
-void qemu_get_timedate(struct tm *tm, int offset)
-{
-    time_t ti = qemu_ref_timedate(rtc_clock);
-
-    ti += offset;
-
-    switch (rtc_base_type) {
-    case RTC_BASE_DATETIME:
-    case RTC_BASE_UTC:
-        gmtime_r(&ti, tm);
-        break;
-    case RTC_BASE_LOCALTIME:
-        localtime_r(&ti, tm);
-        break;
-    }
-}
-
-int qemu_timedate_diff(struct tm *tm)
-{
-    time_t seconds;
-
-    switch (rtc_base_type) {
-    case RTC_BASE_DATETIME:
-    case RTC_BASE_UTC:
-        seconds = mktimegm(tm);
-        break;
-    case RTC_BASE_LOCALTIME:
-    {
-        struct tm tmp = *tm;
-        tmp.tm_isdst = -1; /* use timezone to figure it out */
-        seconds = mktime(&tmp);
-        break;
-    }
-    default:
-        abort();
-    }
-
-    return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST);
-}
-
-static void configure_rtc_base_datetime(const char *startdate)
-{
-    time_t rtc_start_datetime;
-    struct tm tm;
-
-    if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon,
-               &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
-        /* OK */
-    } else if (sscanf(startdate, "%d-%d-%d",
-                      &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) {
-        tm.tm_hour = 0;
-        tm.tm_min = 0;
-        tm.tm_sec = 0;
-    } else {
-        goto date_fail;
-    }
-    tm.tm_year -= 1900;
-    tm.tm_mon--;
-    rtc_start_datetime = mktimegm(&tm);
-    if (rtc_start_datetime == -1) {
-    date_fail:
-        error_report("invalid datetime format");
-        error_printf("valid formats: "
-                     "'2006-06-17T16:01:21' or '2006-06-17'\n");
-        exit(1);
-    }
-    rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime;
-    rtc_ref_start_datetime = rtc_start_datetime;
-}
-
-static void configure_rtc(QemuOpts *opts)
-{
-    const char *value;
-
-    /* Set defaults */
-    rtc_clock = QEMU_CLOCK_HOST;
-    rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
-    rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
-
-    value = qemu_opt_get(opts, "base");
-    if (value) {
-        if (!strcmp(value, "utc")) {
-            rtc_base_type = RTC_BASE_UTC;
-        } else if (!strcmp(value, "localtime")) {
-            Error *blocker = NULL;
-            rtc_base_type = RTC_BASE_LOCALTIME;
-            error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
-                      "-rtc base=localtime");
-            replay_add_blocker(blocker);
-        } else {
-            rtc_base_type = RTC_BASE_DATETIME;
-            configure_rtc_base_datetime(value);
-        }
-    }
-    value = qemu_opt_get(opts, "clock");
-    if (value) {
-        if (!strcmp(value, "host")) {
-            rtc_clock = QEMU_CLOCK_HOST;
-        } else if (!strcmp(value, "rt")) {
-            rtc_clock = QEMU_CLOCK_REALTIME;
-        } else if (!strcmp(value, "vm")) {
-            rtc_clock = QEMU_CLOCK_VIRTUAL;
-        } else {
-            error_report("invalid option value '%s'", value);
-            exit(1);
-        }
-    }
-    value = qemu_opt_get(opts, "driftfix");
-    if (value) {
-        if (!strcmp(value, "slew")) {
-            object_register_sugar_prop("mc146818rtc",
-                                       "lost_tick_policy",
-                                       "slew");
-        } else if (!strcmp(value, "none")) {
-            /* discard is default */
-        } else {
-            error_report("invalid option value '%s'", value);
-            exit(1);
-        }
-    }
-}
-
 static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
 {
     const char *proc_name;
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 32/36] vl: extract softmmu/runstate.c
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (30 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 31/36] vl: extract softmmu/rtc.c Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 12:59   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 33/36] vl: extract softmmu/globals.c Paolo Bonzini
                   ` (5 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/sysemu/sysemu.h |   3 +
 softmmu/meson.build     |   1 +
 softmmu/runstate.c      | 800 ++++++++++++++++++++++++++++++++++++++++
 softmmu/vl.c            | 752 +------------------------------------
 4 files changed, 805 insertions(+), 751 deletions(-)
 create mode 100644 softmmu/runstate.c

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 18cf586cd0..3dac3229ec 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -24,6 +24,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
 
 void configure_rtc(QemuOpts *opts);
 
+void qemu_init_subsystems(void);
+
 extern int autostart;
 
 typedef enum {
@@ -44,6 +46,7 @@ extern int alt_grab;
 extern int ctrl_grab;
 extern int graphic_rotate;
 extern int no_shutdown;
+extern int no_reboot;
 extern int old_param;
 extern int boot_menu;
 extern bool boot_strict;
diff --git a/softmmu/meson.build b/softmmu/meson.build
index d098d89653..2a73ebc223 100644
--- a/softmmu/meson.build
+++ b/softmmu/meson.build
@@ -7,6 +7,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
   'physmem.c',
   'ioport.c',
   'rtc.c',
+  'runstate.c',
   'memory.c',
   'memory_mapping.c',
   'qtest.c',
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
new file mode 100644
index 0000000000..892f2f679f
--- /dev/null
+++ b/softmmu/runstate.c
@@ -0,0 +1,800 @@
+/*
+ * QEMU main system emulation loop
+ *
+ * Copyright (c) 2003-2020 QEMU contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "audio/audio.h"
+#include "block/block.h"
+#include "chardev/char.h"
+#include "crypto/cipher.h"
+#include "crypto/init.h"
+#include "exec/cpu-common.h"
+#include "exec/exec-all.h"
+#include "exec/gdbstub.h"
+#include "hw/boards.h"
+#include "migration/misc.h"
+#include "migration/postcopy-ram.h"
+#include "monitor/monitor.h"
+#include "net/net.h"
+#include "net/vhost_net.h"
+#include "qapi/error.h"
+#include "qapi/qapi-commands-run-state.h"
+#include "qapi/qapi-events-run-state.h"
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "qemu/job.h"
+#include "qemu/module.h"
+#include "qemu/plugin.h"
+#include "qemu/sockets.h"
+#include "qemu/thread.h"
+#include "qom/object.h"
+#include "qom/object_interfaces.h"
+#include "sysemu/cpus.h"
+#include "sysemu/qtest.h"
+#include "sysemu/replay.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/tpm.h"
+#include "trace.h"
+
+static NotifierList exit_notifiers =
+    NOTIFIER_LIST_INITIALIZER(exit_notifiers);
+
+static RunState current_run_state = RUN_STATE_PRELAUNCH;
+
+/* We use RUN_STATE__MAX but any invalid value will do */
+static RunState vmstop_requested = RUN_STATE__MAX;
+static QemuMutex vmstop_lock;
+
+typedef struct {
+    RunState from;
+    RunState to;
+} RunStateTransition;
+
+static const RunStateTransition runstate_transitions_def[] = {
+    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
+
+    { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
+    { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
+
+    { RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
+    { RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
+    { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
+    { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
+    { RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
+    { RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
+    { RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
+    { RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
+    { RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
+    { RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
+    { RUN_STATE_INMIGRATE, RUN_STATE_COLO },
+
+    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
+    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
+
+    { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
+    { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
+
+    { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
+    { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
+    { RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
+    { RUN_STATE_PAUSED, RUN_STATE_COLO},
+
+    { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
+    { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
+
+    { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
+    { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
+
+    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
+    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
+    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
+    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
+    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
+
+    { RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
+    { RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
+
+    { RUN_STATE_COLO, RUN_STATE_RUNNING },
+
+    { RUN_STATE_RUNNING, RUN_STATE_DEBUG },
+    { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
+    { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
+    { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
+    { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
+    { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
+    { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
+    { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
+    { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
+    { RUN_STATE_RUNNING, RUN_STATE_COLO},
+
+    { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
+
+    { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
+    { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
+    { RUN_STATE_SHUTDOWN, RUN_STATE_COLO },
+
+    { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
+    { RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
+    { RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
+    { RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
+    { RUN_STATE_SUSPENDED, RUN_STATE_COLO},
+
+    { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
+    { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
+    { RUN_STATE_WATCHDOG, RUN_STATE_COLO},
+
+    { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
+    { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
+    { RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
+
+    { RUN_STATE__MAX, RUN_STATE__MAX },
+};
+
+static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
+
+bool runstate_check(RunState state)
+{
+    return current_run_state == state;
+}
+
+bool runstate_store(char *str, size_t size)
+{
+    const char *state = RunState_str(current_run_state);
+    size_t len = strlen(state) + 1;
+
+    if (len > size) {
+        return false;
+    }
+    memcpy(str, state, len);
+    return true;
+}
+
+static void runstate_init(void)
+{
+    const RunStateTransition *p;
+
+    memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
+    for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
+        runstate_valid_transitions[p->from][p->to] = true;
+    }
+
+    qemu_mutex_init(&vmstop_lock);
+}
+
+/* This function will abort() on invalid state transitions */
+void runstate_set(RunState new_state)
+{
+    assert(new_state < RUN_STATE__MAX);
+
+    trace_runstate_set(current_run_state, RunState_str(current_run_state),
+                       new_state, RunState_str(new_state));
+
+    if (current_run_state == new_state) {
+        return;
+    }
+
+    if (!runstate_valid_transitions[current_run_state][new_state]) {
+        error_report("invalid runstate transition: '%s' -> '%s'",
+                     RunState_str(current_run_state),
+                     RunState_str(new_state));
+        abort();
+    }
+
+    current_run_state = new_state;
+}
+
+int runstate_is_running(void)
+{
+    return runstate_check(RUN_STATE_RUNNING);
+}
+
+bool runstate_needs_reset(void)
+{
+    return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
+        runstate_check(RUN_STATE_SHUTDOWN);
+}
+
+StatusInfo *qmp_query_status(Error **errp)
+{
+    StatusInfo *info = g_malloc0(sizeof(*info));
+
+    info->running = runstate_is_running();
+    info->singlestep = singlestep;
+    info->status = current_run_state;
+
+    return info;
+}
+
+bool qemu_vmstop_requested(RunState *r)
+{
+    qemu_mutex_lock(&vmstop_lock);
+    *r = vmstop_requested;
+    vmstop_requested = RUN_STATE__MAX;
+    qemu_mutex_unlock(&vmstop_lock);
+    return *r < RUN_STATE__MAX;
+}
+
+void qemu_system_vmstop_request_prepare(void)
+{
+    qemu_mutex_lock(&vmstop_lock);
+}
+
+void qemu_system_vmstop_request(RunState state)
+{
+    vmstop_requested = state;
+    qemu_mutex_unlock(&vmstop_lock);
+    qemu_notify_event();
+}
+struct VMChangeStateEntry {
+    VMChangeStateHandler *cb;
+    void *opaque;
+    QTAILQ_ENTRY(VMChangeStateEntry) entries;
+    int priority;
+};
+
+static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
+    QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
+
+/**
+ * qemu_add_vm_change_state_handler_prio:
+ * @cb: the callback to invoke
+ * @opaque: user data passed to the callback
+ * @priority: low priorities execute first when the vm runs and the reverse is
+ *            true when the vm stops
+ *
+ * Register a callback function that is invoked when the vm starts or stops
+ * running.
+ *
+ * Returns: an entry to be freed using qemu_del_vm_change_state_handler()
+ */
+VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
+        VMChangeStateHandler *cb, void *opaque, int priority)
+{
+    VMChangeStateEntry *e;
+    VMChangeStateEntry *other;
+
+    e = g_malloc0(sizeof(*e));
+    e->cb = cb;
+    e->opaque = opaque;
+    e->priority = priority;
+
+    /* Keep list sorted in ascending priority order */
+    QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
+        if (priority < other->priority) {
+            QTAILQ_INSERT_BEFORE(other, e, entries);
+            return e;
+        }
+    }
+
+    QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
+    return e;
+}
+
+VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
+                                                     void *opaque)
+{
+    return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
+}
+
+void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
+{
+    QTAILQ_REMOVE(&vm_change_state_head, e, entries);
+    g_free(e);
+}
+
+void vm_state_notify(int running, RunState state)
+{
+    VMChangeStateEntry *e, *next;
+
+    trace_vm_state_notify(running, state, RunState_str(state));
+
+    if (running) {
+        QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
+            e->cb(e->opaque, running, state);
+        }
+    } else {
+        QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next) {
+            e->cb(e->opaque, running, state);
+        }
+    }
+}
+
+static ShutdownCause reset_requested;
+static ShutdownCause shutdown_requested;
+static int shutdown_signal;
+static pid_t shutdown_pid;
+static int powerdown_requested;
+static int debug_requested;
+static int suspend_requested;
+static WakeupReason wakeup_reason;
+static NotifierList powerdown_notifiers =
+    NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
+static NotifierList suspend_notifiers =
+    NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
+static NotifierList wakeup_notifiers =
+    NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
+static NotifierList shutdown_notifiers =
+    NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
+static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
+
+ShutdownCause qemu_shutdown_requested_get(void)
+{
+    return shutdown_requested;
+}
+
+ShutdownCause qemu_reset_requested_get(void)
+{
+    return reset_requested;
+}
+
+static int qemu_shutdown_requested(void)
+{
+    return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
+}
+
+static void qemu_kill_report(void)
+{
+    if (!qtest_driver() && shutdown_signal) {
+        if (shutdown_pid == 0) {
+            /* This happens for eg ^C at the terminal, so it's worth
+             * avoiding printing an odd message in that case.
+             */
+            error_report("terminating on signal %d", shutdown_signal);
+        } else {
+            char *shutdown_cmd = qemu_get_pid_name(shutdown_pid);
+
+            error_report("terminating on signal %d from pid " FMT_pid " (%s)",
+                         shutdown_signal, shutdown_pid,
+                         shutdown_cmd ? shutdown_cmd : "<unknown process>");
+            g_free(shutdown_cmd);
+        }
+        shutdown_signal = 0;
+    }
+}
+
+static ShutdownCause qemu_reset_requested(void)
+{
+    ShutdownCause r = reset_requested;
+
+    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
+        reset_requested = SHUTDOWN_CAUSE_NONE;
+        return r;
+    }
+    return SHUTDOWN_CAUSE_NONE;
+}
+
+static int qemu_suspend_requested(void)
+{
+    int r = suspend_requested;
+    if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
+        suspend_requested = 0;
+        return r;
+    }
+    return false;
+}
+
+static WakeupReason qemu_wakeup_requested(void)
+{
+    return wakeup_reason;
+}
+
+static int qemu_powerdown_requested(void)
+{
+    int r = powerdown_requested;
+    powerdown_requested = 0;
+    return r;
+}
+
+static int qemu_debug_requested(void)
+{
+    int r = debug_requested;
+    debug_requested = 0;
+    return r;
+}
+
+/*
+ * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
+ */
+void qemu_system_reset(ShutdownCause reason)
+{
+    MachineClass *mc;
+
+    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
+
+    cpu_synchronize_all_states();
+
+    if (mc && mc->reset) {
+        mc->reset(current_machine);
+    } else {
+        qemu_devices_reset();
+    }
+    if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
+        qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
+    }
+    cpu_synchronize_all_post_reset();
+}
+
+/*
+ * Wake the VM after suspend.
+ */
+static void qemu_system_wakeup(void)
+{
+    MachineClass *mc;
+
+    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
+
+    if (mc && mc->wakeup) {
+        mc->wakeup(current_machine);
+    }
+}
+
+void qemu_system_guest_panicked(GuestPanicInformation *info)
+{
+    qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
+
+    if (current_cpu) {
+        current_cpu->crash_occurred = true;
+    }
+    qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
+                                   !!info, info);
+    vm_stop(RUN_STATE_GUEST_PANICKED);
+    if (!no_shutdown) {
+        qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
+                                       !!info, info);
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
+    }
+
+    if (info) {
+        if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
+            qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
+                          " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
+                          info->u.hyper_v.arg1,
+                          info->u.hyper_v.arg2,
+                          info->u.hyper_v.arg3,
+                          info->u.hyper_v.arg4,
+                          info->u.hyper_v.arg5);
+        } else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
+            qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
+                          "PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
+                          info->u.s390.core,
+                          S390CrashReason_str(info->u.s390.reason),
+                          info->u.s390.psw_mask,
+                          info->u.s390.psw_addr);
+        }
+        qapi_free_GuestPanicInformation(info);
+    }
+}
+
+void qemu_system_guest_crashloaded(GuestPanicInformation *info)
+{
+    qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded");
+
+    qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN,
+                                   !!info, info);
+
+    if (info) {
+        qapi_free_GuestPanicInformation(info);
+    }
+}
+
+void qemu_system_reset_request(ShutdownCause reason)
+{
+    if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
+        shutdown_requested = reason;
+    } else {
+        reset_requested = reason;
+    }
+    cpu_stop_current();
+    qemu_notify_event();
+}
+
+static void qemu_system_suspend(void)
+{
+    pause_all_vcpus();
+    notifier_list_notify(&suspend_notifiers, NULL);
+    runstate_set(RUN_STATE_SUSPENDED);
+    qapi_event_send_suspend();
+}
+
+void qemu_system_suspend_request(void)
+{
+    if (runstate_check(RUN_STATE_SUSPENDED)) {
+        return;
+    }
+    suspend_requested = 1;
+    cpu_stop_current();
+    qemu_notify_event();
+}
+
+void qemu_register_suspend_notifier(Notifier *notifier)
+{
+    notifier_list_add(&suspend_notifiers, notifier);
+}
+
+void qemu_system_wakeup_request(WakeupReason reason, Error **errp)
+{
+    trace_system_wakeup_request(reason);
+
+    if (!runstate_check(RUN_STATE_SUSPENDED)) {
+        error_setg(errp,
+                   "Unable to wake up: guest is not in suspended state");
+        return;
+    }
+    if (!(wakeup_reason_mask & (1 << reason))) {
+        return;
+    }
+    runstate_set(RUN_STATE_RUNNING);
+    wakeup_reason = reason;
+    qemu_notify_event();
+}
+
+void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
+{
+    if (enabled) {
+        wakeup_reason_mask |= (1 << reason);
+    } else {
+        wakeup_reason_mask &= ~(1 << reason);
+    }
+}
+
+void qemu_register_wakeup_notifier(Notifier *notifier)
+{
+    notifier_list_add(&wakeup_notifiers, notifier);
+}
+
+static bool wakeup_suspend_enabled;
+
+void qemu_register_wakeup_support(void)
+{
+    wakeup_suspend_enabled = true;
+}
+
+bool qemu_wakeup_suspend_enabled(void)
+{
+    return wakeup_suspend_enabled;
+}
+
+void qemu_system_killed(int signal, pid_t pid)
+{
+    shutdown_signal = signal;
+    shutdown_pid = pid;
+    no_shutdown = 0;
+
+    /* Cannot call qemu_system_shutdown_request directly because
+     * we are in a signal handler.
+     */
+    shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
+    qemu_notify_event();
+}
+
+void qemu_system_shutdown_request(ShutdownCause reason)
+{
+    trace_qemu_system_shutdown_request(reason);
+    replay_shutdown_request(reason);
+    shutdown_requested = reason;
+    qemu_notify_event();
+}
+
+static void qemu_system_powerdown(void)
+{
+    qapi_event_send_powerdown();
+    notifier_list_notify(&powerdown_notifiers, NULL);
+}
+
+static void qemu_system_shutdown(ShutdownCause cause)
+{
+    qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause);
+    notifier_list_notify(&shutdown_notifiers, &cause);
+}
+
+void qemu_system_powerdown_request(void)
+{
+    trace_qemu_system_powerdown_request();
+    powerdown_requested = 1;
+    qemu_notify_event();
+}
+
+void qemu_register_powerdown_notifier(Notifier *notifier)
+{
+    notifier_list_add(&powerdown_notifiers, notifier);
+}
+
+void qemu_register_shutdown_notifier(Notifier *notifier)
+{
+    notifier_list_add(&shutdown_notifiers, notifier);
+}
+
+void qemu_system_debug_request(void)
+{
+    debug_requested = 1;
+    qemu_notify_event();
+}
+
+static bool main_loop_should_exit(void)
+{
+    RunState r;
+    ShutdownCause request;
+
+    if (qemu_debug_requested()) {
+        vm_stop(RUN_STATE_DEBUG);
+    }
+    if (qemu_suspend_requested()) {
+        qemu_system_suspend();
+    }
+    request = qemu_shutdown_requested();
+    if (request) {
+        qemu_kill_report();
+        qemu_system_shutdown(request);
+        if (no_shutdown) {
+            vm_stop(RUN_STATE_SHUTDOWN);
+        } else {
+            return true;
+        }
+    }
+    request = qemu_reset_requested();
+    if (request) {
+        pause_all_vcpus();
+        qemu_system_reset(request);
+        resume_all_vcpus();
+        /*
+         * runstate can change in pause_all_vcpus()
+         * as iothread mutex is unlocked
+         */
+        if (!runstate_check(RUN_STATE_RUNNING) &&
+                !runstate_check(RUN_STATE_INMIGRATE) &&
+                !runstate_check(RUN_STATE_FINISH_MIGRATE)) {
+            runstate_set(RUN_STATE_PRELAUNCH);
+        }
+    }
+    if (qemu_wakeup_requested()) {
+        pause_all_vcpus();
+        qemu_system_wakeup();
+        notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
+        wakeup_reason = QEMU_WAKEUP_REASON_NONE;
+        resume_all_vcpus();
+        qapi_event_send_wakeup();
+    }
+    if (qemu_powerdown_requested()) {
+        qemu_system_powerdown();
+    }
+    if (qemu_vmstop_requested(&r)) {
+        vm_stop(r);
+    }
+    return false;
+}
+
+void qemu_main_loop(void)
+{
+#ifdef CONFIG_PROFILER
+    int64_t ti;
+#endif
+    while (!main_loop_should_exit()) {
+#ifdef CONFIG_PROFILER
+        ti = profile_getclock();
+#endif
+        main_loop_wait(false);
+#ifdef CONFIG_PROFILER
+        dev_time += profile_getclock() - ti;
+#endif
+    }
+}
+
+void qemu_add_exit_notifier(Notifier *notify)
+{
+    notifier_list_add(&exit_notifiers, notify);
+}
+
+void qemu_remove_exit_notifier(Notifier *notify)
+{
+    notifier_remove(notify);
+}
+
+static void qemu_run_exit_notifiers(void)
+{
+    notifier_list_notify(&exit_notifiers, NULL);
+}
+
+void qemu_init_subsystems(void)
+{
+    Error *err;
+
+    os_set_line_buffering();
+
+    module_call_init(MODULE_INIT_TRACE);
+
+    qemu_init_cpu_list();
+    qemu_init_cpu_loop();
+    qemu_mutex_lock_iothread();
+
+    atexit(qemu_run_exit_notifiers);
+
+    module_call_init(MODULE_INIT_QOM);
+    module_call_init(MODULE_INIT_MIGRATION);
+
+    runstate_init();
+    precopy_infrastructure_init();
+    postcopy_infrastructure_init();
+    monitor_init_globals();
+
+    if (qcrypto_init(&err) < 0) {
+        error_reportf_err(err, "cannot initialize crypto: ");
+        exit(1);
+    }
+
+    os_setup_early_signal_handling();
+
+    bdrv_init_with_whitelist();
+    socket_init();
+}
+
+
+void qemu_cleanup(void)
+{
+    gdbserver_cleanup();
+
+    /*
+     * cleaning up the migration object cancels any existing migration
+     * try to do this early so that it also stops using devices.
+     */
+    migration_shutdown();
+
+    /*
+     * We must cancel all block jobs while the block layer is drained,
+     * or cancelling will be affected by throttling and thus may block
+     * for an extended period of time.
+     * vm_shutdown() will bdrv_drain_all(), so we may as well include
+     * it in the drained section.
+     * We do not need to end this section, because we do not want any
+     * requests happening from here on anyway.
+     */
+    bdrv_drain_all_begin();
+
+    /* No more vcpu or device emulation activity beyond this point */
+    vm_shutdown();
+    replay_finish();
+
+    job_cancel_sync_all();
+    bdrv_close_all();
+
+    /* vhost-user must be cleaned up before chardevs.  */
+    tpm_cleanup();
+    net_cleanup();
+    audio_cleanup();
+    monitor_cleanup();
+    qemu_chr_cleanup();
+    user_creatable_cleanup();
+    /* TODO: unref root container, check all devices are ok */
+}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index c9bb205c42..914b86ee86 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -112,7 +112,6 @@
 #include "qapi/qapi-commands-block-core.h"
 #include "qapi/qapi-commands-migration.h"
 #include "qapi/qapi-commands-misc.h"
-#include "qapi/qapi-commands-run-state.h"
 #include "qapi/qapi-commands-ui.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/iothread.h"
@@ -164,7 +163,7 @@ Chardev *parallel_hds[MAX_PARALLEL_PORTS];
 int win2k_install_hack = 0;
 int singlestep = 0;
 int fd_bootchk = 1;
-static int no_reboot;
+int no_reboot;
 int no_shutdown = 0;
 int graphic_rotate = 0;
 static const char *watchdog;
@@ -191,9 +190,6 @@ static const char *qtest_log;
 QemuUUID qemu_uuid;
 bool qemu_uuid_set;
 
-static NotifierList exit_notifiers =
-    NOTIFIER_LIST_INITIALIZER(exit_notifiers);
-
 uint32_t xen_domid;
 enum xen_mode xen_mode = XEN_EMULATE;
 bool xen_domid_restrict;
@@ -535,12 +531,6 @@ const char *qemu_get_vm_name(void)
     return qemu_name;
 }
 
-static void res_free(void)
-{
-    g_free(boot_splash_filedata);
-    boot_splash_filedata = NULL;
-}
-
 static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp)
 {
     const char *driver = qemu_opt_get(opts, "driver");
@@ -556,206 +546,6 @@ static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp)
     return 0;
 }
 
-/***********************************************************/
-/* QEMU state */
-
-static RunState current_run_state = RUN_STATE_PRELAUNCH;
-
-/* We use RUN_STATE__MAX but any invalid value will do */
-static RunState vmstop_requested = RUN_STATE__MAX;
-static QemuMutex vmstop_lock;
-
-typedef struct {
-    RunState from;
-    RunState to;
-} RunStateTransition;
-
-static const RunStateTransition runstate_transitions_def[] = {
-    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
-
-    { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
-    { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
-
-    { RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
-    { RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
-    { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
-    { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
-    { RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
-    { RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
-    { RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
-    { RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
-    { RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
-    { RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
-    { RUN_STATE_INMIGRATE, RUN_STATE_COLO },
-
-    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
-    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
-
-    { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
-    { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
-
-    { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
-    { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
-    { RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
-    { RUN_STATE_PAUSED, RUN_STATE_COLO},
-
-    { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
-    { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
-
-    { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
-    { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
-
-    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
-    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
-    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
-    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
-    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
-
-    { RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
-    { RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
-
-    { RUN_STATE_COLO, RUN_STATE_RUNNING },
-
-    { RUN_STATE_RUNNING, RUN_STATE_DEBUG },
-    { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
-    { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
-    { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
-    { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
-    { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
-    { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
-    { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
-    { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
-    { RUN_STATE_RUNNING, RUN_STATE_COLO},
-
-    { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
-
-    { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
-    { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
-    { RUN_STATE_SHUTDOWN, RUN_STATE_COLO },
-
-    { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
-    { RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
-    { RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
-    { RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
-    { RUN_STATE_SUSPENDED, RUN_STATE_COLO},
-
-    { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
-    { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
-    { RUN_STATE_WATCHDOG, RUN_STATE_COLO},
-
-    { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
-    { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
-    { RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
-
-    { RUN_STATE__MAX, RUN_STATE__MAX },
-};
-
-static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
-
-bool runstate_check(RunState state)
-{
-    return current_run_state == state;
-}
-
-bool runstate_store(char *str, size_t size)
-{
-    const char *state = RunState_str(current_run_state);
-    size_t len = strlen(state) + 1;
-
-    if (len > size) {
-        return false;
-    }
-    memcpy(str, state, len);
-    return true;
-}
-
-static void runstate_init(void)
-{
-    const RunStateTransition *p;
-
-    memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
-    for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
-        runstate_valid_transitions[p->from][p->to] = true;
-    }
-
-    qemu_mutex_init(&vmstop_lock);
-}
-
-/* This function will abort() on invalid state transitions */
-void runstate_set(RunState new_state)
-{
-    assert(new_state < RUN_STATE__MAX);
-
-    trace_runstate_set(current_run_state, RunState_str(current_run_state),
-                       new_state, RunState_str(new_state));
-
-    if (current_run_state == new_state) {
-        return;
-    }
-
-    if (!runstate_valid_transitions[current_run_state][new_state]) {
-        error_report("invalid runstate transition: '%s' -> '%s'",
-                     RunState_str(current_run_state),
-                     RunState_str(new_state));
-        abort();
-    }
-
-    current_run_state = new_state;
-}
-
-int runstate_is_running(void)
-{
-    return runstate_check(RUN_STATE_RUNNING);
-}
-
-bool runstate_needs_reset(void)
-{
-    return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
-        runstate_check(RUN_STATE_SHUTDOWN);
-}
-
-StatusInfo *qmp_query_status(Error **errp)
-{
-    StatusInfo *info = g_malloc0(sizeof(*info));
-
-    info->running = runstate_is_running();
-    info->singlestep = singlestep;
-    info->status = current_run_state;
-
-    return info;
-}
-
-bool qemu_vmstop_requested(RunState *r)
-{
-    qemu_mutex_lock(&vmstop_lock);
-    *r = vmstop_requested;
-    vmstop_requested = RUN_STATE__MAX;
-    qemu_mutex_unlock(&vmstop_lock);
-    return *r < RUN_STATE__MAX;
-}
-
-void qemu_system_vmstop_request_prepare(void)
-{
-    qemu_mutex_lock(&vmstop_lock);
-}
-
-void qemu_system_vmstop_request(RunState state)
-{
-    vmstop_requested = state;
-    qemu_mutex_unlock(&vmstop_lock);
-    qemu_notify_event();
-}
 static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
 {
     const char *proc_name;
@@ -1072,458 +862,6 @@ static int machine_help_func(QemuOpts *opts, MachineState *machine)
     return 1;
 }
 
-struct VMChangeStateEntry {
-    VMChangeStateHandler *cb;
-    void *opaque;
-    QTAILQ_ENTRY(VMChangeStateEntry) entries;
-    int priority;
-};
-
-static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
-    QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
-
-/**
- * qemu_add_vm_change_state_handler_prio:
- * @cb: the callback to invoke
- * @opaque: user data passed to the callback
- * @priority: low priorities execute first when the vm runs and the reverse is
- *            true when the vm stops
- *
- * Register a callback function that is invoked when the vm starts or stops
- * running.
- *
- * Returns: an entry to be freed using qemu_del_vm_change_state_handler()
- */
-VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
-        VMChangeStateHandler *cb, void *opaque, int priority)
-{
-    VMChangeStateEntry *e;
-    VMChangeStateEntry *other;
-
-    e = g_malloc0(sizeof(*e));
-    e->cb = cb;
-    e->opaque = opaque;
-    e->priority = priority;
-
-    /* Keep list sorted in ascending priority order */
-    QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
-        if (priority < other->priority) {
-            QTAILQ_INSERT_BEFORE(other, e, entries);
-            return e;
-        }
-    }
-
-    QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
-    return e;
-}
-
-VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
-                                                     void *opaque)
-{
-    return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
-}
-
-void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
-{
-    QTAILQ_REMOVE(&vm_change_state_head, e, entries);
-    g_free(e);
-}
-
-void vm_state_notify(int running, RunState state)
-{
-    VMChangeStateEntry *e, *next;
-
-    trace_vm_state_notify(running, state, RunState_str(state));
-
-    if (running) {
-        QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
-            e->cb(e->opaque, running, state);
-        }
-    } else {
-        QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next) {
-            e->cb(e->opaque, running, state);
-        }
-    }
-}
-
-static ShutdownCause reset_requested;
-static ShutdownCause shutdown_requested;
-static int shutdown_signal;
-static pid_t shutdown_pid;
-static int powerdown_requested;
-static int debug_requested;
-static int suspend_requested;
-static WakeupReason wakeup_reason;
-static NotifierList powerdown_notifiers =
-    NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
-static NotifierList suspend_notifiers =
-    NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
-static NotifierList wakeup_notifiers =
-    NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
-static NotifierList shutdown_notifiers =
-    NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
-static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
-
-ShutdownCause qemu_shutdown_requested_get(void)
-{
-    return shutdown_requested;
-}
-
-ShutdownCause qemu_reset_requested_get(void)
-{
-    return reset_requested;
-}
-
-static int qemu_shutdown_requested(void)
-{
-    return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
-}
-
-static void qemu_kill_report(void)
-{
-    if (!qtest_driver() && shutdown_signal) {
-        if (shutdown_pid == 0) {
-            /* This happens for eg ^C at the terminal, so it's worth
-             * avoiding printing an odd message in that case.
-             */
-            error_report("terminating on signal %d", shutdown_signal);
-        } else {
-            char *shutdown_cmd = qemu_get_pid_name(shutdown_pid);
-
-            error_report("terminating on signal %d from pid " FMT_pid " (%s)",
-                         shutdown_signal, shutdown_pid,
-                         shutdown_cmd ? shutdown_cmd : "<unknown process>");
-            g_free(shutdown_cmd);
-        }
-        shutdown_signal = 0;
-    }
-}
-
-static ShutdownCause qemu_reset_requested(void)
-{
-    ShutdownCause r = reset_requested;
-
-    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
-        reset_requested = SHUTDOWN_CAUSE_NONE;
-        return r;
-    }
-    return SHUTDOWN_CAUSE_NONE;
-}
-
-static int qemu_suspend_requested(void)
-{
-    int r = suspend_requested;
-    if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
-        suspend_requested = 0;
-        return r;
-    }
-    return false;
-}
-
-static WakeupReason qemu_wakeup_requested(void)
-{
-    return wakeup_reason;
-}
-
-static int qemu_powerdown_requested(void)
-{
-    int r = powerdown_requested;
-    powerdown_requested = 0;
-    return r;
-}
-
-static int qemu_debug_requested(void)
-{
-    int r = debug_requested;
-    debug_requested = 0;
-    return r;
-}
-
-/*
- * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
- */
-void qemu_system_reset(ShutdownCause reason)
-{
-    MachineClass *mc;
-
-    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
-
-    cpu_synchronize_all_states();
-
-    if (mc && mc->reset) {
-        mc->reset(current_machine);
-    } else {
-        qemu_devices_reset();
-    }
-    if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
-        qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
-    }
-    cpu_synchronize_all_post_reset();
-}
-
-/*
- * Wake the VM after suspend.
- */
-static void qemu_system_wakeup(void)
-{
-    MachineClass *mc;
-
-    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
-
-    if (mc && mc->wakeup) {
-        mc->wakeup(current_machine);
-    }
-}
-
-void qemu_system_guest_panicked(GuestPanicInformation *info)
-{
-    qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
-
-    if (current_cpu) {
-        current_cpu->crash_occurred = true;
-    }
-    qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
-                                   !!info, info);
-    vm_stop(RUN_STATE_GUEST_PANICKED);
-    if (!no_shutdown) {
-        qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
-                                       !!info, info);
-        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
-    }
-
-    if (info) {
-        if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
-            qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
-                          " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
-                          info->u.hyper_v.arg1,
-                          info->u.hyper_v.arg2,
-                          info->u.hyper_v.arg3,
-                          info->u.hyper_v.arg4,
-                          info->u.hyper_v.arg5);
-        } else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
-            qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
-                          "PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
-                          info->u.s390.core,
-                          S390CrashReason_str(info->u.s390.reason),
-                          info->u.s390.psw_mask,
-                          info->u.s390.psw_addr);
-        }
-        qapi_free_GuestPanicInformation(info);
-    }
-}
-
-void qemu_system_guest_crashloaded(GuestPanicInformation *info)
-{
-    qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded");
-
-    qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN,
-                                   !!info, info);
-
-    if (info) {
-        qapi_free_GuestPanicInformation(info);
-    }
-}
-
-void qemu_system_reset_request(ShutdownCause reason)
-{
-    if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
-        shutdown_requested = reason;
-    } else {
-        reset_requested = reason;
-    }
-    cpu_stop_current();
-    qemu_notify_event();
-}
-
-static void qemu_system_suspend(void)
-{
-    pause_all_vcpus();
-    notifier_list_notify(&suspend_notifiers, NULL);
-    runstate_set(RUN_STATE_SUSPENDED);
-    qapi_event_send_suspend();
-}
-
-void qemu_system_suspend_request(void)
-{
-    if (runstate_check(RUN_STATE_SUSPENDED)) {
-        return;
-    }
-    suspend_requested = 1;
-    cpu_stop_current();
-    qemu_notify_event();
-}
-
-void qemu_register_suspend_notifier(Notifier *notifier)
-{
-    notifier_list_add(&suspend_notifiers, notifier);
-}
-
-void qemu_system_wakeup_request(WakeupReason reason, Error **errp)
-{
-    trace_system_wakeup_request(reason);
-
-    if (!runstate_check(RUN_STATE_SUSPENDED)) {
-        error_setg(errp,
-                   "Unable to wake up: guest is not in suspended state");
-        return;
-    }
-    if (!(wakeup_reason_mask & (1 << reason))) {
-        return;
-    }
-    runstate_set(RUN_STATE_RUNNING);
-    wakeup_reason = reason;
-    qemu_notify_event();
-}
-
-void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
-{
-    if (enabled) {
-        wakeup_reason_mask |= (1 << reason);
-    } else {
-        wakeup_reason_mask &= ~(1 << reason);
-    }
-}
-
-void qemu_register_wakeup_notifier(Notifier *notifier)
-{
-    notifier_list_add(&wakeup_notifiers, notifier);
-}
-
-void qemu_register_wakeup_support(void)
-{
-    wakeup_suspend_enabled = true;
-}
-
-bool qemu_wakeup_suspend_enabled(void)
-{
-    return wakeup_suspend_enabled;
-}
-
-void qemu_system_killed(int signal, pid_t pid)
-{
-    shutdown_signal = signal;
-    shutdown_pid = pid;
-    no_shutdown = 0;
-
-    /* Cannot call qemu_system_shutdown_request directly because
-     * we are in a signal handler.
-     */
-    shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
-    qemu_notify_event();
-}
-
-void qemu_system_shutdown_request(ShutdownCause reason)
-{
-    trace_qemu_system_shutdown_request(reason);
-    replay_shutdown_request(reason);
-    shutdown_requested = reason;
-    qemu_notify_event();
-}
-
-static void qemu_system_powerdown(void)
-{
-    qapi_event_send_powerdown();
-    notifier_list_notify(&powerdown_notifiers, NULL);
-}
-
-static void qemu_system_shutdown(ShutdownCause cause)
-{
-    qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause);
-    notifier_list_notify(&shutdown_notifiers, &cause);
-}
-
-void qemu_system_powerdown_request(void)
-{
-    trace_qemu_system_powerdown_request();
-    powerdown_requested = 1;
-    qemu_notify_event();
-}
-
-void qemu_register_powerdown_notifier(Notifier *notifier)
-{
-    notifier_list_add(&powerdown_notifiers, notifier);
-}
-
-void qemu_register_shutdown_notifier(Notifier *notifier)
-{
-    notifier_list_add(&shutdown_notifiers, notifier);
-}
-
-void qemu_system_debug_request(void)
-{
-    debug_requested = 1;
-    qemu_notify_event();
-}
-
-static bool main_loop_should_exit(void)
-{
-    RunState r;
-    ShutdownCause request;
-
-    if (qemu_debug_requested()) {
-        vm_stop(RUN_STATE_DEBUG);
-    }
-    if (qemu_suspend_requested()) {
-        qemu_system_suspend();
-    }
-    request = qemu_shutdown_requested();
-    if (request) {
-        qemu_kill_report();
-        qemu_system_shutdown(request);
-        if (no_shutdown) {
-            vm_stop(RUN_STATE_SHUTDOWN);
-        } else {
-            return true;
-        }
-    }
-    request = qemu_reset_requested();
-    if (request) {
-        pause_all_vcpus();
-        qemu_system_reset(request);
-        resume_all_vcpus();
-        /*
-         * runstate can change in pause_all_vcpus()
-         * as iothread mutex is unlocked
-         */
-        if (!runstate_check(RUN_STATE_RUNNING) &&
-                !runstate_check(RUN_STATE_INMIGRATE) &&
-                !runstate_check(RUN_STATE_FINISH_MIGRATE)) {
-            runstate_set(RUN_STATE_PRELAUNCH);
-        }
-    }
-    if (qemu_wakeup_requested()) {
-        pause_all_vcpus();
-        qemu_system_wakeup();
-        notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
-        wakeup_reason = QEMU_WAKEUP_REASON_NONE;
-        resume_all_vcpus();
-        qapi_event_send_wakeup();
-    }
-    if (qemu_powerdown_requested()) {
-        qemu_system_powerdown();
-    }
-    if (qemu_vmstop_requested(&r)) {
-        vm_stop(r);
-    }
-    return false;
-}
-
-void qemu_main_loop(void)
-{
-#ifdef CONFIG_PROFILER
-    int64_t ti;
-#endif
-    while (!main_loop_should_exit()) {
-#ifdef CONFIG_PROFILER
-        ti = profile_getclock();
-#endif
-        main_loop_wait(false);
-#ifdef CONFIG_PROFILER
-        dev_time += profile_getclock() - ti;
-#endif
-    }
-}
-
 static void version(void)
 {
     printf("QEMU emulator version " QEMU_FULL_VERSION "\n"
@@ -2248,21 +1586,6 @@ static MachineClass *machine_parse(const char *name, GSList *machines)
     return mc;
 }
 
-void qemu_add_exit_notifier(Notifier *notify)
-{
-    notifier_list_add(&exit_notifiers, notify);
-}
-
-void qemu_remove_exit_notifier(Notifier *notify)
-{
-    notifier_remove(notify);
-}
-
-static void qemu_run_exit_notifiers(void)
-{
-    notifier_list_notify(&exit_notifiers, NULL);
-}
-
 static const char *pid_file;
 static Notifier qemu_unlink_pidfile_notifier;
 
@@ -3061,39 +2384,6 @@ static void qemu_maybe_daemonize(const char *pid_file)
     qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
 }
 
-static void qemu_init_subsystems(void)
-{
-    Error *err;
-
-    os_set_line_buffering();
-
-    module_call_init(MODULE_INIT_TRACE);
-
-    qemu_init_cpu_list();
-    qemu_init_cpu_loop();
-    qemu_mutex_lock_iothread();
-
-    atexit(qemu_run_exit_notifiers);
-
-    module_call_init(MODULE_INIT_QOM);
-    module_call_init(MODULE_INIT_MIGRATION);
-
-    runstate_init();
-    precopy_infrastructure_init();
-    postcopy_infrastructure_init();
-    monitor_init_globals();
-
-    if (qcrypto_init(&err) < 0) {
-        error_reportf_err(err, "cannot initialize crypto: ");
-        exit(1);
-    }
-
-    os_setup_early_signal_handling();
-
-    bdrv_init_with_whitelist();
-    socket_init();
-}
-
 static void qemu_init_displays(void)
 {
     DisplayState *ds;
@@ -4275,43 +3565,3 @@ void qemu_init(int argc, char **argv, char **envp)
     accel_setup_post(current_machine);
     os_setup_post();
 }
-
-void qemu_cleanup(void)
-{
-    gdbserver_cleanup();
-
-    /*
-     * cleaning up the migration object cancels any existing migration
-     * try to do this early so that it also stops using devices.
-     */
-    migration_shutdown();
-
-    /*
-     * We must cancel all block jobs while the block layer is drained,
-     * or cancelling will be affected by throttling and thus may block
-     * for an extended period of time.
-     * vm_shutdown() will bdrv_drain_all(), so we may as well include
-     * it in the drained section.
-     * We do not need to end this section, because we do not want any
-     * requests happening from here on anyway.
-     */
-    bdrv_drain_all_begin();
-
-    /* No more vcpu or device emulation activity beyond this point */
-    vm_shutdown();
-    replay_finish();
-
-    job_cancel_sync_all();
-    bdrv_close_all();
-
-    res_free();
-
-    /* vhost-user must be cleaned up before chardevs.  */
-    tpm_cleanup();
-    net_cleanup();
-    audio_cleanup();
-    monitor_cleanup();
-    qemu_chr_cleanup();
-    user_creatable_cleanup();
-    /* TODO: unref root container, check all devices are ok */
-}
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 33/36] vl: extract softmmu/globals.c
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (31 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 32/36] vl: extract softmmu/runstate.c Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 13:19   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 34/36] vl: remove serial_max_hds Paolo Bonzini
                   ` (4 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine.c         |  2 ++
 include/exec/cpu-common.h |  3 ++
 include/exec/exec-all.h   |  3 --
 softmmu/globals.c         | 74 +++++++++++++++++++++++++++++++++++++++
 softmmu/meson.build       |  1 +
 softmmu/vl.c              | 45 ++----------------------
 6 files changed, 83 insertions(+), 45 deletions(-)
 create mode 100644 softmmu/globals.c

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 745531c9d9..5659b1f49c 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -213,6 +213,8 @@ GlobalProperty hw_compat_2_1[] = {
 };
 const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
 
+MachineState *current_machine;
+
 static char *machine_get_kernel(Object *obj, Error **errp)
 {
     MachineState *ms = MACHINE(obj);
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index bd5e15dd7d..5a0a2d93e0 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -105,4 +105,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
 
 #endif
 
+/* vl.c */
+extern int singlestep;
+
 #endif /* CPU_COMMON_H */
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 94fe05daaa..fab573da06 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -676,7 +676,4 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
                                        MemoryRegionSection *section);
 #endif
 
-/* vl.c */
-extern int singlestep;
-
 #endif
diff --git a/softmmu/globals.c b/softmmu/globals.c
new file mode 100644
index 0000000000..e62d9cd8da
--- /dev/null
+++ b/softmmu/globals.c
@@ -0,0 +1,74 @@
+/*
+ * Global variables that (mostly) should not exist
+ *
+ * Copyright (c) 2003-2020 QEMU contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "exec/cpu-common.h"
+#include "hw/display/vga.h"
+#include "hw/i386/pc.h"
+#include "hw/i386/x86.h"
+#include "hw/loader.h"
+#include "hw/xen/xen.h"
+#include "net/net.h"
+#include "sysemu/cpus.h"
+#include "sysemu/sysemu.h"
+
+enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
+int display_opengl;
+const char* keyboard_layout;
+bool enable_mlock;
+bool enable_cpu_pm;
+int nb_nics;
+NICInfo nd_table[MAX_NICS];
+int autostart = 1;
+int vga_interface_type = VGA_NONE;
+Chardev *parallel_hds[MAX_PARALLEL_PORTS];
+int win2k_install_hack;
+int singlestep;
+int fd_bootchk = 1;
+int no_reboot;
+int no_shutdown;
+int graphic_rotate;
+QEMUOptionRom option_rom[MAX_OPTION_ROMS];
+int nb_option_roms;
+int old_param;
+const char *qemu_name;
+int alt_grab;
+int ctrl_grab;
+unsigned int nb_prom_envs;
+const char *prom_envs[MAX_PROM_ENVS];
+int boot_menu;
+bool boot_strict;
+uint8_t *boot_splash_filedata;
+int only_migratable; /* turn it off unless user states otherwise */
+int icount_align_option;
+
+/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the
+ * little-endian "wire format" described in the SMBIOS 2.6 specification.
+ */
+QemuUUID qemu_uuid;
+bool qemu_uuid_set;
+
+uint32_t xen_domid;
+enum xen_mode xen_mode = XEN_EMULATE;
+bool xen_domid_restrict;
diff --git a/softmmu/meson.build b/softmmu/meson.build
index 2a73ebc223..e5865b97cb 100644
--- a/softmmu/meson.build
+++ b/softmmu/meson.build
@@ -4,6 +4,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
   'cpus.c',
   'cpu-throttle.c',
   'datadir.c',
+  'globals.c',
   'physmem.c',
   'ioport.c',
   'rtc.c',
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 914b86ee86..fce15c249a 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -26,6 +26,7 @@
 #include "qemu-common.h"
 #include "qemu/datadir.h"
 #include "qemu/units.h"
+#include "exec/cpu-common.h"
 #include "hw/boards.h"
 #include "hw/qdev-properties.h"
 #include "qapi/error.h"
@@ -67,6 +68,8 @@
 #include "qemu/log.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
+#include "hw/i386/x86.h"
+#include "hw/i386/pc.h"
 #include "migration/misc.h"
 #include "migration/snapshot.h"
 #include "migration/global_state.h"
@@ -141,17 +144,8 @@ 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;
-enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static int mem_prealloc; /* force preallocation of physical target memory */
-int display_opengl;
-const char* keyboard_layout = NULL;
 static ram_addr_t ram_size;
-bool enable_mlock = false;
-bool enable_cpu_pm = false;
-int nb_nics;
-NICInfo nd_table[MAX_NICS];
-int autostart = 1;
-int vga_interface_type = VGA_NONE;
 static const char *vga_model = NULL;
 static DisplayOptions dpy;
 static int num_serial_hds;
@@ -159,41 +153,10 @@ static Chardev **serial_hds;
 static const char *log_mask;
 static const char *log_file;
 static bool list_data_dirs;
-Chardev *parallel_hds[MAX_PARALLEL_PORTS];
-int win2k_install_hack = 0;
-int singlestep = 0;
-int fd_bootchk = 1;
-int no_reboot;
-int no_shutdown = 0;
-int graphic_rotate = 0;
 static const char *watchdog;
-QEMUOptionRom option_rom[MAX_OPTION_ROMS];
-int nb_option_roms;
-int old_param = 0;
-const char *qemu_name;
-int alt_grab = 0;
-int ctrl_grab = 0;
-unsigned int nb_prom_envs = 0;
-const char *prom_envs[MAX_PROM_ENVS];
-int boot_menu;
-bool boot_strict;
-uint8_t *boot_splash_filedata;
-int only_migratable; /* turn it off unless user states otherwise */
-bool wakeup_suspend_enabled;
-int icount_align_option;
 static const char *qtest_chrdev;
 static const char *qtest_log;
 
-/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the
- * little-endian "wire format" described in the SMBIOS 2.6 specification.
- */
-QemuUUID qemu_uuid;
-bool qemu_uuid_set;
-
-uint32_t xen_domid;
-enum xen_mode xen_mode = XEN_EMULATE;
-bool xen_domid_restrict;
-
 static int has_defaults = 1;
 static int default_serial = 1;
 static int default_parallel = 1;
@@ -801,8 +764,6 @@ static int usb_parse(const char *cmdline)
 /***********************************************************/
 /* machine registration */
 
-MachineState *current_machine;
-
 static MachineClass *find_machine(const char *name, GSList *machines)
 {
     GSList *el;
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 34/36] vl: remove serial_max_hds
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (32 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 33/36] vl: extract softmmu/globals.c Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 13:11   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 35/36] vl: clean up -boot variables Paolo Bonzini
                   ` (3 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

serial_hd(i) is NULL if and only if i >= serial_max_hds().  Test
serial_hd(i) instead of bounding the loop at serial_max_hds(),
thus removing one more function that vl.c is expected to export.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ppc/spapr.c          | 6 ++----
 include/sysemu/sysemu.h | 4 ----
 softmmu/vl.c            | 5 -----
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 049efa0bbf..b7e0894019 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2878,10 +2878,8 @@ static void spapr_machine_init(MachineState *machine)
     /* Set up VIO bus */
     spapr->vio_bus = spapr_vio_bus_init();
 
-    for (i = 0; i < serial_max_hds(); i++) {
-        if (serial_hd(i)) {
-            spapr_vty_create(spapr->vio_bus, serial_hd(i));
-        }
+    for (i = 0; serial_hd(i); i++) {
+        spapr_vty_create(spapr->vio_bus, serial_hd(i));
     }
 
     /* We always have at least the nvram device on VIO */
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 3dac3229ec..0e7b405d22 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -74,10 +74,6 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict);
 
 /* Return the Chardev for serial port i, or NULL if none */
 Chardev *serial_hd(int i);
-/* return the number of serial ports defined by the user. serial_hd(i)
- * will always return NULL for any i which is greater than or equal to this.
- */
-int serial_max_hds(void);
 
 /* parallel ports */
 
diff --git a/softmmu/vl.c b/softmmu/vl.c
index fce15c249a..d76f87028d 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -1439,11 +1439,6 @@ Chardev *serial_hd(int i)
     return NULL;
 }
 
-int serial_max_hds(void)
-{
-    return num_serial_hds;
-}
-
 static int parallel_parse(const char *devname)
 {
     static int index = 0;
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 35/36] vl: clean up -boot variables
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (33 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 34/36] vl: remove serial_max_hds Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 13:12   ` Igor Mammedov
  2020-11-23 14:14 ` [PATCH 36/36] vl: move all generic initialization out of vl.c Paolo Bonzini
                   ` (2 subsequent siblings)
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

Move more of them into MachineState, in preparation for moving initialization
of the machine out of vl.c.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 include/hw/boards.h |  1 +
 softmmu/vl.c        | 11 ++++++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/include/hw/boards.h b/include/hw/boards.h
index 4537cfb5c6..b9233af54a 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -283,6 +283,7 @@ struct MachineState {
     ram_addr_t maxram_size;
     uint64_t   ram_slots;
     const char *boot_order;
+    const char *boot_once;
     char *kernel_filename;
     char *kernel_cmdline;
     char *initrd_filename;
diff --git a/softmmu/vl.c b/softmmu/vl.c
index d76f87028d..aeb988bcad 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -132,8 +132,6 @@ typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue;
 
 static const char *cpu_option;
 static const char *mem_path;
-static const char *boot_order;
-static const char *boot_once;
 static const char *incoming;
 static const char *loadvm;
 static ram_addr_t maxram_size;
@@ -1733,6 +1731,8 @@ static void qemu_apply_machine_options(void)
 {
     MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
     QemuOpts *machine_opts = qemu_get_machine_opts();
+    const char *boot_order = NULL;
+    const char *boot_once = NULL;
     QemuOpts *opts;
 
     qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
@@ -1762,6 +1762,7 @@ static void qemu_apply_machine_options(void)
     }
 
     current_machine->boot_order = boot_order;
+    current_machine->boot_once = boot_once;
 }
 
 static void qemu_create_early_backends(void)
@@ -2444,9 +2445,9 @@ static void qemu_machine_creation_done(void)
 
     qdev_prop_check_globals();
 
-    if (boot_once) {
-        qemu_boot_set(boot_once, &error_fatal);
-        qemu_register_reset(restore_boot_order, g_strdup(boot_order));
+    if (current_machine->boot_once) {
+        qemu_boot_set(current_machine->boot_once, &error_fatal);
+        qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
     }
 
     if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
-- 
2.26.2




^ permalink raw reply related	[flat|nested] 70+ messages in thread

* [PATCH 36/36] vl: move all generic initialization out of vl.c
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (34 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 35/36] vl: clean up -boot variables Paolo Bonzini
@ 2020-11-23 14:14 ` Paolo Bonzini
  2020-11-27 13:30   ` Igor Mammedov
  2020-11-27 12:00 ` [PATCH 37/36] machine: introduce MachineInitPhase Paolo Bonzini
  2020-11-30 12:50 ` [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Igor Mammedov
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-23 14:14 UTC (permalink / raw)
  To: qemu-devel

qdev_machine_creation_done is only setting a flag now.  Extend it to
move more code out of vl.c.  Leave only consistency checks and gdbserver
processing in qemu_machine_creation_done.

gdbserver_start can be moved after qdev_machine_creation_done because
it only does listen on the socket and creates some internal data
structures; it does not send any data (e.g. guest state) over the socket.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/core/machine.c      | 47 +++++++++++++++++++++++++++++++++++++++++-
 hw/core/qdev.c         | 12 +++--------
 include/hw/qdev-core.h |  1 +
 softmmu/vl.c           | 37 +--------------------------------
 4 files changed, 51 insertions(+), 46 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 5659b1f49c..025c4f9749 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -16,16 +16,21 @@
 #include "sysemu/replay.h"
 #include "qemu/units.h"
 #include "hw/boards.h"
+#include "hw/loader.h"
 #include "qapi/error.h"
 #include "qapi/qapi-visit-common.h"
 #include "qapi/visitor.h"
 #include "hw/sysbus.h"
+#include "sysemu/cpus.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
 #include "sysemu/numa.h"
 #include "qemu/error-report.h"
 #include "sysemu/qtest.h"
 #include "hw/pci/pci.h"
 #include "hw/mem/nvdimm.h"
+#include "migration/global_state.h"
 #include "migration/vmstate.h"
 
 GlobalProperty hw_compat_5_1[] = {
@@ -1186,10 +1191,50 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify)
     notifier_remove(notify);
 }
 
-void qemu_run_machine_init_done_notifiers(void)
+void qdev_machine_creation_done(void)
 {
+    cpu_synchronize_all_post_init();
+
+    if (current_machine->boot_once) {
+        qemu_boot_set(current_machine->boot_once, &error_fatal);
+        qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
+    }
+
+    /*
+     * ok, initial machine setup is done, starting from now we can
+     * only create hotpluggable devices
+     */
+    qdev_hotplug = true;
+    qdev_assert_realized_properly();
+
+    /* TODO: once all bus devices are qdevified, this should be done
+     * when bus is created by qdev.c */
+    /*
+     * TODO: If we had a main 'reset container' that the whole system
+     * lived in, we could reset that using the multi-phase reset
+     * APIs. For the moment, we just reset the sysbus, which will cause
+     * all devices hanging off it (and all their child buses, recursively)
+     * to be reset. Note that this will *not* reset any Device objects
+     * which are not attached to some part of the qbus tree!
+     */
+    qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
+
     machine_init_done = true;
     notifier_list_notify(&machine_init_done_notifiers, NULL);
+
+    if (rom_check_and_register_reset() != 0) {
+        error_report("rom check and register reset failed");
+        exit(1);
+    }
+
+    replay_start();
+
+    /* This checkpoint is required by replay to separate prior clock
+       reading from the other reads, because timer polling functions query
+       clock values from the log. */
+    replay_checkpoint(CHECKPOINT_RESET);
+    qemu_system_reset(SHUTDOWN_CAUSE_NONE);
+    register_global_state();
 }
 
 static const TypeInfo machine_info = {
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 262bca716f..bc5df8ce69 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -413,7 +413,7 @@ void qdev_unrealize(DeviceState *dev)
     object_property_set_bool(OBJECT(dev), "realized", false, &error_abort);
 }
 
-static int qdev_assert_realized_properly(Object *obj, void *opaque)
+static int qdev_assert_realized_properly_cb(Object *obj, void *opaque)
 {
     DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE));
     DeviceClass *dc;
@@ -426,16 +426,10 @@ static int qdev_assert_realized_properly(Object *obj, void *opaque)
     return 0;
 }
 
-void qdev_machine_creation_done(void)
+void qdev_assert_realized_properly(void)
 {
-    /*
-     * ok, initial machine setup is done, starting from now we can
-     * only create hotpluggable devices
-     */
-    qdev_hotplug = true;
-
     object_child_foreach_recursive(object_get_root(),
-                                   qdev_assert_realized_properly, NULL);
+                                   qdev_assert_realized_properly_cb, NULL);
 }
 
 bool qdev_machine_modified(void)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index b77a2f1da7..6446846752 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -815,6 +815,7 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
 
 const char *qdev_fw_name(DeviceState *dev);
 
+void qdev_assert_realized_properly(void);
 Object *qdev_get_machine(void);
 
 /* FIXME: make this a link<> */
diff --git a/softmmu/vl.c b/softmmu/vl.c
index aeb988bcad..1fde4a17a9 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -72,7 +72,6 @@
 #include "hw/i386/pc.h"
 #include "migration/misc.h"
 #include "migration/snapshot.h"
-#include "migration/global_state.h"
 #include "sysemu/tpm.h"
 #include "sysemu/dma.h"
 #include "hw/audio/soundhw.h"
@@ -2426,8 +2425,6 @@ static void qemu_create_cli_devices(void)
 
 static void qemu_machine_creation_done(void)
 {
-    cpu_synchronize_all_post_init();
-
     /* Did we create any drives that we failed to create a device for? */
     drive_check_orphaned();
 
@@ -2445,43 +2442,11 @@ static void qemu_machine_creation_done(void)
 
     qdev_prop_check_globals();
 
-    if (current_machine->boot_once) {
-        qemu_boot_set(current_machine->boot_once, &error_fatal);
-        qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
-    }
-
-    if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
-        exit(1);
-    }
-
     qdev_machine_creation_done();
 
-    /* TODO: once all bus devices are qdevified, this should be done
-     * when bus is created by qdev.c */
-    /*
-     * TODO: If we had a main 'reset container' that the whole system
-     * lived in, we could reset that using the multi-phase reset
-     * APIs. For the moment, we just reset the sysbus, which will cause
-     * all devices hanging off it (and all their child buses, recursively)
-     * to be reset. Note that this will *not* reset any Device objects
-     * which are not attached to some part of the qbus tree!
-     */
-    qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
-    qemu_run_machine_init_done_notifiers();
-
-    if (rom_check_and_register_reset() != 0) {
-        error_report("rom check and register reset failed");
+    if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
         exit(1);
     }
-
-    replay_start();
-
-    /* This checkpoint is required by replay to separate prior clock
-       reading from the other reads, because timer polling functions query
-       clock values from the log. */
-    replay_checkpoint(CHECKPOINT_RESET);
-    qemu_system_reset(SHUTDOWN_CAUSE_NONE);
-    register_global_state();
 }
 
 void qmp_x_exit_preconfig(Error **errp)
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* Re: [PATCH 03/36] vl: split various early command line options to a separate function
  2020-11-23 14:14 ` [PATCH 03/36] vl: split various early command line options to a separate function Paolo Bonzini
@ 2020-11-26 16:47   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 16:47 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:02 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Various options affect the global state of QEMU including the rest of
> qemu_init, and they need to be called very early.  Group them together
> in a function that is called at the beginning.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  softmmu/vl.c | 200 ++++++++++++++++++++++++++++-----------------------
>  1 file changed, 112 insertions(+), 88 deletions(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index c45a99a2bf..07378301d5 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -117,6 +117,7 @@
>  
>  #define MAX_VIRTIO_CONSOLES 1
>  
> +static const char *cpu_option;
>  static const char *data_dir[16];
>  static int data_dir_idx;
>  enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
> @@ -142,6 +143,9 @@ int vga_interface_type = VGA_NONE;
>  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;
>  Chardev *parallel_hds[MAX_PARALLEL_PORTS];
>  int win2k_install_hack = 0;
>  int singlestep = 0;
> @@ -2862,6 +2866,105 @@ static char *find_datadir(void)
>      return get_relocated_path(CONFIG_QEMU_DATADIR);
>  }
>  
> +static void qemu_process_early_options(void)
> +{
> +    char **dirs;
> +    int i;
> +
> +#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);
> +
> +#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
> +
> +    if (!trace_init_backends()) {
> +        exit(1);
> +    }
> +    trace_init_file();
> +
> +    /* Open the logfile at this point and set the log mask if necessary.  */
> +    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);
> +    }
> +
> +    /* add configured firmware directories */
> +    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
> +    for (i = 0; dirs[i] != NULL; i++) {
> +        qemu_add_data_dir(get_relocated_path(dirs[i]));
> +    }
> +    g_strfreev(dirs);
> +
> +    /* try to find datadir relative to the executable path */
> +    qemu_add_data_dir(find_datadir());
> +}
> +
> +static void qemu_process_help_options(void)
> +{
> +    int i;
> +
> +    /*
> +     * 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) {
> +        for (i = 0; i < data_dir_idx; i++) {
> +            printf("%s\n", data_dir[i]);
> +        }
> +        exit(0);
> +    }
> +}
> +
> +static void qemu_maybe_daemonize(const char *pid_file)
> +{
> +    Error *err;
> +
> +    os_daemonize();
> +    rcu_disable_atfork();
> +
> +    if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
> +        error_reportf_err(err, "cannot create PID file: ");
> +        exit(1);
> +    }
> +
> +    qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
> +    qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
> +}
> +
> +
>  void qemu_init(int argc, char **argv, char **envp)
>  {
>      int i;
> @@ -2878,21 +2981,16 @@ void qemu_init(int argc, char **argv, char **envp)
>      const char *optarg;
>      const char *loadvm = NULL;
>      MachineClass *machine_class;
> -    const char *cpu_option;
>      const char *vga_model = NULL;
>      const char *incoming = NULL;
>      bool userconfig = true;
>      bool nographic = false;
>      int display_remote = 0;
> -    const char *log_mask = NULL;
> -    const char *log_file = NULL;
>      ram_addr_t maxram_size;
>      uint64_t ram_slots = 0;
>      FILE *vmstate_dump_file = NULL;
>      Error *main_loop_err = NULL;
>      Error *err = NULL;
> -    bool list_data_dirs = false;
> -    char **dirs;
>      const char *mem_path = NULL;
>      bool have_custom_ram_size;
>      BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
> @@ -3842,19 +3940,17 @@ void qemu_init(int argc, char **argv, char **envp)
>      loc_set_none();
>  
>      /*
> -     * 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'.
> +     * These options affect everything else and should be processed
> +     * before daemonizing.
>       */
> -    if (cpu_option && is_help_option(cpu_option)) {
> -        list_cpus(cpu_option);
> -        exit(0);
> -    }
> +    qemu_process_early_options();
>  
> -    if (qemu_opts_foreach(qemu_find_opts("device"),
> -                          device_help_func, NULL, NULL)) {
> -        exit(0);
> +    qemu_process_help_options();
> +    qemu_maybe_daemonize(pid_file);
> +
> +    if (qemu_init_main_loop(&main_loop_err)) {
> +        error_report_err(main_loop_err);
> +        exit(1);
>      }
>  
>      user_register_global_props();
> @@ -3875,40 +3971,6 @@ void qemu_init(int argc, char **argv, char **envp)
>      have_custom_ram_size = set_memory_options(&ram_slots, &maxram_size,
>                                                machine_class);
>  
> -    os_daemonize();
> -    rcu_disable_atfork();
> -
> -    if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
> -        error_reportf_err(err, "cannot create PID file: ");
> -        exit(1);
> -    }
> -
> -    qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
> -    qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
> -
> -    if (qemu_init_main_loop(&main_loop_err)) {
> -        error_report_err(main_loop_err);
> -        exit(1);
> -    }
> -
> -#ifdef CONFIG_SECCOMP
> -    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);
> -
> -#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
> -
>      current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
>      if (machine_help_func(qemu_get_machine_opts(), current_machine)) {
>          exit(0);
> @@ -3934,44 +3996,6 @@ void qemu_init(int argc, char **argv, char **envp)
>          qemu_set_hw_version(machine_class->hw_version);
>      }
>  
> -    if (!trace_init_backends()) {
> -        exit(1);
> -    }
> -    trace_init_file();
> -
> -    /* Open the logfile at this point and set the log mask if necessary.
> -     */
> -    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);
> -    }
> -
> -    /* add configured firmware directories */
> -    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
> -    for (i = 0; dirs[i] != NULL; i++) {
> -        qemu_add_data_dir(get_relocated_path(dirs[i]));
> -    }
> -    g_strfreev(dirs);
> -
> -    /* try to find datadir relative to the executable path */
> -    qemu_add_data_dir(find_datadir());
> -
> -    /* -L help lists the data directories and exits. */
> -    if (list_data_dirs) {
> -        for (i = 0; i < data_dir_idx; i++) {
> -            printf("%s\n", data_dir[i]);
> -        }
> -        exit(0);
> -    }
> -
>      machine_smp_parse(current_machine,
>          qemu_opts_find(qemu_find_opts("smp-opts"), NULL), &error_fatal);
>  



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 12/36] vl: load plugins as late as possible
  2020-11-23 14:14 ` [PATCH 12/36] vl: load plugins as late as possible Paolo Bonzini
@ 2020-11-26 16:54   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 16:54 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Philippe Mathieu-Daudé, qemu-devel

On Mon, 23 Nov 2020 09:14:11 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> There is no need to load plugins in the middle of default device processing,
> move -plugin handling just before preconfig is entered.
> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  softmmu/vl.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 87c10f625c..ab08a0290c 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -125,6 +125,7 @@ static const char *boot_order;
>  static const char *boot_once;
>  static const char *incoming;
>  static const char *loadvm;
> +static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
>  enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
>  static int mem_prealloc; /* force preallocation of physical target memory */
>  int display_opengl;
> @@ -3074,6 +3075,11 @@ static void qemu_init_board(void)
>          create_default_memdev(current_machine, mem_path);
>      }
>  
> +    /* process plugin before CPUs are created, but once -smp has been parsed */
> +    if (qemu_plugin_load_list(&plugin_list)) {
> +        exit(1);
> +    }
> +
>      machine_run_board_init(current_machine);
>  
>      /*
> @@ -3208,7 +3214,6 @@ void qemu_init(int argc, char **argv, char **envp)
>      Error *err = NULL;
>      bool have_custom_ram_size;
>      BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue);
> -    QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
>  
>      qemu_add_opts(&qemu_drive_opts);
>      qemu_add_drive_opts(&qemu_legacy_drive_opts);
> @@ -4178,11 +4183,6 @@ void qemu_init(int argc, char **argv, char **envp)
>                                 machine_class->default_machine_opts, 0);
>      }
>  
> -    /* process plugin before CPUs are created, but once -smp has been parsed */
> -    if (qemu_plugin_load_list(&plugin_list)) {
> -        exit(1);
> -    }
> -
>      qemu_opts_foreach(qemu_find_opts("device"),
>                        default_driver_check, NULL, NULL);
>      qemu_opts_foreach(qemu_find_opts("global"),



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board
  2020-11-23 14:14 ` [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board Paolo Bonzini
@ 2020-11-26 17:10   ` Igor Mammedov
  2020-11-27  5:03     ` Paolo Bonzini
  0 siblings, 1 reply; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 17:10 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:12 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Move more sane parts of the huge qemu_init function out of it.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  softmmu/vl.c | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index ab08a0290c..5d68cf828c 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -3070,6 +3070,11 @@ static void qemu_init_board(void)
>  {
>      MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
>  
> +    if (semihosting_enabled() && !semihosting_get_argc() && current_machine->kernel_filename) {
> +        /* fall back to the -kernel/-append */
> +        semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline);
> +    }

it doesn't seem to depend on anything that warrants calling it this late.

>      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);
> @@ -4385,13 +4390,6 @@ void qemu_init(int argc, char **argv, char **envp)
>          boot_order = machine_class->default_boot_order;
>      }
>  
> -    if (semihosting_enabled() && !semihosting_get_argc()) {
> -        const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
> -        const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
> -        /* fall back to the -kernel/-append */
> -        semihosting_arg_fallback(kernel_filename, kernel_cmdline);
> -    }

Can we move this hunk as is to somewhere around qemu_maybe_daemonize() time?


>      if (net_init_clients(&err) < 0) {
>          error_report_err(err);
>          exit(1);



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 14/36] vl: extract default devices to separate functions
  2020-11-23 14:14 ` [PATCH 14/36] vl: extract default devices to separate functions Paolo Bonzini
@ 2020-11-26 17:29   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 17:29 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:13 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  softmmu/vl.c | 216 +++++++++++++++++++++++++++------------------------
>  1 file changed, 114 insertions(+), 102 deletions(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 5d68cf828c..b6c62e1e4f 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -125,7 +125,9 @@ static const char *boot_order;
>  static const char *boot_once;
>  static const char *incoming;
>  static const char *loadvm;
> +static int display_remote;
>  static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list);
> +static bool nographic = false;
>  enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
>  static int mem_prealloc; /* force preallocation of physical target memory */
>  int display_opengl;
> @@ -147,6 +149,7 @@ static int rtc_host_datetime_offset = -1; /* valid & used only with
>                                               RTC_BASE_DATETIME */
>  QEMUClockType rtc_clock;
>  int vga_interface_type = VGA_NONE;
> +static const char *vga_model = NULL;
>  static DisplayOptions dpy;
>  static int num_serial_hds;
>  static Chardev **serial_hds;
> @@ -2224,6 +2227,115 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline))
>      return 0;
>  }
>  
> +static void qemu_disable_default_devices(void)
> +{
> +    MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
> +
> +    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;
> +#if defined(CONFIG_VNC)
> +            vnc_parse("localhost:0,to=99,id=default", &error_abort);
> +#endif
> +        }
> +    }
> +    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;
> @@ -3209,10 +3321,7 @@ void qemu_init(int argc, char **argv, char **envp)
>      int optind;
>      const char *optarg;
>      MachineClass *machine_class;
> -    const char *vga_model = NULL;
>      bool userconfig = true;
> -    bool nographic = false;
> -    int display_remote = 0;
>      ram_addr_t maxram_size;
>      uint64_t ram_slots = 0;
>      FILE *vmstate_dump_file = NULL;
> @@ -4188,97 +4297,8 @@ void qemu_init(int argc, char **argv, char **envp)
>                                 machine_class->default_machine_opts, 0);
>      }
>  
> -    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;
> -    }
> -
> -    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;
> -#if defined(CONFIG_VNC)
> -            vnc_parse("localhost:0,to=99,id=default", &error_abort);
> -#endif
> -        }
> -    }
> -    if (dpy.type == DISPLAY_TYPE_DEFAULT) {
> -        dpy.type = DISPLAY_TYPE_NONE;
> -    }
> -
> +    qemu_disable_default_devices();
> +    qemu_create_default_devices();
>      if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
>          error_report("-alt-grab and -ctrl-grab are only valid "
>                       "for SDL, ignoring option");
> @@ -4417,14 +4437,6 @@ void qemu_init(int argc, char **argv, char **envp)
>      qemu_semihosting_connect_chardevs();
>      qemu_semihosting_console_init();
>  
> -    /* 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);
> -    }
> -
>      /* This checkpoint is required by replay to separate prior clock
>         reading from the other reads, because timer polling functions query
>         clock values from the log. */



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 15/36] vl: move CHECKPOINT_INIT after preconfig
  2020-11-23 14:14 ` [PATCH 15/36] vl: move CHECKPOINT_INIT after preconfig Paolo Bonzini
@ 2020-11-26 17:36   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 17:36 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Philippe Mathieu-Daudé, qemu-devel

On Mon, 23 Nov 2020 09:14:14 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Move CHECKPOINT_INIT right before the machine initialization is
> completed.  Everything before is essentially an extension of
> command line parsing.
> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  hw/core/machine.c | 5 +++++
>  softmmu/vl.c      | 5 -----
>  2 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 7ef3de5ce5..a5cfbcc7cb 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -1107,6 +1107,11 @@ void machine_run_board_init(MachineState *machine)
>      ObjectClass *oc = object_class_by_name(machine->cpu_type);
>      CPUClass *cc;
>  
> +    /* This checkpoint is required by replay to separate prior clock
> +       reading from the other reads, because timer polling functions query
> +       clock values from the log. */
> +    replay_checkpoint(CHECKPOINT_INIT);
> +
>      if (machine->ram_memdev_id) {
>          Object *o;
>          o = object_resolve_path_type(machine->ram_memdev_id,
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index b6c62e1e4f..dc0cdc3417 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -4437,11 +4437,6 @@ void qemu_init(int argc, char **argv, char **envp)
>      qemu_semihosting_connect_chardevs();
>      qemu_semihosting_console_init();
>  
> -    /* This checkpoint is required by replay to separate prior clock
> -       reading from the other reads, because timer polling functions query
> -       clock values from the log. */
> -    replay_checkpoint(CHECKPOINT_INIT);
> -
>      current_machine->boot_order = boot_order;
>  
>      /* parse features once if machine provides default cpu_type */



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 20/36] vl: separate qemu_resolve_machine_memdev
  2020-11-23 14:14 ` [PATCH 20/36] vl: separate qemu_resolve_machine_memdev Paolo Bonzini
@ 2020-11-26 17:39   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 17:39 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:19 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> This is a bit nasty: the machine is storing a string and later
> resolving it.  We probably want to make the memdev property a
> normal link, and handle "-M memdev" as a legacy option that is
> special cased by machine_set_property.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  softmmu/vl.c | 70 +++++++++++++++++++++++++++-------------------------
>  1 file changed, 37 insertions(+), 33 deletions(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 741a800114..6c8a103178 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2834,6 +2834,42 @@ static bool have_custom_ram_size(void)
>      return !!qemu_opt_get_size(opts, "size", 0);
>  }
>  
> +static void qemu_resolve_machine_memdev(void)
> +{
> +    if (current_machine->ram_memdev_id) {
> +        Object *backend;
> +        ram_addr_t backend_size;
> +
> +        backend = object_resolve_path_type(current_machine->ram_memdev_id,
> +                                           TYPE_MEMORY_BACKEND, NULL);
> +        if (!backend) {
> +            error_report("Memory backend '%s' not found",
> +                         current_machine->ram_memdev_id);
> +            exit(EXIT_FAILURE);
> +        }
> +        backend_size = object_property_get_uint(backend, "size",  &error_abort);
> +        if (have_custom_ram_size() && backend_size != ram_size) {
> +                error_report("Size specified by -m option must match size of "
> +                             "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;
> +    }
> +
> +    if (!xen_enabled()) {
> +        /* On 32-bit hosts, QEMU is limited by virtual address space */
> +        if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
> +            error_report("at most 2047 MB RAM can be simulated");
> +            exit(1);
> +        }
> +    }
> +}
> +
>  static void set_memory_options(MachineClass *mc)
>  {
>      uint64_t sz;
> @@ -4467,39 +4503,7 @@ void qemu_init(int argc, char **argv, char **envp)
>          current_machine->cpu_type = parse_cpu_option(cpu_option);
>      }
>  
> -    if (current_machine->ram_memdev_id) {
> -        Object *backend;
> -        ram_addr_t backend_size;
> -
> -        backend = object_resolve_path_type(current_machine->ram_memdev_id,
> -                                           TYPE_MEMORY_BACKEND, NULL);
> -        if (!backend) {
> -            error_report("Memory backend '%s' not found",
> -                         current_machine->ram_memdev_id);
> -            exit(EXIT_FAILURE);
> -        }
> -        backend_size = object_property_get_uint(backend, "size",  &error_abort);
> -        if (have_custom_ram_size() && backend_size != ram_size) {
> -                error_report("Size specified by -m option must match size of "
> -                             "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;
> -    }
> -
> -    if (!xen_enabled()) {
> -        /* On 32-bit hosts, QEMU is limited by virtual address space */
> -        if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
> -            error_report("at most 2047 MB RAM can be simulated");
> -            exit(1);
> -        }
> -    }
> -
> +    qemu_resolve_machine_memdev();
>      parse_numa_opts(current_machine);
>  
>      /* do monitor/qmp handling at preconfig state if requested */



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 21/36] vl: initialize displays before preconfig loop
  2020-11-23 14:14 ` [PATCH 21/36] vl: initialize displays before preconfig loop Paolo Bonzini
@ 2020-11-26 17:51   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 17:51 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:20 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Displays should be available before the monitor starts, so that
> it is possible to use the graphical console to interact with
> the monitor itself.
> 
> This patch is quite ugly, but all this is temporary.  The double
> call to qemu_init_displays will go away as soon we can unify machine
> initialization between the preconfig and "normal" flows, and so will
> the preconfig_exit_requested variable (that is only preconfig_requested
> remains).
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  softmmu/vl.c | 57 +++++++++++++++++++++++++++++++++-------------------
>  1 file changed, 36 insertions(+), 21 deletions(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 6c8a103178..073d7412ad 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -137,6 +137,7 @@ 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;
> @@ -3211,12 +3212,12 @@ static void qemu_validate_options(void)
>            }
>      }
>  
> -    if (loadvm && !preconfig_exit_requested) {
> +    if (loadvm && preconfig_requested) {
>          error_report("'preconfig' and 'loadvm' options are "
>                       "mutually exclusive");
>          exit(EXIT_FAILURE);
>      }
> -    if (incoming && !preconfig_exit_requested) {
> +    if (incoming && preconfig_requested) {
>          error_report("'preconfig' and 'incoming' options are "
>                       "mutually exclusive");
>          exit(EXIT_FAILURE);
> @@ -3380,6 +3381,28 @@ static void qemu_init_subsystems(void)
>      socket_init();
>  }
>  
> +static void qemu_init_displays(void)
> +{
> +    DisplayState *ds;
> +
> +    /* init local displays */
> +    ds = init_displaystate();
> +    qemu_display_init(ds, &dpy);
> +
> +    /* 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();
> +    }
> +}
> +
>  /*
>   * Called after leaving preconfig state.  From here on runstate is
>   * RUN_STATE_PRELAUNCH or RUN_STATE_INMIGRATE.
> @@ -3443,8 +3466,6 @@ static void qemu_create_cli_devices(void)
>  
>  static void qemu_machine_creation_done(void)
>  {
> -    DisplayState *ds;
> -
>      cpu_synchronize_all_post_init();
>  
>      /* Did we create any drives that we failed to create a device for? */
> @@ -3467,23 +3488,6 @@ static void qemu_machine_creation_done(void)
>          qemu_register_reset(restore_boot_order, g_strdup(boot_order));
>      }
>  
> -    /* init local displays */
> -    ds = init_displaystate();
> -    qemu_display_init(ds, &dpy);
> -
> -    /* 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();
> -    }
> -
>      if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
>          exit(1);
>      }
> @@ -4083,6 +4087,7 @@ void qemu_init(int argc, char **argv, char **envp)
>                  break;
>              case QEMU_OPTION_preconfig:
>                  preconfig_exit_requested = false;
> +                preconfig_requested = true;
>                  break;
>              case QEMU_OPTION_enable_kvm:
>                  olist = qemu_find_opts("machine");
> @@ -4506,11 +4511,21 @@ void qemu_init(int argc, char **argv, char **envp)
>      qemu_resolve_machine_memdev();
>      parse_numa_opts(current_machine);
>  
> +    if (preconfig_requested) {
> +        qemu_init_displays();
> +    }
> +
>      /* do monitor/qmp handling at preconfig state if requested */
>      qemu_main_loop();
>  
>      qemu_init_board();
> +
>      qemu_create_cli_devices();
> +
> +    /* initialize displays after all errors have been reported */
> +    if (!preconfig_requested) {
> +        qemu_init_displays();
> +    }
>      qemu_machine_creation_done();
>  
>      if (loadvm) {



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 22/36] vl: move -global check earlier
  2020-11-23 14:14 ` [PATCH 22/36] vl: move -global check earlier Paolo Bonzini
@ 2020-11-26 17:55   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 17:55 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:21 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> The check has the same effect here, it only matters that it is performed
> once all devices, both builtin and user-specified, have been created.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  softmmu/vl.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 073d7412ad..ccc3b8e838 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -3483,6 +3483,8 @@ static void qemu_machine_creation_done(void)
>          net_check_clients();
>      }
>  
> +    qdev_prop_check_globals();
> +
>      if (boot_once) {
>          qemu_boot_set(boot_once, &error_fatal);
>          qemu_register_reset(restore_boot_order, g_strdup(boot_order));
> @@ -4540,7 +4542,6 @@ void qemu_init(int argc, char **argv, char **envp)
>          replay_vmstate_init();
>      }
>  
> -    qdev_prop_check_globals();
>      if (vmstate_dump_file) {
>          /* dump and exit */
>          dump_vmstate_json_to_file(vmstate_dump_file);



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 23/36] migration, vl: start migration via qmp_migrate_incoming
  2020-11-23 14:14 ` [PATCH 23/36] migration, vl: start migration via qmp_migrate_incoming Paolo Bonzini
@ 2020-11-26 18:04   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 18:04 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:22 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Make qemu_start_incoming_migration local to migration/migration.c.
> By using the runstate instead of a separate flag, vl need not do
> anything to setup deferred incoming migration.
> 
> qmp_migrate_incoming also does not need the deferred_incoming flag
> anymore, because "-incoming PROTOCOL" will clear the "once" flag
> before the main loop starts.  Therefore, later invocations of
> the migrate-incoming command will fail with the existing
> "The incoming migration has already been started" error message.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  include/migration/misc.h |  1 -
>  migration/migration.c    | 33 ++++++++-------------------------
>  softmmu/vl.c             | 11 +++++++----
>  3 files changed, 15 insertions(+), 30 deletions(-)
> 
> diff --git a/include/migration/misc.h b/include/migration/misc.h
> index 34e7d75713..bccc1b6b44 100644
> --- a/include/migration/misc.h
> +++ b/include/migration/misc.h
> @@ -58,7 +58,6 @@ void dump_vmstate_json_to_file(FILE *out_fp);
>  /* migration/migration.c */
>  void migration_object_init(void);
>  void migration_shutdown(void);
> -void qemu_start_incoming_migration(const char *uri, Error **errp);
>  bool migration_is_idle(void);
>  bool migration_is_active(MigrationState *);
>  void add_migration_state_change_notifier(Notifier *notify);
> diff --git a/migration/migration.c b/migration/migration.c
> index d9e94f4080..e0dbde4091 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -118,8 +118,6 @@
>  static NotifierList migration_state_notifiers =
>      NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
>  
> -static bool deferred_incoming;
> -
>  /* Messages sent on the return path from destination to source */
>  enum mig_rp_message_type {
>      MIG_RP_MSG_INVALID = 0,  /* Must be 0 */
> @@ -275,19 +273,6 @@ static bool migrate_late_block_activate(void)
>          MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
>  }
>  
> -/*
> - * Called on -incoming with a defer: uri.
> - * The migration can be started later after any parameters have been
> - * changed.
> - */
> -static void deferred_incoming_migration(Error **errp)
> -{
> -    if (deferred_incoming) {
> -        error_setg(errp, "Incoming migration already deferred");
> -    }
> -    deferred_incoming = true;
> -}
> -
>  /*
>   * Send a message on the return channel back to the source
>   * of the migration.
> @@ -429,16 +414,14 @@ void migrate_add_address(SocketAddress *address)
>      addrs->value = QAPI_CLONE(SocketAddress, address);
>  }
>  
> -void qemu_start_incoming_migration(const char *uri, Error **errp)
> +static void qemu_start_incoming_migration(const char *uri, Error **errp)
>  {
>      const char *p = NULL;
>  
>      qapi_event_send_migration(MIGRATION_STATUS_SETUP);
> -    if (!strcmp(uri, "defer")) {
> -        deferred_incoming_migration(errp);
> -    } else if (strstart(uri, "tcp:", &p) ||
> -               strstart(uri, "unix:", NULL) ||
> -               strstart(uri, "vsock:", NULL)) {
> +    if (strstart(uri, "tcp:", &p) ||
> +        strstart(uri, "unix:", NULL) ||
> +        strstart(uri, "vsock:", NULL)) {
>          socket_start_incoming_migration(p ? p : uri, errp);
>  #ifdef CONFIG_RDMA
>      } else if (strstart(uri, "rdma:", &p)) {
> @@ -1988,14 +1971,14 @@ void qmp_migrate_incoming(const char *uri, Error **errp)
>      Error *local_err = NULL;
>      static bool once = true;
>  
> -    if (!deferred_incoming) {
> -        error_setg(errp, "For use with '-incoming defer'");
> -        return;
> -    }
>      if (!once) {
>          error_setg(errp, "The incoming migration has already been started");
>          return;
>      }
> +    if (!runstate_check(RUN_STATE_INMIGRATE)) {
> +        error_setg(errp, "'-incoming' was not specified on the command line");
> +        return;
> +    }
>  
>      qemu_start_incoming_migration(uri, &local_err);
>  
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index ccc3b8e838..d548c31ba0 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -109,6 +109,7 @@
>  #include "qapi/qapi-visit-block-core.h"
>  #include "qapi/qapi-visit-ui.h"
>  #include "qapi/qapi-commands-block-core.h"
> +#include "qapi/qapi-commands-migration.h"
>  #include "qapi/qapi-commands-run-state.h"
>  #include "qapi/qapi-commands-ui.h"
>  #include "qapi/qmp/qerror.h"
> @@ -4549,10 +4550,12 @@ void qemu_init(int argc, char **argv, char **envp)
>      }
>      if (incoming) {
>          Error *local_err = NULL;
> -        qemu_start_incoming_migration(incoming, &local_err);
> -        if (local_err) {
> -            error_reportf_err(local_err, "-incoming %s: ", incoming);
> -            exit(1);
> +        if (strcmp(incoming, "defer") != 0) {
> +            qmp_migrate_incoming(incoming, &local_err);
> +            if (local_err) {
> +                error_reportf_err(local_err, "-incoming %s: ", incoming);
> +                exit(1);
> +            }
>          }
>      } else if (autostart) {
>          vm_start();



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 26/36] remove preconfig state
  2020-11-23 14:14 ` [PATCH 26/36] remove preconfig state Paolo Bonzini
@ 2020-11-26 18:55   ` Igor Mammedov
  2020-11-27  5:19     ` Paolo Bonzini
  0 siblings, 1 reply; 70+ messages in thread
From: Igor Mammedov @ 2020-11-26 18:55 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:25 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> The preconfig state is only used if -incoming is not specified, which
> makes the RunState state machine more tricky than it need be.  However
> there is already an equivalent condition which works even with -incoming,
> namely qdev_hotplug.  Use it instead of a separate runstate.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/core/machine-qmp-cmds.c    |  5 ++---
>  include/qapi/qmp/dispatch.h   |  1 +
>  monitor/hmp.c                 |  7 ++++---
>  monitor/qmp-cmds.c            |  5 ++---
>  qapi/qmp-dispatch.c           |  5 +----
>  qapi/run-state.json           |  5 +----
>  softmmu/qdev-monitor.c        | 12 ++++++++++++
>  softmmu/vl.c                  | 13 ++-----------
>  stubs/meson.build             |  1 +
>  stubs/qmp-command-available.c |  7 +++++++
>  tests/qtest/qmp-test.c        |  2 +-
>  11 files changed, 34 insertions(+), 29 deletions(-)
>  create mode 100644 stubs/qmp-command-available.c
> 
> diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
> index 5362c80a18..cb9387c5f5 100644
> --- a/hw/core/machine-qmp-cmds.c
> +++ b/hw/core/machine-qmp-cmds.c
> @@ -286,9 +286,8 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
>  
>  void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
>  {
> -    if (!runstate_check(RUN_STATE_PRECONFIG)) {
> -        error_setg(errp, "The command is permitted only in '%s' state",
> -                   RunState_str(RUN_STATE_PRECONFIG));
> +    if (qdev_hotplug) {

that would work only as long as qemu_init_board() hasn't been called,
and fall apart as soon as we permit creating cold-pluged devices
(qemu_create_cli_devices()) at preconfig stage.

for qmp_set_numa_node() the better fit would something like
  if(is_board_created)
     error_out
so it won't break silently when we start extending list of
commands allowed at preconfig time.

> +         error_setg(errp, "The command is permitted only before the machine has been created");
>           return;
>      }
>  
> diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
> index af8d96c570..1486cac3ef 100644
> --- a/include/qapi/qmp/dispatch.h
> +++ b/include/qapi/qmp/dispatch.h
> @@ -48,6 +48,7 @@ void qmp_disable_command(QmpCommandList *cmds, const char *name);
>  void qmp_enable_command(QmpCommandList *cmds, const char *name);
>  
>  bool qmp_command_is_enabled(const QmpCommand *cmd);
> +bool qmp_command_available(const QmpCommand *cmd, Error **errp);
>  const char *qmp_command_name(const QmpCommand *cmd);
>  bool qmp_has_success_response(const QmpCommand *cmd);
>  QDict *qmp_error_response(Error *err);
> diff --git a/monitor/hmp.c b/monitor/hmp.c
> index d40f4f4391..f2fe192d69 100644
> --- a/monitor/hmp.c
> +++ b/monitor/hmp.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include <dirent.h>
> +#include "hw/qdev-core.h"
>  #include "monitor-internal.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qdict.h"
> @@ -215,7 +216,7 @@ static bool cmd_can_preconfig(const HMPCommand *cmd)
>  
>  static bool cmd_available(const HMPCommand *cmd)
>  {
> -    return !runstate_check(RUN_STATE_PRECONFIG) || cmd_can_preconfig(cmd);
> +    return qdev_hotplug || cmd_can_preconfig(cmd);
>  }
>  
>  static void help_cmd_dump_one(Monitor *mon,
> @@ -658,8 +659,8 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon,
>          return NULL;
>      }
>      if (!cmd_available(cmd)) {
> -        monitor_printf(mon, "Command '%.*s' not available with -preconfig "
> -                            "until after exit_preconfig.\n",
> +        monitor_printf(mon, "Command '%.*s' not available "
> +                            "until machine initialization has completed.\n",
>                         (int)(p - cmdp_start), cmdp_start);
>          return NULL;
>      }
> diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
> index 6299c0c8c7..501a3024c7 100644
> --- a/monitor/qmp-cmds.c
> +++ b/monitor/qmp-cmds.c
> @@ -104,9 +104,8 @@ void qmp_system_powerdown(Error **errp)
>  
>  void qmp_x_exit_preconfig(Error **errp)
>  {
> -    if (!runstate_check(RUN_STATE_PRECONFIG)) {
> -        error_setg(errp, "The command is permitted only in '%s' state",
> -                   RunState_str(RUN_STATE_PRECONFIG));
> +    if (qdev_hotplug) {
> +        error_setg(errp, "The command is permitted only before machine initialization");
>          return;
>      }
>      qemu_exit_preconfig_request();
> diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
> index 9a2d7dd29a..0a2b20a4e4 100644
> --- a/qapi/qmp-dispatch.c
> +++ b/qapi/qmp-dispatch.c
> @@ -167,10 +167,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
>          goto out;
>      }
>  
> -    if (runstate_check(RUN_STATE_PRECONFIG) &&
> -        !(cmd->options & QCO_ALLOW_PRECONFIG)) {
> -        error_setg(&err, "The command '%s' isn't permitted in '%s' state",
> -                   cmd->name, RunState_str(RUN_STATE_PRECONFIG));
> +    if (!qmp_command_available(cmd, &err)) {
>          goto out;
>      }
>  
> diff --git a/qapi/run-state.json b/qapi/run-state.json
> index 964c8ef391..38194b0e44 100644
> --- a/qapi/run-state.json
> +++ b/qapi/run-state.json
> @@ -50,15 +50,12 @@
>  # @colo: guest is paused to save/restore VM state under colo checkpoint,
>  #        VM can not get into this state unless colo capability is enabled
>  #        for migration. (since 2.8)
> -# @preconfig: QEMU is paused before board specific init callback is executed.
> -#             The state is reachable only if the --preconfig CLI option is used.
> -#             (Since 3.0)
>  ##
>  { 'enum': 'RunState',
>    'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
>              'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
>              'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
> -            'guest-panicked', 'colo', 'preconfig' ] }
> +            'guest-panicked', 'colo' ] }
>  
>  ##
>  # @ShutdownCause:
> diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
> index d060e765da..e967d13bd0 100644
> --- a/softmmu/qdev-monitor.c
> +++ b/softmmu/qdev-monitor.c
> @@ -25,6 +25,7 @@
>  #include "sysemu/arch_init.h"
>  #include "qapi/error.h"
>  #include "qapi/qapi-commands-qdev.h"
> +#include "qapi/qmp/dispatch.h"
>  #include "qapi/qmp/qdict.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/config-file.h"
> @@ -997,3 +998,14 @@ int qemu_global_option(const char *str)
>  
>      return 0;
>  }
> +
> +bool qmp_command_available(const QmpCommand *cmd, Error **errp)
> +{
> +    if (!qdev_hotplug &&
> +        !(cmd->options & QCO_ALLOW_PRECONFIG)) {
> +        error_setg(errp, "The command '%s' is permitted only after machine initialization has completed",
> +                   cmd->name);
> +        return false;
> +    }
> +    return true;
> +}
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index ecfe16c4c4..95c62bdad4 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -573,7 +573,7 @@ static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp)
>  /***********************************************************/
>  /* QEMU state */
>  
> -static RunState current_run_state = RUN_STATE_PRECONFIG;
> +static RunState current_run_state = RUN_STATE_PRELAUNCH;
>  
>  /* We use RUN_STATE__MAX but any invalid value will do */
>  static RunState vmstop_requested = RUN_STATE__MAX;
> @@ -585,13 +585,7 @@ typedef struct {
>  } RunStateTransition;
>  
>  static const RunStateTransition runstate_transitions_def[] = {
> -    /*     from      ->     to      */
> -    { RUN_STATE_PRECONFIG, RUN_STATE_PRELAUNCH },
> -      /* Early switch to inmigrate state to allow  -incoming CLI option work
> -       * as it used to. TODO: delay actual switching to inmigrate state to
> -       * the point after machine is built and remove this hack.
> -       */
> -    { RUN_STATE_PRECONFIG, RUN_STATE_INMIGRATE },
> +    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
>  
>      { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
>      { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
> @@ -1633,9 +1627,6 @@ static bool main_loop_should_exit(void)
>      ShutdownCause request;
>  
>      if (preconfig_exit_requested) {
> -        if (runstate_check(RUN_STATE_PRECONFIG)) {
> -            runstate_set(RUN_STATE_PRELAUNCH);
> -        }
>          preconfig_exit_requested = false;
>          return true;
>      }
> diff --git a/stubs/meson.build b/stubs/meson.build
> index 82b7ba60ab..cc56c83063 100644
> --- a/stubs/meson.build
> +++ b/stubs/meson.build
> @@ -29,6 +29,7 @@ stub_ss.add(files('pci-bus.c'))
>  stub_ss.add(files('pci-host-piix.c'))
>  stub_ss.add(files('qemu-timer-notify-cb.c'))
>  stub_ss.add(files('qmp_memory_device.c'))
> +stub_ss.add(files('qmp-command-available.c'))
>  stub_ss.add(files('qtest.c'))
>  stub_ss.add(files('ram-block.c'))
>  stub_ss.add(files('ramfb.c'))
> diff --git a/stubs/qmp-command-available.c b/stubs/qmp-command-available.c
> new file mode 100644
> index 0000000000..46540af7bf
> --- /dev/null
> +++ b/stubs/qmp-command-available.c
> @@ -0,0 +1,7 @@
> +#include "qemu/osdep.h"
> +#include "qapi/qmp/dispatch.h"
> +
> +bool qmp_command_available(const QmpCommand *cmd, Error **errp)
> +{
> +    return true;
> +}
> diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c
> index eb1cd8abb8..11614bf63f 100644
> --- a/tests/qtest/qmp-test.c
> +++ b/tests/qtest/qmp-test.c
> @@ -295,7 +295,7 @@ static void test_qmp_preconfig(void)
>      rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }");
>      ret = qdict_get_qdict(rsp, "return");
>      g_assert(ret);
> -    g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "preconfig");
> +    g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "prelaunch");
>      qobject_unref(rsp);
>  
>      /* exit preconfig state */



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board
  2020-11-26 17:10   ` Igor Mammedov
@ 2020-11-27  5:03     ` Paolo Bonzini
  2020-11-27 10:31       ` Igor Mammedov
  0 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-27  5:03 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On 26/11/20 18:10, Igor Mammedov wrote:
> On Mon, 23 Nov 2020 09:14:12 -0500
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
>> Move more sane parts of the huge qemu_init function out of it.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>>   softmmu/vl.c | 12 +++++-------
>>   1 file changed, 5 insertions(+), 7 deletions(-)
>>
>> diff --git a/softmmu/vl.c b/softmmu/vl.c
>> index ab08a0290c..5d68cf828c 100644
>> --- a/softmmu/vl.c
>> +++ b/softmmu/vl.c
>> @@ -3070,6 +3070,11 @@ static void qemu_init_board(void)
>>   {
>>       MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
>>   
>> +    if (semihosting_enabled() && !semihosting_get_argc() && current_machine->kernel_filename) {
>> +        /* fall back to the -kernel/-append */
>> +        semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline);
>> +    }
> 
> it doesn't seem to depend on anything that warrants calling it this late.

Yes, calling it around machine initialization time is also a 
possibility.  I just wanted to get rid of it in code that I'm actually 
looking at. :)

Paolo

> 
>>       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);
>> @@ -4385,13 +4390,6 @@ void qemu_init(int argc, char **argv, char **envp)
>>           boot_order = machine_class->default_boot_order;
>>       }
>>   
>> -    if (semihosting_enabled() && !semihosting_get_argc()) {
>> -        const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
>> -        const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
>> -        /* fall back to the -kernel/-append */
>> -        semihosting_arg_fallback(kernel_filename, kernel_cmdline);
>> -    }
> 
> Can we move this hunk as is to somewhere around qemu_maybe_daemonize() time?
> 
> 
>>       if (net_init_clients(&err) < 0) {
>>           error_report_err(err);
>>           exit(1);
> 



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 26/36] remove preconfig state
  2020-11-26 18:55   ` Igor Mammedov
@ 2020-11-27  5:19     ` Paolo Bonzini
  2020-11-27 10:50       ` Igor Mammedov
  0 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-27  5:19 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On 26/11/20 19:55, Igor Mammedov wrote:
> On Mon, 23 Nov 2020 09:14:25 -0500
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
>> The preconfig state is only used if -incoming is not specified, which
>> makes the RunState state machine more tricky than it need be.  However
>> there is already an equivalent condition which works even with -incoming,
>> namely qdev_hotplug.  Use it instead of a separate runstate.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>>   hw/core/machine-qmp-cmds.c    |  5 ++---
>>   include/qapi/qmp/dispatch.h   |  1 +
>>   monitor/hmp.c                 |  7 ++++---
>>   monitor/qmp-cmds.c            |  5 ++---
>>   qapi/qmp-dispatch.c           |  5 +----
>>   qapi/run-state.json           |  5 +----
>>   softmmu/qdev-monitor.c        | 12 ++++++++++++
>>   softmmu/vl.c                  | 13 ++-----------
>>   stubs/meson.build             |  1 +
>>   stubs/qmp-command-available.c |  7 +++++++
>>   tests/qtest/qmp-test.c        |  2 +-
>>   11 files changed, 34 insertions(+), 29 deletions(-)
>>   create mode 100644 stubs/qmp-command-available.c
>>
>> diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
>> index 5362c80a18..cb9387c5f5 100644
>> --- a/hw/core/machine-qmp-cmds.c
>> +++ b/hw/core/machine-qmp-cmds.c
>> @@ -286,9 +286,8 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
>>   
>>   void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
>>   {
>> -    if (!runstate_check(RUN_STATE_PRECONFIG)) {
>> -        error_setg(errp, "The command is permitted only in '%s' state",
>> -                   RunState_str(RUN_STATE_PRECONFIG));
>> +    if (qdev_hotplug) {
> 
> that would work only as long as qemu_init_board() hasn't been called,
> and fall apart as soon as we permit creating cold-pluged devices
> (qemu_create_cli_devices()) at preconfig stage.
> 
> for qmp_set_numa_node() the better fit would something like
>    if(is_board_created)
>       error_out
> so it won't break silently when we start extending list of
> commands allowed at preconfig time.
> 
>> +         error_setg(errp, "The command is permitted only before the machine has been created");
>>            return;
>>       }

I don't understand...  qdev_hotplug is a bad name for is_board_created, 
it is set by qdev_machine_creation_done which is called after preconfig 
is left.  As of this patch that happens after the early 
qemu_main_loop(); the next patch moves it to qmp_x_exit_preconfig.

Cold-plugged devices would (by definition) be created while qdev_hotplug 
is false.  But before we get there, I will have replaced the two states 
permitted by qdev_hotplug with five separate phases (PHASE_NO_MACHINE, 
PHASE_MACHINE_CREATED, PHASE_ACCEL_CREATED, PHASE_MACHINE_INITIALIZED, 
PHASE_MACHINE_READY) to clarify the QMP command implementation and to 
assert that various functions are called in the right phase.

Thanks,

Paolo



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board
  2020-11-27  5:03     ` Paolo Bonzini
@ 2020-11-27 10:31       ` Igor Mammedov
  2020-11-27 11:22         ` Paolo Bonzini
  0 siblings, 1 reply; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 10:31 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Fri, 27 Nov 2020 06:03:43 +0100
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 26/11/20 18:10, Igor Mammedov wrote:
> > On Mon, 23 Nov 2020 09:14:12 -0500
> > Paolo Bonzini <pbonzini@redhat.com> wrote:
> >   
> >> Move more sane parts of the huge qemu_init function out of it.
> >>
> >> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> >> ---
> >>   softmmu/vl.c | 12 +++++-------
> >>   1 file changed, 5 insertions(+), 7 deletions(-)
> >>
> >> diff --git a/softmmu/vl.c b/softmmu/vl.c
> >> index ab08a0290c..5d68cf828c 100644
> >> --- a/softmmu/vl.c
> >> +++ b/softmmu/vl.c
> >> @@ -3070,6 +3070,11 @@ static void qemu_init_board(void)
> >>   {
> >>       MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
> >>   
> >> +    if (semihosting_enabled() && !semihosting_get_argc() && current_machine->kernel_filename) {
> >> +        /* fall back to the -kernel/-append */
> >> +        semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline);
> >> +    }  
> > 
> > it doesn't seem to depend on anything that warrants calling it this late.  
> 
> Yes, calling it around machine initialization time is also a 
> possibility.  I just wanted to get rid of it in code that I'm actually 
> looking at. :)

I'd prefer it being moved close to CLI parsing,
in a place where other _early call go.

We probably want qemu_init_board() being clear of not really needed clutter.

> 
> Paolo
> 
> >   
> >>       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);
> >> @@ -4385,13 +4390,6 @@ void qemu_init(int argc, char **argv, char **envp)
> >>           boot_order = machine_class->default_boot_order;
> >>       }
> >>   
> >> -    if (semihosting_enabled() && !semihosting_get_argc()) {
> >> -        const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
> >> -        const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
> >> -        /* fall back to the -kernel/-append */
> >> -        semihosting_arg_fallback(kernel_filename, kernel_cmdline);
> >> -    }  
> > 
> > Can we move this hunk as is to somewhere around qemu_maybe_daemonize() time?
> > 
> >   
> >>       if (net_init_clients(&err) < 0) {
> >>           error_report_err(err);
> >>           exit(1);  
> >   
> 



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 26/36] remove preconfig state
  2020-11-27  5:19     ` Paolo Bonzini
@ 2020-11-27 10:50       ` Igor Mammedov
  2020-11-27 11:50         ` Paolo Bonzini
  0 siblings, 1 reply; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 10:50 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Fri, 27 Nov 2020 06:19:51 +0100
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 26/11/20 19:55, Igor Mammedov wrote:
> > On Mon, 23 Nov 2020 09:14:25 -0500
> > Paolo Bonzini <pbonzini@redhat.com> wrote:
> >   
> >> The preconfig state is only used if -incoming is not specified, which
> >> makes the RunState state machine more tricky than it need be.  However
> >> there is already an equivalent condition which works even with -incoming,
> >> namely qdev_hotplug.  Use it instead of a separate runstate.
> >>
> >> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> >> ---
> >>   hw/core/machine-qmp-cmds.c    |  5 ++---
> >>   include/qapi/qmp/dispatch.h   |  1 +
> >>   monitor/hmp.c                 |  7 ++++---
> >>   monitor/qmp-cmds.c            |  5 ++---
> >>   qapi/qmp-dispatch.c           |  5 +----
> >>   qapi/run-state.json           |  5 +----
> >>   softmmu/qdev-monitor.c        | 12 ++++++++++++
> >>   softmmu/vl.c                  | 13 ++-----------
> >>   stubs/meson.build             |  1 +
> >>   stubs/qmp-command-available.c |  7 +++++++
> >>   tests/qtest/qmp-test.c        |  2 +-
> >>   11 files changed, 34 insertions(+), 29 deletions(-)
> >>   create mode 100644 stubs/qmp-command-available.c
> >>
> >> diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
> >> index 5362c80a18..cb9387c5f5 100644
> >> --- a/hw/core/machine-qmp-cmds.c
> >> +++ b/hw/core/machine-qmp-cmds.c
> >> @@ -286,9 +286,8 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
> >>   
> >>   void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
> >>   {
> >> -    if (!runstate_check(RUN_STATE_PRECONFIG)) {
> >> -        error_setg(errp, "The command is permitted only in '%s' state",
> >> -                   RunState_str(RUN_STATE_PRECONFIG));
> >> +    if (qdev_hotplug) {  
> > 
> > that would work only as long as qemu_init_board() hasn't been called,
> > and fall apart as soon as we permit creating cold-pluged devices
> > (qemu_create_cli_devices()) at preconfig stage.
> > 
> > for qmp_set_numa_node() the better fit would something like
> >    if(is_board_created)
> >       error_out
> > so it won't break silently when we start extending list of
> > commands allowed at preconfig time.
> >   
> >> +         error_setg(errp, "The command is permitted only before the machine has been created");
> >>            return;
> >>       }  
> 
> I don't understand...  qdev_hotplug is a bad name for is_board_created, 
> it is set by qdev_machine_creation_done which is called after preconfig 
> is left.  As of this patch that happens after the early 
> qemu_main_loop(); the next patch moves it to qmp_x_exit_preconfig.
it works in context of this series since

  +    qemu_init_board();
  +    qemu_create_cli_devices();
  +    qemu_machine_creation_done();

are called within the same command qmp_x_exit_preconfig, 
if preconfig is enabled we happen to call qmp_set_numa_node()
and if (qdev_hotplug) {error} work as expected, since qemu_init_board()
hasn't been called yet.

but I'm thinking about what happens beyond this series, when we start
splitting qmp_x_exit_preconfig() after this series on separate stages.

By using qdev_hotplug here, we practically loose dependency tracking
on qemu_init_board() not being yet called. And if later we forget that,
then it would allow to call qmp_set_numa_node() after qemu_init_board()
but before qemu_machine_creation_done()

So for this intermediate stage, instead of abusing qdev_hotplug adding
a temporary is_board_created might be used. And when we introduce
new phases you've described below, is_board_created could be replaced
with appropriate phase check.


> Cold-plugged devices would (by definition) be created while qdev_hotplug 
> is false.  But before we get there, I will have replaced the two states 
> permitted by qdev_hotplug with five separate phases (PHASE_NO_MACHINE, 
> PHASE_MACHINE_CREATED, PHASE_ACCEL_CREATED, PHASE_MACHINE_INITIALIZED, 
> PHASE_MACHINE_READY) to clarify the QMP command implementation and to 
> assert that various functions are called in the right phase.
> 
> Thanks,
> 
> Paolo
> 



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 28/36] vl: allow -incoming defer with -preconfig
  2020-11-23 14:14 ` [PATCH 28/36] vl: allow -incoming defer with -preconfig Paolo Bonzini
@ 2020-11-27 10:51   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 10:51 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:27 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Now that there is no RUN_STATE_PRECONFIG anymore that can conflict with
> RUN_STATE_INMIGRATE, we can allow -incoming defer with -preconfig.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  softmmu/vl.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index aa11fc4871..0ba1fcdb3d 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -3200,9 +3200,8 @@ static void qemu_validate_options(void)
>                       "mutually exclusive");
>          exit(EXIT_FAILURE);
>      }
> -    if (incoming && preconfig_requested) {
> -        error_report("'preconfig' and 'incoming' options are "
> -                     "mutually exclusive");
> +    if (incoming && preconfig_requested && strcmp(incoming, "defer") != 0) {
> +        error_report("'preconfig' supports '-incoming defer' only");
>          exit(EXIT_FAILURE);
>      }
>  



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board
  2020-11-27 10:31       ` Igor Mammedov
@ 2020-11-27 11:22         ` Paolo Bonzini
  2020-11-27 12:12           ` Igor Mammedov
  0 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-27 11:22 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On 27/11/20 11:31, Igor Mammedov wrote:
>> Yes, calling it around machine initialization time is also a
>> possibility.  I just wanted to get rid of it in code that I'm actually
>> looking at.:)
> I'd prefer it being moved close to CLI parsing,
> in a place where other _early call go.
> 
> We probably want qemu_init_board() being clear of not really needed clutter.
> 

Fair enough, I'd put -semihosting-config in the same bucket as 
-m/-boot/-smp (machine configuration that isn't in -M) so I'll move it 
together with them.

Paolo



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 26/36] remove preconfig state
  2020-11-27 10:50       ` Igor Mammedov
@ 2020-11-27 11:50         ` Paolo Bonzini
  2020-11-30 12:41           ` Igor Mammedov
  0 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-27 11:50 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On 27/11/20 11:50, Igor Mammedov wrote:
> it works in context of this series since
> 
>    +    qemu_init_board();
>    +    qemu_create_cli_devices();
>    +    qemu_machine_creation_done();
> 
> are called within the same command qmp_x_exit_preconfig,
> if preconfig is enabled we happen to call qmp_set_numa_node()
> and if (qdev_hotplug) {error} work as expected, since qemu_init_board()
> hasn't been called yet.
> 
> but I'm thinking about what happens beyond this series, when we start
> splitting qmp_x_exit_preconfig() after this series on separate stages.

Ok, so that's the source of confusion.  I don't think anymore that 
x-exit-preconfig should be split in separate stages; I'm not looking 
anymore at being able to do device-add from "qemu-system-x86_64 
-preconfig".  Instead, I'm looking at having a completely separate 
executable for QMP-only machine creation, which would not use vl.c 
command line parsing at all.

For this reason I've left MachinePhase to a separate series, which I 
still plan for 6.0.  But I will add it here instead.

FWIW I intend to have four parts: 1) this 2) QemuOpts->keyval switch for 
-object/-M/-accel 3) making Machine's memdev property a 
link<memory-backend> 4) making -smp/-boot/-m sugar for non-scalar 
properties of Machine.  I'll definitely need your review on part 3 too!

Thanks,

Paolo

> By using qdev_hotplug here, we practically loose dependency tracking
> on qemu_init_board() not being yet called. And if later we forget that,
> then it would allow to call qmp_set_numa_node() after qemu_init_board()
> but before qemu_machine_creation_done()
> 
> So for this intermediate stage, instead of abusing qdev_hotplug adding
> a temporary is_board_created might be used. And when we introduce
> new phases you've described below, is_board_created could be replaced
> with appropriate phase check.



^ permalink raw reply	[flat|nested] 70+ messages in thread

* [PATCH 37/36] machine: introduce MachineInitPhase
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (35 preceding siblings ...)
  2020-11-23 14:14 ` [PATCH 36/36] vl: move all generic initialization out of vl.c Paolo Bonzini
@ 2020-11-27 12:00 ` Paolo Bonzini
  2020-11-27 13:29   ` Igor Mammedov
  2020-11-30 12:50 ` [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Igor Mammedov
  37 siblings, 1 reply; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-27 12:00 UTC (permalink / raw)
  To: qemu-devel; +Cc: imammedo

Generalize the qdev_hotplug variable to the different phases of
machine initialization.  We would like to allow different
monitor commands depending on the phase.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
	This has to be the last patch because patch 36 is where
	hw/core/machine.c takes care of setting qdev_hotplug to true.

	And this explains the weird [PATCH 00/37] in the previous
	version of the RFC. :)

 hw/core/machine-qmp-cmds.c |  6 +++---
 hw/core/machine.c          |  3 ++-
 hw/core/qdev.c             | 16 ++++++++++++++--
 hw/pci/pci.c               |  2 +-
 hw/usb/core.c              |  2 +-
 hw/virtio/virtio-iommu.c   |  2 +-
 include/hw/qdev-core.h     | 12 +++++++++++-
 monitor/hmp.c              |  2 +-
 softmmu/qdev-monitor.c     | 24 +++++++++++++-----------
 softmmu/vl.c               |  4 +++-
 ui/console.c               |  2 +-
 11 files changed, 51 insertions(+), 24 deletions(-)

diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index cb9387c5f5..6cbeb688c4 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -286,9 +286,9 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
 
 void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
 {
-    if (qdev_hotplug) {
-         error_setg(errp, "The command is permitted only before the machine has been created");
-         return;
+    if (phase_check(PHASE_MACHINE_READY)) {
+        error_setg(errp, "The command is permitted only before the machine has been created");
+        return;
     }
 
     set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 025c4f9749..a71cb23ecf 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -1171,6 +1171,7 @@ void machine_run_board_init(MachineState *machine)
     }
 
     machine_class->init(machine);
+    phase_advance(PHASE_MACHINE_INITIALIZED);
 }
 
 static NotifierList machine_init_done_notifiers =
@@ -1204,7 +1205,7 @@ void qdev_machine_creation_done(void)
      * ok, initial machine setup is done, starting from now we can
      * only create hotpluggable devices
      */
-    qdev_hotplug = true;
+    phase_advance(PHASE_MACHINE_READY);
     qdev_assert_realized_properly();
 
     /* TODO: once all bus devices are qdevified, this should be done
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index bc5df8ce69..beb35879c6 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -41,7 +41,6 @@
 #include "migration/vmstate.h"
 #include "trace.h"
 
-bool qdev_hotplug = false;
 static bool qdev_hot_added = false;
 bool qdev_hot_removed = false;
 
@@ -1023,7 +1022,7 @@ static void device_initfn(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
 
-    if (qdev_hotplug) {
+    if (phase_check(PHASE_MACHINE_READY)) {
         dev->hotplugged = 1;
         qdev_hot_added = true;
     }
@@ -1267,6 +1266,19 @@ Object *qdev_get_machine(void)
     return dev;
 }
 
+static MachineInitPhase machine_phase;
+
+bool phase_check(MachineInitPhase phase)
+{
+    return machine_phase >= phase;
+}
+
+void phase_advance(MachineInitPhase phase)
+{
+    assert(machine_phase == phase - 1);
+    machine_phase = phase;
+}
+
 static const TypeInfo device_type_info = {
     .name = TYPE_DEVICE,
     .parent = TYPE_OBJECT,
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 9424231542..d4349ea577 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1062,7 +1062,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
     address_space_init(&pci_dev->bus_master_as,
                        &pci_dev->bus_master_container_region, pci_dev->name);
 
-    if (qdev_hotplug) {
+    if (phase_check(PHASE_MACHINE_READY)) {
         pci_init_bus_master(pci_dev);
     }
     pci_dev->irq_state = 0;
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 5234dcc73f..e960036f4d 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -97,7 +97,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
     USBDevice *dev = ep->dev;
     USBBus *bus = usb_bus_from_device(dev);
 
-    if (!qdev_hotplug) {
+    if (!phase_check(PHASE_MACHINE_READY)) {
         /*
          * This is machine init cold plug.  No need to wakeup anyone,
          * all devices will be reset anyway.  And trying to wakeup can
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index fc5c75d693..8370fd80d7 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -928,7 +928,7 @@ static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
      * accept it. Having a different masks is possible but the guest will use
      * sub-optimal block sizes, so warn about it.
      */
-    if (qdev_hotplug) {
+    if (phase_check(PHASE_MACHINE_READY)) {
         int new_granule = ctz64(new_mask);
         int cur_granule = ctz64(cur_mask);
 
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 6446846752..05e7e7bc45 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -821,7 +821,6 @@ Object *qdev_get_machine(void);
 /* FIXME: make this a link<> */
 bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
 
-extern bool qdev_hotplug;
 extern bool qdev_hot_removed;
 
 char *qdev_get_dev_path(DeviceState *dev);
@@ -847,4 +846,15 @@ void device_listener_unregister(DeviceListener *listener);
  */
 bool qdev_should_hide_device(QemuOpts *opts);
 
+typedef enum MachineInitPhase {
+    PHASE_NO_MACHINE,
+    PHASE_MACHINE_CREATED,
+    PHASE_ACCEL_CREATED,
+    PHASE_MACHINE_INITIALIZED,
+    PHASE_MACHINE_READY,
+} MachineInitPhase;
+
+extern bool phase_check(MachineInitPhase phase);
+extern void phase_advance(MachineInitPhase phase);
+
 #endif
diff --git a/monitor/hmp.c b/monitor/hmp.c
index f2fe192d69..6c0b33a0b1 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -216,7 +216,7 @@ static bool cmd_can_preconfig(const HMPCommand *cmd)
 
 static bool cmd_available(const HMPCommand *cmd)
 {
-    return qdev_hotplug || cmd_can_preconfig(cmd);
+    return phase_check(PHASE_MACHINE_READY) || cmd_can_preconfig(cmd);
 }
 
 static void help_cmd_dump_one(Monitor *mon,
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index e967d13bd0..184fe317af 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -244,7 +244,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
 
     dc = DEVICE_CLASS(oc);
     if (!dc->user_creatable ||
-        (qdev_hotplug && !dc->hotpluggable)) {
+        (phase_check(PHASE_MACHINE_READY) && !dc->hotpluggable)) {
         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
                    "pluggable device type");
         return NULL;
@@ -637,7 +637,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
     }
     hide = should_hide_device(opts);
 
-    if ((hide || qdev_hotplug) && bus && !qbus_is_hotpluggable(bus)) {
+    if ((hide || phase_check(PHASE_MACHINE_READY)) && bus && !qbus_is_hotpluggable(bus)) {
         error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name);
         return NULL;
     }
@@ -655,15 +655,17 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
     dev = qdev_new(driver);
 
     /* Check whether the hotplug is allowed by the machine */
-    if (qdev_hotplug && !qdev_hotplug_allowed(dev, errp)) {
-        goto err_del_dev;
-    }
+    if (phase_check(PHASE_MACHINE_READY)) {
+        if (!qdev_hotplug_allowed(dev, errp)) {
+            goto err_del_dev;
+        }
 
-    if (!bus && qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
-        /* No bus, no machine hotplug handler --> device is not hotpluggable */
-        error_setg(errp, "Device '%s' can not be hotplugged on this machine",
-                   driver);
-        goto err_del_dev;
+        if (!bus && !qdev_get_machine_hotplug_handler(dev)) {
+            /* No bus, no machine hotplug handler --> device is not hotpluggable */
+            error_setg(errp, "Device '%s' can not be hotplugged on this machine",
+                       driver);
+            goto err_del_dev;
+        }
     }
 
     qdev_set_id(dev, qemu_opts_id(opts));
@@ -1001,7 +1003,7 @@ int qemu_global_option(const char *str)
 
 bool qmp_command_available(const QmpCommand *cmd, Error **errp)
 {
-    if (!qdev_hotplug &&
+    if (!phase_check(PHASE_MACHINE_READY) &&
         !(cmd->options & QCO_ALLOW_PRECONFIG)) {
         error_setg(errp, "The command '%s' is permitted only after machine initialization has completed",
                    cmd->name);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 1fde4a17a9..2dd5c2c775 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2451,7 +2451,7 @@ static void qemu_machine_creation_done(void)
 
 void qmp_x_exit_preconfig(Error **errp)
 {
-    if (qdev_hotplug) {
+    if (phase_check(PHASE_MACHINE_READY)) {
         error_setg(errp, "The command is permitted only before machine initialization");
         return;
     }
@@ -3428,12 +3428,14 @@ void qemu_init(int argc, char **argv, char **envp)
     qemu_create_early_backends();
 
     qemu_apply_machine_options();
+    phase_advance(PHASE_MACHINE_CREATED);
 
     /*
      * Note: uses machine properties such as kernel-irqchip, must run
      * after machine_set_property().
      */
     configure_accelerators(argv[0]);
+    phase_advance(PHASE_ACCEL_CREATED);
 
     /*
      * Beware, QOM objects created before this point miss global and
diff --git a/ui/console.c b/ui/console.c
index e07d2c380d..3a98135daa 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1343,7 +1343,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
     if (QTAILQ_EMPTY(&consoles)) {
         s->index = 0;
         QTAILQ_INSERT_TAIL(&consoles, s, next);
-    } else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
+    } else if (console_type != GRAPHIC_CONSOLE || phase_check(PHASE_MACHINE_READY)) {
         QemuConsole *last = QTAILQ_LAST(&consoles);
         s->index = last->index + 1;
         QTAILQ_INSERT_TAIL(&consoles, s, next);
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 70+ messages in thread

* Re: [PATCH 29/36] vl: extract softmmu/datadir.c
  2020-11-23 14:14 ` [PATCH 29/36] vl: extract softmmu/datadir.c Paolo Bonzini
@ 2020-11-27 12:06   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 12:06 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:28 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>


> ---
>  hw/alpha/dp264.c        |   1 +
>  hw/arm/boot.c           |   1 +
>  hw/arm/digic_boards.c   |   1 +
>  hw/arm/highbank.c       |   1 +
>  hw/arm/npcm7xx_boards.c |   1 +
>  hw/arm/sbsa-ref.c       |   1 +
>  hw/arm/vexpress.c       |   1 +
>  hw/arm/virt.c           |   1 +
>  hw/avr/boot.c           |   1 +
>  hw/core/loader.c        |   1 +
>  hw/display/cg3.c        |   1 +
>  hw/display/tcx.c        |   1 +
>  hw/hppa/machine.c       |   1 +
>  hw/i386/x86.c           |   1 +
>  hw/lm32/milkymist.c     |   1 +
>  hw/m68k/mcf5208.c       |   1 +
>  hw/m68k/q800.c          |   1 +
>  hw/microblaze/boot.c    |   1 +
>  hw/mips/fuloong2e.c     |   1 +
>  hw/mips/jazz.c          |   1 +
>  hw/mips/malta.c         |   1 +
>  hw/mips/mipssim.c       |   1 +
>  hw/nios2/boot.c         |   1 +
>  hw/nvram/fw_cfg.c       |   1 +
>  hw/pci-host/prep.c      |   1 +
>  hw/pci/pci.c            |   1 +
>  hw/ppc/e500.c           |   1 +
>  hw/ppc/mac_newworld.c   |   1 +
>  hw/ppc/mac_oldworld.c   |   1 +
>  hw/ppc/pnv.c            |   1 +
>  hw/ppc/ppc405_boards.c  |   1 +
>  hw/ppc/ppc440_bamboo.c  |   1 +
>  hw/ppc/sam460ex.c       |   1 +
>  hw/ppc/spapr.c          |   1 +
>  hw/ppc/virtex_ml507.c   |   1 +
>  hw/riscv/boot.c         |   1 +
>  hw/s390x/ipl.c          |   1 +
>  hw/sparc/leon3.c        |   1 +
>  hw/sparc/sun4m.c        |   1 +
>  hw/sparc64/sun4u.c      |   1 +
>  include/qemu-common.h   |  21 -------
>  include/qemu/datadir.h  |  28 +++++++++
>  include/sysemu/sysemu.h |   2 -
>  softmmu/datadir.c       | 129 ++++++++++++++++++++++++++++++++++++++++
>  softmmu/meson.build     |   1 +
>  softmmu/vl.c            |  95 +----------------------------
>  tests/qtest/fuzz/fuzz.c |   1 +
>  ui/keymaps.c            |   1 +
>  48 files changed, 203 insertions(+), 115 deletions(-)
>  create mode 100644 include/qemu/datadir.h
>  create mode 100644 softmmu/datadir.c
> 
> diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
> index c4d407a9f1..c8e300d93f 100644
> --- a/hw/alpha/dp264.c
> +++ b/hw/alpha/dp264.c
> @@ -21,6 +21,7 @@
>  #include "hw/dma/i8257.h"
>  #include "net/net.h"
>  #include "qemu/cutils.h"
> +#include "qemu/datadir.h"
>  #include "net/net.h"
>  
>  #define MAX_IDE_BUS 2
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index cf97600a91..4d9d47ba1c 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -9,6 +9,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include <libfdt.h>
> diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
> index fd228fa96f..be12873673 100644
> --- a/hw/arm/digic_boards.c
> +++ b/hw/arm/digic_boards.c
> @@ -26,6 +26,7 @@
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/boards.h"
>  #include "exec/address-spaces.h"
> diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
> index fd3429720e..bf7b8f4c64 100644
> --- a/hw/arm/highbank.c
> +++ b/hw/arm/highbank.c
> @@ -19,6 +19,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "hw/sysbus.h"
>  #include "migration/vmstate.h"
> diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
> index 9821013bc6..306260fa67 100644
> --- a/hw/arm/npcm7xx_boards.c
> +++ b/hw/arm/npcm7xx_boards.c
> @@ -23,6 +23,7 @@
>  #include "hw/qdev-properties.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "sysemu/sysemu.h"
>  
> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
> index c3a31f5b8b..b1fa3779d8 100644
> --- a/hw/arm/sbsa-ref.c
> +++ b/hw/arm/sbsa-ref.c
> @@ -19,6 +19,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "qemu/error-report.h"
>  #include "qemu/units.h"
> diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
> index 1adb663d77..ac098375c1 100644
> --- a/hw/arm/vexpress.c
> +++ b/hw/arm/vexpress.c
> @@ -24,6 +24,7 @@
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/sysbus.h"
>  #include "hw/arm/boot.h"
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 9c54eea585..82cb9c95cf 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -30,6 +30,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "qemu/option.h"
>  #include "monitor/qdev.h"
> diff --git a/hw/avr/boot.c b/hw/avr/boot.c
> index d16bb3dbe1..cbede775ce 100644
> --- a/hw/avr/boot.c
> +++ b/hw/avr/boot.c
> @@ -10,6 +10,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "hw/loader.h"
>  #include "elf.h"
>  #include "boot.h"
> diff --git a/hw/core/loader.c b/hw/core/loader.c
> index 8bbb1797a4..fea22d265c 100644
> --- a/hw/core/loader.c
> +++ b/hw/core/loader.c
> @@ -44,6 +44,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "trace.h"
>  #include "hw/hw.h"
> diff --git a/hw/display/cg3.c b/hw/display/cg3.c
> index 42fcf40010..4b7e78d919 100644
> --- a/hw/display/cg3.c
> +++ b/hw/display/cg3.c
> @@ -25,6 +25,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "qemu/error-report.h"
>  #include "ui/console.h"
> diff --git a/hw/display/tcx.c b/hw/display/tcx.c
> index 3799d29b75..965f92ff6b 100644
> --- a/hw/display/tcx.c
> +++ b/hw/display/tcx.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "ui/console.h"
>  #include "ui/pixel_ops.h"
> diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
> index 7e41cb2462..f2b71db9bd 100644
> --- a/hw/hppa/machine.c
> +++ b/hw/hppa/machine.c
> @@ -5,6 +5,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "elf.h"
>  #include "hw/loader.h"
> diff --git a/hw/i386/x86.c b/hw/i386/x86.c
> index 836d388248..f3a2425f37 100644
> --- a/hw/i386/x86.c
> +++ b/hw/i386/x86.c
> @@ -26,6 +26,7 @@
>  #include "qemu/cutils.h"
>  #include "qemu/units.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qapi/qapi-visit-common.h"
> diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
> index 93ca8bc2ac..72d1326531 100644
> --- a/hw/lm32/milkymist.c
> +++ b/hw/lm32/milkymist.c
> @@ -21,6 +21,7 @@
>  #include "qemu/units.h"
>  #include "qemu/error-report.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/sysbus.h"
>  #include "hw/irq.h"
> diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
> index 2205145ecc..7a03c71059 100644
> --- a/hw/m68k/mcf5208.c
> +++ b/hw/m68k/mcf5208.c
> @@ -12,6 +12,7 @@
>  #include "qemu/log.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/irq.h"
>  #include "hw/m68k/mcf.h"
> diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
> index 6ebcddcfb2..4db2b9bbc7 100644
> --- a/hw/m68k/q800.c
> +++ b/hw/m68k/q800.c
> @@ -23,6 +23,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/units.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "sysemu/sysemu.h"
>  #include "cpu.h"
>  #include "hw/hw.h"
> diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
> index e1f56f83f9..6715ba2ff9 100644
> --- a/hw/microblaze/boot.c
> +++ b/hw/microblaze/boot.c
> @@ -26,6 +26,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "qemu/option.h"
>  #include "qemu/config-file.h"
> diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c
> index 84a2132f85..45c596f4fe 100644
> --- a/hw/mips/fuloong2e.c
> +++ b/hw/mips/fuloong2e.c
> @@ -20,6 +20,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "qapi/error.h"
>  #include "cpu.h"
> diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
> index aa95c6a3d3..f9442731dd 100644
> --- a/hw/mips/jazz.c
> +++ b/hw/mips/jazz.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "hw/clock.h"
>  #include "hw/mips/mips.h"
>  #include "hw/mips/cpudevs.h"
> diff --git a/hw/mips/malta.c b/hw/mips/malta.c
> index 467b21849e..5c11eecec1 100644
> --- a/hw/mips/malta.c
> +++ b/hw/mips/malta.c
> @@ -25,6 +25,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/units.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/clock.h"
>  #include "hw/southbridge/piix.h"
> diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c
> index cc9b0934b3..f2e6273525 100644
> --- a/hw/mips/mipssim.c
> +++ b/hw/mips/mipssim.c
> @@ -28,6 +28,7 @@
>  #include "qemu/osdep.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/clock.h"
>  #include "hw/mips/mips.h"
> diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
> index 3cb864914b..95a8697906 100644
> --- a/hw/nios2/boot.c
> +++ b/hw/nios2/boot.c
> @@ -31,6 +31,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/units.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "qemu/option.h"
>  #include "qemu/config-file.h"
> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> index 08539a1aab..9e80633d6e 100644
> --- a/hw/nvram/fw_cfg.c
> +++ b/hw/nvram/fw_cfg.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "sysemu/sysemu.h"
>  #include "sysemu/dma.h"
>  #include "sysemu/reset.h"
> diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
> index d0323fefb1..0469db8c1d 100644
> --- a/hw/pci-host/prep.c
> +++ b/hw/pci-host/prep.c
> @@ -25,6 +25,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "qapi/error.h"
>  #include "hw/pci/pci.h"
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 0131d9d02c..9424231542 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "hw/irq.h"
>  #include "hw/pci/pci.h"
>  #include "hw/pci/pci_bridge.h"
> diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
> index 153a74c98c..6a64eb31ab 100644
> --- a/hw/ppc/e500.c
> +++ b/hw/ppc/e500.c
> @@ -16,6 +16,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "qapi/error.h"
>  #include "e500.h"
> diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
> index 61c63819df..c0accda592 100644
> --- a/hw/ppc/mac_newworld.c
> +++ b/hw/ppc/mac_newworld.c
> @@ -48,6 +48,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "hw/ppc/ppc.h"
>  #include "hw/qdev-properties.h"
> diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
> index 11623e8e67..04f98a4d81 100644
> --- a/hw/ppc/mac_oldworld.c
> +++ b/hw/ppc/mac_oldworld.c
> @@ -26,6 +26,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "qapi/error.h"
>  #include "hw/ppc/ppc.h"
> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> index 53a5121cab..14fc9758a9 100644
> --- a/hw/ppc/pnv.c
> +++ b/hw/ppc/pnv.c
> @@ -19,6 +19,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "qapi/error.h"
>  #include "sysemu/qtest.h"
> diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
> index c867e46330..b7249f21cf 100644
> --- a/hw/ppc/ppc405_boards.c
> +++ b/hw/ppc/ppc405_boards.c
> @@ -26,6 +26,7 @@
>  #include "qemu/units.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/ppc/ppc.h"
>  #include "hw/qdev-properties.h"
> diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
> index 74028dc986..665bc1784e 100644
> --- a/hw/ppc/ppc440_bamboo.c
> +++ b/hw/ppc/ppc440_bamboo.c
> @@ -15,6 +15,7 @@
>  #include "qemu/units.h"
>  #include "qemu/error-report.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/error-report.h"
>  #include "net/net.h"
>  #include "hw/pci/pci.h"
> diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
> index 7e59a91981..14e6583eb0 100644
> --- a/hw/ppc/sam460ex.c
> +++ b/hw/ppc/sam460ex.c
> @@ -14,6 +14,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/units.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include "hw/boards.h"
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index cd8be98caf..049efa0bbf 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -26,6 +26,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "qapi/visitor.h"
>  #include "sysemu/sysemu.h"
> diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
> index c790c1113f..7f1bca928c 100644
> --- a/hw/ppc/virtex_ml507.c
> +++ b/hw/ppc/virtex_ml507.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "cpu.h"
>  #include "hw/sysbus.h"
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 70a9bf8f5d..d62f3dc758 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -19,6 +19,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "qemu/error-report.h"
>  #include "exec/cpu-defs.h"
> diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
> index bddbaffac6..ff6b55e816 100644
> --- a/hw/s390x/ipl.c
> +++ b/hw/s390x/ipl.c
> @@ -14,6 +14,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qapi/error.h"
>  #include "sysemu/reset.h"
>  #include "sysemu/runstate.h"
> diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
> index 1c50b02f81..4bc4ebea84 100644
> --- a/hw/sparc/leon3.c
> +++ b/hw/sparc/leon3.c
> @@ -27,6 +27,7 @@
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/irq.h"
>  #include "qemu/timer.h"
> diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
> index 0f9cd2bf52..8686371318 100644
> --- a/hw/sparc/sun4m.c
> +++ b/hw/sparc/sun4m.c
> @@ -25,6 +25,7 @@
>  #include "qemu/osdep.h"
>  #include "qemu/units.h"
>  #include "qapi/error.h"
> +#include "qemu/datadir.h"
>  #include "qemu-common.h"
>  #include "cpu.h"
>  #include "hw/sysbus.h"
> diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
> index 8bee7dd2f4..0fa13a7330 100644
> --- a/hw/sparc64/sun4u.c
> +++ b/hw/sparc64/sun4u.c
> @@ -27,6 +27,7 @@
>  #include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "cpu.h"
>  #include "hw/pci/pci.h"
>  #include "hw/pci/pci_bridge.h"
> diff --git a/include/qemu-common.h b/include/qemu-common.h
> index fda7dc6ca7..654621444e 100644
> --- a/include/qemu-common.h
> +++ b/include/qemu-common.h
> @@ -108,27 +108,6 @@ void qemu_progress_end(void);
>  void qemu_progress_print(float delta, int max);
>  const char *qemu_get_vm_name(void);
>  
> -#define QEMU_FILE_TYPE_BIOS   0
> -#define QEMU_FILE_TYPE_KEYMAP 1
> -/**
> - * qemu_find_file:
> - * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS)
> - *        or QEMU_FILE_TYPE_KEYMAP (for keymaps).
> - * @name: Relative or absolute file name
> - *
> - * If @name exists on disk as an absolute path, or a path relative
> - * to the current directory, then returns @name unchanged.
> - * Otherwise searches for @name file in the data directories, either
> - * configured at build time (DATADIR) or registered with the -L command
> - * line option.
> - *
> - * The caller must use g_free() to free the returned data when it is
> - * no longer required.
> - *
> - * Returns: a path that can access @name, or NULL if no matching file exists.
> - */
> -char *qemu_find_file(int type, const char *name);
> -
>  /* OS specific functions */
>  void os_setup_early_signal_handling(void);
>  int os_parse_cmd_args(int index, const char *optarg);
> diff --git a/include/qemu/datadir.h b/include/qemu/datadir.h
> new file mode 100644
> index 0000000000..21f9097f58
> --- /dev/null
> +++ b/include/qemu/datadir.h
> @@ -0,0 +1,28 @@
> +#ifndef QEMU_DATADIR_H
> +#define QEMU_DATADIR_H
> +
> +#define QEMU_FILE_TYPE_BIOS   0
> +#define QEMU_FILE_TYPE_KEYMAP 1
> +/**
> + * qemu_find_file:
> + * @type: QEMU_FILE_TYPE_BIOS (for BIOS, VGA BIOS)
> + *        or QEMU_FILE_TYPE_KEYMAP (for keymaps).
> + * @name: Relative or absolute file name
> + *
> + * If @name exists on disk as an absolute path, or a path relative
> + * to the current directory, then returns @name unchanged.
> + * Otherwise searches for @name file in the data directories, either
> + * configured at build time (DATADIR) or registered with the -L command
> + * line option.
> + *
> + * The caller must use g_free() to free the returned data when it is
> + * no longer required.
> + *
> + * Returns: a path that can access @name, or NULL if no matching file exists.
> + */
> +char *qemu_find_file(int type, const char *name);
> +void qemu_add_default_firmwarepath(void);
> +void qemu_add_data_dir(char *path);
> +void qemu_list_data_dirs(void);
> +
> +#endif
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 1336b4264a..c94b2e7159 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -13,8 +13,6 @@ extern const char *qemu_name;
>  extern QemuUUID qemu_uuid;
>  extern bool qemu_uuid_set;
>  
> -void qemu_add_data_dir(char *path);
> -
>  void qemu_add_exit_notifier(Notifier *notify);
>  void qemu_remove_exit_notifier(Notifier *notify);
>  
> diff --git a/softmmu/datadir.c b/softmmu/datadir.c
> new file mode 100644
> index 0000000000..504c4665be
> --- /dev/null
> +++ b/softmmu/datadir.c
> @@ -0,0 +1,129 @@
> +/*
> + * QEMU firmware and keymap file search
> + *
> + * Copyright (c) 2003-2020 QEMU contributors
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/datadir.h"
> +#include "qemu/cutils.h"
> +#include "trace.h"
> +
> +static const char *data_dir[16];
> +static int data_dir_idx;
> +
> +char *qemu_find_file(int type, const char *name)
> +{
> +    int i;
> +    const char *subdir;
> +    char *buf;
> +
> +    /* Try the name as a straight path first */
> +    if (access(name, R_OK) == 0) {
> +        trace_load_file(name, name);
> +        return g_strdup(name);
> +    }
> +
> +    switch (type) {
> +    case QEMU_FILE_TYPE_BIOS:
> +        subdir = "";
> +        break;
> +    case QEMU_FILE_TYPE_KEYMAP:
> +        subdir = "keymaps/";
> +        break;
> +    default:
> +        abort();
> +    }
> +
> +    for (i = 0; i < data_dir_idx; i++) {
> +        buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
> +        if (access(buf, R_OK) == 0) {
> +            trace_load_file(name, buf);
> +            return buf;
> +        }
> +        g_free(buf);
> +    }
> +    return NULL;
> +}
> +
> +void qemu_add_data_dir(char *path)
> +{
> +    int i;
> +
> +    if (path == NULL) {
> +        return;
> +    }
> +    if (data_dir_idx == ARRAY_SIZE(data_dir)) {
> +        return;
> +    }
> +    for (i = 0; i < data_dir_idx; i++) {
> +        if (strcmp(data_dir[i], path) == 0) {
> +            g_free(path); /* duplicate */
> +            return;
> +        }
> +    }
> +    data_dir[data_dir_idx++] = path;
> +}
> +
> +/*
> + * Find a likely location for support files using the location of the binary.
> + * When running from the build tree this will be "$bindir/pc-bios".
> + * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated).
> + *
> + * The caller must use g_free() to free the returned data when it is
> + * no longer required.
> + */
> +static char *find_datadir(void)
> +{
> +    g_autofree char *dir = NULL;
> +
> +    dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL);
> +    if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
> +        return g_steal_pointer(&dir);
> +    }
> +
> +    return get_relocated_path(CONFIG_QEMU_DATADIR);
> +}
> +
> +void qemu_add_default_firmwarepath(void)
> +{
> +    char **dirs;
> +    size_t i;
> +
> +    /* add configured firmware directories */
> +    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
> +    for (i = 0; dirs[i] != NULL; i++) {
> +        qemu_add_data_dir(get_relocated_path(dirs[i]));
> +    }
> +    g_strfreev(dirs);
> +
> +    /* try to find datadir relative to the executable path */
> +    qemu_add_data_dir(find_datadir());
> +}
> +
> +void qemu_list_data_dirs(void)
> +{
> +    int i;
> +    for (i = 0; i < data_dir_idx; i++) {
> +        printf("%s\n", data_dir[i]);
> +    }
> +}
> diff --git a/softmmu/meson.build b/softmmu/meson.build
> index 8f7210b4f0..7b52339e7a 100644
> --- a/softmmu/meson.build
> +++ b/softmmu/meson.build
> @@ -3,6 +3,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
>    'balloon.c',
>    'cpus.c',
>    'cpu-throttle.c',
> +  'datadir.c',
>    'physmem.c',
>    'ioport.c',
>    'memory.c',
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 0ba1fcdb3d..86ace29f98 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "qemu/units.h"
>  #include "hw/boards.h"
>  #include "hw/qdev-properties.h"
> @@ -128,8 +129,6 @@ typedef struct BlockdevOptionsQueueEntry {
>  typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue;
>  
>  static const char *cpu_option;
> -static const char *data_dir[16];
> -static int data_dir_idx;
>  static const char *mem_path;
>  static const char *boot_order;
>  static const char *boot_once;
> @@ -1975,59 +1974,6 @@ static void parse_display(const char *p)
>      }
>  }
>  
> -char *qemu_find_file(int type, const char *name)
> -{
> -    int i;
> -    const char *subdir;
> -    char *buf;
> -
> -    /* Try the name as a straight path first */
> -    if (access(name, R_OK) == 0) {
> -        trace_load_file(name, name);
> -        return g_strdup(name);
> -    }
> -
> -    switch (type) {
> -    case QEMU_FILE_TYPE_BIOS:
> -        subdir = "";
> -        break;
> -    case QEMU_FILE_TYPE_KEYMAP:
> -        subdir = "keymaps/";
> -        break;
> -    default:
> -        abort();
> -    }
> -
> -    for (i = 0; i < data_dir_idx; i++) {
> -        buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
> -        if (access(buf, R_OK) == 0) {
> -            trace_load_file(name, buf);
> -            return buf;
> -        }
> -        g_free(buf);
> -    }
> -    return NULL;
> -}
> -
> -void qemu_add_data_dir(char *path)
> -{
> -    int i;
> -
> -    if (path == NULL) {
> -        return;
> -    }
> -    if (data_dir_idx == ARRAY_SIZE(data_dir)) {
> -        return;
> -    }
> -    for (i = 0; i < data_dir_idx; i++) {
> -        if (strcmp(data_dir[i], path) == 0) {
> -            g_free(path); /* duplicate */
> -            return;
> -        }
> -    }
> -    data_dir[data_dir_idx++] = path;
> -}
> -
>  static inline bool nonempty_str(const char *str)
>  {
>      return str && *str;
> @@ -3156,26 +3102,6 @@ static void create_default_memdev(MachineState *ms, const char *path)
>                              &error_fatal);
>  }
>  
> -/*
> - * Find a likely location for support files using the location of the binary.
> - * When running from the build tree this will be "$bindir/pc-bios".
> - * Otherwise, this is CONFIG_QEMU_DATADIR (possibly relocated).
> - *
> - * The caller must use g_free() to free the returned data when it is
> - * no longer required.
> - */
> -static char *find_datadir(void)
> -{
> -    g_autofree char *dir = NULL;
> -
> -    dir = g_build_filename(qemu_get_exec_dir(), "pc-bios", NULL);
> -    if (g_file_test(dir, G_FILE_TEST_IS_DIR)) {
> -        return g_steal_pointer(&dir);
> -    }
> -
> -    return get_relocated_path(CONFIG_QEMU_DATADIR);
> -}
> -
>  static void qemu_validate_options(void)
>  {
>      QemuOpts *machine_opts = qemu_get_machine_opts();
> @@ -3234,9 +3160,6 @@ static void qemu_process_sugar_options(void)
>  
>  static void qemu_process_early_options(void)
>  {
> -    char **dirs;
> -    int i;
> -
>  #ifdef CONFIG_SECCOMP
>      QemuOptsList *olist = qemu_find_opts_err("sandbox", NULL);
>      if (olist) {
> @@ -3274,21 +3197,11 @@ static void qemu_process_early_options(void)
>          qemu_set_log(0);
>      }
>  
> -    /* add configured firmware directories */
> -    dirs = g_strsplit(CONFIG_QEMU_FIRMWAREPATH, G_SEARCHPATH_SEPARATOR_S, 0);
> -    for (i = 0; dirs[i] != NULL; i++) {
> -        qemu_add_data_dir(get_relocated_path(dirs[i]));
> -    }
> -    g_strfreev(dirs);
> -
> -    /* try to find datadir relative to the executable path */
> -    qemu_add_data_dir(find_datadir());
> +    qemu_add_default_firmwarepath();
>  }
>  
>  static void qemu_process_help_options(void)
>  {
> -    int i;
> -
>      /*
>       * Check for -cpu help and -device help before we call select_machine(),
>       * which will return an error if the architecture has no default machine
> @@ -3307,9 +3220,7 @@ static void qemu_process_help_options(void)
>  
>      /* -L help lists the data directories and exits. */
>      if (list_data_dirs) {
> -        for (i = 0; i < data_dir_idx; i++) {
> -            printf("%s\n", data_dir[i]);
> -        }
> +        qemu_list_data_dirs();
>          exit(0);
>      }
>  }
> diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
> index 7be7226bc0..238866a037 100644
> --- a/tests/qtest/fuzz/fuzz.c
> +++ b/tests/qtest/fuzz/fuzz.c
> @@ -15,6 +15,7 @@
>  
>  #include <wordexp.h>
>  
> +#include "qemu/datadir.h"
>  #include "sysemu/qtest.h"
>  #include "sysemu/runstate.h"
>  #include "sysemu/sysemu.h"
> diff --git a/ui/keymaps.c b/ui/keymaps.c
> index 4e5fca57a8..d4a647464b 100644
> --- a/ui/keymaps.c
> +++ b/ui/keymaps.c
> @@ -24,6 +24,7 @@
>  
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/datadir.h"
>  #include "keymaps.h"
>  #include "trace.h"
>  #include "qemu/ctype.h"



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board
  2020-11-27 11:22         ` Paolo Bonzini
@ 2020-11-27 12:12           ` Igor Mammedov
  2020-11-27 12:22             ` Paolo Bonzini
  0 siblings, 1 reply; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 12:12 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Fri, 27 Nov 2020 12:22:51 +0100
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 27/11/20 11:31, Igor Mammedov wrote:
> >> Yes, calling it around machine initialization time is also a
> >> possibility.  I just wanted to get rid of it in code that I'm actually
> >> looking at.:)  
> > I'd prefer it being moved close to CLI parsing,
> > in a place where other _early call go.
> > 
> > We probably want qemu_init_board() being clear of not really needed clutter.
> >   
> 
> Fair enough, I'd put -semihosting-config in the same bucket as 
> -m/-boot/-smp (machine configuration that isn't in -M) so I'll move it 
> together with them.
it might be machine code, but I didn't see anything that depends
on machine in there that's why I've suggested to move it right after
we parse CLI options (i.e. as early as possible) to keep the rest of
code cleaner

> 
> Paolo
> 



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 30/36] vl: extract machine done notifiers
  2020-11-23 14:14 ` [PATCH 30/36] vl: extract machine done notifiers Paolo Bonzini
@ 2020-11-27 12:14   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 12:14 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:29 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  hw/core/machine.c       | 24 ++++++++++++++++++++++++
>  include/sysemu/sysemu.h |  1 +
>  softmmu/vl.c            | 24 ------------------------
>  3 files changed, 25 insertions(+), 24 deletions(-)
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index a5cfbcc7cb..745531c9d9 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -1166,6 +1166,30 @@ void machine_run_board_init(MachineState *machine)
>      machine_class->init(machine);
>  }
>  
> +static NotifierList machine_init_done_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
> +
> +bool machine_init_done;
> +
> +void qemu_add_machine_init_done_notifier(Notifier *notify)
> +{
> +    notifier_list_add(&machine_init_done_notifiers, notify);
> +    if (machine_init_done) {
> +        notify->notify(notify, NULL);
> +    }
> +}
> +
> +void qemu_remove_machine_init_done_notifier(Notifier *notify)
> +{
> +    notifier_remove(notify);
> +}
> +
> +void qemu_run_machine_init_done_notifiers(void)
> +{
> +    machine_init_done = true;
> +    notifier_list_notify(&machine_init_done_notifiers, NULL);
> +}
> +
>  static const TypeInfo machine_info = {
>      .name = TYPE_MACHINE,
>      .parent = TYPE_OBJECT,
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index c94b2e7159..1b62deaf2b 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -18,6 +18,7 @@ void qemu_remove_exit_notifier(Notifier *notify);
>  
>  extern bool machine_init_done;
>  
> +void qemu_run_machine_init_done_notifiers(void);
>  void qemu_add_machine_init_done_notifier(Notifier *notify);
>  void qemu_remove_machine_init_done_notifier(Notifier *notify);
>  
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 86ace29f98..7e13bb4a59 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -204,9 +204,6 @@ bool qemu_uuid_set;
>  static NotifierList exit_notifiers =
>      NOTIFIER_LIST_INITIALIZER(exit_notifiers);
>  
> -static NotifierList machine_init_done_notifiers =
> -    NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
> -
>  uint32_t xen_domid;
>  enum xen_mode xen_mode = XEN_EMULATE;
>  bool xen_domid_restrict;
> @@ -2432,27 +2429,6 @@ static void qemu_unlink_pidfile(Notifier *n, void *data)
>      }
>  }
>  
> -bool machine_init_done;
> -
> -void qemu_add_machine_init_done_notifier(Notifier *notify)
> -{
> -    notifier_list_add(&machine_init_done_notifiers, notify);
> -    if (machine_init_done) {
> -        notify->notify(notify, NULL);
> -    }
> -}
> -
> -void qemu_remove_machine_init_done_notifier(Notifier *notify)
> -{
> -    notifier_remove(notify);
> -}
> -
> -static void qemu_run_machine_init_done_notifiers(void)
> -{
> -    machine_init_done = true;
> -    notifier_list_notify(&machine_init_done_notifiers, NULL);
> -}
> -
>  static const QEMUOption *lookup_opt(int argc, char **argv,
>                                      const char **poptarg, int *poptind)
>  {



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board
  2020-11-27 12:12           ` Igor Mammedov
@ 2020-11-27 12:22             ` Paolo Bonzini
  0 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-27 12:22 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On 27/11/20 13:12, Igor Mammedov wrote:
>> Fair enough, I'd put -semihosting-config in the same bucket as
>> -m/-boot/-smp (machine configuration that isn't in -M) so I'll move it
>> together with them.
> it might be machine code, but I didn't see anything that depends
> on machine in there that's why I've suggested to move it right after
> we parse CLI options (i.e. as early as possible) to keep the rest of
> code cleaner

Yes, if I just remove this patch the fallback will end up in 
qemu_apply_machine_options.  That seems to be the right place.

Paolo



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 31/36] vl: extract softmmu/rtc.c
  2020-11-23 14:14 ` [PATCH 31/36] vl: extract softmmu/rtc.c Paolo Bonzini
@ 2020-11-27 12:43   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 12:43 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:30 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  include/sysemu/sysemu.h |   2 +
>  softmmu/meson.build     |   1 +
>  softmmu/rtc.c           | 190 ++++++++++++++++++++++++++++++++++++++++
>  softmmu/vl.c            | 156 ---------------------------------
>  4 files changed, 193 insertions(+), 156 deletions(-)
>  create mode 100644 softmmu/rtc.c
> 
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 1b62deaf2b..18cf586cd0 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -22,6 +22,8 @@ void qemu_run_machine_init_done_notifiers(void);
>  void qemu_add_machine_init_done_notifier(Notifier *notify);
>  void qemu_remove_machine_init_done_notifier(Notifier *notify);
>  
> +void configure_rtc(QemuOpts *opts);
> +
>  extern int autostart;
>  
>  typedef enum {
> diff --git a/softmmu/meson.build b/softmmu/meson.build
> index 7b52339e7a..d098d89653 100644
> --- a/softmmu/meson.build
> +++ b/softmmu/meson.build
> @@ -6,6 +6,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
>    'datadir.c',
>    'physmem.c',
>    'ioport.c',
> +  'rtc.c',
>    'memory.c',
>    'memory_mapping.c',
>    'qtest.c',
> diff --git a/softmmu/rtc.c b/softmmu/rtc.c
> new file mode 100644
> index 0000000000..e1e15ef613
> --- /dev/null
> +++ b/softmmu/rtc.c
> @@ -0,0 +1,190 @@
> +/*
> + * RTC configuration and clock read
> + *
> + * Copyright (c) 2003-2020 QEMU contributors
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/cutils.h"
> +#include "qapi/error.h"
> +#include "qapi/qmp/qerror.h"
> +#include "qemu/error-report.h"
> +#include "qemu/option.h"
> +#include "qemu/timer.h"
> +#include "qom/object.h"
> +#include "sysemu/replay.h"
> +#include "sysemu/sysemu.h"
> +
> +static enum {
> +    RTC_BASE_UTC,
> +    RTC_BASE_LOCALTIME,
> +    RTC_BASE_DATETIME,
> +} rtc_base_type = RTC_BASE_UTC;
> +static time_t rtc_ref_start_datetime;
> +static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
> +static int rtc_host_datetime_offset = -1; /* valid & used only with
> +                                             RTC_BASE_DATETIME */
> +QEMUClockType rtc_clock;
> +/***********************************************************/
> +/* RTC reference time/date access */
> +static time_t qemu_ref_timedate(QEMUClockType clock)
> +{
> +    time_t value = qemu_clock_get_ms(clock) / 1000;
> +    switch (clock) {
> +    case QEMU_CLOCK_REALTIME:
> +        value -= rtc_realtime_clock_offset;
> +        /* fall through */
> +    case QEMU_CLOCK_VIRTUAL:
> +        value += rtc_ref_start_datetime;
> +        break;
> +    case QEMU_CLOCK_HOST:
> +        if (rtc_base_type == RTC_BASE_DATETIME) {
> +            value -= rtc_host_datetime_offset;
> +        }
> +        break;
> +    default:
> +        assert(0);
> +    }
> +    return value;
> +}
> +
> +void qemu_get_timedate(struct tm *tm, int offset)
> +{
> +    time_t ti = qemu_ref_timedate(rtc_clock);
> +
> +    ti += offset;
> +
> +    switch (rtc_base_type) {
> +    case RTC_BASE_DATETIME:
> +    case RTC_BASE_UTC:
> +        gmtime_r(&ti, tm);
> +        break;
> +    case RTC_BASE_LOCALTIME:
> +        localtime_r(&ti, tm);
> +        break;
> +    }
> +}
> +
> +int qemu_timedate_diff(struct tm *tm)
> +{
> +    time_t seconds;
> +
> +    switch (rtc_base_type) {
> +    case RTC_BASE_DATETIME:
> +    case RTC_BASE_UTC:
> +        seconds = mktimegm(tm);
> +        break;
> +    case RTC_BASE_LOCALTIME:
> +    {
> +        struct tm tmp = *tm;
> +        tmp.tm_isdst = -1; /* use timezone to figure it out */
> +        seconds = mktime(&tmp);
> +        break;
> +    }
> +    default:
> +        abort();
> +    }
> +
> +    return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST);
> +}
> +
> +static void configure_rtc_base_datetime(const char *startdate)
> +{
> +    time_t rtc_start_datetime;
> +    struct tm tm;
> +
> +    if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon,
> +               &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
> +        /* OK */
> +    } else if (sscanf(startdate, "%d-%d-%d",
> +                      &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) {
> +        tm.tm_hour = 0;
> +        tm.tm_min = 0;
> +        tm.tm_sec = 0;
> +    } else {
> +        goto date_fail;
> +    }
> +    tm.tm_year -= 1900;
> +    tm.tm_mon--;
> +    rtc_start_datetime = mktimegm(&tm);
> +    if (rtc_start_datetime == -1) {
> +    date_fail:
> +        error_report("invalid datetime format");
> +        error_printf("valid formats: "
> +                     "'2006-06-17T16:01:21' or '2006-06-17'\n");
> +        exit(1);
> +    }
> +    rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime;
> +    rtc_ref_start_datetime = rtc_start_datetime;
> +}
> +
> +void configure_rtc(QemuOpts *opts)
> +{
> +    const char *value;
> +
> +    /* Set defaults */
> +    rtc_clock = QEMU_CLOCK_HOST;
> +    rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
> +    rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
> +
> +    value = qemu_opt_get(opts, "base");
> +    if (value) {
> +        if (!strcmp(value, "utc")) {
> +            rtc_base_type = RTC_BASE_UTC;
> +        } else if (!strcmp(value, "localtime")) {
> +            Error *blocker = NULL;
> +            rtc_base_type = RTC_BASE_LOCALTIME;
> +            error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
> +                      "-rtc base=localtime");
> +            replay_add_blocker(blocker);
> +        } else {
> +            rtc_base_type = RTC_BASE_DATETIME;
> +            configure_rtc_base_datetime(value);
> +        }
> +    }
> +    value = qemu_opt_get(opts, "clock");
> +    if (value) {
> +        if (!strcmp(value, "host")) {
> +            rtc_clock = QEMU_CLOCK_HOST;
> +        } else if (!strcmp(value, "rt")) {
> +            rtc_clock = QEMU_CLOCK_REALTIME;
> +        } else if (!strcmp(value, "vm")) {
> +            rtc_clock = QEMU_CLOCK_VIRTUAL;
> +        } else {
> +            error_report("invalid option value '%s'", value);
> +            exit(1);
> +        }
> +    }
> +    value = qemu_opt_get(opts, "driftfix");
> +    if (value) {
> +        if (!strcmp(value, "slew")) {
> +            object_register_sugar_prop("mc146818rtc",
> +                                       "lost_tick_policy",
> +                                       "slew");
> +        } else if (!strcmp(value, "none")) {
> +            /* discard is default */
> +        } else {
> +            error_report("invalid option value '%s'", value);
> +            exit(1);
> +        }
> +    }
> +}
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 7e13bb4a59..c9bb205c42 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -152,16 +152,6 @@ bool enable_cpu_pm = false;
>  int nb_nics;
>  NICInfo nd_table[MAX_NICS];
>  int autostart = 1;
> -static enum {
> -    RTC_BASE_UTC,
> -    RTC_BASE_LOCALTIME,
> -    RTC_BASE_DATETIME,
> -} rtc_base_type = RTC_BASE_UTC;
> -static time_t rtc_ref_start_datetime;
> -static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
> -static int rtc_host_datetime_offset = -1; /* valid & used only with
> -                                             RTC_BASE_DATETIME */
> -QEMUClockType rtc_clock;
>  int vga_interface_type = VGA_NONE;
>  static const char *vga_model = NULL;
>  static DisplayOptions dpy;
> @@ -766,152 +756,6 @@ void qemu_system_vmstop_request(RunState state)
>      qemu_mutex_unlock(&vmstop_lock);
>      qemu_notify_event();
>  }
> -
> -/***********************************************************/
> -/* RTC reference time/date access */
> -static time_t qemu_ref_timedate(QEMUClockType clock)
> -{
> -    time_t value = qemu_clock_get_ms(clock) / 1000;
> -    switch (clock) {
> -    case QEMU_CLOCK_REALTIME:
> -        value -= rtc_realtime_clock_offset;
> -        /* fall through */
> -    case QEMU_CLOCK_VIRTUAL:
> -        value += rtc_ref_start_datetime;
> -        break;
> -    case QEMU_CLOCK_HOST:
> -        if (rtc_base_type == RTC_BASE_DATETIME) {
> -            value -= rtc_host_datetime_offset;
> -        }
> -        break;
> -    default:
> -        assert(0);
> -    }
> -    return value;
> -}
> -
> -void qemu_get_timedate(struct tm *tm, int offset)
> -{
> -    time_t ti = qemu_ref_timedate(rtc_clock);
> -
> -    ti += offset;
> -
> -    switch (rtc_base_type) {
> -    case RTC_BASE_DATETIME:
> -    case RTC_BASE_UTC:
> -        gmtime_r(&ti, tm);
> -        break;
> -    case RTC_BASE_LOCALTIME:
> -        localtime_r(&ti, tm);
> -        break;
> -    }
> -}
> -
> -int qemu_timedate_diff(struct tm *tm)
> -{
> -    time_t seconds;
> -
> -    switch (rtc_base_type) {
> -    case RTC_BASE_DATETIME:
> -    case RTC_BASE_UTC:
> -        seconds = mktimegm(tm);
> -        break;
> -    case RTC_BASE_LOCALTIME:
> -    {
> -        struct tm tmp = *tm;
> -        tmp.tm_isdst = -1; /* use timezone to figure it out */
> -        seconds = mktime(&tmp);
> -        break;
> -    }
> -    default:
> -        abort();
> -    }
> -
> -    return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST);
> -}
> -
> -static void configure_rtc_base_datetime(const char *startdate)
> -{
> -    time_t rtc_start_datetime;
> -    struct tm tm;
> -
> -    if (sscanf(startdate, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon,
> -               &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
> -        /* OK */
> -    } else if (sscanf(startdate, "%d-%d-%d",
> -                      &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3) {
> -        tm.tm_hour = 0;
> -        tm.tm_min = 0;
> -        tm.tm_sec = 0;
> -    } else {
> -        goto date_fail;
> -    }
> -    tm.tm_year -= 1900;
> -    tm.tm_mon--;
> -    rtc_start_datetime = mktimegm(&tm);
> -    if (rtc_start_datetime == -1) {
> -    date_fail:
> -        error_report("invalid datetime format");
> -        error_printf("valid formats: "
> -                     "'2006-06-17T16:01:21' or '2006-06-17'\n");
> -        exit(1);
> -    }
> -    rtc_host_datetime_offset = rtc_ref_start_datetime - rtc_start_datetime;
> -    rtc_ref_start_datetime = rtc_start_datetime;
> -}
> -
> -static void configure_rtc(QemuOpts *opts)
> -{
> -    const char *value;
> -
> -    /* Set defaults */
> -    rtc_clock = QEMU_CLOCK_HOST;
> -    rtc_ref_start_datetime = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000;
> -    rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
> -
> -    value = qemu_opt_get(opts, "base");
> -    if (value) {
> -        if (!strcmp(value, "utc")) {
> -            rtc_base_type = RTC_BASE_UTC;
> -        } else if (!strcmp(value, "localtime")) {
> -            Error *blocker = NULL;
> -            rtc_base_type = RTC_BASE_LOCALTIME;
> -            error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED,
> -                      "-rtc base=localtime");
> -            replay_add_blocker(blocker);
> -        } else {
> -            rtc_base_type = RTC_BASE_DATETIME;
> -            configure_rtc_base_datetime(value);
> -        }
> -    }
> -    value = qemu_opt_get(opts, "clock");
> -    if (value) {
> -        if (!strcmp(value, "host")) {
> -            rtc_clock = QEMU_CLOCK_HOST;
> -        } else if (!strcmp(value, "rt")) {
> -            rtc_clock = QEMU_CLOCK_REALTIME;
> -        } else if (!strcmp(value, "vm")) {
> -            rtc_clock = QEMU_CLOCK_VIRTUAL;
> -        } else {
> -            error_report("invalid option value '%s'", value);
> -            exit(1);
> -        }
> -    }
> -    value = qemu_opt_get(opts, "driftfix");
> -    if (value) {
> -        if (!strcmp(value, "slew")) {
> -            object_register_sugar_prop("mc146818rtc",
> -                                       "lost_tick_policy",
> -                                       "slew");
> -        } else if (!strcmp(value, "none")) {
> -            /* discard is default */
> -        } else {
> -            error_report("invalid option value '%s'", value);
> -            exit(1);
> -        }
> -    }
> -}
> -
>  static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
>  {
>      const char *proc_name;



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 32/36] vl: extract softmmu/runstate.c
  2020-11-23 14:14 ` [PATCH 32/36] vl: extract softmmu/runstate.c Paolo Bonzini
@ 2020-11-27 12:59   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 12:59 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:31 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Looks like a lot more than just runstate, starting from qemu_init_subsystems()
which pulls in a lot of headers. But I don't have a better idea how to name new
file, maybe latter it could be split further, but for now 

Acked-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  include/sysemu/sysemu.h |   3 +
>  softmmu/meson.build     |   1 +
>  softmmu/runstate.c      | 800 ++++++++++++++++++++++++++++++++++++++++
>  softmmu/vl.c            | 752 +------------------------------------
>  4 files changed, 805 insertions(+), 751 deletions(-)
>  create mode 100644 softmmu/runstate.c
> 
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 18cf586cd0..3dac3229ec 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -24,6 +24,8 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
>  
>  void configure_rtc(QemuOpts *opts);
>  
> +void qemu_init_subsystems(void);
> +
>  extern int autostart;
>  
>  typedef enum {
> @@ -44,6 +46,7 @@ extern int alt_grab;
>  extern int ctrl_grab;
>  extern int graphic_rotate;
>  extern int no_shutdown;
> +extern int no_reboot;
>  extern int old_param;
>  extern int boot_menu;
>  extern bool boot_strict;
> diff --git a/softmmu/meson.build b/softmmu/meson.build
> index d098d89653..2a73ebc223 100644
> --- a/softmmu/meson.build
> +++ b/softmmu/meson.build
> @@ -7,6 +7,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
>    'physmem.c',
>    'ioport.c',
>    'rtc.c',
> +  'runstate.c',
>    'memory.c',
>    'memory_mapping.c',
>    'qtest.c',
> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
> new file mode 100644
> index 0000000000..892f2f679f
> --- /dev/null
> +++ b/softmmu/runstate.c
> @@ -0,0 +1,800 @@
> +/*
> + * QEMU main system emulation loop
> + *
> + * Copyright (c) 2003-2020 QEMU contributors
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "audio/audio.h"
> +#include "block/block.h"
> +#include "chardev/char.h"
> +#include "crypto/cipher.h"
> +#include "crypto/init.h"
> +#include "exec/cpu-common.h"
> +#include "exec/exec-all.h"
> +#include "exec/gdbstub.h"
> +#include "hw/boards.h"
> +#include "migration/misc.h"
> +#include "migration/postcopy-ram.h"
> +#include "monitor/monitor.h"
> +#include "net/net.h"
> +#include "net/vhost_net.h"
> +#include "qapi/error.h"
> +#include "qapi/qapi-commands-run-state.h"
> +#include "qapi/qapi-events-run-state.h"
> +#include "qemu-common.h"
> +#include "qemu/error-report.h"
> +#include "qemu/job.h"
> +#include "qemu/module.h"
> +#include "qemu/plugin.h"
> +#include "qemu/sockets.h"
> +#include "qemu/thread.h"
> +#include "qom/object.h"
> +#include "qom/object_interfaces.h"
> +#include "sysemu/cpus.h"
> +#include "sysemu/qtest.h"
> +#include "sysemu/replay.h"
> +#include "sysemu/reset.h"
> +#include "sysemu/runstate.h"
> +#include "sysemu/sysemu.h"
> +#include "sysemu/tpm.h"
> +#include "trace.h"

looks like an awful lot headers just for runstate

> +
> +static NotifierList exit_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(exit_notifiers);
> +
> +static RunState current_run_state = RUN_STATE_PRELAUNCH;
> +
> +/* We use RUN_STATE__MAX but any invalid value will do */
> +static RunState vmstop_requested = RUN_STATE__MAX;
> +static QemuMutex vmstop_lock;
> +
> +typedef struct {
> +    RunState from;
> +    RunState to;
> +} RunStateTransition;
> +
> +static const RunStateTransition runstate_transitions_def[] = {
> +    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> +
> +    { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
> +    { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
> +
> +    { RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
> +    { RUN_STATE_INMIGRATE, RUN_STATE_COLO },
> +
> +    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
> +    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
> +
> +    { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
> +    { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
> +
> +    { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
> +    { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
> +    { RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
> +    { RUN_STATE_PAUSED, RUN_STATE_COLO},
> +
> +    { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
> +    { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
> +
> +    { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
> +    { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> +
> +    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
> +    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
> +    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
> +    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
> +    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
> +
> +    { RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
> +    { RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
> +
> +    { RUN_STATE_COLO, RUN_STATE_RUNNING },
> +
> +    { RUN_STATE_RUNNING, RUN_STATE_DEBUG },
> +    { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
> +    { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
> +    { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
> +    { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
> +    { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
> +    { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
> +    { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
> +    { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
> +    { RUN_STATE_RUNNING, RUN_STATE_COLO},
> +
> +    { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
> +
> +    { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
> +    { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
> +    { RUN_STATE_SHUTDOWN, RUN_STATE_COLO },
> +
> +    { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
> +    { RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
> +    { RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
> +    { RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
> +    { RUN_STATE_SUSPENDED, RUN_STATE_COLO},
> +
> +    { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
> +    { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
> +    { RUN_STATE_WATCHDOG, RUN_STATE_COLO},
> +
> +    { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
> +    { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
> +    { RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
> +
> +    { RUN_STATE__MAX, RUN_STATE__MAX },
> +};
> +
> +static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
> +
> +bool runstate_check(RunState state)
> +{
> +    return current_run_state == state;
> +}
> +
> +bool runstate_store(char *str, size_t size)
> +{
> +    const char *state = RunState_str(current_run_state);
> +    size_t len = strlen(state) + 1;
> +
> +    if (len > size) {
> +        return false;
> +    }
> +    memcpy(str, state, len);
> +    return true;
> +}
> +
> +static void runstate_init(void)
> +{
> +    const RunStateTransition *p;
> +
> +    memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
> +    for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
> +        runstate_valid_transitions[p->from][p->to] = true;
> +    }
> +
> +    qemu_mutex_init(&vmstop_lock);
> +}
> +
> +/* This function will abort() on invalid state transitions */
> +void runstate_set(RunState new_state)
> +{
> +    assert(new_state < RUN_STATE__MAX);
> +
> +    trace_runstate_set(current_run_state, RunState_str(current_run_state),
> +                       new_state, RunState_str(new_state));
> +
> +    if (current_run_state == new_state) {
> +        return;
> +    }
> +
> +    if (!runstate_valid_transitions[current_run_state][new_state]) {
> +        error_report("invalid runstate transition: '%s' -> '%s'",
> +                     RunState_str(current_run_state),
> +                     RunState_str(new_state));
> +        abort();
> +    }
> +
> +    current_run_state = new_state;
> +}
> +
> +int runstate_is_running(void)
> +{
> +    return runstate_check(RUN_STATE_RUNNING);
> +}
> +
> +bool runstate_needs_reset(void)
> +{
> +    return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
> +        runstate_check(RUN_STATE_SHUTDOWN);
> +}
> +
> +StatusInfo *qmp_query_status(Error **errp)
> +{
> +    StatusInfo *info = g_malloc0(sizeof(*info));
> +
> +    info->running = runstate_is_running();
> +    info->singlestep = singlestep;
> +    info->status = current_run_state;
> +
> +    return info;
> +}
> +
> +bool qemu_vmstop_requested(RunState *r)
> +{
> +    qemu_mutex_lock(&vmstop_lock);
> +    *r = vmstop_requested;
> +    vmstop_requested = RUN_STATE__MAX;
> +    qemu_mutex_unlock(&vmstop_lock);
> +    return *r < RUN_STATE__MAX;
> +}
> +
> +void qemu_system_vmstop_request_prepare(void)
> +{
> +    qemu_mutex_lock(&vmstop_lock);
> +}
> +
> +void qemu_system_vmstop_request(RunState state)
> +{
> +    vmstop_requested = state;
> +    qemu_mutex_unlock(&vmstop_lock);
> +    qemu_notify_event();
> +}
> +struct VMChangeStateEntry {
> +    VMChangeStateHandler *cb;
> +    void *opaque;
> +    QTAILQ_ENTRY(VMChangeStateEntry) entries;
> +    int priority;
> +};
> +
> +static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
> +    QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
> +
> +/**
> + * qemu_add_vm_change_state_handler_prio:
> + * @cb: the callback to invoke
> + * @opaque: user data passed to the callback
> + * @priority: low priorities execute first when the vm runs and the reverse is
> + *            true when the vm stops
> + *
> + * Register a callback function that is invoked when the vm starts or stops
> + * running.
> + *
> + * Returns: an entry to be freed using qemu_del_vm_change_state_handler()
> + */
> +VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
> +        VMChangeStateHandler *cb, void *opaque, int priority)
> +{
> +    VMChangeStateEntry *e;
> +    VMChangeStateEntry *other;
> +
> +    e = g_malloc0(sizeof(*e));
> +    e->cb = cb;
> +    e->opaque = opaque;
> +    e->priority = priority;
> +
> +    /* Keep list sorted in ascending priority order */
> +    QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
> +        if (priority < other->priority) {
> +            QTAILQ_INSERT_BEFORE(other, e, entries);
> +            return e;
> +        }
> +    }
> +
> +    QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
> +    return e;
> +}
> +
> +VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
> +                                                     void *opaque)
> +{
> +    return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
> +}
> +
> +void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
> +{
> +    QTAILQ_REMOVE(&vm_change_state_head, e, entries);
> +    g_free(e);
> +}
> +
> +void vm_state_notify(int running, RunState state)
> +{
> +    VMChangeStateEntry *e, *next;
> +
> +    trace_vm_state_notify(running, state, RunState_str(state));
> +
> +    if (running) {
> +        QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
> +            e->cb(e->opaque, running, state);
> +        }
> +    } else {
> +        QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next) {
> +            e->cb(e->opaque, running, state);
> +        }
> +    }
> +}
> +
> +static ShutdownCause reset_requested;
> +static ShutdownCause shutdown_requested;
> +static int shutdown_signal;
> +static pid_t shutdown_pid;
> +static int powerdown_requested;
> +static int debug_requested;
> +static int suspend_requested;
> +static WakeupReason wakeup_reason;
> +static NotifierList powerdown_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
> +static NotifierList suspend_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
> +static NotifierList wakeup_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
> +static NotifierList shutdown_notifiers =
> +    NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
> +static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
> +
> +ShutdownCause qemu_shutdown_requested_get(void)
> +{
> +    return shutdown_requested;
> +}
> +
> +ShutdownCause qemu_reset_requested_get(void)
> +{
> +    return reset_requested;
> +}
> +
> +static int qemu_shutdown_requested(void)
> +{
> +    return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
> +}
> +
> +static void qemu_kill_report(void)
> +{
> +    if (!qtest_driver() && shutdown_signal) {
> +        if (shutdown_pid == 0) {
> +            /* This happens for eg ^C at the terminal, so it's worth
> +             * avoiding printing an odd message in that case.
> +             */
> +            error_report("terminating on signal %d", shutdown_signal);
> +        } else {
> +            char *shutdown_cmd = qemu_get_pid_name(shutdown_pid);
> +
> +            error_report("terminating on signal %d from pid " FMT_pid " (%s)",
> +                         shutdown_signal, shutdown_pid,
> +                         shutdown_cmd ? shutdown_cmd : "<unknown process>");
> +            g_free(shutdown_cmd);
> +        }
> +        shutdown_signal = 0;
> +    }
> +}
> +
> +static ShutdownCause qemu_reset_requested(void)
> +{
> +    ShutdownCause r = reset_requested;
> +
> +    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> +        reset_requested = SHUTDOWN_CAUSE_NONE;
> +        return r;
> +    }
> +    return SHUTDOWN_CAUSE_NONE;
> +}
> +
> +static int qemu_suspend_requested(void)
> +{
> +    int r = suspend_requested;
> +    if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
> +        suspend_requested = 0;
> +        return r;
> +    }
> +    return false;
> +}
> +
> +static WakeupReason qemu_wakeup_requested(void)
> +{
> +    return wakeup_reason;
> +}
> +
> +static int qemu_powerdown_requested(void)
> +{
> +    int r = powerdown_requested;
> +    powerdown_requested = 0;
> +    return r;
> +}
> +
> +static int qemu_debug_requested(void)
> +{
> +    int r = debug_requested;
> +    debug_requested = 0;
> +    return r;
> +}
> +
> +/*
> + * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
> + */
> +void qemu_system_reset(ShutdownCause reason)
> +{
> +    MachineClass *mc;
> +
> +    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
> +
> +    cpu_synchronize_all_states();
> +
> +    if (mc && mc->reset) {
> +        mc->reset(current_machine);
> +    } else {
> +        qemu_devices_reset();
> +    }
> +    if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> +        qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
> +    }
> +    cpu_synchronize_all_post_reset();
> +}
> +
> +/*
> + * Wake the VM after suspend.
> + */
> +static void qemu_system_wakeup(void)
> +{
> +    MachineClass *mc;
> +
> +    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
> +
> +    if (mc && mc->wakeup) {
> +        mc->wakeup(current_machine);
> +    }
> +}
> +
> +void qemu_system_guest_panicked(GuestPanicInformation *info)
> +{
> +    qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
> +
> +    if (current_cpu) {
> +        current_cpu->crash_occurred = true;
> +    }
> +    qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
> +                                   !!info, info);
> +    vm_stop(RUN_STATE_GUEST_PANICKED);
> +    if (!no_shutdown) {
> +        qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
> +                                       !!info, info);
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
> +    }
> +
> +    if (info) {
> +        if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
> +            qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
> +                          " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
> +                          info->u.hyper_v.arg1,
> +                          info->u.hyper_v.arg2,
> +                          info->u.hyper_v.arg3,
> +                          info->u.hyper_v.arg4,
> +                          info->u.hyper_v.arg5);
> +        } else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
> +            qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
> +                          "PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
> +                          info->u.s390.core,
> +                          S390CrashReason_str(info->u.s390.reason),
> +                          info->u.s390.psw_mask,
> +                          info->u.s390.psw_addr);
> +        }
> +        qapi_free_GuestPanicInformation(info);
> +    }
> +}
> +
> +void qemu_system_guest_crashloaded(GuestPanicInformation *info)
> +{
> +    qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded");
> +
> +    qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN,
> +                                   !!info, info);
> +
> +    if (info) {
> +        qapi_free_GuestPanicInformation(info);
> +    }
> +}
> +
> +void qemu_system_reset_request(ShutdownCause reason)
> +{
> +    if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> +        shutdown_requested = reason;
> +    } else {
> +        reset_requested = reason;
> +    }
> +    cpu_stop_current();
> +    qemu_notify_event();
> +}
> +
> +static void qemu_system_suspend(void)
> +{
> +    pause_all_vcpus();
> +    notifier_list_notify(&suspend_notifiers, NULL);
> +    runstate_set(RUN_STATE_SUSPENDED);
> +    qapi_event_send_suspend();
> +}
> +
> +void qemu_system_suspend_request(void)
> +{
> +    if (runstate_check(RUN_STATE_SUSPENDED)) {
> +        return;
> +    }
> +    suspend_requested = 1;
> +    cpu_stop_current();
> +    qemu_notify_event();
> +}
> +
> +void qemu_register_suspend_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&suspend_notifiers, notifier);
> +}
> +
> +void qemu_system_wakeup_request(WakeupReason reason, Error **errp)
> +{
> +    trace_system_wakeup_request(reason);
> +
> +    if (!runstate_check(RUN_STATE_SUSPENDED)) {
> +        error_setg(errp,
> +                   "Unable to wake up: guest is not in suspended state");
> +        return;
> +    }
> +    if (!(wakeup_reason_mask & (1 << reason))) {
> +        return;
> +    }
> +    runstate_set(RUN_STATE_RUNNING);
> +    wakeup_reason = reason;
> +    qemu_notify_event();
> +}
> +
> +void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
> +{
> +    if (enabled) {
> +        wakeup_reason_mask |= (1 << reason);
> +    } else {
> +        wakeup_reason_mask &= ~(1 << reason);
> +    }
> +}
> +
> +void qemu_register_wakeup_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&wakeup_notifiers, notifier);
> +}
> +
> +static bool wakeup_suspend_enabled;
> +
> +void qemu_register_wakeup_support(void)
> +{
> +    wakeup_suspend_enabled = true;
> +}
> +
> +bool qemu_wakeup_suspend_enabled(void)
> +{
> +    return wakeup_suspend_enabled;
> +}
> +
> +void qemu_system_killed(int signal, pid_t pid)
> +{
> +    shutdown_signal = signal;
> +    shutdown_pid = pid;
> +    no_shutdown = 0;
> +
> +    /* Cannot call qemu_system_shutdown_request directly because
> +     * we are in a signal handler.
> +     */
> +    shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
> +    qemu_notify_event();
> +}
> +
> +void qemu_system_shutdown_request(ShutdownCause reason)
> +{
> +    trace_qemu_system_shutdown_request(reason);
> +    replay_shutdown_request(reason);
> +    shutdown_requested = reason;
> +    qemu_notify_event();
> +}
> +
> +static void qemu_system_powerdown(void)
> +{
> +    qapi_event_send_powerdown();
> +    notifier_list_notify(&powerdown_notifiers, NULL);
> +}
> +
> +static void qemu_system_shutdown(ShutdownCause cause)
> +{
> +    qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause);
> +    notifier_list_notify(&shutdown_notifiers, &cause);
> +}
> +
> +void qemu_system_powerdown_request(void)
> +{
> +    trace_qemu_system_powerdown_request();
> +    powerdown_requested = 1;
> +    qemu_notify_event();
> +}
> +
> +void qemu_register_powerdown_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&powerdown_notifiers, notifier);
> +}
> +
> +void qemu_register_shutdown_notifier(Notifier *notifier)
> +{
> +    notifier_list_add(&shutdown_notifiers, notifier);
> +}
> +
> +void qemu_system_debug_request(void)
> +{
> +    debug_requested = 1;
> +    qemu_notify_event();
> +}
> +
> +static bool main_loop_should_exit(void)
> +{
> +    RunState r;
> +    ShutdownCause request;
> +
> +    if (qemu_debug_requested()) {
> +        vm_stop(RUN_STATE_DEBUG);
> +    }
> +    if (qemu_suspend_requested()) {
> +        qemu_system_suspend();
> +    }
> +    request = qemu_shutdown_requested();
> +    if (request) {
> +        qemu_kill_report();
> +        qemu_system_shutdown(request);
> +        if (no_shutdown) {
> +            vm_stop(RUN_STATE_SHUTDOWN);
> +        } else {
> +            return true;
> +        }
> +    }
> +    request = qemu_reset_requested();
> +    if (request) {
> +        pause_all_vcpus();
> +        qemu_system_reset(request);
> +        resume_all_vcpus();
> +        /*
> +         * runstate can change in pause_all_vcpus()
> +         * as iothread mutex is unlocked
> +         */
> +        if (!runstate_check(RUN_STATE_RUNNING) &&
> +                !runstate_check(RUN_STATE_INMIGRATE) &&
> +                !runstate_check(RUN_STATE_FINISH_MIGRATE)) {
> +            runstate_set(RUN_STATE_PRELAUNCH);
> +        }
> +    }
> +    if (qemu_wakeup_requested()) {
> +        pause_all_vcpus();
> +        qemu_system_wakeup();
> +        notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
> +        wakeup_reason = QEMU_WAKEUP_REASON_NONE;
> +        resume_all_vcpus();
> +        qapi_event_send_wakeup();
> +    }
> +    if (qemu_powerdown_requested()) {
> +        qemu_system_powerdown();
> +    }
> +    if (qemu_vmstop_requested(&r)) {
> +        vm_stop(r);
> +    }
> +    return false;
> +}
> +
> +void qemu_main_loop(void)
> +{
> +#ifdef CONFIG_PROFILER
> +    int64_t ti;
> +#endif
> +    while (!main_loop_should_exit()) {
> +#ifdef CONFIG_PROFILER
> +        ti = profile_getclock();
> +#endif
> +        main_loop_wait(false);
> +#ifdef CONFIG_PROFILER
> +        dev_time += profile_getclock() - ti;
> +#endif
> +    }
> +}
> +
> +void qemu_add_exit_notifier(Notifier *notify)
> +{
> +    notifier_list_add(&exit_notifiers, notify);
> +}
> +
> +void qemu_remove_exit_notifier(Notifier *notify)
> +{
> +    notifier_remove(notify);
> +}
> +
> +static void qemu_run_exit_notifiers(void)
> +{
> +    notifier_list_notify(&exit_notifiers, NULL);
> +}
> +
> +void qemu_init_subsystems(void)
> +{
> +    Error *err;
> +
> +    os_set_line_buffering();
> +
> +    module_call_init(MODULE_INIT_TRACE);
> +
> +    qemu_init_cpu_list();
> +    qemu_init_cpu_loop();
> +    qemu_mutex_lock_iothread();
> +
> +    atexit(qemu_run_exit_notifiers);
> +
> +    module_call_init(MODULE_INIT_QOM);
> +    module_call_init(MODULE_INIT_MIGRATION);
> +
> +    runstate_init();
> +    precopy_infrastructure_init();
> +    postcopy_infrastructure_init();
> +    monitor_init_globals();
> +
> +    if (qcrypto_init(&err) < 0) {
> +        error_reportf_err(err, "cannot initialize crypto: ");
> +        exit(1);
> +    }
> +
> +    os_setup_early_signal_handling();
> +
> +    bdrv_init_with_whitelist();
> +    socket_init();
> +}
> +
> +
> +void qemu_cleanup(void)
> +{
> +    gdbserver_cleanup();
> +
> +    /*
> +     * cleaning up the migration object cancels any existing migration
> +     * try to do this early so that it also stops using devices.
> +     */
> +    migration_shutdown();
> +
> +    /*
> +     * We must cancel all block jobs while the block layer is drained,
> +     * or cancelling will be affected by throttling and thus may block
> +     * for an extended period of time.
> +     * vm_shutdown() will bdrv_drain_all(), so we may as well include
> +     * it in the drained section.
> +     * We do not need to end this section, because we do not want any
> +     * requests happening from here on anyway.
> +     */
> +    bdrv_drain_all_begin();
> +
> +    /* No more vcpu or device emulation activity beyond this point */
> +    vm_shutdown();
> +    replay_finish();
> +
> +    job_cancel_sync_all();
> +    bdrv_close_all();
> +
> +    /* vhost-user must be cleaned up before chardevs.  */
> +    tpm_cleanup();
> +    net_cleanup();
> +    audio_cleanup();
> +    monitor_cleanup();
> +    qemu_chr_cleanup();
> +    user_creatable_cleanup();
> +    /* TODO: unref root container, check all devices are ok */
> +}
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index c9bb205c42..914b86ee86 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -112,7 +112,6 @@
>  #include "qapi/qapi-commands-block-core.h"
>  #include "qapi/qapi-commands-migration.h"
>  #include "qapi/qapi-commands-misc.h"
> -#include "qapi/qapi-commands-run-state.h"
>  #include "qapi/qapi-commands-ui.h"
>  #include "qapi/qmp/qerror.h"
>  #include "sysemu/iothread.h"
> @@ -164,7 +163,7 @@ Chardev *parallel_hds[MAX_PARALLEL_PORTS];
>  int win2k_install_hack = 0;
>  int singlestep = 0;
>  int fd_bootchk = 1;
> -static int no_reboot;
> +int no_reboot;
>  int no_shutdown = 0;
>  int graphic_rotate = 0;
>  static const char *watchdog;
> @@ -191,9 +190,6 @@ static const char *qtest_log;
>  QemuUUID qemu_uuid;
>  bool qemu_uuid_set;
>  
> -static NotifierList exit_notifiers =
> -    NOTIFIER_LIST_INITIALIZER(exit_notifiers);
> -
>  uint32_t xen_domid;
>  enum xen_mode xen_mode = XEN_EMULATE;
>  bool xen_domid_restrict;
> @@ -535,12 +531,6 @@ const char *qemu_get_vm_name(void)
>      return qemu_name;
>  }
>  
> -static void res_free(void)
> -{
> -    g_free(boot_splash_filedata);
> -    boot_splash_filedata = NULL;
> -}
> -
>  static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp)
>  {
>      const char *driver = qemu_opt_get(opts, "driver");
> @@ -556,206 +546,6 @@ static int default_driver_check(void *opaque, QemuOpts *opts, Error **errp)
>      return 0;
>  }
>  
> -/***********************************************************/
> -/* QEMU state */
> -
> -static RunState current_run_state = RUN_STATE_PRELAUNCH;
> -
> -/* We use RUN_STATE__MAX but any invalid value will do */
> -static RunState vmstop_requested = RUN_STATE__MAX;
> -static QemuMutex vmstop_lock;
> -
> -typedef struct {
> -    RunState from;
> -    RunState to;
> -} RunStateTransition;
> -
> -static const RunStateTransition runstate_transitions_def[] = {
> -    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> -
> -    { RUN_STATE_DEBUG, RUN_STATE_RUNNING },
> -    { RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
> -
> -    { RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
> -    { RUN_STATE_INMIGRATE, RUN_STATE_COLO },
> -
> -    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
> -    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
> -
> -    { RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
> -    { RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
> -
> -    { RUN_STATE_PAUSED, RUN_STATE_RUNNING },
> -    { RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
> -    { RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
> -    { RUN_STATE_PAUSED, RUN_STATE_COLO},
> -
> -    { RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
> -    { RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
> -
> -    { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
> -    { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
> -
> -    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
> -    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
> -    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
> -    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
> -    { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
> -
> -    { RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
> -    { RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
> -
> -    { RUN_STATE_COLO, RUN_STATE_RUNNING },
> -
> -    { RUN_STATE_RUNNING, RUN_STATE_DEBUG },
> -    { RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
> -    { RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
> -    { RUN_STATE_RUNNING, RUN_STATE_PAUSED },
> -    { RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
> -    { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
> -    { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
> -    { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
> -    { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
> -    { RUN_STATE_RUNNING, RUN_STATE_COLO},
> -
> -    { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
> -
> -    { RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
> -    { RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
> -    { RUN_STATE_SHUTDOWN, RUN_STATE_COLO },
> -
> -    { RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
> -    { RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
> -    { RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
> -    { RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
> -    { RUN_STATE_SUSPENDED, RUN_STATE_COLO},
> -
> -    { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
> -    { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
> -    { RUN_STATE_WATCHDOG, RUN_STATE_COLO},
> -
> -    { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
> -    { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
> -    { RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
> -
> -    { RUN_STATE__MAX, RUN_STATE__MAX },
> -};
> -
> -static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
> -
> -bool runstate_check(RunState state)
> -{
> -    return current_run_state == state;
> -}
> -
> -bool runstate_store(char *str, size_t size)
> -{
> -    const char *state = RunState_str(current_run_state);
> -    size_t len = strlen(state) + 1;
> -
> -    if (len > size) {
> -        return false;
> -    }
> -    memcpy(str, state, len);
> -    return true;
> -}
> -
> -static void runstate_init(void)
> -{
> -    const RunStateTransition *p;
> -
> -    memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
> -    for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
> -        runstate_valid_transitions[p->from][p->to] = true;
> -    }
> -
> -    qemu_mutex_init(&vmstop_lock);
> -}
> -
> -/* This function will abort() on invalid state transitions */
> -void runstate_set(RunState new_state)
> -{
> -    assert(new_state < RUN_STATE__MAX);
> -
> -    trace_runstate_set(current_run_state, RunState_str(current_run_state),
> -                       new_state, RunState_str(new_state));
> -
> -    if (current_run_state == new_state) {
> -        return;
> -    }
> -
> -    if (!runstate_valid_transitions[current_run_state][new_state]) {
> -        error_report("invalid runstate transition: '%s' -> '%s'",
> -                     RunState_str(current_run_state),
> -                     RunState_str(new_state));
> -        abort();
> -    }
> -
> -    current_run_state = new_state;
> -}
> -
> -int runstate_is_running(void)
> -{
> -    return runstate_check(RUN_STATE_RUNNING);
> -}
> -
> -bool runstate_needs_reset(void)
> -{
> -    return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
> -        runstate_check(RUN_STATE_SHUTDOWN);
> -}
> -
> -StatusInfo *qmp_query_status(Error **errp)
> -{
> -    StatusInfo *info = g_malloc0(sizeof(*info));
> -
> -    info->running = runstate_is_running();
> -    info->singlestep = singlestep;
> -    info->status = current_run_state;
> -
> -    return info;
> -}
> -
> -bool qemu_vmstop_requested(RunState *r)
> -{
> -    qemu_mutex_lock(&vmstop_lock);
> -    *r = vmstop_requested;
> -    vmstop_requested = RUN_STATE__MAX;
> -    qemu_mutex_unlock(&vmstop_lock);
> -    return *r < RUN_STATE__MAX;
> -}
> -
> -void qemu_system_vmstop_request_prepare(void)
> -{
> -    qemu_mutex_lock(&vmstop_lock);
> -}
> -
> -void qemu_system_vmstop_request(RunState state)
> -{
> -    vmstop_requested = state;
> -    qemu_mutex_unlock(&vmstop_lock);
> -    qemu_notify_event();
> -}
>  static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
>  {
>      const char *proc_name;
> @@ -1072,458 +862,6 @@ static int machine_help_func(QemuOpts *opts, MachineState *machine)
>      return 1;
>  }
>  
> -struct VMChangeStateEntry {
> -    VMChangeStateHandler *cb;
> -    void *opaque;
> -    QTAILQ_ENTRY(VMChangeStateEntry) entries;
> -    int priority;
> -};
> -
> -static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
> -    QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
> -
> -/**
> - * qemu_add_vm_change_state_handler_prio:
> - * @cb: the callback to invoke
> - * @opaque: user data passed to the callback
> - * @priority: low priorities execute first when the vm runs and the reverse is
> - *            true when the vm stops
> - *
> - * Register a callback function that is invoked when the vm starts or stops
> - * running.
> - *
> - * Returns: an entry to be freed using qemu_del_vm_change_state_handler()
> - */
> -VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
> -        VMChangeStateHandler *cb, void *opaque, int priority)
> -{
> -    VMChangeStateEntry *e;
> -    VMChangeStateEntry *other;
> -
> -    e = g_malloc0(sizeof(*e));
> -    e->cb = cb;
> -    e->opaque = opaque;
> -    e->priority = priority;
> -
> -    /* Keep list sorted in ascending priority order */
> -    QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
> -        if (priority < other->priority) {
> -            QTAILQ_INSERT_BEFORE(other, e, entries);
> -            return e;
> -        }
> -    }
> -
> -    QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
> -    return e;
> -}
> -
> -VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
> -                                                     void *opaque)
> -{
> -    return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
> -}
> -
> -void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
> -{
> -    QTAILQ_REMOVE(&vm_change_state_head, e, entries);
> -    g_free(e);
> -}
> -
> -void vm_state_notify(int running, RunState state)
> -{
> -    VMChangeStateEntry *e, *next;
> -
> -    trace_vm_state_notify(running, state, RunState_str(state));
> -
> -    if (running) {
> -        QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
> -            e->cb(e->opaque, running, state);
> -        }
> -    } else {
> -        QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next) {
> -            e->cb(e->opaque, running, state);
> -        }
> -    }
> -}
> -
> -static ShutdownCause reset_requested;
> -static ShutdownCause shutdown_requested;
> -static int shutdown_signal;
> -static pid_t shutdown_pid;
> -static int powerdown_requested;
> -static int debug_requested;
> -static int suspend_requested;
> -static WakeupReason wakeup_reason;
> -static NotifierList powerdown_notifiers =
> -    NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
> -static NotifierList suspend_notifiers =
> -    NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
> -static NotifierList wakeup_notifiers =
> -    NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
> -static NotifierList shutdown_notifiers =
> -    NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
> -static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
> -
> -ShutdownCause qemu_shutdown_requested_get(void)
> -{
> -    return shutdown_requested;
> -}
> -
> -ShutdownCause qemu_reset_requested_get(void)
> -{
> -    return reset_requested;
> -}
> -
> -static int qemu_shutdown_requested(void)
> -{
> -    return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
> -}
> -
> -static void qemu_kill_report(void)
> -{
> -    if (!qtest_driver() && shutdown_signal) {
> -        if (shutdown_pid == 0) {
> -            /* This happens for eg ^C at the terminal, so it's worth
> -             * avoiding printing an odd message in that case.
> -             */
> -            error_report("terminating on signal %d", shutdown_signal);
> -        } else {
> -            char *shutdown_cmd = qemu_get_pid_name(shutdown_pid);
> -
> -            error_report("terminating on signal %d from pid " FMT_pid " (%s)",
> -                         shutdown_signal, shutdown_pid,
> -                         shutdown_cmd ? shutdown_cmd : "<unknown process>");
> -            g_free(shutdown_cmd);
> -        }
> -        shutdown_signal = 0;
> -    }
> -}
> -
> -static ShutdownCause qemu_reset_requested(void)
> -{
> -    ShutdownCause r = reset_requested;
> -
> -    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> -        reset_requested = SHUTDOWN_CAUSE_NONE;
> -        return r;
> -    }
> -    return SHUTDOWN_CAUSE_NONE;
> -}
> -
> -static int qemu_suspend_requested(void)
> -{
> -    int r = suspend_requested;
> -    if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
> -        suspend_requested = 0;
> -        return r;
> -    }
> -    return false;
> -}
> -
> -static WakeupReason qemu_wakeup_requested(void)
> -{
> -    return wakeup_reason;
> -}
> -
> -static int qemu_powerdown_requested(void)
> -{
> -    int r = powerdown_requested;
> -    powerdown_requested = 0;
> -    return r;
> -}
> -
> -static int qemu_debug_requested(void)
> -{
> -    int r = debug_requested;
> -    debug_requested = 0;
> -    return r;
> -}
> -
> -/*
> - * Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
> - */
> -void qemu_system_reset(ShutdownCause reason)
> -{
> -    MachineClass *mc;
> -
> -    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
> -
> -    cpu_synchronize_all_states();
> -
> -    if (mc && mc->reset) {
> -        mc->reset(current_machine);
> -    } else {
> -        qemu_devices_reset();
> -    }
> -    if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> -        qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
> -    }
> -    cpu_synchronize_all_post_reset();
> -}
> -
> -/*
> - * Wake the VM after suspend.
> - */
> -static void qemu_system_wakeup(void)
> -{
> -    MachineClass *mc;
> -
> -    mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
> -
> -    if (mc && mc->wakeup) {
> -        mc->wakeup(current_machine);
> -    }
> -}
> -
> -void qemu_system_guest_panicked(GuestPanicInformation *info)
> -{
> -    qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
> -
> -    if (current_cpu) {
> -        current_cpu->crash_occurred = true;
> -    }
> -    qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
> -                                   !!info, info);
> -    vm_stop(RUN_STATE_GUEST_PANICKED);
> -    if (!no_shutdown) {
> -        qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
> -                                       !!info, info);
> -        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
> -    }
> -
> -    if (info) {
> -        if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
> -            qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
> -                          " %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
> -                          info->u.hyper_v.arg1,
> -                          info->u.hyper_v.arg2,
> -                          info->u.hyper_v.arg3,
> -                          info->u.hyper_v.arg4,
> -                          info->u.hyper_v.arg5);
> -        } else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
> -            qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
> -                          "PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
> -                          info->u.s390.core,
> -                          S390CrashReason_str(info->u.s390.reason),
> -                          info->u.s390.psw_mask,
> -                          info->u.s390.psw_addr);
> -        }
> -        qapi_free_GuestPanicInformation(info);
> -    }
> -}
> -
> -void qemu_system_guest_crashloaded(GuestPanicInformation *info)
> -{
> -    qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded");
> -
> -    qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN,
> -                                   !!info, info);
> -
> -    if (info) {
> -        qapi_free_GuestPanicInformation(info);
> -    }
> -}
> -
> -void qemu_system_reset_request(ShutdownCause reason)
> -{
> -    if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
> -        shutdown_requested = reason;
> -    } else {
> -        reset_requested = reason;
> -    }
> -    cpu_stop_current();
> -    qemu_notify_event();
> -}
> -
> -static void qemu_system_suspend(void)
> -{
> -    pause_all_vcpus();
> -    notifier_list_notify(&suspend_notifiers, NULL);
> -    runstate_set(RUN_STATE_SUSPENDED);
> -    qapi_event_send_suspend();
> -}
> -
> -void qemu_system_suspend_request(void)
> -{
> -    if (runstate_check(RUN_STATE_SUSPENDED)) {
> -        return;
> -    }
> -    suspend_requested = 1;
> -    cpu_stop_current();
> -    qemu_notify_event();
> -}
> -
> -void qemu_register_suspend_notifier(Notifier *notifier)
> -{
> -    notifier_list_add(&suspend_notifiers, notifier);
> -}
> -
> -void qemu_system_wakeup_request(WakeupReason reason, Error **errp)
> -{
> -    trace_system_wakeup_request(reason);
> -
> -    if (!runstate_check(RUN_STATE_SUSPENDED)) {
> -        error_setg(errp,
> -                   "Unable to wake up: guest is not in suspended state");
> -        return;
> -    }
> -    if (!(wakeup_reason_mask & (1 << reason))) {
> -        return;
> -    }
> -    runstate_set(RUN_STATE_RUNNING);
> -    wakeup_reason = reason;
> -    qemu_notify_event();
> -}
> -
> -void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
> -{
> -    if (enabled) {
> -        wakeup_reason_mask |= (1 << reason);
> -    } else {
> -        wakeup_reason_mask &= ~(1 << reason);
> -    }
> -}
> -
> -void qemu_register_wakeup_notifier(Notifier *notifier)
> -{
> -    notifier_list_add(&wakeup_notifiers, notifier);
> -}
> -
> -void qemu_register_wakeup_support(void)
> -{
> -    wakeup_suspend_enabled = true;
> -}
> -
> -bool qemu_wakeup_suspend_enabled(void)
> -{
> -    return wakeup_suspend_enabled;
> -}
> -
> -void qemu_system_killed(int signal, pid_t pid)
> -{
> -    shutdown_signal = signal;
> -    shutdown_pid = pid;
> -    no_shutdown = 0;
> -
> -    /* Cannot call qemu_system_shutdown_request directly because
> -     * we are in a signal handler.
> -     */
> -    shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
> -    qemu_notify_event();
> -}
> -
> -void qemu_system_shutdown_request(ShutdownCause reason)
> -{
> -    trace_qemu_system_shutdown_request(reason);
> -    replay_shutdown_request(reason);
> -    shutdown_requested = reason;
> -    qemu_notify_event();
> -}
> -
> -static void qemu_system_powerdown(void)
> -{
> -    qapi_event_send_powerdown();
> -    notifier_list_notify(&powerdown_notifiers, NULL);
> -}
> -
> -static void qemu_system_shutdown(ShutdownCause cause)
> -{
> -    qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause);
> -    notifier_list_notify(&shutdown_notifiers, &cause);
> -}
> -
> -void qemu_system_powerdown_request(void)
> -{
> -    trace_qemu_system_powerdown_request();
> -    powerdown_requested = 1;
> -    qemu_notify_event();
> -}
> -
> -void qemu_register_powerdown_notifier(Notifier *notifier)
> -{
> -    notifier_list_add(&powerdown_notifiers, notifier);
> -}
> -
> -void qemu_register_shutdown_notifier(Notifier *notifier)
> -{
> -    notifier_list_add(&shutdown_notifiers, notifier);
> -}
> -
> -void qemu_system_debug_request(void)
> -{
> -    debug_requested = 1;
> -    qemu_notify_event();
> -}
> -
> -static bool main_loop_should_exit(void)
> -{
> -    RunState r;
> -    ShutdownCause request;
> -
> -    if (qemu_debug_requested()) {
> -        vm_stop(RUN_STATE_DEBUG);
> -    }
> -    if (qemu_suspend_requested()) {
> -        qemu_system_suspend();
> -    }
> -    request = qemu_shutdown_requested();
> -    if (request) {
> -        qemu_kill_report();
> -        qemu_system_shutdown(request);
> -        if (no_shutdown) {
> -            vm_stop(RUN_STATE_SHUTDOWN);
> -        } else {
> -            return true;
> -        }
> -    }
> -    request = qemu_reset_requested();
> -    if (request) {
> -        pause_all_vcpus();
> -        qemu_system_reset(request);
> -        resume_all_vcpus();
> -        /*
> -         * runstate can change in pause_all_vcpus()
> -         * as iothread mutex is unlocked
> -         */
> -        if (!runstate_check(RUN_STATE_RUNNING) &&
> -                !runstate_check(RUN_STATE_INMIGRATE) &&
> -                !runstate_check(RUN_STATE_FINISH_MIGRATE)) {
> -            runstate_set(RUN_STATE_PRELAUNCH);
> -        }
> -    }
> -    if (qemu_wakeup_requested()) {
> -        pause_all_vcpus();
> -        qemu_system_wakeup();
> -        notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
> -        wakeup_reason = QEMU_WAKEUP_REASON_NONE;
> -        resume_all_vcpus();
> -        qapi_event_send_wakeup();
> -    }
> -    if (qemu_powerdown_requested()) {
> -        qemu_system_powerdown();
> -    }
> -    if (qemu_vmstop_requested(&r)) {
> -        vm_stop(r);
> -    }
> -    return false;
> -}
> -
> -void qemu_main_loop(void)
> -{
> -#ifdef CONFIG_PROFILER
> -    int64_t ti;
> -#endif
> -    while (!main_loop_should_exit()) {
> -#ifdef CONFIG_PROFILER
> -        ti = profile_getclock();
> -#endif
> -        main_loop_wait(false);
> -#ifdef CONFIG_PROFILER
> -        dev_time += profile_getclock() - ti;
> -#endif
> -    }
> -}
> -
>  static void version(void)
>  {
>      printf("QEMU emulator version " QEMU_FULL_VERSION "\n"
> @@ -2248,21 +1586,6 @@ static MachineClass *machine_parse(const char *name, GSList *machines)
>      return mc;
>  }
>  
> -void qemu_add_exit_notifier(Notifier *notify)
> -{
> -    notifier_list_add(&exit_notifiers, notify);
> -}
> -
> -void qemu_remove_exit_notifier(Notifier *notify)
> -{
> -    notifier_remove(notify);
> -}
> -
> -static void qemu_run_exit_notifiers(void)
> -{
> -    notifier_list_notify(&exit_notifiers, NULL);
> -}
> -
>  static const char *pid_file;
>  static Notifier qemu_unlink_pidfile_notifier;
>  
> @@ -3061,39 +2384,6 @@ static void qemu_maybe_daemonize(const char *pid_file)
>      qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
>  }
>  
> -static void qemu_init_subsystems(void)
> -{
> -    Error *err;
> -
> -    os_set_line_buffering();
> -
> -    module_call_init(MODULE_INIT_TRACE);
> -
> -    qemu_init_cpu_list();
> -    qemu_init_cpu_loop();
> -    qemu_mutex_lock_iothread();
> -
> -    atexit(qemu_run_exit_notifiers);
> -
> -    module_call_init(MODULE_INIT_QOM);
> -    module_call_init(MODULE_INIT_MIGRATION);
> -
> -    runstate_init();
> -    precopy_infrastructure_init();
> -    postcopy_infrastructure_init();
> -    monitor_init_globals();
> -
> -    if (qcrypto_init(&err) < 0) {
> -        error_reportf_err(err, "cannot initialize crypto: ");
> -        exit(1);
> -    }
> -
> -    os_setup_early_signal_handling();
> -
> -    bdrv_init_with_whitelist();
> -    socket_init();
> -}
> -
>  static void qemu_init_displays(void)
>  {
>      DisplayState *ds;
> @@ -4275,43 +3565,3 @@ void qemu_init(int argc, char **argv, char **envp)
>      accel_setup_post(current_machine);
>      os_setup_post();
>  }
> -
> -void qemu_cleanup(void)
> -{
> -    gdbserver_cleanup();
> -
> -    /*
> -     * cleaning up the migration object cancels any existing migration
> -     * try to do this early so that it also stops using devices.
> -     */
> -    migration_shutdown();
> -
> -    /*
> -     * We must cancel all block jobs while the block layer is drained,
> -     * or cancelling will be affected by throttling and thus may block
> -     * for an extended period of time.
> -     * vm_shutdown() will bdrv_drain_all(), so we may as well include
> -     * it in the drained section.
> -     * We do not need to end this section, because we do not want any
> -     * requests happening from here on anyway.
> -     */
> -    bdrv_drain_all_begin();
> -
> -    /* No more vcpu or device emulation activity beyond this point */
> -    vm_shutdown();
> -    replay_finish();
> -
> -    job_cancel_sync_all();
> -    bdrv_close_all();
> -
> -    res_free();
> -
> -    /* vhost-user must be cleaned up before chardevs.  */
> -    tpm_cleanup();
> -    net_cleanup();
> -    audio_cleanup();
> -    monitor_cleanup();
> -    qemu_chr_cleanup();
> -    user_creatable_cleanup();
> -    /* TODO: unref root container, check all devices are ok */
> -}



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 34/36] vl: remove serial_max_hds
  2020-11-23 14:14 ` [PATCH 34/36] vl: remove serial_max_hds Paolo Bonzini
@ 2020-11-27 13:11   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 13:11 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:33 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> serial_hd(i) is NULL if and only if i >= serial_max_hds().  Test
> serial_hd(i) instead of bounding the loop at serial_max_hds(),
> thus removing one more function that vl.c is expected to export.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  hw/ppc/spapr.c          | 6 ++----
>  include/sysemu/sysemu.h | 4 ----
>  softmmu/vl.c            | 5 -----
>  3 files changed, 2 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 049efa0bbf..b7e0894019 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -2878,10 +2878,8 @@ static void spapr_machine_init(MachineState *machine)
>      /* Set up VIO bus */
>      spapr->vio_bus = spapr_vio_bus_init();
>  
> -    for (i = 0; i < serial_max_hds(); i++) {
> -        if (serial_hd(i)) {
> -            spapr_vty_create(spapr->vio_bus, serial_hd(i));
> -        }
> +    for (i = 0; serial_hd(i); i++) {
> +        spapr_vty_create(spapr->vio_bus, serial_hd(i));
>      }
>  
>      /* We always have at least the nvram device on VIO */
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 3dac3229ec..0e7b405d22 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -74,10 +74,6 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict);
>  
>  /* Return the Chardev for serial port i, or NULL if none */
>  Chardev *serial_hd(int i);
> -/* return the number of serial ports defined by the user. serial_hd(i)
> - * will always return NULL for any i which is greater than or equal to this.
> - */
> -int serial_max_hds(void);
>  
>  /* parallel ports */
>  
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index fce15c249a..d76f87028d 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -1439,11 +1439,6 @@ Chardev *serial_hd(int i)
>      return NULL;
>  }
>  
> -int serial_max_hds(void)
> -{
> -    return num_serial_hds;
> -}
> -
>  static int parallel_parse(const char *devname)
>  {
>      static int index = 0;



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 35/36] vl: clean up -boot variables
  2020-11-23 14:14 ` [PATCH 35/36] vl: clean up -boot variables Paolo Bonzini
@ 2020-11-27 13:12   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 13:12 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:34 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Move more of them into MachineState, in preparation for moving initialization
> of the machine out of vl.c.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  include/hw/boards.h |  1 +
>  softmmu/vl.c        | 11 ++++++-----
>  2 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/include/hw/boards.h b/include/hw/boards.h
> index 4537cfb5c6..b9233af54a 100644
> --- a/include/hw/boards.h
> +++ b/include/hw/boards.h
> @@ -283,6 +283,7 @@ struct MachineState {
>      ram_addr_t maxram_size;
>      uint64_t   ram_slots;
>      const char *boot_order;
> +    const char *boot_once;
>      char *kernel_filename;
>      char *kernel_cmdline;
>      char *initrd_filename;
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index d76f87028d..aeb988bcad 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -132,8 +132,6 @@ typedef QSIMPLEQ_HEAD(, BlockdevOptionsQueueEntry) BlockdevOptionsQueue;
>  
>  static const char *cpu_option;
>  static const char *mem_path;
> -static const char *boot_order;
> -static const char *boot_once;
>  static const char *incoming;
>  static const char *loadvm;
>  static ram_addr_t maxram_size;
> @@ -1733,6 +1731,8 @@ static void qemu_apply_machine_options(void)
>  {
>      MachineClass *machine_class = MACHINE_GET_CLASS(current_machine);
>      QemuOpts *machine_opts = qemu_get_machine_opts();
> +    const char *boot_order = NULL;
> +    const char *boot_once = NULL;
>      QemuOpts *opts;
>  
>      qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
> @@ -1762,6 +1762,7 @@ static void qemu_apply_machine_options(void)
>      }
>  
>      current_machine->boot_order = boot_order;
> +    current_machine->boot_once = boot_once;
>  }
>  
>  static void qemu_create_early_backends(void)
> @@ -2444,9 +2445,9 @@ static void qemu_machine_creation_done(void)
>  
>      qdev_prop_check_globals();
>  
> -    if (boot_once) {
> -        qemu_boot_set(boot_once, &error_fatal);
> -        qemu_register_reset(restore_boot_order, g_strdup(boot_order));
> +    if (current_machine->boot_once) {
> +        qemu_boot_set(current_machine->boot_once, &error_fatal);
> +        qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
>      }
>  
>      if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 33/36] vl: extract softmmu/globals.c
  2020-11-23 14:14 ` [PATCH 33/36] vl: extract softmmu/globals.c Paolo Bonzini
@ 2020-11-27 13:19   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 13:19 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:32 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  hw/core/machine.c         |  2 ++
>  include/exec/cpu-common.h |  3 ++
>  include/exec/exec-all.h   |  3 --
>  softmmu/globals.c         | 74 +++++++++++++++++++++++++++++++++++++++
>  softmmu/meson.build       |  1 +
>  softmmu/vl.c              | 45 ++----------------------
>  6 files changed, 83 insertions(+), 45 deletions(-)
>  create mode 100644 softmmu/globals.c
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 745531c9d9..5659b1f49c 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -213,6 +213,8 @@ GlobalProperty hw_compat_2_1[] = {
>  };
>  const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
>  
> +MachineState *current_machine;
> +
>  static char *machine_get_kernel(Object *obj, Error **errp)
>  {
>      MachineState *ms = MACHINE(obj);
> diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
> index bd5e15dd7d..5a0a2d93e0 100644
> --- a/include/exec/cpu-common.h
> +++ b/include/exec/cpu-common.h
> @@ -105,4 +105,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
>  
>  #endif
>  
> +/* vl.c */
> +extern int singlestep;
> +
>  #endif /* CPU_COMMON_H */
> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 94fe05daaa..fab573da06 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -676,7 +676,4 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
>                                         MemoryRegionSection *section);
>  #endif
>  
> -/* vl.c */
> -extern int singlestep;
> -
>  #endif
> diff --git a/softmmu/globals.c b/softmmu/globals.c
> new file mode 100644
> index 0000000000..e62d9cd8da
> --- /dev/null
> +++ b/softmmu/globals.c
> @@ -0,0 +1,74 @@
> +/*
> + * Global variables that (mostly) should not exist
> + *
> + * Copyright (c) 2003-2020 QEMU contributors
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "exec/cpu-common.h"
> +#include "hw/display/vga.h"
> +#include "hw/i386/pc.h"
> +#include "hw/i386/x86.h"
> +#include "hw/loader.h"
> +#include "hw/xen/xen.h"
> +#include "net/net.h"
> +#include "sysemu/cpus.h"
> +#include "sysemu/sysemu.h"
> +
> +enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
> +int display_opengl;
> +const char* keyboard_layout;
> +bool enable_mlock;
> +bool enable_cpu_pm;
> +int nb_nics;
> +NICInfo nd_table[MAX_NICS];
> +int autostart = 1;
> +int vga_interface_type = VGA_NONE;
> +Chardev *parallel_hds[MAX_PARALLEL_PORTS];
> +int win2k_install_hack;
> +int singlestep;
> +int fd_bootchk = 1;
> +int no_reboot;
> +int no_shutdown;
> +int graphic_rotate;
> +QEMUOptionRom option_rom[MAX_OPTION_ROMS];
> +int nb_option_roms;
> +int old_param;
> +const char *qemu_name;
> +int alt_grab;
> +int ctrl_grab;
> +unsigned int nb_prom_envs;
> +const char *prom_envs[MAX_PROM_ENVS];
> +int boot_menu;
> +bool boot_strict;
> +uint8_t *boot_splash_filedata;
> +int only_migratable; /* turn it off unless user states otherwise */
> +int icount_align_option;
> +
> +/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the
> + * little-endian "wire format" described in the SMBIOS 2.6 specification.
> + */
> +QemuUUID qemu_uuid;
> +bool qemu_uuid_set;
> +
> +uint32_t xen_domid;
> +enum xen_mode xen_mode = XEN_EMULATE;
> +bool xen_domid_restrict;
> diff --git a/softmmu/meson.build b/softmmu/meson.build
> index 2a73ebc223..e5865b97cb 100644
> --- a/softmmu/meson.build
> +++ b/softmmu/meson.build
> @@ -4,6 +4,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
>    'cpus.c',
>    'cpu-throttle.c',
>    'datadir.c',
> +  'globals.c',
>    'physmem.c',
>    'ioport.c',
>    'rtc.c',
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 914b86ee86..fce15c249a 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -26,6 +26,7 @@
>  #include "qemu-common.h"
>  #include "qemu/datadir.h"
>  #include "qemu/units.h"
> +#include "exec/cpu-common.h"
>  #include "hw/boards.h"
>  #include "hw/qdev-properties.h"
>  #include "qapi/error.h"
> @@ -67,6 +68,8 @@
>  #include "qemu/log.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/block/block.h"
> +#include "hw/i386/x86.h"
> +#include "hw/i386/pc.h"
>  #include "migration/misc.h"
>  #include "migration/snapshot.h"
>  #include "migration/global_state.h"
> @@ -141,17 +144,8 @@ 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;
> -enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
>  static int mem_prealloc; /* force preallocation of physical target memory */
> -int display_opengl;
> -const char* keyboard_layout = NULL;
>  static ram_addr_t ram_size;
> -bool enable_mlock = false;
> -bool enable_cpu_pm = false;
> -int nb_nics;
> -NICInfo nd_table[MAX_NICS];
> -int autostart = 1;
> -int vga_interface_type = VGA_NONE;
>  static const char *vga_model = NULL;
>  static DisplayOptions dpy;
>  static int num_serial_hds;
> @@ -159,41 +153,10 @@ static Chardev **serial_hds;
>  static const char *log_mask;
>  static const char *log_file;
>  static bool list_data_dirs;
> -Chardev *parallel_hds[MAX_PARALLEL_PORTS];
> -int win2k_install_hack = 0;
> -int singlestep = 0;
> -int fd_bootchk = 1;
> -int no_reboot;
> -int no_shutdown = 0;
> -int graphic_rotate = 0;
>  static const char *watchdog;
> -QEMUOptionRom option_rom[MAX_OPTION_ROMS];
> -int nb_option_roms;
> -int old_param = 0;
> -const char *qemu_name;
> -int alt_grab = 0;
> -int ctrl_grab = 0;
> -unsigned int nb_prom_envs = 0;
> -const char *prom_envs[MAX_PROM_ENVS];
> -int boot_menu;
> -bool boot_strict;
> -uint8_t *boot_splash_filedata;
> -int only_migratable; /* turn it off unless user states otherwise */
> -bool wakeup_suspend_enabled;
> -int icount_align_option;
>  static const char *qtest_chrdev;
>  static const char *qtest_log;
>  
> -/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the
> - * little-endian "wire format" described in the SMBIOS 2.6 specification.
> - */
> -QemuUUID qemu_uuid;
> -bool qemu_uuid_set;
> -
> -uint32_t xen_domid;
> -enum xen_mode xen_mode = XEN_EMULATE;
> -bool xen_domid_restrict;
> -
>  static int has_defaults = 1;
>  static int default_serial = 1;
>  static int default_parallel = 1;
> @@ -801,8 +764,6 @@ static int usb_parse(const char *cmdline)
>  /***********************************************************/
>  /* machine registration */
>  
> -MachineState *current_machine;
> -
>  static MachineClass *find_machine(const char *name, GSList *machines)
>  {
>      GSList *el;



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 37/36] machine: introduce MachineInitPhase
  2020-11-27 12:00 ` [PATCH 37/36] machine: introduce MachineInitPhase Paolo Bonzini
@ 2020-11-27 13:29   ` Igor Mammedov
  2020-11-27 15:29     ` Paolo Bonzini
  0 siblings, 1 reply; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 13:29 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Fri, 27 Nov 2020 07:00:21 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Generalize the qdev_hotplug variable to the different phases of
> machine initialization.  We would like to allow different
> monitor commands depending on the phase.

new machine states need more documentation
+ a couple more comments below

> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> 	This has to be the last patch because patch 36 is where
> 	hw/core/machine.c takes care of setting qdev_hotplug to true.
> 
> 	And this explains the weird [PATCH 00/37] in the previous
> 	version of the RFC. :)
> 
>  hw/core/machine-qmp-cmds.c |  6 +++---
>  hw/core/machine.c          |  3 ++-
>  hw/core/qdev.c             | 16 ++++++++++++++--
>  hw/pci/pci.c               |  2 +-
>  hw/usb/core.c              |  2 +-
>  hw/virtio/virtio-iommu.c   |  2 +-
>  include/hw/qdev-core.h     | 12 +++++++++++-
>  monitor/hmp.c              |  2 +-
>  softmmu/qdev-monitor.c     | 24 +++++++++++++-----------
>  softmmu/vl.c               |  4 +++-
>  ui/console.c               |  2 +-
>  11 files changed, 51 insertions(+), 24 deletions(-)
> 
> diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
> index cb9387c5f5..6cbeb688c4 100644
> --- a/hw/core/machine-qmp-cmds.c
> +++ b/hw/core/machine-qmp-cmds.c
> @@ -286,9 +286,9 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
>  
>  void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
>  {
> -    if (qdev_hotplug) {
> -         error_setg(errp, "The command is permitted only before the machine has been created");
> -         return;
> +    if (phase_check(PHASE_MACHINE_READY)) {
that's what I was afraid of in 26/36,
it should be PHASE_MACHINE_INITIALIZED

> +        error_setg(errp, "The command is permitted only before the machine has been created");
> +        return;
>      }
>  
>      set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 025c4f9749..a71cb23ecf 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -1171,6 +1171,7 @@ void machine_run_board_init(MachineState *machine)
>      }
>  
>      machine_class->init(machine);
> +    phase_advance(PHASE_MACHINE_INITIALIZED);
>  }
>  
>  static NotifierList machine_init_done_notifiers =
> @@ -1204,7 +1205,7 @@ void qdev_machine_creation_done(void)
>       * ok, initial machine setup is done, starting from now we can
>       * only create hotpluggable devices
>       */
> -    qdev_hotplug = true;
> +    phase_advance(PHASE_MACHINE_READY);
>      qdev_assert_realized_properly();
>  
>      /* TODO: once all bus devices are qdevified, this should be done
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index bc5df8ce69..beb35879c6 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -41,7 +41,6 @@
>  #include "migration/vmstate.h"
>  #include "trace.h"
>  
> -bool qdev_hotplug = false;
>  static bool qdev_hot_added = false;
>  bool qdev_hot_removed = false;
>  
> @@ -1023,7 +1022,7 @@ static void device_initfn(Object *obj)
>  {
>      DeviceState *dev = DEVICE(obj);
>  
> -    if (qdev_hotplug) {
> +    if (phase_check(PHASE_MACHINE_READY)) {
>          dev->hotplugged = 1;
>          qdev_hot_added = true;
>      }
> @@ -1267,6 +1266,19 @@ Object *qdev_get_machine(void)
>      return dev;
>  }
>  
> +static MachineInitPhase machine_phase;
> +
> +bool phase_check(MachineInitPhase phase)
> +{
> +    return machine_phase >= phase;
> +}
> +
> +void phase_advance(MachineInitPhase phase)
> +{
> +    assert(machine_phase == phase - 1);
> +    machine_phase = phase;
> +}
> +
>  static const TypeInfo device_type_info = {
>      .name = TYPE_DEVICE,
>      .parent = TYPE_OBJECT,
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 9424231542..d4349ea577 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -1062,7 +1062,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
>      address_space_init(&pci_dev->bus_master_as,
>                         &pci_dev->bus_master_container_region, pci_dev->name);
>  
> -    if (qdev_hotplug) {
> +    if (phase_check(PHASE_MACHINE_READY)) {
>          pci_init_bus_master(pci_dev);
>      }
>      pci_dev->irq_state = 0;
> diff --git a/hw/usb/core.c b/hw/usb/core.c
> index 5234dcc73f..e960036f4d 100644
> --- a/hw/usb/core.c
> +++ b/hw/usb/core.c
> @@ -97,7 +97,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
>      USBDevice *dev = ep->dev;
>      USBBus *bus = usb_bus_from_device(dev);
>  
> -    if (!qdev_hotplug) {
> +    if (!phase_check(PHASE_MACHINE_READY)) {
>          /*
>           * This is machine init cold plug.  No need to wakeup anyone,
>           * all devices will be reset anyway.  And trying to wakeup can
> diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
> index fc5c75d693..8370fd80d7 100644
> --- a/hw/virtio/virtio-iommu.c
> +++ b/hw/virtio/virtio-iommu.c
> @@ -928,7 +928,7 @@ static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
>       * accept it. Having a different masks is possible but the guest will use
>       * sub-optimal block sizes, so warn about it.
>       */
> -    if (qdev_hotplug) {
> +    if (phase_check(PHASE_MACHINE_READY)) {
>          int new_granule = ctz64(new_mask);
>          int cur_granule = ctz64(cur_mask);
>  
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 6446846752..05e7e7bc45 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -821,7 +821,6 @@ Object *qdev_get_machine(void);
>  /* FIXME: make this a link<> */
>  bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
>  
> -extern bool qdev_hotplug;
>  extern bool qdev_hot_removed;
>  
>  char *qdev_get_dev_path(DeviceState *dev);
> @@ -847,4 +846,15 @@ void device_listener_unregister(DeviceListener *listener);
>   */
>  bool qdev_should_hide_device(QemuOpts *opts);
>  
> +typedef enum MachineInitPhase {
> +    PHASE_NO_MACHINE,
> +    PHASE_MACHINE_CREATED,
> +    PHASE_ACCEL_CREATED,
> +    PHASE_MACHINE_INITIALIZED,
> +    PHASE_MACHINE_READY,
> +} MachineInitPhase;
Perhaps add doc comments here describing phases?

> +
> +extern bool phase_check(MachineInitPhase phase);
> +extern void phase_advance(MachineInitPhase phase);
> +
>  #endif
> diff --git a/monitor/hmp.c b/monitor/hmp.c
> index f2fe192d69..6c0b33a0b1 100644
> --- a/monitor/hmp.c
> +++ b/monitor/hmp.c
> @@ -216,7 +216,7 @@ static bool cmd_can_preconfig(const HMPCommand *cmd)
>  
>  static bool cmd_available(const HMPCommand *cmd)
>  {
> -    return qdev_hotplug || cmd_can_preconfig(cmd);
> +    return phase_check(PHASE_MACHINE_READY) || cmd_can_preconfig(cmd);
>  }
>  
>  static void help_cmd_dump_one(Monitor *mon,
> diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
> index e967d13bd0..184fe317af 100644
> --- a/softmmu/qdev-monitor.c
> +++ b/softmmu/qdev-monitor.c
> @@ -244,7 +244,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
>  
>      dc = DEVICE_CLASS(oc);
>      if (!dc->user_creatable ||
> -        (qdev_hotplug && !dc->hotpluggable)) {
> +        (phase_check(PHASE_MACHINE_READY) && !dc->hotpluggable)) {
>          error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
>                     "pluggable device type");
>          return NULL;
> @@ -637,7 +637,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
>      }
>      hide = should_hide_device(opts);
>  
> -    if ((hide || qdev_hotplug) && bus && !qbus_is_hotpluggable(bus)) {
> +    if ((hide || phase_check(PHASE_MACHINE_READY)) && bus && !qbus_is_hotpluggable(bus)) {
>          error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name);
>          return NULL;
>      }
> @@ -655,15 +655,17 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
>      dev = qdev_new(driver);
>  
>      /* Check whether the hotplug is allowed by the machine */
> -    if (qdev_hotplug && !qdev_hotplug_allowed(dev, errp)) {
> -        goto err_del_dev;
> -    }
> +    if (phase_check(PHASE_MACHINE_READY)) {
> +        if (!qdev_hotplug_allowed(dev, errp)) {
> +            goto err_del_dev;
> +        }
>  
> -    if (!bus && qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
> -        /* No bus, no machine hotplug handler --> device is not hotpluggable */
> -        error_setg(errp, "Device '%s' can not be hotplugged on this machine",
> -                   driver);
> -        goto err_del_dev;
> +        if (!bus && !qdev_get_machine_hotplug_handler(dev)) {
> +            /* No bus, no machine hotplug handler --> device is not hotpluggable */
> +            error_setg(errp, "Device '%s' can not be hotplugged on this machine",
> +                       driver);
> +            goto err_del_dev;
> +        }
>      }
>  
>      qdev_set_id(dev, qemu_opts_id(opts));
> @@ -1001,7 +1003,7 @@ int qemu_global_option(const char *str)
>  
>  bool qmp_command_available(const QmpCommand *cmd, Error **errp)
>  {
> -    if (!qdev_hotplug &&
> +    if (!phase_check(PHASE_MACHINE_READY) &&
>          !(cmd->options & QCO_ALLOW_PRECONFIG)) {
>          error_setg(errp, "The command '%s' is permitted only after machine initialization has completed",
>                     cmd->name);
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 1fde4a17a9..2dd5c2c775 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2451,7 +2451,7 @@ static void qemu_machine_creation_done(void)
>  
>  void qmp_x_exit_preconfig(Error **errp)
>  {
> -    if (qdev_hotplug) {
> +    if (phase_check(PHASE_MACHINE_READY)) {
>          error_setg(errp, "The command is permitted only before machine initialization");
>          return;
>      }
> @@ -3428,12 +3428,14 @@ void qemu_init(int argc, char **argv, char **envp)
>      qemu_create_early_backends();
>  
>      qemu_apply_machine_options();
> +    phase_advance(PHASE_MACHINE_CREATED);
>  
>      /*
>       * Note: uses machine properties such as kernel-irqchip, must run
>       * after machine_set_property().
>       */
>      configure_accelerators(argv[0]);
> +    phase_advance(PHASE_ACCEL_CREATED);
>  
>      /*
>       * Beware, QOM objects created before this point miss global and
> diff --git a/ui/console.c b/ui/console.c
> index e07d2c380d..3a98135daa 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -1343,7 +1343,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
>      if (QTAILQ_EMPTY(&consoles)) {
>          s->index = 0;
>          QTAILQ_INSERT_TAIL(&consoles, s, next);
> -    } else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
> +    } else if (console_type != GRAPHIC_CONSOLE || phase_check(PHASE_MACHINE_READY)) {
>          QemuConsole *last = QTAILQ_LAST(&consoles);
>          s->index = last->index + 1;
>          QTAILQ_INSERT_TAIL(&consoles, s, next);



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 36/36] vl: move all generic initialization out of vl.c
  2020-11-23 14:14 ` [PATCH 36/36] vl: move all generic initialization out of vl.c Paolo Bonzini
@ 2020-11-27 13:30   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-27 13:30 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:35 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> qdev_machine_creation_done is only setting a flag now.  Extend it to
> move more code out of vl.c.  Leave only consistency checks and gdbserver
> processing in qemu_machine_creation_done.
> 
> gdbserver_start can be moved after qdev_machine_creation_done because
> it only does listen on the socket and creates some internal data
> structures; it does not send any data (e.g. guest state) over the socket.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Reviewed-by: 

> ---
>  hw/core/machine.c      | 47 +++++++++++++++++++++++++++++++++++++++++-
>  hw/core/qdev.c         | 12 +++--------
>  include/hw/qdev-core.h |  1 +
>  softmmu/vl.c           | 37 +--------------------------------
>  4 files changed, 51 insertions(+), 46 deletions(-)
> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 5659b1f49c..025c4f9749 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -16,16 +16,21 @@
>  #include "sysemu/replay.h"
>  #include "qemu/units.h"
>  #include "hw/boards.h"
> +#include "hw/loader.h"
>  #include "qapi/error.h"
>  #include "qapi/qapi-visit-common.h"
>  #include "qapi/visitor.h"
>  #include "hw/sysbus.h"
> +#include "sysemu/cpus.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/reset.h"
> +#include "sysemu/runstate.h"
>  #include "sysemu/numa.h"
>  #include "qemu/error-report.h"
>  #include "sysemu/qtest.h"
>  #include "hw/pci/pci.h"
>  #include "hw/mem/nvdimm.h"
> +#include "migration/global_state.h"
>  #include "migration/vmstate.h"
>  
>  GlobalProperty hw_compat_5_1[] = {
> @@ -1186,10 +1191,50 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify)
>      notifier_remove(notify);
>  }
>  
> -void qemu_run_machine_init_done_notifiers(void)
> +void qdev_machine_creation_done(void)
>  {
> +    cpu_synchronize_all_post_init();
> +
> +    if (current_machine->boot_once) {
> +        qemu_boot_set(current_machine->boot_once, &error_fatal);
> +        qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
> +    }
> +
> +    /*
> +     * ok, initial machine setup is done, starting from now we can
> +     * only create hotpluggable devices
> +     */
> +    qdev_hotplug = true;
> +    qdev_assert_realized_properly();
> +
> +    /* TODO: once all bus devices are qdevified, this should be done
> +     * when bus is created by qdev.c */
> +    /*
> +     * TODO: If we had a main 'reset container' that the whole system
> +     * lived in, we could reset that using the multi-phase reset
> +     * APIs. For the moment, we just reset the sysbus, which will cause
> +     * all devices hanging off it (and all their child buses, recursively)
> +     * to be reset. Note that this will *not* reset any Device objects
> +     * which are not attached to some part of the qbus tree!
> +     */
> +    qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
> +
>      machine_init_done = true;
>      notifier_list_notify(&machine_init_done_notifiers, NULL);
> +
> +    if (rom_check_and_register_reset() != 0) {
> +        error_report("rom check and register reset failed");
> +        exit(1);
> +    }
> +
> +    replay_start();
> +
> +    /* This checkpoint is required by replay to separate prior clock
> +       reading from the other reads, because timer polling functions query
> +       clock values from the log. */
> +    replay_checkpoint(CHECKPOINT_RESET);
> +    qemu_system_reset(SHUTDOWN_CAUSE_NONE);
> +    register_global_state();
>  }
>  
>  static const TypeInfo machine_info = {
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 262bca716f..bc5df8ce69 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -413,7 +413,7 @@ void qdev_unrealize(DeviceState *dev)
>      object_property_set_bool(OBJECT(dev), "realized", false, &error_abort);
>  }
>  
> -static int qdev_assert_realized_properly(Object *obj, void *opaque)
> +static int qdev_assert_realized_properly_cb(Object *obj, void *opaque)
>  {
>      DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE));
>      DeviceClass *dc;
> @@ -426,16 +426,10 @@ static int qdev_assert_realized_properly(Object *obj, void *opaque)
>      return 0;
>  }
>  
> -void qdev_machine_creation_done(void)
> +void qdev_assert_realized_properly(void)
>  {
> -    /*
> -     * ok, initial machine setup is done, starting from now we can
> -     * only create hotpluggable devices
> -     */
> -    qdev_hotplug = true;
> -
>      object_child_foreach_recursive(object_get_root(),
> -                                   qdev_assert_realized_properly, NULL);
> +                                   qdev_assert_realized_properly_cb, NULL);
>  }
>  
>  bool qdev_machine_modified(void)
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index b77a2f1da7..6446846752 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -815,6 +815,7 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
>  
>  const char *qdev_fw_name(DeviceState *dev);
>  
> +void qdev_assert_realized_properly(void);
>  Object *qdev_get_machine(void);
>  
>  /* FIXME: make this a link<> */
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index aeb988bcad..1fde4a17a9 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -72,7 +72,6 @@
>  #include "hw/i386/pc.h"
>  #include "migration/misc.h"
>  #include "migration/snapshot.h"
> -#include "migration/global_state.h"
>  #include "sysemu/tpm.h"
>  #include "sysemu/dma.h"
>  #include "hw/audio/soundhw.h"
> @@ -2426,8 +2425,6 @@ static void qemu_create_cli_devices(void)
>  
>  static void qemu_machine_creation_done(void)
>  {
> -    cpu_synchronize_all_post_init();
> -
>      /* Did we create any drives that we failed to create a device for? */
>      drive_check_orphaned();
>  
> @@ -2445,43 +2442,11 @@ static void qemu_machine_creation_done(void)
>  
>      qdev_prop_check_globals();
>  
> -    if (current_machine->boot_once) {
> -        qemu_boot_set(current_machine->boot_once, &error_fatal);
> -        qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
> -    }
> -
> -    if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
> -        exit(1);
> -    }
> -
>      qdev_machine_creation_done();
>  
> -    /* TODO: once all bus devices are qdevified, this should be done
> -     * when bus is created by qdev.c */
> -    /*
> -     * TODO: If we had a main 'reset container' that the whole system
> -     * lived in, we could reset that using the multi-phase reset
> -     * APIs. For the moment, we just reset the sysbus, which will cause
> -     * all devices hanging off it (and all their child buses, recursively)
> -     * to be reset. Note that this will *not* reset any Device objects
> -     * which are not attached to some part of the qbus tree!
> -     */
> -    qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
> -    qemu_run_machine_init_done_notifiers();
> -
> -    if (rom_check_and_register_reset() != 0) {
> -        error_report("rom check and register reset failed");
> +    if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
>          exit(1);
>      }
> -
> -    replay_start();
> -
> -    /* This checkpoint is required by replay to separate prior clock
> -       reading from the other reads, because timer polling functions query
> -       clock values from the log. */
> -    replay_checkpoint(CHECKPOINT_RESET);
> -    qemu_system_reset(SHUTDOWN_CAUSE_NONE);
> -    register_global_state();
>  }
>  
>  void qmp_x_exit_preconfig(Error **errp)



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 37/36] machine: introduce MachineInitPhase
  2020-11-27 13:29   ` Igor Mammedov
@ 2020-11-27 15:29     ` Paolo Bonzini
  0 siblings, 0 replies; 70+ messages in thread
From: Paolo Bonzini @ 2020-11-27 15:29 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On 27/11/20 14:29, Igor Mammedov wrote:
>>   void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
>>   {
>> -    if (qdev_hotplug) {
>> -         error_setg(errp, "The command is permitted only before the machine has been created");
>> -         return;
>> +    if (phase_check(PHASE_MACHINE_READY)) {
> that's what I was afraid of in 26/36,
> it should be PHASE_MACHINE_INITIALIZED
> 
Indeed it should, and the same goes for qmp_x_exit_preconfig.  Also, 
it's probably best to add a comment to qemu_init_board, like

+    /* From here on we enter MACHINE_PHASE_INITIALIZED.  */
      machine_run_board_init(current_machine);

Paolo



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 26/36] remove preconfig state
  2020-11-27 11:50         ` Paolo Bonzini
@ 2020-11-30 12:41           ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-30 12:41 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Fri, 27 Nov 2020 12:50:39 +0100
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 27/11/20 11:50, Igor Mammedov wrote:
> > it works in context of this series since
> > 
> >    +    qemu_init_board();
> >    +    qemu_create_cli_devices();
> >    +    qemu_machine_creation_done();
> > 
> > are called within the same command qmp_x_exit_preconfig,
> > if preconfig is enabled we happen to call qmp_set_numa_node()
> > and if (qdev_hotplug) {error} work as expected, since qemu_init_board()
> > hasn't been called yet.
> > 
> > but I'm thinking about what happens beyond this series, when we start
> > splitting qmp_x_exit_preconfig() after this series on separate stages.  
> 
> Ok, so that's the source of confusion.  I don't think anymore that 
> x-exit-preconfig should be split in separate stages; I'm not looking 
> anymore at being able to do device-add from "qemu-system-x86_64 
> -preconfig".  Instead, I'm looking at having a completely separate 
> executable for QMP-only machine creation, which would not use vl.c 
> command line parsing at all.
> 
> For this reason I've left MachinePhase to a separate series, which I 
> still plan for 6.0.  But I will add it here instead.
Assuming that qmp_x_exit_preconfig() won't be split:

 Reviewed-by: Igor Mammedov <imammedo@redhat.com>


> FWIW I intend to have four parts: 1) this 2) QemuOpts->keyval switch for 
> -object/-M/-accel 3) making Machine's memdev property a 
> link<memory-backend> 4) making -smp/-boot/-m sugar for non-scalar 
> properties of Machine.  I'll definitely need your review on part 3 too!

I can review #3, #4 and your ram_size cleanup, which I'm somewhat familiar with.

> 
> Thanks,
> 
> Paolo
> 
> > By using qdev_hotplug here, we practically loose dependency tracking
> > on qemu_init_board() not being yet called. And if later we forget that,
> > then it would allow to call qmp_set_numa_node() after qemu_init_board()
> > but before qemu_machine_creation_done()
> > 
> > So for this intermediate stage, instead of abusing qdev_hotplug adding
> > a temporary is_board_created might be used. And when we introduce
> > new phases you've described below, is_board_created could be replaced
> > with appropriate phase check.  
> 



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH 27/36] vl: remove separate preconfig main_loop
  2020-11-23 14:14 ` [PATCH 27/36] vl: remove separate preconfig main_loop Paolo Bonzini
@ 2020-11-30 12:46   ` Igor Mammedov
  0 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-30 12:46 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

On Mon, 23 Nov 2020 09:14:26 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Move post-preconfig initialization to the x-exit-preconfig.  If preconfig
> is not requested, just exit preconfig mode immediately with the QMP
> command.
> 
> As a result, the preconfig loop will run with accel_setup_post
> and os_setup_post restrictions (xen_restrict, chroot, etc.)
> already done.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

with a comment at qmp_x_exit_preconfig():
 Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
[...]
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 95c62bdad4..aa11fc4871 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
[...]
> @@ -3517,6 +3507,43 @@ static void qemu_machine_creation_done(void)
>      register_global_state();
>  }
>  
> +void qmp_x_exit_preconfig(Error **errp)

this needs a comment that it shouldn't be split without taking care of
qmp commands that were allowed to be called before qemu_init_board(),
otherwise there would be nothing to remind us about it.

> +{
> +    if (qdev_hotplug) {
> +        error_setg(errp, "The command is permitted only before machine initialization");
> +        return;
> +    }
> +
> +    qemu_init_board();
> +    qemu_create_cli_devices();
> +    qemu_machine_creation_done();
> +
> +    if (loadvm) {
> +        Error *local_err = NULL;
> +        if (load_snapshot(loadvm, &local_err) < 0) {
> +            error_report_err(local_err);
> +            autostart = 0;
> +            exit(1);
> +        }
> +    }
> +    if (replay_mode != REPLAY_MODE_NONE) {
> +        replay_vmstate_init();
> +    }
> +
> +    if (incoming) {
> +        Error *local_err = NULL;
> +        if (strcmp(incoming, "defer") != 0) {
> +            qmp_migrate_incoming(incoming, &local_err);
> +            if (local_err) {
> +                error_reportf_err(local_err, "-incoming %s: ", incoming);
> +                exit(1);
> +            }
> +        }
> +    } else if (autostart) {
> +        qmp_cont(NULL);
> +    }
> +}
> +
>  void qemu_init(int argc, char **argv, char **envp)
>  {
>      QemuOpts *opts;
[...]



^ permalink raw reply	[flat|nested] 70+ messages in thread

* Re: [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing
  2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
                   ` (36 preceding siblings ...)
  2020-11-27 12:00 ` [PATCH 37/36] machine: introduce MachineInitPhase Paolo Bonzini
@ 2020-11-30 12:50 ` Igor Mammedov
  37 siblings, 0 replies; 70+ messages in thread
From: Igor Mammedov @ 2020-11-30 12:50 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, armbru

On Mon, 23 Nov 2020 09:13:59 -0500
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Incompatible changes WRT 5.x:
> 
> - "-incoming defer" will not generate a MIGRATION event until
>   the migrate-incoming command is sent
> 
> - the "preconfig" runstate is not reported anymore, and is replaced
>   with "prelaunch"

I completed reviewing this series (modulo 10/36) which I'm not confident
enough to review. I think Markus might be better fit for reviewing it.

> Since the patches build on a bunch of more mechanical changes to
> remove the ram_size and bios_name global variables, which affect
> all targets, I have already placed the result in the for-6.0 branch of
> my gitlab repository.  The branch has also passed CI already.
> 
> Thanks,
> 
> Paolo
> 
> Paolo Bonzini (36):
>   vl: extract validation of -smp to machine.c
>   vl: remove bogus check
>   vl: split various early command line options to a separate function
>   vl: move various initialization routines out of qemu_init
>   vl: extract qemu_init_subsystems
>   vl: move prelaunch part of qemu_init to new functions
>   vl: extract various command line validation snippets to a new function
>   vl: preconfig and loadvm are mutually exclusive
>   vl: extract various command line desugaring snippets to a new function
>   qemu-option: restrict qemu_opts_set to merge-lists QemuOpts
>   vl: create "-net nic -net user" default earlier
>   vl: load plugins as late as possible
>   vl: move semihosting command line fallback to qemu_init_board
>   vl: extract default devices to separate functions
>   vl: move CHECKPOINT_INIT after preconfig
>   vl: separate qemu_create_early_backends
>   vl: separate qemu_create_late_backends
>   vl: separate qemu_create_machine
>   vl: separate qemu_apply_machine_options
>   vl: separate qemu_resolve_machine_memdev
>   vl: initialize displays before preconfig loop
>   vl: move -global check earlier
>   migration, vl: start migration via qmp_migrate_incoming
>   vl: start VM via qmp_cont
>   hmp: introduce cmd_available
>   remove preconfig state
>   vl: remove separate preconfig main_loop
>   vl: allow -incoming defer with -preconfig
>   vl: extract softmmu/datadir.c
>   vl: extract machine done notifiers
>   vl: extract softmmu/rtc.c
>   vl: extract softmmu/runstate.c
>   vl: extract softmmu/globals.c
>   vl: remove serial_max_hds
>   vl: clean up -boot variables
>   vl: move all generic initialization out of vl.c
> 
>  hw/alpha/dp264.c              |    1 +
>  hw/arm/boot.c                 |    1 +
>  hw/arm/digic_boards.c         |    1 +
>  hw/arm/highbank.c             |    1 +
>  hw/arm/npcm7xx_boards.c       |    1 +
>  hw/arm/sbsa-ref.c             |    1 +
>  hw/arm/vexpress.c             |    1 +
>  hw/arm/virt.c                 |    1 +
>  hw/avr/boot.c                 |    1 +
>  hw/core/loader.c              |    1 +
>  hw/core/machine-qmp-cmds.c    |    5 +-
>  hw/core/machine.c             |  103 ++
>  hw/core/qdev.c                |   12 +-
>  hw/display/cg3.c              |    1 +
>  hw/display/tcx.c              |    1 +
>  hw/hppa/machine.c             |    1 +
>  hw/i386/x86.c                 |    1 +
>  hw/lm32/milkymist.c           |    1 +
>  hw/m68k/mcf5208.c             |    1 +
>  hw/m68k/q800.c                |    1 +
>  hw/microblaze/boot.c          |    1 +
>  hw/mips/fuloong2e.c           |    1 +
>  hw/mips/jazz.c                |    1 +
>  hw/mips/malta.c               |    1 +
>  hw/mips/mipssim.c             |    1 +
>  hw/nios2/boot.c               |    1 +
>  hw/nvram/fw_cfg.c             |    1 +
>  hw/pci-host/prep.c            |    1 +
>  hw/pci/pci.c                  |    1 +
>  hw/ppc/e500.c                 |    1 +
>  hw/ppc/mac_newworld.c         |    1 +
>  hw/ppc/mac_oldworld.c         |    1 +
>  hw/ppc/pnv.c                  |    1 +
>  hw/ppc/ppc405_boards.c        |    1 +
>  hw/ppc/ppc440_bamboo.c        |    1 +
>  hw/ppc/sam460ex.c             |    1 +
>  hw/ppc/spapr.c                |    7 +-
>  hw/ppc/virtex_ml507.c         |    1 +
>  hw/riscv/boot.c               |    1 +
>  hw/s390x/ipl.c                |    1 +
>  hw/sparc/leon3.c              |    1 +
>  hw/sparc/sun4m.c              |    1 +
>  hw/sparc64/sun4u.c            |    1 +
>  include/exec/cpu-common.h     |    3 +
>  include/exec/exec-all.h       |    3 -
>  include/hw/boards.h           |    2 +
>  include/hw/qdev-core.h        |    9 +-
>  include/migration/misc.h      |    1 -
>  include/qapi/qmp/dispatch.h   |    1 +
>  include/qemu-common.h         |   21 -
>  include/qemu/datadir.h        |   28 +
>  include/qemu/option.h         |    3 +-
>  include/sysemu/runstate.h     |    1 -
>  include/sysemu/sysemu.h       |   12 +-
>  migration/migration.c         |   37 +-
>  monitor/hmp.c                 |   23 +-
>  monitor/qmp-cmds.c            |   10 -
>  qapi/qmp-dispatch.c           |    5 +-
>  qapi/run-state.json           |    5 +-
>  softmmu/datadir.c             |  129 ++
>  softmmu/globals.c             |   74 +
>  softmmu/meson.build           |    4 +
>  softmmu/qdev-monitor.c        |   18 +-
>  softmmu/rtc.c                 |  190 +++
>  softmmu/runstate.c            |  800 ++++++++++
>  softmmu/vl.c                  | 2761 ++++++++++-----------------------
>  stubs/meson.build             |    1 +
>  stubs/qmp-command-available.c |    7 +
>  tests/qtest/fuzz/fuzz.c       |    1 +
>  tests/qtest/qmp-test.c        |    2 +-
>  tests/test-qemu-opts.c        |   20 +-
>  ui/keymaps.c                  |    1 +
>  util/qemu-option.c            |    9 +-
>  73 files changed, 2311 insertions(+), 2036 deletions(-)
>  create mode 100644 include/qemu/datadir.h
>  create mode 100644 softmmu/datadir.c
>  create mode 100644 softmmu/globals.c
>  create mode 100644 softmmu/rtc.c
>  create mode 100644 softmmu/runstate.c
>  create mode 100644 stubs/qmp-command-available.c
> 



^ permalink raw reply	[flat|nested] 70+ messages in thread

end of thread, other threads:[~2020-11-30 13:08 UTC | newest]

Thread overview: 70+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-23 14:13 [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Paolo Bonzini
2020-11-23 14:14 ` [PATCH 01/36] vl: extract validation of -smp to machine.c Paolo Bonzini
2020-11-23 14:14 ` [PATCH 02/36] vl: remove bogus check Paolo Bonzini
2020-11-23 14:14 ` [PATCH 03/36] vl: split various early command line options to a separate function Paolo Bonzini
2020-11-26 16:47   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 04/36] vl: move various initialization routines out of qemu_init Paolo Bonzini
2020-11-23 14:14 ` [PATCH 05/36] vl: extract qemu_init_subsystems Paolo Bonzini
2020-11-23 14:14 ` [PATCH 06/36] vl: move prelaunch part of qemu_init to new functions Paolo Bonzini
2020-11-23 14:14 ` [PATCH 07/36] vl: extract various command line validation snippets to a new function Paolo Bonzini
2020-11-23 14:14 ` [PATCH 08/36] vl: preconfig and loadvm are mutually exclusive Paolo Bonzini
2020-11-23 14:14 ` [PATCH 09/36] vl: extract various command line desugaring snippets to a new function Paolo Bonzini
2020-11-23 14:14 ` [PATCH 10/36] qemu-option: restrict qemu_opts_set to merge-lists QemuOpts Paolo Bonzini
2020-11-23 14:14 ` [PATCH 11/36] vl: create "-net nic -net user" default earlier Paolo Bonzini
2020-11-23 14:14 ` [PATCH 12/36] vl: load plugins as late as possible Paolo Bonzini
2020-11-26 16:54   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 13/36] vl: move semihosting command line fallback to qemu_init_board Paolo Bonzini
2020-11-26 17:10   ` Igor Mammedov
2020-11-27  5:03     ` Paolo Bonzini
2020-11-27 10:31       ` Igor Mammedov
2020-11-27 11:22         ` Paolo Bonzini
2020-11-27 12:12           ` Igor Mammedov
2020-11-27 12:22             ` Paolo Bonzini
2020-11-23 14:14 ` [PATCH 14/36] vl: extract default devices to separate functions Paolo Bonzini
2020-11-26 17:29   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 15/36] vl: move CHECKPOINT_INIT after preconfig Paolo Bonzini
2020-11-26 17:36   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 16/36] vl: separate qemu_create_early_backends Paolo Bonzini
2020-11-23 14:14 ` [PATCH 17/36] vl: separate qemu_create_late_backends Paolo Bonzini
2020-11-23 14:14 ` [PATCH 18/36] vl: separate qemu_create_machine Paolo Bonzini
2020-11-23 14:14 ` [PATCH 19/36] vl: separate qemu_apply_machine_options Paolo Bonzini
2020-11-23 14:14 ` [PATCH 20/36] vl: separate qemu_resolve_machine_memdev Paolo Bonzini
2020-11-26 17:39   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 21/36] vl: initialize displays before preconfig loop Paolo Bonzini
2020-11-26 17:51   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 22/36] vl: move -global check earlier Paolo Bonzini
2020-11-26 17:55   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 23/36] migration, vl: start migration via qmp_migrate_incoming Paolo Bonzini
2020-11-26 18:04   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 24/36] vl: start VM via qmp_cont Paolo Bonzini
2020-11-23 14:14 ` [PATCH 25/36] hmp: introduce cmd_available Paolo Bonzini
2020-11-23 14:14 ` [PATCH 26/36] remove preconfig state Paolo Bonzini
2020-11-26 18:55   ` Igor Mammedov
2020-11-27  5:19     ` Paolo Bonzini
2020-11-27 10:50       ` Igor Mammedov
2020-11-27 11:50         ` Paolo Bonzini
2020-11-30 12:41           ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 27/36] vl: remove separate preconfig main_loop Paolo Bonzini
2020-11-30 12:46   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 28/36] vl: allow -incoming defer with -preconfig Paolo Bonzini
2020-11-27 10:51   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 29/36] vl: extract softmmu/datadir.c Paolo Bonzini
2020-11-27 12:06   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 30/36] vl: extract machine done notifiers Paolo Bonzini
2020-11-27 12:14   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 31/36] vl: extract softmmu/rtc.c Paolo Bonzini
2020-11-27 12:43   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 32/36] vl: extract softmmu/runstate.c Paolo Bonzini
2020-11-27 12:59   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 33/36] vl: extract softmmu/globals.c Paolo Bonzini
2020-11-27 13:19   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 34/36] vl: remove serial_max_hds Paolo Bonzini
2020-11-27 13:11   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 35/36] vl: clean up -boot variables Paolo Bonzini
2020-11-27 13:12   ` Igor Mammedov
2020-11-23 14:14 ` [PATCH 36/36] vl: move all generic initialization out of vl.c Paolo Bonzini
2020-11-27 13:30   ` Igor Mammedov
2020-11-27 12:00 ` [PATCH 37/36] machine: introduce MachineInitPhase Paolo Bonzini
2020-11-27 13:29   ` Igor Mammedov
2020-11-27 15:29     ` Paolo Bonzini
2020-11-30 12:50 ` [PATCH v3 00/36] cleanup qemu_init and make sense of command line processing Igor Mammedov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.