error_handler: unify stack walking logic
[sdk/emulator/qemu.git] / vl.c
diff --git a/vl.c b/vl.c
index b0bcc25..cf0f23b 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -37,6 +37,7 @@
 #ifdef CONFIG_SDL
 #if defined(__APPLE__) || defined(main)
 #include <SDL.h>
+#ifndef CONFIG_MARU
 int qemu_main(int argc, char **argv, char **envp);
 int main(int argc, char **argv)
 {
@@ -45,6 +46,7 @@ int main(int argc, char **argv)
 #undef main
 #define main qemu_main
 #endif
+#endif
 #endif /* CONFIG_SDL */
 
 #ifdef CONFIG_COCOA
@@ -52,6 +54,13 @@ int main(int argc, char **argv)
 #define main qemu_main
 #endif /* CONFIG_COCOA */
 
+#ifdef CONFIG_MARU
+#ifdef main
+#undef main
+#endif
+int qemu_main(int argc, char **argv, char **envp);
+#define main qemu_main
+#endif
 
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
@@ -90,6 +99,7 @@ int main(int argc, char **argv)
 #include "migration/migration.h"
 #include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
+#include "sysemu/hax.h"
 #include "qapi/qmp/qjson.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
@@ -122,6 +132,20 @@ int main(int argc, char **argv)
 #include "sysemu/replay.h"
 #include "qapi/qmp/qerror.h"
 
+#ifdef CONFIG_MARU
+#include "tizen/src/emulator.h"
+#include "tizen/src/emul_state.h"
+#include "tizen/src/ui/qt5.h"
+#include "tizen/src/util/ui_operations.h"
+#include "tizen/src/ecs/ecs.h"
+#include "tizen/src/util/error_handler.h"
+#include "tizen/src/util/exported_strings.h"
+
+inline static bool is_maru_machine(MachineClass *mc) {
+   return g_str_has_prefix(mc->name, "maru");
+}
+#endif
+
 #define MAX_VIRTIO_CONSOLES 1
 #define MAX_SCLP_CONSOLES 1
 
@@ -154,7 +178,7 @@ CharDriverState *sclp_hds[MAX_SCLP_CONSOLES];
 int win2k_install_hack = 0;
 int singlestep = 0;
 int smp_cpus = 1;
-int max_cpus = 0;
+int max_cpus = 1;
 int smp_cores = 1;
 int smp_threads = 1;
 int acpi_enabled = 1;
@@ -262,26 +286,6 @@ static QemuOptsList qemu_sandbox_opts = {
     },
 };
 
-static QemuOptsList qemu_trace_opts = {
-    .name = "trace",
-    .implied_opt_name = "enable",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
-    .desc = {
-        {
-            .name = "enable",
-            .type = QEMU_OPT_STRING,
-        },
-        {
-            .name = "events",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "file",
-            .type = QEMU_OPT_STRING,
-        },
-        { /* end of list */ }
-    },
-};
-
 static QemuOptsList qemu_option_rom_opts = {
     .name = "option-rom",
     .implied_opt_name = "romfile",
@@ -1072,11 +1076,6 @@ bool defaults_enabled(void)
     return has_defaults;
 }
 
-bool usb_enabled(void)
-{
-    return machine_usb(current_machine);
-}
-
 #ifndef _WIN32
 static int parse_add_fd(void *opaque, QemuOpts *opts, Error **errp)
 {
@@ -1223,7 +1222,6 @@ static QemuOptsList qemu_smp_opts = {
 static void smp_parse(QemuOpts *opts)
 {
     if (opts) {
-
         unsigned cpus    = qemu_opt_get_number(opts, "cpus", 0);
         unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
         unsigned cores   = qemu_opt_get_number(opts, "cores", 0);
@@ -1240,8 +1238,10 @@ static void smp_parse(QemuOpts *opts)
         } else if (cores == 0) {
             threads = threads > 0 ? threads : 1;
             cores = cpus / (sockets * threads);
+            cores = cores > 0 ? cores : 1;
         } else if (threads == 0) {
             threads = cpus / (cores * sockets);
+            threads = threads > 0 ? threads : 1;
         } else if (sockets * cores * threads < cpus) {
             error_report("cpu topology: "
                          "sockets (%u) * cores (%u) * threads (%u) < "
@@ -1251,6 +1251,17 @@ static void smp_parse(QemuOpts *opts)
         }
 
         max_cpus = qemu_opt_get_number(opts, "maxcpus", cpus);
+
+        if (max_cpus > MAX_CPUMASK_BITS) {
+            error_report("unsupported number of maxcpus");
+            exit(1);
+        }
+
+        if (max_cpus < cpus) {
+            error_report("maxcpus must be equal to or greater than smp");
+            exit(1);
+        }
+
         if (sockets * cores * threads > max_cpus) {
             error_report("cpu topology: "
                          "sockets (%u) * cores (%u) * threads (%u) > "
@@ -1260,25 +1271,11 @@ static void smp_parse(QemuOpts *opts)
         }
 
         smp_cpus = cpus;
-        smp_cores = cores > 0 ? cores : 1;
-        smp_threads = threads > 0 ? threads : 1;
-
+        smp_cores = cores;
+        smp_threads = threads;
     }
 
-    if (max_cpus == 0) {
-        max_cpus = smp_cpus;
-    }
-
-    if (max_cpus > MAX_CPUMASK_BITS) {
-        error_report("unsupported number of maxcpus");
-        exit(1);
-    }
-    if (max_cpus < smp_cpus) {
-        error_report("maxcpus must be equal to or greater than smp");
-        exit(1);
-    }
-
-    if (smp_cpus > 1 || smp_cores > 1 || smp_threads > 1) {
+    if (smp_cpus > 1) {
         Error *blocker = NULL;
         error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
         replay_add_blocker(blocker);
@@ -1393,7 +1390,7 @@ static int usb_device_add(const char *devname)
     const char *p;
 #endif
 
-    if (!usb_enabled()) {
+    if (!machine_usb(current_machine)) {
         return -1;
     }
 
@@ -1425,7 +1422,7 @@ static int usb_device_del(const char *devname)
         return -1;
     }
 
-    if (!usb_enabled()) {
+    if (!machine_usb(current_machine)) {
         return -1;
     }
 
@@ -1533,6 +1530,7 @@ MachineInfoList *qmp_query_machines(Error **errp)
 
         info->name = g_strdup(mc->name);
         info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus;
+        info->hotpluggable_cpus = !!mc->query_hotpluggable_cpus;
 
         entry = g_malloc0(sizeof(*entry));
         entry->value = info;
@@ -1836,11 +1834,18 @@ void qemu_system_killed(int signal, pid_t pid)
     shutdown_pid = pid;
     no_shutdown = 0;
 
+#ifdef CONFIG_MARU
+    if (current_machine &&
+            is_maru_machine(MACHINE_GET_CLASS(current_machine))) {
+        qemu_system_graceful_shutdown_request(TIMEOUT_FOR_SHUTDOWN);
+    }
+#else
     /* Cannot call qemu_system_shutdown_request directly because
      * we are in a signal handler.
      */
     shutdown_requested = 1;
     qemu_notify_event();
+#endif
 }
 
 void qemu_system_shutdown_request(void)
@@ -1926,8 +1931,11 @@ static void main_loop(void)
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
+
+    hax_sync_vcpus();
+
     do {
-        nonblocking = !kvm_enabled() && !xen_enabled() && last_io > 0;
+        nonblocking = !kvm_enabled() && !xen_enabled() && !hax_enabled() && last_io > 0;
 #ifdef CONFIG_PROFILER
         ti = profile_getclock();
 #endif
@@ -1940,7 +1948,8 @@ static void main_loop(void)
 
 static void version(void)
 {
-    printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
+    printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION ", "
+           QEMU_COPYRIGHT "\n");
 }
 
 static void help(int exitcode)
@@ -2084,6 +2093,13 @@ typedef enum DisplayType {
     DT_SDL,
     DT_COCOA,
     DT_GTK,
+#ifdef CONFIG_MARU
+    DT_MARU_REMOTE_SPICE,
+# ifdef CONFIG_QT
+    DT_MARU_QT_ONSCREEN,
+    DT_MARU_QT_OFFSCREEN,
+# endif
+#endif
     DT_NONE,
 } DisplayType;
 
@@ -2203,6 +2219,64 @@ static DisplayType select_display(const char *p)
         error_report("GTK support is disabled");
         exit(1);
 #endif
+#ifdef CONFIG_MARU
+    } else if (strstart(p, "maru_remote_spice", &opts)) {
+# ifdef CONFIG_SPICE
+        display = DT_MARU_REMOTE_SPICE;
+# else
+        fprintf(stderr, "maru_remote_spice is disabled\n");
+        exit(1);
+# endif
+    } else if (strstart(p, "maru_qt", &opts)) {
+# ifdef CONFIG_QT
+        display = DT_MARU_QT_ONSCREEN;
+        while (*opts) {
+            const char *nextopt;
+            if (strstart(opts, ",rendering=", &nextopt)) {
+                opts = nextopt;
+                if (strstart(opts, "onscreen", &nextopt)) {
+                    display = DT_MARU_QT_ONSCREEN;
+                } else if (strstart(opts, "offscreen", &nextopt)) {
+                    display = DT_MARU_QT_OFFSCREEN;
+                } else {
+                    goto invalid_maru_qt_args;
+                }
+            } else if (strstart(opts, ",resolution=", &nextopt)) {
+                opts = nextopt;
+                char *endptr = NULL;
+                // Resolution should be formed "640x480" or "640*480".
+                int width = (int)g_ascii_strtoll(opts, &endptr, 10);
+                int height = (int)g_ascii_strtoll(++endptr, &endptr, 10);
+                if (width <= 0 || height <= 0) {
+                    goto invalid_maru_qt_args;
+                }
+                set_initial_display_resolution(width, height);
+                nextopt = endptr;
+            } else if (strstart(opts, ",dpi=", &nextopt)) {
+                opts = nextopt;
+                char *endptr = NULL;
+                int dpi = (int)g_ascii_strtoll(opts, &endptr, 10);
+                if (dpi <= 0) {
+                    goto invalid_maru_qt_args;
+                }
+                set_display_pixel_density(dpi);
+                nextopt = endptr;
+            } else if (strstart(opts, ",forcelegacy", &nextopt)) {
+                opts = nextopt;
+                maru_qt5_set_force_legacy(true);
+            } else {
+            invalid_maru_qt_args:
+                error_report(FAILED_TO_DISPLAY_PARSING);
+                exit(1);
+            }
+            opts = nextopt;
+        }
+# else
+        error_report("maru_qt is disabled.\n");
+
+        exit(1);
+# endif
+#endif /* CONFIG_MARU */
     } else if (strstart(p, "none", &opts)) {
         display = DT_NONE;
     } else {
@@ -2361,10 +2435,7 @@ static int chardev_init_func(void *opaque, QemuOpts *opts, Error **errp)
 #ifdef CONFIG_VIRTFS
 static int fsdev_init_func(void *opaque, QemuOpts *opts, Error **errp)
 {
-    int ret;
-    ret = qemu_fsdev_add(opts);
-
-    return ret;
+    return qemu_fsdev_add(opts);
 }
 #endif
 
@@ -2704,6 +2775,11 @@ void qemu_add_machine_init_done_notifier(Notifier *notify)
     }
 }
 
+void qemu_remove_machine_init_done_notifier(Notifier *notify)
+{
+    notifier_remove(notify);
+}
+
 static void qemu_run_machine_init_done_notifiers(void)
 {
     notifier_list_notify(&machine_init_done_notifiers, NULL);
@@ -2937,6 +3013,28 @@ static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size,
     loc_pop(&loc);
 }
 
+static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
+{
+    GlobalProperty *g;
+
+    g = g_malloc0(sizeof(*g));
+    g->driver   = qemu_opt_get(opts, "driver");
+    g->property = qemu_opt_get(opts, "property");
+    g->value    = qemu_opt_get(opts, "value");
+    g->user_provided = true;
+    g->errp = &error_fatal;
+    qdev_prop_register_global(g);
+    return 0;
+}
+
+#ifdef CONFIG_MARU
+// W/A for preserve larger continuous heap for RAM.
+extern void *preallocated_ram_ptr;
+extern int preallocated_ram_size;
+// FIXME
+extern bool nodisplay;
+#endif
+
 int main(int argc, char **argv, char **envp)
 {
     int i;
@@ -2959,7 +3057,6 @@ int main(int argc, char **argv, char **envp)
     const char *qtest_log = NULL;
     const char *pid_file = NULL;
     const char *incoming = NULL;
-    int show_vnc_port = 0;
     bool defconfig = true;
     bool userconfig = true;
     bool nographic = false;
@@ -2973,6 +3070,14 @@ int main(int argc, char **argv, char **envp)
     FILE *vmstate_dump_file = NULL;
     Error *main_loop_err = NULL;
     Error *err = NULL;
+    bool list_data_dirs = false;
+#ifdef CONFIG_YAGL
+    static bool yagl_enabled = false;
+#endif /* CONFIG_YAGL */
+#ifdef CONFIG_VIGS
+    static bool vigs_enabled = false;
+    static char *vigs_backend = NULL;
+#endif /* CONFIG_VIGS */
 
     qemu_init_cpu_loop();
     qemu_mutex_lock_iothread();
@@ -3076,7 +3181,7 @@ int main(int argc, char **argv, char **envp)
 
             popt = lookup_opt(argc, argv, &optarg, &optind);
             if (!(popt->arch_mask & arch_type)) {
-                printf("Option %s not supported for this target\n", popt->name);
+                error_report("Option not supported for this target");
                 exit(1);
             }
             switch(popt->index) {
@@ -3350,7 +3455,7 @@ int main(int argc, char **argv, char **envp)
                 log_file = optarg;
                 break;
             case QEMU_OPTION_DFILTER:
-                qemu_set_dfilter_ranges(optarg);
+                qemu_set_dfilter_ranges(optarg, &error_fatal);
                 break;
             case QEMU_OPTION_s:
                 add_device_config(DEV_GDB, "tcp::" DEFAULT_GDBSTUB_PORT);
@@ -3359,7 +3464,9 @@ int main(int argc, char **argv, char **envp)
                 add_device_config(DEV_GDB, optarg);
                 break;
             case QEMU_OPTION_L:
-                if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+                if (is_help_option(optarg)) {
+                    list_data_dirs = true;
+                } else if (data_dir_idx < ARRAY_SIZE(data_dir)) {
                     data_dir[data_dir_idx++] = optarg;
                 }
                 break;
@@ -3657,6 +3764,30 @@ int main(int argc, char **argv, char **envp)
                 olist = qemu_find_opts("machine");
                 qemu_opts_parse_noisily(olist, "accel=kvm", false);
                 break;
+           case QEMU_OPTION_enable_yagl:
+#if defined(CONFIG_YAGL)
+                yagl_enabled = true;
+#else
+                fprintf(stderr, "YaGL openGLES passthrough support is disabled,"
+                    " ignoring -enable-yagl\n");
+#endif
+                break;
+           case QEMU_OPTION_enable_vigs:
+#if defined(CONFIG_VIGS)
+                vigs_enabled = true;
+#else
+                fprintf(stderr, "VIGS support is disabled,"
+                    " ignoring -enable-vigs\n");
+#endif
+                break;
+           case QEMU_OPTION_vigs_backend:
+#if defined(CONFIG_VIGS)
+                vigs_backend = g_strdup(optarg);
+#else
+                fprintf(stderr, "VIGS support is disabled,"
+                    " ignoring -vigs-backend\n");
+#endif
+                break;
             case QEMU_OPTION_M:
             case QEMU_OPTION_machine:
                 olist = qemu_find_opts("machine");
@@ -3852,43 +3983,29 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_xen_domid:
                 if (!(xen_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
+                    error_report("Option not supported for this target");
                     exit(1);
                 }
                 xen_domid = atoi(optarg);
                 break;
             case QEMU_OPTION_xen_create:
                 if (!(xen_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
+                    error_report("Option not supported for this target");
                     exit(1);
                 }
                 xen_mode = XEN_CREATE;
                 break;
             case QEMU_OPTION_xen_attach:
                 if (!(xen_available())) {
-                    printf("Option %s not supported for this target\n", popt->name);
+                    error_report("Option not supported for this target");
                     exit(1);
                 }
                 xen_mode = XEN_ATTACH;
                 break;
             case QEMU_OPTION_trace:
-            {
-                opts = qemu_opts_parse_noisily(qemu_find_opts("trace"),
-                                               optarg, true);
-                if (!opts) {
-                    exit(1);
-                }
-                if (qemu_opt_get(opts, "enable")) {
-                    trace_enable_events(qemu_opt_get(opts, "enable"));
-                }
-                trace_init_events(qemu_opt_get(opts, "events"));
-                if (trace_file) {
-                    g_free(trace_file);
-                }
-                trace_file = g_strdup(qemu_opt_get(opts, "file"));
-                qemu_opts_del(opts);
+                g_free(trace_file);
+                trace_file = trace_opt_parse(optarg);
                 break;
-            }
             case QEMU_OPTION_readconfig:
                 {
                     int ret = qemu_read_config_file(optarg);
@@ -3943,6 +4060,10 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_enable_hax:
+                olist = qemu_find_opts("machine");
+                qemu_opts_parse_noisily(olist, "accel=hax", false);
+                break;
             case QEMU_OPTION_add_fd:
 #ifndef _WIN32
                 opts = qemu_opts_parse_noisily(qemu_find_opts("add-fd"),
@@ -3956,6 +4077,11 @@ int main(int argc, char **argv, char **envp)
                 exit(1);
 #endif
                 break;
+#if defined(CONFIG_MARU)
+            case QEMU_OPTION_enable_suspend:
+                ecs_set_suspend_state(SUSPEND_UNLOCK);
+                break;
+#endif
             case QEMU_OPTION_object:
                 opts = qemu_opts_parse_noisily(qemu_find_opts("object"),
                                                optarg, true);
@@ -4006,6 +4132,15 @@ int main(int argc, char **argv, char **envp)
 
     machine_class = select_machine();
 
+#if defined(CONFIG_MARU)
+    if (is_maru_machine(machine_class)) {
+        preallocated_ram_ptr = qemu_anon_ram_alloc(ram_size, NULL);
+        if (preallocated_ram_ptr) {
+            preallocated_ram_size = ram_size;
+        }
+    }
+#endif
+
     set_memory_options(&ram_slots, &maxram_size, machine_class);
 
     os_daemonize();
@@ -4063,7 +4198,7 @@ int main(int argc, char **argv, char **envp)
     /* Open the logfile at this point and set the log mask if necessary.
      */
     if (log_file) {
-        qemu_set_log_filename(log_file);
+        qemu_set_log_filename(log_file, &error_fatal);
     }
 
     if (log_mask) {
@@ -4091,6 +4226,14 @@ int main(int argc, char **argv, char **envp)
         data_dir[data_dir_idx++] = CONFIG_QEMU_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);
+    }
+
     smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL));
 
     machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */
@@ -4217,7 +4360,6 @@ int main(int argc, char **argv, char **envp)
         display_type = DT_COCOA;
 #elif defined(CONFIG_VNC)
         vnc_parse("localhost:0,to=99,id=default", &error_abort);
-        show_vnc_port = 1;
 #else
         display_type = DT_NONE;
 #endif
@@ -4249,6 +4391,16 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+#ifdef CONFIG_MARU
+# if defined(CONFIG_QT)
+    if (display_type == DT_MARU_QT_ONSCREEN) {
+        maru_early_qt5_display_init(true);
+    } else if (display_type == DT_MARU_QT_OFFSCREEN) {
+        maru_early_qt5_display_init(false);
+    }
+# endif
+#endif
+
     page_size_init();
     socket_init();
 
@@ -4287,8 +4439,6 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    configure_accelerator(current_machine);
-
     if (qtest_chrdev) {
         qtest_init(qtest_chrdev, qtest_log, &error_fatal);
     }
@@ -4353,7 +4503,7 @@ int main(int argc, char **argv, char **envp)
 
     cpu_ticks_init();
     if (icount_opts) {
-        if (kvm_enabled() || xen_enabled()) {
+        if (kvm_enabled() || xen_enabled() || hax_enabled()) {
             error_report("-icount is not allowed with kvm or xen");
             exit(1);
         }
@@ -4361,9 +4511,6 @@ int main(int argc, char **argv, char **envp)
         qemu_opts_del(icount_opts);
     }
 
-    /* clean up network at qemu process termination */
-    atexit(&net_cleanup);
-
     if (default_net) {
         QemuOptsList *net = qemu_find_opts("net");
         qemu_opts_set(net, NULL, "type", "nic", &error_abort);
@@ -4464,14 +4611,10 @@ int main(int argc, char **argv, char **envp)
             exit (i == 1 ? 1 : 0);
     }
 
-    if (machine_class->compat_props) {
-        GlobalProperty *p;
-        for (i = 0; i < machine_class->compat_props->len; i++) {
-            p = g_array_index(machine_class->compat_props, GlobalProperty *, i);
-            qdev_prop_register_global(p);
-        }
-    }
-    qemu_add_globals();
+    machine_register_compat_props(current_machine);
+
+    qemu_opts_foreach(qemu_find_opts("global"),
+                      global_init_func, NULL, NULL);
 
     /* This checkpoint is required by replay to separate prior clock
        reading from the other reads, because timer polling functions query
@@ -4485,10 +4628,28 @@ int main(int argc, char **argv, char **envp)
     current_machine->boot_order = boot_order;
     current_machine->cpu_model = cpu_model;
 
+    configure_accelerator(current_machine);
+
+#if defined(CONFIG_MARU)
+    if (is_maru_machine(machine_class)) {
+        kernel_cmdline = qemu_opt_get(machine_opts, "append");
+        // Returned variable points different address from input variable.
+        kernel_cmdline = prepare_maru(kernel_cmdline);
+        qemu_opt_set(qemu_get_machine_opts(), "append",
+                kernel_cmdline, &error_abort);
+
+        current_machine->kernel_cmdline = (char *)kernel_cmdline;
+        if (display_type == DT_NONE) {
+            nodisplay = true;
+        }
+    }
+#endif
+
     machine_class->init(current_machine);
 
     realtime_init();
 
+    // TODO: Check about it...
     audio_init();
 
     cpu_synchronize_all_post_init();
@@ -4500,8 +4661,12 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+    if (hax_enabled()) {
+        hax_sync_vcpus();
+    }
+
     /* init USB devices */
-    if (usb_enabled()) {
+    if (machine_usb(current_machine)) {
         if (foreach_device_config(DEV_USB, usb_parse) < 0)
             exit(1);
     }
@@ -4517,6 +4682,37 @@ int main(int argc, char **argv, char **envp)
     }
     rom_reset_order_override();
 
+#if defined(CONFIG_MARU)
+    if (is_maru_machine(machine_class)) {
+        prepare_maru_after_device_init();
+    }
+#endif
+#ifdef CONFIG_VIGS
+    // To support legacy VIGS options
+    if (vigs_enabled) {
+        PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
+        PCIDevice *pci_dev = pci_create(pci_bus, -1, "vigs");
+        if (vigs_backend) {
+            qdev_prop_set_string(&pci_dev->qdev, "backend", vigs_backend);
+        } else {
+            qdev_prop_set_string(&pci_dev->qdev, "backend", "gl");
+        }
+        qdev_prop_set_string(&pci_dev->qdev, "wsi", "wsi0");
+        qdev_init_nofail(&pci_dev->qdev);
+    }
+#endif
+#ifdef CONFIG_YAGL
+    // To support legacy YaGL options
+    if (yagl_enabled) {
+        PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
+        PCIDevice *pci_dev = pci_create(pci_bus, -1, "yagl");
+        if (vigs_enabled) {
+            qdev_prop_set_string(&pci_dev->qdev, "wsi", "wsi0");
+        }
+        qdev_init_nofail(&pci_dev->qdev);
+    }
+#endif
+
     /* Did we create any drives that we failed to create a device for? */
     drive_check_orphaned();
 
@@ -4554,6 +4750,19 @@ int main(int argc, char **argv, char **envp)
     case DT_GTK:
         gtk_display_init(ds, full_screen, grab_on_hover);
         break;
+#if defined(CONFIG_MARU)
+ #if defined(CONFIG_QT)
+    case DT_MARU_QT_ONSCREEN:
+    case DT_MARU_QT_OFFSCREEN:
+        if (!is_maru_machine(machine_class)) {
+            error_report("maru_qt can not work"
+                    " without maru machine");
+            exit(1);
+        }
+        maru_qt5_display_init(ds, full_screen);
+        break;
+ #endif
+#endif
     default:
         break;
     }
@@ -4562,13 +4771,10 @@ int main(int argc, char **argv, char **envp)
     os_setup_signal_handling();
 
     /* init remote displays */
+#ifdef CONFIG_VNC
     qemu_opts_foreach(qemu_find_opts("vnc"),
                       vnc_init_func, NULL, NULL);
-    if (show_vnc_port) {
-        char *ret = vnc_display_local_addr("default");
-        printf("VNC server running on '%s'\n", ret);
-        g_free(ret);
-    }
+#endif
 
     if (using_spice) {
         qemu_spice_display_init();
@@ -4624,6 +4830,10 @@ int main(int argc, char **argv, char **envp)
 
     os_setup_post();
 
+#ifdef CONFIG_MARU
+    enable_print_backtrace_at_normal_exit();
+#endif
+    trace_init_vcpu_events();
     main_loop();
     replay_disable_events();
 
@@ -4634,5 +4844,22 @@ int main(int argc, char **argv, char **envp)
     tpm_cleanup();
 #endif
 
+    /* vhost-user must be cleaned up before chardevs.  */
+    net_cleanup();
+    audio_cleanup();
+    monitor_cleanup();
+    qemu_chr_cleanup();
+
+#if defined(CONFIG_MARU) && defined(CONFIG_QT)
+    switch (display_type) {
+    case DT_MARU_QT_ONSCREEN:
+    case DT_MARU_QT_OFFSCREEN:
+        maru_qt5_display_fini();
+        break;
+    default:
+        break;
+    }
+#endif
+
     return 0;
 }