[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [qemu-xen stable-4.12] Merge tag 'v3.0.1' into staging-4.12
=== This changeset includes merge from high-traffic branch === Commits on that branch are not reported individually. commit 8023a62081ffbe3f734019076ec1a2b4213142bb Merge: a55e2eca4b45108c9ffa4ab6f6068cd2e8501654 1dfcf652e6ae5eb6b98d2c55a509e8eb054a2fab Author: Anthony PERARD <anthony.perard@xxxxxxxxxx> AuthorDate: Tue Apr 16 10:52:53 2019 +0100 Commit: Anthony PERARD <anthony.perard@xxxxxxxxxx> CommitDate: Tue Apr 16 10:52:53 2019 +0100 Merge tag 'v3.0.1' into staging-4.12 3.0.1 VERSION | 2 +- block.c | 2 + block/block-backend.c | 3 + block/mirror.c | 18 +++--- block/nbd-client.c | 22 ++++++- block/nvme.c | 37 ++++-------- block/qapi.c | 3 +- block/rbd.c | 90 ++++++++++++++++++++++++----- configure | 7 +-- exec.c | 10 ++-- hw/acpi/piix4.c | 1 + hw/arm/virt.c | 2 + hw/audio/fmopl.h | 4 +- hw/block/fdc.c | 2 +- hw/char/virtio-serial-bus.c | 6 +- hw/i2c/bitbang_i2c.h | 2 - hw/i2c/smbus.c | 6 +- hw/i386/acpi-build.c | 85 +++++++-------------------- hw/i386/intel_iommu.c | 34 +++++++---- hw/net/ne2000.c | 4 +- hw/net/pcnet.c | 4 +- hw/net/rtl8139.c | 8 +-- hw/pci/pcie.c | 12 ++++ hw/ppc/pnv_lpc.c | 8 ++- hw/ppc/spapr_cpu_core.c | 62 ++++++++++---------- hw/rdma/rdma_rm_defs.h | 4 +- hw/scsi/lsi53c895a.c | 19 +++++- hw/scsi/vhost-scsi.c | 2 +- hw/tpm/tpm_emulator.c | 1 + hw/tpm/tpm_tis.c | 10 +++- hw/usb/dev-mtp.c | 19 ++++-- hw/virtio/vhost-user.c | 20 +++---- hw/virtio/vhost.c | 4 +- hw/virtio/virtio.c | 17 +++++- include/block/nbd.h | 4 +- include/hw/i2c/i2c.h | 2 + include/hw/i2c/ppc4xx_i2c.h | 3 - include/hw/s390x/tod.h | 2 +- job.c | 20 ++----- linux-user/syscall.c | 44 ++++++++++---- migration/postcopy-ram.c | 11 ++-- monitor.c | 2 + nbd/server.c | 9 ++- net/slirp.c | 9 +++ qemu-deprecated.texi | 15 +++++ qemu-img.c | 35 ++++++----- qemu-seccomp.c | 36 +++++++++++- qga/qapi-schema.json | 25 ++++---- scripts/make-release | 1 + slirp/bootp.c | 32 ++++++---- slirp/tcp_subr.c | 15 +++-- target/arm/cpu.c | 6 +- target/arm/cpu.h | 5 +- target/arm/cpu64.c | 29 ++++++++++ target/arm/helper.c | 55 +++++++++++------- target/arm/sve_helper.c | 23 +++----- target/arm/translate-a64.c | 106 ++++++++++++++++++++++++++++------ target/arm/translate-sve.c | 81 +++++++++++++++----------- target/i386/cpu.c | 6 ++ target/ppc/translate/vmx-ops.inc.c | 2 +- target/s390x/diag.c | 2 +- target/xtensa/translate.c | 8 +-- tests/acpi-test-data/pc/DSDT | Bin 5144 -> 5131 bytes tests/acpi-test-data/pc/DSDT.bridge | Bin 7003 -> 6990 bytes tests/acpi-test-data/pc/DSDT.cphp | Bin 5607 -> 5594 bytes tests/acpi-test-data/pc/DSDT.dimmpxm | Bin 6803 -> 6790 bytes tests/acpi-test-data/pc/DSDT.ipmikcs | Bin 5216 -> 5203 bytes tests/acpi-test-data/pc/DSDT.memhp | Bin 6509 -> 6496 bytes tests/acpi-test-data/pc/DSDT.numamem | Bin 5150 -> 5137 bytes tests/acpi-test-data/pc/SRAT.dimmpxm | Bin 472 -> 392 bytes tests/acpi-test-data/pc/SRAT.memhp | Bin 264 -> 264 bytes tests/acpi-test-data/q35/DSDT | Bin 7828 -> 7815 bytes tests/acpi-test-data/q35/DSDT.bridge | Bin 7845 -> 7832 bytes tests/acpi-test-data/q35/DSDT.cphp | Bin 8291 -> 8278 bytes tests/acpi-test-data/q35/DSDT.dimmpxm | Bin 9487 -> 9474 bytes tests/acpi-test-data/q35/DSDT.ipmibt | Bin 7903 -> 7890 bytes tests/acpi-test-data/q35/DSDT.memhp | Bin 9193 -> 9180 bytes tests/acpi-test-data/q35/DSDT.numamem | Bin 7834 -> 7821 bytes tests/acpi-test-data/q35/SRAT.dimmpxm | Bin 472 -> 392 bytes tests/acpi-test-data/q35/SRAT.memhp | Bin 264 -> 264 bytes tests/qemu-iotests/041 | 6 ++ tests/qemu-iotests/041.out | 4 +- tests/qemu-iotests/067.out | 1 + tests/qemu-iotests/229 | 95 ++++++++++++++++++++++++++++++ tests/qemu-iotests/229.out | 23 ++++++++ tests/qemu-iotests/231 | 62 ++++++++++++++++++++ tests/qemu-iotests/231.out | 9 +++ tests/qemu-iotests/235 | 78 +++++++++++++++++++++++++ tests/qemu-iotests/235.out | 3 + tests/qemu-iotests/group | 3 + ui/vnc-jobs.c | 3 +- util/aio-posix.c | 7 ++- util/aio-win32.c | 3 +- util/hbitmap.c | 3 + util/vfio-helpers.c | 2 +- vl.c | 1 + 96 files changed, 1026 insertions(+), 395 deletions(-) diff --git a/VERSION b/VERSION index 4a36342fca..cb2b00e4f7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0 +3.0.1 diff --git a/block.c b/block.c index 39f373e035..50b9bd695d 100644 --- a/block.c +++ b/block.c @@ -2787,6 +2787,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, bdrv_parent_cb_change_media(bs, true); qobject_unref(options); + options = NULL; /* For snapshot=on, create a temporary qcow2 overlay. bs points to the * temporary snapshot afterwards. */ @@ -4394,6 +4395,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, if (parent->role->activate) { parent->role->activate(parent, &local_err); if (local_err) { + bs->open_flags |= BDRV_O_INACTIVE; error_propagate(errp, local_err); return; } diff --git a/block/block-backend.c b/block/block-backend.c index f2f75a977d..1b27a68ae7 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -324,6 +324,9 @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm) blk->shared_perm = shared_perm; blk_set_enable_write_cache(blk, true); + blk->on_read_error = BLOCKDEV_ON_ERROR_REPORT; + blk->on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; + block_acct_init(&blk->stats); notifier_list_init(&blk->remove_bs_notifiers); diff --git a/block/mirror.c b/block/mirror.c index b48c3f8cf5..b097853983 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -198,7 +198,6 @@ static void coroutine_fn mirror_write_complete(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; - aio_context_acquire(blk_get_aio_context(s->common.blk)); if (ret < 0) { BlockErrorAction action; @@ -208,15 +207,14 @@ static void coroutine_fn mirror_write_complete(MirrorOp *op, int ret) s->ret = ret; } } + mirror_iteration_done(op, ret); - aio_context_release(blk_get_aio_context(s->common.blk)); } static void coroutine_fn mirror_read_complete(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; - aio_context_acquire(blk_get_aio_context(s->common.blk)); if (ret < 0) { BlockErrorAction action; @@ -227,12 +225,11 @@ static void coroutine_fn mirror_read_complete(MirrorOp *op, int ret) } mirror_iteration_done(op, ret); - } else { - ret = blk_co_pwritev(s->target, op->offset, - op->qiov.size, &op->qiov, 0); - mirror_write_complete(op, ret); + return; } - aio_context_release(blk_get_aio_context(s->common.blk)); + + ret = blk_co_pwritev(s->target, op->offset, op->qiov.size, &op->qiov, 0); + mirror_write_complete(op, ret); } /* Clip bytes relative to offset to not exceed end-of-file */ @@ -1499,6 +1496,11 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, buf_size = DEFAULT_MIRROR_BUF_SIZE; } + if (bs == target) { + error_setg(errp, "Can't mirror node into itself"); + return; + } + /* In the case of active commit, add dummy driver to provide consistent * reads on the top, while disabling it in the intermediate nodes, and make * the backing chain writable. */ diff --git a/block/nbd-client.c b/block/nbd-client.c index 9686ecbd5e..1b7b5b0a88 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -992,11 +992,18 @@ int nbd_client_init(BlockDriverState *bs, logout("Failed to negotiate with the NBD server\n"); return ret; } + if (x_dirty_bitmap && !client->info.base_allocation) { + error_setg(errp, "requested x-dirty-bitmap %s not found", + x_dirty_bitmap); + ret = -EINVAL; + goto fail; + } if (client->info.flags & NBD_FLAG_READ_ONLY && !bdrv_is_read_only(bs)) { error_setg(errp, "request for write access conflicts with read-only export"); - return -EACCES; + ret = -EACCES; + goto fail; } if (client->info.flags & NBD_FLAG_SEND_FUA) { bs->supported_write_flags = BDRV_REQ_FUA; @@ -1024,4 +1031,17 @@ int nbd_client_init(BlockDriverState *bs, logout("Established connection with NBD server\n"); return 0; + + fail: + /* + * We have connected, but must fail for other reasons. The + * connection is still blocking; send NBD_CMD_DISC as a courtesy + * to the server. + */ + { + NBDRequest request = { .type = NBD_CMD_DISC }; + + nbd_send_request(client->ioc ?: QIO_CHANNEL(sioc), &request); + return ret; + } } diff --git a/block/nvme.c b/block/nvme.c index 6f71122bf5..37805e8890 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -569,13 +569,13 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, s->vfio = qemu_vfio_open_pci(device, errp); if (!s->vfio) { ret = -EINVAL; - goto fail; + goto out; } s->regs = qemu_vfio_pci_map_bar(s->vfio, 0, 0, NVME_BAR_SIZE, errp); if (!s->regs) { ret = -EINVAL; - goto fail; + goto out; } /* Perform initialize sequence as described in NVMe spec "7.6.1 @@ -585,7 +585,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, if (!(cap & (1ULL << 37))) { error_setg(errp, "Device doesn't support NVMe command set"); ret = -EINVAL; - goto fail; + goto out; } s->page_size = MAX(4096, 1 << (12 + ((cap >> 48) & 0xF))); @@ -603,7 +603,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, PRId64 " ms)", timeout_ms); ret = -ETIMEDOUT; - goto fail; + goto out; } } @@ -613,7 +613,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, s->queues[0] = nvme_create_queue_pair(bs, 0, NVME_QUEUE_SIZE, errp); if (!s->queues[0]) { ret = -EINVAL; - goto fail; + goto out; } QEMU_BUILD_BUG_ON(NVME_QUEUE_SIZE & 0xF000); s->regs->aqa = cpu_to_le32((NVME_QUEUE_SIZE << 16) | NVME_QUEUE_SIZE); @@ -633,14 +633,14 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, PRId64 " ms)", timeout_ms); ret = -ETIMEDOUT; - goto fail_queue; + goto out; } } ret = qemu_vfio_pci_init_irq(s->vfio, &s->irq_notifier, VFIO_PCI_MSIX_IRQ_INDEX, errp); if (ret) { - goto fail_queue; + goto out; } aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier, false, nvme_handle_event, nvme_poll_cb); @@ -649,30 +649,15 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, if (local_err) { error_propagate(errp, local_err); ret = -EIO; - goto fail_handler; + goto out; } /* Set up command queues. */ if (!nvme_add_io_queue(bs, errp)) { ret = -EIO; - goto fail_handler; } - return 0; - -fail_handler: - aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier, - false, NULL, NULL); -fail_queue: - nvme_free_queue_pair(bs, s->queues[0]); -fail: - g_free(s->queues); - if (s->regs) { - qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE); - } - if (s->vfio) { - qemu_vfio_close(s->vfio); - } - event_notifier_cleanup(&s->irq_notifier); +out: + /* Cleaning up is done in nvme_file_open() upon error. */ return ret; } @@ -739,8 +724,10 @@ static void nvme_close(BlockDriverState *bs) for (i = 0; i < s->nr_queues; ++i) { nvme_free_queue_pair(bs, s->queues[i]); } + g_free(s->queues); aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier, false, NULL, NULL); + event_notifier_cleanup(&s->irq_notifier); qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE); qemu_vfio_close(s->vfio); } diff --git a/block/qapi.c b/block/qapi.c index 339727f0f4..c66f949db8 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -594,7 +594,7 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes, } } else { for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) { - BlockStatsList *info = g_malloc0(sizeof(*info)); + BlockStatsList *info; AioContext *ctx = blk_get_aio_context(blk); BlockStats *s; char *qdev; @@ -619,6 +619,7 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes, bdrv_query_blk_stats(s->stats, blk); aio_context_release(ctx); + info = g_malloc0(sizeof(*info)); info->value = s; *p_next = info; p_next = &info->next; diff --git a/block/rbd.c b/block/rbd.c index ca8e5bbace..014c68d629 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -655,12 +655,61 @@ failed_opts: return r; } +static int qemu_rbd_convert_options(QDict *options, BlockdevOptionsRbd **opts, + Error **errp) +{ + Visitor *v; + Error *local_err = NULL; + + /* Convert the remaining options into a QAPI object */ + v = qobject_input_visitor_new_flat_confused(options, errp); + if (!v) { + return -EINVAL; + } + + visit_type_BlockdevOptionsRbd(v, NULL, opts, &local_err); + visit_free(v); + + if (local_err) { + error_propagate(errp, local_err); + return -EINVAL; + } + + return 0; +} + +static int qemu_rbd_attempt_legacy_options(QDict *options, + BlockdevOptionsRbd **opts, + char **keypairs) +{ + char *filename; + int r; + + filename = g_strdup(qdict_get_try_str(options, "filename")); + if (!filename) { + return -EINVAL; + } + qdict_del(options, "filename"); + + qemu_rbd_parse_filename(filename, options, NULL); + + /* keypairs freed by caller */ + *keypairs = g_strdup(qdict_get_try_str(options, "=keyvalue-pairs")); + if (*keypairs) { + qdict_del(options, "=keyvalue-pairs"); + } + + r = qemu_rbd_convert_options(options, opts, NULL); + + g_free(filename); + return r; +} + static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; BlockdevOptionsRbd *opts = NULL; - Visitor *v; const QDictEntry *e; Error *local_err = NULL; char *keypairs, *secretid; @@ -676,20 +725,33 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, qdict_del(options, "password-secret"); } - /* Convert the remaining options into a QAPI object */ - v = qobject_input_visitor_new_flat_confused(options, errp); - if (!v) { - r = -EINVAL; - goto out; - } - - visit_type_BlockdevOptionsRbd(v, NULL, &opts, &local_err); - visit_free(v); - + r = qemu_rbd_convert_options(options, &opts, &local_err); if (local_err) { - error_propagate(errp, local_err); - r = -EINVAL; - goto out; + /* If keypairs are present, that means some options are present in + * the modern option format. Don't attempt to parse legacy option + * formats, as we won't support mixed usage. */ + if (keypairs) { + error_propagate(errp, local_err); + goto out; + } + + /* If the initial attempt to convert and process the options failed, + * we may be attempting to open an image file that has the rbd options + * specified in the older format consisting of all key/value pairs + * encoded in the filename. Go ahead and attempt to parse the + * filename, and see if we can pull out the required options. */ + r = qemu_rbd_attempt_legacy_options(options, &opts, &keypairs); + if (r < 0) { + /* Propagate the original error, not the legacy parsing fallback + * error, as the latter was just a best-effort attempt. */ + error_propagate(errp, local_err); + goto out; + } + /* Take care whenever deciding to actually deprecate; once this ability + * is removed, we will not be able to open any images with legacy-styled + * backing image strings. */ + error_report("RBD options encoded in the filename as keyvalue pairs " + "is deprecated"); } /* Remove the processed options from the QDict (the visitor processes diff --git a/configure b/configure index a8b707a670..98870f56ec 100755 --- a/configure +++ b/configure @@ -2224,13 +2224,10 @@ fi ########################################## # libseccomp check +libseccomp_minver="2.2.0" if test "$seccomp" != "no" ; then case "$cpu" in - i386|x86_64) - libseccomp_minver="2.1.0" - ;; - mips) - libseccomp_minver="2.2.0" + i386|x86_64|mips) ;; arm|aarch64) libseccomp_minver="2.2.3" diff --git a/exec.c b/exec.c index 4f5df07b6a..9bafcb155a 100644 --- a/exec.c +++ b/exec.c @@ -690,7 +690,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu, int i; for (i = 0; i < cpu->iommu_notifiers->len; i++) { - notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i); + notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i); if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) { break; } @@ -698,7 +698,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu, if (i == cpu->iommu_notifiers->len) { /* Not found, add a new entry at the end of the array */ cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1); - notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i); + notifier = g_new0(TCGIOMMUNotifier, 1); + g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier; notifier->mr = mr; notifier->iommu_idx = iommu_idx; @@ -730,8 +731,9 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu) TCGIOMMUNotifier *notifier; for (i = 0; i < cpu->iommu_notifiers->len; i++) { - notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i); + notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i); memory_region_unregister_iommu_notifier(notifier->mr, ¬ifier->n); + g_free(notifier); } g_array_free(cpu->iommu_notifiers, true); } @@ -1000,7 +1002,7 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp) vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); } - cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier)); + cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *)); #endif } diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 6404af5f33..7ae6d14b46 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -173,6 +173,7 @@ static int vmstate_acpi_post_load(void *opaque, int version_id) PIIX4PMState *s = opaque; pm_io_space_update(s); + smbus_io_space_update(s); return 0; } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 281ddcdf6e..7f234ff6e8 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1881,6 +1881,8 @@ static void virt_machine_2_10_options(MachineClass *mc) { virt_machine_2_11_options(mc); SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_10); + /* before 2.11 we never faulted accesses to bad addresses */ + mc->ignore_memory_transaction_failures = true; } DEFINE_VIRT_MACHINE(2, 10) diff --git a/hw/audio/fmopl.h b/hw/audio/fmopl.h index e7e578a48e..e008e72d7a 100644 --- a/hw/audio/fmopl.h +++ b/hw/audio/fmopl.h @@ -72,8 +72,8 @@ typedef struct fm_opl_f { /* Rhythm sention */ uint8_t rhythm; /* Rhythm mode , key flag */ /* time tables */ - int32_t AR_TABLE[75]; /* atttack rate tables */ - int32_t DR_TABLE[75]; /* decay rate tables */ + int32_t AR_TABLE[76]; /* attack rate tables */ + int32_t DR_TABLE[76]; /* decay rate tables */ uint32_t FN_TABLE[1024]; /* fnumber -> increment counter */ /* LFO */ int32_t *ams_table; diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 2e9c1e1e2f..6f19f127a5 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -1617,7 +1617,7 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0, fdctrl->fifo[5] = cur_drv->sect; fdctrl->fifo[6] = FD_SECTOR_SC; fdctrl->data_dir = FD_DIR_READ; - if (!(fdctrl->msr & FD_MSR_NONDMA)) { + if (fdctrl->dma_chann != -1 && !(fdctrl->msr & FD_MSR_NONDMA)) { IsaDmaClass *k = ISADMA_GET_CLASS(fdctrl->dma); k->release_DREQ(fdctrl->dma, fdctrl->dma_chann); } diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index d2dd8ab502..04e3ebe352 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -667,9 +667,9 @@ static void virtio_serial_save_device(VirtIODevice *vdev, QEMUFile *f) /* The config space (ignored on the far end in current versions) */ get_config(vdev, (uint8_t *)&config); - qemu_put_be16s(f, &config.cols); - qemu_put_be16s(f, &config.rows); - qemu_put_be32s(f, &config.max_nr_ports); + qemu_put_be16(f, config.cols); + qemu_put_be16(f, config.rows); + qemu_put_be32(f, config.max_nr_ports); /* The ports map */ max_nr_ports = s->serial.max_virtserial_ports; diff --git a/hw/i2c/bitbang_i2c.h b/hw/i2c/bitbang_i2c.h index 3a7126d5de..9443021710 100644 --- a/hw/i2c/bitbang_i2c.h +++ b/hw/i2c/bitbang_i2c.h @@ -3,8 +3,6 @@ #include "hw/i2c/i2c.h" -typedef struct bitbang_i2c_interface bitbang_i2c_interface; - #define BITBANG_I2C_SDA 0 #define BITBANG_I2C_SCL 1 diff --git a/hw/i2c/smbus.c b/hw/i2c/smbus.c index 587ce1ab7f..639ff90b65 100644 --- a/hw/i2c/smbus.c +++ b/hw/i2c/smbus.c @@ -193,7 +193,11 @@ static int smbus_i2c_send(I2CSlave *s, uint8_t data) switch (dev->mode) { case SMBUS_WRITE_DATA: DPRINTF("Write data %02x\n", data); - dev->data_buf[dev->data_len++] = data; + if (dev->data_len >= sizeof(dev->data_buf)) { + BADF("Too many bytes sent\n"); + } else { + dev->data_buf[dev->data_len++] = data; + } break; default: BADF("Unexpected write in state %d\n", dev->mode); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index e1ee8ae9e0..31ed0e16a2 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2134,8 +2134,16 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en); if (TPM_IS_TIS(tpm_find())) { - dev = aml_device("ISA.TPM"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31"))); + if (misc->tpm_version == TPM_VERSION_2_0) { + dev = aml_device("TPM"); + aml_append(dev, aml_name_decl("_HID", + aml_string("MSFT0101"))); + } else { + dev = aml_device("ISA.TPM"); + aml_append(dev, aml_name_decl("_HID", + aml_eisaid("PNP0C31"))); + } + aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); crs = aml_resource_template(); aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE, @@ -2251,64 +2259,6 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) #define HOLE_640K_START (640 * KiB) #define HOLE_640K_END (1 * MiB) -static void build_srat_hotpluggable_memory(GArray *table_data, uint64_t base, - uint64_t len, int default_node) -{ - MemoryDeviceInfoList *info_list = qmp_memory_device_list(); - MemoryDeviceInfoList *info; - MemoryDeviceInfo *mi; - PCDIMMDeviceInfo *di; - uint64_t end = base + len, cur, size; - bool is_nvdimm; - AcpiSratMemoryAffinity *numamem; - MemoryAffinityFlags flags; - - for (cur = base, info = info_list; - cur < end; - cur += size, info = info->next) { - numamem = acpi_data_push(table_data, sizeof *numamem); - - if (!info) { - /* - * Entry is required for Windows to enable memory hotplug in OS - * and for Linux to enable SWIOTLB when booted with less than - * 4G of RAM. Windows works better if the entry sets proximity - * to the highest NUMA node in the machine at the end of the - * reserved space. - * Memory devices may override proximity set by this entry, - * providing _PXM method if necessary. - */ - build_srat_memory(numamem, end - 1, 1, default_node, - MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); - break; - } - - mi = info->value; - is_nvdimm = (mi->type == MEMORY_DEVICE_INFO_KIND_NVDIMM); - di = !is_nvdimm ? mi->u.dimm.data : mi->u.nvdimm.data; - - if (cur < di->addr) { - build_srat_memory(numamem, cur, di->addr - cur, default_node, - MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); - numamem = acpi_data_push(table_data, sizeof *numamem); - } - - size = di->size; - - flags = MEM_AFFINITY_ENABLED; - if (di->hotpluggable) { - flags |= MEM_AFFINITY_HOTPLUGGABLE; - } - if (is_nvdimm) { - flags |= MEM_AFFINITY_NON_VOLATILE; - } - - build_srat_memory(numamem, di->addr, size, di->node, flags); - } - - qapi_free_MemoryDeviceInfoList(info_list); -} - static void build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) { @@ -2414,10 +2364,19 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS); } + /* + * Entry is required for Windows to enable memory hotplug in OS + * and for Linux to enable SWIOTLB when booted with less than + * 4G of RAM. Windows works better if the entry sets proximity + * to the highest NUMA node in the machine. + * Memory devices may override proximity set by this entry, + * providing _PXM method if necessary. + */ if (hotplugabble_address_space_size) { - build_srat_hotpluggable_memory(table_data, machine->device_memory->base, - hotplugabble_address_space_size, - pcms->numa_nodes - 1); + numamem = acpi_data_push(table_data, sizeof *numamem); + build_srat_memory(numamem, machine->device_memory->base, + hotplugabble_address_space_size, pcms->numa_nodes - 1, + MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); } build_header(linker, table_data, diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 0a8cd4e9cc..4dfa9d5e2b 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -37,6 +37,8 @@ #include "kvm_i386.h" #include "trace.h" +static void vtd_address_space_refresh_all(IntelIOMMUState *s); + static void vtd_define_quad(IntelIOMMUState *s, hwaddr addr, uint64_t val, uint64_t wmask, uint64_t w1cmask) { @@ -227,6 +229,14 @@ static void vtd_reset_iotlb(IntelIOMMUState *s) vtd_iommu_unlock(s); } +static void vtd_reset_caches(IntelIOMMUState *s) +{ + vtd_iommu_lock(s); + vtd_reset_iotlb_locked(s); + vtd_reset_context_cache_locked(s); + vtd_iommu_unlock(s); +} + static uint64_t vtd_get_iotlb_key(uint64_t gfn, uint16_t source_id, uint32_t level) { @@ -1418,7 +1428,7 @@ static void vtd_context_global_invalidate(IntelIOMMUState *s) vtd_reset_context_cache_locked(s); } vtd_iommu_unlock(s); - vtd_switch_address_space_all(s); + vtd_address_space_refresh_all(s); /* * From VT-d spec 6.5.2.1, a global context entry invalidation * should be followed by a IOTLB global invalidation, so we should @@ -1703,6 +1713,8 @@ static void vtd_handle_gcmd_srtp(IntelIOMMUState *s) vtd_root_table_setup(s); /* Ok - report back to driver */ vtd_set_clear_mask_long(s, DMAR_GSTS_REG, 0, VTD_GSTS_RTPS); + vtd_reset_caches(s); + vtd_address_space_refresh_all(s); } /* Set Interrupt Remap Table Pointer */ @@ -1735,7 +1747,8 @@ static void vtd_handle_gcmd_te(IntelIOMMUState *s, bool en) vtd_set_clear_mask_long(s, DMAR_GSTS_REG, VTD_GSTS_TES, 0); } - vtd_switch_address_space_all(s); + vtd_reset_caches(s); + vtd_address_space_refresh_all(s); } /* Handle Interrupt Remap Enable/Disable */ @@ -3014,6 +3027,12 @@ static void vtd_address_space_unmap_all(IntelIOMMUState *s) } } +static void vtd_address_space_refresh_all(IntelIOMMUState *s) +{ + vtd_address_space_unmap_all(s); + vtd_switch_address_space_all(s); +} + static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private) { memory_region_notify_one((IOMMUNotifier *)private, entry); @@ -3123,10 +3142,7 @@ static void vtd_init(IntelIOMMUState *s) s->cap |= VTD_CAP_CM; } - vtd_iommu_lock(s); - vtd_reset_context_cache_locked(s); - vtd_reset_iotlb_locked(s); - vtd_iommu_unlock(s); + vtd_reset_caches(s); /* Define registers with default values and bit semantics */ vtd_define_long(s, DMAR_VER_REG, 0x10UL, 0, 0); @@ -3189,11 +3205,7 @@ static void vtd_reset(DeviceState *dev) IntelIOMMUState *s = INTEL_IOMMU_DEVICE(dev); vtd_init(s); - - /* - * When device reset, throw away all mappings and external caches - */ - vtd_address_space_unmap_all(s); + vtd_address_space_refresh_all(s); } static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn) diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index 07d79e317f..869518ee06 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -174,7 +174,7 @@ static int ne2000_buffer_full(NE2000State *s) ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_) { NE2000State *s = qemu_get_nic_opaque(nc); - int size = size_; + size_t size = size_; uint8_t *p; unsigned int total_len, next, avail, len, index, mcast_idx; uint8_t buf1[60]; @@ -182,7 +182,7 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_) { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #if defined(DEBUG_NE2000) - printf("NE2000: received len=%d\n", size); + printf("NE2000: received len=%zu\n", size); #endif if (s->cmd & E8390_STOP || ne2000_buffer_full(s)) diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 0c44554168..d9ba04bdfc 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -988,14 +988,14 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) uint8_t buf1[60]; int remaining; int crc_err = 0; - int size = size_; + size_t size = size_; if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size || (CSR_LOOP(s) && !s->looptest)) { return -1; } #ifdef PCNET_DEBUG - printf("pcnet_receive size=%d\n", size); + printf("pcnet_receive size=%zu\n", size); #endif /* if too small buffer, then expand it */ diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 46daa16202..2342a095e3 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -817,7 +817,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t RTL8139State *s = qemu_get_nic_opaque(nc); PCIDevice *d = PCI_DEVICE(s); /* size is the length of the buffer passed to the driver */ - int size = size_; + size_t size = size_; const uint8_t *dot1q_buf = NULL; uint32_t packet_header = 0; @@ -826,7 +826,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - DPRINTF(">>> received len=%d\n", size); + DPRINTF(">>> received len=%zu\n", size); /* test if board clock is stopped */ if (!s->clock_enabled) @@ -1035,7 +1035,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t if (size+4 > rx_space) { - DPRINTF("C+ Rx mode : descriptor %d size %d received %d + 4\n", + DPRINTF("C+ Rx mode : descriptor %d size %d received %zu + 4\n", descriptor, rx_space, size); s->IntrStatus |= RxOverflow; @@ -1148,7 +1148,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t if (avail != 0 && RX_ALIGN(size + 8) >= avail) { DPRINTF("rx overflow: rx buffer length %d head 0x%04x " - "read 0x%04x === available 0x%04x need 0x%04x\n", + "read 0x%04x === available 0x%04x need 0x%04zx\n", s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8); s->IntrStatus |= RxOverflow; diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 6c91bd44a0..66b73b87c8 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -345,6 +345,10 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, if (!dev->hotplugged) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); + if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { + pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, + PCI_EXP_LNKSTA_DLLLA); + } return; } @@ -355,6 +359,10 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, if (pci_get_function_0(pci_dev)) { pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); + if (pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { + pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, + PCI_EXP_LNKSTA_DLLLA); + } pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP); } @@ -531,6 +539,10 @@ void pcie_cap_slot_write_config(PCIDevice *dev, pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDS); + if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { + pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA, + PCI_EXP_LNKSTA_DLLLA); + } pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDC); } diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c index d7721320a2..172a915cfc 100644 --- a/hw/ppc/pnv_lpc.c +++ b/hw/ppc/pnv_lpc.c @@ -155,9 +155,15 @@ static void pnv_lpc_do_eccb(PnvLpcController *lpc, uint64_t cmd) /* XXX Check for magic bits at the top, addr size etc... */ unsigned int sz = (cmd & ECCB_CTL_SZ_MASK) >> ECCB_CTL_SZ_LSH; uint32_t opb_addr = cmd & ECCB_CTL_ADDR_MASK; - uint8_t data[4]; + uint8_t data[8]; bool success; + if (sz > sizeof(data)) { + qemu_log_mask(LOG_GUEST_ERROR, + "ECCB: invalid operation at @0x%08x size %d\n", opb_addr, sz); + return; + } + if (cmd & ECCB_CTL_READ) { success = opb_read(lpc, opb_addr, data, sz); if (success) { diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 993759db47..bb88a3ce4e 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -113,26 +113,6 @@ const char *spapr_get_cpu_core_type(const char *cpu_type) return object_class_get_name(oc); } -static void spapr_unrealize_vcpu(PowerPCCPU *cpu) -{ - qemu_unregister_reset(spapr_cpu_reset, cpu); - object_unparent(cpu->intc); - cpu_remove_sync(CPU(cpu)); - object_unparent(OBJECT(cpu)); -} - -static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp) -{ - sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); - CPUCore *cc = CPU_CORE(dev); - int i; - - for (i = 0; i < cc->nr_threads; i++) { - spapr_unrealize_vcpu(sc->threads[i]); - } - g_free(sc->threads); -} - static bool slb_shadow_needed(void *opaque) { sPAPRCPUState *spapr_cpu = opaque; @@ -207,10 +187,34 @@ static const VMStateDescription vmstate_spapr_cpu_state = { } }; +static void spapr_unrealize_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc) +{ + if (!sc->pre_3_0_migration) { + vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data); + } + qemu_unregister_reset(spapr_cpu_reset, cpu); + object_unparent(cpu->intc); + cpu_remove_sync(CPU(cpu)); + object_unparent(OBJECT(cpu)); +} + +static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp) +{ + sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); + CPUCore *cc = CPU_CORE(dev); + int i; + + for (i = 0; i < cc->nr_threads; i++) { + spapr_unrealize_vcpu(sc->threads[i], sc); + } + g_free(sc->threads); +} + static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr, - Error **errp) + sPAPRCPUCore *sc, Error **errp) { CPUPPCState *env = &cpu->env; + CPUState *cs = CPU(cpu); Error *local_err = NULL; object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); @@ -233,6 +237,11 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr, goto error_unregister; } + if (!sc->pre_3_0_migration) { + vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state, + cpu->machine_data); + } + return; error_unregister: @@ -272,10 +281,6 @@ static PowerPCCPU *spapr_create_vcpu(sPAPRCPUCore *sc, int i, Error **errp) } cpu->machine_data = g_new0(sPAPRCPUState, 1); - if (!sc->pre_3_0_migration) { - vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state, - cpu->machine_data); - } object_unref(obj); return cpu; @@ -290,9 +295,6 @@ static void spapr_delete_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc) { sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu); - if (!sc->pre_3_0_migration) { - vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data); - } cpu->machine_data = NULL; g_free(spapr_cpu); object_unparent(OBJECT(cpu)); @@ -325,7 +327,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) } for (j = 0; j < cc->nr_threads; j++) { - spapr_realize_vcpu(sc->threads[j], spapr, &local_err); + spapr_realize_vcpu(sc->threads[j], spapr, sc, &local_err); if (local_err) { goto err_unrealize; } @@ -334,7 +336,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) err_unrealize: while (--j >= 0) { - spapr_unrealize_vcpu(sc->threads[j]); + spapr_unrealize_vcpu(sc->threads[j], sc); } err: while (--i >= 0) { diff --git a/hw/rdma/rdma_rm_defs.h b/hw/rdma/rdma_rm_defs.h index 226011176d..f098d91813 100644 --- a/hw/rdma/rdma_rm_defs.h +++ b/hw/rdma/rdma_rm_defs.h @@ -89,7 +89,7 @@ typedef struct RdmaRmPort { enum ibv_port_state state; } RdmaRmPort; -typedef struct RdmaDeviceResources { +struct RdmaDeviceResources { RdmaRmPort ports[MAX_PORTS]; RdmaRmResTbl pd_tbl; RdmaRmResTbl mr_tbl; @@ -98,6 +98,6 @@ typedef struct RdmaDeviceResources { RdmaRmResTbl cq_tbl; RdmaRmResTbl cqe_ctx_tbl; GHashTable *qp_hash; /* Keeps mapping between real and emulated */ -} RdmaDeviceResources; +}; #endif diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 160657f4b9..3758635665 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -865,10 +865,11 @@ static void lsi_do_status(LSIState *s) static void lsi_do_msgin(LSIState *s) { - int len; + uint8_t len; DPRINTF("Message in len=%d/%d\n", s->dbc, s->msg_len); s->sfbr = s->msg[0]; len = s->msg_len; + assert(len > 0 && len <= LSI_MAX_MSGIN_LEN); if (len > s->dbc) len = s->dbc; pci_dma_write(PCI_DEVICE(s), s->dnad, s->msg, len); @@ -1703,8 +1704,10 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) break; case 0x58: /* SBDL */ /* Some drivers peek at the data bus during the MSG IN phase. */ - if ((s->sstat1 & PHASE_MASK) == PHASE_MI) + if ((s->sstat1 & PHASE_MASK) == PHASE_MI) { + assert(s->msg_len > 0); return s->msg[0]; + } ret = 0; break; case 0x59: /* SBDL high */ @@ -2096,11 +2099,23 @@ static int lsi_pre_save(void *opaque) return 0; } +static int lsi_post_load(void *opaque, int version_id) +{ + LSIState *s = opaque; + + if (s->msg_len < 0 || s->msg_len > LSI_MAX_MSGIN_LEN) { + return -EINVAL; + } + + return 0; +} + static const VMStateDescription vmstate_lsi_scsi = { .name = "lsiscsi", .version_id = 0, .minimum_version_id = 0, .pre_save = lsi_pre_save, + .post_load = lsi_post_load, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, LSIState), diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 9c1bea8ff3..a5eb2800a2 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -183,7 +183,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) } vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; - vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs); + vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); vsc->dev.vq_index = 0; vsc->dev.backend_features = 0; diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 10bc20dbec..70f4b10284 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -166,6 +166,7 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number, trace_tpm_emulator_set_locality(locty_number); + memset(&loc, 0, sizeof(loc)); loc.u.req.loc = locty_number; if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_LOCALITY, &loc, sizeof(loc), sizeof(loc)) < 0) { diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 12f5c9a759..fb08b483bc 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -263,7 +263,9 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) { uint8_t busy_locty; - s->aborting_locty = locty; + assert(TPM_TIS_IS_VALID_LOCTY(newlocty)); + + s->aborting_locty = locty; /* may also be TPM_TIS_NO_LOCALITY */ s->next_locty = newlocty; /* locality after successful abort */ /* @@ -293,9 +295,11 @@ static void tpm_tis_request_completed(TPMIf *ti, int ret) uint8_t locty = s->cmd.locty; uint8_t l; + assert(TPM_TIS_IS_VALID_LOCTY(locty)); + if (s->cmd.selftest_done) { for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { - s->loc[locty].sts |= TPM_TIS_STS_SELFTEST_DONE; + s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE; } } @@ -616,7 +620,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, } /* cancel any seize by a lower locality */ - for (l = 0; l < locty - 1; l++) { + for (l = 0; l < locty; l++) { s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE; } diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 1ded7ac9a3..f4223fb9de 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -649,13 +649,18 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o) { struct dirent *entry; DIR *dir; + int fd; if (o->have_children) { return; } o->have_children = true; - dir = opendir(o->path); + fd = open(o->path, O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); + if (fd < 0) { + return; + } + dir = fdopendir(fd); if (!dir) { return; } @@ -1003,7 +1008,7 @@ static MTPData *usb_mtp_get_object(MTPState *s, MTPControl *c, trace_usb_mtp_op_get_object(s->dev.addr, o->handle, o->path); - d->fd = open(o->path, O_RDONLY); + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); if (d->fd == -1) { usb_mtp_data_free(d); return NULL; @@ -1027,7 +1032,7 @@ static MTPData *usb_mtp_get_partial_object(MTPState *s, MTPControl *c, c->argv[1], c->argv[2]); d = usb_mtp_data_alloc(c); - d->fd = open(o->path, O_RDONLY); + d->fd = open(o->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); if (d->fd == -1) { usb_mtp_data_free(d); return NULL; @@ -1608,7 +1613,7 @@ static void usb_mtp_write_data(MTPState *s) 0, 0, 0, 0); goto done; } - d->fd = open(path, O_CREAT | O_WRONLY, mask); + d->fd = open(path, O_CREAT | O_WRONLY | O_CLOEXEC | O_NOFOLLOW, mask); if (d->fd == -1) { usb_mtp_queue_result(s, RES_STORE_FULL, d->trans, 0, 0, 0, 0); @@ -1667,6 +1672,12 @@ static void usb_mtp_write_metadata(MTPState *s) utf16_to_str(dataset->length, dataset->filename, filename); + if (strchr(filename, '/')) { + usb_mtp_queue_result(s, RES_PARAMETER_NOT_SUPPORTED, d->trans, + 0, 0, 0, 0); + return; + } + o = usb_mtp_object_lookup_name(p, filename, dataset->length); if (o != NULL) { next_handle = o->handle; diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index b041343632..e09bed0e4a 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -374,8 +374,6 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, int fds[VHOST_MEMORY_MAX_NREGIONS]; int i, fd; size_t fd_num = 0; - bool reply_supported = virtio_has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_REPLY_ACK); VhostUserMsg msg_reply; int region_i, msg_i; @@ -384,10 +382,6 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, .hdr.flags = VHOST_USER_VERSION, }; - if (reply_supported) { - msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; - } - if (u->region_rb_len < dev->mem->nregions) { u->region_rb = g_renew(RAMBlock*, u->region_rb, dev->mem->nregions); u->region_rb_offset = g_renew(ram_addr_t, u->region_rb_offset, @@ -503,10 +497,6 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, return -1; } - if (reply_supported) { - return process_message_reply(dev, &msg); - } - return 0; } @@ -519,8 +509,7 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, size_t fd_num = 0; bool do_postcopy = u->postcopy_listen && u->postcopy_fd.handler; bool reply_supported = virtio_has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_REPLY_ACK) && - !do_postcopy; + VHOST_USER_PROTOCOL_F_REPLY_ACK); if (do_postcopy) { /* Postcopy has enough differences that it's best done in it's own @@ -1291,6 +1280,7 @@ static int vhost_user_postcopy_end(struct vhost_dev *dev, Error **errp) return ret; } postcopy_unregister_shared_ufd(&u->postcopy_fd); + close(u->postcopy_fd.fd); u->postcopy_fd.handler = NULL; trace_vhost_user_postcopy_end_exit(); @@ -1430,6 +1420,12 @@ static int vhost_user_backend_cleanup(struct vhost_dev *dev) postcopy_remove_notifier(&u->postcopy_notifier); u->postcopy_notifier.notify = NULL; } + u->postcopy_listen = false; + if (u->postcopy_fd.handler) { + postcopy_unregister_shared_ufd(&u->postcopy_fd); + close(u->postcopy_fd.fd); + u->postcopy_fd.handler = NULL; + } if (u->slave_fd >= 0) { qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL); close(u->slave_fd); diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index d4cb5894a8..569c4053ea 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1073,10 +1073,8 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, .index = vhost_vq_index, }; int r; - int a; - a = virtio_queue_get_desc_addr(vdev, idx); - if (a == 0) { + if (virtio_queue_get_desc_addr(vdev, idx) == 0) { /* Don't stop the virtqueue which might have not been started */ return; } diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index d4e4d98b59..57a603a65b 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1604,6 +1604,8 @@ void virtio_del_queue(VirtIODevice *vdev, int n) vdev->vq[n].vring.num = 0; vdev->vq[n].vring.num_default = 0; + vdev->vq[n].handle_output = NULL; + vdev->vq[n].handle_aio_output = NULL; } static void virtio_set_isr(VirtIODevice *vdev, int value) @@ -2006,14 +2008,25 @@ static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val) int virtio_set_features(VirtIODevice *vdev, uint64_t val) { - /* + int ret; + /* * The driver must not attempt to set features after feature negotiation * has finished. */ if (vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) { return -EINVAL; } - return virtio_set_features_nocheck(vdev, val); + ret = virtio_set_features_nocheck(vdev, val); + if (!ret && virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { + /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */ + int i; + for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { + if (vdev->vq[i].vring.num != 0) { + virtio_init_region_cache(vdev, i); + } + } + } + return ret; } int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) diff --git a/include/block/nbd.h b/include/block/nbd.h index 4638c839f5..a53b0cfae0 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -135,7 +135,9 @@ typedef struct NBDExtent { #define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */ #define NBD_FLAG_SEND_DF (1 << 7) /* Send DF (Do not Fragment) */ -#define NBD_FLAG_SEND_CACHE (1 << 8) /* Send CACHE (prefetch) */ +#define NBD_FLAG_CAN_MULTI_CONN (1 << 8) /* Multi-client cache consistent */ +#define NBD_FLAG_SEND_RESIZE (1 << 9) /* Send resize */ +#define NBD_FLAG_SEND_CACHE (1 << 10) /* Send CACHE (prefetch) */ /* New-style handshake (global) flags, sent from server to client, and control what will happen during handshake phase. */ diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h index 5dc166158b..cf4c45a98f 100644 --- a/include/hw/i2c/i2c.h +++ b/include/hw/i2c/i2c.h @@ -82,6 +82,8 @@ int i2c_recv(I2CBus *bus); DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr); +typedef struct bitbang_i2c_interface bitbang_i2c_interface; + /* lm832x.c */ void lm832x_key_event(DeviceState *dev, int key, int state); diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h index 0891a9c948..b3450bacf7 100644 --- a/include/hw/i2c/ppc4xx_i2c.h +++ b/include/hw/i2c/ppc4xx_i2c.h @@ -31,9 +31,6 @@ #include "hw/sysbus.h" #include "hw/i2c/i2c.h" -/* from hw/i2c/bitbang_i2c.h */ -typedef struct bitbang_i2c_interface bitbang_i2c_interface; - #define TYPE_PPC4xx_I2C "ppc4xx-i2c" #define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C) diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h index 413c0d7c02..442f45b2f5 100644 --- a/include/hw/s390x/tod.h +++ b/include/hw/s390x/tod.h @@ -50,7 +50,7 @@ typedef struct S390TODClass { /* Converts ns to s390's clock format */ static inline uint64_t time2tod(uint64_t ns) { - return (ns << 9) / 125 + (((ns & 0xff10000000000000ull) / 125) << 9); + return (ns << 9) / 125 + (((ns & 0xff80000000000000ull) / 125) << 9); } /* Converts s390's clock format to ns */ diff --git a/job.c b/job.c index fa671b431a..a3bec7fb22 100644 --- a/job.c +++ b/job.c @@ -136,21 +136,13 @@ static void job_txn_del_job(Job *job) } } -static int job_txn_apply(JobTxn *txn, int fn(Job *), bool lock) +static int job_txn_apply(JobTxn *txn, int fn(Job *)) { - AioContext *ctx; Job *job, *next; int rc = 0; QLIST_FOREACH_SAFE(job, &txn->jobs, txn_list, next) { - if (lock) { - ctx = job->aio_context; - aio_context_acquire(ctx); - } rc = fn(job); - if (lock) { - aio_context_release(ctx); - } if (rc) { break; } @@ -732,10 +724,10 @@ static void job_cancel_async(Job *job, bool force) { if (job->user_paused) { /* Do not call job_enter here, the caller will handle it. */ - job->user_paused = false; if (job->driver->user_resume) { job->driver->user_resume(job); } + job->user_paused = false; assert(job->pause_count > 0); job->pause_count--; } @@ -807,11 +799,11 @@ static void job_do_finalize(Job *job) assert(job && job->txn); /* prepare the transaction to complete */ - rc = job_txn_apply(job->txn, job_prepare, true); + rc = job_txn_apply(job->txn, job_prepare); if (rc) { job_completed_txn_abort(job); } else { - job_txn_apply(job->txn, job_finalize_single, true); + job_txn_apply(job->txn, job_finalize_single); } } @@ -857,10 +849,10 @@ static void job_completed_txn_success(Job *job) assert(other_job->ret == 0); } - job_txn_apply(txn, job_transition_to_pending, false); + job_txn_apply(txn, job_transition_to_pending); /* If no jobs need manual finalization, automatically do so */ - if (job_txn_apply(txn, job_needs_finalize, false) == 0) { + if (job_txn_apply(txn, job_needs_finalize) == 0) { job_do_finalize(job); } } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index dfc851cc35..0859739e9d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8077,6 +8077,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_write: + if (arg2 == 0 && arg3 == 0) { + return get_errno(safe_write(arg1, 0, 0)); + } if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) goto efault; if (fd_trans_target_to_host_data(arg1)) { @@ -10848,15 +10851,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_AARCH64 case TARGET_PR_SVE_SET_VL: - /* We cannot support either PR_SVE_SET_VL_ONEXEC - or PR_SVE_VL_INHERIT. Therefore, anything above - ARM_MAX_VQ results in EINVAL. */ + /* + * We cannot support either PR_SVE_SET_VL_ONEXEC or + * PR_SVE_VL_INHERIT. Note the kernel definition + * of sve_vl_valid allows for VQ=512, i.e. VL=8192, + * even though the current architectural maximum is VQ=16. + */ ret = -TARGET_EINVAL; if (arm_feature(cpu_env, ARM_FEATURE_SVE) - && arg2 >= 0 && arg2 <= ARM_MAX_VQ * 16 && !(arg2 & 15)) { + && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) { CPUARMState *env = cpu_env; - int old_vq = (env->vfp.zcr_el[1] & 0xf) + 1; - int vq = MAX(arg2 / 16, 1); + ARMCPU *cpu = arm_env_get_cpu(env); + uint32_t vq, old_vq; + + old_vq = (env->vfp.zcr_el[1] & 0xf) + 1; + vq = MAX(arg2 / 16, 1); + vq = MIN(vq, cpu->sve_max_vq); if (vq < old_vq) { aarch64_sve_narrow_vq(env, vq); @@ -10900,8 +10910,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, arg4 = arg5; arg5 = arg6; } - if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) - goto efault; + if (arg2 == 0 && arg3 == 0) { + /* Special-case NULL buffer and zero length, which should succeed */ + p = 0; + } else { + p = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (!p) { + goto efault; + } + } ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); unlock_user(p, arg2, ret); break; @@ -10910,8 +10927,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, arg4 = arg5; arg5 = arg6; } - if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) - goto efault; + if (arg2 == 0 && arg3 == 0) { + /* Special-case NULL buffer and zero length, which should succeed */ + p = 0; + } else { + p = lock_user(VERIFY_READ, arg2, arg3, 1); + if (!p) { + goto efault; + } + } ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); unlock_user(p, arg2, 0); break; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 932f188949..d6cc99fee1 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -519,6 +519,12 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis) if (mis->have_fault_thread) { Error *local_err = NULL; + /* Let the fault thread quit */ + atomic_set(&mis->fault_thread_quit, 1); + postcopy_fault_thread_notify(mis); + trace_postcopy_ram_incoming_cleanup_join(); + qemu_thread_join(&mis->fault_thread); + if (postcopy_notify(POSTCOPY_NOTIFY_INBOUND_END, &local_err)) { error_report_err(local_err); return -1; @@ -527,11 +533,6 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis) if (qemu_ram_foreach_migratable_block(cleanup_range, mis)) { return -1; } - /* Let the fault thread quit */ - atomic_set(&mis->fault_thread_quit, 1); - postcopy_fault_thread_notify(mis); - trace_postcopy_ram_incoming_cleanup_join(); - qemu_thread_join(&mis->fault_thread); trace_postcopy_ram_incoming_cleanup_closeuf(); close(mis->userfault_fd); diff --git a/monitor.c b/monitor.c index 77861e96af..a1999e396c 100644 --- a/monitor.c +++ b/monitor.c @@ -4277,6 +4277,8 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id) ?: ""); monitor_qmp_dispatch(mon, req, id); + qobject_unref(req); + qobject_unref(id); return; } diff --git a/nbd/server.c b/nbd/server.c index ea5fe0eb33..2193e16c68 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -978,6 +978,7 @@ static int nbd_negotiate_meta_queries(NBDClient *client, if (client->opt == NBD_OPT_LIST_META_CONTEXT && !nb_queries) { /* enable all known contexts */ meta->base_allocation = true; + meta->bitmap = !!meta->exp->export_bitmap; } else { for (i = 0; i < nb_queries; ++i) { ret = nbd_negotiate_meta_query(client, meta, errp); @@ -1951,6 +1952,8 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset, assert(begin < overall_end && nb_extents); while (begin < overall_end && i < nb_extents) { + bool next_dirty = !dirty; + if (dirty) { end = bdrv_dirty_bitmap_next_zero(bitmap, begin); } else { @@ -1962,6 +1965,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset, end = MIN(bdrv_dirty_bitmap_size(bitmap), begin + UINT32_MAX + 1 - bdrv_dirty_bitmap_granularity(bitmap)); + next_dirty = dirty; } if (dont_fragment && end > overall_end) { end = overall_end; @@ -1971,7 +1975,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset, extents[i].flags = cpu_to_be32(dirty ? NBD_STATE_DIRTY : 0); i++; begin = end; - dirty = !dirty; + dirty = next_dirty; } bdrv_dirty_iter_free(it); @@ -2135,7 +2139,8 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, } if (client->structured_reply && !(request->flags & NBD_CMD_FLAG_DF) && - request->len) { + request->len && request->type != NBD_CMD_CACHE) + { return nbd_co_send_sparse_read(client, request->handle, request->from, data, request->len, errp); } diff --git a/net/slirp.c b/net/slirp.c index 1e14318b4d..fd21dc728c 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -365,6 +365,15 @@ static int net_slirp_init(NetClientState *peer, const char *model, return -1; } + if (vdomainname && strlen(vdomainname) > 255) { + error_setg(errp, "'domainname' parameter cannot exceed 255 bytes"); + return -1; + } + + if (vhostname && strlen(vhostname) > 255) { + error_setg(errp, "'vhostname' parameter cannot exceed 255 bytes"); + return -1; + } nc = qemu_new_net_client(&net_slirp_info, peer, model, name); diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi index 9920a85adc..cff0e8b309 100644 --- a/qemu-deprecated.texi +++ b/qemu-deprecated.texi @@ -227,6 +227,21 @@ from old QEMU versions anymore. A newer machine type should be used instead. In order to prevent QEMU from automatically opening an image's backing chain, use ``"backing": null'' instead. +@subsubsection rbd keyvalue pair encoded filenames: "" (since 3.1.0) + +Options for ``rbd'' should be specified according to its runtime options, +like other block drivers. Legacy parsing of keyvalue pair encoded +filenames is useful to open images with the old format for backing files; +These image files should be updated to use the current format. + +Example of legacy encoding: + +@code{json:@{"file.driver":"rbd", "file.filename":"rbd:rbd/name"@}} + +The above, converted to the current supported format: + +@code{json:@{"file.driver":"rbd", "file.pool":"rbd", "file.image":"name"@}} + @subsection vio-spapr-device device options @subsubsection "irq": "" (since 3.0.0) diff --git a/qemu-img.c b/qemu-img.c index 1acddf693c..4799e097dc 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -261,8 +261,9 @@ static int print_block_option_help(const char *filename, const char *fmt) return 1; } if (!proto_drv->create_opts) { - error_report("Protocal driver '%s' does not support image creation", + error_report("Protocol driver '%s' does not support image creation", proto_drv->format_name); + qemu_opts_free(create_opts); return 1; } create_opts = qemu_opts_append(create_opts, proto_drv->create_opts); @@ -345,21 +346,6 @@ static int img_add_key_secrets(void *opaque, return 0; } -static BlockBackend *img_open_new_file(const char *filename, - QemuOpts *create_opts, - const char *fmt, int flags, - bool writethrough, bool quiet, - bool force_share) -{ - QDict *options = NULL; - - options = qdict_new(); - qemu_opt_foreach(create_opts, img_add_key_secrets, options, &error_abort); - - return img_open_file(filename, options, fmt, flags, writethrough, quiet, - force_share); -} - static BlockBackend *img_open(bool image_opts, const char *filename, @@ -2018,6 +2004,7 @@ static int img_convert(int argc, char **argv) BlockDriverState *out_bs; QemuOpts *opts = NULL, *sn_opts = NULL; QemuOptsList *create_opts = NULL; + QDict *open_opts = NULL; char *options = NULL; Error *local_err = NULL; bool writethrough, src_writethrough, quiet = false, image_opts = false, @@ -2362,6 +2349,16 @@ static int img_convert(int argc, char **argv) } } + /* + * The later open call will need any decryption secrets, and + * bdrv_create() will purge "opts", so extract them now before + * they are lost. + */ + if (!skip_create) { + open_opts = qdict_new(); + qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort); + } + if (!skip_create) { /* Create the new image */ ret = bdrv_create(drv, out_filename, opts, &local_err); @@ -2388,8 +2385,9 @@ static int img_convert(int argc, char **argv) * That has to wait for bdrv_create to be improved * to allow filenames in option syntax */ - s.target = img_open_new_file(out_filename, opts, out_fmt, - flags, writethrough, quiet, false); + s.target = img_open_file(out_filename, open_opts, out_fmt, + flags, writethrough, quiet, false); + open_opts = NULL; /* blk_new_open will have freed it */ } if (!s.target) { ret = -1; @@ -2464,6 +2462,7 @@ out: qemu_opts_del(opts); qemu_opts_free(create_opts); qemu_opts_del(sn_opts); + qobject_unref(open_opts); blk_unref(s.target); if (s.src) { for (bs_i = 0; bs_i < s.src_num; bs_i++) { diff --git a/qemu-seccomp.c b/qemu-seccomp.c index 9cd8eb9499..4729eb107f 100644 --- a/qemu-seccomp.c +++ b/qemu-seccomp.c @@ -20,6 +20,7 @@ #include <sys/prctl.h> #include <seccomp.h> #include "sysemu/seccomp.h" +#include <linux/seccomp.h> /* For some architectures (notably ARM) cacheflush is not supported until * libseccomp 2.2.3, but configure enforces that we are using a more recent @@ -107,12 +108,40 @@ static const struct QemuSeccompSyscall blacklist[] = { { SCMP_SYS(sched_get_priority_min), QEMU_SECCOMP_SET_RESOURCECTL }, }; +static inline __attribute__((unused)) int +qemu_seccomp(unsigned int operation, unsigned int flags, void *args) +{ +#ifdef __NR_seccomp + return syscall(__NR_seccomp, operation, flags, args); +#else + errno = ENOSYS; + return -1; +#endif +} + +static uint32_t qemu_seccomp_get_kill_action(void) +{ +#if defined(SECCOMP_GET_ACTION_AVAIL) && defined(SCMP_ACT_KILL_PROCESS) && \ + defined(SECCOMP_RET_KILL_PROCESS) + { + uint32_t action = SECCOMP_RET_KILL_PROCESS; + + if (qemu_seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &action) == 0) { + return SCMP_ACT_KILL_PROCESS; + } + } +#endif + + return SCMP_ACT_TRAP; +} + static int seccomp_start(uint32_t seccomp_opts) { int rc = 0; unsigned int i = 0; scmp_filter_ctx ctx; + uint32_t action = qemu_seccomp_get_kill_action(); ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) { @@ -120,12 +149,17 @@ static int seccomp_start(uint32_t seccomp_opts) goto seccomp_return; } + rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_TSYNC, 1); + if (rc != 0) { + goto seccomp_return; + } + for (i = 0; i < ARRAY_SIZE(blacklist); i++) { if (!(seccomp_opts & blacklist[i].set)) { continue; } - rc = seccomp_rule_add_array(ctx, SCMP_ACT_KILL, blacklist[i].num, + rc = seccomp_rule_add_array(ctx, action, blacklist[i].num, blacklist[i].narg, blacklist[i].arg_cmp); if (rc < 0) { goto seccomp_return; diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index dfbc4a5e32..6a472476a2 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -532,12 +532,12 @@ # # Suspend guest to disk. # -# This command tries to execute the scripts provided by the pm-utils package. -# If it's not available, the suspend operation will be performed by manually -# writing to a sysfs file. +# This command attempts to suspend the guest using three strategies, in this +# order: # -# For the best results it's strongly recommended to have the pm-utils -# package installed in the guest. +# - systemd hibernate +# - pm-utils (via pm-hibernate) +# - manual write into sysfs # # This command does NOT return a response on success. There is a high chance # the command succeeded if the VM exits with a zero exit status or, when @@ -560,12 +560,12 @@ # # Suspend guest to ram. # -# This command tries to execute the scripts provided by the pm-utils package. -# If it's not available, the suspend operation will be performed by manually -# writing to a sysfs file. +# This command attempts to suspend the guest using three strategies, in this +# order: # -# For the best results it's strongly recommended to have the pm-utils -# package installed in the guest. +# - systemd suspend +# - pm-utils (via pm-suspend) +# - manual write into sysfs # # IMPORTANT: guest-suspend-ram requires QEMU to support the 'system_wakeup' # command. Thus, it's *required* to query QEMU for the presence of the @@ -592,7 +592,10 @@ # # Save guest state to disk and suspend to ram. # -# This command requires the pm-utils package to be installed in the guest. +# This command attempts to suspend the guest by executing, in this order: +# +# - systemd hybrid-sleep +# - pm-utils (via pm-suspend-hybrid) # # IMPORTANT: guest-suspend-hybrid requires QEMU to support the 'system_wakeup' # command. Thus, it's *required* to query QEMU for the presence of the diff --git a/scripts/make-release b/scripts/make-release index 04fa9defdc..c14f75b12c 100755 --- a/scripts/make-release +++ b/scripts/make-release @@ -19,6 +19,7 @@ pushd ${destination} git checkout "v${version}" git submodule update --init (cd roms/seabios && git describe --tags --long --dirty > .version) +(cd roms/skiboot && ./make_version.sh > .version) # FIXME: The following line is a workaround for avoiding filename collisions # when unpacking u-boot sources on case-insensitive filesystems. Once we # update to something with u-boot commit 610eec7f0 we can drop this line. diff --git a/slirp/bootp.c b/slirp/bootp.c index 9e7b53ba94..1e8185f0ec 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -159,6 +159,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) struct in_addr preq_addr; int dhcp_msg_type, val; uint8_t *q; + uint8_t *end; uint8_t client_ethaddr[ETH_ALEN]; /* extract exact DHCP msg type */ @@ -240,6 +241,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ q = rbp->bp_vend; + end = (uint8_t *)&rbp[1]; memcpy(q, rfc1533_cookie, 4); q += 4; @@ -292,24 +294,33 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) if (*slirp->client_hostname) { val = strlen(slirp->client_hostname); - *q++ = RFC1533_HOSTNAME; - *q++ = val; - memcpy(q, slirp->client_hostname, val); - q += val; + if (q + val + 2 >= end) { + g_warning("DHCP packet size exceeded, " + "omitting host name option."); + } else { + *q++ = RFC1533_HOSTNAME; + *q++ = val; + memcpy(q, slirp->client_hostname, val); + q += val; + } } if (slirp->vdomainname) { val = strlen(slirp->vdomainname); - *q++ = RFC1533_DOMAINNAME; - *q++ = val; - memcpy(q, slirp->vdomainname, val); - q += val; + if (q + val + 2 >= end) { + g_warning("DHCP packet size exceeded, " + "omitting domain name option."); + } else { + *q++ = RFC1533_DOMAINNAME; + *q++ = val; + memcpy(q, slirp->vdomainname, val); + q += val; + } } if (slirp->vdnssearch) { - size_t spaceleft = sizeof(rbp->bp_vend) - (q - rbp->bp_vend); val = slirp->vdnssearch_len; - if (val + 1 > spaceleft) { + if (q + val >= end) { g_warning("DHCP packet size exceeded, " "omitting domain-search option."); } else { @@ -331,6 +342,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) memcpy(q, nak_msg, sizeof(nak_msg) - 1); q += sizeof(nak_msg) - 1; } + assert(q < end); *q = RFC1533_END; daddr.sin_addr.s_addr = 0xffffffffu; diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 8d0f94b75f..aa88de854a 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -640,6 +640,11 @@ tcp_emu(struct socket *so, struct mbuf *m) socklen_t addrlen = sizeof(struct sockaddr_in); struct sbuf *so_rcv = &so->so_rcv; + if (m->m_len > so_rcv->sb_datalen + - (so_rcv->sb_wptr - so_rcv->sb_data)) { + return 1; + } + memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); so_rcv->sb_wptr += m->m_len; so_rcv->sb_rptr += m->m_len; @@ -662,12 +667,12 @@ tcp_emu(struct socket *so, struct mbuf *m) break; } } + so_rcv->sb_cc = snprintf(so_rcv->sb_data, + so_rcv->sb_datalen, + "%d,%d\r\n", n1, n2); + so_rcv->sb_rptr = so_rcv->sb_data; + so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; } - so_rcv->sb_cc = snprintf(so_rcv->sb_data, - so_rcv->sb_datalen, - "%d,%d\r\n", n1, n2); - so_rcv->sb_rptr = so_rcv->sb_data; - so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; } m_free(m); return 0; diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 64a8005a4b..b25898ed4c 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -168,9 +168,9 @@ static void arm_cpu_reset(CPUState *s) env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3); env->cp15.cptr_el[3] |= CPTR_EZ; /* with maximum vector length */ - env->vfp.zcr_el[1] = ARM_MAX_VQ - 1; - env->vfp.zcr_el[2] = ARM_MAX_VQ - 1; - env->vfp.zcr_el[3] = ARM_MAX_VQ - 1; + env->vfp.zcr_el[1] = cpu->sve_max_vq - 1; + env->vfp.zcr_el[2] = env->vfp.zcr_el[1]; + env->vfp.zcr_el[3] = env->vfp.zcr_el[1]; #else /* Reset into the highest available EL */ if (arm_feature(env, ARM_FEATURE_EL3)) { diff --git a/target/arm/cpu.h b/target/arm/cpu.h index e310ffc29d..0dce472aae 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -857,6 +857,9 @@ struct ARMCPU { /* Used to synchronize KVM and QEMU in-kernel device levels */ uint8_t device_irq_level; + + /* Used to set the maximum vector length the cpu will support. */ + uint32_t sve_max_vq; }; static inline ARMCPU *arm_env_get_cpu(CPUARMState *env) @@ -1260,7 +1263,7 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val); * we store the underlying state in fpscr and just mask on read/write. */ #define FPSR_MASK 0xf800009f -#define FPCR_MASK 0x07f79f00 +#define FPCR_MASK 0x07ff9f00 #define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */ #define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */ diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index d0581d59d8..800bff780e 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -29,6 +29,7 @@ #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "kvm_arm.h" +#include "qapi/visitor.h" static inline void set_feature(CPUARMState *env, int feature) { @@ -217,6 +218,29 @@ static void aarch64_a53_initfn(Object *obj) define_arm_cp_regs(cpu, cortex_a57_a53_cp_reginfo); } +static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + ARMCPU *cpu = ARM_CPU(obj); + visit_type_uint32(v, name, &cpu->sve_max_vq, errp); +} + +static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + ARMCPU *cpu = ARM_CPU(obj); + Error *err = NULL; + + visit_type_uint32(v, name, &cpu->sve_max_vq, &err); + + if (!err && (cpu->sve_max_vq == 0 || cpu->sve_max_vq > ARM_MAX_VQ)) { + error_setg(&err, "unsupported SVE vector length"); + error_append_hint(&err, "Valid sve-max-vq in range [1-%d]\n", + ARM_MAX_VQ); + } + error_propagate(errp, err); +} + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); * otherwise, a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; @@ -253,6 +277,10 @@ static void aarch64_max_initfn(Object *obj) cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ cpu->dcz_blocksize = 7; /* 512 bytes */ #endif + + cpu->sve_max_vq = ARM_MAX_VQ; + object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_vq, + cpu_max_set_sve_vq, NULL, NULL, &error_fatal); } } @@ -405,6 +433,7 @@ void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) uint64_t pmask; assert(vq >= 1 && vq <= ARM_MAX_VQ); + assert(vq <= arm_env_get_cpu(env)->sve_max_vq); /* Zap the high bits of the zregs. */ for (i = 0; i < 32; i++) { diff --git a/target/arm/helper.c b/target/arm/helper.c index 66afb08ee0..cae2b2649d 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6858,7 +6858,7 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain, * not already saved. */ if (lr & R_V7M_EXCRET_DCRS_MASK && - !(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) { + !(dotailchain && !(lr & R_V7M_EXCRET_ES_MASK))) { push_failed = v7m_push_callee_stack(cpu, lr, dotailchain, ignore_stackfaults); } @@ -11283,9 +11283,13 @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env) fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16) | (env->vfp.vec_stride << 20); + i = get_float_exception_flags(&env->vfp.fp_status); i |= get_float_exception_flags(&env->vfp.standard_fp_status); - i |= get_float_exception_flags(&env->vfp.fp_status_f16); + /* FZ16 does not generate an input denormal exception. */ + i |= (get_float_exception_flags(&env->vfp.fp_status_f16) + & ~float_flag_input_denormal); + fpscr |= vfp_exceptbits_from_host(i); return fpscr; } @@ -11320,6 +11324,11 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val) int i; uint32_t changed; + /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */ + if (!arm_feature(env, ARM_FEATURE_V8_FP16)) { + val &= ~FPCR_FZ16; + } + changed = env->vfp.xregs[ARM_VFP_FPSCR]; env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff); env->vfp.vec_len = (val >> 16) & 7; @@ -12392,33 +12401,39 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, uint32_t flags; if (is_a64(env)) { - int sve_el = sve_exception_el(env); - uint32_t zcr_len; - *pc = env->pc; flags = ARM_TBFLAG_AARCH64_STATE_MASK; /* Get control bits for tagged addresses */ flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT); flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT); - flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT; - /* If SVE is disabled, but FP is enabled, - then the effective len is 0. */ - if (sve_el != 0 && fp_el == 0) { - zcr_len = 0; - } else { - int current_el = arm_current_el(env); + if (arm_feature(env, ARM_FEATURE_SVE)) { + int sve_el = sve_exception_el(env); + uint32_t zcr_len; - zcr_len = env->vfp.zcr_el[current_el <= 1 ? 1 : current_el]; - zcr_len &= 0xf; - if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) { - zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]); - } - if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) { - zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]); + /* If SVE is disabled, but FP is enabled, + * then the effective len is 0. + */ + if (sve_el != 0 && fp_el == 0) { + zcr_len = 0; + } else { + int current_el = arm_current_el(env); + ARMCPU *cpu = arm_env_get_cpu(env); + + zcr_len = cpu->sve_max_vq - 1; + if (current_el <= 1) { + zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]); + } + if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) { + zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]); + } + if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) { + zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]); + } } + flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT; + flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT; } - flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT; } else { *pc = env->regs[15]; flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c index 54795c9194..0f98097253 100644 --- a/target/arm/sve_helper.c +++ b/target/arm/sve_helper.c @@ -1042,7 +1042,7 @@ void HELPER(sve_movz_d)(void *vd, void *vn, void *vg, uint32_t desc) uint64_t *d = vd, *n = vn; uint8_t *pg = vg; for (i = 0; i < opr_sz; i += 1) { - d[i] = n[1] & -(uint64_t)(pg[H1(i)] & 1); + d[i] = n[i] & -(uint64_t)(pg[H1(i)] & 1); } } @@ -2436,13 +2436,13 @@ uint32_t HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \ #define DO_CMP_PPZW_S(NAME, TYPE, TYPEW, OP) \ DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H1_4, 0x1111111111111111ull) -DO_CMP_PPZW_B(sve_cmpeq_ppzw_b, uint8_t, uint64_t, ==) -DO_CMP_PPZW_H(sve_cmpeq_ppzw_h, uint16_t, uint64_t, ==) -DO_CMP_PPZW_S(sve_cmpeq_ppzw_s, uint32_t, uint64_t, ==) +DO_CMP_PPZW_B(sve_cmpeq_ppzw_b, int8_t, uint64_t, ==) +DO_CMP_PPZW_H(sve_cmpeq_ppzw_h, int16_t, uint64_t, ==) +DO_CMP_PPZW_S(sve_cmpeq_ppzw_s, int32_t, uint64_t, ==) -DO_CMP_PPZW_B(sve_cmpne_ppzw_b, uint8_t, uint64_t, !=) -DO_CMP_PPZW_H(sve_cmpne_ppzw_h, uint16_t, uint64_t, !=) -DO_CMP_PPZW_S(sve_cmpne_ppzw_s, uint32_t, uint64_t, !=) +DO_CMP_PPZW_B(sve_cmpne_ppzw_b, int8_t, uint64_t, !=) +DO_CMP_PPZW_H(sve_cmpne_ppzw_h, int16_t, uint64_t, !=) +DO_CMP_PPZW_S(sve_cmpne_ppzw_s, int32_t, uint64_t, !=) DO_CMP_PPZW_B(sve_cmpgt_ppzw_b, int8_t, int64_t, >) DO_CMP_PPZW_H(sve_cmpgt_ppzw_h, int16_t, int64_t, >) @@ -2846,11 +2846,6 @@ uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc) return flags; } - /* Scale from predicate element count to bits. */ - count <<= esz; - /* Bound to the bits in the predicate. */ - count = MIN(count, oprsz * 8); - /* Set all of the requested bits. */ for (i = 0; i < count / 64; ++i) { d->p[i] = esz_mask; @@ -3363,7 +3358,7 @@ static void do_fmla_zpzzz_h(CPUARMState *env, void *vg, uint32_t desc, e1 = *(uint16_t *)(vn + H1_2(i)) ^ neg1; e2 = *(uint16_t *)(vm + H1_2(i)); e3 = *(uint16_t *)(va + H1_2(i)) ^ neg3; - r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status); + r = float16_muladd(e1, e2, e3, 0, &env->vfp.fp_status_f16); *(uint16_t *)(vd + H1_2(i)) = r; } } while (i & 63); @@ -4050,7 +4045,7 @@ DO_LD1(sve_ld1bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, ) DO_LD1(sve_ld1bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, ) DO_LD1(sve_ld1hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4) -DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int8_t, H1_4) +DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int16_t, H1_4) DO_LD1(sve_ld1hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, ) DO_LD1(sve_ld1hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, ) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 45a6c2a3aa..b29dc49c4f 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -137,14 +137,13 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int el = arm_current_el(env); const char *ns_status; - cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", - env->pc, env->xregs[31]); - for (i = 0; i < 31; i++) { - cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); - if ((i % 4) == 3) { - cpu_fprintf(f, "\n"); + cpu_fprintf(f, " PC=%016" PRIx64 " ", env->pc); + for (i = 0; i < 32; i++) { + if (i == 31) { + cpu_fprintf(f, " SP=%016" PRIx64 "\n", env->xregs[i]); } else { - cpu_fprintf(f, " "); + cpu_fprintf(f, "X%02d=%016" PRIx64 "%s", i, env->xregs[i], + (i + 2) % 3 ? " " : "\n"); } } @@ -153,8 +152,7 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, } else { ns_status = ""; } - - cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n", + cpu_fprintf(f, "PSTATE=%08x %c%c%c%c %sEL%d%c", psr, psr & PSTATE_N ? 'N' : '-', psr & PSTATE_Z ? 'Z' : '-', @@ -164,17 +162,89 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f, el, psr & PSTATE_SP ? 'h' : 't'); - if (flags & CPU_DUMP_FPU) { - int numvfpregs = 32; - for (i = 0; i < numvfpregs; i++) { + if (!(flags & CPU_DUMP_FPU)) { + cpu_fprintf(f, "\n"); + return; + } + cpu_fprintf(f, " FPCR=%08x FPSR=%08x\n", + vfp_get_fpcr(env), vfp_get_fpsr(env)); + + if (arm_feature(env, ARM_FEATURE_SVE)) { + int j, zcr_len = env->vfp.zcr_el[1] & 0xf; /* fix for system mode */ + + for (i = 0; i <= FFR_PRED_NUM; i++) { + bool eol; + if (i == FFR_PRED_NUM) { + cpu_fprintf(f, "FFR="); + /* It's last, so end the line. */ + eol = true; + } else { + cpu_fprintf(f, "P%02d=", i); + switch (zcr_len) { + case 0: + eol = i % 8 == 7; + break; + case 1: + eol = i % 6 == 5; + break; + case 2: + case 3: + eol = i % 3 == 2; + break; + default: + /* More than one quadword per predicate. */ + eol = true; + break; + } + } + for (j = zcr_len / 4; j >= 0; j--) { + int digits; + if (j * 4 + 4 <= zcr_len + 1) { + digits = 16; + } else { + digits = (zcr_len % 4 + 1) * 4; + } + cpu_fprintf(f, "%0*" PRIx64 "%s", digits, + env->vfp.pregs[i].p[j], + j ? ":" : eol ? "\n" : " "); + } + } + + for (i = 0; i < 32; i++) { + if (zcr_len == 0) { + cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 "%s", + i, env->vfp.zregs[i].d[1], + env->vfp.zregs[i].d[0], i & 1 ? "\n" : " "); + } else if (zcr_len == 1) { + cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 + ":%016" PRIx64 ":%016" PRIx64 "\n", + i, env->vfp.zregs[i].d[3], env->vfp.zregs[i].d[2], + env->vfp.zregs[i].d[1], env->vfp.zregs[i].d[0]); + } else { + for (j = zcr_len; j >= 0; j--) { + bool odd = (zcr_len - j) % 2 != 0; + if (j == zcr_len) { + cpu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1); + } else if (!odd) { + if (j > 0) { + cpu_fprintf(f, " [%x-%x]=", j, j - 1); + } else { + cpu_fprintf(f, " [%x]=", j); + } + } + cpu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%s", + env->vfp.zregs[i].d[j * 2 + 1], + env->vfp.zregs[i].d[j * 2], + odd || j == 0 ? "\n" : ":"); + } + } + } + } else { + for (i = 0; i < 32; i++) { uint64_t *q = aa64_vfp_qreg(env, i); - uint64_t vlo = q[0]; - uint64_t vhi = q[1]; - cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c", - i, vhi, vlo, (i & 1 ? '\n' : ' ')); + cpu_fprintf(f, "Q%02d=%016" PRIx64 ":%016" PRIx64 "%s", + i, q[1], q[0], (i & 1 ? "\n" : " ")); } - cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n", - vfp_get_fpcr(env), vfp_get_fpsr(env)); } } diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index 374051cd20..667879564f 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -1625,7 +1625,7 @@ static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d) /* Detect signed overflow for subtraction. */ tcg_gen_xor_i64(t0, reg, val); tcg_gen_sub_i64(t1, reg, val); - tcg_gen_xor_i64(reg, reg, t0); + tcg_gen_xor_i64(reg, reg, t1); tcg_gen_and_i64(t0, t0, reg); /* Bound the result. */ @@ -3173,19 +3173,19 @@ static bool trans_CTERM(DisasContext *s, arg_CTERM *a, uint32_t insn) static bool trans_WHILE(DisasContext *s, arg_WHILE *a, uint32_t insn) { - if (!sve_access_check(s)) { - return true; - } - - TCGv_i64 op0 = read_cpu_reg(s, a->rn, 1); - TCGv_i64 op1 = read_cpu_reg(s, a->rm, 1); - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); + TCGv_i64 op0, op1, t0, t1, tmax; TCGv_i32 t2, t3; TCGv_ptr ptr; unsigned desc, vsz = vec_full_reg_size(s); TCGCond cond; + if (!sve_access_check(s)) { + return true; + } + + op0 = read_cpu_reg(s, a->rn, 1); + op1 = read_cpu_reg(s, a->rm, 1); + if (!a->sf) { if (a->u) { tcg_gen_ext32u_i64(op0, op0); @@ -3198,32 +3198,47 @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a, uint32_t insn) /* For the helper, compress the different conditions into a computation * of how many iterations for which the condition is true. - * - * This is slightly complicated by 0 <= UINT64_MAX, which is nominally - * 2**64 iterations, overflowing to 0. Of course, predicate registers - * aren't that large, so any value >= predicate size is sufficient. */ + t0 = tcg_temp_new_i64(); + t1 = tcg_temp_new_i64(); tcg_gen_sub_i64(t0, op1, op0); - /* t0 = MIN(op1 - op0, vsz). */ - tcg_gen_movi_i64(t1, vsz); - tcg_gen_umin_i64(t0, t0, t1); + tmax = tcg_const_i64(vsz >> a->esz); if (a->eq) { /* Equality means one more iteration. */ tcg_gen_addi_i64(t0, t0, 1); + + /* If op1 is max (un)signed integer (and the only time the addition + * above could overflow), then we produce an all-true predicate by + * setting the count to the vector length. This is because the + * pseudocode is described as an increment + compare loop, and the + * max integer would always compare true. + */ + tcg_gen_movi_i64(t1, (a->sf + ? (a->u ? UINT64_MAX : INT64_MAX) + : (a->u ? UINT32_MAX : INT32_MAX))); + tcg_gen_movcond_i64(TCG_COND_EQ, t0, op1, t1, tmax, t0); } - /* t0 = (condition true ? t0 : 0). */ + /* Bound to the maximum. */ + tcg_gen_umin_i64(t0, t0, tmax); + tcg_temp_free_i64(tmax); + + /* Set the count to zero if the condition is false. */ cond = (a->u ? (a->eq ? TCG_COND_LEU : TCG_COND_LTU) : (a->eq ? TCG_COND_LE : TCG_COND_LT)); tcg_gen_movi_i64(t1, 0); tcg_gen_movcond_i64(cond, t0, op0, op1, t0, t1); + tcg_temp_free_i64(t1); + /* Since we're bounded, pass as a 32-bit type. */ t2 = tcg_temp_new_i32(); tcg_gen_extrl_i64_i32(t2, t0); tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); + + /* Scale elements to bits. */ + tcg_gen_shli_i32(t2, t2, a->esz); desc = (vsz / 8) - 2; desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz); @@ -4078,7 +4093,7 @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg, static bool trans_FCVT_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) { - return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_sh); + return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sh); } static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn) @@ -4088,7 +4103,7 @@ static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn) static bool trans_FCVT_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) { - return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_dh); + return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_dh); } static bool trans_FCVT_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) @@ -4357,12 +4372,11 @@ static bool trans_UCVTF_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) * The load should begin at the address Rn + IMM. */ -static void do_ldr(DisasContext *s, uint32_t vofs, uint32_t len, - int rn, int imm) +static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm) { - uint32_t len_align = QEMU_ALIGN_DOWN(len, 8); - uint32_t len_remain = len % 8; - uint32_t nparts = len / 8 + ctpop8(len_remain); + int len_align = QEMU_ALIGN_DOWN(len, 8); + int len_remain = len % 8; + int nparts = len / 8 + ctpop8(len_remain); int midx = get_mem_index(s); TCGv_i64 addr, t0, t1; @@ -4443,12 +4457,11 @@ static void do_ldr(DisasContext *s, uint32_t vofs, uint32_t len, } /* Similarly for stores. */ -static void do_str(DisasContext *s, uint32_t vofs, uint32_t len, - int rn, int imm) +static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) { - uint32_t len_align = QEMU_ALIGN_DOWN(len, 8); - uint32_t len_remain = len % 8; - uint32_t nparts = len / 8 + ctpop8(len_remain); + int len_align = QEMU_ALIGN_DOWN(len, 8); + int len_remain = len % 8; + int nparts = len / 8 + ctpop8(len_remain); int midx = get_mem_index(s); TCGv_i64 addr, t0; @@ -4652,8 +4665,7 @@ static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn) } if (sve_access_check(s)) { TCGv_i64 addr = new_tmp_a64(s); - tcg_gen_muli_i64(addr, cpu_reg(s, a->rm), - (a->nreg + 1) << dtype_msz(a->dtype)); + tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype)); tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn)); do_ld_zpa(s, a->rd, a->pg, addr, a->dtype, a->nreg); } @@ -4806,6 +4818,7 @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) unsigned vsz = vec_full_reg_size(s); unsigned psz = pred_full_reg_size(s); unsigned esz = dtype_esz[a->dtype]; + unsigned msz = dtype_msz(a->dtype); TCGLabel *over = gen_new_label(); TCGv_i64 temp; @@ -4829,7 +4842,7 @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn) /* Load the data. */ temp = tcg_temp_new_i64(); - tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << esz); + tcg_gen_addi_i64(temp, cpu_reg_sp(s, a->rn), a->imm << msz); tcg_gen_qemu_ld_i64(temp, temp, get_mem_index(s), s->be_data | dtype_mop[a->dtype]); @@ -4885,7 +4898,7 @@ static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn) } if (sve_access_check(s)) { TCGv_i64 addr = new_tmp_a64(s); - tcg_gen_muli_i64(addr, cpu_reg(s, a->rm), (a->nreg + 1) << a->msz); + tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), a->msz); tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn)); do_st_zpa(s, a->rd, a->pg, addr, a->msz, a->esz, a->nreg); } diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 723e02221e..3ac627978f 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -849,6 +849,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, .cpuid_eax = 0x80000001, .cpuid_reg = R_ECX, .tcg_features = TCG_EXT3_FEATURES, + /* + * TOPOEXT is always allowed but can't be enabled blindly by + * "-cpu host", as it requires consistent cache topology info + * to be provided so it doesn't confuse guests. + */ + .no_autoenable_flags = CPUID_EXT3_TOPOEXT, }, [FEAT_C000_0001_EDX] = { .feat_names = { diff --git a/target/ppc/translate/vmx-ops.inc.c b/target/ppc/translate/vmx-ops.inc.c index 139f80cb24..84e05fb827 100644 --- a/target/ppc/translate/vmx-ops.inc.c +++ b/target/ppc/translate/vmx-ops.inc.c @@ -143,7 +143,7 @@ GEN_VXFORM(vaddsws, 0, 14), GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE), GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE), GEN_VXFORM(vsubuws, 0, 26), -GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_NONE, PPC2_ISA300), +GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_ALTIVEC, PPC2_ISA300), GEN_VXFORM(vsubshs, 0, 29), GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE), GEN_VXFORM_207(vadduqm, 0, 4), diff --git a/target/s390x/diag.c b/target/s390x/diag.c index acb0f3d4af..aafa740f61 100644 --- a/target/s390x/diag.c +++ b/target/s390x/diag.c @@ -130,7 +130,7 @@ out: } return; default: - hw_error("Unhandled diag308 subcode %" PRIx64, subcode); + s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, ra); break; } } diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index d22cdcdb16..c626583cd9 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -2288,7 +2288,7 @@ static void translate_s32c1i(DisasContext *dc, const uint32_t arg[], gen_load_store_alignment(dc, 2, addr, true); gen_check_atomctl(dc, addr); tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1], - tmp, dc->cring, MO_32); + tmp, dc->cring, MO_TEUL); tcg_temp_free(addr); tcg_temp_free(tmp); } @@ -4706,7 +4706,7 @@ static void translate_movcond_s(DisasContext *dc, const uint32_t arg[], tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]], cpu_R[arg[2]], zero, - cpu_FR[arg[1]], cpu_FR[arg[2]]); + cpu_FR[arg[1]], cpu_FR[arg[0]]); tcg_temp_free(zero); } } @@ -4867,7 +4867,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .translate = translate_compare_s, .par = (const uint32_t[]){COMPARE_OLT}, }, { - .name = "rfr.s", + .name = "rfr", .translate = translate_rfr_s, }, { .name = "round.s", @@ -4921,7 +4921,7 @@ static const XtensaOpcodeOps fpu2000_ops[] = { .translate = translate_ftoi_s, .par = (const uint32_t[]){float_round_to_zero, true}, }, { - .name = "wfr.s", + .name = "wfr", .translate = translate_wfr_s, }, }; diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT index 99f05a5027..c6adfe32d5 100644 Binary files a/tests/acpi-test-data/pc/DSDT and b/tests/acpi-test-data/pc/DSDT differ diff --git a/tests/acpi-test-data/pc/DSDT.bridge b/tests/acpi-test-data/pc/DSDT.bridge index cf23343e64..f01fa3ad4e 100644 Binary files a/tests/acpi-test-data/pc/DSDT.bridge and b/tests/acpi-test-data/pc/DSDT.bridge differ diff --git a/tests/acpi-test-data/pc/DSDT.cphp b/tests/acpi-test-data/pc/DSDT.cphp index c99c49f437..3295d81c7f 100644 Binary files a/tests/acpi-test-data/pc/DSDT.cphp and b/tests/acpi-test-data/pc/DSDT.cphp differ diff --git a/tests/acpi-test-data/pc/DSDT.dimmpxm b/tests/acpi-test-data/pc/DSDT.dimmpxm index 38661cb13e..f6ec911b11 100644 Binary files a/tests/acpi-test-data/pc/DSDT.dimmpxm and b/tests/acpi-test-data/pc/DSDT.dimmpxm differ diff --git a/tests/acpi-test-data/pc/DSDT.ipmikcs b/tests/acpi-test-data/pc/DSDT.ipmikcs index 5e970fda72..2633a8cecf 100644 Binary files a/tests/acpi-test-data/pc/DSDT.ipmikcs and b/tests/acpi-test-data/pc/DSDT.ipmikcs differ diff --git a/tests/acpi-test-data/pc/DSDT.memhp b/tests/acpi-test-data/pc/DSDT.memhp index 1fe6871aa2..e31ef50296 100644 Binary files a/tests/acpi-test-data/pc/DSDT.memhp and b/tests/acpi-test-data/pc/DSDT.memhp differ diff --git a/tests/acpi-test-data/pc/DSDT.numamem b/tests/acpi-test-data/pc/DSDT.numamem index 224cfdd9e9..71a975b3e2 100644 Binary files a/tests/acpi-test-data/pc/DSDT.numamem and b/tests/acpi-test-data/pc/DSDT.numamem differ diff --git a/tests/acpi-test-data/pc/SRAT.dimmpxm b/tests/acpi-test-data/pc/SRAT.dimmpxm index 5aa6f693ef..f5c0267ea2 100644 Binary files a/tests/acpi-test-data/pc/SRAT.dimmpxm and b/tests/acpi-test-data/pc/SRAT.dimmpxm differ diff --git a/tests/acpi-test-data/pc/SRAT.memhp b/tests/acpi-test-data/pc/SRAT.memhp index 5de8a100a4..e508b4ae3c 100644 Binary files a/tests/acpi-test-data/pc/SRAT.memhp and b/tests/acpi-test-data/pc/SRAT.memhp differ diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT index aa402cca66..7576ffcd05 100644 Binary files a/tests/acpi-test-data/q35/DSDT and b/tests/acpi-test-data/q35/DSDT differ diff --git a/tests/acpi-test-data/q35/DSDT.bridge b/tests/acpi-test-data/q35/DSDT.bridge index fc3e79c583..c623cc5d72 100644 Binary files a/tests/acpi-test-data/q35/DSDT.bridge and b/tests/acpi-test-data/q35/DSDT.bridge differ diff --git a/tests/acpi-test-data/q35/DSDT.cphp b/tests/acpi-test-data/q35/DSDT.cphp index fd3cb34218..7ac526e466 100644 Binary files a/tests/acpi-test-data/q35/DSDT.cphp and b/tests/acpi-test-data/q35/DSDT.cphp differ diff --git a/tests/acpi-test-data/q35/DSDT.dimmpxm b/tests/acpi-test-data/q35/DSDT.dimmpxm index 14904e8ea2..3837792dec 100644 Binary files a/tests/acpi-test-data/q35/DSDT.dimmpxm and b/tests/acpi-test-data/q35/DSDT.dimmpxm differ diff --git a/tests/acpi-test-data/q35/DSDT.ipmibt b/tests/acpi-test-data/q35/DSDT.ipmibt index 332237529e..c7f431f058 100644 Binary files a/tests/acpi-test-data/q35/DSDT.ipmibt and b/tests/acpi-test-data/q35/DSDT.ipmibt differ diff --git a/tests/acpi-test-data/q35/DSDT.memhp b/tests/acpi-test-data/q35/DSDT.memhp index f0a27e1a30..8fba0baf79 100644 Binary files a/tests/acpi-test-data/q35/DSDT.memhp and b/tests/acpi-test-data/q35/DSDT.memhp differ diff --git a/tests/acpi-test-data/q35/DSDT.numamem b/tests/acpi-test-data/q35/DSDT.numamem index 8c9fa445b0..6c0d4f2bcb 100644 Binary files a/tests/acpi-test-data/q35/DSDT.numamem and b/tests/acpi-test-data/q35/DSDT.numamem differ diff --git a/tests/acpi-test-data/q35/SRAT.dimmpxm b/tests/acpi-test-data/q35/SRAT.dimmpxm index 5aa6f693ef..f5c0267ea2 100644 Binary files a/tests/acpi-test-data/q35/SRAT.dimmpxm and b/tests/acpi-test-data/q35/SRAT.dimmpxm differ diff --git a/tests/acpi-test-data/q35/SRAT.memhp b/tests/acpi-test-data/q35/SRAT.memhp index 5de8a100a4..e508b4ae3c 100644 Binary files a/tests/acpi-test-data/q35/SRAT.memhp and b/tests/acpi-test-data/q35/SRAT.memhp differ diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index c20ac7da87..9336ab6ff5 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -234,6 +234,12 @@ class TestSingleBlockdev(TestSingleDrive): result = self.vm.qmp("blockdev-add", **args) self.assert_qmp(result, 'return', {}) + def test_mirror_to_self(self): + result = self.vm.qmp(self.qmp_cmd, job_id='job0', + device=self.qmp_target, sync='full', + target=self.qmp_target) + self.assert_qmp(result, 'error/class', 'GenericError') + test_large_cluster = None test_image_not_found = None test_small_buffer2 = None diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out index c28b392b87..e071d0b261 100644 --- a/tests/qemu-iotests/041.out +++ b/tests/qemu-iotests/041.out @@ -1,5 +1,5 @@ -..................................................................................... +........................................................................................ ---------------------------------------------------------------------- -Ran 85 tests +Ran 88 tests OK diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 2e71cff3ce..b10c71db03 100644 --- a/tests/qemu-iotests/067.out +++ b/tests/qemu-iotests/067.out @@ -385,6 +385,7 @@ Testing: -device virtio-scsi -device scsi-cd,id=cd0 { "return": [ { + "io-status": "ok", "device": "", "locked": false, "removable": true, diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229 new file mode 100755 index 0000000000..ff851ec431 --- /dev/null +++ b/tests/qemu-iotests/229 @@ -0,0 +1,95 @@ +#!/bin/bash +# +# Test for force canceling a running blockjob that is paused in +# an error state. +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=jcody@xxxxxxxxxx + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_qemu + _cleanup_test_img + rm -f "$TEST_IMG" "$DEST_IMG" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.qemu + +# Needs backing file and backing format support +_supported_fmt qcow2 qed +_supported_proto file +_supported_os Linux + + +DEST_IMG="$TEST_DIR/d.$IMGFMT" +TEST_IMG="$TEST_DIR/b.$IMGFMT" + +_make_test_img 2M + +# destination for mirror will be too small, causing error +TEST_IMG=$DEST_IMG _make_test_img 1M + +$QEMU_IO -c 'write 0 2M' "$TEST_IMG" | _filter_qemu_io + +_launch_qemu -drive id=testdisk,file="$TEST_IMG",format="$IMGFMT" + +_send_qemu_cmd $QEMU_HANDLE \ + "{'execute': 'qmp_capabilities'}" \ + 'return' + +echo +echo '=== Starting drive-mirror, causing error & stop ===' +echo + +_send_qemu_cmd $QEMU_HANDLE \ + "{'execute': 'drive-mirror', + 'arguments': {'device': 'testdisk', + 'mode': 'absolute-paths', + 'format': '$IMGFMT', + 'target': '$DEST_IMG', + 'sync': 'full', + 'mode': 'existing', + 'on-source-error': 'stop', + 'on-target-error': 'stop' }}" \ + "JOB_STATUS_CHANGE.*pause" + +echo +echo '=== Force cancel job paused in error state ===' +echo + +success_or_failure="y" _send_qemu_cmd $QEMU_HANDLE \ + "{'execute': 'block-job-cancel', + 'arguments': { 'device': 'testdisk', + 'force': true}}" \ + "BLOCK_JOB_CANCELLED" "Assertion" + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out new file mode 100644 index 0000000000..4c4112805f --- /dev/null +++ b/tests/qemu-iotests/229.out @@ -0,0 +1,23 @@ +QA output created by 229 +Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=2097152 +Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=1048576 +wrote 2097152/2097152 bytes at offset 0 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": {}} + +=== Starting drive-mirror, causing error & stop === + +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "testdisk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "testdisk", "operation": "write", "action": "stop"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "testdisk"}} + +=== Force cancel job paused in error state === + +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "testdisk", "operation": "write", "action": "stop"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |