aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore150
-rw-r--r--block.c52
-rw-r--r--block/blkdebug.c4
-rw-r--r--block/blkverify.c2
-rw-r--r--block/curl.c2
-rw-r--r--block/gluster.c2
-rw-r--r--block/iscsi.c12
-rw-r--r--block/mirror.c19
-rw-r--r--block/nbd.c2
-rw-r--r--block/qapi.c4
-rw-r--r--block/qcow2-snapshot.c8
-rw-r--r--block/qcow2.c6
-rw-r--r--block/raw-posix.c12
-rw-r--r--block/raw-win32.c4
-rw-r--r--block/raw_bsd.c2
-rw-r--r--block/rbd.c2
-rw-r--r--block/sheepdog.c2
-rw-r--r--block/snapshot.c2
-rw-r--r--block/vmdk.c6
-rw-r--r--block/vvfat.c2
-rw-r--r--blockdev.c97
-rw-r--r--blockjob.c4
-rwxr-xr-xconfigure79
-rw-r--r--disas/libvixl/a64/disasm-a64.cc16
-rw-r--r--disas/libvixl/utils.cc20
-rw-r--r--hmp.c11
-rw-r--r--hw/acpi/pcihp.c127
-rw-r--r--hw/acpi/piix4.c322
-rw-r--r--hw/char/serial.c2
-rw-r--r--hw/core/Makefile.objs1
-rw-r--r--hw/core/hotplug.c48
-rw-r--r--hw/core/qdev.c50
-rw-r--r--hw/display/cirrus_vga.c2
-rw-r--r--hw/display/qxl.c2
-rw-r--r--hw/display/vga-pci.c2
-rw-r--r--hw/display/vmware_vga.c2
-rw-r--r--hw/i386/acpi-build.c4
-rw-r--r--hw/i386/acpi-dsdt-hpet.dsl3
-rw-r--r--hw/i386/pc.c4
-rw-r--r--hw/i386/pc_piix.c11
-rw-r--r--hw/ide/piix.c4
-rw-r--r--hw/isa/piix4.c2
-rw-r--r--hw/pci-bridge/pci_bridge_dev.c9
-rw-r--r--hw/pci-host/piix.c6
-rw-r--r--hw/pci/pci-hotplug-old.c4
-rw-r--r--hw/pci/pci.c40
-rw-r--r--hw/pci/pcie.c65
-rw-r--r--hw/pci/pcie_port.c8
-rw-r--r--hw/pci/shpc.c124
-rw-r--r--hw/sd/sdhci.c1
-rw-r--r--hw/sparc/leon3.c3
-rw-r--r--hw/usb/dev-network.c2
-rw-r--r--hw/usb/hcd-ehci-pci.c2
-rw-r--r--hw/usb/hcd-ohci.c2
-rw-r--r--hw/usb/hcd-uhci.c2
-rw-r--r--hw/usb/hcd-xhci.c2
-rw-r--r--include/hw/acpi/acpi.h1
-rw-r--r--include/hw/acpi/pcihp.h17
-rw-r--r--include/hw/hotplug.h78
-rw-r--r--include/hw/loader.h7
-rw-r--r--include/hw/pci/pci.h13
-rw-r--r--include/hw/pci/pci_bus.h2
-rw-r--r--include/hw/pci/pcie.h5
-rw-r--r--include/hw/pci/shpc.h8
-rw-r--r--include/hw/qdev-core.h15
-rw-r--r--include/net/checksum.h1
-rw-r--r--linux-user/syscall.c326
-rw-r--r--monitor.c95
-rw-r--r--net/net.c12
-rw-r--r--pc-bios/optionrom/Makefile3
-rw-r--r--qapi-schema.json22
-rw-r--r--qdev-monitor.c2
-rw-r--r--qemu-char.c25
-rw-r--r--qemu-img.c8
-rw-r--r--qga/commands-posix.c18
-rw-r--r--qga/commands-win32.c2
-rw-r--r--qmp-commands.hx41
-rw-r--r--savevm.c4
-rwxr-xr-xscripts/qmp/qmp-shell3
-rwxr-xr-xscripts/switch-timer-api2
-rw-r--r--target-mips/cpu.h13
-rw-r--r--target-mips/helper.h4
-rw-r--r--target-mips/mips-defs.h8
-rw-r--r--target-mips/op_helper.c53
-rw-r--r--target-mips/translate.c39
-rw-r--r--target-mips/translate_init.c43
-rw-r--r--target-openrisc/translate.c99
-rw-r--r--target-ppc/kvm.c2
-rw-r--r--tests/Makefile2
-rw-r--r--tests/i440fx-test.c2
-rwxr-xr-xtests/qemu-iotests/0052
-rwxr-xr-xtests/qemu-iotests/07013
-rw-r--r--tests/qemu-iotests/070.out15
-rw-r--r--tests/test-qmp-input-strict.c16
-rw-r--r--tests/test-qmp-input-visitor.c20
-rw-r--r--tests/test-qmp-output-visitor.c22
-rw-r--r--tests/test-string-input-visitor.c20
-rw-r--r--tests/test-string-output-visitor.c14
-rw-r--r--tpm.c2
-rw-r--r--util/qemu-config.c16
-rw-r--r--util/qemu-option.c22
-rw-r--r--vl.c57
102 files changed, 1388 insertions, 1184 deletions
diff --git a/.gitignore b/.gitignore
index 1c9d63d651..6e48b5ed3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,64 +1,64 @@
-config-devices.*
-config-all-devices.*
-config-all-disas.*
-config-host.*
-config-target.*
-config.status
-trace/generated-tracers.h
-trace/generated-tracers.c
-trace/generated-tracers-dtrace.h
-trace/generated-tracers.dtrace
-trace/generated-events.h
-trace/generated-events.c
-libcacard/trace/generated-tracers.c
+/config-devices.*
+/config-all-devices.*
+/config-all-disas.*
+/config-host.*
+/config-target.*
+/config.status
+/trace/generated-tracers.h
+/trace/generated-tracers.c
+/trace/generated-tracers-dtrace.h
+/trace/generated-tracers.dtrace
+/trace/generated-events.h
+/trace/generated-events.c
+/libcacard/trace/generated-tracers.c
*-timestamp
-*-softmmu
-*-darwin-user
-*-linux-user
-*-bsd-user
+/*-softmmu
+/*-darwin-user
+/*-linux-user
+/*-bsd-user
libdis*
libuser
-linux-headers/asm
-qapi-generated
-qapi-types.[ch]
-qapi-visit.[ch]
-qmp-commands.h
-qmp-marshal.c
-qemu-doc.html
-qemu-tech.html
-qemu-doc.info
-qemu-tech.info
-qemu.1
-qemu.pod
-qemu-img.1
-qemu-img.pod
-qemu-img
-qemu-nbd
-qemu-nbd.8
-qemu-nbd.pod
-qemu-options.def
-qemu-options.texi
-qemu-img-cmds.texi
-qemu-img-cmds.h
-qemu-io
-qemu-ga
-qemu-bridge-helper
-qemu-monitor.texi
-vscclient
-qmp-commands.txt
-test-bitops
-test-coroutine
-test-int128
-test-opts-visitor
-test-qmp-input-visitor
-test-qmp-output-visitor
-test-string-input-visitor
-test-string-output-visitor
-test-visitor-serialization
-fsdev/virtfs-proxy-helper
-fsdev/virtfs-proxy-helper.1
-fsdev/virtfs-proxy-helper.pod
-.gdbinit
+/linux-headers/asm
+/qapi-generated
+/qapi-types.[ch]
+/qapi-visit.[ch]
+/qmp-commands.h
+/qmp-marshal.c
+/qemu-doc.html
+/qemu-tech.html
+/qemu-doc.info
+/qemu-tech.info
+/qemu.1
+/qemu.pod
+/qemu-img.1
+/qemu-img.pod
+/qemu-img
+/qemu-nbd
+/qemu-nbd.8
+/qemu-nbd.pod
+/qemu-options.def
+/qemu-options.texi
+/qemu-img-cmds.texi
+/qemu-img-cmds.h
+/qemu-io
+/qemu-ga
+/qemu-bridge-helper
+/qemu-monitor.texi
+/qmp-commands.txt
+/vscclient
+/test-bitops
+/test-coroutine
+/test-int128
+/test-opts-visitor
+/test-qmp-input-visitor
+/test-qmp-output-visitor
+/test-string-input-visitor
+/test-string-output-visitor
+/test-visitor-serialization
+/fsdev/virtfs-proxy-helper
+/fsdev/virtfs-proxy-helper.1
+/fsdev/virtfs-proxy-helper.pod
+/.gdbinit
*.a
*.aux
*.cp
@@ -77,7 +77,7 @@ fsdev/virtfs-proxy-helper.pod
*.tp
*.vr
*.d
-!scripts/qemu-guest-agent/fsfreeze-hook.d
+!/scripts/qemu-guest-agent/fsfreeze-hook.d
*.o
*.lo
*.la
@@ -90,22 +90,22 @@ fsdev/virtfs-proxy-helper.pod
*.gcda
*.gcno
patches
-pc-bios/bios-pq/status
-pc-bios/vgabios-pq/status
-pc-bios/optionrom/linuxboot.asm
-pc-bios/optionrom/linuxboot.bin
-pc-bios/optionrom/linuxboot.raw
-pc-bios/optionrom/linuxboot.img
-pc-bios/optionrom/multiboot.asm
-pc-bios/optionrom/multiboot.bin
-pc-bios/optionrom/multiboot.raw
-pc-bios/optionrom/multiboot.img
-pc-bios/optionrom/kvmvapic.asm
-pc-bios/optionrom/kvmvapic.bin
-pc-bios/optionrom/kvmvapic.raw
-pc-bios/optionrom/kvmvapic.img
-pc-bios/s390-ccw/s390-ccw.elf
-pc-bios/s390-ccw/s390-ccw.img
+/pc-bios/bios-pq/status
+/pc-bios/vgabios-pq/status
+/pc-bios/optionrom/linuxboot.asm
+/pc-bios/optionrom/linuxboot.bin
+/pc-bios/optionrom/linuxboot.raw
+/pc-bios/optionrom/linuxboot.img
+/pc-bios/optionrom/multiboot.asm
+/pc-bios/optionrom/multiboot.bin
+/pc-bios/optionrom/multiboot.raw
+/pc-bios/optionrom/multiboot.img
+/pc-bios/optionrom/kvmvapic.asm
+/pc-bios/optionrom/kvmvapic.bin
+/pc-bios/optionrom/kvmvapic.raw
+/pc-bios/optionrom/kvmvapic.img
+/pc-bios/s390-ccw/s390-ccw.elf
+/pc-bios/s390-ccw/s390-ccw.img
.stgit-*
cscope.*
tags
diff --git a/block.c b/block.c
index 636aa117c3..6f4bacaa58 100644
--- a/block.c
+++ b/block.c
@@ -421,7 +421,7 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque)
assert(cco->drv);
ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(&cco->err, local_err);
}
cco->ret = ret;
@@ -460,7 +460,7 @@ int bdrv_create(BlockDriver *drv, const char* filename,
ret = cco.ret;
if (ret < 0) {
- if (error_is_set(&cco.err)) {
+ if (cco.err) {
error_propagate(errp, cco.err);
} else {
error_setg_errno(errp, -ret, "Could not create image");
@@ -486,7 +486,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options,
}
ret = bdrv_create(drv, filename, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
@@ -796,6 +796,13 @@ static int bdrv_assign_node_name(BlockDriverState *bs,
return -EINVAL;
}
+ /* takes care of avoiding namespaces collisions */
+ if (bdrv_find(node_name)) {
+ error_setg(errp, "node-name=%s is conflicting with a device id",
+ node_name);
+ return -EINVAL;
+ }
+
/* takes care of avoiding duplicates node names */
if (bdrv_find_node(node_name)) {
error_setg(errp, "Duplicate node name");
@@ -909,7 +916,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
}
if (ret < 0) {
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
} else if (bs->filename[0]) {
error_setg_errno(errp, -ret, "Could not open '%s'", bs->filename);
@@ -977,9 +984,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
}
QDECREF(options);
- bs = bdrv_find(reference);
+ bs = bdrv_lookup_bs(reference, reference, errp);
if (!bs) {
- error_setg(errp, "Cannot find block device '%s'", reference);
return -ENODEV;
}
bdrv_ref(bs);
@@ -1031,7 +1037,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
/* Parse the filename and open it */
if (drv->bdrv_parse_filename && filename) {
drv->bdrv_parse_filename(filename, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
@@ -1400,7 +1406,7 @@ fail:
QDECREF(bs->options);
QDECREF(options);
bs->options = NULL;
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
@@ -1408,7 +1414,7 @@ fail:
close_and_fail:
bdrv_close(bs);
QDECREF(options);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
@@ -3574,30 +3580,26 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
{
BlockDriverState *bs = NULL;
- if ((!device && !node_name) || (device && node_name)) {
- error_setg(errp, "Use either device or node-name but not both");
- return NULL;
- }
-
if (device) {
bs = bdrv_find(device);
- if (!bs) {
- error_set(errp, QERR_DEVICE_NOT_FOUND, device);
- return NULL;
+ if (bs) {
+ return bs;
}
-
- return bs;
}
- bs = bdrv_find_node(node_name);
+ if (node_name) {
+ bs = bdrv_find_node(node_name);
- if (!bs) {
- error_set(errp, QERR_DEVICE_NOT_FOUND, node_name);
- return NULL;
+ if (bs) {
+ return bs;
+ }
}
- return bs;
+ error_setg(errp, "Cannot find device=%s nor node_name=%s",
+ device ? device : "",
+ node_name ? node_name : "");
+ return NULL;
}
BlockDriverState *bdrv_next(BlockDriverState *bs)
@@ -5338,7 +5340,7 @@ out:
free_option_parameters(create_options);
free_option_parameters(param);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
}
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 8eb0db0723..ee10013362 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -303,7 +303,7 @@ static int read_config(BDRVBlkdebugState *s, const char *filename,
}
qemu_config_parse_qdict(options, config_groups, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
@@ -393,7 +393,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto out;
diff --git a/block/blkverify.c b/block/blkverify.c
index cfcbcf41c3..1563c88324 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -128,7 +128,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
diff --git a/block/curl.c b/block/curl.c
index a8075847b8..bb1fc4ae28 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -463,7 +463,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
goto out_noclean;
diff --git a/block/gluster.c b/block/gluster.c
index a009b15ded..58eab07829 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -282,7 +282,7 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
ret = -EINVAL;
diff --git a/block/iscsi.c b/block/iscsi.c
index 8d0f9667c5..f8e496f8ef 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1099,6 +1099,10 @@ fail:
/*
* We support iscsi url's on the form
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
+ *
+ * Note: flags are currently not used by iscsi_open. If this function
+ * is changed such that flags are used, please examine iscsi_reopen_prepare()
+ * to see if needs to be changed as well.
*/
static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
@@ -1123,7 +1127,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
ret = -EINVAL;
@@ -1336,11 +1340,13 @@ static int iscsi_refresh_limits(BlockDriverState *bs)
return 0;
}
-/* We have nothing to do for iSCSI reopen, stub just returns
- * success */
+/* Since iscsi_open() ignores bdrv_flags, there is nothing to do here in
+ * prepare. Note that this will not re-establish a connection with an iSCSI
+ * target - it is effectively a NOP. */
static int iscsi_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
+ /* NOP */
return 0;
}
diff --git a/block/mirror.c b/block/mirror.c
index 2a4333474e..e683959570 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -633,6 +633,8 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
{
int64_t length, base_length;
int orig_base_flags;
+ int ret;
+ Error *local_err = NULL;
orig_base_flags = bdrv_get_flags(base);
@@ -642,19 +644,23 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
length = bdrv_getlength(bs);
if (length < 0) {
- error_setg(errp, "Unable to determine length of %s", bs->filename);
+ error_setg_errno(errp, -length,
+ "Unable to determine length of %s", bs->filename);
goto error_restore_flags;
}
base_length = bdrv_getlength(base);
if (base_length < 0) {
- error_setg(errp, "Unable to determine length of %s", base->filename);
+ error_setg_errno(errp, -base_length,
+ "Unable to determine length of %s", base->filename);
goto error_restore_flags;
}
if (length > base_length) {
- if (bdrv_truncate(base, length) < 0) {
- error_setg(errp, "Top image %s is larger than base image %s, and "
+ ret = bdrv_truncate(base, length);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret,
+ "Top image %s is larger than base image %s, and "
"resize of base image failed",
bs->filename, base->filename);
goto error_restore_flags;
@@ -663,9 +669,10 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
bdrv_ref(base);
mirror_start_job(bs, base, speed, 0, 0,
- on_error, on_error, cb, opaque, errp,
+ on_error, on_error, cb, opaque, &local_err,
&commit_active_job_driver, false, base);
- if (error_is_set(errp)) {
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
goto error_restore_flags;
}
diff --git a/block/nbd.c b/block/nbd.c
index 327e913002..abae506f04 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -209,7 +209,7 @@ static int nbd_config(BDRVNBDState *s, QDict *options, char **export)
&error_abort);
qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -EINVAL;
diff --git a/block/qapi.c b/block/qapi.c
index 8f4134b40a..8f2b4dbe7d 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -271,7 +271,7 @@ void bdrv_query_info(BlockDriverState *bs,
p_image_info = &info->inserted->image;
while (1) {
bdrv_query_image_info(bs0, p_image_info, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto err;
}
@@ -336,7 +336,7 @@ BlockInfoList *qmp_query_block(Error **errp)
while ((bs = bdrv_next(bs))) {
BlockInfoList *info = g_malloc0(sizeof(*info));
bdrv_query_info(bs, &info->value, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto err;
}
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index ad8bf3dcd9..2fc6320aa1 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -606,7 +606,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
s->nb_snapshots--;
ret = qcow2_write_snapshots(bs);
if (ret < 0) {
- error_setg(errp, "Failed to remove snapshot from snapshot list");
+ error_setg_errno(errp, -ret,
+ "Failed to remove snapshot from snapshot list");
return ret;
}
@@ -624,7 +625,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
ret = qcow2_update_snapshot_refcount(bs, sn.l1_table_offset,
sn.l1_size, -1);
if (ret < 0) {
- error_setg(errp, "Failed to free the cluster and L1 table");
+ error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table");
return ret;
}
qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t),
@@ -633,7 +634,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
/* must update the copied flag on the current cluster offsets */
ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
if (ret < 0) {
- error_setg(errp, "Failed to update snapshot status in disk");
+ error_setg_errno(errp, -ret,
+ "Failed to update snapshot status in disk");
return ret;
}
diff --git a/block/qcow2.c b/block/qcow2.c
index 0b4335ca5b..b1dbdb120e 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -671,7 +671,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
/* Enable lazy_refcounts according to image and command line options */
opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
@@ -1605,7 +1605,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
ret = bdrv_open(bs, filename, NULL,
BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING,
drv, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto out;
}
@@ -1685,7 +1685,7 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options,
ret = qcow2_create2(filename, sectors, backing_file, backing_fmt, flags,
cluster_size, prealloc, options, version, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 126a634e45..161ea14812 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -361,7 +361,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
@@ -448,7 +448,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
s->type = FTYPE_FILE;
ret = raw_open_common(bs, options, flags, 0, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
@@ -1597,7 +1597,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
ret = raw_open_common(bs, options, flags, 0, &local_err);
if (ret < 0) {
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
@@ -1832,7 +1832,7 @@ static int floppy_open(BlockDriverState *bs, QDict *options, int flags,
/* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err);
if (ret) {
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
@@ -1961,7 +1961,7 @@ static int cdrom_open(BlockDriverState *bs, QDict *options, int flags,
/* open will not fail even if no CD is inserted, so add O_NONBLOCK */
ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
@@ -2078,7 +2078,7 @@ static int cdrom_open(BlockDriverState *bs, QDict *options, int flags,
ret = raw_open_common(bs, options, flags, 0, &local_err);
if (ret) {
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
diff --git a/block/raw-win32.c b/block/raw-win32.c
index beb7f2395e..ae1c8e6cca 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -279,7 +279,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
@@ -594,7 +594,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0,
&error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto done;
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index af8706dc97..01ea692a46 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -146,7 +146,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options,
int ret;
ret = bdrv_create_file(filename, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
return ret;
diff --git a/block/rbd.c b/block/rbd.c
index 121fae221e..dbc79f4525 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -440,7 +440,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
qemu_opts_del(opts);
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 672b9c97a2..e6c0376566 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1385,7 +1385,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
ret = -EINVAL;
diff --git a/block/snapshot.c b/block/snapshot.c
index 9047f8ddc9..85c52ff455 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -345,7 +345,7 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
ret = bdrv_snapshot_load_tmp(bs, NULL, id_or_name, &local_err);
}
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
}
diff --git a/block/vmdk.c b/block/vmdk.c
index e809e2ef46..ff6f5ee911 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1502,7 +1502,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
if (flat) {
ret = bdrv_truncate(bs, filesize);
if (ret < 0) {
- error_setg(errp, "Could not truncate file");
+ error_setg_errno(errp, -ret, "Could not truncate file");
}
goto exit;
}
@@ -1562,7 +1562,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
ret = bdrv_truncate(bs, le64_to_cpu(header.grain_offset) << 9);
if (ret < 0) {
- error_setg(errp, "Could not truncate file");
+ error_setg_errno(errp, -ret, "Could not truncate file");
goto exit;
}
@@ -1846,7 +1846,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
if (desc_offset == 0) {
ret = bdrv_truncate(new_bs, desc_len);
if (ret < 0) {
- error_setg(errp, "Could not truncate file");
+ error_setg_errno(errp, -ret, "Could not truncate file");
}
}
exit:
diff --git a/block/vvfat.c b/block/vvfat.c
index 664941c560..a19e4ca227 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1085,7 +1085,7 @@ DLOG(if (stderr == NULL) {
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
ret = -EINVAL;
diff --git a/blockdev.c b/blockdev.c
index d71f815a76..3cc8cda2bd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -308,7 +308,6 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
/* Takes the ownership of bs_opts */
static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
- BlockInterfaceType type,
Error **errp)
{
const char *buf;
@@ -331,13 +330,13 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
* stay in bs_opts for processing by bdrv_open(). */
id = qdict_get_try_str(bs_opts, "id");
opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
return NULL;
}
qemu_opts_absorb_qdict(opts, bs_opts, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
goto early_err;
}
@@ -437,13 +436,8 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
- if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
- error_setg(errp, "werror is not supported by this bus type");
- goto early_err;
- }
-
on_write_error = parse_block_error_action(buf, 0, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
goto early_err;
}
@@ -451,25 +445,25 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
on_read_error = BLOCKDEV_ON_ERROR_REPORT;
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
- if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
- error_report("rerror is not supported by this bus type");
- goto early_err;
- }
-
on_read_error = parse_block_error_action(buf, 1, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
goto early_err;
}
}
+ if (bdrv_find_node(qemu_opts_id(opts))) {
+ error_setg(errp, "device id=%s is conflicting with a node-name",
+ qemu_opts_id(opts));
+ goto early_err;
+ }
+
/* init */
dinfo = g_malloc0(sizeof(*dinfo));
dinfo->id = g_strdup(qemu_opts_id(opts));
dinfo->bdrv = bdrv_new(dinfo->id);
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
dinfo->bdrv->read_only = ro;
- dinfo->type = type;
dinfo->refcount = 1;
if (serial != NULL) {
dinfo->serial = g_strdup(serial);
@@ -609,6 +603,14 @@ QemuOptsList qemu_legacy_drive_opts = {
.type = QEMU_OPT_BOOL,
.help = "open drive file as read-only",
},{
+ .name = "rerror",
+ .type = QEMU_OPT_STRING,
+ .help = "read error action",
+ },{
+ .name = "werror",
+ .type = QEMU_OPT_STRING,
+ .help = "write error action",
+ },{
.name = "copy-on-read",
.type = QEMU_OPT_BOOL,
.help = "copy read data from backing file into image file",
@@ -629,6 +631,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
int cyls, heads, secs, translation;
int max_devs, bus_id, unit_id, index;
const char *devaddr;
+ const char *werror, *rerror;
bool read_only = false;
bool copy_on_read;
const char *filename;
@@ -688,7 +691,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
legacy_opts = qemu_opts_create(&qemu_legacy_drive_opts, NULL, 0,
&error_abort);
qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
goto fail;
@@ -876,16 +879,37 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
filename = qemu_opt_get(legacy_opts, "file");
+ /* Check werror/rerror compatibility with if=... */
+ werror = qemu_opt_get(legacy_opts, "werror");
+ if (werror != NULL) {
+ if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO &&
+ type != IF_NONE) {
+ error_report("werror is not supported by this bus type");
+ goto fail;
+ }
+ qdict_put(bs_opts, "werror", qstring_from_str(werror));
+ }
+
+ rerror = qemu_opt_get(legacy_opts, "rerror");
+ if (rerror != NULL) {
+ if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI &&
+ type != IF_NONE) {
+ error_report("rerror is not supported by this bus type");
+ goto fail;
+ }
+ qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
+ }
+
/* Actual block device init: Functionality shared with blockdev-add */
- dinfo = blockdev_init(filename, bs_opts, type, &local_err);
+ dinfo = blockdev_init(filename, bs_opts, &local_err);
if (dinfo == NULL) {
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
}
goto fail;
} else {
- assert(!error_is_set(&local_err));
+ assert(!local_err);
}
/* Set legacy DriveInfo fields */
@@ -897,6 +921,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
dinfo->secs = secs;
dinfo->trans = translation;
+ dinfo->type = type;
dinfo->bus = bus_id;
dinfo->unit = unit_id;
dinfo->devaddr = devaddr;
@@ -1021,7 +1046,7 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
}
ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return NULL;
}
@@ -1034,7 +1059,7 @@ SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
}
bdrv_snapshot_delete(bs, id, name, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return NULL;
}
@@ -1248,7 +1273,7 @@ static void external_snapshot_prepare(BlkTransactionState *common,
state->old_bs = bdrv_lookup_bs(has_device ? device : NULL,
has_node_name ? node_name : NULL,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -1293,7 +1318,7 @@ static void external_snapshot_prepare(BlkTransactionState *common,
state->old_bs->filename,
state->old_bs->drv->format_name,
NULL, -1, flags, &local_err, false);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -1314,8 +1339,6 @@ static void external_snapshot_prepare(BlkTransactionState *common,
if (ret != 0) {
error_propagate(errp, local_err);
}
-
- QDECREF(options);
}
static void external_snapshot_commit(BlkTransactionState *common)
@@ -1364,7 +1387,7 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp)
backup->has_on_source_error, backup->on_source_error,
backup->has_on_target_error, backup->on_target_error,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
state->bs = NULL;
state->job = NULL;
@@ -1456,7 +1479,7 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp)
QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
state->ops->prepare(state, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto delete_and_fail;
}
@@ -1537,7 +1560,7 @@ void qmp_block_passwd(bool has_device, const char *device,
bs = bdrv_lookup_bs(has_device ? device : NULL,
has_node_name ? node_name : NULL,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -1602,7 +1625,7 @@ void qmp_change_blockdev(const char *device, const char *filename,
}
eject_device(bs, 0, &err);
- if (error_is_set(&err)) {
+ if (err) {
error_propagate(errp, err);
return;
}
@@ -1739,7 +1762,7 @@ void qmp_block_resize(bool has_device, const char *device,
bs = bdrv_lookup_bs(has_device ? device : NULL,
has_node_name ? node_name : NULL,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -1832,7 +1855,7 @@ void qmp_block_stream(const char *device, bool has_base,
stream_start(bs, base_bs, base, has_speed ? speed : 0,
on_error, block_job_cb, bs, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -1990,7 +2013,7 @@ void qmp_drive_backup(const char *device, const char *target,
}
}
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -2131,7 +2154,7 @@ void qmp_drive_mirror(const char *device, const char *target,
}
}
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -2270,7 +2293,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
visit_type_BlockdevOptions(qmp_output_get_visitor(ov),
&options, NULL, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto fail;
}
@@ -2280,8 +2303,8 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
qdict_flatten(qdict);
- blockdev_init(NULL, qdict, IF_NONE, &local_err);
- if (error_is_set(&local_err)) {
+ blockdev_init(NULL, qdict, &local_err);
+ if (local_err) {
error_propagate(errp, local_err);
goto fail;
}
diff --git a/blockjob.c b/blockjob.c
index 9e5fd5c162..b3ce14cebd 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -61,7 +61,7 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
Error *local_err = NULL;
block_job_set_speed(job, speed, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
bs->job = NULL;
g_free(job);
bdrv_set_in_use(bs, 0);
@@ -92,7 +92,7 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
return;
}
job->driver->set_speed(job, speed, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
diff --git a/configure b/configure
index 88133a100e..4648117957 100755
--- a/configure
+++ b/configure
@@ -1392,6 +1392,11 @@ EOF
pie="no"
fi
fi
+
+ if compile_prog "-fno-pie" "-nopie"; then
+ CFLAGS_NOPIE="-fno-pie"
+ LDFLAGS_NOPIE="-nopie"
+ fi
fi
##########################################
@@ -1474,9 +1479,11 @@ esac
feature_not_found() {
feature=$1
+ remedy=$2
error_exit "User requested feature $feature" \
- "configure was not able to find it"
+ "configure was not able to find it." \
+ "$remedy"
}
# ---
@@ -1524,7 +1531,7 @@ int main(void) {
}
EOF
if ! compile_object ; then
- feature_not_found "nptl"
+ feature_not_found "nptl" "Install glibc and linux kernel headers."
fi
fi
@@ -1555,7 +1562,7 @@ if test "$seccomp" != "no" ; then
seccomp="yes"
else
if test "$seccomp" = "yes"; then
- feature_not_found "libseccomp"
+ feature_not_found "libseccomp" "Install libseccomp devel >= 2.1.0"
fi
seccomp="no"
fi
@@ -1580,7 +1587,7 @@ EOF
if ! compile_prog "" "$xen_libs" ; then
# Xen not found
if test "$xen" = "yes" ; then
- feature_not_found "xen"
+ feature_not_found "xen" "Install xen devel"
fi
xen=no
@@ -1703,7 +1710,7 @@ EOF
# Xen version unsupported
else
if test "$xen" = "yes" ; then
- feature_not_found "xen (unsupported version)"
+ feature_not_found "xen (unsupported version)" "Install supported xen (e.g. 4.0, 3.4, 3.3)"
fi
xen=no
fi
@@ -1752,7 +1759,7 @@ if test "$sparse" != "no" ; then
sparse=yes
else
if test "$sparse" = "yes" ; then
- feature_not_found "sparse"
+ feature_not_found "sparse" "Install sparse binary"
fi
sparse=no
fi
@@ -1774,7 +1781,7 @@ if test "$gtk" != "no"; then
fi
if ! $pkg_config --exists "$gtkpackage >= $gtkversion"; then
if test "$gtk" = "yes" ; then
- feature_not_found "gtk"
+ feature_not_found "gtk" "Install gtk2 or gtk3 (requires --with-gtkabi=3.0 option to configure) devel"
fi
gtk="no"
elif ! $pkg_config --exists "$vtepackage >= $vteversion"; then
@@ -1809,7 +1816,7 @@ elif has ${sdl_config}; then
_sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
else
if test "$sdl" = "yes" ; then
- feature_not_found "sdl"
+ feature_not_found "sdl" "Install SDL devel"
fi
sdl=no
fi
@@ -1853,7 +1860,7 @@ EOF
fi # static link
else # sdl not found
if test "$sdl" = "yes" ; then
- feature_not_found "sdl"
+ feature_not_found "sdl" "Install SDL devel"
fi
sdl=no
fi # sdl compile test
@@ -1919,10 +1926,10 @@ EOF
QEMU_CFLAGS="$QEMU_CFLAGS $vnc_tls_cflags"
else
if test "$vnc_tls" = "yes" ; then
- feature_not_found "vnc-tls"
+ feature_not_found "vnc-tls" "Install gnutls devel"
fi
if test "$vnc_ws" = "yes" ; then
- feature_not_found "vnc-ws"
+ feature_not_found "vnc-ws" "Install gnutls devel"
fi
vnc_tls=no
vnc_ws=no
@@ -1946,7 +1953,7 @@ EOF
QEMU_CFLAGS="$QEMU_CFLAGS $vnc_sasl_cflags"
else
if test "$vnc_sasl" = "yes" ; then
- feature_not_found "vnc-sasl"
+ feature_not_found "vnc-sasl" "Install Cyrus SASL devel"
fi
vnc_sasl=no
fi
@@ -1968,7 +1975,7 @@ EOF
QEMU_CFLAGS="$QEMU_CFLAGS $vnc_jpeg_cflags"
else
if test "$vnc_jpeg" = "yes" ; then
- feature_not_found "vnc-jpeg"
+ feature_not_found "vnc-jpeg" "Install libjpeg-turbo devel"
fi
vnc_jpeg=no
fi
@@ -2000,7 +2007,7 @@ EOF
QEMU_CFLAGS="$QEMU_CFLAGS $vnc_png_cflags"
else
if test "$vnc_png" = "yes" ; then
- feature_not_found "vnc-png"
+ feature_not_found "vnc-png" "Install libpng devel"
fi
vnc_png=no
fi
@@ -2044,7 +2051,7 @@ EOF
libs_tools="$uuid_libs $libs_tools"
else
if test "$uuid" = "yes" ; then
- feature_not_found "uuid"
+ feature_not_found "uuid" "Install libuuid devel"
fi
uuid=no
fi
@@ -2078,7 +2085,7 @@ EOF
xfs="yes"
else
if test "$xfs" = "yes" ; then
- feature_not_found "xfs"
+ feature_not_found "xfs" "Instal xfsprogs/xfslibs devel"
fi
xfs=no
fi
@@ -2104,7 +2111,7 @@ EOF
libs_tools="$vde_libs $libs_tools"
else
if test "$vde" = "yes" ; then
- feature_not_found "vde"
+ feature_not_found "vde" "Install vde (Virtual Distributed Ethernet) devel"
fi
vde=no
fi
@@ -2147,7 +2154,7 @@ EOF
libs_tools="$cap_libs $libs_tools"
else
if test "$cap_ng" = "yes" ; then
- feature_not_found "cap_ng"
+ feature_not_found "cap_ng" "Install libcap-ng devel"
fi
cap_ng=no
fi
@@ -2252,7 +2259,7 @@ EOF
libs_softmmu="$brlapi_libs $libs_softmmu"
else
if test "$brlapi" = "yes" ; then
- feature_not_found "brlapi"
+ feature_not_found "brlapi" "Install brlapi devel"
fi
brlapi=no
fi
@@ -2289,7 +2296,7 @@ EOF
curses=yes
else
if test "$curses" = "yes" ; then
- feature_not_found "curses"
+ feature_not_found "curses" "Install ncurses devel"
fi
curses=no
fi
@@ -2315,7 +2322,7 @@ EOF
libs_softmmu="$curl_libs $libs_softmmu"
else
if test "$curl" = "yes" ; then
- feature_not_found "curl"
+ feature_not_found "curl" "Install libcurl devel"
fi
curl=no
fi
@@ -2335,7 +2342,7 @@ EOF
libs_softmmu="$bluez_libs $libs_softmmu"
else
if test "$bluez" = "yes" ; then
- feature_not_found "bluez"
+ feature_not_found "bluez" "Install bluez-libs/libbluetooth devel"
fi
bluez="no"
fi
@@ -2471,7 +2478,7 @@ EOF
libs_softmmu="$rbd_libs $libs_softmmu"
else
if test "$rbd" = "yes" ; then
- feature_not_found "rados block device"
+ feature_not_found "rados block device" "Install librbd/ceph devel"
fi
rbd=no
fi
@@ -2537,7 +2544,7 @@ EOF
libs_tools="$libs_tools -laio"
else
if test "$linux_aio" = "yes" ; then
- feature_not_found "linux AIO"
+ feature_not_found "linux AIO" "Install libaio devel"
fi
linux_aio=no
fi
@@ -2585,7 +2592,7 @@ EOF
libattr=yes
else
if test "$attr" = "yes" ; then
- feature_not_found "ATTR"
+ feature_not_found "ATTR" "Install libc6 or libattr devel"
fi
attr=no
fi
@@ -2662,8 +2669,8 @@ EOF
fdt_libs="-L\$(BUILD_DIR)/dtc/libfdt $fdt_libs"
elif test "$fdt" = "yes" ; then
# have neither and want - prompt for system/submodule install
- error_exit "DTC not present. Your options:" \
- " (1) Preferred: Install the DTC devel package" \
+ error_exit "DTC (libfdt) not present. Your options:" \
+ " (1) Preferred: Install the DTC (libfdt) devel package" \
" (2) Fetch the DTC submodule, using:" \
" git submodule update --init dtc"
else
@@ -2689,7 +2696,7 @@ EOF
glx=yes
else
if test "$glx" = "yes" ; then
- feature_not_found "glx"
+ feature_not_found "glx" "Install GL devel (e.g. MESA)"
fi
glx_libs=
glx=no
@@ -2714,7 +2721,7 @@ if test "$glusterfs" != "no" ; then
fi
else
if test "$glusterfs" = "yes" ; then
- feature_not_found "GlusterFS backend support"
+ feature_not_found "GlusterFS backend support" "Install glusterfs-api devel"
fi
glusterfs="no"
fi
@@ -3034,7 +3041,7 @@ if test "$docs" != "no" ; then
docs=yes
else
if test "$docs" = "yes" ; then
- feature_not_found "docs"
+ feature_not_found "docs" "Install texinfo and Perl/perl-podlators"
fi
docs=no
fi
@@ -3083,7 +3090,7 @@ EOF
LIBS="$LIBS -liscsi"
else
if test "$libiscsi" = "yes" ; then
- feature_not_found "libiscsi"
+ feature_not_found "libiscsi" "Install libiscsi devel"
fi
libiscsi="no"
fi
@@ -3167,7 +3174,7 @@ EOF
spice_server_version=$($pkg_config --modversion spice-server)
else
if test "$spice" = "yes" ; then
- feature_not_found "spice"
+ feature_not_found "spice" "Install spice-server and spice-protocol devel"
fi
spice="no"
fi
@@ -3217,7 +3224,7 @@ if test "$libusb" != "no" ; then
libs_softmmu="$libs_softmmu $libusb_libs"
else
if test "$libusb" = "yes"; then
- feature_not_found "libusb"
+ feature_not_found "libusb" "Install libusb devel"
fi
libusb="no"
fi
@@ -3233,7 +3240,7 @@ if test "$usb_redir" != "no" ; then
libs_softmmu="$libs_softmmu $usb_redir_libs"
else
if test "$usb_redir" = "yes"; then
- feature_not_found "usb-redir"
+ feature_not_found "usb-redir" "Install usbredir devel"
fi
usb_redir="no"
fi
@@ -4320,7 +4327,7 @@ if test "$trace_backend" = "ftrace"; then
echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
trace_default=no
else
- feature_not_found "ftrace(trace backend)"
+ feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
fi
fi
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
@@ -4376,6 +4383,7 @@ echo "LD=$ld" >> $config_host_mak
echo "WINDRES=$windres" >> $config_host_mak
echo "LIBTOOL=$libtool" >> $config_host_mak
echo "CFLAGS=$CFLAGS" >> $config_host_mak
+echo "CFLAGS_NOPIE=$CFLAGS_NOPIE" >> $config_host_mak
echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak
if test "$sparse" = "yes" ; then
@@ -4389,6 +4397,7 @@ else
echo "AUTOCONF_HOST := " >> $config_host_mak
fi
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
+echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak
echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
echo "LIBS+=$LIBS" >> $config_host_mak
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
diff --git a/disas/libvixl/a64/disasm-a64.cc b/disas/libvixl/a64/disasm-a64.cc
index 4a49748095..5c6b898ea6 100644
--- a/disas/libvixl/a64/disasm-a64.cc
+++ b/disas/libvixl/a64/disasm-a64.cc
@@ -269,19 +269,19 @@ bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
((reg_size == kWRegSize) && (value <= 0xffffffff)));
// Test for movz: 16 bits set at positions 0, 16, 32 or 48.
- if (((value & 0xffffffffffff0000UL) == 0UL) ||
- ((value & 0xffffffff0000ffffUL) == 0UL) ||
- ((value & 0xffff0000ffffffffUL) == 0UL) ||
- ((value & 0x0000ffffffffffffUL) == 0UL)) {
+ if (((value & 0xffffffffffff0000ULL) == 0ULL) ||
+ ((value & 0xffffffff0000ffffULL) == 0ULL) ||
+ ((value & 0xffff0000ffffffffULL) == 0ULL) ||
+ ((value & 0x0000ffffffffffffULL) == 0ULL)) {
return true;
}
// Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
if ((reg_size == kXRegSize) &&
- (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) ||
- ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) ||
- ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) ||
- ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) {
+ (((value & 0xffffffffffff0000ULL) == 0xffffffffffff0000ULL) ||
+ ((value & 0xffffffff0000ffffULL) == 0xffffffff0000ffffULL) ||
+ ((value & 0xffff0000ffffffffULL) == 0xffff0000ffffffffULL) ||
+ ((value & 0x0000ffffffffffffULL) == 0x0000ffffffffffffULL))) {
return true;
}
if ((reg_size == kWRegSize) &&
diff --git a/disas/libvixl/utils.cc b/disas/libvixl/utils.cc
index 6f85e61835..a45fb95f47 100644
--- a/disas/libvixl/utils.cc
+++ b/disas/libvixl/utils.cc
@@ -95,7 +95,7 @@ int CountSetBits(uint64_t value, int width) {
ASSERT((width == 32) || (width == 64));
// Mask out unused bits to ensure that they are not counted.
- value &= (0xffffffffffffffffUL >> (64-width));
+ value &= (0xffffffffffffffffULL >> (64-width));
// Add up the set bits.
// The algorithm works by adding pairs of bit fields together iteratively,
@@ -108,12 +108,18 @@ int CountSetBits(uint64_t value, int width) {
// value = h+g+f+e d+c+b+a
// \ |
// value = h+g+f+e+d+c+b+a
- value = ((value >> 1) & 0x5555555555555555) + (value & 0x5555555555555555);
- value = ((value >> 2) & 0x3333333333333333) + (value & 0x3333333333333333);
- value = ((value >> 4) & 0x0f0f0f0f0f0f0f0f) + (value & 0x0f0f0f0f0f0f0f0f);
- value = ((value >> 8) & 0x00ff00ff00ff00ff) + (value & 0x00ff00ff00ff00ff);
- value = ((value >> 16) & 0x0000ffff0000ffff) + (value & 0x0000ffff0000ffff);
- value = ((value >> 32) & 0x00000000ffffffff) + (value & 0x00000000ffffffff);
+ value = ((value >> 1) & 0x5555555555555555ULL) +
+ (value & 0x5555555555555555ULL);
+ value = ((value >> 2) & 0x3333333333333333ULL) +
+ (value & 0x3333333333333333ULL);
+ value = ((value >> 4) & 0x0f0f0f0f0f0f0f0fULL) +
+ (value & 0x0f0f0f0f0f0f0f0fULL);
+ value = ((value >> 8) & 0x00ff00ff00ff00ffULL) +
+ (value & 0x00ff00ff00ff00ffULL);
+ value = ((value >> 16) & 0x0000ffff0000ffffULL) +
+ (value & 0x0000ffff0000ffffULL);
+ value = ((value >> 32) & 0x00000000ffffffffULL) +
+ (value & 0x00000000ffffffffULL);
return value;
}
diff --git a/hmp.c b/hmp.c
index 1af0809305..e3ddd4654d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -881,7 +881,7 @@ void hmp_balloon(Monitor *mon, const QDict *qdict)
Error *errp = NULL;
qmp_balloon(value, &errp);
- if (error_is_set(&errp)) {
+ if (errp) {
monitor_printf(mon, "balloon: %s\n", error_get_pretty(errp));
error_free(errp);
}
@@ -1118,7 +1118,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
}
qmp_change(device, target, !!arg, arg, &err);
- if (error_is_set(&err) &&
+ if (err &&
error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
error_free(err);
monitor_read_block_device_key(mon, device, NULL, NULL);
@@ -1234,7 +1234,8 @@ static void hmp_migrate_status_cb(void *opaque)
MigrationInfo *info;
info = qmp_query_migrate(NULL);
- if (!info->has_status || strcmp(info->status, "active") == 0) {
+ if (!info->has_status || strcmp(info->status, "active") == 0 ||
+ strcmp(info->status, "setup") == 0) {
if (info->has_disk) {
int progress;
@@ -1335,12 +1336,12 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict)
QemuOpts *opts;
opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
- if (error_is_set(&err)) {
+ if (err) {
goto out;
}
netdev_add(opts, &err);
- if (error_is_set(&err)) {
+ if (err) {
qemu_opts_del(opts);
}
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 3fa3d7c290..f80c48008c 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -46,13 +46,15 @@
# define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0)
#endif
-#define PCI_HOTPLUG_ADDR 0xae00
-#define PCI_HOTPLUG_SIZE 0x0014
-#define PCI_UP_BASE 0xae00
-#define PCI_DOWN_BASE 0xae04
-#define PCI_EJ_BASE 0xae08
-#define PCI_RMV_BASE 0xae0c
-#define PCI_SEL_BASE 0xae10
+#define ACPI_PCI_HOTPLUG_STATUS 2
+#define ACPI_PCIHP_ADDR 0xae00
+#define ACPI_PCIHP_SIZE 0x0014
+#define ACPI_PCIHP_LEGACY_SIZE 0x000f
+#define PCI_UP_BASE 0x0000
+#define PCI_DOWN_BASE 0x0004
+#define PCI_EJ_BASE 0x0008
+#define PCI_RMV_BASE 0x000c
+#define PCI_SEL_BASE 0x0010
typedef struct AcpiPciHpFind {
int bsel;
@@ -104,19 +106,19 @@ static PCIBus *acpi_pcihp_find_hotplug_bus(AcpiPciHpState *s, int bsel)
static bool acpi_pcihp_pc_no_hotplug(AcpiPciHpState *s, PCIDevice *dev)
{
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+ DeviceClass *dc = DEVICE_GET_CLASS(dev);
/*
* ACPI doesn't allow hotplug of bridge devices. Don't allow
* hot-unplug of bridge devices unless they were added by hotplug
* (and so, not described by acpi).
*/
- return (pc->is_bridge && !dev->qdev.hotplugged) || pc->no_hotplug;
+ return (pc->is_bridge && !dev->qdev.hotplugged) || !dc->hotpluggable;
}
static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slots)
{
BusChild *kid, *next;
int slot = ffs(slots) - 1;
- bool slot_free = true;
PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
if (!bus) {
@@ -125,21 +127,17 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo
/* Mark request as complete */
s->acpi_pcihp_pci_status[bsel].down &= ~(1U << slot);
+ s->acpi_pcihp_pci_status[bsel].up &= ~(1U << slot);
QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
DeviceState *qdev = kid->child;
PCIDevice *dev = PCI_DEVICE(qdev);
if (PCI_SLOT(dev->devfn) == slot) {
- if (acpi_pcihp_pc_no_hotplug(s, dev)) {
- slot_free = false;
- } else {
+ if (!acpi_pcihp_pc_no_hotplug(s, dev)) {
object_unparent(OBJECT(qdev));
}
}
}
- if (slot_free) {
- s->acpi_pcihp_pci_status[bsel].device_present &= ~(1U << slot);
- }
}
static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
@@ -153,7 +151,6 @@ static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
}
s->acpi_pcihp_pci_status[bsel].hotplug_enable = ~0;
- s->acpi_pcihp_pci_status[bsel].device_present = 0;
if (!bus) {
return;
@@ -166,8 +163,6 @@ static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
if (acpi_pcihp_pc_no_hotplug(s, pdev)) {
s->acpi_pcihp_pci_status[bsel].hotplug_enable &= ~(1U << slot);
}
-
- s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
}
}
@@ -185,40 +180,47 @@ void acpi_pcihp_reset(AcpiPciHpState *s)
acpi_pcihp_update(s);
}
-static void enable_device(AcpiPciHpState *s, unsigned bsel, int slot)
-{
- s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
-}
-
-static void disable_device(AcpiPciHpState *s, unsigned bsel, int slot)
-{
- s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
-}
-
-int acpi_pcihp_device_hotplug(AcpiPciHpState *s, PCIDevice *dev,
- PCIHotplugState state)
+void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+ DeviceState *dev, Error **errp)
{
- int slot = PCI_SLOT(dev->devfn);
- int bsel = acpi_pcihp_get_bsel(dev->bus);
+ PCIDevice *pdev = PCI_DEVICE(dev);
+ int slot = PCI_SLOT(pdev->devfn);
+ int bsel = acpi_pcihp_get_bsel(pdev->bus);
if (bsel < 0) {
- return -1;
+ error_setg(errp, "Unsupported bus. Bus doesn't have property '"
+ ACPI_PCIHP_PROP_BSEL "' set");
+ return;
}
/* Don't send event when device is enabled during qemu machine creation:
* it is present on boot, no hotplug event is necessary. We do send an
* event when the device is disabled later. */
- if (state == PCI_COLDPLUG_ENABLED) {
- s->acpi_pcihp_pci_status[bsel].device_present |= (1U << slot);
- return 0;
+ if (!dev->hotplugged) {
+ return;
}
- if (state == PCI_HOTPLUG_ENABLED) {
- enable_device(s, bsel, slot);
- } else {
- disable_device(s, bsel, slot);
+ s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
+
+ ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS;
+ acpi_update_sci(ar, irq);
+}
+
+void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+ DeviceState *dev, Error **errp)
+{
+ PCIDevice *pdev = PCI_DEVICE(dev);
+ int slot = PCI_SLOT(pdev->devfn);
+ int bsel = acpi_pcihp_get_bsel(pdev->bus);
+ if (bsel < 0) {
+ error_setg(errp, "Unsupported bus. Bus doesn't have property '"
+ ACPI_PCIHP_PROP_BSEL "' set");
+ return;
}
- return 0;
+ s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
+
+ ar->gpe.sts[0] |= ACPI_PCI_HOTPLUG_STATUS;
+ acpi_update_sci(ar, irq);
}
static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
@@ -232,26 +234,26 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
}
switch (addr) {
- case PCI_UP_BASE - PCI_HOTPLUG_ADDR:
- /* Manufacture an "up" value to cause a device check on any hotplug
- * slot with a device. Extra device checks are harmless. */
- val = s->acpi_pcihp_pci_status[bsel].device_present &
- s->acpi_pcihp_pci_status[bsel].hotplug_enable;
+ case PCI_UP_BASE:
+ val = s->acpi_pcihp_pci_status[bsel].up;
+ if (!s->legacy_piix) {
+ s->acpi_pcihp_pci_status[bsel].up = 0;
+ }
ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val);
break;
- case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR:
+ case PCI_DOWN_BASE:
val = s->acpi_pcihp_pci_status[bsel].down;
ACPI_PCIHP_DPRINTF("pci_down_read %" PRIu32 "\n", val);
break;
- case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
+ case PCI_EJ_BASE:
/* No feature defined yet */
ACPI_PCIHP_DPRINTF("pci_features_read %" PRIu32 "\n", val);
break;
- case PCI_RMV_BASE - PCI_HOTPLUG_ADDR:
+ case PCI_RMV_BASE:
val = s->acpi_pcihp_pci_status[bsel].hotplug_enable;
ACPI_PCIHP_DPRINTF("pci_rmv_read %" PRIu32 "\n", val);
break;
- case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
+ case PCI_SEL_BASE:
val = s->hotplug_select;
ACPI_PCIHP_DPRINTF("pci_sel_read %" PRIu32 "\n", val);
default:
@@ -266,7 +268,7 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data,
{
AcpiPciHpState *s = opaque;
switch (addr) {
- case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
+ case PCI_EJ_BASE:
if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
break;
}
@@ -274,7 +276,7 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data,
ACPI_PCIHP_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
addr, data);
break;
- case PCI_SEL_BASE - PCI_HOTPLUG_ADDR:
+ case PCI_SEL_BASE:
s->hotplug_select = data;
ACPI_PCIHP_DPRINTF("pcisel write %" HWADDR_PRIx " <== %" PRIu64 "\n",
addr, data);
@@ -294,13 +296,26 @@ static const MemoryRegionOps acpi_pcihp_io_ops = {
};
void acpi_pcihp_init(AcpiPciHpState *s, PCIBus *root_bus,
- MemoryRegion *address_space_io)
+ MemoryRegion *address_space_io, bool bridges_enabled)
{
+ uint16_t io_size = ACPI_PCIHP_SIZE;
+
s->root= root_bus;
+ s->legacy_piix = !bridges_enabled;
+
+ if (s->legacy_piix) {
+ unsigned *bus_bsel = g_malloc(sizeof *bus_bsel);
+
+ io_size = ACPI_PCIHP_LEGACY_SIZE;
+
+ *bus_bsel = ACPI_PCIHP_BSEL_DEFAULT;
+ object_property_add_uint32_ptr(OBJECT(root_bus), ACPI_PCIHP_PROP_BSEL,
+ bus_bsel, NULL);
+ }
+
memory_region_init_io(&s->io, NULL, &acpi_pcihp_io_ops, s,
- "acpi-pci-hotplug",
- PCI_HOTPLUG_SIZE);
- memory_region_add_subregion(address_space_io, PCI_HOTPLUG_ADDR, &s->io);
+ "acpi-pci-hotplug", io_size);
+ memory_region_add_subregion(address_space_io, ACPI_PCIHP_ADDR, &s->io);
}
const VMStateDescription vmstate_acpi_pcihp_pci_status = {
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 33e812d238..67dc0752f7 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -32,6 +32,7 @@
#include "hw/acpi/piix4.h"
#include "hw/acpi/pcihp.h"
#include "hw/acpi/cpu_hotplug.h"
+#include "hw/hotplug.h"
//#define DEBUG
@@ -44,15 +45,6 @@
#define GPE_BASE 0xafe0
#define GPE_LEN 4
-#define PCI_HOTPLUG_ADDR 0xae00
-#define PCI_HOTPLUG_SIZE 0x000f
-#define PCI_UP_BASE 0xae00
-#define PCI_DOWN_BASE 0xae04
-#define PCI_EJ_BASE 0xae08
-#define PCI_RMV_BASE 0xae0c
-
-#define PIIX4_PCI_HOTPLUG_STATUS 2
-
struct pci_status {
uint32_t up; /* deprecated, maintained for migration compatibility */
uint32_t down;
@@ -80,13 +72,6 @@ typedef struct PIIX4PMState {
Notifier machine_ready;
Notifier powerdown_notifier;
- /* for legacy pci hotplug (compatible with qemu 1.6 and older) */
- MemoryRegion io_pci;
- struct pci_status pci0_status;
- uint32_t pci0_hotplug_enable;
- uint32_t pci0_slot_device_present;
-
- /* for new pci hotplug (with PCI2PCI bridge support) */
AcpiPciHpState acpi_pci_hotplug;
bool use_acpi_pci_hotplug;
@@ -170,17 +155,6 @@ static void pm_write_config(PCIDevice *d,
}
}
-static void vmstate_pci_status_pre_save(void *opaque)
-{
- struct pci_status *pci0_status = opaque;
- PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status);
-
- /* We no longer track up, so build a safe value for migrating
- * to a version that still does... of course these might get lost
- * by an old buggy implementation, but we try. */
- pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable;
-}
-
static int vmstate_acpi_post_load(void *opaque, int version_id)
{
PIIX4PMState *s = opaque;
@@ -216,10 +190,9 @@ static const VMStateDescription vmstate_pci_status = {
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
- .pre_save = vmstate_pci_status_pre_save,
.fields = (VMStateField []) {
- VMSTATE_UINT32(up, struct pci_status),
- VMSTATE_UINT32(down, struct pci_status),
+ VMSTATE_UINT32(up, struct AcpiPciHpPciStatus),
+ VMSTATE_UINT32(down, struct AcpiPciHpPciStatus),
VMSTATE_END_OF_LIST()
}
};
@@ -256,7 +229,8 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id)
qemu_get_be16s(f, &temp);
}
- ret = vmstate_load_state(f, &vmstate_pci_status, &s->pci0_status, 1);
+ ret = vmstate_load_state(f, &vmstate_pci_status,
+ &s->acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT], 1);
return ret;
}
@@ -294,70 +268,18 @@ static const VMStateDescription vmstate_acpi = {
VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState),
VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState),
VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE),
- VMSTATE_STRUCT_TEST(pci0_status, PIIX4PMState,
- vmstate_test_no_use_acpi_pci_hotplug,
- 2, vmstate_pci_status,
- struct pci_status),
+ VMSTATE_STRUCT_TEST(
+ acpi_pci_hotplug.acpi_pcihp_pci_status[ACPI_PCIHP_BSEL_DEFAULT],
+ PIIX4PMState,
+ vmstate_test_no_use_acpi_pci_hotplug,
+ 2, vmstate_pci_status,
+ struct AcpiPciHpPciStatus),
VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState,
vmstate_test_use_acpi_pci_hotplug),
VMSTATE_END_OF_LIST()
}
};
-static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
-{
- BusChild *kid, *next;
- BusState *bus = qdev_get_parent_bus(DEVICE(s));
- int slot = ffs(slots) - 1;
- bool slot_free = true;
-
- /* Mark request as complete */
- s->pci0_status.down &= ~(1U << slot);
-
- QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
- DeviceState *qdev = kid->child;
- PCIDevice *dev = PCI_DEVICE(qdev);
- PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
- if (PCI_SLOT(dev->devfn) == slot) {
- if (pc->no_hotplug) {
- slot_free = false;
- } else {
- object_unparent(OBJECT(qdev));
- }
- }
- }
- if (slot_free) {
- s->pci0_slot_device_present &= ~(1U << slot);
- }
-}
-
-static void piix4_update_hotplug(PIIX4PMState *s)
-{
- BusState *bus = qdev_get_parent_bus(DEVICE(s));
- BusChild *kid, *next;
-
- /* Execute any pending removes during reset */
- while (s->pci0_status.down) {
- acpi_piix_eject_slot(s, s->pci0_status.down);
- }
-
- s->pci0_hotplug_enable = ~0;
- s->pci0_slot_device_present = 0;
-
- QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
- DeviceState *qdev = kid->child;
- PCIDevice *pdev = PCI_DEVICE(qdev);
- PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
- int slot = PCI_SLOT(pdev->devfn);
-
- if (pc->no_hotplug) {
- s->pci0_hotplug_enable &= ~(1U << slot);
- }
-
- s->pci0_slot_device_present |= (1U << slot);
- }
-}
-
static void piix4_reset(void *opaque)
{
PIIX4PMState *s = opaque;
@@ -377,11 +299,7 @@ static void piix4_reset(void *opaque)
pci_conf[0x5B] = 0x02;
}
pm_io_space_update(s);
- if (s->use_acpi_pci_hotplug) {
- acpi_pcihp_reset(&s->acpi_pci_hotplug);
- } else {
- piix4_update_hotplug(s);
- }
+ acpi_pcihp_reset(&s->acpi_pci_hotplug);
}
static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
@@ -392,24 +310,26 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
acpi_pm1_evt_power_down(&s->ar);
}
-static int piix4_acpi_pci_hotplug(DeviceState *qdev, PCIDevice *dev,
- PCIHotplugState state)
+static void piix4_pci_device_plug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
- PIIX4PMState *s = PIIX4_PM(qdev);
- int ret = acpi_pcihp_device_hotplug(&s->acpi_pci_hotplug, dev, state);
- if (ret < 0) {
- return ret;
- }
- s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
+ PIIX4PMState *s = PIIX4_PM(hotplug_dev);
+ acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, errp);
+}
- acpi_update_sci(&s->ar, s->irq);
- return 0;
+static void piix4_pci_device_unplug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ PIIX4PMState *s = PIIX4_PM(hotplug_dev);
+ acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
+ errp);
}
-static void piix4_update_bus_hotplug(PCIBus *bus, void *opaque)
+static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque)
{
PIIX4PMState *s = opaque;
- pci_bus_hotplug(bus, piix4_acpi_pci_hotplug, DEVICE(s));
+
+ qbus_set_hotplug_handler(BUS(pci_bus), DEVICE(s), &error_abort);
}
static void piix4_pm_machine_ready(Notifier *n, void *opaque)
@@ -428,6 +348,8 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
if (s->use_acpi_pci_hotplug) {
pci_for_each_bus(d->bus, piix4_update_bus_hotplug, s);
+ } else {
+ piix4_update_bus_hotplug(d->bus, s);
}
}
@@ -545,52 +467,6 @@ I2CBus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
return s->smb.smbus;
}
-static Property piix4_pm_properties[] = {
- DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
- DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
- DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
- DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
- DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState,
- use_acpi_pci_hotplug, true),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void piix4_pm_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
- k->no_hotplug = 1;
- k->init = piix4_pm_initfn;
- k->config_write = pm_write_config;
- k->vendor_id = PCI_VENDOR_ID_INTEL;
- k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
- k->revision = 0x03;
- k->class_id = PCI_CLASS_BRIDGE_OTHER;
- dc->desc = "PM";
- dc->vmsd = &vmstate_acpi;
- dc->props = piix4_pm_properties;
- /*
- * Reason: part of PIIX4 southbridge, needs to be wired up,
- * e.g. by mips_malta_init()
- */
- dc->cannot_instantiate_with_device_add_yet = true;
-}
-
-static const TypeInfo piix4_pm_info = {
- .name = TYPE_PIIX4_PM,
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PIIX4PMState),
- .class_init = piix4_pm_class_init,
-};
-
-static void piix4_pm_register_types(void)
-{
- type_register_static(&piix4_pm_info);
-}
-
-type_init(piix4_pm_register_types)
-
static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width)
{
PIIX4PMState *s = opaque;
@@ -621,60 +497,6 @@ static const MemoryRegionOps piix4_gpe_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
-{
- PIIX4PMState *s = opaque;
- uint32_t val = 0;
-
- switch (addr) {
- case PCI_UP_BASE - PCI_HOTPLUG_ADDR:
- /* Manufacture an "up" value to cause a device check on any hotplug
- * slot with a device. Extra device checks are harmless. */
- val = s->pci0_slot_device_present & s->pci0_hotplug_enable;
- PIIX4_DPRINTF("pci_up_read %" PRIu32 "\n", val);
- break;
- case PCI_DOWN_BASE - PCI_HOTPLUG_ADDR:
- val = s->pci0_status.down;
- PIIX4_DPRINTF("pci_down_read %" PRIu32 "\n", val);
- break;
- case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
- /* No feature defined yet */
- PIIX4_DPRINTF("pci_features_read %" PRIu32 "\n", val);
- break;
- case PCI_RMV_BASE - PCI_HOTPLUG_ADDR:
- val = s->pci0_hotplug_enable;
- break;
- default:
- break;
- }
-
- return val;
-}
-
-static void pci_write(void *opaque, hwaddr addr, uint64_t data,
- unsigned int size)
-{
- switch (addr) {
- case PCI_EJ_BASE - PCI_HOTPLUG_ADDR:
- acpi_piix_eject_slot(opaque, (uint32_t)data);
- PIIX4_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
- addr, data);
- break;
- default:
- break;
- }
-}
-
-static const MemoryRegionOps piix4_pci_ops = {
- .read = pci_read,
- .write = pci_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
static void piix4_cpu_added_req(Notifier *n, void *opaque)
{
PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier);
@@ -684,9 +506,6 @@ static void piix4_cpu_added_req(Notifier *n, void *opaque)
acpi_update_sci(&s->ar, s->irq);
}
-static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
- PCIHotplugState state);
-
static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
PCIBus *bus, PIIX4PMState *s)
{
@@ -694,15 +513,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
"acpi-gpe0", GPE_LEN);
memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe);
- if (s->use_acpi_pci_hotplug) {
- acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent);
- } else {
- memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s,
- "acpi-pci-hotplug", PCI_HOTPLUG_SIZE);
- memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR,
- &s->io_pci);
- pci_bus_hotplug(bus, piix4_device_hotplug, DEVICE(s));
- }
+ acpi_pcihp_init(&s->acpi_pci_hotplug, bus, parent,
+ s->use_acpi_pci_hotplug);
AcpiCpuHotplug_init(parent, OBJECT(s), &s->gpe_cpu,
PIIX4_CPU_HOTPLUG_IO_BASE);
@@ -710,39 +522,55 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
}
-static void enable_device(PIIX4PMState *s, int slot)
-{
- s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
- s->pci0_slot_device_present |= (1U << slot);
-}
+static Property piix4_pm_properties[] = {
+ DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
+ DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
+ DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_DISABLED, PIIX4PMState, disable_s4, 0),
+ DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
+ DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState,
+ use_acpi_pci_hotplug, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
-static void disable_device(PIIX4PMState *s, int slot)
+static void piix4_pm_class_init(ObjectClass *klass, void *data)
{
- s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
- s->pci0_status.down |= (1U << slot);
-}
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
-static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
- PCIHotplugState state)
-{
- int slot = PCI_SLOT(dev->devfn);
- PIIX4PMState *s = PIIX4_PM(qdev);
-
- /* Don't send event when device is enabled during qemu machine creation:
- * it is present on boot, no hotplug event is necessary. We do send an
- * event when the device is disabled later. */
- if (state == PCI_COLDPLUG_ENABLED) {
- s->pci0_slot_device_present |= (1U << slot);
- return 0;
- }
+ k->init = piix4_pm_initfn;
+ k->config_write = pm_write_config;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_BRIDGE_OTHER;
+ dc->desc = "PM";
+ dc->vmsd = &vmstate_acpi;
+ dc->props = piix4_pm_properties;
+ /*
+ * Reason: part of PIIX4 southbridge, needs to be wired up,
+ * e.g. by mips_malta_init()
+ */
+ dc->cannot_instantiate_with_device_add_yet = true;
+ dc->hotpluggable = false;
+ hc->plug = piix4_pci_device_plug_cb;
+ hc->unplug = piix4_pci_device_unplug_cb;
+}
- if (state == PCI_HOTPLUG_ENABLED) {
- enable_device(s, slot);
- } else {
- disable_device(s, slot);
+static const TypeInfo piix4_pm_info = {
+ .name = TYPE_PIIX4_PM,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PIIX4PMState),
+ .class_init = piix4_pm_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
}
+};
- acpi_update_sci(&s->ar, s->irq);
-
- return 0;
+static void piix4_pm_register_types(void)
+{
+ type_register_static(&piix4_pm_info);
}
+
+type_init(piix4_pm_register_types)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 27dab7d9d6..6d3b5aff8b 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -225,7 +225,7 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
if (s->tsr_retry <= 0) {
if (s->fcr & UART_FCR_FE) {
- s->tsr = fifo8_is_full(&s->xmit_fifo) ?
+ s->tsr = fifo8_is_empty(&s->xmit_fifo) ?
0 : fifo8_pop(&s->xmit_fifo);
if (!s->xmit_fifo.num) {
s->lsr |= UART_LSR_THRE;
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index 950146c6ff..9e324befd6 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -2,6 +2,7 @@
common-obj-y += qdev.o qdev-properties.o
# irq.o needed for qdev GPIO handling:
common-obj-y += irq.o
+common-obj-y += hotplug.o
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
common-obj-$(CONFIG_XILINX_AXI) += stream.o
diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c
new file mode 100644
index 0000000000..5573d9d2d9
--- /dev/null
+++ b/hw/core/hotplug.c
@@ -0,0 +1,48 @@
+/*
+ * Hotplug handler interface.
+ *
+ * Copyright (c) 2014 Red Hat Inc.
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "hw/hotplug.h"
+#include "qemu/module.h"
+
+void hotplug_handler_plug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp)
+{
+ HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+
+ if (hdc->plug) {
+ hdc->plug(plug_handler, plugged_dev, errp);
+ }
+}
+
+void hotplug_handler_unplug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp)
+{
+ HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
+
+ if (hdc->unplug) {
+ hdc->unplug(plug_handler, plugged_dev, errp);
+ }
+}
+
+static const TypeInfo hotplug_handler_info = {
+ .name = TYPE_HOTPLUG_HANDLER,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(HotplugHandlerClass),
+};
+
+static void hotplug_handler_register_types(void)
+{
+ type_register_static(&hotplug_handler_info);
+}
+
+type_init(hotplug_handler_register_types)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 482a9780d1..c0b857fbd4 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -32,6 +32,7 @@
#include "qapi/visitor.h"
#include "qapi/qmp/qjson.h"
#include "monitor/monitor.h"
+#include "hw/hotplug.h"
int qdev_hotplug = 0;
static bool qdev_hot_added = false;
@@ -212,13 +213,22 @@ void qdev_unplug(DeviceState *dev, Error **errp)
error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
return;
}
- assert(dc->unplug != NULL);
+
+ if (!dc->hotpluggable) {
+ error_set(errp, QERR_DEVICE_NO_HOTPLUG,
+ object_get_typename(OBJECT(dev)));
+ return;
+ }
qdev_hot_removed = true;
- if (dc->unplug(dev) < 0) {
- error_set(errp, QERR_UNDEFINED_ERROR);
- return;
+ if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
+ hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp);
+ } else {
+ assert(dc->unplug != NULL);
+ if (dc->unplug(dev) < 0) { /* legacy handler */
+ error_set(errp, QERR_UNDEFINED_ERROR);
+ }
}
}
@@ -663,6 +673,11 @@ static void device_set_realized(Object *obj, bool value, Error **err)
DeviceClass *dc = DEVICE_GET_CLASS(dev);
Error *local_err = NULL;
+ if (dev->hotplugged && !dc->hotpluggable) {
+ error_set(err, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
+ return;
+ }
+
if (value && !dev->realized) {
if (!obj->parent && local_err == NULL) {
static int unattached_count;
@@ -678,6 +693,12 @@ static void device_set_realized(Object *obj, bool value, Error **err)
dc->realize(dev, &local_err);
}
+ if (dev->parent_bus && dev->parent_bus->hotplug_handler &&
+ local_err == NULL) {
+ hotplug_handler_plug(dev->parent_bus->hotplug_handler,
+ dev, &local_err);
+ }
+
if (qdev_get_vmsd(dev) && local_err == NULL) {
vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
dev->instance_id_alias,
@@ -703,6 +724,14 @@ static void device_set_realized(Object *obj, bool value, Error **err)
dev->realized = value;
}
+static bool device_get_hotpluggable(Object *obj, Error **err)
+{
+ DeviceClass *dc = DEVICE_GET_CLASS(obj);
+ DeviceState *dev = DEVICE(obj);
+
+ return dc->hotpluggable && dev->parent_bus->allow_hotplug;
+}
+
static void device_initfn(Object *obj)
{
DeviceState *dev = DEVICE(obj);
@@ -719,6 +748,8 @@ static void device_initfn(Object *obj)
object_property_add_bool(obj, "realized",
device_get_realized, device_set_realized, NULL);
+ object_property_add_bool(obj, "hotpluggable",
+ device_get_hotpluggable, NULL, NULL);
class = object_get_class(OBJECT(dev));
do {
@@ -755,6 +786,14 @@ static void device_class_base_init(ObjectClass *class, void *data)
* so do not propagate them to the subclasses.
*/
klass->props = NULL;
+
+ /* by default all devices were considered as hotpluggable,
+ * so with intent to check it in generic qdev_unplug() /
+ * device_set_realized() functions make every device
+ * hotpluggable. Devices that shouldn't be hotpluggable,
+ * should override it in their class_init()
+ */
+ klass->hotpluggable = true;
}
static void device_unparent(Object *obj)
@@ -840,6 +879,9 @@ static void qbus_initfn(Object *obj)
BusState *bus = BUS(obj);
QTAILQ_INIT(&bus->children);
+ object_property_add_link(obj, QDEV_HOTPLUG_HANDLER_PROPERTY,
+ TYPE_HOTPLUG_HANDLER,
+ (Object **)&bus->hotplug_handler, NULL);
}
static char *default_bus_get_fw_dev_path(DeviceState *dev)
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index e4c345fa82..3a8fc0bf8e 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2996,7 +2996,6 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = pci_cirrus_vga_initfn;
k->romfile = VGABIOS_CIRRUS_FILENAME;
k->vendor_id = PCI_VENDOR_ID_CIRRUS;
@@ -3006,6 +3005,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data)
dc->desc = "Cirrus CLGD 54xx VGA";
dc->vmsd = &vmstate_pci_cirrus_vga;
dc->props = pci_vga_cirrus_properties;
+ dc->hotpluggable = false;
}
static const TypeInfo cirrus_vga_info = {
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 334c2719f8..1471cc093b 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2303,7 +2303,6 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = qxl_init_primary;
k->romfile = "vgabios-qxl.bin";
k->vendor_id = REDHAT_PCI_VENDOR_ID;
@@ -2314,6 +2313,7 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data)
dc->reset = qxl_reset_handler;
dc->vmsd = &qxl_vmstate;
dc->props = qxl_properties;
+ dc->hotpluggable = false;
}
static const TypeInfo qxl_primary_info = {
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index b3a45c81da..f74fc43aa6 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -190,7 +190,6 @@ static void vga_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = pci_std_vga_initfn;
k->romfile = "vgabios-stdvga.bin";
k->vendor_id = PCI_VENDOR_ID_QEMU;
@@ -198,6 +197,7 @@ static void vga_class_init(ObjectClass *klass, void *data)
k->class_id = PCI_CLASS_DISPLAY_VGA;
dc->vmsd = &vmstate_vga_pci;
dc->props = vga_pci_properties;
+ dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index aba292ccde..334e71856e 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1296,7 +1296,6 @@ static void vmsvga_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = pci_vmsvga_initfn;
k->romfile = "vgabios-vmware.bin";
k->vendor_id = PCI_VENDOR_ID_VMWARE;
@@ -1307,6 +1306,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data)
dc->reset = vmsvga_reset;
dc->vmsd = &vmstate_vmware_vga;
dc->props = vga_vmware_properties;
+ dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 50e83f3b46..b1a7ebb8e3 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -768,6 +768,7 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
memset(slot_hotplug_enable, 0xff, sizeof slot_hotplug_enable);
for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
+ DeviceClass *dc;
PCIDeviceClass *pc;
PCIDevice *pdev = bus->devices[i];
@@ -776,8 +777,9 @@ static void build_pci_bus_end(PCIBus *bus, void *bus_state)
}
pc = PCI_DEVICE_GET_CLASS(pdev);
+ dc = DEVICE_GET_CLASS(pdev);
- if (pc->no_hotplug || pc->is_bridge) {
+ if (!dc->hotpluggable || pc->is_bridge) {
int slot = PCI_SLOT(i);
clear_bit(slot, slot_hotplug_enable);
diff --git a/hw/i386/acpi-dsdt-hpet.dsl b/hw/i386/acpi-dsdt-hpet.dsl
index dfde174317..44961b87a1 100644
--- a/hw/i386/acpi-dsdt-hpet.dsl
+++ b/hw/i386/acpi-dsdt-hpet.dsl
@@ -39,9 +39,6 @@ Scope(\_SB) {
Return (0x0F)
}
Name(_CRS, ResourceTemplate() {
-#if 0 /* This makes WinXP BSOD for not yet figured reasons. */
- IRQNoFlags() {2, 8}
-#endif
Memory32Fixed(ReadOnly,
0xFED00000, // Address Base
0x00000400, // Address Length
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 348b15f267..e715a3312d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -835,8 +835,8 @@ static void load_linux(FWCfgState *fw_cfg,
initrd_size = get_image_size(initrd_filename);
if (initrd_size < 0) {
- fprintf(stderr, "qemu: error reading initrd %s\n",
- initrd_filename);
+ fprintf(stderr, "qemu: error reading initrd %s: %s\n",
+ initrd_filename, strerror(errno));
exit(1);
}
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 3639a6d099..d5dc1ef336 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -793,6 +793,17 @@ static QEMUMachine xenfv_machine = {
.max_cpus = HVM_MAX_VCPUS,
.default_machine_opts = "accel=xen",
.hot_add_cpu = pc_hot_add_cpu,
+ .compat_props = (GlobalProperty[]) {
+ /* xenfv has no fwcfg and so does not load acpi from QEMU.
+ * as such new acpi features don't work.
+ */
+ {
+ .driver = "PIIX4_PM",
+ .property = "acpi-pci-hotplug-with-bridge-support",
+ .value = "off",
+ },
+ { /* end of list */ }
+ },
};
#endif
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 9b5960b44e..0eda301ba9 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -241,13 +241,13 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = pci_piix_ide_initfn;
k->exit = pci_piix_ide_exitfn;
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
k->class_id = PCI_CLASS_STORAGE_IDE;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
+ dc->hotpluggable = false;
}
static const TypeInfo piix3_ide_info = {
@@ -280,13 +280,13 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = pci_piix_ide_initfn;
k->exit = pci_piix_ide_exitfn;
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82371AB;
k->class_id = PCI_CLASS_STORAGE_IDE;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
+ dc->hotpluggable = false;
}
static const TypeInfo piix4_ide_info = {
diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index def6fe3a0f..492cd22fcf 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -107,7 +107,6 @@ static void piix4_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = piix4_initfn;
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0;
@@ -119,6 +118,7 @@ static void piix4_class_init(ObjectClass *klass, void *data)
* e.g. by mips_malta_init()
*/
dc->cannot_instantiate_with_device_add_yet = true;
+ dc->hotpluggable = false;
}
static const TypeInfo piix4_info = {
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index 440e187c46..e68145c52f 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -26,6 +26,7 @@
#include "hw/pci/slotid_cap.h"
#include "exec/memory.h"
#include "hw/pci/pci_bus.h"
+#include "hw/hotplug.h"
#define TYPE_PCI_BRIDGE_DEV "pci-bridge"
#define PCI_BRIDGE_DEV(obj) \
@@ -136,6 +137,8 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
+
k->init = pci_bridge_dev_initfn;
k->exit = pci_bridge_dev_exitfn;
k->config_write = pci_bridge_dev_write_config;
@@ -148,6 +151,8 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
dc->props = pci_bridge_dev_properties;
dc->vmsd = &pci_bridge_dev_vmstate;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+ hc->plug = shpc_device_hotplug_cb;
+ hc->unplug = shpc_device_hot_unplug_cb;
}
static const TypeInfo pci_bridge_dev_info = {
@@ -155,6 +160,10 @@ static const TypeInfo pci_bridge_dev_info = {
.parent = TYPE_PCI_BRIDGE,
.instance_size = sizeof(PCIBridgeDev),
.class_init = pci_bridge_dev_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ }
};
static void pci_bridge_dev_register(void)
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index e89d5c1dfa..ffdc853a62 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -628,7 +628,7 @@ static void piix3_class_init(ObjectClass *klass, void *data)
dc->desc = "ISA bridge";
dc->vmsd = &vmstate_piix3;
- k->no_hotplug = 1;
+ dc->hotpluggable = false;
k->init = piix3_initfn;
k->config_write = piix3_write_config;
k->vendor_id = PCI_VENDOR_ID_INTEL;
@@ -656,7 +656,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data)
dc->desc = "ISA bridge";
dc->vmsd = &vmstate_piix3;
- k->no_hotplug = 1;
+ dc->hotpluggable = false;
k->init = piix3_initfn;
k->config_write = piix3_write_config_xen;
k->vendor_id = PCI_VENDOR_ID_INTEL;
@@ -682,7 +682,6 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
- k->no_hotplug = 1;
k->init = i440fx_initfn;
k->config_write = i440fx_write_config;
k->vendor_id = PCI_VENDOR_ID_INTEL;
@@ -696,6 +695,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
* host-facing part, which can't be device_add'ed, yet.
*/
dc->cannot_instantiate_with_device_add_yet = true;
+ dc->hotpluggable = false;
}
static const TypeInfo i440fx_info = {
diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
index 8dbc3c1cab..cf2caebfb1 100644
--- a/hw/pci/pci-hotplug-old.c
+++ b/hw/pci/pci-hotplug-old.c
@@ -90,7 +90,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
qemu_opt_set(opts, "type", "nic");
ret = net_client_init(opts, 0, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return NULL;
@@ -322,7 +322,7 @@ static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
}
qdev_unplug(&d->qdev, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
monitor_printf(mon, "%s\n", error_get_pretty(local_err));
error_free(local_err);
return -1;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 1221f32847..4e0701df38 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -35,6 +35,7 @@
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
#include "exec/address-spaces.h"
+#include "hw/hotplug.h"
//#define DEBUG_PCI
#ifdef DEBUG_PCI
@@ -346,13 +347,6 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
}
-void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
-{
- bus->qbus.allow_hotplug = 1;
- bus->hotplug = hotplug;
- bus->hotplug_qdev = qdev;
-}
-
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque,
@@ -1761,11 +1755,7 @@ static int pci_qdev_init(DeviceState *qdev)
pci_dev->devfn);
if (pci_dev == NULL)
return -1;
- if (qdev->hotplugged && pc->no_hotplug) {
- qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev)));
- do_pci_unregister_device(pci_dev);
- return -1;
- }
+
if (pc->init) {
rc = pc->init(pci_dev);
if (rc != 0) {
@@ -1782,34 +1772,9 @@ static int pci_qdev_init(DeviceState *qdev)
}
pci_add_option_rom(pci_dev, is_default_rom);
- if (bus->hotplug) {
- /* Let buses differentiate between hotplug and when device is
- * enabled during qemu machine creation. */
- rc = bus->hotplug(bus->hotplug_qdev, pci_dev,
- qdev->hotplugged ? PCI_HOTPLUG_ENABLED:
- PCI_COLDPLUG_ENABLED);
- if (rc != 0) {
- int r = pci_unregister_device(&pci_dev->qdev);
- assert(!r);
- return rc;
- }
- }
return 0;
}
-static int pci_unplug_device(DeviceState *qdev)
-{
- PCIDevice *dev = PCI_DEVICE(qdev);
- PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
-
- if (pc->no_hotplug) {
- qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev)));
- return -1;
- }
- return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
- PCI_HOTPLUG_DISABLED);
-}
-
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
const char *name)
{
@@ -2280,7 +2245,6 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = pci_qdev_init;
- k->unplug = pci_unplug_device;
k->exit = pci_unregister_device;
k->bus_type = TYPE_PCI_BUS;
k->props = pci_props;
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index ca60cf2177..8ecd11eca2 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -26,6 +26,7 @@
#include "hw/pci/pci_bus.h"
#include "hw/pci/pcie_regs.h"
#include "qemu/range.h"
+#include "qapi/qmp/qerror.h"
//#define DEBUG_PCIE
#ifdef DEBUG_PCIE
@@ -216,28 +217,20 @@ static void pcie_cap_slot_event(PCIDevice *dev, PCIExpressHotPlugEvent event)
hotplug_event_notify(dev);
}
-static int pcie_cap_slot_hotplug(DeviceState *qdev,
- PCIDevice *pci_dev, PCIHotplugState state)
+static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev,
+ DeviceState *dev,
+ uint8_t **exp_cap, Error **errp)
{
- PCIDevice *d = PCI_DEVICE(qdev);
- uint8_t *exp_cap = d->config + d->exp.exp_cap;
- uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
-
- /* Don't send event when device is enabled during qemu machine creation:
- * it is present on boot, no hotplug event is necessary. We do send an
- * event when the device is disabled later. */
- if (state == PCI_COLDPLUG_ENABLED) {
- pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
- PCI_EXP_SLTSTA_PDS);
- return 0;
- }
+ PCIDevice *pci_dev = PCI_DEVICE(dev);
+ *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
+ uint16_t sltsta = pci_get_word(*exp_cap + PCI_EXP_SLTSTA);
PCIE_DEV_PRINTF(pci_dev, "hotplug state: %d\n", state);
if (sltsta & PCI_EXP_SLTSTA_EIS) {
/* the slot is electromechanically locked.
* This error is propagated up to qdev and then to HMP/QMP.
*/
- return -EBUSY;
+ error_setg_errno(errp, -EBUSY, "slot is electromechanically locked");
}
/* TODO: multifunction hot-plug.
@@ -245,18 +238,40 @@ static int pcie_cap_slot_hotplug(DeviceState *qdev,
* hot plugged/unplugged.
*/
assert(PCI_FUNC(pci_dev->devfn) == 0);
+}
- if (state == PCI_HOTPLUG_ENABLED) {
+void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ uint8_t *exp_cap;
+
+ pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
+
+ /* Don't send event when device is enabled during qemu machine creation:
+ * it is present on boot, no hotplug event is necessary. We do send an
+ * event when the device is disabled later. */
+ if (!dev->hotplugged) {
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDS);
- pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
- } else {
- object_unparent(OBJECT(pci_dev));
- pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
- PCI_EXP_SLTSTA_PDS);
- pcie_cap_slot_event(d, PCI_EXP_HP_EV_PDC);
+ return;
}
- return 0;
+
+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
+ PCI_EXP_SLTSTA_PDS);
+ pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
+}
+
+void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ uint8_t *exp_cap;
+
+ pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
+
+ object_unparent(OBJECT(dev));
+ pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
+ PCI_EXP_SLTSTA_PDS);
+ pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC);
}
/* pci express slot for pci express root/downstream port
@@ -305,8 +320,8 @@ void pcie_cap_slot_init(PCIDevice *dev, uint16_t slot)
dev->exp.hpev_notified = false;
- pci_bus_hotplug(pci_bridge_get_sec_bus(PCI_BRIDGE(dev)),
- pcie_cap_slot_hotplug, &dev->qdev);
+ qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))),
+ DEVICE(dev), NULL);
}
void pcie_cap_slot_reset(PCIDevice *dev)
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 2adb0300f4..fa24877955 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -19,6 +19,7 @@
*/
#include "hw/pci/pcie_port.h"
+#include "hw/hotplug.h"
void pcie_port_init_reg(PCIDevice *d)
{
@@ -149,8 +150,11 @@ static Property pcie_slot_props[] = {
static void pcie_slot_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
dc->props = pcie_slot_props;
+ hc->plug = pcie_cap_slot_hotplug_cb;
+ hc->unplug = pcie_cap_slot_hot_unplug_cb;
}
static const TypeInfo pcie_slot_type_info = {
@@ -159,6 +163,10 @@ static const TypeInfo pcie_slot_type_info = {
.instance_size = sizeof(PCIESlot),
.abstract = true,
.class_init = pcie_slot_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ }
};
static void pcie_port_register_types(void)
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 576244b9f6..180faa7adb 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -7,6 +7,7 @@
#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci/msi.h"
+#include "qapi/qmp/qerror.h"
/* TODO: model power only and disabled slot states. */
/* TODO: handle SERR and wakeups */
@@ -490,65 +491,93 @@ static const MemoryRegionOps shpc_mmio_ops = {
.max_access_size = 4,
},
};
-
-static int shpc_device_hotplug(DeviceState *qdev, PCIDevice *affected_dev,
- PCIHotplugState hotplug_state)
+static void shpc_device_hotplug_common(PCIDevice *affected_dev, int *slot,
+ SHPCDevice *shpc, Error **errp)
{
int pci_slot = PCI_SLOT(affected_dev->devfn);
- uint8_t state;
- uint8_t led;
- PCIDevice *d = DO_UPCAST(PCIDevice, qdev, qdev);
- SHPCDevice *shpc = d->shpc;
- int slot = SHPC_PCI_TO_IDX(pci_slot);
- if (pci_slot < SHPC_IDX_TO_PCI(0) || slot >= shpc->nslots) {
- error_report("Unsupported PCI slot %d for standard hotplug "
- "controller. Valid slots are between %d and %d.",
- pci_slot, SHPC_IDX_TO_PCI(0),
- SHPC_IDX_TO_PCI(shpc->nslots) - 1);
- return -1;
+ *slot = SHPC_PCI_TO_IDX(pci_slot);
+
+ if (pci_slot < SHPC_IDX_TO_PCI(0) || *slot >= shpc->nslots) {
+ error_setg(errp, "Unsupported PCI slot %d for standard hotplug "
+ "controller. Valid slots are between %d and %d.",
+ pci_slot, SHPC_IDX_TO_PCI(0),
+ SHPC_IDX_TO_PCI(shpc->nslots) - 1);
+ return;
+ }
+}
+
+void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ Error *local_err = NULL;
+ PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
+ SHPCDevice *shpc = pci_hotplug_dev->shpc;
+ int slot;
+
+ shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
}
+
/* Don't send event when device is enabled during qemu machine creation:
* it is present on boot, no hotplug event is necessary. We do send an
* event when the device is disabled later. */
- if (hotplug_state == PCI_COLDPLUG_ENABLED) {
+ if (!dev->hotplugged) {
shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
SHPC_SLOT_STATUS_PRSNT_MASK);
- return 0;
+ return;
}
- if (hotplug_state == PCI_HOTPLUG_DISABLED) {
- shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON;
- state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
- led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
- if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) {
- shpc_free_devices_in_slot(shpc, slot);
- shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
- shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
- SHPC_SLOT_STATUS_PRSNT_MASK);
- shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
- SHPC_SLOT_EVENT_MRL |
- SHPC_SLOT_EVENT_PRESENCE;
- }
+
+ /* This could be a cancellation of the previous removal.
+ * We check MRL state to figure out. */
+ if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) {
+ shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
+ shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
+ SHPC_SLOT_STATUS_PRSNT_MASK);
+ shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+ SHPC_SLOT_EVENT_BUTTON |
+ SHPC_SLOT_EVENT_MRL |
+ SHPC_SLOT_EVENT_PRESENCE;
} else {
- /* This could be a cancellation of the previous removal.
- * We check MRL state to figure out. */
- if (shpc_get_status(shpc, slot, SHPC_SLOT_STATUS_MRL_OPEN)) {
- shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_MRL_OPEN);
- shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_7_5W,
- SHPC_SLOT_STATUS_PRSNT_MASK);
- shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
- SHPC_SLOT_EVENT_BUTTON |
- SHPC_SLOT_EVENT_MRL |
- SHPC_SLOT_EVENT_PRESENCE;
- } else {
- /* Press attention button to cancel removal */
- shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
- SHPC_SLOT_EVENT_BUTTON;
- }
+ /* Press attention button to cancel removal */
+ shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+ SHPC_SLOT_EVENT_BUTTON;
}
shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66);
- shpc_interrupt_update(d);
- return 0;
+ shpc_interrupt_update(pci_hotplug_dev);
+}
+
+void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
+{
+ Error *local_err = NULL;
+ PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);
+ SHPCDevice *shpc = pci_hotplug_dev->shpc;
+ uint8_t state;
+ uint8_t led;
+ int slot;
+
+ shpc_device_hotplug_common(PCI_DEVICE(dev), &slot, shpc, errp);
+ if (local_err) {
+ return;
+ }
+
+ shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |= SHPC_SLOT_EVENT_BUTTON;
+ state = shpc_get_status(shpc, slot, SHPC_SLOT_STATE_MASK);
+ led = shpc_get_status(shpc, slot, SHPC_SLOT_PWR_LED_MASK);
+ if (state == SHPC_STATE_DISABLED && led == SHPC_LED_OFF) {
+ shpc_free_devices_in_slot(shpc, slot);
+ shpc_set_status(shpc, slot, 1, SHPC_SLOT_STATUS_MRL_OPEN);
+ shpc_set_status(shpc, slot, SHPC_SLOT_STATUS_PRSNT_EMPTY,
+ SHPC_SLOT_STATUS_PRSNT_MASK);
+ shpc->config[SHPC_SLOT_EVENT_LATCH(slot)] |=
+ SHPC_SLOT_EVENT_MRL |
+ SHPC_SLOT_EVENT_PRESENCE;
+ }
+ shpc_set_status(shpc, slot, 0, SHPC_SLOT_STATUS_66);
+ shpc_interrupt_update(pci_hotplug_dev);
}
/* Initialize the SHPC structure in bridge's BAR. */
@@ -616,7 +645,8 @@ int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned offset)
d, "shpc-mmio", SHPC_SIZEOF(d));
shpc_cap_update_dword(d);
memory_region_add_subregion(bar, offset, &shpc->mmio);
- pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev);
+
+ qbus_set_hotplug_handler(BUS(sec_bus), DEVICE(d), NULL);
d->cap_present |= QEMU_PCI_CAP_SHPC;
return 0;
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 027a6fa369..843e697bfe 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -26,7 +26,6 @@
#include "sysemu/blockdev.h"
#include "sysemu/dma.h"
#include "qemu/timer.h"
-#include "block/block_int.h"
#include "qemu/bitops.h"
#include "sdhci.h"
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index c583c3d0c5..c16e9e4c81 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -45,6 +45,7 @@
typedef struct ResetData {
SPARCCPU *cpu;
uint32_t entry; /* save kernel entry in case of reset */
+ target_ulong sp; /* initial stack pointer */
} ResetData;
static void main_cpu_reset(void *opaque)
@@ -58,6 +59,7 @@ static void main_cpu_reset(void *opaque)
cpu->halted = 0;
env->pc = s->entry;
env->npc = s->entry + 4;
+ env->regbase[6] = s->sp;
}
void leon3_irq_ack(void *irq_manager, int intno)
@@ -133,6 +135,7 @@ static void leon3_generic_hw_init(QEMUMachineInitArgs *args)
/* Reset data */
reset_info = g_malloc0(sizeof(ResetData));
reset_info->cpu = cpu;
+ reset_info->sp = 0x40000000 + ram_size;
qemu_register_reset(main_cpu_reset, reset_info);
/* Allocate IRQ manager */
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 4c532b7d6a..f0c253647e 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1391,7 +1391,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
qemu_opt_set(opts, "model", "usb");
idx = net_client_init(opts, 0, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return NULL;
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 0c985942f9..484a9bd059 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -123,7 +123,7 @@ static void ehci_class_init(ObjectClass *klass, void *data)
k->init = usb_ehci_pci_initfn;
k->class_id = PCI_CLASS_SERIAL_USB;
k->config_write = usb_ehci_pci_write_config;
- k->no_hotplug = 1;
+ dc->hotpluggable = false;
dc->vmsd = &vmstate_ehci_pci;
dc->props = ehci_pci_properties;
}
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index e38cdebfec..3d35058b14 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1993,10 +1993,10 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data)
k->vendor_id = PCI_VENDOR_ID_APPLE;
k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
k->class_id = PCI_CLASS_SERIAL_USB;
- k->no_hotplug = 1;
set_bit(DEVICE_CATEGORY_USB, dc->categories);
dc->desc = "Apple USB Controller";
dc->props = ohci_pci_properties;
+ dc->hotpluggable = false;
}
static const TypeInfo ohci_pci_info = {
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 238d1d2b5f..ad814b58d4 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1318,7 +1318,7 @@ static void uhci_class_init(ObjectClass *klass, void *data)
k->device_id = info->device_id;
k->revision = info->revision;
k->class_id = PCI_CLASS_SERIAL_USB;
- k->no_hotplug = 1;
+ dc->hotpluggable = false;
dc->vmsd = &vmstate_uhci;
dc->props = uhci_properties;
set_bit(DEVICE_CATEGORY_USB, dc->categories);
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index bafe08590b..0fa814ee09 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3798,6 +3798,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_xhci;
dc->props = xhci_properties;
dc->reset = xhci_reset;
+ dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_USB, dc->categories);
k->init = usb_xhci_initfn;
k->vendor_id = PCI_VENDOR_ID_NEC;
@@ -3805,7 +3806,6 @@ static void xhci_class_init(ObjectClass *klass, void *data)
k->class_id = PCI_CLASS_SERIAL_USB;
k->revision = 0x03;
k->is_express = 1;
- k->no_hotplug = 1;
}
static const TypeInfo xhci_info = {
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 3e53297a99..a9fae9d5c5 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -24,6 +24,7 @@
#include "qemu/notify.h"
#include "qemu/option.h"
#include "exec/memory.h"
+#include "hw/irq.h"
/* from linux include/acpi/actype.h */
/* Default ACPI register widths */
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index 6230e60954..9323838319 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -29,31 +29,34 @@
#include <inttypes.h>
#include <qemu/typedefs.h>
-#include "hw/pci/pci.h" /* for PCIHotplugState */
+#include "hw/acpi/acpi.h"
+#include "migration/vmstate.h"
typedef struct AcpiPciHpPciStatus {
- uint32_t up; /* deprecated, maintained for migration compatibility */
+ uint32_t up;
uint32_t down;
uint32_t hotplug_enable;
- uint32_t device_present;
} AcpiPciHpPciStatus;
#define ACPI_PCIHP_PROP_BSEL "acpi-pcihp-bsel"
#define ACPI_PCIHP_MAX_HOTPLUG_BUS 256
+#define ACPI_PCIHP_BSEL_DEFAULT 0x0
typedef struct AcpiPciHpState {
AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS];
uint32_t hotplug_select;
PCIBus *root;
MemoryRegion io;
+ bool legacy_piix;
} AcpiPciHpState;
void acpi_pcihp_init(AcpiPciHpState *, PCIBus *root,
- MemoryRegion *address_space_io);
+ MemoryRegion *address_space_io, bool bridges_enabled);
-/* Invoke on device hotplug */
-int acpi_pcihp_device_hotplug(AcpiPciHpState *, PCIDevice *,
- PCIHotplugState state);
+void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+ DeviceState *dev, Error **errp);
+void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+ DeviceState *dev, Error **errp);
/* Called on reset */
void acpi_pcihp_reset(AcpiPciHpState *s);
diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h
new file mode 100644
index 0000000000..a6533cb0b1
--- /dev/null
+++ b/include/hw/hotplug.h
@@ -0,0 +1,78 @@
+/*
+ * Hotplug handler interface.
+ *
+ * Copyright (c) 2014 Red Hat Inc.
+ *
+ * Authors:
+ * Igor Mammedov <imammedo@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef HOTPLUG_H
+#define HOTPLUG_H
+
+#include "qom/object.h"
+#include "qemu/typedefs.h"
+
+#define TYPE_HOTPLUG_HANDLER "hotplug-handler"
+
+#define HOTPLUG_HANDLER_CLASS(klass) \
+ OBJECT_CLASS_CHECK(HotplugHandlerClass, (klass), TYPE_HOTPLUG_HANDLER)
+#define HOTPLUG_HANDLER_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(HotplugHandlerClass, (obj), TYPE_HOTPLUG_HANDLER)
+#define HOTPLUG_HANDLER(obj) \
+ INTERFACE_CHECK(HotplugHandler, (obj), TYPE_HOTPLUG_HANDLER)
+
+
+typedef struct HotplugHandler {
+ /* <private> */
+ Object Parent;
+} HotplugHandler;
+
+/**
+ * hotplug_fn:
+ * @plug_handler: a device performing plug/uplug action
+ * @plugged_dev: a device that has been (un)plugged
+ * @errp: returns an error if this function fails
+ */
+typedef void (*hotplug_fn)(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev, Error **errp);
+
+/**
+ * HotplugDeviceClass:
+ *
+ * Interface to be implemented by a device performing
+ * hardware (un)plug functions.
+ *
+ * @parent: Opaque parent interface.
+ * @plug: plug callback.
+ * @unplug: unplug callback.
+ */
+typedef struct HotplugHandlerClass {
+ /* <private> */
+ InterfaceClass parent;
+
+ /* <public> */
+ hotplug_fn plug;
+ hotplug_fn unplug;
+} HotplugHandlerClass;
+
+/**
+ * hotplug_handler_plug:
+ *
+ * Call #HotplugHandlerClass.plug callback of @plug_handler.
+ */
+void hotplug_handler_plug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp);
+
+/**
+ * hotplug_handler_unplug:
+ *
+ * Call #HotplugHandlerClass.unplug callback of @plug_handler.
+ */
+void hotplug_handler_unplug(HotplugHandler *plug_handler,
+ DeviceState *plugged_dev,
+ Error **errp);
+#endif
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 7a23d6bdc1..91b01224a3 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -4,6 +4,13 @@
#include "hw/nvram/fw_cfg.h"
/* loader.c */
+/**
+ * get_image_size: retrieve size of an image file
+ * @filename: Path to the image file
+ *
+ * Returns the size of the image file on success, -1 otherwise.
+ * On error, errno is also set as appropriate.
+ */
int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
int load_image_targphys(const char *filename, hwaddr,
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 52523467b6..693dd6b658 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -201,9 +201,6 @@ typedef struct PCIDeviceClass {
/* pcie stuff */
int is_express; /* is this device pci express? */
- /* device isn't hot-pluggable */
- int no_hotplug;
-
/* rom bar */
const char *romfile;
} PCIDeviceClass;
@@ -330,15 +327,6 @@ typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
-typedef enum {
- PCI_HOTPLUG_DISABLED,
- PCI_HOTPLUG_ENABLED,
- PCI_COLDPLUG_ENABLED,
-} PCIHotplugState;
-
-typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
- PCIHotplugState state);
-
#define TYPE_PCI_BUS "PCI"
#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
#define TYPE_PCIE_BUS "PCIE"
@@ -357,7 +345,6 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name,
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int nirq);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
-void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h
index 9df17885ec..fabaeee86b 100644
--- a/include/hw/pci/pci_bus.h
+++ b/include/hw/pci/pci_bus.h
@@ -16,8 +16,6 @@ struct PCIBus {
pci_set_irq_fn set_irq;
pci_map_irq_fn map_irq;
pci_route_irq_fn route_intx_to_irq;
- pci_hotplug_fn hotplug;
- DeviceState *hotplug_qdev;
void *irq_opaque;
PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
PCIDevice *parent_dev;
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 1966169553..b0bf7e3ce1 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -25,6 +25,7 @@
#include "hw/pci/pci_regs.h"
#include "hw/pci/pcie_regs.h"
#include "hw/pci/pcie_aer.h"
+#include "hw/hotplug.h"
typedef enum {
/* for attention and power indicator */
@@ -122,4 +123,8 @@ extern const VMStateDescription vmstate_pcie_device;
.offset = vmstate_offset_value(_state, _field, PCIDevice), \
}
+void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
#endif /* QEMU_PCIE_H */
diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h
index 467911a558..eef1a1ad6e 100644
--- a/include/hw/pci/shpc.h
+++ b/include/hw/pci/shpc.h
@@ -4,6 +4,8 @@
#include "qemu-common.h"
#include "exec/memory.h"
#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "hw/hotplug.h"
struct SHPCDevice {
/* Capability offset in device's config space */
@@ -41,6 +43,12 @@ int shpc_init(PCIDevice *dev, PCIBus *sec_bus, MemoryRegion *bar, unsigned off);
void shpc_cleanup(PCIDevice *dev, MemoryRegion *bar);
void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);
+
+void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+
extern VMStateInfo shpc_vmstate_info;
#define SHPC_VMSTATE(_field, _type) \
VMSTATE_BUFFER_UNSAFE_INFO(_field, _type, 0, shpc_vmstate_info, 0)
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index d0cda38686..276b336c09 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -8,6 +8,7 @@
#include "qom/object.h"
#include "hw/irq.h"
#include "qapi/error.h"
+#include "hw/hotplug.h"
enum {
DEV_NVECTORS_UNSPECIFIED = -1,
@@ -49,6 +50,8 @@ struct VMStateDescription;
* is changed to %true. Deprecated, new types inheriting directly from
* TYPE_DEVICE should use @realize instead, new leaf types should consult
* their respective parent type.
+ * @hotpluggable: indicates if #DeviceClass is hotpluggable, available
+ * as readonly "hotpluggable" property of #DeviceState instance
*
* # Realization #
* Devices are constructed in two stages,
@@ -109,6 +112,7 @@ typedef struct DeviceClass {
* TODO remove once we're there
*/
bool cannot_instantiate_with_device_add_yet;
+ bool hotpluggable;
/* callbacks */
void (*reset)(DeviceState *dev);
@@ -180,14 +184,18 @@ typedef struct BusChild {
QTAILQ_ENTRY(BusChild) sibling;
} BusChild;
+#define QDEV_HOTPLUG_HANDLER_PROPERTY "hotplug-handler"
+
/**
* BusState:
+ * @hotplug_device: link to a hotplug device associated with bus.
*/
struct BusState {
Object obj;
DeviceState *parent;
const char *name;
int allow_hotplug;
+ HotplugHandler *hotplug_handler;
int max_index;
QTAILQ_HEAD(ChildrenHead, BusChild) children;
QLIST_ENTRY(BusState) sibling;
@@ -320,4 +328,11 @@ extern int qdev_hotplug;
char *qdev_get_dev_path(DeviceState *dev);
+static inline void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler,
+ Error **errp)
+{
+ object_property_set_link(OBJECT(bus), OBJECT(handler),
+ QDEV_HOTPLUG_HANDLER_PROPERTY, errp);
+ bus->allow_hotplug = 1;
+}
#endif
diff --git a/include/net/checksum.h b/include/net/checksum.h
index 80203fb6e0..2d7a363d40 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -19,6 +19,7 @@
#define QEMU_NET_CHECKSUM_H
#include <stdint.h>
+struct iovec;
uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq);
uint16_t net_checksum_finish(uint32_t sum);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bc0ac98d4f..f3700876a3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2177,271 +2177,81 @@ fail:
/* do_socketcall() Must return target values and target errnos. */
static abi_long do_socketcall(int num, abi_ulong vptr)
{
- abi_long ret;
- const int n = sizeof(abi_ulong);
-
- switch(num) {
- case SOCKOP_socket:
- {
- abi_ulong domain, type, protocol;
-
- if (get_user_ual(domain, vptr)
- || get_user_ual(type, vptr + n)
- || get_user_ual(protocol, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_socket(domain, type, protocol);
- }
- break;
- case SOCKOP_bind:
- {
- abi_ulong sockfd;
- abi_ulong target_addr;
- socklen_t addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_bind(sockfd, target_addr, addrlen);
- }
- break;
- case SOCKOP_connect:
- {
- abi_ulong sockfd;
- abi_ulong target_addr;
- socklen_t addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_connect(sockfd, target_addr, addrlen);
- }
- break;
- case SOCKOP_listen:
- {
- abi_ulong sockfd, backlog;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(backlog, vptr + n))
- return -TARGET_EFAULT;
-
- ret = get_errno(listen(sockfd, backlog));
- }
- break;
- case SOCKOP_accept:
- {
- abi_ulong sockfd;
- abi_ulong target_addr, target_addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(target_addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_accept4(sockfd, target_addr, target_addrlen, 0);
- }
- break;
- case SOCKOP_accept4:
- {
- abi_ulong sockfd;
- abi_ulong target_addr, target_addrlen;
- abi_ulong flags;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(target_addrlen, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n)) {
+ static const unsigned ac[] = { /* number of arguments per call */
+ [SOCKOP_socket] = 3, /* domain, type, protocol */
+ [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_listen] = 2, /* sockfd, backlog */
+ [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */
+ [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */
+ [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */
+ [SOCKOP_send] = 4, /* sockfd, msg, len, flags */
+ [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */
+ [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */
+ [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */
+ [SOCKOP_shutdown] = 2, /* sockfd, how */
+ [SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */
+ [SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */
+ [SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */
+ [SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */
+ };
+ abi_long a[6]; /* max 6 args */
+
+ /* first, collect the arguments in a[] according to ac[] */
+ if (num >= 0 && num < ARRAY_SIZE(ac)) {
+ unsigned i;
+ assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */
+ for (i = 0; i < ac[num]; ++i) {
+ if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
return -TARGET_EFAULT;
}
-
- ret = do_accept4(sockfd, target_addr, target_addrlen, flags);
- }
- break;
- case SOCKOP_getsockname:
- {
- abi_ulong sockfd;
- abi_ulong target_addr, target_addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(target_addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_getsockname(sockfd, target_addr, target_addrlen);
}
- break;
- case SOCKOP_getpeername:
- {
- abi_ulong sockfd;
- abi_ulong target_addr, target_addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(target_addr, vptr + n)
- || get_user_ual(target_addrlen, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_getpeername(sockfd, target_addr, target_addrlen);
- }
- break;
- case SOCKOP_socketpair:
- {
- abi_ulong domain, type, protocol;
- abi_ulong tab;
-
- if (get_user_ual(domain, vptr)
- || get_user_ual(type, vptr + n)
- || get_user_ual(protocol, vptr + 2 * n)
- || get_user_ual(tab, vptr + 3 * n))
- return -TARGET_EFAULT;
-
- ret = do_socketpair(domain, type, protocol, tab);
- }
- break;
- case SOCKOP_send:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n))
- return -TARGET_EFAULT;
-
- ret = do_sendto(sockfd, msg, len, flags, 0, 0);
- }
- break;
- case SOCKOP_recv:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n))
- return -TARGET_EFAULT;
-
- ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
- }
- break;
- case SOCKOP_sendto:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
- abi_ulong addr;
- abi_ulong addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n)
- || get_user_ual(addr, vptr + 4 * n)
- || get_user_ual(addrlen, vptr + 5 * n))
- return -TARGET_EFAULT;
-
- ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
- }
- break;
- case SOCKOP_recvfrom:
- {
- abi_ulong sockfd;
- abi_ulong msg;
- size_t len;
- abi_ulong flags;
- abi_ulong addr;
- socklen_t addrlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(msg, vptr + n)
- || get_user_ual(len, vptr + 2 * n)
- || get_user_ual(flags, vptr + 3 * n)
- || get_user_ual(addr, vptr + 4 * n)
- || get_user_ual(addrlen, vptr + 5 * n))
- return -TARGET_EFAULT;
-
- ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
- }
- break;
- case SOCKOP_shutdown:
- {
- abi_ulong sockfd, how;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(how, vptr + n))
- return -TARGET_EFAULT;
-
- ret = get_errno(shutdown(sockfd, how));
- }
- break;
- case SOCKOP_sendmsg:
- case SOCKOP_recvmsg:
- {
- abi_ulong fd;
- abi_ulong target_msg;
- abi_ulong flags;
-
- if (get_user_ual(fd, vptr)
- || get_user_ual(target_msg, vptr + n)
- || get_user_ual(flags, vptr + 2 * n))
- return -TARGET_EFAULT;
-
- ret = do_sendrecvmsg(fd, target_msg, flags,
- (num == SOCKOP_sendmsg));
- }
- break;
- case SOCKOP_setsockopt:
- {
- abi_ulong sockfd;
- abi_ulong level;
- abi_ulong optname;
- abi_ulong optval;
- abi_ulong optlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(level, vptr + n)
- || get_user_ual(optname, vptr + 2 * n)
- || get_user_ual(optval, vptr + 3 * n)
- || get_user_ual(optlen, vptr + 4 * n))
- return -TARGET_EFAULT;
-
- ret = do_setsockopt(sockfd, level, optname, optval, optlen);
- }
- break;
- case SOCKOP_getsockopt:
- {
- abi_ulong sockfd;
- abi_ulong level;
- abi_ulong optname;
- abi_ulong optval;
- socklen_t optlen;
-
- if (get_user_ual(sockfd, vptr)
- || get_user_ual(level, vptr + n)
- || get_user_ual(optname, vptr + 2 * n)
- || get_user_ual(optval, vptr + 3 * n)
- || get_user_ual(optlen, vptr + 4 * n))
- return -TARGET_EFAULT;
+ }
- ret = do_getsockopt(sockfd, level, optname, optval, optlen);
- }
- break;
+ /* now when we have the args, actually handle the call */
+ switch (num) {
+ case SOCKOP_socket: /* domain, type, protocol */
+ return do_socket(a[0], a[1], a[2]);
+ case SOCKOP_bind: /* sockfd, addr, addrlen */
+ return do_bind(a[0], a[1], a[2]);
+ case SOCKOP_connect: /* sockfd, addr, addrlen */
+ return do_connect(a[0], a[1], a[2]);
+ case SOCKOP_listen: /* sockfd, backlog */
+ return get_errno(listen(a[0], a[1]));
+ case SOCKOP_accept: /* sockfd, addr, addrlen */
+ return do_accept4(a[0], a[1], a[2], 0);
+ case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */
+ return do_accept4(a[0], a[1], a[2], a[3]);
+ case SOCKOP_getsockname: /* sockfd, addr, addrlen */
+ return do_getsockname(a[0], a[1], a[2]);
+ case SOCKOP_getpeername: /* sockfd, addr, addrlen */
+ return do_getpeername(a[0], a[1], a[2]);
+ case SOCKOP_socketpair: /* domain, type, protocol, tab */
+ return do_socketpair(a[0], a[1], a[2], a[3]);
+ case SOCKOP_send: /* sockfd, msg, len, flags */
+ return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
+ case SOCKOP_recv: /* sockfd, msg, len, flags */
+ return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
+ case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */
+ return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
+ case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */
+ return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
+ case SOCKOP_shutdown: /* sockfd, how */
+ return get_errno(shutdown(a[0], a[1]));
+ case SOCKOP_sendmsg: /* sockfd, msg, flags */
+ return do_sendrecvmsg(a[0], a[1], a[2], 1);
+ case SOCKOP_recvmsg: /* sockfd, msg, flags */
+ return do_sendrecvmsg(a[0], a[1], a[2], 0);
+ case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */
+ return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
+ case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */
+ return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
default:
gemu_log("Unsupported socketcall: %d\n", num);
- ret = -TARGET_ENOSYS;
- break;
+ return -TARGET_ENOSYS;
}
- return ret;
}
#endif
diff --git a/monitor.c b/monitor.c
index 690c152d0b..de90fba41e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -56,6 +56,7 @@
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/json-streamer.h"
#include "qapi/qmp/json-parser.h"
+#include <qom/object_interfaces.h>
#include "qemu/osdep.h"
#include "cpu.h"
#include "trace.h"
@@ -4254,6 +4255,87 @@ static const char *next_arg_type(const char *typestr)
return (p != NULL ? ++p : typestr);
}
+static void device_add_completion(ReadLineState *rs, const char *str)
+{
+ GSList *list, *elt;
+ size_t len;
+
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ list = elt = object_class_get_list(TYPE_DEVICE, false);
+ while (elt) {
+ const char *name;
+ DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
+ TYPE_DEVICE);
+ name = object_class_get_name(OBJECT_CLASS(dc));
+ if (!strncmp(name, str, len)) {
+ readline_add_completion(rs, name);
+ }
+ elt = elt->next;
+ }
+ g_slist_free(list);
+}
+
+static void object_add_completion(ReadLineState *rs, const char *str)
+{
+ GSList *list, *elt;
+ size_t len;
+
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ list = elt = object_class_get_list(TYPE_USER_CREATABLE, false);
+ while (elt) {
+ const char *name;
+
+ name = object_class_get_name(OBJECT_CLASS(elt->data));
+ if (!strncmp(name, str, len) && strcmp(name, TYPE_USER_CREATABLE)) {
+ readline_add_completion(rs, name);
+ }
+ elt = elt->next;
+ }
+ g_slist_free(list);
+}
+
+static void device_del_completion(ReadLineState *rs, BusState *bus,
+ const char *str, size_t len)
+{
+ BusChild *kid;
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+ BusState *dev_child;
+
+ if (dev->id && !strncmp(str, dev->id, len)) {
+ readline_add_completion(rs, dev->id);
+ }
+
+ QLIST_FOREACH(dev_child, &dev->child_bus, sibling) {
+ device_del_completion(rs, dev_child, str, len);
+ }
+ }
+}
+
+static void object_del_completion(ReadLineState *rs, const char *str)
+{
+ ObjectPropertyInfoList *list, *start;
+ size_t len;
+
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+
+ start = list = qmp_qom_list("/objects", NULL);
+ while (list) {
+ ObjectPropertyInfo *info = list->value;
+
+ if (!strncmp(info->type, "child<", 5)
+ && !strncmp(info->name, str, len)) {
+ readline_add_completion(rs, info->name);
+ }
+ list = list->next;
+ }
+ qapi_free_ObjectPropertyInfoList(start);
+}
+
static void monitor_find_completion_by_table(Monitor *mon,
const mon_cmd_t *cmd_table,
char **args,
@@ -4317,6 +4399,13 @@ 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")) {
@@ -4330,6 +4419,12 @@ 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/net/net.c b/net/net.c
index 2c3af202a6..41b38830ea 100644
--- a/net/net.c
+++ b/net/net.c
@@ -882,7 +882,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
qemu_opt_set(opts, "type", device);
net_client_init(opts, 0, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
monitor_printf(mon, "adding host network device %s failed\n", device);
@@ -918,17 +918,17 @@ int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
QemuOpts *opts;
opts_list = qemu_find_opts_err("netdev", &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
goto exit_err;
}
opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
goto exit_err;
}
netdev_add(opts, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qemu_opts_del(opts);
goto exit_err;
}
@@ -1152,7 +1152,7 @@ static int net_init_client(QemuOpts *opts, void *dummy)
Error *local_err = NULL;
net_client_init(opts, 0, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
@@ -1167,7 +1167,7 @@ static int net_init_netdev(QemuOpts *opts, void *dummy)
int ret;
ret = net_client_init(opts, 1, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index 57d8bd0d6c..ce4852a4d5 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -12,6 +12,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/optionrom)
CFLAGS := -Wall -Wstrict-prototypes -Werror -fomit-frame-pointer -fno-builtin
CFLAGS += -I$(SRC_PATH)
CFLAGS += $(call cc-option, $(CFLAGS), -fno-stack-protector)
+CFLAGS += $(CFLAGS_NOPIE)
QEMU_CFLAGS = $(CFLAGS)
build-all: multiboot.bin linuxboot.bin kvmvapic.bin
@@ -20,7 +21,7 @@ build-all: multiboot.bin linuxboot.bin kvmvapic.bin
.SECONDARY:
%.img: %.o
- $(call quiet-command,$(LD) -Ttext 0 -e _start -s -o $@ $<," Building $(TARGET_DIR)$@")
+ $(call quiet-command,$(LD) $(LDFLAGS_NOPIE) -Ttext 0 -e _start -s -o $@ $<," Building $(TARGET_DIR)$@")
%.raw: %.img
$(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@," Building $(TARGET_DIR)$@")
diff --git a/qapi-schema.json b/qapi-schema.json
index 2d64ce67d9..473c096fa9 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -495,6 +495,28 @@
{ 'command': 'query-chardev', 'returns': ['ChardevInfo'] }
##
+# @ChardevBackendInfo:
+#
+# Information about a character device backend
+#
+# @name: The backend name
+#
+# Since: 2.0
+##
+{ 'type': 'ChardevBackendInfo', 'data': {'name': 'str'} }
+
+##
+# @query-chardev-backends:
+#
+# Returns information about character device backends.
+#
+# Returns: a list of @ChardevBackendInfo
+#
+# Since: 2.0
+##
+{ 'command': 'query-chardev-backends', 'returns': ['ChardevBackendInfo'] }
+
+##
# @DataFormat:
#
# An enumeration of data format.
diff --git a/qdev-monitor.c b/qdev-monitor.c
index b37778f0f3..3a7dc0d428 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -656,7 +656,7 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
DeviceState *dev;
opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
diff --git a/qemu-char.c b/qemu-char.c
index 30c5a6afd0..4d50838b3b 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2725,7 +2725,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet,
is_waitconnect, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
goto fail;
}
return chr;
@@ -2938,7 +2938,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
Error *local_err = NULL;
opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return NULL;
@@ -3323,7 +3323,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*in
return NULL;
chr = qemu_chr_new_from_opts(opts, init, &err);
- if (error_is_set(&err)) {
+ if (err) {
error_report("%s", error_get_pretty(err));
error_free(err);
}
@@ -3432,6 +3432,25 @@ ChardevInfoList *qmp_query_chardev(Error **errp)
return chr_list;
}
+ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)
+{
+ ChardevBackendInfoList *backend_list = NULL;
+ CharDriver *c = NULL;
+ GSList *i = NULL;
+
+ for (i = backends; i; i = i->next) {
+ ChardevBackendInfoList *info = g_malloc0(sizeof(*info));
+ c = i->data;
+ info->value = g_malloc0(sizeof(*info->value));
+ info->value->name = g_strdup(c->name);
+
+ info->next = backend_list;
+ backend_list = info;
+ }
+
+ return backend_list;
+}
+
CharDriverState *qemu_chr_find(const char *name)
{
CharDriverState *chr;
diff --git a/qemu-img.c b/qemu-img.c
index c989850ce7..0927b090de 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -419,7 +419,7 @@ static int img_create(int argc, char **argv)
bdrv_img_create(filename, fmt, base_filename, base_fmt,
options, img_size, BDRV_O_FLAGS, &local_err, quiet);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_report("%s: %s", filename, error_get_pretty(local_err));
error_free(local_err);
return 1;
@@ -1289,7 +1289,7 @@ static int img_convert(int argc, char **argv)
bdrv_snapshot_load_tmp_by_id_or_name(bs[0], snapshot_name, &local_err);
}
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_report("Failed to load snapshot: %s",
error_get_pretty(local_err));
error_free(local_err);
@@ -1775,7 +1775,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
}
bdrv_query_image_info(bs, &info, &err);
- if (error_is_set(&err)) {
+ if (err) {
error_report("%s", error_get_pretty(err));
error_free(err);
goto err;
@@ -2184,7 +2184,7 @@ static int img_snapshot(int argc, char **argv)
case SNAPSHOT_DELETE:
bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err);
- if (error_is_set(&err)) {
+ if (err) {
error_report("Could not delete snapshot '%s': (%s)",
snapshot_name, error_get_pretty(err));
error_free(err);
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 8100bee67e..cae41716ca 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -108,7 +108,7 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
}
ga_wait_child(pid, &status, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
return;
}
@@ -181,7 +181,7 @@ void qmp_guest_set_time(int64_t time_ns, Error **errp)
}
ga_wait_child(pid, &status, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
@@ -669,7 +669,7 @@ static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err)
}
ga_wait_child(pid, &status, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
return;
}
@@ -713,14 +713,14 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err)
slog("guest-fsfreeze called");
execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
return -1;
}
QTAILQ_INIT(&mounts);
build_fs_mount_list(&mounts, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
return -1;
}
@@ -780,7 +780,7 @@ int64_t qmp_guest_fsfreeze_thaw(Error **err)
QTAILQ_INIT(&mounts);
build_fs_mount_list(&mounts, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
return 0;
}
@@ -861,7 +861,7 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
QTAILQ_INIT(&mounts);
build_fs_mount_list(&mounts, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
return;
}
@@ -957,7 +957,7 @@ static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
}
ga_wait_child(pid, &status, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
goto out;
}
@@ -1034,7 +1034,7 @@ static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
}
ga_wait_child(pid, &status, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(err, local_err);
goto out;
}
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index a6a0af264b..50094ddfd3 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -197,7 +197,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err)
error:
qmp_guest_fsfreeze_thaw(&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
g_debug("cleanup thaw: %s", error_get_pretty(local_err));
error_free(local_err);
}
diff --git a/qmp-commands.hx b/qmp-commands.hx
index cce6b81da4..8a0e8320c6 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1924,6 +1924,47 @@ EQMP
},
SQMP
+query-chardev-backends
+-------------
+
+List available character device backends.
+
+Each backend is represented by a json-object, the returned value is a json-array
+of all backends.
+
+Each json-object contains:
+
+- "name": backend name (json-string)
+
+Example:
+
+-> { "execute": "query-chardev-backends" }
+<- {
+ "return":[
+ {
+ "name":"udp"
+ },
+ {
+ "name":"tcp"
+ },
+ {
+ "name":"unix"
+ },
+ {
+ "name":"spiceport"
+ }
+ ]
+ }
+
+EQMP
+
+ {
+ .name = "query-chardev-backends",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_chardev_backends,
+ },
+
+SQMP
query-block
-----------
diff --git a/savevm.c b/savevm.c
index a7dbe18a67..7329fc58de 100644
--- a/savevm.c
+++ b/savevm.c
@@ -880,7 +880,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name)
if (bdrv_can_snapshot(bs) &&
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
- if (error_is_set(&err)) {
+ if (err) {
monitor_printf(mon,
"Error while deleting snapshot on device '%s':"
" %s\n",
@@ -1115,7 +1115,7 @@ void do_delvm(Monitor *mon, const QDict *qdict)
while ((bs1 = bdrv_next(bs1))) {
if (bdrv_can_snapshot(bs1)) {
bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
- if (error_is_set(&err)) {
+ if (err) {
monitor_printf(mon,
"Error while deleting snapshot on device '%s':"
" %s\n",
diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index d6b420f18a..d374b357aa 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -31,6 +31,7 @@
# (QEMU)
import qmp
+import json
import readline
import sys
import pprint
@@ -107,6 +108,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
value = True
elif opt[1] == 'false':
value = False
+ elif opt[1].startswith('{'):
+ value = json.loads(opt[1])
else:
value = opt[1]
qmpcmd['arguments'][opt[0]] = value
diff --git a/scripts/switch-timer-api b/scripts/switch-timer-api
index a369a083d1..b0e230b9f1 100755
--- a/scripts/switch-timer-api
+++ b/scripts/switch-timer-api
@@ -20,7 +20,7 @@ sub Syntax
print STDERR <<STOP;
Usage: $FindBin::Script [options] FILE ...
-Translate each FILE to the new Qemu timer API. If no files
+Translate each FILE to the new QEMU timer API. If no files
are passed, a reasonable guess is taken.
Options:
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 9caf4474b9..60c80617a5 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -73,6 +73,7 @@ struct CPUMIPSFPUContext {
float_status fp_status;
/* fpu implementation/revision register (fir) */
uint32_t fcr0;
+#define FCR0_UFRP 28
#define FCR0_F64 22
#define FCR0_L 21
#define FCR0_W 20
@@ -368,6 +369,18 @@ struct CPUMIPSState {
#define CP0C3_MT 2
#define CP0C3_SM 1
#define CP0C3_TL 0
+ uint32_t CP0_Config4;
+ uint32_t CP0_Config4_rw_bitmask;
+#define CP0C4_M 31
+ uint32_t CP0_Config5;
+ uint32_t CP0_Config5_rw_bitmask;
+#define CP0C5_M 31
+#define CP0C5_K 30
+#define CP0C5_CV 29
+#define CP0C5_EVA 28
+#define CP0C5_MSAEn 27
+#define CP0C5_UFR 2
+#define CP0C5_NFExists 0
int32_t CP0_Config6;
int32_t CP0_Config7;
/* XXX: Maybe make LLAddr per-TC? */
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 1a8b86dea5..8c7921a724 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -134,6 +134,8 @@ DEF_HELPER_2(mtc0_ebase, void, env, tl)
DEF_HELPER_2(mttc0_ebase, void, env, tl)
DEF_HELPER_2(mtc0_config0, void, env, tl)
DEF_HELPER_2(mtc0_config2, void, env, tl)
+DEF_HELPER_2(mtc0_config4, void, env, tl)
+DEF_HELPER_2(mtc0_config5, void, env, tl)
DEF_HELPER_2(mtc0_lladdr, void, env, tl)
DEF_HELPER_3(mtc0_watchlo, void, env, tl, i32)
DEF_HELPER_3(mtc0_watchhi, void, env, tl, i32)
@@ -177,7 +179,7 @@ DEF_HELPER_2(yield, tl, env, tl)
/* CP1 functions */
DEF_HELPER_2(cfc1, tl, env, i32)
-DEF_HELPER_3(ctc1, void, env, tl, i32)
+DEF_HELPER_4(ctc1, void, env, tl, i32, i32)
DEF_HELPER_2(float_cvtd_s, i64, env, i32)
DEF_HELPER_2(float_cvtd_w, i64, env, i32)
diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
index bf094a3bd5..9dfa5168da 100644
--- a/target-mips/mips-defs.h
+++ b/target-mips/mips-defs.h
@@ -29,6 +29,8 @@
#define ISA_MIPS32R2 0x00000040
#define ISA_MIPS64 0x00000080
#define ISA_MIPS64R2 0x00000100
+#define ISA_MIPS32R3 0x00000200
+#define ISA_MIPS32R5 0x00000400
/* MIPS ASEs. */
#define ASE_MIPS16 0x00001000
@@ -64,6 +66,12 @@
#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2)
#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
+/* MIPS Technologies "Release 3" */
+#define CPU_MIPS32R3 (CPU_MIPS32R2 | ISA_MIPS32R3)
+
+/* MIPS Technologies "Release 5" */
+#define CPU_MIPS32R5 (CPU_MIPS32R3 | ISA_MIPS32R5)
+
/* Strictly follow the architecture standard:
- Disallow "special" instruction handling for PMON/SPIM.
Note that we still maintain Count/Compare to match the host clock. */
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 8e3a6d7da6..2ef6633f47 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1489,6 +1489,18 @@ void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
}
+void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1)
+{
+ env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) |
+ (arg1 & env->CP0_Config4_rw_bitmask);
+}
+
+void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
+{
+ env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
+ (arg1 & env->CP0_Config5_rw_bitmask);
+}
+
void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1)
{
target_long mask = env->CP0_LLAddr_rw_bitmask;
@@ -2187,12 +2199,23 @@ static inline void restore_flush_mode(CPUMIPSState *env)
target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
{
- target_ulong arg1;
+ target_ulong arg1 = 0;
switch (reg) {
case 0:
arg1 = (int32_t)env->active_fpu.fcr0;
break;
+ case 1:
+ /* UFR Support - Read Status FR */
+ if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) {
+ if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
+ arg1 = (int32_t)
+ ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ }
+ break;
case 25:
arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
break;
@@ -2210,9 +2233,33 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
return arg1;
}
-void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg)
+void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
{
- switch(reg) {
+ switch (fs) {
+ case 1:
+ /* UFR Alias - Reset Status FR */
+ if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
+ return;
+ }
+ if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
+ env->CP0_Status &= ~(1 << CP0St_FR);
+ compute_hflags(env);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ break;
+ case 4:
+ /* UNFR Alias - Set Status FR */
+ if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
+ return;
+ }
+ if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
+ env->CP0_Status |= (1 << CP0St_FR);
+ compute_hflags(env);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ break;
case 25:
if (arg1 & 0xffffff00)
return;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index ef0a2c36b0..083f6ab283 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -4405,7 +4405,14 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
rn = "Config3";
break;
- /* 4,5 are reserved */
+ case 4:
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
+ rn = "Config4";
+ break;
+ case 5:
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
+ rn = "Config5";
+ break;
/* 6,7 are implementation dependent */
case 6:
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
@@ -4982,7 +4989,17 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
/* ignored, read only */
rn = "Config3";
break;
- /* 4,5 are reserved */
+ case 4:
+ gen_helper_mtc0_config4(cpu_env, arg);
+ rn = "Config4";
+ ctx->bstate = BS_STOP;
+ break;
+ case 5:
+ gen_helper_mtc0_config5(cpu_env, arg);
+ rn = "Config5";
+ /* Stop translation as we may have switched the execution mode */
+ ctx->bstate = BS_STOP;
+ break;
/* 6,7 are implementation dependent */
case 6:
/* ignored */
@@ -6801,7 +6818,12 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
break;
case 3:
/* XXX: For now we support only a single FPU context. */
- gen_helper_0e1i(ctc1, t0, rd);
+ {
+ TCGv_i32 fs_tmp = tcg_const_i32(rd);
+
+ gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
+ tcg_temp_free_i32(fs_tmp);
+ }
break;
/* COP2: Not implemented. */
case 4:
@@ -7237,7 +7259,12 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
break;
case OPC_CTC1:
gen_load_gpr(t0, rt);
- gen_helper_0e1i(ctc1, t0, fs);
+ {
+ TCGv_i32 fs_tmp = tcg_const_i32(fs);
+
+ gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
+ tcg_temp_free_i32(fs_tmp);
+ }
opn = "ctc1";
break;
#if defined(TARGET_MIPS64)
@@ -15916,6 +15943,10 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_Config1 = env->cpu_model->CP0_Config1;
env->CP0_Config2 = env->cpu_model->CP0_Config2;
env->CP0_Config3 = env->cpu_model->CP0_Config3;
+ env->CP0_Config4 = env->cpu_model->CP0_Config4;
+ env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
+ env->CP0_Config5 = env->cpu_model->CP0_Config5;
+ env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
env->CP0_Config6 = env->cpu_model->CP0_Config6;
env->CP0_Config7 = env->cpu_model->CP0_Config7;
env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index c45b1b21b2..29d39e2a39 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -45,6 +45,12 @@
(0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
(0 << CP0C3_SM) | (0 << CP0C3_TL))
+#define MIPS_CONFIG4 \
+((0 << CP0C4_M))
+
+#define MIPS_CONFIG5 \
+((0 << CP0C5_M))
+
/* MMU types, the first four entries have the same layout as the
CP0C0_MT field. */
enum mips_mmu_types {
@@ -64,6 +70,10 @@ struct mips_def_t {
int32_t CP0_Config1;
int32_t CP0_Config2;
int32_t CP0_Config3;
+ int32_t CP0_Config4;
+ int32_t CP0_Config4_rw_bitmask;
+ int32_t CP0_Config5;
+ int32_t CP0_Config5_rw_bitmask;
int32_t CP0_Config6;
int32_t CP0_Config7;
target_ulong CP0_LLAddr_rw_bitmask;
@@ -333,6 +343,39 @@ static const mips_def_t mips_defs[] =
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
.mmu_type = MMU_TYPE_R4000,
},
+ {
+ /* A generic CPU providing MIPS32 Release 5 features.
+ FIXME: Eventually this should be replaced by a real CPU model. */
+ .name = "mips32r5-generic",
+ .CP0_PRid = 0x00019700,
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
+ (MMU_TYPE_R4000 << CP0C0_MT),
+ .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
+ (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
+ (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
+ (1 << CP0C1_CA),
+ .CP0_Config2 = MIPS_CONFIG2,
+ .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_M),
+ .CP0_Config4 = MIPS_CONFIG4 | (1 << CP0C4_M),
+ .CP0_Config4_rw_bitmask = 0,
+ .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR),
+ .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) |
+ (1 << CP0C5_CV) | (0 << CP0C5_EVA) |
+ (1 << CP0C5_MSAEn) | (1 << CP0C5_UFR) |
+ (0 << CP0C5_NFExists),
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
+ .SYNCI_Step = 32,
+ .CCRes = 2,
+ .CP0_Status_rw_bitmask = 0x3778FF1F,
+ .CP1_fcr0 = (1 << FCR0_UFRP) | (1 << FCR0_F64) | (1 << FCR0_L) |
+ (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
+ (0x93 << FCR0_PRID),
+ .SEGBITS = 32,
+ .PABITS = 32,
+ .insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
+ .mmu_type = MMU_TYPE_R4000,
+ },
#if defined(TARGET_MIPS64)
{
.name = "R4000",
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index b381477d29..776cb6eece 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -707,6 +707,8 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
uint32_t L6, K5;
#endif
uint32_t I16, I5, I11, N26, tmp;
+ TCGMemOp mop;
+
op0 = extract32(insn, 26, 6);
op1 = extract32(insn, 24, 2);
ra = extract32(insn, 16, 5);
@@ -838,72 +840,46 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
/*#ifdef TARGET_OPENRISC64
case 0x20: l.ld
LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
- {
- check_ob64s(dc);
- TCGv_i64 t0 = tcg_temp_new_i64();
- tcg_gen_addi_i64(t0, cpu_R[ra], sign_extend(I16, 16));
- tcg_gen_qemu_ld64(cpu_R[rd], t0, dc->mem_idx);
- tcg_temp_free_i64(t0);
- }
- break;
+ check_ob64s(dc);
+ mop = MO_TEQ;
+ goto do_load;
#endif*/
case 0x21: /* l.lwz */
LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
- {
- TCGv t0 = tcg_temp_new();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
- tcg_gen_qemu_ld32u(cpu_R[rd], t0, dc->mem_idx);
- tcg_temp_free(t0);
- }
- break;
+ mop = MO_TEUL;
+ goto do_load;
case 0x22: /* l.lws */
LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
- {
- TCGv t0 = tcg_temp_new();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
- tcg_gen_qemu_ld32s(cpu_R[rd], t0, dc->mem_idx);
- tcg_temp_free(t0);
- }
- break;
+ mop = MO_TESL;
+ goto do_load;
case 0x23: /* l.lbz */
LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
- {
- TCGv t0 = tcg_temp_new();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
- tcg_gen_qemu_ld8u(cpu_R[rd], t0, dc->mem_idx);
- tcg_temp_free(t0);
- }
- break;
+ mop = MO_UB;
+ goto do_load;
case 0x24: /* l.lbs */
LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
- {
- TCGv t0 = tcg_temp_new();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
- tcg_gen_qemu_ld8s(cpu_R[rd], t0, dc->mem_idx);
- tcg_temp_free(t0);
- }
- break;
+ mop = MO_SB;
+ goto do_load;
case 0x25: /* l.lhz */
LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
- {
- TCGv t0 = tcg_temp_new();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
- tcg_gen_qemu_ld16u(cpu_R[rd], t0, dc->mem_idx);
- tcg_temp_free(t0);
- }
- break;
+ mop = MO_TEUW;
+ goto do_load;
case 0x26: /* l.lhs */
LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
+ mop = MO_TESW;
+ goto do_load;
+
+ do_load:
{
TCGv t0 = tcg_temp_new();
tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(I16, 16));
- tcg_gen_qemu_ld16s(cpu_R[rd], t0, dc->mem_idx);
+ tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
tcg_temp_free(t0);
}
break;
@@ -1042,42 +1018,31 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
/*#ifdef TARGET_OPENRISC64
case 0x34: l.sd
LOG_DIS("l.sd %d, r%d, r%d, %d\n", I5, ra, rb, I11);
- {
- check_ob64s(dc);
- TCGv_i64 t0 = tcg_temp_new_i64();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
- tcg_gen_qemu_st64(cpu_R[rb], t0, dc->mem_idx);
- tcg_temp_free_i64(t0);
- }
- break;
+ check_ob64s(dc);
+ mop = MO_TEQ;
+ goto do_store;
#endif*/
case 0x35: /* l.sw */
LOG_DIS("l.sw %d, r%d, r%d, %d\n", I5, ra, rb, I11);
- {
- TCGv t0 = tcg_temp_new();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
- tcg_gen_qemu_st32(cpu_R[rb], t0, dc->mem_idx);
- tcg_temp_free(t0);
- }
- break;
+ mop = MO_TEUL;
+ goto do_store;
case 0x36: /* l.sb */
LOG_DIS("l.sb %d, r%d, r%d, %d\n", I5, ra, rb, I11);
- {
- TCGv t0 = tcg_temp_new();
- tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
- tcg_gen_qemu_st8(cpu_R[rb], t0, dc->mem_idx);
- tcg_temp_free(t0);
- }
- break;
+ mop = MO_UB;
+ goto do_store;
case 0x37: /* l.sh */
LOG_DIS("l.sh %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+ mop = MO_TEUW;
+ goto do_store;
+
+ do_store:
{
TCGv t0 = tcg_temp_new();
tcg_gen_addi_tl(t0, cpu_R[ra], sign_extend(tmp, 16));
- tcg_gen_qemu_st16(cpu_R[rb], t0, dc->mem_idx);
+ tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
tcg_temp_free(t0);
}
break;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 781b72f1ea..7af3fe277d 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1228,7 +1228,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
#endif
case KVM_EXIT_EPR:
DPRINTF("handle epr\n");
- run->epr.epr = ldl_phys(env->mpic_iack);
+ run->epr.epr = ldl_phys(cs->as, env->mpic_iack);
ret = 0;
break;
case KVM_EXIT_WATCHDOG:
diff --git a/tests/Makefile b/tests/Makefile
index 0ef8727873..b17d41e4e2 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -181,7 +181,7 @@ tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuuti
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
tests/test-int128$(EXESUF): tests/test-int128.o
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
- hw/core/qdev.o hw/core/qdev-properties.o \
+ hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
hw/core/irq.o \
$(qom-core-obj) \
$(test-qapi-obj-y) \
diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c
index e398b83018..ad232b561c 100644
--- a/tests/i440fx-test.c
+++ b/tests/i440fx-test.c
@@ -349,7 +349,7 @@ static void test_i440fx_firmware(FirmwareTestFixture *fixture,
qtest_start(cmdline);
g_free(cmdline);
- /* Qemu has loaded the firmware (because qtest_start() only returns after
+ /* QEMU has loaded the firmware (because qtest_start() only returns after
* the QMP handshake completes). We must unlink the firmware blob right
* here, because any assertion firing below would leak it in the
* filesystem. This is also the reason why we recreate the blob every time
diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005
index 9abcb84e4b..ba1236dfbf 100755
--- a/tests/qemu-iotests/005
+++ b/tests/qemu-iotests/005
@@ -44,6 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt generic
_supported_proto generic
_supported_os Linux
+_unsupported_imgopts "subformat=twoGbMaxExtentFlat" \
+ "subformat=twoGbMaxExtentSparse"
# vpc is limited to 127GB, so we can't test it here
if [ "$IMGFMT" = "vpc" ]; then
diff --git a/tests/qemu-iotests/070 b/tests/qemu-iotests/070
index 41bf100701..ce71fa4a22 100755
--- a/tests/qemu-iotests/070
+++ b/tests/qemu-iotests/070
@@ -56,11 +56,22 @@ _use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2
echo
echo "=== Verify open image read-only fails, due to dirty log ==="
-$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | grep -o "Permission denied"
+$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | _filter_testdir \
+ | _filter_qemu_io
echo "=== Verify open image replays log ==="
$QEMU_IO -c "read -pP 0xa5 0 18M" "$TEST_IMG" | _filter_qemu_io
+# extract fresh sample image again
+_use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2
+
+echo "=== Verify qemu-img check -r all replays log ==="
+$QEMU_IMG check -r all "$TEST_IMG" 2>&1 | _filter_testdir | _filter_qemu
+
+echo "=== Verify open image read-only succeeds after log replay ==="
+$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | _filter_testdir \
+ | _filter_qemu_io
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out
index 9db8ff2650..922d62cb51 100644
--- a/tests/qemu-iotests/070.out
+++ b/tests/qemu-iotests/070.out
@@ -1,8 +1,21 @@
QA output created by 070
=== Verify open image read-only fails, due to dirty log ===
-Permission denied
+qemu-io: can't open device TEST_DIR/iotest-dirtylog-10G-4M.vhdx: VHDX image file 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' opened read-only, but contains a log that needs to be replayed. To replay the log, execute:
+ qemu-img check -r all 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx': Operation not permitted
+ no file open, try 'help open'
=== Verify open image replays log ===
read 18874368/18874368 bytes at offset 0
18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== Verify qemu-img check -r all replays log ===
+The following inconsistencies were found and repaired:
+
+ 0 leaked clusters
+ 1 corruptions
+
+Double checking the fixed image now...
+No errors were found on the image.
+=== Verify open image read-only succeeds after log replay ===
+read 18874368/18874368 bytes at offset 0
+18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
index 6f68963a3d..38bdf5ec7c 100644
--- a/tests/test-qmp-input-strict.c
+++ b/tests/test-qmp-input-strict.c
@@ -92,7 +92,7 @@ static void test_validate_struct(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_free(p->string);
g_free(p);
}
@@ -107,7 +107,7 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
visit_type_UserDefNested(v, &udp, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
qapi_free_UserDefNested(udp);
}
@@ -121,7 +121,7 @@ static void test_validate_list(TestInputVisitorData *data,
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
visit_type_UserDefOneList(v, &head, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
qapi_free_UserDefOneList(head);
}
@@ -135,7 +135,7 @@ static void test_validate_union(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
visit_type_UserDefUnion(v, &tmp, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
qapi_free_UserDefUnion(tmp);
}
@@ -149,7 +149,7 @@ static void test_validate_fail_struct(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(error_is_set(&errp));
+ g_assert(errp);
if (p) {
g_free(p->string);
}
@@ -166,7 +166,7 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
visit_type_UserDefNested(v, &udp, NULL, &errp);
- g_assert(error_is_set(&errp));
+ g_assert(errp);
qapi_free_UserDefNested(udp);
}
@@ -180,7 +180,7 @@ static void test_validate_fail_list(TestInputVisitorData *data,
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
visit_type_UserDefOneList(v, &head, NULL, &errp);
- g_assert(error_is_set(&errp));
+ g_assert(errp);
qapi_free_UserDefOneList(head);
}
@@ -194,7 +194,7 @@ static void test_validate_fail_union(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
visit_type_UserDefUnion(v, &tmp, NULL, &errp);
- g_assert(error_is_set(&errp));
+ g_assert(errp);
qapi_free_UserDefUnion(tmp);
}
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 1e1c6fa0c2..6eb7dc5bcf 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -96,7 +96,7 @@ static void test_visitor_in_int(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%" PRId64, value);
visit_type_int(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, value);
}
@@ -114,7 +114,7 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%f", DBL_MAX);
visit_type_int(v, &res, NULL, &errp);
- g_assert(error_is_set(&errp));
+ g_assert(errp);
error_free(errp);
}
@@ -128,7 +128,7 @@ static void test_visitor_in_bool(TestInputVisitorData *data,
v = visitor_input_test_init(data, "true");
visit_type_bool(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, true);
}
@@ -142,7 +142,7 @@ static void test_visitor_in_number(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%f", value);
visit_type_number(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpfloat(res, ==, value);
}
@@ -156,7 +156,7 @@ static void test_visitor_in_string(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%s", value);
visit_type_str(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpstr(res, ==, value);
g_free(res);
@@ -175,7 +175,7 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
visit_type_EnumOne(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(i, ==, res);
visitor_input_teardown(data, NULL);
@@ -223,7 +223,7 @@ static void test_visitor_in_struct(TestInputVisitorData *data,
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(p->integer, ==, -42);
g_assert(p->boolean == true);
g_assert_cmpstr(p->string, ==, "foo");
@@ -248,7 +248,7 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
visit_type_UserDefNested(v, &udp, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
check_and_free_str(udp->string0, "string0");
check_and_free_str(udp->dict1.string1, "string1");
@@ -272,7 +272,7 @@ static void test_visitor_in_list(TestInputVisitorData *data,
v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
visit_type_UserDefOneList(v, &head, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert(head != NULL);
for (i = 0, item = head; item; item = item->next, i++) {
@@ -601,7 +601,7 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(error_is_set(&errp));
+ g_assert(errp);
g_assert(p->string == NULL);
error_free(errp);
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index e073d833bf..f31d168d63 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -49,7 +49,7 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
QObject *obj;
visit_type_int(data->ov, &value, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -67,7 +67,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
QObject *obj;
visit_type_bool(data->ov, &value, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -85,7 +85,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
QObject *obj;
visit_type_number(data->ov, &value, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -103,7 +103,7 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
QObject *obj;
visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -122,7 +122,7 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
/* A null string should return "" */
visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -141,7 +141,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
for (i = 0; i < ENUM_ONE_MAX; i++) {
visit_type_EnumOne(data->ov, &i, "unused", &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -161,7 +161,7 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
errp = NULL;
visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
- g_assert(error_is_set(&errp) == true);
+ g_assert(errp);
error_free(errp);
}
}
@@ -198,7 +198,7 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
QDict *qdict;
visit_type_TestStruct(data->ov, &p, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -241,7 +241,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
ud2->dict1.dict3.string3 = g_strdup(strings[3]);
visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -288,7 +288,7 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
u.has_enum1 = true;
u.enum1 = bad_values[i];
visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
- g_assert(error_is_set(&errp) == true);
+ g_assert(errp);
error_free(errp);
}
}
@@ -343,7 +343,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
}
visit_type_TestStructList(data->ov, &head, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index 5989f8118e..d406263aee 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -60,7 +60,7 @@ static void test_visitor_in_int(TestInputVisitorData *data,
v = visitor_input_test_init(data, "-42");
visit_type_int(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, value);
}
@@ -74,42 +74,42 @@ static void test_visitor_in_bool(TestInputVisitorData *data,
v = visitor_input_test_init(data, "true");
visit_type_bool(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, true);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "yes");
visit_type_bool(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, true);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "on");
visit_type_bool(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, true);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "false");
visit_type_bool(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, false);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "no");
visit_type_bool(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, false);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "off");
visit_type_bool(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(res, ==, false);
}
@@ -123,7 +123,7 @@ static void test_visitor_in_number(TestInputVisitorData *data,
v = visitor_input_test_init(data, "3.14");
visit_type_number(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpfloat(res, ==, value);
}
@@ -137,7 +137,7 @@ static void test_visitor_in_string(TestInputVisitorData *data,
v = visitor_input_test_init(data, value);
visit_type_str(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpstr(res, ==, value);
g_free(res);
@@ -156,7 +156,7 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
v = visitor_input_test_init(data, EnumOne_lookup[i]);
visit_type_EnumOne(v, &res, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
g_assert_cmpint(i, ==, res);
visitor_input_teardown(data, NULL);
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 56cc21d078..22363d100f 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -49,7 +49,7 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
char *str;
visit_type_int(data->ov, &value, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -65,7 +65,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
char *str;
visit_type_bool(data->ov, &value, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -81,7 +81,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
char *str;
visit_type_number(data->ov, &value, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -97,7 +97,7 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
char *str;
visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -114,7 +114,7 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
/* A null string should return "" */
visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(error_is_set(&errp) == 0);
+ g_assert(!errp);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -131,7 +131,7 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
for (i = 0; i < ENUM_ONE_MAX; i++) {
visit_type_EnumOne(data->ov, &i, "unused", &errp);
- g_assert(!error_is_set(&errp));
+ g_assert(!errp);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -149,7 +149,7 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
errp = NULL;
visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
- g_assert(error_is_set(&errp) == true);
+ g_assert(errp);
error_free(errp);
}
}
diff --git a/tpm.c b/tpm.c
index d68d69fe39..c371023b1c 100644
--- a/tpm.c
+++ b/tpm.c
@@ -161,7 +161,7 @@ static int configure_tpm(QemuOpts *opts)
/* validate backend specific opts */
qemu_opts_validate(opts, be->opts, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return 1;
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 9298f55ecf..797df71569 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -31,7 +31,7 @@ QemuOptsList *qemu_find_opts(const char *group)
Error *local_err = NULL;
ret = find_list(vm_config_groups, group, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_report("%s", error_get_pretty(local_err));
error_free(local_err);
}
@@ -295,7 +295,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
/* group with id */
list = find_list(lists, group, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_report("%s", error_get_pretty(local_err));
error_free(local_err);
goto out;
@@ -306,7 +306,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
if (sscanf(line, "[%63[^]]]", group) == 1) {
/* group without id */
list = find_list(lists, group, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_report("%s", error_get_pretty(local_err));
error_free(local_err);
goto out;
@@ -376,13 +376,13 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
}
subopts = qemu_opts_create(opts, NULL, 0, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto out;
}
qemu_opts_absorb_qdict(subopts, subqdict, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto out;
}
@@ -416,13 +416,13 @@ static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
opt_name = g_strdup_printf("%s.%u", opts->name, i++);
subopts = qemu_opts_create(opts, opt_name, 1, &local_err);
g_free(opt_name);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto out;
}
qemu_opts_absorb_qdict(subopts, section, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
qemu_opts_del(subopts);
goto out;
@@ -450,7 +450,7 @@ void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
for (i = 0; lists[i]; i++) {
config_parse_qdict_section(options, lists[i], &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 668e5d919f..fd76cd2ada 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -246,7 +246,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
switch (list->type) {
case OPT_FLAG:
parse_option_bool(name, value, &flag, &local_err);
- if (!error_is_set(&local_err)) {
+ if (!local_err) {
list->value.n = flag;
}
break;
@@ -269,7 +269,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
return -1;
}
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
@@ -640,7 +640,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value,
opt->desc = desc;
opt->str = g_strdup(value);
qemu_opt_parse(opt, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
qemu_opt_del(opt);
}
@@ -651,7 +651,7 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
Error *local_err = NULL;
opt_set(opts, name, value, false, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
@@ -812,7 +812,7 @@ int qemu_opts_set(QemuOptsList *list, const char *id,
Error *local_err = NULL;
opts = qemu_opts_create(list, id, 1, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
@@ -897,7 +897,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
if (strcmp(option, "id") != 0) {
/* store and parse */
opt_set(opts, option, value, prepend, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
@@ -945,7 +945,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
assert(!defaults || list->merge_lists);
opts = qemu_opts_create(list, id, !defaults, &local_err);
if (opts == NULL) {
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
}
@@ -1034,7 +1034,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return NULL;
}
@@ -1044,7 +1044,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
state.errp = &local_err;
state.opts = opts;
qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
qemu_opts_del(opts);
return NULL;
@@ -1075,7 +1075,7 @@ void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
if (find_desc_by_name(opts->list->desc, entry->key)) {
qemu_opts_from_qdict_1(entry->key, entry->value, &state);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
} else {
@@ -1129,7 +1129,7 @@ void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
}
qemu_opt_parse(opt, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
diff --git a/vl.c b/vl.c
index 071372d309..9379d335ac 100644
--- a/vl.c
+++ b/vl.c
@@ -27,64 +27,13 @@
#include <time.h>
#include <errno.h>
#include <sys/time.h>
-#include <zlib.h>
-#include "qemu/bitmap.h"
-/* Needed early for CONFIG_BSD etc. */
#include "config-host.h"
-#ifndef _WIN32
-#include <libgen.h>
-#include <sys/times.h>
-#include <sys/wait.h>
-#include <termios.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <dirent.h>
-#include <netdb.h>
-#include <sys/select.h>
-
-#ifdef CONFIG_BSD
-#include <sys/stat.h>
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-#include <sys/sysctl.h>
-#else
-#include <util.h>
-#endif
-#else
-#ifdef __linux__
-#include <malloc.h>
-
-#include <linux/ppdev.h>
-#include <linux/parport.h>
-#endif
-
#ifdef CONFIG_SECCOMP
#include "sysemu/seccomp.h"
#endif
-#ifdef __sun__
-#include <sys/stat.h>
-#include <sys/ethernet.h>
-#include <sys/sockio.h>
-#include <netinet/arp.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> // must come after ip.h
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-#include <net/if.h>
-#include <syslog.h>
-#include <stropts.h>
-#endif
-#endif
-#endif
-
#if defined(CONFIG_VDE)
#include <libvdeplug.h>
#endif
@@ -135,6 +84,7 @@ int main(int argc, char **argv)
#include "exec/gdbstub.h"
#include "qemu/timer.h"
#include "sysemu/char.h"
+#include "qemu/bitmap.h"
#include "qemu/cache-utils.h"
#include "sysemu/blockdev.h"
#include "hw/block/block.h"
@@ -172,9 +122,6 @@ int main(int argc, char **argv)
#include "qapi/string-input-visitor.h"
#include "qom/object_interfaces.h"
-//#define DEBUG_NET
-//#define DEBUG_SLIRP
-
#define DEFAULT_RAM_SIZE 128
#define MAX_VIRTIO_CONSOLES 1
@@ -2321,7 +2268,7 @@ static int chardev_init_func(QemuOpts *opts, void *opaque)
Error *local_err = NULL;
qemu_chr_new_from_opts(opts, NULL, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_report("%s", error_get_pretty(local_err));
error_free(local_err);
return -1;