summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure48
-rw-r--r--device_tree.c27
-rw-r--r--exec.c13
-rw-r--r--fsdev/qemu-fsdev.c2
-rw-r--r--hw/9pfs/virtio-9p-device.c26
-rw-r--r--hw/arm/boot.c8
-rw-r--r--hw/i2c/pm_smbus.c25
-rw-r--r--hw/microblaze/boot.c27
-rw-r--r--hw/ppc/e500.c25
-rw-r--r--hw/ppc/spapr.c28
-rw-r--r--include/exec/cpu-all.h1
-rw-r--r--include/sysemu/sysemu.h2
-rw-r--r--kvm-all.c5
-rw-r--r--qemu-char.c13
-rw-r--r--qemu-options.hx8
-rw-r--r--qom/object.c6
-rw-r--r--target-i386/kvm.c17
-rw-r--r--util/qemu-option.c22
-rw-r--r--vl.c51
19 files changed, 176 insertions, 178 deletions
diff --git a/configure b/configure
index 0e0adde410..cb0f870b95 100755
--- a/configure
+++ b/configure
@@ -3445,6 +3445,36 @@ if test "$cpu" = "s390x" ; then
   roms="$roms s390-ccw"
 fi
 
+# Probe for the need for relocating the user-only binary.
+if test "$pie" = "no" ; then
+  textseg_addr=
+  case "$cpu" in
+    arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64)
+      textseg_addr=0x60000000
+      ;;
+    mips)
+      textseg_addr=0x400000
+      ;;
+  esac
+  if [ -n "$textseg_addr" ]; then
+    cat > $TMPC <<EOF
+    int main(void) { return 0; }
+EOF
+    textseg_ldflags="-Wl,-Ttext-segment=$textseg_addr"
+    if ! compile_prog "" "$textseg_ldflags"; then
+      # In case ld does not support -Ttext-segment, edit the default linker
+      # script via sed to set the .text start addr.  This is needed on FreeBSD
+      # at least.
+      $ld --verbose | sed \
+        -e '1,/==================================================/d' \
+        -e '/==================================================/,$d' \
+        -e "s/[.] = [0-9a-fx]* [+] SIZEOF_HEADERS/. = $textseg_addr + SIZEOF_HEADERS/" \
+        -e "s/__executable_start = [0-9a-fx]*/__executable_start = $textseg_addr/" > config-host.ld
+      textseg_ldflags="-Wl,-T../config-host.ld"
+    fi
+  fi
+fi
+
 # add pixman flags after all config tests are done
 QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags $fdt_cflags"
 libs_softmmu="$libs_softmmu $pixman_libs"
@@ -4073,9 +4103,6 @@ if test "$gcov" = "yes" ; then
   echo "GCOV=$gcov_tool" >> $config_host_mak
 fi
 
-# generate list of library paths for linker script
-$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > config-host.ld
-
 # use included Linux headers
 if test "$linux" = "yes" ; then
   mkdir -p linux-headers
@@ -4438,21 +4465,8 @@ if test "$gprof" = "yes" ; then
   fi
 fi
 
-if test "$ARCH" = "tci"; then
-  linker_script=""
-else
-  linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/ldscripts/\$(ARCH).ld"
-fi
-
 if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
-  case "$ARCH" in
-  alpha | s390x | aarch64)
-    # The default placement of the application is fine.
-    ;;
-  *)
-    ldflags="$linker_script $ldflags"
-    ;;
-  esac
+  ldflags="$ldflags $textseg_ldflags"
 fi
 
 echo "LDFLAGS+=$ldflags" >> $config_target_mak
diff --git a/device_tree.c b/device_tree.c
index 69be9da8e4..10cf3d0b60 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "qemu-common.h"
 #include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
 #include "hw/loader.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
@@ -239,15 +240,8 @@ uint32_t qemu_devtree_alloc_phandle(void *fdt)
      * which phandle id to start allocting phandles.
      */
     if (!phandle) {
-        QemuOpts *machine_opts;
-        machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-        if (machine_opts) {
-            const char *phandle_start;
-            phandle_start = qemu_opt_get(machine_opts, "phandle_start");
-            if (phandle_start) {
-                phandle = strtoul(phandle_start, NULL, 0);
-            }
-        }
+        phandle = qemu_opt_get_number(qemu_get_machine_opts(),
+                                      "phandle_start", 0);
     }
 
     if (!phandle) {
@@ -307,15 +301,10 @@ int qemu_devtree_add_subnode(void *fdt, const char *name)
 
 void qemu_devtree_dumpdtb(void *fdt, int size)
 {
-    QemuOpts *machine_opts;
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb");
-        if (dumpdtb) {
-            /* Dump the dtb to a file and quit */
-            exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
-        }
-    }
+    const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb");
 
+    if (dumpdtb) {
+        /* Dump the dtb to a file and quit */
+        exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
+    }
 }
diff --git a/exec.c b/exec.c
index 03fdf7e730..e150935e72 100644
--- a/exec.c
+++ b/exec.c
@@ -31,6 +31,7 @@
 #include "hw/qdev.h"
 #include "qemu/osdep.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
 #include "hw/xen/xen.h"
 #include "qemu/timer.h"
 #include "qemu/config-file.h"
@@ -53,7 +54,6 @@
 //#define DEBUG_SUBPAGE
 
 #if !defined(CONFIG_USER_ONLY)
-int phys_ram_fd;
 static int in_migration;
 
 RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
@@ -1044,12 +1044,10 @@ ram_addr_t last_ram_offset(void)
 static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
 {
     int ret;
-    QemuOpts *machine_opts;
 
     /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts &&
-        !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) {
+    if (!qemu_opt_get_bool(qemu_get_machine_opts(),
+                           "dump-guest-core", true)) {
         ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
         if (ret) {
             perror("qemu_madvise");
@@ -1096,10 +1094,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
 
 static int memory_try_enable_merging(void *addr, size_t len)
 {
-    QemuOpts *opts;
-
-    opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (opts && !qemu_opt_get_bool(opts, "mem-merge", true)) {
+    if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
         /* disabled by the user */
         return 0;
     }
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 6eaf36dbfa..ccfec139ab 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -76,6 +76,8 @@ int qemu_fsdev_add(QemuOpts *opts)
 
     if (fsle->fse.ops->parse_opts) {
         if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) {
+            g_free(fsle->fse.fsdev_id);
+            g_free(fsle);
             return -1;
         }
     }
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index dc6f4e404f..35e2af47b2 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -68,14 +68,14 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
         fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
                 "id = %s\n",
                 s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
-        return -1;
+        goto out;
     }
 
     if (!s->fsconf.tag) {
         /* we haven't specified a mount_tag */
         fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
                 s->fsconf.fsdev_id);
-        return -1;
+        goto out;
     }
 
     s->ctx.export_flags = fse->export_flags;
@@ -85,10 +85,10 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
     if (len > MAX_TAG_LEN - 1) {
         fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
                 "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
-        return -1;
+        goto out;
     }
 
-    s->tag = strdup(s->fsconf.tag);
+    s->tag = g_strdup(s->fsconf.tag);
     s->ctx.uid = -1;
 
     s->ops = fse->ops;
@@ -99,11 +99,11 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
     if (s->ops->init(&s->ctx) < 0) {
         fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s"
                 " and export path:%s\n", s->fsconf.fsdev_id, s->ctx.fs_root);
-        return -1;
+        goto out;
     }
     if (v9fs_init_worker_threads() < 0) {
         fprintf(stderr, "worker thread initialization failed\n");
-        return -1;
+        goto out;
     }
 
     /*
@@ -115,18 +115,26 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
     if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
         fprintf(stderr,
                 "error in converting name to path %s", strerror(errno));
-        return -1;
+        goto out;
     }
     if (s->ops->lstat(&s->ctx, &path, &stat)) {
         fprintf(stderr, "share path %s does not exist\n", fse->path);
-        return -1;
+        goto out;
     } else if (!S_ISDIR(stat.st_mode)) {
         fprintf(stderr, "share path %s is not a directory\n", fse->path);
-        return -1;
+        goto out;
     }
     v9fs_path_free(&path);
 
     return 0;
+out:
+    g_free(s->ctx.fs_root);
+    g_free(s->tag);
+    virtio_cleanup(vdev);
+    v9fs_path_free(&path);
+
+    return -1;
+
 }
 
 /* virtio-9p device */
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 7c0090ff4e..3e8741e015 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -359,7 +359,6 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
     uint64_t elf_entry;
     hwaddr entry;
     int big_endian;
-    QemuOpts *machine_opts;
 
     /* Load the kernel.  */
     if (!info->kernel_filename) {
@@ -367,12 +366,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
         exit(1);
     }
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
-    } else {
-        info->dtb_filename = NULL;
-    }
+    info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
 
     if (!info->secondary_cpu_reset_hook) {
         info->secondary_cpu_reset_hook = default_reset_secondary;
diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
index 6df0fa916d..c98e447533 100644
--- a/hw/i2c/pm_smbus.c
+++ b/hw/i2c/pm_smbus.c
@@ -32,6 +32,18 @@
 #define SMBHSTDAT1      0x06
 #define SMBBLKDAT       0x07
 
+#define STS_HOST_BUSY   (1)
+#define STS_INTR        (1<<1)
+#define STS_DEV_ERR     (1<<2)
+#define STS_BUS_ERR     (1<<3)
+#define STS_FAILED      (1<<4)
+#define STS_SMBALERT    (1<<5)
+#define STS_INUSE_STS   (1<<6)
+#define STS_BYTE_DONE   (1<<7)
+/* Signs of successfully transaction end :
+*  ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR )
+*/
+
 //#define DEBUG
 
 #ifdef DEBUG
@@ -50,9 +62,14 @@ static void smb_transaction(PMSMBus *s)
     i2c_bus *bus = s->smbus;
 
     SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+    /* Transaction isn't exec if STS_DEV_ERR bit set */
+    if ((s->smb_stat & STS_DEV_ERR) != 0)  {
+            goto error;
+        }
     switch(prot) {
     case 0x0:
         smbus_quick_command(bus, addr, read);
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x1:
         if (read) {
@@ -60,6 +77,7 @@ static void smb_transaction(PMSMBus *s)
         } else {
             smbus_send_byte(bus, addr, cmd);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x2:
         if (read) {
@@ -67,6 +85,7 @@ static void smb_transaction(PMSMBus *s)
         } else {
             smbus_write_byte(bus, addr, cmd, s->smb_data0);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x3:
         if (read) {
@@ -77,6 +96,7 @@ static void smb_transaction(PMSMBus *s)
         } else {
             smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     case 0x5:
         if (read) {
@@ -84,6 +104,7 @@ static void smb_transaction(PMSMBus *s)
         } else {
             smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
         }
+        s->smb_stat |= STS_BYTE_DONE | STS_INTR;
         break;
     default:
         goto error;
@@ -91,7 +112,7 @@ static void smb_transaction(PMSMBus *s)
     return;
 
   error:
-    s->smb_stat |= 0x04;
+    s->smb_stat |= STS_DEV_ERR;
 }
 
 static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
@@ -102,7 +123,7 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
     SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
     switch(addr) {
     case SMBHSTSTS:
-        s->smb_stat = 0;
+        s->smb_stat = (~(val & 0xff)) & s->smb_stat;
         s->smb_index = 0;
         break;
     case SMBHSTCNT:
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 3f1d70ef9b..5b057f7880 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -28,6 +28,7 @@
 #include "qemu/config-file.h"
 #include "qemu-common.h"
 #include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
 #include "hw/loader.h"
 #include "elf.h"
 
@@ -93,20 +94,18 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
                             void (*machine_cpu_reset)(MicroBlazeCPU *))
 {
     QemuOpts *machine_opts;
-    const char *kernel_filename = NULL;
-    const char *kernel_cmdline = NULL;
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *dtb_arg;
-        kernel_filename = qemu_opt_get(machine_opts, "kernel");
-        kernel_cmdline = qemu_opt_get(machine_opts, "append");
-        dtb_arg = qemu_opt_get(machine_opts, "dtb");
-        if (dtb_arg) { /* Preference a -dtb argument */
-            dtb_filename = dtb_arg;
-        } else { /* default to pcbios dtb as passed by machine_init */
-            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
-        }
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *dtb_arg;
+
+    machine_opts = qemu_get_machine_opts();
+    kernel_filename = qemu_opt_get(machine_opts, "kernel");
+    kernel_cmdline = qemu_opt_get(machine_opts, "append");
+    dtb_arg = qemu_opt_get(machine_opts, "dtb");
+    if (dtb_arg) { /* Preference a -dtb argument */
+        dtb_filename = dtb_arg;
+    } else { /* default to pcbios dtb as passed by machine_init */
+        dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
     }
 
     boot_info.machine_cpu_reset = machine_cpu_reset;
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 69837a5fb8..ee7e49a959 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -137,7 +137,6 @@ static int ppce500_load_device_tree(CPUPPCState *env,
     uint32_t clock_freq = 400000000;
     uint32_t tb_freq = 400000000;
     int i;
-    const char *toplevel_compat = NULL; /* user override */
     char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
     char soc[128];
     char mpic[128];
@@ -158,14 +157,9 @@ static int ppce500_load_device_tree(CPUPPCState *env,
             0x0, 0xe1000000,
             0x0, 0x10000,
         };
-    QemuOpts *machine_opts;
-    const char *dtb_file = NULL;
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        dtb_file = qemu_opt_get(machine_opts, "dtb");
-        toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
-    }
+    QemuOpts *machine_opts = qemu_get_machine_opts();
+    const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
+    const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
 
     if (dtb_file) {
         char *filename;
@@ -528,7 +522,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
 static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
                                    qemu_irq **irqs)
 {
-    QemuOptsList *list;
     qemu_irq *mpic;
     DeviceState *dev = NULL;
     SysBusDevice *s;
@@ -537,15 +530,11 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
     mpic = g_new(qemu_irq, 256);
 
     if (kvm_enabled()) {
-        bool irqchip_allowed = true, irqchip_required = false;
-
-        list = qemu_find_opts("machine");
-        if (!QTAILQ_EMPTY(&list->head)) {
-            irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
+        QemuOpts *machine_opts = qemu_get_machine_opts();
+        bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
                                                 "kernel_irqchip", true);
-            irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
-                                                 "kernel_irqchip", false);
-        }
+        bool irqchip_required = qemu_opt_get_bool(machine_opts,
+                                                  "kernel_irqchip", false);
 
         if (irqchip_allowed) {
             dev = ppce500_init_mpic_kvm(params, irqs);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c040794081..226ae70ae3 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -676,27 +676,19 @@ static void spapr_cpu_reset(void *opaque)
 
 static void spapr_create_nvram(sPAPREnvironment *spapr)
 {
-    QemuOpts *machine_opts;
-    DeviceState *dev;
+    DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+    const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram");
 
-    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+    if (drivename) {
+        BlockDriverState *bs;
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *drivename;
-
-        drivename = qemu_opt_get(machine_opts, "nvram");
-        if (drivename) {
-            BlockDriverState *bs;
-
-            bs = bdrv_find(drivename);
-            if (!bs) {
-                fprintf(stderr, "No such block device \"%s\" for nvram\n",
-                        drivename);
-                exit(1);
-            }
-            qdev_prop_set_drive_nofail(dev, "drive", bs);
+        bs = bdrv_find(drivename);
+        if (!bs) {
+            fprintf(stderr, "No such block device \"%s\" for nvram\n",
+                    drivename);
+            exit(1);
         }
+        qdev_prop_set_drive_nofail(dev, "drive", bs);
     }
 
     qdev_init_nofail(dev);
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 35bdf858f2..e791c05c4d 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -447,7 +447,6 @@ hwaddr cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr);
 
 /* memory API */
 
-extern int phys_ram_fd;
 extern ram_addr_t ram_size;
 
 /* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 2fb71afa25..d85bdc0cac 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -185,6 +185,8 @@ char *get_boot_devices_list(size_t *size);
 
 DeviceState *get_boot_device(uint32_t position);
 
+QemuOpts *qemu_get_machine_opts(void);
+
 bool usb_enabled(bool default_usb);
 
 extern QemuOptsList qemu_drive_opts;
diff --git a/kvm-all.c b/kvm-all.c
index de658de98f..a5cd3d3340 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1288,12 +1288,9 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
 
 static int kvm_irqchip_create(KVMState *s)
 {
-    QemuOptsList *list = qemu_find_opts("machine");
     int ret;
 
-    if (QTAILQ_EMPTY(&list->head) ||
-        !qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
-                           "kernel_irqchip", true) ||
+    if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
         !kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
         return 0;
     }
diff --git a/qemu-char.c b/qemu-char.c
index 6cec5d7114..18c42a39da 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -926,7 +926,6 @@ static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo)
         tty.c_cc[VMIN] = 1;
         tty.c_cc[VTIME] = 0;
     }
-    /* if graphical mode, we allow Ctrl-C handling */
     if (!stdio_allow_signal)
         tty.c_lflag &= ~ISIG;
 
@@ -955,7 +954,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
     chr = qemu_chr_open_fd(0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     chr->chr_set_echo = qemu_chr_set_echo_stdio;
-    stdio_allow_signal = display_type != DT_NOGRAPHIC;
     if (opts->has_signal) {
         stdio_allow_signal = opts->signal;
     }
@@ -2932,6 +2930,14 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
     if (strstart(filename, "mon:", &p)) {
         filename = p;
         qemu_opt_set(opts, "mux", "on");
+        if (strcmp(filename, "stdio") == 0) {
+            /* Monitor is muxed to stdio: do not exit on Ctrl+C by default
+             * but pass it to the guest.  Handle this only for compat syntax,
+             * for -chardev syntax we have special option for this.
+             * This is what -nographic did, redirecting+muxing serial+monitor
+             * to stdio causing Ctrl+C to be passed to guest. */
+            qemu_opt_set(opts, "signal", "off");
+        }
     }
 
     if (strcmp(filename, "null")    == 0 ||
@@ -3060,8 +3066,7 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
 {
     backend->stdio = g_new0(ChardevStdio, 1);
     backend->stdio->has_signal = true;
-    backend->stdio->signal =
-        qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC);
+    backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true);
 }
 
 static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
diff --git a/qemu-options.hx b/qemu-options.hx
index 137a39b7ad..7cc4d8ef25 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -842,7 +842,8 @@ STEXI
 Normally, QEMU uses SDL to display the VGA output. With this option,
 you can totally disable graphical output so that QEMU is a simple
 command line application. The emulated serial port is redirected on
-the console. Therefore, you can still use QEMU to debug a Linux kernel
+the console and muxed with the monitor (unless redirected elsewhere
+explicitly). Therefore, you can still use QEMU to debug a Linux kernel
 with a serial console.
 ETEXI
 
@@ -2485,14 +2486,15 @@ same as if you had specified @code{-serial tcp} except the unix domain socket
 @item mon:@var{dev_string}
 This is a special option to allow the monitor to be multiplexed onto
 another serial port.  The monitor is accessed with key sequence of
-@key{Control-a} and then pressing @key{c}. See monitor access
-@ref{pcsys_keys} in the -nographic section for more keys.
+@key{Control-a} and then pressing @key{c}.
 @var{dev_string} should be any one of the serial devices specified
 above.  An example to multiplex the monitor onto a telnet server
 listening on port 4444 would be:
 @table @code
 @item -serial mon:telnet::4444,server,nowait
 @end table
+When monitor is multiplexed to stdio this way, Ctrl+C will not terminate
+QEMU anymore but will be passed to the guest instead.
 
 @item braille
 Braille device.  This will use BrlAPI to display the braille output on a real
diff --git a/qom/object.c b/qom/object.c
index cbd7e86033..b2479d1c06 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -531,14 +531,14 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
 #ifdef CONFIG_QOM_CAST_DEBUG
     int i;
 
-    for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) {
+    for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
         if (class->cast_cache[i] == typename) {
             ret = class;
             goto out;
         }
     }
 #else
-    if (!class->interfaces) {
+    if (!class || !class->interfaces) {
         return class;
     }
 #endif
@@ -551,7 +551,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
     }
 
 #ifdef CONFIG_QOM_CAST_DEBUG
-    if (ret == class) {
+    if (class && ret == class) {
         for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
             class->cast_cache[i - 1] = class->cast_cache[i];
         }
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 4b557b3a38..15da3d7baf 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -741,7 +741,6 @@ static int kvm_get_supported_msrs(KVMState *s)
 
 int kvm_arch_init(KVMState *s)
 {
-    QemuOptsList *list = qemu_find_opts("machine");
     uint64_t identity_base = 0xfffbc000;
     uint64_t shadow_mem;
     int ret;
@@ -790,15 +789,13 @@ int kvm_arch_init(KVMState *s)
     }
     qemu_register_reset(kvm_unpoison_all, NULL);
 
-    if (!QTAILQ_EMPTY(&list->head)) {
-        shadow_mem = qemu_opt_get_size(QTAILQ_FIRST(&list->head),
-                                       "kvm_shadow_mem", -1);
-        if (shadow_mem != -1) {
-            shadow_mem /= 4096;
-            ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem);
-            if (ret < 0) {
-                return ret;
-            }
+    shadow_mem = qemu_opt_get_size(qemu_get_machine_opts(),
+                                   "kvm_shadow_mem", -1);
+    if (shadow_mem != -1) {
+        shadow_mem /= 4096;
+        ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem);
+        if (ret < 0) {
+            return ret;
         }
     }
     return 0;
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 412c425518..e0ef426daa 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -706,16 +706,12 @@ QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
     QemuOpts *opts;
 
     QTAILQ_FOREACH(opts, &list->head, next) {
-        if (!opts->id) {
-            if (!id) {
-                return opts;
-            }
-            continue;
+        if (!opts->id && !id) {
+            return opts;
         }
-        if (strcmp(opts->id, id) != 0) {
-            continue;
+        if (opts->id && id && !strcmp(opts->id, id)) {
+            return opts;
         }
-        return opts;
     }
     return NULL;
 }
@@ -918,15 +914,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
         get_opt_value(value, sizeof(value), p+4);
         id = value;
     }
-    if (defaults) {
-        if (!id && !QTAILQ_EMPTY(&list->head)) {
-            opts = qemu_opts_find(list, NULL);
-        } else {
-            opts = qemu_opts_create(list, id, 0, &local_err);
-        }
-    } else {
-        opts = qemu_opts_create(list, id, 1, &local_err);
-    }
+    opts = qemu_opts_create(list, id, !defaults, &local_err);
     if (opts == NULL) {
         if (error_is_set(&local_err)) {
             qerror_report_err(local_err);
diff --git a/vl.c b/vl.c
index 6d9fd7d807..bea1a10cc6 100644
--- a/vl.c
+++ b/vl.c
@@ -409,7 +409,7 @@ static QemuOptsList qemu_machine_opts = {
             .help = "Dump current dtb to a file and quit",
         }, {
             .name = "phandle_start",
-            .type = QEMU_OPT_STRING,
+            .type = QEMU_OPT_NUMBER,
             .help = "The first phandle ID we may generate dynamically",
         }, {
             .name = "dt_compatible",
@@ -516,6 +516,25 @@ static QemuOptsList qemu_realtime_opts = {
     },
 };
 
+/**
+ * Get machine options
+ *
+ * Returns: machine options (never null).
+ */
+QemuOpts *qemu_get_machine_opts(void)
+{
+    QemuOptsList *list;
+    QemuOpts *opts;
+
+    list = qemu_find_opts("machine");
+    assert(list);
+    opts = qemu_opts_find(list, NULL);
+    if (!opts) {
+        opts = qemu_opts_create_nofail(list);
+    }
+    return opts;
+}
+
 const char *qemu_get_vm_name(void)
 {
     return qemu_name;
@@ -1017,15 +1036,9 @@ static int parse_sandbox(QemuOpts *opts, void *opaque)
     return 0;
 }
 
-/*********QEMU USB setting******/
 bool usb_enabled(bool default_usb)
 {
-    QemuOpts *mach_opts;
-    mach_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (mach_opts) {
-        return qemu_opt_get_bool(mach_opts, "usb", default_usb);
-    }
-    return default_usb;
+    return qemu_opt_get_bool(qemu_get_machine_opts(), "usb", default_usb);
 }
 
 #ifndef _WIN32
@@ -2672,17 +2685,13 @@ static struct {
 
 static int configure_accelerator(void)
 {
-    const char *p = NULL;
+    const char *p;
     char buf[10];
     int i, ret;
     bool accel_initialised = false;
     bool init_failed = false;
 
-    QemuOptsList *list = qemu_find_opts("machine");
-    if (!QTAILQ_EMPTY(&list->head)) {
-        p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
-    }
-
+    p = qemu_opt_get(qemu_get_machine_opts(), "accel");
     if (p == NULL) {
         /* Use the default "accelerator", tcg */
         p = "tcg";
@@ -4080,14 +4089,10 @@ int main(int argc, char **argv, char **envp)
         qtest_init();
     }
 
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (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");
-    } else {
-        kernel_filename = initrd_filename = kernel_cmdline = NULL;
-    }
+    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");
 
     if (!boot_order) {
         boot_order = machine->boot_order;
@@ -4130,7 +4135,7 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    if (!linux_boot && machine_opts && qemu_opt_get(machine_opts, "dtb")) {
+    if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) {
         fprintf(stderr, "-dtb only allowed with -kernel option\n");
         exit(1);
     }