diff options
54 files changed, 512 insertions, 130 deletions
diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml index 11d079ea58..892ca8d838 100644 --- a/.gitlab-ci.d/containers.yml +++ b/.gitlab-ci.d/containers.yml @@ -8,7 +8,7 @@ - export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/$NAME:latest" - apk add python3 - docker info - - docker login registry.gitlab.com -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" + - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" script: - echo "TAG:$TAG" - echo "COMMON_TAG:$COMMON_TAG" diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h index f5f5c553a9..bd6c12cb86 100644 --- a/backends/tpm/tpm_ioctl.h +++ b/backends/tpm/tpm_ioctl.h @@ -12,6 +12,10 @@ #include <sys/uio.h> #include <sys/ioctl.h> +#ifdef HAVE_SYS_IOCCOM_H +#include <sys/ioccom.h> +#endif + /* * Every response from a command involving a TPM command execution must hold * the ptm_res as the first element. diff --git a/block/export/meson.build b/block/export/meson.build index 19526435d8..135b356775 100644 --- a/block/export/meson.build +++ b/block/export/meson.build @@ -1,2 +1,5 @@ blockdev_ss.add(files('export.c')) -blockdev_ss.add(when: 'CONFIG_VHOST_USER_BLK_SERVER', if_true: files('vhost-user-blk-server.c')) + +if have_vhost_user_blk_server + blockdev_ss.add(files('vhost-user-blk-server.c')) +endif diff --git a/block/file-posix.c b/block/file-posix.c index c63926d592..d5fd1dbcd2 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1698,6 +1698,7 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) switch (ret) { case -ENOTSUP: case -EINVAL: + case -EBUSY: break; default: return ret; diff --git a/block/io_uring.c b/block/io_uring.c index 037af09471..00a3ee9fb8 100644 --- a/block/io_uring.c +++ b/block/io_uring.c @@ -425,6 +425,6 @@ LuringState *luring_init(Error **errp) void luring_cleanup(LuringState *s) { io_uring_queue_exit(&s->ring); - g_free(s); trace_luring_cleanup_state(s); + g_free(s); } diff --git a/block/quorum.c b/block/quorum.c index e846a7e892..b10fc2089e 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1163,7 +1163,12 @@ static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c, uint64_t perm, uint64_t shared, uint64_t *nperm, uint64_t *nshared) { + BDRVQuorumState *s = bs->opaque; + *nperm = perm & DEFAULT_PERM_PASSTHROUGH; + if (s->rewrite_corrupted) { + *nperm |= BLK_PERM_WRITE; + } /* * We cannot share RESIZE or WRITE, as this would make the diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c index 82eaebc1db..403da308c9 100644 --- a/chardev/char-stdio.c +++ b/chardev/char-stdio.c @@ -112,9 +112,7 @@ static void qemu_chr_open_stdio(Chardev *chr, qemu_chr_open_fd(chr, 0, 1); - if (opts->has_signal) { - stdio_allow_signal = opts->signal; - } + stdio_allow_signal = !opts->has_signal || opts->signal; qemu_chr_set_echo_stdio(chr, false); } #endif @@ -328,8 +328,8 @@ vhost_net="" vhost_crypto="" vhost_scsi="" vhost_vsock="" -vhost_user="" -vhost_user_blk_server="" +vhost_user="no" +vhost_user_blk_server="auto" vhost_user_fs="" kvm="auto" hax="auto" @@ -718,7 +718,6 @@ fi case $targetos in MINGW32*) mingw32="yes" - vhost_user="no" audio_possible_drivers="dsound sdl" if check_include dsound.h; then audio_drv_list="dsound" @@ -790,13 +789,14 @@ SunOS) ;; Haiku) haiku="yes" - QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -DBSD_SOURCE $QEMU_CFLAGS" + QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -D_BSD_SOURCE $QEMU_CFLAGS" ;; Linux) audio_drv_list="try-pa oss" audio_possible_drivers="oss alsa sdl pa" linux="yes" linux_user="yes" + vhost_user="yes" ;; esac @@ -1247,9 +1247,9 @@ for opt do ;; --enable-vhost-vsock) vhost_vsock="yes" ;; - --disable-vhost-user-blk-server) vhost_user_blk_server="no" + --disable-vhost-user-blk-server) vhost_user_blk_server="disabled" ;; - --enable-vhost-user-blk-server) vhost_user_blk_server="yes" + --enable-vhost-user-blk-server) vhost_user_blk_server="enabled" ;; --disable-vhost-user-fs) vhost_user_fs="no" ;; @@ -2341,9 +2341,8 @@ fi # vhost interdependencies and host support # vhost backends -test "$vhost_user" = "" && vhost_user=yes -if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then - error_exit "vhost-user isn't available on win32" +if test "$vhost_user" = "yes" && test "$linux" != "yes"; then + error_exit "vhost-user is only available on Linux" fi test "$vhost_vdpa" = "" && vhost_vdpa=$linux if test "$vhost_vdpa" = "yes" && test "$linux" != "yes"; then @@ -2390,12 +2389,6 @@ if test "$vhost_net" = ""; then test "$vhost_kernel" = "yes" && vhost_net=yes fi -# libvhost-user is Linux-only -test "$vhost_user_blk_server" = "" && vhost_user_blk_server=$linux -if test "$vhost_user_blk_server" = "yes" && test "$linux" = "no"; then - error_exit "--enable-vhost-user-blk-server is only available on Linux" -fi - ########################################## # pkg-config probe @@ -3512,8 +3505,15 @@ if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then # Check that the libraries actually work -- Ubuntu 18.04 ships # with pkg-config --static --libs data for gio-2.0 that is missing # -lblkid and will give a link error. - write_c_skeleton - if compile_prog "" "$gio_libs" ; then + cat > $TMPC <<EOF +#include <gio/gio.h> +int main(void) +{ + g_dbus_proxy_new_sync(0, 0, 0, 0, 0, 0, 0, 0); + return 0; +} +EOF + if compile_prog "$gio_cflags" "$gio_libs" ; then gio=yes else gio=no @@ -5842,7 +5842,7 @@ fi roms= if { test "$cpu" = "i386" || test "$cpu" = "x86_64"; } && \ test "$targetos" != "Darwin" && test "$targetos" != "SunOS" && \ - test "$softmmu" = yes ; then + test "$targetos" != "Haiku" && test "$softmmu" = yes ; then # Different host OS linkers have different ideas about the name of the ELF # emulation. Linux and OpenBSD/amd64 use 'elf_i386'; FreeBSD uses the _fbsd # variant; OpenBSD/i386 uses the _obsd variant; and Windows uses i386pe. @@ -6289,9 +6289,6 @@ fi if test "$vhost_vdpa" = "yes" ; then echo "CONFIG_VHOST_VDPA=y" >> $config_host_mak fi -if test "$vhost_user_blk_server" = "yes" ; then - echo "CONFIG_VHOST_USER_BLK_SERVER=y" >> $config_host_mak -fi if test "$vhost_user_fs" = "yes" ; then echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak fi @@ -7012,6 +7009,7 @@ NINJA=$ninja $meson setup \ -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \ -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\ -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \ + -Dvhost_user_blk_server=$vhost_user_blk_server \ $cross_arg \ "$PWD" "$source_path" diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index bfec8a881a..5c73ffdd6b 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -701,7 +701,7 @@ vu_add_mem_reg(VuDev *dev, VhostUserMsg *vmsg) { return false; } - DPRINT("Adding region: %d\n", dev->nregions); + DPRINT("Adding region: %u\n", dev->nregions); DPRINT(" guest_phys_addr: 0x%016"PRIx64"\n", msg_region->guest_phys_addr); DPRINT(" memory_size: 0x%016"PRIx64"\n", @@ -848,7 +848,7 @@ vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) VhostUserMemory m = vmsg->payload.memory, *memory = &m; dev->nregions = memory->nregions; - DPRINT("Nregions: %d\n", memory->nregions); + DPRINT("Nregions: %u\n", memory->nregions); for (i = 0; i < dev->nregions; i++) { void *mmap_addr; VhostUserMemoryRegion *msg_region = &memory->regions[i]; @@ -938,7 +938,7 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg) return vu_set_mem_table_exec_postcopy(dev, vmsg); } - DPRINT("Nregions: %d\n", memory->nregions); + DPRINT("Nregions: %u\n", memory->nregions); for (i = 0; i < dev->nregions; i++) { void *mmap_addr; VhostUserMemoryRegion *msg_region = &memory->regions[i]; @@ -1049,8 +1049,8 @@ vu_set_vring_num_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int num = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.num: %d\n", num); + DPRINT("State.index: %u\n", index); + DPRINT("State.num: %u\n", num); dev->vq[index].vring.num = num; return false; @@ -1105,8 +1105,8 @@ vu_set_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int num = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.num: %d\n", num); + DPRINT("State.index: %u\n", index); + DPRINT("State.num: %u\n", num); dev->vq[index].shadow_avail_idx = dev->vq[index].last_avail_idx = num; return false; @@ -1117,7 +1117,7 @@ vu_get_vring_base_exec(VuDev *dev, VhostUserMsg *vmsg) { unsigned int index = vmsg->payload.state.index; - DPRINT("State.index: %d\n", index); + DPRINT("State.index: %u\n", index); vmsg->payload.state.num = dev->vq[index].last_avail_idx; vmsg->size = sizeof(vmsg->payload.state); @@ -1478,8 +1478,8 @@ vu_set_vring_enable_exec(VuDev *dev, VhostUserMsg *vmsg) unsigned int index = vmsg->payload.state.index; unsigned int enable = vmsg->payload.state.num; - DPRINT("State.index: %d\n", index); - DPRINT("State.enable: %d\n", enable); + DPRINT("State.index: %u\n", index); + DPRINT("State.enable: %u\n", enable); if (index >= dev->max_queues) { vu_panic(dev, "Invalid vring_enable index: %u", index); @@ -1728,7 +1728,7 @@ vu_handle_vring_kick(VuDev *dev, VhostUserMsg *vmsg) return false; } - DPRINT("Got kick message: handler:%p idx:%d\n", + DPRINT("Got kick message: handler:%p idx:%u\n", dev->vq[index].handler, index); if (!dev->vq[index].started) { @@ -1772,7 +1772,7 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg) DPRINT("Request: %s (%d)\n", vu_request_to_string(vmsg->request), vmsg->request); DPRINT("Flags: 0x%x\n", vmsg->flags); - DPRINT("Size: %d\n", vmsg->size); + DPRINT("Size: %u\n", vmsg->size); if (vmsg->fd_num) { int i; diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index a1539dbb69..7d47f1364a 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -136,7 +136,7 @@ typedef struct VhostUserMemory { } VhostUserMemory; typedef struct VhostUserMemRegMsg { - uint32_t padding; + uint64_t padding; VhostUserMemoryRegion region; } VhostUserMemRegMsg; diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c index caad88637e..dc981bf945 100644 --- a/contrib/vhost-user-blk/vhost-user-blk.c +++ b/contrib/vhost-user-blk/vhost-user-blk.c @@ -476,7 +476,7 @@ static int unix_sock_new(char *unix_fn) assert(unix_fn); sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock <= 0) { + if (sock < 0) { perror("socket"); return -1; } diff --git a/contrib/vhost-user-scsi/vhost-user-scsi.c b/contrib/vhost-user-scsi/vhost-user-scsi.c index 3c912384e9..0f9ba4b2a2 100644 --- a/contrib/vhost-user-scsi/vhost-user-scsi.c +++ b/contrib/vhost-user-scsi/vhost-user-scsi.c @@ -320,7 +320,7 @@ static int unix_sock_new(char *unix_fn) assert(unix_fn); sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock <= 0) { + if (sock < 0) { perror("socket"); return -1; } diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst index 988f154144..6d4025ba6a 100644 --- a/docs/interop/vhost-user.rst +++ b/docs/interop/vhost-user.rst @@ -131,6 +131,23 @@ A region is: :mmap offset: 64-bit offset where region starts in the mapped memory +Single memory region description +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ++---------+---------------+------+--------------+-------------+ +| padding | guest address | size | user address | mmap offset | ++---------+---------------+------+--------------+-------------+ + +:padding: 64-bit + +:guest address: a 64-bit guest address of the region + +:size: a 64-bit size + +:user address: a 64-bit user address + +:mmap offset: 64-bit offset where region starts in the mapped memory + Log description ^^^^^^^^^^^^^^^ @@ -1281,7 +1298,7 @@ Master message types ``VHOST_USER_ADD_MEM_REG`` :id: 37 :equivalent ioctl: N/A - :slave payload: memory region + :slave payload: single memory region description When the ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol feature has been successfully negotiated, this message is submitted @@ -1296,7 +1313,7 @@ Master message types ``VHOST_USER_REM_MEM_REG`` :id: 38 :equivalent ioctl: N/A - :slave payload: memory region + :slave payload: single memory region description When the ``VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS`` protocol feature has been successfully negotiated, this message is submitted diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7d022eeefd..e69a9009cf 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -6,6 +6,7 @@ config ARM_VIRT imply VFIO_PLATFORM imply VFIO_XGMAC imply TPM_TIS_SYSBUS + select ARM_GIC select ACPI select ARM_SMMUV3 select GPIO_KEY diff --git a/hw/block/nand.c b/hw/block/nand.c index bcceb64ebb..1d7a48a2ec 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -449,6 +449,7 @@ static void nand_class_init(ObjectClass *klass, void *data) dc->reset = nand_reset; dc->vmsd = &vmstate_nand; device_class_set_props(dc, nand_properties); + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } static const TypeInfo nand_info = { diff --git a/hw/core/register.c b/hw/core/register.c index 31038bd7cc..3600ef5bde 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -258,10 +258,6 @@ static RegisterInfoArray *register_init_block(DeviceState *owner, int index = rae[i].addr / data_size; RegisterInfo *r = &ri[index]; - if (data + data_size * index == 0 || !&rae[i]) { - continue; - } - /* Init the register, this will zero it. */ object_initialize((void *)r, sizeof(*r), TYPE_REGISTER); diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c index 023165b2a3..cb3a431cfd 100644 --- a/hw/display/ads7846.c +++ b/hw/display/ads7846.c @@ -163,10 +163,12 @@ static void ads7846_realize(SSISlave *d, Error **errp) static void ads7846_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); SSISlaveClass *k = SSI_SLAVE_CLASS(klass); k->realize = ads7846_realize; k->transfer = ads7846_transfer; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo ads7846_info = { diff --git a/hw/display/ssd0323.c b/hw/display/ssd0323.c index 17d4b32ae3..cbfd21dfd5 100644 --- a/hw/display/ssd0323.c +++ b/hw/display/ssd0323.c @@ -370,6 +370,7 @@ static void ssd0323_class_init(ObjectClass *klass, void *data) k->transfer = ssd0323_transfer; k->cs_polarity = SSI_CS_HIGH; dc->vmsd = &vmstate_ssd0323; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } static const TypeInfo ssd0323_info = { diff --git a/hw/input/ps2.c b/hw/input/ps2.c index f8746d2f52..72cdb80ae1 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -33,12 +33,6 @@ #include "trace.h" -/* debug PC keyboard */ -//#define DEBUG_KBD - -/* debug PC keyboard : only mouse */ -//#define DEBUG_MOUSE - /* Keyboard Commands */ #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ #define KBD_CMD_ECHO 0xEE @@ -790,9 +784,6 @@ void ps2_write_mouse(void *opaque, int val) PS2MouseState *s = (PS2MouseState *)opaque; trace_ps2_write_mouse(opaque, val); -#ifdef DEBUG_MOUSE - printf("kbd: write mouse 0x%02x\n", val); -#endif switch(s->common.write_cmd) { default: case -1: diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index 7e6723f343..eae0f9b598 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -185,6 +185,7 @@ static void max111x_class_init(ObjectClass *klass, void *data) k->transfer = max111x_transfer; dc->reset = max111x_reset; dc->vmsd = &vmstate_max111x; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); } static const TypeInfo max111x_info = { diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c index b47120492a..d299d9b21b 100644 --- a/hw/misc/tmp105.c +++ b/hw/misc/tmp105.c @@ -41,16 +41,40 @@ static void tmp105_alarm_update(TMP105State *s) return; } - if ((s->config >> 1) & 1) { /* TM */ - if (s->temperature >= s->limit[1]) - s->alarm = 1; - else if (s->temperature < s->limit[0]) - s->alarm = 1; + if (s->config >> 1 & 1) { + /* + * TM == 1 : Interrupt mode. We signal Alert when the + * temperature rises above T_high, and expect the guest to clear + * it (eg by reading a device register). + */ + if (s->detect_falling) { + if (s->temperature < s->limit[0]) { + s->alarm = 1; + s->detect_falling = false; + } + } else { + if (s->temperature >= s->limit[1]) { + s->alarm = 1; + s->detect_falling = true; + } + } } else { - if (s->temperature >= s->limit[1]) - s->alarm = 1; - else if (s->temperature < s->limit[0]) - s->alarm = 0; + /* + * TM == 0 : Comparator mode. We signal Alert when the temperature + * rises above T_high, and stop signalling it when the temperature + * falls below T_low. + */ + if (s->detect_falling) { + if (s->temperature < s->limit[0]) { + s->alarm = 0; + s->detect_falling = false; + } + } else { + if (s->temperature >= s->limit[1]) { + s->alarm = 1; + s->detect_falling = true; + } + } } tmp105_interrupt_update(s); @@ -197,6 +221,29 @@ static int tmp105_post_load(void *opaque, int version_id) return 0; } +static bool detect_falling_needed(void *opaque) +{ + TMP105State *s = opaque; + + /* + * We only need to migrate the detect_falling bool if it's set; + * for migration from older machines we assume that it is false + * (ie temperature is not out of range). + */ + return s->detect_falling; +} + +static const VMStateDescription vmstate_tmp105_detect_falling = { + .name = "TMP105/detect-falling", + .version_id = 1, + .minimum_version_id = 1, + .needed = detect_falling_needed, + .fields = (VMStateField[]) { + VMSTATE_BOOL(detect_falling, TMP105State), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_tmp105 = { .name = "TMP105", .version_id = 0, @@ -212,6 +259,10 @@ static const VMStateDescription vmstate_tmp105 = { VMSTATE_UINT8(alarm, TMP105State), VMSTATE_I2C_SLAVE(i2c, TMP105State), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_tmp105_detect_falling, + NULL } }; @@ -224,6 +275,10 @@ static void tmp105_reset(I2CSlave *i2c) s->config = 0; s->faults = tmp105_faultq[(s->config >> 3) & 3]; s->alarm = 0; + s->detect_falling = false; + + s->limit[0] = 0x4b00; /* T_LOW, 75 degrees C */ + s->limit[1] = 0x5000; /* T_HIGH, 80 degrees C */ tmp105_interrupt_update(s); } diff --git a/hw/misc/tmp105.h b/hw/misc/tmp105.h index e5198fce80..7c97071ad7 100644 --- a/hw/misc/tmp105.h +++ b/hw/misc/tmp105.h @@ -43,6 +43,13 @@ struct TMP105State { int16_t limit[2]; int faults; uint8_t alarm; + /* + * The TMP105 initially looks for a temperature rising above T_high; + * once this is detected, the condition it looks for next is the + * temperature falling below T_low. This flag is false when initially + * looking for T_high, true when looking for T_low. + */ + bool detect_falling; }; #endif diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index e859534eaf..90841ad791 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -461,6 +461,25 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) } error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); break; +#ifdef CONFIG_LINUX + /* These errno mapping are specific to Linux. For more information: + * - scsi_decide_disposition in drivers/scsi/scsi_error.c + * - scsi_result_to_blk_status in drivers/scsi/scsi_lib.c + * - blk_errors[] in block/blk-core.c + */ + case EBADE: + /* DID_NEXUS_FAILURE -> BLK_STS_NEXUS. */ + scsi_req_complete(&r->req, RESERVATION_CONFLICT); + break; + case ENODATA: + /* DID_MEDIUM_ERROR -> BLK_STS_MEDIUM. */ + scsi_check_condition(r, SENSE_CODE(READ_ERROR)); + break; + case EREMOTEIO: + /* DID_TARGET_FAILURE -> BLK_STS_TARGET. */ + scsi_req_complete(&r->req, HARDWARE_ERROR); + break; +#endif case ENOMEDIUM: scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); break; diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 3091382614..1842c03797 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -389,10 +389,17 @@ static const uint8_t sd_csd_rw_mask[16] = { static void sd_set_csd(SDState *sd, uint64_t size) { - uint32_t csize = (size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1; + int hwblock_shift = HWBLOCK_SHIFT; + uint32_t csize; uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1; uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1; + /* To indicate 2 GiB card, BLOCK_LEN shall be 1024 bytes */ + if (size == SDSC_MAX_CAPACITY) { + hwblock_shift += 1; + } + csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1; + if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */ sd->csd[0] = 0x00; /* CSD structure */ sd->csd[1] = 0x26; /* Data read access-time-1 */ @@ -400,7 +407,7 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */ sd->csd[4] = 0x5f; /* Card Command Classes */ sd->csd[5] = 0x50 | /* Max. read data block length */ - HWBLOCK_SHIFT; + hwblock_shift; sd->csd[6] = 0xe0 | /* Partial block for read allowed */ ((csize >> 10) & 0x03); sd->csd[7] = 0x00 | /* Device size */ @@ -414,9 +421,9 @@ static void sd_set_csd(SDState *sd, uint64_t size) sd->csd[11] = 0x00 | /* Write protect group size */ ((sectsize << 7) & 0x80) | wpsize; sd->csd[12] = 0x90 | /* Write speed factor */ - (HWBLOCK_SHIFT >> 2); + (hwblock_shift >> 2); sd->csd[13] = 0x20 | /* Max. write data block length */ - ((HWBLOCK_SHIFT << 6) & 0xc0); + ((hwblock_shift << 6) & 0xc0); sd->csd[14] = 0x00; /* File format group */ } else { /* SDHC */ size /= 512 * KiB; diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index 08ee3ca76c..439053acd2 100644 --- a/hw/timer/exynos4210_mct.c +++ b/hw/timer/exynos4210_mct.c @@ -537,7 +537,7 @@ static void exynos4210_gcomp_raise_irq(void *opaque, uint32_t id) /* If CSTAT is pending and IRQ is enabled */ if ((s->reg.int_cstat & G_INT_CSTAT_COMP(id)) && (s->reg.int_enb & G_INT_ENABLE(id))) { - DPRINTF("gcmp timer[%d] IRQ\n", id); + DPRINTF("gcmp timer[%u] IRQ\n", id); qemu_irq_raise(s->irq[id]); } } @@ -1003,7 +1003,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s) MCT_CFG_GET_DIVIDER(s->reg_mct_cfg)); if (freq != s->freq) { - DPRINTF("freq=%dHz\n", s->freq); + DPRINTF("freq=%uHz\n", s->freq); /* global timer */ tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq); diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c index 4fa3d87396..de181428b4 100644 --- a/hw/timer/exynos4210_pwm.c +++ b/hw/timer/exynos4210_pwm.c @@ -169,7 +169,7 @@ static void exynos4210_pwm_update_freq(Exynos4210PWMState *s, uint32_t id) if (freq != s->timer[id].freq) { ptimer_set_freq(s->timer[id].ptimer, s->timer[id].freq); - DPRINTF("freq=%dHz\n", s->timer[id].freq); + DPRINTF("freq=%uHz\n", s->timer[id].freq); } } @@ -183,14 +183,14 @@ static void exynos4210_pwm_tick(void *opaque) uint32_t id = s->id; bool cmp; - DPRINTF("timer %d tick\n", id); + DPRINTF("timer %u tick\n", id); /* set irq status */ p->reg_tint_cstat |= TINT_CSTAT_STATUS(id); /* raise IRQ */ if (p->reg_tint_cstat & TINT_CSTAT_ENABLE(id)) { - DPRINTF("timer %d IRQ\n", id); + DPRINTF("timer %u IRQ\n", id); qemu_irq_raise(p->timer[id].irq); } @@ -202,7 +202,7 @@ static void exynos4210_pwm_tick(void *opaque) } if (cmp) { - DPRINTF("auto reload timer %d count to %x\n", id, + DPRINTF("auto reload timer %u count to %x\n", id, p->timer[id].reg_tcntb); ptimer_set_count(p->timer[id].ptimer, p->timer[id].reg_tcntb); ptimer_run(p->timer[id].ptimer, 1); diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 9c5b4f7fbc..2fdd5daf74 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -149,7 +149,7 @@ typedef struct VhostUserMemory { } VhostUserMemory; typedef struct VhostUserMemRegMsg { - uint32_t padding; + uint64_t padding; VhostUserMemoryRegion region; } VhostUserMemRegMsg; @@ -800,8 +800,7 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev, uint64_t shadow_pcb[VHOST_USER_MAX_RAM_SLOTS] = {}; int nr_add_reg, nr_rem_reg; - msg->hdr.size = sizeof(msg->payload.mem_reg.padding) + - sizeof(VhostUserMemoryRegion); + msg->hdr.size = sizeof(msg->payload.mem_reg); /* Find the regions which need to be removed or added. */ scrub_shadow_regions(dev, add_reg, &nr_add_reg, rem_reg, &nr_rem_reg, diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index 1d3e4c24e4..8b01c38040 100644 --- a/include/qemu/bswap.h +++ b/include/qemu/bswap.h @@ -169,12 +169,6 @@ CPU_CONVERT(le, 16, uint16_t) CPU_CONVERT(le, 32, uint32_t) CPU_CONVERT(le, 64, uint64_t) -/* len must be one of 1, 2, 4 */ -static inline uint32_t qemu_bswap_len(uint32_t value, int len) -{ - return bswap32(value) >> (32 - 8 * len); -} - /* * Same as cpu_to_le{16,32}, except that gcc will figure the result is * a compile-time constant if you pass in a constant. So this can be diff --git a/meson.build b/meson.build index 132bc49782..7ddf983ff7 100644 --- a/meson.build +++ b/meson.build @@ -756,6 +756,19 @@ statx_test = ''' has_statx = cc.links(statx_test) +have_vhost_user_blk_server = (targetos == 'linux' and + 'CONFIG_VHOST_USER' in config_host) + +if get_option('vhost_user_blk_server').enabled() + if targetos != 'linux' + error('vhost_user_blk_server requires linux') + elif 'CONFIG_VHOST_USER' not in config_host + error('vhost_user_blk_server requires vhost-user support') + endif +elif get_option('vhost_user_blk_server').disabled() or not have_system + have_vhost_user_blk_server = false +endif + ################# # config-host.h # ################# @@ -780,6 +793,7 @@ config_host_data.set('CONFIG_MPATH_NEW_API', mpathpersist_new_api) config_host_data.set('CONFIG_CURSES', curses.found()) config_host_data.set('CONFIG_SDL', sdl.found()) config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) +config_host_data.set('CONFIG_VHOST_USER_BLK_SERVER', have_vhost_user_blk_server) config_host_data.set('CONFIG_VNC', vnc.found()) config_host_data.set('CONFIG_VNC_JPEG', jpeg.found()) config_host_data.set('CONFIG_VNC_PNG', png.found()) @@ -794,6 +808,8 @@ config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0] config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1]) config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2]) +config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h')) + ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST'] strings = ['HOST_DSOSUF', 'CONFIG_IASL'] @@ -2109,6 +2125,7 @@ summary_info += {'vhost-crypto support': config_host.has_key('CONFIG_VHOST_CRYPT summary_info += {'vhost-scsi support': config_host.has_key('CONFIG_VHOST_SCSI')} summary_info += {'vhost-vsock support': config_host.has_key('CONFIG_VHOST_VSOCK')} summary_info += {'vhost-user support': config_host.has_key('CONFIG_VHOST_USER')} +summary_info += {'vhost-user-blk server support': have_vhost_user_blk_server} summary_info += {'vhost-user-fs support': config_host.has_key('CONFIG_VHOST_USER_FS')} summary_info += {'vhost-vdpa support': config_host.has_key('CONFIG_VHOST_VDPA')} summary_info += {'Trace backends': config_host['TRACE_BACKENDS']} diff --git a/meson_options.txt b/meson_options.txt index b4f1801875..f6f64785fe 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -64,6 +64,8 @@ option('xkbcommon', type : 'feature', value : 'auto', description: 'xkbcommon support') option('virtiofsd', type: 'feature', value: 'auto', description: 'build virtiofs daemon (virtiofsd)') +option('vhost_user_blk_server', type: 'feature', value: 'auto', + description: 'build vhost-user-blk server') option('capstone', type: 'combo', value: 'auto', choices: ['disabled', 'enabled', 'auto', 'system', 'internal'], diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index 60629ef160..1b2141ab4b 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -19,7 +19,7 @@ #ifndef _WIN32 #include <sys/ioctl.h> #endif -#if defined(__sun__) || defined(__HAIKU__) +#ifdef HAVE_SYS_IOCCOM_H #include <sys/ioccom.h> #endif diff --git a/nbd/server.c b/nbd/server.c index d145e1a690..613ed2634a 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -2129,8 +2129,8 @@ static void bitmap_to_extents(BdrvDirtyBitmap *bitmap, } if (!full) { - /* last non dirty extent */ - nbd_extent_array_add(es, end - start, 0); + /* last non dirty extent, nothing to do if array is now full */ + (void) nbd_extent_array_add(es, end - start, 0); } bdrv_dirty_bitmap_unlock(bitmap); diff --git a/qapi/char.json b/qapi/char.json index b4d66ec90b..43486d1daa 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -321,8 +321,7 @@ # Configuration info for stdio chardevs. # # @signal: Allow signals (such as SIGINT triggered by ^C) -# be delivered to qemu. Default: true in -nographic mode, -# false otherwise. +# be delivered to qemu. Default: true. # # Since: 1.5 ## diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 12c1ba5ef7..c089e38120 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -1285,6 +1285,7 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk) g_debug("failed to list entries in %s", deps_dir); return; } + disk->has_dependencies = true; while ((dep = g_dir_read_name(dp_deps)) != NULL) { g_autofree char *dep_dir = NULL; strList *dep_item = NULL; @@ -1297,8 +1298,8 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk) g_debug(" adding dependent device: %s", dev_name); dep_item = g_new0(strList, 1); dep_item->value = dev_name; - dep_item->next = disk->dependents; - disk->dependents = dep_item; + dep_item->next = disk->dependencies; + disk->dependencies = dep_item; } } g_dir_close(dp_deps); @@ -1351,8 +1352,9 @@ static GuestDiskInfoList *get_disk_partitions( partition->name = dev_name; partition->partition = true; /* Add parent disk as dependent for easier tracking of hierarchy */ - partition->dependents = g_new0(strList, 1); - partition->dependents->value = g_strdup(disk_dev); + partition->dependencies = g_new0(strList, 1); + partition->dependencies->value = g_strdup(disk_dev); + partition->has_dependencies = true; item = g_new0(GuestDiskInfoList, 1); item->value = partition; diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 6ca85f995f..3b3d1d0bd9 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -870,9 +870,9 @@ # # @name: device node (Linux) or device UNC (Windows) # @partition: whether this is a partition or disk -# @dependents: list of dependent devices; e.g. for LVs of the LVM this will -# hold the list of PVs, for LUKS encrypted volume this will -# contain the disk where the volume is placed. (Linux) +# @dependencies: list of device dependencies; e.g. for LVs of the LVM this will +# hold the list of PVs, for LUKS encrypted volume this will +# contain the disk where the volume is placed. (Linux) # @address: disk address information (only for non-virtual devices) # @alias: optional alias assigned to the disk, on Linux this is a name assigned # by device mapper @@ -880,7 +880,7 @@ # Since 5.2 ## { 'struct': 'GuestDiskInfo', - 'data': {'name': 'str', 'partition': 'bool', 'dependents': ['str'], + 'data': {'name': 'str', 'partition': 'bool', '*dependencies': ['str'], '*address': 'GuestDiskAddress', '*alias': 'str'} } ## diff --git a/qobject/json-parser.c b/qobject/json-parser.c index d083810d37..c0f521b56b 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -257,8 +257,9 @@ static JSONToken *parser_context_peek_token(JSONParserContext *ctxt) */ static int parse_pair(JSONParserContext *ctxt, QDict *dict) { + QObject *key_obj = NULL; + QString *key; QObject *value; - QString *key = NULL; JSONToken *peek, *token; peek = parser_context_peek_token(ctxt); @@ -267,7 +268,8 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict) goto out; } - key = qobject_to(QString, parse_value(ctxt)); + key_obj = parse_value(ctxt); + key = qobject_to(QString, key_obj); if (!key) { parse_error(ctxt, peek, "key is not a string in object"); goto out; @@ -297,13 +299,11 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict) qdict_put_obj(dict, qstring_get_str(key), value); - qobject_unref(key); - + qobject_unref(key_obj); return 0; out: - qobject_unref(key); - + qobject_unref(key_obj); return -1; } diff --git a/softmmu/memory.c b/softmmu/memory.c index 71951fe4dc..aa393f1bb0 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1806,7 +1806,10 @@ bool memory_region_is_ram_device(MemoryRegion *mr) uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr) { uint8_t mask = mr->dirty_log_mask; - if (global_dirty_log && (mr->ram_block || memory_region_is_iommu(mr))) { + RAMBlock *rb = mr->ram_block; + + if (global_dirty_log && ((rb && qemu_ram_is_migratable(rb)) || + memory_region_is_iommu(mr))) { mask |= (1 << DIRTY_MEMORY_MIGRATION); } return mask; diff --git a/stubs/ram-block.c b/stubs/ram-block.c index 73c0a3ee08..108197683b 100644 --- a/stubs/ram-block.c +++ b/stubs/ram-block.c @@ -1,6 +1,7 @@ #include "qemu/osdep.h" #include "exec/ramlist.h" #include "exec/cpu-common.h" +#include "exec/memory.h" void *qemu_ram_get_host_addr(RAMBlock *rb) { @@ -29,3 +30,8 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque) { return 0; } + +int ram_block_discard_disable(bool state) +{ + return 0; +} diff --git a/target/i386/helper.c b/target/i386/helper.c index 516ce0cad8..034f46bcc2 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -908,16 +908,14 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) return; } - if (recursive) { - need_reset = true; - msg = g_strdup_printf("CPU %d: Previous MCE still in progress, " - "raising triple fault", cs->cpu_index); - } - if (!(cenv->cr[4] & CR4_MCE_MASK)) { need_reset = true; msg = g_strdup_printf("CPU %d: MCE capability is not enabled, " "raising triple fault", cs->cpu_index); + } else if (recursive) { + need_reset = true; + msg = g_strdup_printf("CPU %d: Previous MCE still in progress, " + "raising triple fault", cs->cpu_index); } if (need_reset) { diff --git a/target/i386/kvm.c b/target/i386/kvm.c index cf46259534..a2934dda02 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -1820,12 +1820,14 @@ int kvm_arch_init_vcpu(CPUState *cs) env->nested_state = g_malloc0(max_nested_state_len); env->nested_state->size = max_nested_state_len; - env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; if (cpu_has_vmx(env)) { - vmx_hdr = &env->nested_state->hdr.vmx; - vmx_hdr->vmxon_pa = -1ull; - vmx_hdr->vmcs12_pa = -1ull; + env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; + vmx_hdr = &env->nested_state->hdr.vmx; + vmx_hdr->vmxon_pa = -1ull; + vmx_hdr->vmcs12_pa = -1ull; + } else { + env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; } } } diff --git a/target/microblaze/mmu.c b/target/microblaze/mmu.c index 2baaef7545..1e426963ba 100644 --- a/target/microblaze/mmu.c +++ b/target/microblaze/mmu.c @@ -234,7 +234,8 @@ void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) unsigned int i; qemu_log_mask(CPU_LOG_MMU, - "%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]); + "%s rn=%d=%x old=%x\n", __func__, rn, v, + rn < 3 ? env->mmu.regs[rn] : env->mmu.regs[MMU_R_TLBX]); if (cpu->cfg.mmu < 2 || !cpu->cfg.mmu_tlb_access) { qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index d9fe6c5948..41390d046f 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -176,9 +176,6 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) case TO_SPR(10, 1): /* TTCR */ cpu_openrisc_count_set(cpu, rb); - if (env->ttmr & TIMER_NONE) { - return; - } cpu_openrisc_timer_update(cpu); break; #endif diff --git a/tests/check-qjson.c b/tests/check-qjson.c index 07a773e653..9a02079099 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -1415,6 +1415,14 @@ static void invalid_dict_comma(void) g_assert(obj == NULL); } +static void invalid_dict_key(void) +{ + Error *err = NULL; + QObject *obj = qobject_from_json("{32:'abc'}", &err); + error_free_or_abort(&err); + g_assert(obj == NULL); +} + static void unterminated_literal(void) { Error *err = NULL; @@ -1500,6 +1508,7 @@ int main(int argc, char **argv) g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma); g_test_add_func("/errors/invalid_array_comma", invalid_array_comma); g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma); + g_test_add_func("/errors/invalid_dict_key", invalid_dict_key); g_test_add_func("/errors/unterminated/literal", unterminated_literal); g_test_add_func("/errors/limits/nesting", limits_nesting); g_test_add_func("/errors/multiple_values", multiple_values); diff --git a/tests/keys/vagrant b/tests/keys/vagrant new file mode 100644 index 0000000000..7d6a083909 --- /dev/null +++ b/tests/keys/vagrant @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI +w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP +kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2 +hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO +Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW +yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd +ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1 +Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf +TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK +iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A +sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf +4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP +cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk +EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN +CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX +3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG +YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj +3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+ +dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz +6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC +P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF +llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ +kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH ++vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ +NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s= +-----END RSA PRIVATE KEY----- diff --git a/tests/keys/vagrant.pub b/tests/keys/vagrant.pub new file mode 100644 index 0000000000..b8d012d787 --- /dev/null +++ b/tests/keys/vagrant.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== well-known vagrant key for qemu-test, do not use on any machine exposed to an external network diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081 index 537d40dfd5..4e19972931 100755 --- a/tests/qemu-iotests/081 +++ b/tests/qemu-iotests/081 @@ -42,18 +42,20 @@ _supported_fmt raw _supported_proto file _supported_os Linux _require_drivers quorum +_require_devices virtio-scsi do_run_qemu() { - echo Testing: "$@" | _filter_imgfmt + echo Testing: "$@" $QEMU -nographic -qmp stdio -serial none "$@" echo } run_qemu() { - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\ - | _filter_qemu_io | _filter_generated_node_ids + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_imgfmt | _filter_qemu \ + | _filter_qmp | _filter_qemu_io \ + | _filter_generated_node_ids } quorum="driver=raw,file.driver=quorum,file.vote-threshold=2" @@ -155,6 +157,59 @@ echo "== checking that quorum has corrected the corrupted file ==" $QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io echo +echo "== using quorum rewrite corrupted mode without WRITE permission ==" + +# The same as above, but this time, do it on a quorum node whose only +# parent will not take the WRITE permission + +echo '-- corrupting --' +# Only corrupt a portion: The guest device (scsi-hd on virtio-scsi) +# will read some data (looking for a partition table to guess the +# disk's geometry), which would trigger a quorum mismatch if the +# beginning of the image was corrupted. The subsequent +# QUORUM_REPORT_BAD event would be suppressed (because at that point, +# there cannot have been a qmp_capabilities on the monitor). Because +# that event is rate-limited, the next QUORUM_REPORT_BAD that happens +# thanks to our qemu-io read (which should trigger a mismatch) would +# then be delayed past the VM quit and not appear in the output. +# So we keep the first 1M intact to see a QUORUM_REPORT_BAD resulting +# from the qemu-io invocation. +$QEMU_IO -c "write -P 0x42 1M 1M" "$TEST_DIR/2.raw" | _filter_qemu_io + +# Fix the corruption (on a read-only quorum node, i.e. without taking +# the WRITE permission on it -- its child nodes need to be R/W OTOH, +# so that rewrite-corrupted works) +echo +echo '-- running quorum --' +run_qemu \ + -blockdev file,node-name=file1,filename="$TEST_DIR/1.raw" \ + -blockdev file,node-name=file2,filename="$TEST_DIR/2.raw" \ + -blockdev file,node-name=file3,filename="$TEST_DIR/3.raw" \ + -blockdev '{ + "driver": "quorum", + "node-name": "quorum", + "read-only": true, + "vote-threshold": 2, + "rewrite-corrupted": true, + "children": [ "file1", "file2", "file3" ] + }' \ + -device virtio-scsi,id=scsi \ + -device scsi-hd,id=quorum-drive,bus=scsi.0,drive=quorum \ + <<EOF +{ "execute": "qmp_capabilities" } +{ + "execute": "human-monitor-command", + "arguments": { + "command-line": 'qemu-io -d quorum-drive "read -P 0x32 0 $size"' + } +} +{ "execute": "quit" } +EOF + +echo '-- checking that the image has been corrected --' +$QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io + +echo echo "== breaking quorum ==" $QEMU_IO -c "write -P 0x41 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out index 04091b64e5..1974262fac 100644 --- a/tests/qemu-iotests/081.out +++ b/tests/qemu-iotests/081.out @@ -47,6 +47,33 @@ read 10485760/10485760 bytes at offset 0 read 10485760/10485760 bytes at offset 0 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== using quorum rewrite corrupted mode without WRITE permission == +-- corrupting -- +wrote 1048576/1048576 bytes at offset 1048576 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +-- running quorum -- +Testing: -blockdev file,node-name=file1,filename=TEST_DIR/1.IMGFMT -blockdev file,node-name=file2,filename=TEST_DIR/2.IMGFMT -blockdev file,node-name=file3,filename=TEST_DIR/3.IMGFMT -blockdev { + "driver": "quorum", + "node-name": "quorum", + "read-only": true, + "vote-threshold": 2, + "rewrite-corrupted": true, + "children": [ "file1", "file2", "file3" ] + } -device virtio-scsi,id=scsi -device scsi-hd,id=quorum-drive,bus=scsi.0,drive=quorum +QMP_VERSION +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "QUORUM_REPORT_BAD", "data": {"node-name": "file2", "sectors-count": 20480, "sector-num": 0, "type": "read"}} +read 10485760/10485760 bytes at offset 0 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{"return": ""} +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} + +-- checking that the image has been corrected -- +read 10485760/10485760 bytes at offset 0 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + == breaking quorum == wrote 10485760/10485760 bytes at offset 0 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py index 78f42c4214..6e11ef89b8 100755 --- a/tests/qemu-iotests/nbd-fault-injector.py +++ b/tests/qemu-iotests/nbd-fault-injector.py @@ -227,7 +227,7 @@ def parse_config(config): def load_rules(filename): config = configparser.RawConfigParser() with open(filename, 'rt') as f: - config.readfp(f, filename) + config.read_file(f, filename) return parse_config(config) def open_socket(path): diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include index 61f893ffdc..e94d95ec54 100644 --- a/tests/vm/Makefile.include +++ b/tests/vm/Makefile.include @@ -4,7 +4,7 @@ EFI_AARCH64 = $(wildcard $(BUILD_DIR)/pc-bios/edk2-aarch64-code.fd) -IMAGES := freebsd netbsd openbsd centos fedora +IMAGES := freebsd netbsd openbsd centos fedora haiku.x86_64 ifneq ($(GENISOIMAGE),) IMAGES += ubuntu.i386 centos ifneq ($(EFI_AARCH64),) @@ -41,6 +41,7 @@ endif else @echo " (install genisoimage to build centos/ubuntu images)" endif + @echo " vm-build-haiku.x86_64 - Build QEMU in Haiku VM" @echo "" @echo " vm-build-all - Build QEMU in all VMs" @echo " vm-clean-all - Clean up VM images" diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py index 3fac20e929..00f1d5ca8d 100644 --- a/tests/vm/basevm.py +++ b/tests/vm/basevm.py @@ -44,6 +44,7 @@ DEFAULT_CONFIG = { 'machine' : 'pc', 'guest_user' : "qemu", 'guest_pass' : "qemupass", + 'root_user' : "root", 'root_pass' : "qemupass", 'ssh_key_file' : SSH_KEY_FILE, 'ssh_pub_key_file': SSH_PUB_KEY_FILE, @@ -245,13 +246,13 @@ class BaseVM(object): return self._ssh_do(self._config["guest_user"], cmd, False) def ssh_root(self, *cmd): - return self._ssh_do("root", cmd, False) + return self._ssh_do(self._config["root_user"], cmd, False) def ssh_check(self, *cmd): self._ssh_do(self._config["guest_user"], cmd, True) def ssh_root_check(self, *cmd): - self._ssh_do("root", cmd, True) + self._ssh_do(self._config["root_user"], cmd, True) def build_image(self, img): raise NotImplementedError diff --git a/tests/vm/haiku.x86_64 b/tests/vm/haiku.x86_64 new file mode 100755 index 0000000000..37af48bf1b --- /dev/null +++ b/tests/vm/haiku.x86_64 @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# +# Haiku VM image +# +# Copyright 2020 Haiku, Inc. +# +# Authors: +# Alexander von Gluck IV <kallisti5@unixzen.com> +# +# This code is licensed under the GPL version 2 or later. See +# the COPYING file in the top-level directory. +# + +import os +import re +import sys +import time +import socket +import subprocess +import basevm + +VAGRANT_KEY_FILE = os.path.join(os.path.dirname(__file__), + "..", "keys", "vagrant") + +VAGRANT_PUB_KEY_FILE = os.path.join(os.path.dirname(__file__), + "..", "keys", "vagrant.pub") + +HAIKU_CONFIG = { + 'cpu' : "max", + 'machine' : 'pc', + 'guest_user' : "vagrant", + 'guest_pass' : "", + 'root_user' : "vagrant", + 'root_pass' : "", + 'ssh_key_file' : VAGRANT_KEY_FILE, + 'ssh_pub_key_file': VAGRANT_PUB_KEY_FILE, + 'memory' : "4G", + 'extra_args' : [], + 'qemu_args' : "-device VGA", + 'dns' : "", + 'ssh_port' : 0, + 'install_cmds' : "", + 'boot_dev_type' : "block", + 'ssh_timeout' : 1, +} + +class HaikuVM(basevm.BaseVM): + name = "haiku" + arch = "x86_64" + + link = "https://app.vagrantup.com/haiku-os/boxes/r1beta2-x86_64/versions/20200702/providers/libvirt.box" + csum = "41c38b316e0cbdbc66b5dbaf3612b866700a4f35807cb1eb266a5bf83e9e68d5" + + poweroff = "shutdown" + + requirements = [ + "devel:libbz2", + "devel:libcapstone", + "devel:libcurl", + "devel:libfdt", + "devel:libgcrypt", + "devel:libgl", + "devel:libglib_2.0", + "devel:libgnutls", + "devel:libgpg_error", + "devel:libintl", + "devel:libjpeg", + "devel:liblzo2", + "devel:libncursesw", + "devel:libnettle", + "devel:libpixman_1", + "devel:libpng16", + "devel:libsdl2_2.0", + "devel:libsnappy", + "devel:libssh2", + "devel:libtasn1", + "devel:libusb_1.0", + "devel:libz", + "ninja", + "setuptools_python3" + ] + + # https://dev.haiku-os.org/ticket/16512 virtio disk1 shows up as 0 (reversed order) + BUILD_SCRIPT = """ + set -e; + rm -rf /tmp/qemu-test.* + cd $(mktemp -d /tmp/qemu-test.XXXXXX); + mkdir src build; cd src; + tar -xf /dev/disk/virtual/virtio_block/0/raw; + mkdir -p /usr/bin + ln -s /boot/system/bin/env /usr/bin/env + cd ../build + ../src/configure --disable-slirp {configure_opts}; + make --output-sync -j{jobs} {target} {verbose}; + """ + + def build_image(self, img): + self.print_step("Downloading disk image") + tarball = self._download_with_cache(self.link, sha256sum=self.csum) + + self.print_step("Extracting disk image") + + subprocess.check_call(["tar", "xzf", tarball, "./box.img", "-O"], + stdout=open(img, 'wb')) + + self.print_step("Preparing disk image") + self.boot(img) + + # Wait for ssh to be available. + self.wait_ssh(wait_root=True, cmd="exit 0") + + # Install packages + self.ssh_root("pkgman install -y %s" % " ".join(self.requirements)) + self.graceful_shutdown() + + self.print_step("All done") + +if __name__ == "__main__": + sys.exit(basevm.main(HaikuVM, config=HAIKU_CONFIG)) diff --git a/tests/vm/netbsd b/tests/vm/netbsd index 447de9747d..596717cc76 100755 --- a/tests/vm/netbsd +++ b/tests/vm/netbsd @@ -22,8 +22,8 @@ class NetBSDVM(basevm.BaseVM): name = "netbsd" arch = "x86_64" - link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/images/NetBSD-9.0-amd64.iso" - csum = "34da4882ee61bdbf69f241195a8933dc800949d30b43fc6988da853d57fc2b8cac50cf97a0d2adaf93250b4e329d189c1a8b83c33bd515226f37745d50c33369" + link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.1/images/NetBSD-9.1-amd64.iso" + csum = "65bddc95945991c3b2021f9c8ded7f34c25f0a7611b7aa15a15fe23399e902307e926ae97fcd01dc1662ac67b5f6e4be643c6a2b581692ddcb616d30125066f9" size = "20G" pkgs = [ # tools @@ -38,7 +38,7 @@ class NetBSDVM(basevm.BaseVM): "bash", "gmake", "gsed", - "gettext", + "gettext-tools", # libs: crypto "gnutls", diff --git a/util/cutils.c b/util/cutils.c index 9498e28e1a..0b5073b330 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -891,10 +891,11 @@ char *freq_to_str(uint64_t freq_hz) double freq = freq_hz; size_t idx = 0; - while (freq >= 1000.0 && idx < ARRAY_SIZE(suffixes)) { + while (freq >= 1000.0) { freq /= 1000.0; idx++; } + assert(idx < ARRAY_SIZE(suffixes)); return g_strdup_printf("%0.3g %sHz", freq, suffixes[idx]); } diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c index c469beb061..2bec48e163 100644 --- a/util/vfio-helpers.c +++ b/util/vfio-helpers.c @@ -16,6 +16,7 @@ #include "qapi/error.h" #include "exec/ramlist.h" #include "exec/cpu-common.h" +#include "exec/memory.h" #include "trace.h" #include "qemu/error-report.h" #include "standard-headers/linux/pci_regs.h" @@ -494,8 +495,20 @@ QEMUVFIOState *qemu_vfio_open_pci(const char *device, Error **errp) int r; QEMUVFIOState *s = g_new0(QEMUVFIOState, 1); + /* + * VFIO may pin all memory inside mappings, resulting it in pinning + * all memory inside RAM blocks unconditionally. + */ + r = ram_block_discard_disable(true); + if (r) { + error_setg_errno(errp, -r, "Cannot set discarding of RAM broken"); + g_free(s); + return NULL; + } + r = qemu_vfio_init_pci(s, device, errp); if (r) { + ram_block_discard_disable(false); g_free(s); return NULL; } @@ -837,4 +850,5 @@ void qemu_vfio_close(QEMUVFIOState *s) close(s->device); close(s->group); close(s->container); + ram_block_discard_disable(false); } |