summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--block/commit.c2
-rw-r--r--blockdev.c9
-rw-r--r--blockjob.c2
-rw-r--r--hmp-commands.hx36
-rw-r--r--hmp.c25
-rw-r--r--hmp.h5
-rw-r--r--hw/9pfs/virtio-9p.c5
-rw-r--r--hw/core/qdev-properties.c9
-rw-r--r--hw/misc/ivshmem.c4
-rw-r--r--include/monitor/monitor.h1
-rw-r--r--include/qapi/qmp/qerror.h79
-rw-r--r--include/qemu/error-report.h1
-rw-r--r--monitor.c85
-rw-r--r--qapi/qmp-dispatch.c3
-rw-r--r--qapi/qmp-input-visitor.c2
-rw-r--r--qdev-monitor.c12
-rw-r--r--qmp.c23
-rw-r--r--qobject/json-parser.c2
-rw-r--r--qom/object.c5
-rw-r--r--savevm.c3
-rw-r--r--slirp/misc.c13
-rw-r--r--slirp/slirp.c8
-rw-r--r--slirp/slirp.h2
-rw-r--r--stubs/Makefile.objs1
-rw-r--r--stubs/arch-query-cpu-def.c2
-rw-r--r--stubs/mon-print-filename.c6
-rw-r--r--ui/vnc.c4
-rw-r--r--util/error.c5
-rw-r--r--util/qemu-config.c2
-rw-r--r--util/qemu-error.c4
-rw-r--r--util/qemu-option.c2
31 files changed, 153 insertions, 209 deletions
diff --git a/block/commit.c b/block/commit.c
index acec4ac5a8..5c09f4444e 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -194,7 +194,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
     if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
          on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
         !bdrv_iostatus_is_enabled(bs)) {
-        error_set(errp, QERR_INVALID_PARAMETER_COMBINATION);
+        error_setg(errp, "Invalid parameter combination");
         return;
     }
 
diff --git a/blockdev.c b/blockdev.c
index 952eb60e3d..7810e9fb68 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1523,14 +1523,16 @@ static void eject_device(BlockDriverState *bs, int force, Error **errp)
         return;
     }
     if (!bdrv_dev_has_removable_media(bs)) {
-        error_set(errp, QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
+        error_setg(errp, "Device '%s' is not removable",
+                   bdrv_get_device_name(bs));
         return;
     }
 
     if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
         bdrv_dev_eject_request(bs, force);
         if (!force) {
-            error_set(errp, QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+            error_setg(errp, "Device '%s' is locked",
+                       bdrv_get_device_name(bs));
             return;
         }
     }
@@ -2222,7 +2224,8 @@ void qmp_block_job_cancel(const char *device,
         return;
     }
     if (job->paused && !force) {
-        error_set(errp, QERR_BLOCK_JOB_PAUSED, device);
+        error_setg(errp, "The block job for device '%s' is currently paused",
+                   device);
         return;
     }
 
diff --git a/blockjob.c b/blockjob.c
index b3ce14cebd..cd4784f053 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -88,7 +88,7 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
     Error *local_err = NULL;
 
     if (!job->driver->set_speed) {
-        error_set(errp, QERR_NOT_SUPPORTED);
+        error_set(errp, QERR_UNSUPPORTED);
         return;
     }
     job->driver->set_speed(job, speed, &local_err);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index f3fc514427..8971f1b153 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -176,7 +176,7 @@ ETEXI
 
     {
         .name       = "drive_del",
-        .args_type  = "id:s",
+        .args_type  = "id:B",
         .params     = "device",
         .help       = "remove host block device",
         .user_print = monitor_user_noop,
@@ -658,6 +658,7 @@ ETEXI
         .help       = "add device, like -device on the command line",
         .user_print = monitor_user_noop,
         .mhandler.cmd_new = do_device_add,
+        .command_completion = device_add_completion,
     },
 
 STEXI
@@ -673,6 +674,7 @@ ETEXI
         .params     = "device",
         .help       = "remove device",
         .mhandler.cmd = hmp_device_del,
+        .command_completion = device_del_completion,
     },
 
 STEXI
@@ -998,26 +1000,34 @@ ETEXI
 
     {
         .name       = "dump-guest-memory",
-        .args_type  = "paging:-p,filename:F,begin:i?,length:i?",
-        .params     = "[-p] filename [begin] [length]",
-        .help       = "dump guest memory to file"
-                      "\n\t\t\t begin(optional): the starting physical address"
-                      "\n\t\t\t length(optional): the memory size, in bytes",
+        .args_type  = "paging:-p,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:i?,length:i?",
+        .params     = "[-p] [-z|-l|-s] filename [begin length]",
+        .help       = "dump guest memory into file 'filename'.\n\t\t\t"
+                      "-p: do paging to get guest's memory mapping.\n\t\t\t"
+                      "-z: dump in kdump-compressed format, with zlib compression.\n\t\t\t"
+                      "-l: dump in kdump-compressed format, with lzo compression.\n\t\t\t"
+                      "-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
+                      "begin: the starting physical address.\n\t\t\t"
+                      "length: the memory size, in bytes.",
         .mhandler.cmd = hmp_dump_guest_memory,
     },
 
 
 STEXI
-@item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length}
+@item dump-guest-memory [-p] @var{filename} @var{begin} @var{length}
+@item dump-guest-memory [-z|-l|-s] @var{filename}
 @findex dump-guest-memory
 Dump guest memory to @var{protocol}. The file can be processed with crash or
-gdb.
-  filename: dump file name
-    paging: do paging to get guest's memory mapping
+gdb. Without -z|-l|-s, the dump format is ELF.
+        -p: do paging to get guest's memory mapping.
+        -z: dump in kdump-compressed format, with zlib compression.
+        -l: dump in kdump-compressed format, with lzo compression.
+        -s: dump in kdump-compressed format, with snappy compression.
+  filename: dump file name.
      begin: the starting physical address. It's optional, and should be
-            specified with length together.
+            specified together with length.
     length: the memory size, in bytes. It's optional, and should be specified
-            with begin together.
+            together with begin.
 ETEXI
 
     {
@@ -1254,6 +1264,7 @@ ETEXI
         .params     = "[qom-type=]type,id=str[,prop=value][,...]",
         .help       = "create QOM object",
         .mhandler.cmd = hmp_object_add,
+        .command_completion = object_add_completion,
     },
 
 STEXI
@@ -1268,6 +1279,7 @@ ETEXI
         .params     = "id",
         .help       = "destroy QOM object",
         .mhandler.cmd = hmp_object_del,
+        .command_completion = object_del_completion,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 2f279c4ff2..ca869bafa8 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1308,16 +1308,35 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
 {
     Error *errp = NULL;
     int paging = qdict_get_try_bool(qdict, "paging", 0);
+    int zlib = qdict_get_try_bool(qdict, "zlib", 0);
+    int lzo = qdict_get_try_bool(qdict, "lzo", 0);
+    int snappy = qdict_get_try_bool(qdict, "snappy", 0);
     const char *file = qdict_get_str(qdict, "filename");
     bool has_begin = qdict_haskey(qdict, "begin");
     bool has_length = qdict_haskey(qdict, "length");
-    /* kdump-compressed format is not supported for HMP */
-    bool has_format = false;
     int64_t begin = 0;
     int64_t length = 0;
     enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
     char *prot;
 
+    if (zlib + lzo + snappy > 1) {
+        error_setg(&errp, "only one of '-z|-l|-s' can be set");
+        hmp_handle_error(mon, &errp);
+        return;
+    }
+
+    if (zlib) {
+        dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
+    }
+
+    if (lzo) {
+        dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO;
+    }
+
+    if (snappy) {
+        dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
+    }
+
     if (has_begin) {
         begin = qdict_get_int(qdict, "begin");
     }
@@ -1328,7 +1347,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
     prot = g_strconcat("file:", file, NULL);
 
     qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
-                          has_format, dump_format, &errp);
+                          true, dump_format, &errp);
     hmp_handle_error(mon, &errp);
     g_free(prot);
 }
diff --git a/hmp.h b/hmp.h
index ed58f0ea41..20ef454b4a 100644
--- a/hmp.h
+++ b/hmp.h
@@ -15,6 +15,7 @@
 #define HMP_H
 
 #include "qemu-common.h"
+#include "qemu/readline.h"
 #include "qapi-types.h"
 #include "qapi/qmp/qdict.h"
 
@@ -92,5 +93,9 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict);
 void hmp_cpu_add(Monitor *mon, const QDict *qdict);
 void hmp_object_add(Monitor *mon, const QDict *qdict);
 void hmp_object_del(Monitor *mon, const QDict *qdict);
+void object_add_completion(ReadLineState *rs, int nb_args, const char *str);
+void object_del_completion(ReadLineState *rs, int nb_args, const char *str);
+void device_add_completion(ReadLineState *rs, int nb_args, const char *str);
+void device_del_completion(ReadLineState *rs, int nb_args, const char *str);
 
 #endif
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 83e4e93983..9aa6725f09 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -987,8 +987,9 @@ static void v9fs_attach(void *opaque)
      */
     if (!s->migration_blocker) {
         s->root_fid = fid;
-        error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION,
-                  s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
+        error_setg(&s->migration_blocker,
+                   "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'",
+                   s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
         migrate_add_blocker(s->migration_blocker);
     }
 out:
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index c67acf58b5..585a8e902e 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -587,8 +587,9 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
 
     /* We rely on power-of-2 blocksizes for bitmasks */
     if ((value & (value - 1)) != 0) {
-        error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
-                  dev->id?:"", name, (int64_t)value);
+        error_setg(errp,
+                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
+                  dev->id ?: "", name, (int64_t)value);
         return;
     }
 
@@ -853,7 +854,7 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
 {
     switch (ret) {
     case -EEXIST:
-        error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
+        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
                   object_get_typename(OBJECT(dev)), prop->name, value);
         break;
     default:
@@ -862,7 +863,7 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                   object_get_typename(OBJECT(dev)), prop->name, value);
         break;
     case -ENOENT:
-        error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
+        error_setg(errp, "Property '%s.%s' can't find value '%s'",
                   object_get_typename(OBJECT(dev)), prop->name, value);
         break;
     case 0:
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 8d144baa1e..768e5288bc 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -684,8 +684,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
     }
 
     if (s->role_val == IVSHMEM_PEER) {
-        error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION,
-                  "peer mode", "ivshmem");
+        error_setg(&s->migration_blocker,
+                   "Migration is disabled when using feature 'peer mode' in device 'ivshmem'");
         migrate_add_blocker(s->migration_blocker);
     }
 
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index a49ea11eb4..42d867155b 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -79,7 +79,6 @@ int monitor_handle_fd_param(Monitor *mon, const char *fdname);
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
     GCC_FMT_ATTR(2, 0);
 void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
-void monitor_print_filename(Monitor *mon, const char *filename);
 void monitor_flush(Monitor *mon);
 int monitor_set_cpu(int cpu_index);
 int monitor_get_cpu_index(void);
diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h
index da75abf6d6..902d1a7a18 100644
--- a/include/qapi/qmp/qerror.h
+++ b/include/qapi/qmp/qerror.h
@@ -12,7 +12,6 @@
 #ifndef QERROR_H
 #define QERROR_H
 
-#include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qstring.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
@@ -35,51 +34,30 @@ void qerror_report_err(Error *err);
  * Please keep the definitions in alphabetical order.
  * Use scripts/check-qerror.sh to check.
  */
-#define QERR_ADD_CLIENT_FAILED \
-    ERROR_CLASS_GENERIC_ERROR, "Could not add client"
-
-#define QERR_AMBIGUOUS_PATH \
-    ERROR_CLASS_GENERIC_ERROR, "Path '%s' does not uniquely identify an object"
-
-#define QERR_BAD_BUS_FOR_DEVICE \
-    ERROR_CLASS_GENERIC_ERROR, "Device '%s' can't go on a %s bus"
-
 #define QERR_BASE_NOT_FOUND \
     ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found"
 
 #define QERR_BLOCK_JOB_NOT_ACTIVE \
     ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'"
 
-#define QERR_BLOCK_JOB_PAUSED \
-    ERROR_CLASS_GENERIC_ERROR, "The block job for device '%s' is currently paused"
-
 #define QERR_BLOCK_JOB_NOT_READY \
     ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed"
 
 #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
     ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'"
 
-#define QERR_BUFFER_OVERRUN \
-    ERROR_CLASS_GENERIC_ERROR, "An internal buffer overran"
-
 #define QERR_BUS_NO_HOTPLUG \
     ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging"
 
 #define QERR_BUS_NOT_FOUND \
     ERROR_CLASS_GENERIC_ERROR, "Bus '%s' not found"
 
-#define QERR_COMMAND_DISABLED \
-    ERROR_CLASS_GENERIC_ERROR, "The command %s has been disabled for this instance"
-
 #define QERR_COMMAND_NOT_FOUND \
     ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found"
 
 #define QERR_DEVICE_ENCRYPTED \
     ERROR_CLASS_DEVICE_ENCRYPTED, "'%s' (%s) is encrypted"
 
-#define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \
-    ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when using feature '%s' in device '%s'"
-
 #define QERR_DEVICE_HAS_NO_MEDIUM \
     ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no medium"
 
@@ -92,15 +70,6 @@ void qerror_report_err(Error *err);
 #define QERR_DEVICE_IS_READ_ONLY \
     ERROR_CLASS_GENERIC_ERROR, "Device '%s' is read only"
 
-#define QERR_DEVICE_LOCKED \
-    ERROR_CLASS_GENERIC_ERROR, "Device '%s' is locked"
-
-#define QERR_DEVICE_MULTIPLE_BUSSES \
-    ERROR_CLASS_GENERIC_ERROR, "Device '%s' has multiple child busses"
-
-#define QERR_DEVICE_NO_BUS \
-    ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no child bus"
-
 #define QERR_DEVICE_NO_HOTPLUG \
     ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging"
 
@@ -113,12 +82,6 @@ void qerror_report_err(Error *err);
 #define QERR_DEVICE_NOT_FOUND \
     ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found"
 
-#define QERR_DEVICE_NOT_REMOVABLE \
-    ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not removable"
-
-#define QERR_DUPLICATE_ID \
-    ERROR_CLASS_GENERIC_ERROR, "Duplicate ID '%s' for %s"
-
 #define QERR_FD_NOT_FOUND \
     ERROR_CLASS_GENERIC_ERROR, "File descriptor named '%s' not found"
 
@@ -131,15 +94,9 @@ void qerror_report_err(Error *err);
 #define QERR_INVALID_BLOCK_FORMAT \
     ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'"
 
-#define QERR_INVALID_OPTION_GROUP \
-    ERROR_CLASS_GENERIC_ERROR, "There is no option group '%s'"
-
 #define QERR_INVALID_PARAMETER \
     ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'"
 
-#define QERR_INVALID_PARAMETER_COMBINATION \
-    ERROR_CLASS_GENERIC_ERROR, "Invalid parameter combination"
-
 #define QERR_INVALID_PARAMETER_TYPE \
     ERROR_CLASS_GENERIC_ERROR, "Invalid parameter type for '%s', expected: %s"
 
@@ -152,9 +109,6 @@ void qerror_report_err(Error *err);
 #define QERR_IO_ERROR \
     ERROR_CLASS_GENERIC_ERROR, "An IO error has occurred"
 
-#define QERR_JSON_PARSE_ERROR \
-    ERROR_CLASS_GENERIC_ERROR, "JSON parse error, %s"
-
 #define QERR_JSON_PARSING \
     ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax"
 
@@ -164,45 +118,21 @@ void qerror_report_err(Error *err);
 #define QERR_MIGRATION_ACTIVE \
     ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress"
 
-#define QERR_MIGRATION_NOT_SUPPORTED \
-    ERROR_CLASS_GENERIC_ERROR, "State blocked by non-migratable device '%s'"
-
 #define QERR_MISSING_PARAMETER \
     ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing"
 
-#define QERR_NO_BUS_FOR_DEVICE \
-    ERROR_CLASS_GENERIC_ERROR, "No '%s' bus found for device '%s'"
-
-#define QERR_NOT_SUPPORTED \
-    ERROR_CLASS_GENERIC_ERROR, "Not supported"
-
 #define QERR_PERMISSION_DENIED \
     ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation"
 
-#define QERR_PROPERTY_NOT_FOUND \
-    ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' not found"
-
 #define QERR_PROPERTY_VALUE_BAD \
     ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' doesn't take value '%s'"
 
-#define QERR_PROPERTY_VALUE_IN_USE \
-    ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't take value '%s', it's in use"
-
-#define QERR_PROPERTY_VALUE_NOT_FOUND \
-    ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't find value '%s'"
-
-#define QERR_PROPERTY_VALUE_NOT_POWER_OF_2 \
-    ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2"
-
 #define QERR_PROPERTY_VALUE_OUT_OF_RANGE \
     ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")"
 
 #define QERR_QGA_COMMAND_FAILED \
     ERROR_CLASS_GENERIC_ERROR, "Guest agent command failed, error was '%s'"
 
-#define QERR_QGA_LOGGING_FAILED \
-    ERROR_CLASS_GENERIC_ERROR, "Guest agent failed to log non-optional log statement"
-
 #define QERR_QMP_BAD_INPUT_OBJECT \
     ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input"
 
@@ -212,15 +142,9 @@ void qerror_report_err(Error *err);
 #define QERR_QMP_EXTRA_MEMBER \
     ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' is unexpected"
 
-#define QERR_RESET_REQUIRED \
-    ERROR_CLASS_GENERIC_ERROR, "Resetting the Virtual Machine is required"
-
 #define QERR_SET_PASSWD_FAILED \
     ERROR_CLASS_GENERIC_ERROR, "Could not set password"
 
-#define QERR_TOO_MANY_FILES \
-    ERROR_CLASS_GENERIC_ERROR, "Too many open files"
-
 #define QERR_UNDEFINED_ERROR \
     ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred"
 
@@ -230,9 +154,6 @@ void qerror_report_err(Error *err);
 #define QERR_UNSUPPORTED \
     ERROR_CLASS_GENERIC_ERROR, "this feature or command is not currently supported"
 
-#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \
-    ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'"
-
 #define QERR_SOCKET_CONNECT_FAILED \
     ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket"
 
diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h
index 3b098a9173..000eae3957 100644
--- a/include/qemu/error-report.h
+++ b/include/qemu/error-report.h
@@ -37,7 +37,6 @@ void loc_set_file(const char *fname, int lno);
 void error_vprintf(const char *fmt, va_list ap) GCC_FMT_ATTR(1, 0);
 void error_printf(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 void error_printf_unless_qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
-void error_print_loc(void);
 void error_set_progname(const char *argv0);
 void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
 const char *error_get_progname(void);
diff --git a/monitor.c b/monitor.c
index 342e83baea..1266ba06fb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -137,6 +137,7 @@ typedef struct mon_cmd_t {
      * used, and mhandler of 1st level plays the role of help function.
      */
     struct mon_cmd_t *sub_table;
+    void (*command_completion)(ReadLineState *rs, int nb_args, const char *str);
 } mon_cmd_t;
 
 /* file descriptors passed via SCM_RIGHTS */
@@ -352,33 +353,6 @@ void monitor_printf(Monitor *mon, const char *fmt, ...)
     va_end(ap);
 }
 
-void monitor_print_filename(Monitor *mon, const char *filename)
-{
-    int i;
-
-    for (i = 0; filename[i]; i++) {
-        switch (filename[i]) {
-        case ' ':
-        case '"':
-        case '\\':
-            monitor_printf(mon, "\\%c", filename[i]);
-            break;
-        case '\t':
-            monitor_printf(mon, "\\t");
-            break;
-        case '\r':
-            monitor_printf(mon, "\\r");
-            break;
-        case '\n':
-            monitor_printf(mon, "\\n");
-            break;
-        default:
-            monitor_printf(mon, "%c", filename[i]);
-            break;
-        }
-    }
-}
-
 static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream,
                                               const char *fmt, ...)
 {
@@ -2254,6 +2228,7 @@ void qmp_getfd(const char *fdname, Error **errp)
     }
 
     if (qemu_isdigit(fdname[0])) {
+        close(fd);
         error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdname",
                   "a name not starting with a digit");
         return;
@@ -4277,11 +4252,15 @@ static const char *next_arg_type(const char *typestr)
     return (p != NULL ? ++p : typestr);
 }
 
-static void device_add_completion(ReadLineState *rs, const char *str)
+void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
 {
     GSList *list, *elt;
     size_t len;
 
+    if (nb_args != 2) {
+        return;
+    }
+
     len = strlen(str);
     readline_set_completion_index(rs, len);
     list = elt = object_class_get_list(TYPE_DEVICE, false);
@@ -4290,7 +4269,9 @@ static void device_add_completion(ReadLineState *rs, const char *str)
         DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
                                              TYPE_DEVICE);
         name = object_class_get_name(OBJECT_CLASS(dc));
-        if (!strncmp(name, str, len)) {
+
+        if (!dc->cannot_instantiate_with_device_add_yet
+            && !strncmp(name, str, len)) {
             readline_add_completion(rs, name);
         }
         elt = elt->next;
@@ -4298,11 +4279,15 @@ static void device_add_completion(ReadLineState *rs, const char *str)
     g_slist_free(list);
 }
 
-static void object_add_completion(ReadLineState *rs, const char *str)
+void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
 {
     GSList *list, *elt;
     size_t len;
 
+    if (nb_args != 2) {
+        return;
+    }
+
     len = strlen(str);
     readline_set_completion_index(rs, len);
     list = elt = object_class_get_list(TYPE_USER_CREATABLE, false);
@@ -4318,8 +4303,8 @@ static void object_add_completion(ReadLineState *rs, const char *str)
     g_slist_free(list);
 }
 
-static void device_del_completion(ReadLineState *rs, BusState *bus,
-                                  const char *str, size_t len)
+static void device_del_bus_completion(ReadLineState *rs,  BusState *bus,
+                                      const char *str, size_t len)
 {
     BusChild *kid;
 
@@ -4332,16 +4317,32 @@ static void device_del_completion(ReadLineState *rs, BusState *bus,
         }
 
         QLIST_FOREACH(dev_child, &dev->child_bus, sibling) {
-            device_del_completion(rs, dev_child, str, len);
+            device_del_bus_completion(rs, dev_child, str, len);
         }
     }
 }
 
-static void object_del_completion(ReadLineState *rs, const char *str)
+void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    size_t len;
+
+    if (nb_args != 2) {
+        return;
+    }
+
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    device_del_bus_completion(rs, sysbus_get_default(), str, len);
+}
+
+void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
 {
     ObjectPropertyInfoList *list, *start;
     size_t len;
 
+    if (nb_args != 2) {
+        return;
+    }
     len = strlen(str);
     readline_set_completion_index(rs, len);
 
@@ -4395,6 +4396,9 @@ static void monitor_find_completion_by_table(Monitor *mon,
             return monitor_find_completion_by_table(mon, cmd->sub_table,
                                                     &args[1], nb_args - 1);
         }
+        if (cmd->command_completion) {
+            return cmd->command_completion(mon->rs, nb_args, args[nb_args - 1]);
+        }
 
         ptype = next_arg_type(cmd->args_type);
         for(i = 0; i < nb_args - 2; i++) {
@@ -4421,13 +4425,6 @@ static void monitor_find_completion_by_table(Monitor *mon,
             readline_set_completion_index(mon->rs, strlen(str));
             bdrv_iterate(block_completion_it, &mbs);
             break;
-        case 'O':
-            if (!strcmp(cmd->name, "device_add") && nb_args == 2) {
-                device_add_completion(mon->rs, str);
-            } else if (!strcmp(cmd->name, "object_add") && nb_args == 2) {
-                object_add_completion(mon->rs, str);
-            }
-            break;
         case 's':
         case 'S':
             if (!strcmp(cmd->name, "sendkey")) {
@@ -4441,12 +4438,6 @@ static void monitor_find_completion_by_table(Monitor *mon,
             } else if (!strcmp(cmd->name, "help|?")) {
                 monitor_find_completion_by_table(mon, cmd_table,
                                                  &args[1], nb_args - 1);
-            } else if (!strcmp(cmd->name, "device_del") && nb_args == 2) {
-                size_t len = strlen(str);
-                readline_set_completion_index(mon->rs, len);
-                device_del_completion(mon->rs, sysbus_get_default(), str, len);
-            } else if (!strcmp(cmd->name, "object_del") && nb_args == 2) {
-                object_del_completion(mon->rs, str);
             }
             break;
         default:
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 921de33bce..9c614494f1 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -80,7 +80,8 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
         return NULL;
     }
     if (!cmd->enabled) {
-        error_set(errp, QERR_COMMAND_DISABLED, command);
+        error_setg(errp, "The command %s has been disabled for this instance",
+                   command);
         return NULL;
     }
 
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index bf42c04ea6..a2bed1ef10 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -71,7 +71,7 @@ static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
     GHashTable *h;
 
     if (qiv->nb_stack >= QIV_STACK_SIZE) {
-        error_set(errp, QERR_BUFFER_OVERRUN);
+        error_setg(errp, "An internal buffer overran");
         return;
     }
 
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 9268c8759f..6189780fd7 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -422,12 +422,14 @@ static BusState *qbus_find(const char *path)
              * one child bus accept it nevertheless */
             switch (dev->num_child_bus) {
             case 0:
-                qerror_report(QERR_DEVICE_NO_BUS, elem);
+                qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                              "Device '%s' has no child bus", elem);
                 return NULL;
             case 1:
                 return QLIST_FIRST(&dev->child_bus);
             default:
-                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
+                qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                              "Device '%s' has multiple child busses", elem);
                 if (!monitor_cur_is_qmp()) {
                     qbus_list_bus(dev);
                 }
@@ -505,14 +507,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
             return NULL;
         }
         if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
-            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
+            qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                          "Device '%s' can't go on a %s bus",
                           driver, object_get_typename(OBJECT(bus)));
             return NULL;
         }
     } else if (dc->bus_type != NULL) {
         bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
         if (!bus) {
-            qerror_report(QERR_NO_BUS_FOR_DEVICE,
+            qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                          "No '%s' bus found for device '%s'",
                           dc->bus_type, driver);
             return NULL;
         }
diff --git a/qmp.c b/qmp.c
index 87a28f797d..74107be41b 100644
--- a/qmp.c
+++ b/qmp.c
@@ -166,7 +166,7 @@ void qmp_cont(Error **errp)
     Error *local_err = NULL;
 
     if (runstate_needs_reset()) {
-        error_set(errp, QERR_RESET_REQUIRED);
+        error_setg(errp, "Resetting the Virtual Machine is required");
         return;
     } else if (runstate_check(RUN_STATE_SUSPENDED)) {
         return;
@@ -540,14 +540,27 @@ void object_add(const char *type, const char *id, const QDict *qdict,
                 Visitor *v, Error **errp)
 {
     Object *obj;
+    ObjectClass *klass;
     const QDictEntry *e;
     Error *local_err = NULL;
 
-    if (!object_class_by_name(type)) {
+    klass = object_class_by_name(type);
+    if (!klass) {
         error_setg(errp, "invalid class name");
         return;
     }
 
+    if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
+        error_setg(errp, "object type '%s' isn't supported by object-add",
+                   type);
+        return;
+    }
+
+    if (object_class_is_abstract(klass)) {
+        error_setg(errp, "object type '%s' is abstract", type);
+        return;
+    }
+
     obj = object_new(type);
     if (qdict) {
         for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
@@ -558,12 +571,6 @@ void object_add(const char *type, const char *id, const QDict *qdict,
         }
     }
 
-    if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) {
-        error_setg(&local_err, "object type '%s' isn't supported by object-add",
-                   type);
-        goto out;
-    }
-
     user_creatable_complete(obj, &local_err);
     if (local_err) {
         goto out;
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index e7947b340c..e46c26448e 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -110,7 +110,7 @@ static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt,
         error_free(ctxt->err);
         ctxt->err = NULL;
     }
-    error_set(&ctxt->err, QERR_JSON_PARSE_ERROR, message);
+    error_setg(&ctxt->err, "JSON parse error, %s", message);
 }
 
 /**
diff --git a/qom/object.c b/qom/object.c
index 9a730e74c1..e42b254303 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -768,7 +768,7 @@ ObjectProperty *object_property_find(Object *obj, const char *name,
         }
     }
 
-    error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
+    error_setg(errp, "Property '.%s' not found", name);
     return NULL;
 }
 
@@ -1075,7 +1075,8 @@ static Object *object_resolve_link(Object *obj, const char *name,
     target = object_resolve_path_type(path, target_type, &ambiguous);
 
     if (ambiguous) {
-        error_set(errp, QERR_AMBIGUOUS_PATH, path);
+        error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+                  "Path '%s' does not uniquely identify an object", path);
     } else if (!target) {
         target = object_resolve_path(path, &ambiguous);
         if (target || ambiguous) {
diff --git a/savevm.c b/savevm.c
index 22123be4f9..da8aa2428d 100644
--- a/savevm.c
+++ b/savevm.c
@@ -453,7 +453,8 @@ bool qemu_savevm_state_blocked(Error **errp)
 
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (se->no_migrate) {
-            error_set(errp, QERR_MIGRATION_NOT_SUPPORTED, se->idstr);
+            error_setg(errp, "State blocked by non-migratable device '%s'",
+                       se->idstr);
             return true;
         }
     }
diff --git a/slirp/misc.c b/slirp/misc.c
index 6c1636f7b6..b8eb74cab0 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -136,7 +136,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 		if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
 		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
 		    listen(s, 1) < 0) {
-			lprint("Error: inet socket: %s\n", strerror(errno));
+			error_report("Error: inet socket: %s", strerror(errno));
 			closesocket(s);
 
 			return 0;
@@ -146,7 +146,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 	pid = fork();
 	switch(pid) {
 	 case -1:
-		lprint("Error: fork failed: %s\n", strerror(errno));
+		error_report("Error: fork failed: %s", strerror(errno));
 		close(s);
 		return 0;
 
@@ -242,15 +242,6 @@ strdup(str)
 }
 #endif
 
-void lprint(const char *format, ...)
-{
-    va_list args;
-
-    va_start(args, format);
-    monitor_vprintf(default_mon, format, args);
-    va_end(args);
-}
-
 void slirp_connection_info(Slirp *slirp, Monitor *mon)
 {
     const char * const tcpstates[] = {
diff --git a/slirp/slirp.c b/slirp/slirp.c
index bad8dad02e..3fb48a4921 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -139,7 +139,7 @@ int get_dns_addr(struct in_addr *pdns_addr)
         return -1;
 
 #ifdef DEBUG
-    lprint("IP address of your DNS(s): ");
+    fprintf(stderr, "IP address of your DNS(s): ");
 #endif
     while (fgets(buff, 512, f) != NULL) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
@@ -153,17 +153,17 @@ int get_dns_addr(struct in_addr *pdns_addr)
             }
 #ifdef DEBUG
             else
-                lprint(", ");
+                fprintf(stderr, ", ");
 #endif
             if (++found > 3) {
 #ifdef DEBUG
-                lprint("(more)");
+                fprintf(stderr, "(more)");
 #endif
                 break;
             }
 #ifdef DEBUG
             else
-                lprint("%s", inet_ntoa(tmp_addr));
+                fprintf(stderr, "%s", inet_ntoa(tmp_addr));
 #endif
         }
     }
diff --git a/slirp/slirp.h b/slirp/slirp.h
index e4a1bd4abb..6589d7eef0 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -287,8 +287,6 @@ void if_start(struct ttys *);
  long gethostid(void);
 #endif
 
-void lprint(const char *, ...) GCC_FMT_ATTR(1, 2);
-
 #ifndef _WIN32
 #include <netdb.h>
 #endif
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 5ed1d38d70..d99e2b9259 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -14,7 +14,6 @@ stub-obj-y += iothread-lock.o
 stub-obj-y += migr-blocker.o
 stub-obj-y += mon-is-qmp.o
 stub-obj-y += mon-printf.o
-stub-obj-y += mon-print-filename.o
 stub-obj-y += mon-protocol-event.o
 stub-obj-y += mon-set-error.o
 stub-obj-y += pci-drive-hot-add.o
diff --git a/stubs/arch-query-cpu-def.c b/stubs/arch-query-cpu-def.c
index fa6789598a..22e0b43de9 100644
--- a/stubs/arch-query-cpu-def.c
+++ b/stubs/arch-query-cpu-def.c
@@ -4,6 +4,6 @@
 
 CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
 {
-    error_set(errp, QERR_NOT_SUPPORTED);
+    error_set(errp, QERR_UNSUPPORTED);
     return NULL;
 }
diff --git a/stubs/mon-print-filename.c b/stubs/mon-print-filename.c
deleted file mode 100644
index 9c939641ff..0000000000
--- a/stubs/mon-print-filename.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "qemu-common.h"
-#include "monitor/monitor.h"
-
-void monitor_print_filename(Monitor *mon, const char *filename)
-{
-}
diff --git a/ui/vnc.c b/ui/vnc.c
index 5925774509..2d7def9aa2 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -996,7 +996,7 @@ static void audio_add(VncState *vs)
     struct audio_capture_ops ops;
 
     if (vs->audio_cap) {
-        monitor_printf(default_mon, "audio already running\n");
+        error_report("audio already running");
         return;
     }
 
@@ -1006,7 +1006,7 @@ static void audio_add(VncState *vs)
 
     vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs);
     if (!vs->audio_cap) {
-        monitor_printf(default_mon, "Failed to add audio capture\n");
+        error_report("Failed to add audio capture");
     }
 }
 
diff --git a/util/error.c b/util/error.c
index f11f1d57a0..2bb42e1c4b 100644
--- a/util/error.c
+++ b/util/error.c
@@ -12,10 +12,7 @@
 
 #include "qemu-common.h"
 #include "qapi/error.h"
-#include "qapi/qmp/qjson.h"
-#include "qapi/qmp/qdict.h"
-#include "qapi-types.h"
-#include "qapi/qmp/qerror.h"
+#include "qemu/error-report.h"
 
 struct Error
 {
diff --git a/util/qemu-config.c b/util/qemu-config.c
index f6101012c0..bcf0b86f91 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -20,7 +20,7 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
             break;
     }
     if (lists[i] == NULL) {
-        error_set(errp, QERR_INVALID_OPTION_GROUP, group);
+        error_setg(errp, "There is no option group '%s'", group);
     }
     return lists[i];
 }
diff --git a/util/qemu-error.c b/util/qemu-error.c
index fec02c6075..7b167fd06b 100644
--- a/util/qemu-error.c
+++ b/util/qemu-error.c
@@ -20,7 +20,7 @@
  */
 void error_vprintf(const char *fmt, va_list ap)
 {
-    if (cur_mon) {
+    if (cur_mon && !monitor_cur_is_qmp()) {
         monitor_vprintf(cur_mon, fmt, ap);
     } else {
         vfprintf(stderr, fmt, ap);
@@ -165,7 +165,7 @@ const char *error_get_progname(void)
 /*
  * Print current location to current monitor if we have one, else to stderr.
  */
-void error_print_loc(void)
+static void error_print_loc(void)
 {
     const char *sep = "";
     int i;
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 9d898af443..8bbc3ad4a3 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -819,7 +819,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
         opts = qemu_opts_find(list, id);
         if (opts != NULL) {
             if (fail_if_exists && !list->merge_lists) {
-                error_set(errp, QERR_DUPLICATE_ID, id, list->name);
+                error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
                 return NULL;
             } else {
                 return opts;