diff options
76 files changed, 1045 insertions, 371 deletions
@@ -1,6 +1,7 @@ -# This mailmap just translates the weird addresses from the original import into git -# into proper addresses so that they are counted properly in git shortlog output. -# +# This mailmap fixes up author names/addresses. + +# The first section translates weird addresses from the original git import +# into proper addresses so that they are counted properly by git shortlog. Andrzej Zaborowski <balrogg@gmail.com> balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162> Anthony Liguori <anthony@codemonkey.ws> aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com> @@ -15,10 +16,19 @@ Paul Burton <paul.burton@mips.com> <paul.burton@imgtec.com> Paul Burton <paul.burton@mips.com> <paul@archlinuxmips.org> Thiemo Seufer <ths@networkno.de> ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> malc <av1474@comtv.ru> malc <malc@c046a42c-6fe2-441c-8c8c-71466251a162> + # There is also a: # (no author) <(no author)@c046a42c-6fe2-441c-8c8c-71466251a162> # for the cvs2svn initialization commit e63c3dc74bf. -# + +# Next, translate a few commits where mailman rewrote the From: line due +# to strict SPF, although we prefer to avoid adding more entries like that. +Ed Swierk <eswierk@skyportsystems.com> Ed Swierk via Qemu-devel <qemu-devel@nongnu.org> +Ian McKellar <ianloic@google.com> Ian McKellar via Qemu-devel <qemu-devel@nongnu.org> +Julia Suvorova <jusual@mail.ru> Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org> +Justin Terry (VM) <juterry@microsoft.com> Justin Terry (VM) via Qemu-devel <qemu-devel@nongnu.org> + + # Also list preferred name forms where people have changed their # git author config Daniel P. Berrangé <berrange@redhat.com> @@ -1 +1 @@ -2.11.91 +2.11.92 diff --git a/accel/tcg/tcg-runtime-gvec.c b/accel/tcg/tcg-runtime-gvec.c index 8bf8d63912..90340e56e0 100644 --- a/accel/tcg/tcg-runtime-gvec.c +++ b/accel/tcg/tcg-runtime-gvec.c @@ -705,7 +705,7 @@ void HELPER(NAME)(void *d, void *a, void *b, uint32_t desc) \ { \ intptr_t oprsz = simd_oprsz(desc); \ intptr_t i; \ - for (i = 0; i < oprsz; i += sizeof(vec64)) { \ + for (i = 0; i < oprsz; i += sizeof(TYPE)) { \ *(TYPE *)(d + i) = DO_CMP0(*(TYPE *)(a + i) OP *(TYPE *)(b + i)); \ } \ clear_high(d, oprsz, desc); \ diff --git a/block/file-posix.c b/block/file-posix.c index d7fb772c14..3794c0007a 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1701,6 +1701,7 @@ static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc, case PREALLOC_MODE_FULL: { int64_t num = 0, left = offset - current_length; + off_t seek_result; /* * Knowing the final size from the beginning could allow the file @@ -1715,8 +1716,8 @@ static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc, buf = g_malloc0(65536); - result = lseek(fd, current_length, SEEK_SET); - if (result < 0) { + seek_result = lseek(fd, current_length, SEEK_SET); + if (seek_result < 0) { result = -errno; error_setg_errno(errp, -result, "Failed to seek to the old end of file"); @@ -2114,7 +2115,12 @@ static int find_allocation(BlockDriverState *bs, off_t start, if (offs < 0) { return -errno; /* D3 or D4 */ } - assert(offs >= start); + + if (offs < start) { + /* This is not a valid return by lseek(). We are safe to just return + * -EIO in this case, and we'll treat it like D4. */ + return -EIO; + } if (offs > start) { /* D2: in hole, next data at offs */ @@ -2146,7 +2152,12 @@ static int find_allocation(BlockDriverState *bs, off_t start, if (offs < 0) { return -errno; /* D1 and (H3 or H4) */ } - assert(offs >= start); + + if (offs < start) { + /* This is not a valid return by lseek(). We are safe to just return + * -EIO in this case, and we'll treat it like H4. */ + return -EIO; + } if (offs > start) { /* diff --git a/block/gluster.c b/block/gluster.c index 296e036b3d..4adc1a875b 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -167,7 +167,12 @@ static QemuOptsList runtime_unix_opts = { { .name = GLUSTER_OPT_SOCKET, .type = QEMU_OPT_STRING, - .help = "socket file path)", + .help = "socket file path (legacy)", + }, + { + .name = GLUSTER_OPT_PATH, + .type = QEMU_OPT_STRING, + .help = "socket file path (QAPI)", }, { /* end of list */ } }, @@ -615,10 +620,18 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, goto out; } - ptr = qemu_opt_get(opts, GLUSTER_OPT_SOCKET); + ptr = qemu_opt_get(opts, GLUSTER_OPT_PATH); + if (!ptr) { + ptr = qemu_opt_get(opts, GLUSTER_OPT_SOCKET); + } else if (qemu_opt_get(opts, GLUSTER_OPT_SOCKET)) { + error_setg(&local_err, + "Conflicting parameters 'path' and 'socket'"); + error_append_hint(&local_err, GERR_INDEX_HINT, i); + goto out; + } if (!ptr) { error_setg(&local_err, QERR_MISSING_PARAMETER, - GLUSTER_OPT_SOCKET); + GLUSTER_OPT_PATH); error_append_hint(&local_err, GERR_INDEX_HINT, i); goto out; } @@ -684,7 +697,7 @@ static int qemu_gluster_parse(BlockdevOptionsGluster *gconf, "file.server.0.host=1.2.3.4," "file.server.0.port=24007," "file.server.1.transport=unix," - "file.server.1.socket=/var/run/glusterd.socket ..." + "file.server.1.path=/var/run/glusterd.socket ..." "\n"); return ret; } diff --git a/block/rbd.c b/block/rbd.c index 5b64849dc6..c9359d0ad8 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -623,6 +623,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, BlockdevOptionsRbd *opts = NULL; Visitor *v; QObject *crumpled = NULL; + const QDictEntry *e; Error *local_err = NULL; const char *filename; char *keypairs, *secretid; @@ -671,6 +672,12 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, goto out; } + /* Remove the processed options from the QDict (the visitor processes + * _all_ options in the QDict) */ + while ((e = qdict_first(options))) { + qdict_del(options, e->key); + } + r = qemu_rbd_connect(&s->cluster, &s->io_ctx, opts, !(flags & BDRV_O_NOCACHE), keypairs, secretid, errp); if (r < 0) { diff --git a/blockjob.c b/blockjob.c index ef3ed69ff1..27f957e571 100644 --- a/blockjob.c +++ b/blockjob.c @@ -75,10 +75,8 @@ static void block_job_state_transition(BlockJob *job, BlockJobStatus s1) assert(s1 >= 0 && s1 <= BLOCK_JOB_STATUS__MAX); trace_block_job_state_transition(job, job->ret, BlockJobSTT[s0][s1] ? "allowed" : "disallowed", - qapi_enum_lookup(&BlockJobStatus_lookup, - s0), - qapi_enum_lookup(&BlockJobStatus_lookup, - s1)); + BlockJobStatus_str(s0), + BlockJobStatus_str(s1)); assert(BlockJobSTT[s0][s1]); job->status = s1; } @@ -86,17 +84,15 @@ static void block_job_state_transition(BlockJob *job, BlockJobStatus s1) static int block_job_apply_verb(BlockJob *job, BlockJobVerb bv, Error **errp) { assert(bv >= 0 && bv <= BLOCK_JOB_VERB__MAX); - trace_block_job_apply_verb(job, qapi_enum_lookup(&BlockJobStatus_lookup, - job->status), - qapi_enum_lookup(&BlockJobVerb_lookup, bv), + trace_block_job_apply_verb(job, BlockJobStatus_str(job->status), + BlockJobVerb_str(bv), BlockJobVerbTable[bv][job->status] ? "allowed" : "prohibited"); if (BlockJobVerbTable[bv][job->status]) { return 0; } error_setg(errp, "Job '%s' in state '%s' cannot accept command verb '%s'", - job->id, qapi_enum_lookup(&BlockJobStatus_lookup, job->status), - qapi_enum_lookup(&BlockJobVerb_lookup, bv)); + job->id, BlockJobStatus_str(job->status), BlockJobVerb_str(bv)); return -EPERM; } @@ -204,6 +200,15 @@ void block_job_txn_add_job(BlockJobTxn *txn, BlockJob *job) block_job_txn_ref(txn); } +static void block_job_txn_del_job(BlockJob *job) +{ + if (job->txn) { + QLIST_REMOVE(job, txn_list); + block_job_txn_unref(job->txn); + job->txn = NULL; + } +} + static void block_job_pause(BlockJob *job) { job->pause_count++; @@ -232,6 +237,7 @@ void block_job_unref(BlockJob *job) { if (--job->refcnt == 0) { assert(job->status == BLOCK_JOB_STATUS_NULL); + assert(!job->txn); BlockDriverState *bs = blk_bs(job->blk); QLIST_REMOVE(job, job_list); bs->job = NULL; @@ -392,6 +398,7 @@ static void block_job_decommission(BlockJob *job) job->busy = false; job->paused = false; job->deferred_to_main_loop = true; + block_job_txn_del_job(job); block_job_state_transition(job, BLOCK_JOB_STATUS_NULL); block_job_unref(job); } @@ -481,8 +488,7 @@ static int block_job_finalize_single(BlockJob *job) } } - QLIST_REMOVE(job, txn_list); - block_job_txn_unref(job->txn); + block_job_txn_del_job(job); block_job_conclude(job); return 0; } @@ -1497,16 +1497,19 @@ Advanced options (experts only): --install=INSTALL use specified install [$install] --python=PYTHON use specified python [$python] --smbd=SMBD use specified smbd [$smbd] + --with-git=GIT use specified git [$git] --static enable static build [$static] --mandir=PATH install man pages in PATH --datadir=PATH install firmware in PATH$confsuffix --docdir=PATH install documentation in PATH$confsuffix --bindir=PATH install binaries in PATH --libdir=PATH install libraries in PATH + --libexecdir=PATH install helper binaries in PATH --sysconfdir=PATH install config in PATH$confsuffix --localstatedir=PATH install local state in PATH (set at runtime on win32) --firmwarepath=PATH search PATH for firmware files --with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix] + --with-pkgversion=VERS use specified string as sub-version of the package --enable-debug enable common debug build options --enable-sanitizers enable default sanitizers --disable-strip disable stripping binaries @@ -5054,6 +5057,14 @@ static S2 c2; static S4 c4; static S8 c8; static int i; +void helper(void *d, void *a, int shift, int i); +void helper(void *d, void *a, int shift, int i) +{ + *(U1 *)(d + i) = *(U1 *)(a + i) << shift; + *(U2 *)(d + i) = *(U2 *)(a + i) << shift; + *(U4 *)(d + i) = *(U4 *)(a + i) << shift; + *(U8 *)(d + i) = *(U8 *)(a + i) << shift; +} int main(void) { a1 += b1; a2 += b2; a4 += b4; a8 += b8; diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index 79f7a53ee8..b27075ea3b 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -50,6 +50,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, + VHOST_USER_PROTOCOL_F_CONFIG = 9, VHOST_USER_PROTOCOL_F_MAX }; diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt index c058c407df..534caab18a 100644 --- a/docs/interop/vhost-user.txt +++ b/docs/interop/vhost-user.txt @@ -379,6 +379,7 @@ Protocol features #define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6 #define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7 #define VHOST_USER_PROTOCOL_F_PAGEFAULT 8 +#define VHOST_USER_PROTOCOL_F_CONFIG 9 Master message types -------------------- @@ -664,7 +665,8 @@ Master message types Master payload: virtio device config space Slave payload: virtio device config space - Submitted by the vhost-user master to fetch the contents of the virtio + When VHOST_USER_PROTOCOL_F_CONFIG is negotiated, this message is + submitted by the vhost-user master to fetch the contents of the virtio device configuration space, vhost-user slave's payload size MUST match master's request, vhost-user slave uses zero length of payload to indicate an error to vhost-user master. The vhost-user master may @@ -677,7 +679,8 @@ Master message types Master payload: virtio device config space Slave payload: N/A - Submitted by the vhost-user master when the Guest changes the virtio + When VHOST_USER_PROTOCOL_F_CONFIG is negotiated, this message is + submitted by the vhost-user master when the Guest changes the virtio device configuration space and also can be used for live migration on the destination host. The vhost-user slave must check the flags field, and slaves MUST NOT accept SET_CONFIG for read-only @@ -766,13 +769,13 @@ Slave message types Slave payload: N/A Master payload: N/A - Vhost-user slave sends such messages to notify that the virtio device's - configuration space has changed, for those host devices which can support - such feature, host driver can send VHOST_USER_GET_CONFIG message to slave - to get the latest content. If VHOST_USER_PROTOCOL_F_REPLY_ACK is - negotiated, and slave set the VHOST_USER_NEED_REPLY flag, master must - respond with zero when operation is successfully completed, or non-zero - otherwise. + When VHOST_USER_PROTOCOL_F_CONFIG is negotiated, vhost-user slave sends + such messages to notify that the virtio device's configuration space has + changed, for those host devices which can support such feature, host + driver can send VHOST_USER_GET_CONFIG message to slave to get the latest + content. If VHOST_USER_PROTOCOL_F_REPLY_ACK is negotiated, and slave set + the VHOST_USER_NEED_REPLY flag, master must respond with zero when + operation is successfully completed, or non-zero otherwise. VHOST_USER_PROTOCOL_F_REPLY_ACK: ------------------------------- @@ -814,7 +814,7 @@ static void create_header32(DumpState *s, Error **errp) size = sizeof(DiskDumpHeader32); dh = g_malloc0(size); - strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE)); + memcpy(dh->signature, KDUMP_SIGNATURE, SIG_LEN); dh->header_version = cpu_to_dump32(s, 6); block_size = s->dump_info.page_size; dh->block_size = cpu_to_dump32(s, block_size); @@ -926,7 +926,7 @@ static void create_header64(DumpState *s, Error **errp) size = sizeof(DiskDumpHeader64); dh = g_malloc0(size); - strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE)); + memcpy(dh->signature, KDUMP_SIGNATURE, SIG_LEN); dh->header_version = cpu_to_dump32(s, 6); block_size = s->dump_info.page_size; dh->block_size = cpu_to_dump32(s, block_size); @@ -1495,6 +1495,7 @@ static int find_max_supported_pagesize(Object *obj, void *opaque) mem_path = object_property_get_str(obj, "mem-path", NULL); if (mem_path) { long hpsize = qemu_mempath_getpagesize(mem_path); + g_free(mem_path); if (hpsize < *hpsize_min) { *hpsize_min = hpsize; } @@ -507,6 +507,7 @@ static inline int tohex(int v) return v - 10 + 'a'; } +/* writes 2*len+1 bytes in buf */ static void memtohex(char *buf, const uint8_t *mem, int len) { int i, c; @@ -999,8 +1000,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) const char *p; uint32_t thread; int ch, reg_size, type, res; - char buf[MAX_PACKET_LENGTH]; uint8_t mem_buf[MAX_PACKET_LENGTH]; + char buf[sizeof(mem_buf) + 1 /* trailing NUL */]; uint8_t *registers; target_ulong addr, len; diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index f840f07dfe..262baca432 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -259,6 +259,8 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) s->dev.vq_index = 0; s->dev.backend_features = 0; + vhost_dev_set_config_notifier(&s->dev, &blk_ops); + ret = vhost_dev_init(&s->dev, &s->chardev, VHOST_BACKEND_TYPE_USER, 0); if (ret < 0) { error_setg(errp, "vhost-user-blk: vhost initialization failed: %s", @@ -277,8 +279,6 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) s->blkcfg.num_queues = s->num_queues; } - vhost_dev_set_config_notifier(&s->dev, &blk_ops); - return; vhost_err: diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 9470bd7be7..d2dd8ab502 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -580,13 +580,16 @@ static void set_config(VirtIODevice *vdev, const uint8_t *config_data) VirtIOSerial *vser = VIRTIO_SERIAL(vdev); struct virtio_console_config *config = (struct virtio_console_config *)config_data; - uint8_t emerg_wr_lo = le32_to_cpu(config->emerg_wr); VirtIOSerialPort *port = find_first_connected_console(vser); VirtIOSerialPortClass *vsc; + uint8_t emerg_wr_lo; - if (!config->emerg_wr) { + if (!virtio_has_feature(vser->host_features, + VIRTIO_CONSOLE_F_EMERG_WRITE) || !config->emerg_wr) { return; } + + emerg_wr_lo = le32_to_cpu(config->emerg_wr); /* Make sure we don't misdetect an emergency write when the guest * does a short config write after an emergency write. */ config->emerg_wr = 0; diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c index 83c87d92e0..892f655a7e 100644 --- a/hw/dma/i82374.c +++ b/hw/dma/i82374.c @@ -23,6 +23,7 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "hw/isa/isa.h" #include "hw/dma/i8257.h" @@ -118,13 +119,19 @@ static const MemoryRegionPortio i82374_portio_list[] = { static void i82374_realize(DeviceState *dev, Error **errp) { I82374State *s = I82374(dev); + ISABus *isa_bus = isa_bus_from_device(ISA_DEVICE(dev)); + + if (isa_get_dma(isa_bus, 0)) { + error_setg(errp, "DMA already initialized on ISA bus"); + return; + } + i8257_dma_init(isa_bus, true); portio_list_init(&s->port_list, OBJECT(s), i82374_portio_list, s, "i82374"); portio_list_add(&s->port_list, isa_address_space_io(&s->parent_obj), s->iobase); - i8257_dma_init(isa_bus_from_device(ISA_DEVICE(dev)), true); memset(s->commands, 0, sizeof(s->commands)); } diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index 1707434db3..7dac319403 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -242,6 +242,19 @@ static const VMStateDescription kvmclock_reliable_get_clock = { }; /* + * When migrating, assume the source has an unreliable + * KVM_GET_CLOCK unless told otherwise. + */ +static int kvmclock_pre_load(void *opaque) +{ + KVMClockState *s = opaque; + + s->clock_is_reliable = false; + + return 0; +} + +/* * When migrating, read the clock just before migration, * so that the guest clock counts during the events * between: @@ -268,6 +281,7 @@ static const VMStateDescription kvmclock_vmsd = { .name = "kvmclock", .version_id = 1, .minimum_version_id = 1, + .pre_load = kvmclock_pre_load, .pre_save = kvmclock_pre_save, .fields = (VMStateField[]) { VMSTATE_UINT64(clock, KVMClockState), diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index fdeaec3a58..fb554ab156 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -279,44 +279,52 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl) *timeout = cpu_to_be32(splash_time); } +static CcwDevice *s390_get_ccw_device(DeviceState *dev_st) +{ + CcwDevice *ccw_dev = NULL; + + if (dev_st) { + VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *) + object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), + TYPE_VIRTIO_CCW_DEVICE); + if (virtio_ccw_dev) { + ccw_dev = CCW_DEVICE(virtio_ccw_dev); + } else { + SCSIDevice *sd = (SCSIDevice *) + object_dynamic_cast(OBJECT(dev_st), + TYPE_SCSI_DEVICE); + if (sd) { + SCSIBus *bus = scsi_bus_from_device(sd); + VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus); + VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, + vdev); + + ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw), + TYPE_CCW_DEVICE); + } + } + } + return ccw_dev; +} + static bool s390_gen_initial_iplb(S390IPLState *ipl) { DeviceState *dev_st; + CcwDevice *ccw_dev = NULL; dev_st = get_boot_device(0); if (dev_st) { - VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *) - object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), - TYPE_VIRTIO_CCW_DEVICE); + ccw_dev = s390_get_ccw_device(dev_st); + } + + /* + * Currently allow IPL only from CCW devices. + */ + if (ccw_dev) { SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st), TYPE_SCSI_DEVICE); - VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st), - TYPE_VIRTIO_NET); - - if (vn) { - ipl->netboot = true; - } - if (virtio_ccw_dev) { - CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev); - - ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); - ipl->iplb.blk0_len = - cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); - ipl->iplb.pbt = S390_IPL_TYPE_CCW; - ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); - ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; - } else if (sd) { - SCSIBus *bus = scsi_bus_from_device(sd); - VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus); - VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev); - CcwDevice *ccw_dev; - - ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw), - TYPE_CCW_DEVICE); - if (!ccw_dev) { /* It might be a PCI device instead */ - return false; - } + if (sd) { ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN); ipl->iplb.blk0_len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN); @@ -327,12 +335,25 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno); ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3; } else { - return false; /* unknown device */ + VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st), + TYPE_VIRTIO_NET); + + ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); + ipl->iplb.blk0_len = + cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); + ipl->iplb.pbt = S390_IPL_TYPE_CCW; + ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); + ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; + + if (vn) { + ipl->netboot = true; + } } if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) { ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID; } + return true; } @@ -406,7 +427,8 @@ unref_mr: return img_size; } -static bool is_virtio_net_device(IplParameterBlock *iplb) +static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb, + int virtio_id) { uint8_t cssid; uint8_t ssid; @@ -426,13 +448,23 @@ static bool is_virtio_net_device(IplParameterBlock *iplb) sch = css_find_subch(1, cssid, ssid, schid); if (sch && sch->devno == devno) { - return sch->id.cu_model == VIRTIO_ID_NET; + return sch->id.cu_model == virtio_id; } } } return false; } +static bool is_virtio_net_device(IplParameterBlock *iplb) +{ + return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_NET); +} + +static bool is_virtio_scsi_device(IplParameterBlock *iplb) +{ + return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI); +} + void s390_ipl_update_diag308(IplParameterBlock *iplb) { S390IPLState *ipl = get_ipl_device(); @@ -457,6 +489,22 @@ void s390_reipl_request(void) S390IPLState *ipl = get_ipl_device(); ipl->reipl_requested = true; + if (ipl->iplb_valid && + !ipl->netboot && + ipl->iplb.pbt == S390_IPL_TYPE_CCW && + is_virtio_scsi_device(&ipl->iplb)) { + CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0)); + + if (ccw_dev && + cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno && + (ccw_dev->sch->ssid & 3) == ipl->iplb.ccw.ssid) { + /* + * this is the original boot device's SCSI + * so restore IPL parameter info from it + */ + ipl->iplb_valid = s390_gen_initial_iplb(ipl); + } + } qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 864145a7c6..435f7c99e7 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -246,6 +246,7 @@ static void s390_init_ipl_dev(const char *kernel_filename, { Object *new = object_new(TYPE_S390_IPL); DeviceState *dev = DEVICE(new); + char *netboot_fw_prop; if (kernel_filename) { qdev_prop_set_string(dev, "kernel", kernel_filename); @@ -256,9 +257,11 @@ static void s390_init_ipl_dev(const char *kernel_filename, qdev_prop_set_string(dev, "cmdline", kernel_cmdline); qdev_prop_set_string(dev, "firmware", firmware); qdev_prop_set_bit(dev, "enforce_bios", enforce_bios); - if (!strlen(object_property_get_str(new, "netboot_fw", &error_abort))) { + netboot_fw_prop = object_property_get_str(new, "netboot_fw", &error_abort); + if (!strlen(netboot_fw_prop)) { qdev_prop_set_string(dev, "netboot_fw", netboot_fw); } + g_free(netboot_fw_prop); object_property_add_child(qdev_get_machine(), TYPE_S390_IPL, new, NULL); object_unref(new); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index f5ab767ab5..ded23d36ca 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -714,10 +714,12 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) /* min_io_size and opt_io_size can't be greater than * max_io_sectors */ - min_io_size = - MIN_NON_ZERO(min_io_size, max_io_sectors); - opt_io_size = - MIN_NON_ZERO(opt_io_size, max_io_sectors); + if (min_io_size) { + min_io_size = MIN(min_io_size, max_io_sectors); + } + if (opt_io_size) { + opt_io_size = MIN(opt_io_size, max_io_sectors); + } } /* required VPD size with unmap support */ buflen = 0x40; @@ -823,7 +825,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) * block characteristics VPD page by default. Not all of SPC-3 * is actually implemented, but we're good enough. */ - outbuf[2] = 5; + outbuf[2] = s->qdev.default_scsi_version; outbuf[3] = 2 | 0x10; /* Format 2, HiSup */ if (buflen > 36) { @@ -2191,7 +2193,11 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) case READ_12: case READ_16: DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len); - if (r->req.cmd.buf[1] & 0xe0) { + /* Protection information is not supported. For SCSI versions 2 and + * older (as determined by snooping the guest's INQUIRY commands), + * there is no RD/WR/VRPROTECT, so skip this check in these versions. + */ + if (s->qdev.scsi_version > 2 && (r->req.cmd.buf[1] & 0xe0)) { goto illegal_request; } if (!check_lba_range(s, r->req.cmd.lba, len)) { @@ -2222,7 +2228,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) * As far as DMA is concerned, we can treat it the same as a write; * scsi_block_do_sgio will send VERIFY commands. */ - if (r->req.cmd.buf[1] & 0xe0) { + if (s->qdev.scsi_version > 2 && (r->req.cmd.buf[1] & 0xe0)) { goto illegal_request; } if (!check_lba_range(s, r->req.cmd.lba, len)) { @@ -2268,6 +2274,8 @@ static void scsi_disk_reset(DeviceState *dev) /* reset tray statuses */ s->tray_locked = 0; s->tray_open = 0; + + s->qdev.scsi_version = s->qdev.default_scsi_version; } static void scsi_disk_resize_cb(void *opaque) @@ -2812,6 +2820,8 @@ static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf) static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf) { SCSIBlockReq *r = (SCSIBlockReq *)req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + r->cmd = req->cmd.buf[0]; switch (r->cmd >> 5) { case 0: @@ -2837,8 +2847,11 @@ static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf) abort(); } - if (r->cdb1 & 0xe0) { - /* Protection information is not supported. */ + /* Protection information is not supported. For SCSI versions 2 and + * older (as determined by snooping the guest's INQUIRY commands), + * there is no RD/WR/VRPROTECT, so skip this check in these versions. + */ + if (s->qdev.scsi_version > 2 && (req->cmd.buf[1] & 0xe0)) { scsi_check_condition(&r->req, SENSE_CODE(INVALID_FIELD)); return 0; } @@ -2950,6 +2963,8 @@ static Property scsi_hd_properties[] = { DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, DEFAULT_MAX_IO_SIZE), DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, + 5), DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), DEFINE_PROP_END_OF_LIST(), }; @@ -2995,6 +3010,8 @@ static Property scsi_cd_properties[] = { DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, DEFAULT_MAX_IO_SIZE), + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, + 5), DEFINE_PROP_END_OF_LIST(), }; @@ -3023,6 +3040,8 @@ static Property scsi_block_properties[] = { DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false), DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, + -1), DEFINE_PROP_END_OF_LIST(), }; @@ -3063,6 +3082,8 @@ static Property scsi_disk_properties[] = { DEFAULT_MAX_UNMAP_SIZE), DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, DEFAULT_MAX_IO_SIZE), + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, + 5), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 4753f8738f..381f04e339 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -194,17 +194,40 @@ static void scsi_read_complete(void * opaque, int ret) r->buf[3] |= 0x80; } } - if (s->type == TYPE_DISK && - r->req.cmd.buf[0] == INQUIRY && - r->req.cmd.buf[2] == 0xb0) { - uint32_t max_transfer = - blk_get_max_transfer(s->conf.blk) / s->blocksize; - - assert(max_transfer); - stl_be_p(&r->buf[8], max_transfer); - /* Also take care of the opt xfer len. */ - stl_be_p(&r->buf[12], - MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); + if (r->req.cmd.buf[0] == INQUIRY) { + /* + * EVPD set to zero returns the standard INQUIRY data. + * + * Check if scsi_version is unset (-1) to avoid re-defining it + * each time an INQUIRY with standard data is received. + * scsi_version is initialized with -1 in scsi_generic_reset + * and scsi_disk_reset, making sure that we'll set the + * scsi_version after a reset. If the version field of the + * INQUIRY response somehow changes after a guest reboot, + * we'll be able to keep track of it. + * + * On SCSI-2 and older, first 3 bits of byte 2 is the + * ANSI-approved version, while on later versions the + * whole byte 2 contains the version. Check if we're dealing + * with a newer version and, in that case, assign the + * whole byte. + */ + if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) { + s->scsi_version = r->buf[2] & 0x07; + if (s->scsi_version > 2) { + s->scsi_version = r->buf[2]; + } + } + if (s->type == TYPE_DISK && r->req.cmd.buf[2] == 0xb0) { + uint32_t max_transfer = + blk_get_max_transfer(s->conf.blk) / s->blocksize; + + assert(max_transfer); + stl_be_p(&r->buf[8], max_transfer); + /* Also take care of the opt xfer len. */ + stl_be_p(&r->buf[12], + MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); + } } scsi_req_data(&r->req, len); scsi_req_unref(&r->req); @@ -474,6 +497,7 @@ static void scsi_generic_reset(DeviceState *dev) { SCSIDevice *s = SCSI_DEVICE(dev); + s->scsi_version = s->default_scsi_version; scsi_device_purge_requests(s, SENSE_CODE(RESET)); } @@ -549,6 +573,8 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) DPRINTF("block size %d\n", s->blocksize); + /* Only used by scsi-block, but initialize it nevertheless to be clean. */ + s->default_scsi_version = -1; scsi_generic_read_device_identification(s); } diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 4e5855741a..fe34b50769 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -357,11 +357,13 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) { error_setg(&err, "vfio: subchannel %s has already been attached", vcdev->vdev.name); + g_free(vcdev->vdev.name); goto out_device_err; } } if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) { + g_free(vcdev->vdev.name); goto out_device_err; } diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 5e84716218..07ffa0ba10 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -548,12 +548,11 @@ static void vfio_listener_region_add(MemoryListener *listener, hwaddr pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1; if ((iova & pgmask) || (int128_get64(llsize) & pgmask)) { - error_report("Region 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx - " is not aligned to 0x%"HWADDR_PRIx - " and cannot be mapped for DMA", - section->offset_within_region, - int128_getlo(section->size), - pgmask + 1); + trace_vfio_listener_region_add_no_dma_map( + memory_region_name(section->mr), + section->offset_within_address_space, + int128_getlo(section->size), + pgmask + 1); return; } } diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index 79f63a2ff6..20109cb758 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -90,6 +90,7 @@ vfio_iommu_map_notify(const char *op, uint64_t iova_start, uint64_t iova_end) "i vfio_listener_region_add_skip(uint64_t start, uint64_t end) "SKIPPING region_add 0x%"PRIx64" - 0x%"PRIx64 vfio_listener_region_add_iommu(uint64_t start, uint64_t end) "region_add [iommu] 0x%"PRIx64" - 0x%"PRIx64 vfio_listener_region_add_ram(uint64_t iova_start, uint64_t iova_end, void *vaddr) "region_add [ram] 0x%"PRIx64" - 0x%"PRIx64" [%p]" +vfio_listener_region_add_no_dma_map(const char *name, uint64_t iova, uint64_t size, uint64_t page_size) "Region \"%s\" 0x%"PRIx64" size=0x%"PRIx64" is not aligned to 0x%"PRIx64" and cannot be mapped for DMA" vfio_listener_region_del_skip(uint64_t start, uint64_t end) "SKIPPING region_del 0x%"PRIx64" - 0x%"PRIx64 vfio_listener_region_del(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" - 0x%"PRIx64 vfio_disconnect_container(int fd) "close container->fd=%d" diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 44aea5c0a8..38da8692bb 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -46,6 +46,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, + VHOST_USER_PROTOCOL_F_CONFIG = 9, VHOST_USER_PROTOCOL_F_MAX }; @@ -1211,6 +1212,17 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque) dev->protocol_features = protocol_features & VHOST_USER_PROTOCOL_FEATURE_MASK; + + if (!dev->config_ops || !dev->config_ops->vhost_dev_config_notifier) { + /* Don't acknowledge CONFIG feature if device doesn't support it */ + dev->protocol_features &= ~(1ULL << VHOST_USER_PROTOCOL_F_CONFIG); + } else if (!(protocol_features & + (1ULL << VHOST_USER_PROTOCOL_F_CONFIG))) { + error_report("Device expects VHOST_USER_PROTOCOL_F_CONFIG " + "but backend does not support it."); + return -1; + } + err = vhost_user_set_protocol_features(dev, dev->protocol_features); if (err < 0) { return err; @@ -1405,6 +1417,11 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + config_len, }; + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CONFIG)) { + return -1; + } + if (config_len > VHOST_USER_MAX_CONFIG_SIZE) { return -1; } @@ -1448,6 +1465,11 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, .hdr.size = VHOST_USER_CONFIG_HDR_SIZE + size, }; + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_CONFIG)) { + return -1; + } + if (reply_supported) { msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 250f886acb..f51bf573d5 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -595,10 +595,15 @@ static void vhost_region_add_section(struct vhost_dev *dev, prev_sec->offset_within_address_space, prev_sec->offset_within_region); } else { - error_report("%s: Overlapping but not coherent sections " - "at %"PRIx64, - __func__, mrs_gpa); - return; + /* adjoining regions are fine, but overlapping ones with + * different blocks/offsets shouldn't happen + */ + if (mrs_gpa != prev_gpa_end + 1) { + error_report("%s: Overlapping but not coherent sections " + "at %"PRIx64, + __func__, mrs_gpa); + return; + } } } } @@ -1223,7 +1228,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, if (!(hdev->features & (0x1ULL << VHOST_F_LOG_ALL))) { error_setg(&hdev->migration_blocker, "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature."); - } else if (vhost_dev_log_is_shared(hdev) && !qemu_memfd_check()) { + } else if (vhost_dev_log_is_shared(hdev) && !qemu_memfd_alloc_check()) { error_setg(&hdev->migration_blocker, "Migration disabled: failed to allocate shared memory"); } @@ -1451,7 +1456,6 @@ int vhost_dev_set_config(struct vhost_dev *hdev, const uint8_t *data, void vhost_dev_set_config_notifier(struct vhost_dev *hdev, const VhostDevConfigOps *ops) { - assert(hdev->vhost_ops); hdev->config_ops = ops; } diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 7ecaddac9d..e35137ea78 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -85,6 +85,8 @@ struct SCSIDevice uint64_t max_lba; uint64_t wwn; uint64_t port_wwn; + int scsi_version; + int default_scsi_version; }; extern const VMStateDescription vmstate_scsi_device; diff --git a/include/qemu/memfd.h b/include/qemu/memfd.h index de10198ed6..49e79634da 100644 --- a/include/qemu/memfd.h +++ b/include/qemu/memfd.h @@ -18,6 +18,7 @@ int qemu_memfd_create(const char *name, size_t size, bool hugetlb, uint64_t hugetlbsize, unsigned int seals, Error **errp); +bool qemu_memfd_alloc_check(void); void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, int *fd, Error **errp); void qemu_memfd_free(void *ptr, size_t size, int fd); diff --git a/include/ui/console.h b/include/ui/console.h index 6d2c052068..37a8d68d29 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -99,7 +99,7 @@ void hmp_mouse_set(Monitor *mon, const QDict *qdict); #define QEMU_KEY_CTRL_PAGEDOWN 0xe407 void kbd_put_keysym_console(QemuConsole *s, int keysym); -bool kbd_put_qcode_console(QemuConsole *s, int qcode); +bool kbd_put_qcode_console(QemuConsole *s, int qcode, bool ctrl); void kbd_put_string_console(QemuConsole *s, const char *str, int len); void kbd_put_keysym(int keysym); diff --git a/linux-user/signal.c b/linux-user/signal.c index 33d5ced30c..046d4c8aa0 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -2920,8 +2920,8 @@ static void setup_frame(int sig, struct target_sigaction *ka, env->pc = ka->_sa_handler; env->npc = (env->pc + 4); /* 5. return to kernel instructions */ - if (ka->sa_restorer) { - env->regwptr[UREG_I7] = ka->sa_restorer; + if (ka->ka_restorer) { + env->regwptr[UREG_I7] = ka->ka_restorer; } else { uint32_t val32; @@ -6367,7 +6367,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, &frame->retcode[1]); __put_user(INSN_CALLSYS, &frame->retcode[2]); /* imb() */ - r26 = frame_addr; + r26 = frame_addr + offsetof(struct target_sigframe, retcode); } unlock_user_struct(frame, frame_addr, 1); @@ -6424,7 +6424,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, &frame->retcode[1]); __put_user(INSN_CALLSYS, &frame->retcode[2]); /* imb(); */ - r26 = frame_addr; + r26 = frame_addr + offsetof(struct target_sigframe, retcode); } if (err) { diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 0eab5cc6ad..643b8833de 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8717,6 +8717,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, target_siginitset(&act.sa_mask, old_act->sa_mask); act.sa_flags = old_act->sa_flags; act.sa_restorer = old_act->sa_restorer; +#ifdef TARGET_ARCH_HAS_KA_RESTORER + act.ka_restorer = 0; +#endif unlock_user_struct(old_act, arg2, 0); pact = &act; } else { @@ -8791,8 +8794,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) { goto efault; } -#ifdef TARGET_SPARC - act->sa_restorer = restorer; +#ifdef TARGET_ARCH_HAS_KA_RESTORER + act->ka_restorer = restorer; #endif } else { act = NULL; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 13fe840239..23f5bccf0e 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -435,6 +435,7 @@ int do_sigaction(int sig, const struct target_sigaction *act, #define TARGET_SA_NODEFER 0x20u #define TARGET_SA_RESETHAND 4u #define TARGET_ARCH_HAS_SA_RESTORER 1 +#define TARGET_ARCH_HAS_KA_RESTORER 1 #elif defined(TARGET_MIPS) #define TARGET_SA_NOCLDSTOP 0x00000001 #define TARGET_SA_NOCLDWAIT 0x00010000 @@ -742,6 +743,9 @@ struct target_sigaction { abi_ulong sa_restorer; #endif target_sigset_t sa_mask; +#ifdef TARGET_ARCH_HAS_KA_RESTORER + abi_ulong ka_restorer; +#endif }; #endif @@ -2561,6 +2565,7 @@ struct target_statfs64 { #define TARGET_O_CLOEXEC 0x400000 #define TARGET___O_SYNC 0x800000 #define TARGET_O_PATH 0x1000000 +#define TARGET___O_TMPFILE 0x2000000 #endif /* <asm-generic/fcntl.h> values follow. */ diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img Binary files differindex d2098f1fd9..4ec0dbfc4a 100755 --- a/pc-bios/hppa-firmware.img +++ b/pc-bios/hppa-firmware.img diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img Binary files differindex fbd76bb55e..fdd6809c70 100644 --- a/pc-bios/s390-ccw.img +++ b/pc-bios/s390-ccw.img diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index fc2a9fe33b..9287b7a70f 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -70,6 +70,13 @@ static void jump_to_IPL_code(uint64_t address) { /* store the subsystem information _after_ the bootmap was loaded */ write_subsystem_identification(); + + /* prevent unknown IPL types in the guest */ + if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { + iplb.pbt = S390_IPL_TYPE_CCW; + set_iplb(&iplb); + } + /* * The IPL PSW is at address 0. We also must not overwrite the * content of non-BIOS memory after we loaded the guest, so we diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h index 7dfce4fbcf..5357a36d51 100644 --- a/pc-bios/s390-ccw/iplb.h +++ b/pc-bios/s390-ccw/iplb.h @@ -97,16 +97,27 @@ extern QemuIplParameters qipl; #define S390_IPL_TYPE_CCW 0x02 #define S390_IPL_TYPE_QEMU_SCSI 0xff -static inline bool store_iplb(IplParameterBlock *iplb) +static inline bool manage_iplb(IplParameterBlock *iplb, bool store) { register unsigned long addr asm("0") = (unsigned long) iplb; register unsigned long rc asm("1") = 0; asm volatile ("diag %0,%2,0x308\n" : "+d" (addr), "+d" (rc) - : "d" (6) + : "d" (store ? 6 : 5) : "memory", "cc"); return rc == 0x01; } + +static inline bool store_iplb(IplParameterBlock *iplb) +{ + return manage_iplb(iplb, true); +} + +static inline bool set_iplb(IplParameterBlock *iplb) +{ + return manage_iplb(iplb, false); +} + #endif /* IPLB_H */ diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 817e7f56ea..cdb66f459e 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -14,7 +14,7 @@ #include "virtio-scsi.h" #include "bswap.h" -#define VRING_WAIT_REPLY_TIMEOUT 3 +#define VRING_WAIT_REPLY_TIMEOUT 30 static VRing block[VIRTIO_MAX_VQS]; static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS] diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img Binary files differindex 9f5926b534..31f3d141cd 100644 --- a/pc-bios/s390-netboot.img +++ b/pc-bios/s390-netboot.img diff --git a/qemu-doc.texi b/qemu-doc.texi index 89fa80518a..5813d27615 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -140,6 +140,7 @@ accelerator is required to use more than one host CPU for emulation. * direct_linux_boot:: Direct Linux Boot * pcsys_usb:: USB emulation * vnc_security:: VNC security +* network_tls:: TLS setup for network services * gdb_usage:: GDB usage * pcsys_os_specific:: Target OS specific information @end menu @@ -1041,7 +1042,6 @@ considerations depending on the deployment scenarios. * vnc_sec_certificate_pw:: * vnc_sec_sasl:: * vnc_sec_certificate_sasl:: -* vnc_generate_cert:: * vnc_setup_sasl:: @end menu @node vnc_sec_none @@ -1161,25 +1161,105 @@ with the aforementioned TLS + x509 options: qemu-system-i386 [...OPTIONS...] -vnc :1,tls,x509,sasl -monitor stdio @end example +@node vnc_setup_sasl -@node vnc_generate_cert -@subsection Generating certificates for VNC +@subsection Configuring SASL mechanisms -The GNU TLS packages provides a command called @code{certtool} which can -be used to generate certificates and keys in PEM format. At a minimum it -is necessary to setup a certificate authority, and issue certificates to -each server. If using certificates for authentication, then each client -will also need to be issued a certificate. The recommendation is for the -server to keep its certificates in either @code{/etc/pki/qemu} or for -unprivileged users in @code{$HOME/.pki/qemu}. +The following documentation assumes use of the Cyrus SASL implementation on a +Linux host, but the principles should apply to any other SASL implementation +or host. When SASL is enabled, the mechanism configuration will be loaded from +system default SASL service config /etc/sasl2/qemu.conf. If running QEMU as an +unprivileged user, an environment variable SASL_CONF_PATH can be used to make +it search alternate locations for the service config file. + +If the TLS option is enabled for VNC, then it will provide session encryption, +otherwise the SASL mechanism will have to provide encryption. In the latter +case the list of possible plugins that can be used is drastically reduced. In +fact only the GSSAPI SASL mechanism provides an acceptable level of security +by modern standards. Previous versions of QEMU referred to the DIGEST-MD5 +mechanism, however, it has multiple serious flaws described in detail in +RFC 6331 and thus should never be used any more. The SCRAM-SHA-1 mechanism +provides a simple username/password auth facility similar to DIGEST-MD5, but +does not support session encryption, so can only be used in combination with +TLS. + +When not using TLS the recommended configuration is + +@example +mech_list: gssapi +keytab: /etc/qemu/krb5.tab +@end example + +This says to use the 'GSSAPI' mechanism with the Kerberos v5 protocol, with +the server principal stored in /etc/qemu/krb5.tab. For this to work the +administrator of your KDC must generate a Kerberos principal for the server, +with a name of 'qemu/somehost.example.com@@EXAMPLE.COM' replacing +'somehost.example.com' with the fully qualified host name of the machine +running QEMU, and 'EXAMPLE.COM' with the Kerberos Realm. + +When using TLS, if username+password authentication is desired, then a +reasonable configuration is + +@example +mech_list: scram-sha-1 +sasldb_path: /etc/qemu/passwd.db +@end example + +The @code{saslpasswd2} program can be used to populate the @code{passwd.db} +file with accounts. + +Other SASL configurations will be left as an exercise for the reader. Note that +all mechanisms, except GSSAPI, should be combined with use of TLS to ensure a +secure data channel. + + +@node network_tls +@section TLS setup for network services + +Almost all network services in QEMU have the ability to use TLS for +session data encryption, along with x509 certificates for simple +client authentication. What follows is a description of how to +generate certificates suitable for usage with QEMU, and applies to +the VNC server, character devices with the TCP backend, NBD server +and client, and migration server and client. + +At a high level, QEMU requires certificates and private keys to be +provided in PEM format. Aside from the core fields, the certificates +should include various extension data sets, including v3 basic +constraints data, key purpose, key usage and subject alt name. + +The GnuTLS package includes a command called @code{certtool} which can +be used to easily generate certificates and keys in the required format +with expected data present. Alternatively a certificate management +service may be used. + +At a minimum it is necessary to setup a certificate authority, and +issue certificates to each server. If using x509 certificates for +authentication, then each client will also need to be issued a +certificate. + +Assuming that the QEMU network services will only ever be exposed to +clients on a private intranet, there is no need to use a commercial +certificate authority to create certificates. A self-signed CA is +sufficient, and in fact likely to be more secure since it removes +the ability of malicious 3rd parties to trick the CA into mis-issuing +certs for impersonating your services. The only likely exception +where a commercial CA might be desirable is if enabling the VNC +websockets server and exposing it directly to remote browser clients. +In such a case it might be useful to use a commercial CA to avoid +needing to install custom CA certs in the web browsers. + +The recommendation is for the server to keep its certificates in either +@code{/etc/pki/qemu} or for unprivileged users in @code{$HOME/.pki/qemu}. @menu -* vnc_generate_ca:: -* vnc_generate_server:: -* vnc_generate_client:: +* tls_generate_ca:: +* tls_generate_server:: +* tls_generate_client:: +* tls_creds_setup:: @end menu -@node vnc_generate_ca -@subsubsection Setup the Certificate Authority +@node tls_generate_ca +@subsection Setup the Certificate Authority This step only needs to be performed once per organization / organizational unit. First the CA needs a private key. This key must be kept VERY secret @@ -1190,11 +1270,10 @@ issued with it is lost. # certtool --generate-privkey > ca-key.pem @end example -A CA needs to have a public certificate. For simplicity it can be a self-signed -certificate, or one issue by a commercial certificate issuing authority. To -generate a self-signed certificate requires one core piece of information, the -name of the organization. - +To generate a self-signed certificate requires one core piece of information, +the name of the organization. A template file @code{ca.info} should be +populated with the desired data to avoid having to deal with interactive +prompts from certtool: @example # cat > ca.info <<EOF cn = Name of your organization @@ -1207,123 +1286,224 @@ EOF --outfile ca-cert.pem @end example -The @code{ca-cert.pem} file should be copied to all servers and clients wishing to utilize -TLS support in the VNC server. The @code{ca-key.pem} must not be disclosed/copied at all. +The @code{ca} keyword in the template sets the v3 basic constraints extension +to indicate this certificate is for a CA, while @code{cert_signing_key} sets +the key usage extension to indicate this will be used for signing other keys. +The generated @code{ca-cert.pem} file should be copied to all servers and +clients wishing to utilize TLS support in the VNC server. The @code{ca-key.pem} +must not be disclosed/copied anywhere except the host responsible for issuing +certificates. -@node vnc_generate_server -@subsubsection Issuing server certificates +@node tls_generate_server +@subsection Issuing server certificates Each server (or host) needs to be issued with a key and certificate. When connecting the certificate is sent to the client which validates it against the CA certificate. -The core piece of information for a server certificate is the hostname. This should -be the fully qualified hostname that the client will connect with, since the client -will typically also verify the hostname in the certificate. On the host holding the -secure CA private key: - -@example -# cat > server.info <<EOF +The core pieces of information for a server certificate are the hostnames and/or IP +addresses that will be used by clients when connecting. The hostname / IP address +that the client specifies when connecting will be validated against the hostname(s) +and IP address(es) recorded in the server certificate, and if no match is found +the client will close the connection. + +Thus it is recommended that the server certificate include both the fully qualified +and unqualified hostnames. If the server will have permanently assigned IP address(es), +and clients are likely to use them when connecting, they may also be included in the +certificate. Both IPv4 and IPv6 addresses are supported. Historically certificates +only included 1 hostname in the @code{CN} field, however, usage of this field for +validation is now deprecated. Instead modern TLS clients will validate against the +Subject Alt Name extension data, which allows for multiple entries. In the future +usage of the @code{CN} field may be discontinued entirely, so providing SAN +extension data is strongly recommended. + +On the host holding the CA, create template files containing the information +for each server, and use it to issue server certificates. + +@example +# cat > server-hostNNN.info <<EOF organization = Name of your organization -cn = server.foo.example.com +cn = hostNNN.foo.example.com +dns_name = hostNNN +dns_name = hostNNN.foo.example.com +ip_address = 10.0.1.87 +ip_address = 192.8.0.92 +ip_address = 2620:0:cafe::87 +ip_address = 2001:24::92 tls_www_server encryption_key signing_key EOF -# certtool --generate-privkey > server-key.pem +# certtool --generate-privkey > server-hostNNN-key.pem # certtool --generate-certificate \ --load-ca-certificate ca-cert.pem \ --load-ca-privkey ca-key.pem \ - --load-privkey server-key.pem \ - --template server.info \ - --outfile server-cert.pem + --load-privkey server-hostNNN-key.pem \ + --template server-hostNNN.info \ + --outfile server-hostNNN-cert.pem @end example -The @code{server-key.pem} and @code{server-cert.pem} files should now be securely copied -to the server for which they were generated. The @code{server-key.pem} is security -sensitive and should be kept protected with file mode 0600 to prevent disclosure. +The @code{dns_name} and @code{ip_address} fields in the template are setting +the subject alt name extension data. The @code{tls_www_server} keyword is the +key purpose extension to indicate this certificate is intended for usage in +a web server. Although QEMU network services are not in fact HTTP servers +(except for VNC websockets), setting this key purpose is still recommended. +The @code{encryption_key} and @code{signing_key} keyword is the key usage +extension to indicate this certificate is intended for usage in the data +session. -@node vnc_generate_client -@subsubsection Issuing client certificates +The @code{server-hostNNN-key.pem} and @code{server-hostNNN-cert.pem} files +should now be securely copied to the server for which they were generated, +and renamed to @code{server-key.pem} and @code{server-cert.pem} when added +to the @code{/etc/pki/qemu} directory on the target host. The @code{server-key.pem} +file is security sensitive and should be kept protected with file mode 0600 +to prevent disclosure. + +@node tls_generate_client +@subsection Issuing client certificates + +The QEMU x509 TLS credential setup defaults to enabling client verification +using certificates, providing a simple authentication mechanism. If this +default is used, each client also needs to be issued a certificate. The client +certificate contains enough metadata to uniquely identify the client with the +scope of the certificate authority. The client certificate would typically +include fields for organization, state, city, building, etc. + +Once again on the host holding the CA, create template files containing the +information for each client, and use it to issue client certificates. -If the QEMU VNC server is to use the @code{x509verify} option to validate client -certificates as its authentication mechanism, each client also needs to be issued -a certificate. The client certificate contains enough metadata to uniquely identify -the client, typically organization, state, city, building, etc. On the host holding -the secure CA private key: @example -# cat > client.info <<EOF +# cat > client-hostNNN.info <<EOF country = GB state = London -locality = London +locality = City Of London organization = Name of your organization -cn = client.foo.example.com +cn = hostNNN.foo.example.com tls_www_client encryption_key signing_key EOF -# certtool --generate-privkey > client-key.pem +# certtool --generate-privkey > client-hostNNN-key.pem # certtool --generate-certificate \ --load-ca-certificate ca-cert.pem \ --load-ca-privkey ca-key.pem \ - --load-privkey client-key.pem \ - --template client.info \ - --outfile client-cert.pem + --load-privkey client-hostNNN-key.pem \ + --template client-hostNNN.info \ + --outfile client-hostNNN-cert.pem +@end example + +The subject alt name extension data is not required for clients, so the +the @code{dns_name} and @code{ip_address} fields are not included. +The @code{tls_www_client} keyword is the key purpose extension to indicate +this certificate is intended for usage in a web client. Although QEMU +network clients are not in fact HTTP clients, setting this key purpose is +still recommended. The @code{encryption_key} and @code{signing_key} keyword +is the key usage extension to indicate this certificate is intended for +usage in the data session. + +The @code{client-hostNNN-key.pem} and @code{client-hostNNN-cert.pem} files +should now be securely copied to the client for which they were generated, +and renamed to @code{client-key.pem} and @code{client-cert.pem} when added +to the @code{/etc/pki/qemu} directory on the target host. The @code{client-key.pem} +file is security sensitive and should be kept protected with file mode 0600 +to prevent disclosure. + +If a single host is going to be using TLS in both a client and server +role, it is possible to create a single certificate to cover both roles. +This would be quite common for the migration and NBD services, where a +QEMU process will be started by accepting a TLS protected incoming migration, +and later itself be migrated out to another host. To generate a single +certificate, simply include the template data from both the client and server +instructions in one. + +@example +# cat > both-hostNNN.info <<EOF +country = GB +state = London +locality = City Of London +organization = Name of your organization +cn = hostNNN.foo.example.com +dns_name = hostNNN +dns_name = hostNNN.foo.example.com +ip_address = 10.0.1.87 +ip_address = 192.8.0.92 +ip_address = 2620:0:cafe::87 +ip_address = 2001:24::92 +tls_www_server +tls_www_client +encryption_key +signing_key +EOF +# certtool --generate-privkey > both-hostNNN-key.pem +# certtool --generate-certificate \ + --load-ca-certificate ca-cert.pem \ + --load-ca-privkey ca-key.pem \ + --load-privkey both-hostNNN-key.pem \ + --template both-hostNNN.info \ + --outfile both-hostNNN-cert.pem @end example -The @code{client-key.pem} and @code{client-cert.pem} files should now be securely -copied to the client for which they were generated. +When copying the PEM files to the target host, save them twice, +once as @code{server-cert.pem} and @code{server-key.pem}, and +again as @code{client-cert.pem} and @code{client-key.pem}. +@node tls_creds_setup +@subsection TLS x509 credential configuration -@node vnc_setup_sasl +QEMU has a standard mechanism for loading x509 credentials that will be +used for network services and clients. It requires specifying the +@code{tls-creds-x509} class name to the @code{--object} command line +argument for the system emulators. Each set of credentials loaded should +be given a unique string identifier via the @code{id} parameter. A single +set of TLS credentials can be used for multiple network backends, so VNC, +migration, NBD, character devices can all share the same credentials. Note, +however, that credentials for use in a client endpoint must be loaded +separately from those used in a server endpoint. -@subsection Configuring SASL mechanisms +When specifying the object, the @code{dir} parameters specifies which +directory contains the credential files. This directory is expected to +contain files with the names mentioned previously, @code{ca-cert.pem}, +@code{server-key.pem}, @code{server-cert.pem}, @code{client-key.pem} +and @code{client-cert.pem} as appropriate. It is also possible to +include a set of pre-generated Diffie-Hellman (DH) parameters in a file +@code{dh-params.pem}, which can be created using the +@code{certtool --generate-dh-params} command. If omitted, QEMU will +dynamically generate DH parameters when loading the credentials. -The following documentation assumes use of the Cyrus SASL implementation on a -Linux host, but the principals should apply to any other SASL impl. When SASL -is enabled, the mechanism configuration will be loaded from system default -SASL service config /etc/sasl2/qemu.conf. If running QEMU as an -unprivileged user, an environment variable SASL_CONF_PATH can be used -to make it search alternate locations for the service config. +The @code{endpoint} parameter indicates whether the credentials will +be used for a network client or server, and determines which PEM +files are loaded. -If the TLS option is enabled for VNC, then it will provide session encryption, -otherwise the SASL mechanism will have to provide encryption. In the latter -case the list of possible plugins that can be used is drastically reduced. In -fact only the GSSAPI SASL mechanism provides an acceptable level of security -by modern standards. Previous versions of QEMU referred to the DIGEST-MD5 -mechanism, however, it has multiple serious flaws described in detail in -RFC 6331 and thus should never be used any more. The SCRAM-SHA-1 mechanism -provides a simple username/password auth facility similar to DIGEST-MD5, but -does not support session encryption, so can only be used in combination with -TLS. +The @code{verify} parameter determines whether x509 certificate +validation should be performed. This defaults to enabled, meaning +clients will always validate the server hostname against the +certificate subject alt name fields and/or CN field. It also +means that servers will request that clients provide a certificate +and validate them. Verification should never be turned off for +client endpoints, however, it may be turned off for server endpoints +if an alternative mechanism is used to authenticate clients. For +example, the VNC server can use SASL to authenticate clients +instead. -When not using TLS the recommended configuration is +To load server credentials with client certificate validation +enabled @example -mech_list: gssapi -keytab: /etc/qemu/krb5.tab +$QEMU -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server @end example -This says to use the 'GSSAPI' mechanism with the Kerberos v5 protocol, with -the server principal stored in /etc/qemu/krb5.tab. For this to work the -administrator of your KDC must generate a Kerberos principal for the server, -with a name of 'qemu/somehost.example.com@@EXAMPLE.COM' replacing -'somehost.example.com' with the fully qualified host name of the machine -running QEMU, and 'EXAMPLE.COM' with the Kerberos Realm. - -When using TLS, if username+password authentication is desired, then a -reasonable configuration is +while to load client credentials use @example -mech_list: scram-sha-1 -sasldb_path: /etc/qemu/passwd.db +$QEMU -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=client @end example -The saslpasswd2 program can be used to populate the passwd.db file with -accounts. +Network services which support TLS will all have a @code{tls-creds} +parameter which expects the ID of the TLS credentials object. For +example with VNC: -Other SASL configurations will be left as an exercise for the reader. Note that -all mechanisms except GSSAPI, should be combined with use of TLS to ensure a -secure data channel. +@example +$QEMU -vnc 0.0.0.0:0,tls-creds=tls0 +@end example @node gdb_usage @section GDB usage diff --git a/qemu-options.hx b/qemu-options.hx index 3ece30d216..ca4e412f2f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4112,7 +4112,7 @@ expensive operation that consumes random pool entropy, so it is recommended that a persistent set of parameters be generated upfront and saved. -@item -object tls-creds-x509,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},verify-peer=@var{on|off},passwordid=@var{id} +@item -object tls-creds-x509,id=@var{id},endpoint=@var{endpoint},dir=@var{/path/to/cred/dir},priority=@var{priority},verify-peer=@var{on|off},passwordid=@var{id} Creates a TLS anonymous credentials object, which can be used to provide TLS support on network backends. The @option{id} parameter is a unique @@ -4145,6 +4145,15 @@ version by providing the @var{passwordid} parameter. This provides the ID of a previously created @code{secret} object containing the password for decryption. +The @var{priority} parameter allows to override the global default +priority used by gnutls. This can be useful if the system administrator +needs to use a weaker set of crypto priorities for QEMU without +potentially forcing the weakness onto all applications. Or conversely +if one wants wants a stronger default for QEMU than for all other +applications, they can do this through this parameter. Its format is +a gnutls priority string as described at +@url{https://gnutls.org/manual/html_node/Priority-Strings.html}. + @item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}][,status=@var{on|off}] Interval @var{t} can't be 0, this filter batches the packet delivery: all diff --git a/roms/seabios-hppa b/roms/seabios-hppa -Subproject 649e6202b8d65d46c69f542b1380f840fbe8ab1 +Subproject 1ef99a01572c2581c30e16e6fe69e9ea2ef92ce diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 57daae05ea..d52207a3cc 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2356,6 +2356,18 @@ sub process { # check for missing bracing around if etc if ($line =~ /(^.*)\b(?:if|while|for)\b/ && $line !~ /\#\s*if/) { + my $allowed = 0; + + # Check the pre-context. + if ($line =~ /(\}.*?)$/) { + my $pre = $1; + + if ($line !~ /else/) { + print "APW: ALLOWED: pre<$pre> line<$line>\n" + if $dbg_adv_apw; + $allowed = 1; + } + } my ($level, $endln, @chunks) = ctx_statement_full($linenr, $realcnt, 1); if ($dbg_adv_apw) { @@ -2364,7 +2376,6 @@ sub process { if $#chunks >= 1; } if ($#chunks >= 0 && $level == 0) { - my $allowed = 0; my $seen = 0; my $herectx = $here . "\n"; my $ln = $linenr - 1; @@ -2408,7 +2419,7 @@ sub process { $allowed = 1; } } - if ($seen != ($#chunks + 1)) { + if ($seen != ($#chunks + 1) && !$allowed) { ERROR("braces {} are necessary for all arms of this statement\n" . $herectx); } } diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 24c7bf5a16..5d17dc68dd 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -217,7 +217,6 @@ ERROR_WHITELIST = [ {'exitcode':-6, 'log':r"Object .* is not an instance of type generic-pc-machine", 'loglevel':logging.ERROR}, {'exitcode':-6, 'log':r"Object .* is not an instance of type e500-ccsr", 'loglevel':logging.ERROR}, {'exitcode':-6, 'log':r"vmstate_register_with_alias_id: Assertion `!se->compat \|\| se->instance_id == 0' failed", 'loglevel':logging.ERROR}, - {'exitcode':-6, 'device':'isa-fdc', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'isa-serial', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'mioe3680_pci', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'pcm3680_pci', 'loglevel':logging.ERROR, 'expected':True}, diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c index 21e1b8ea60..d0f83176e1 100644 --- a/scsi/qemu-pr-helper.c +++ b/scsi/qemu-pr-helper.c @@ -924,6 +924,7 @@ int main(int argc, char **argv) Error *local_err = NULL; char *trace_file = NULL; bool daemonize = false; + bool pidfile_specified = false; unsigned socket_activation; struct sigaction sa_sigterm; @@ -954,6 +955,7 @@ int main(int argc, char **argv) case 'f': g_free(pidfile); pidfile = g_strdup(optarg); + pidfile_specified = true; break; #ifdef CONFIG_LIBCAP case 'u': { @@ -1081,20 +1083,22 @@ int main(int argc, char **argv) accept_client, NULL, NULL); -#ifdef CONFIG_LIBCAP - if (drop_privileges() < 0) { - error_report("Failed to drop privileges: %s", strerror(errno)); - exit(EXIT_FAILURE); - } -#endif - if (daemonize) { if (daemon(0, 0) < 0) { error_report("Failed to daemonize: %s", strerror(errno)); exit(EXIT_FAILURE); } + } + + if (daemonize || pidfile_specified) write_pidfile(); + +#ifdef CONFIG_LIBCAP + if (drop_privileges() < 0) { + error_report("Failed to drop privileges: %s", strerror(errno)); + exit(EXIT_FAILURE); } +#endif state = RUNNING; do { diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 555ae79d29..1a6b082b6f 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4761,6 +4761,7 @@ static Property x86_cpu_properties[] = { DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false), DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false), DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false), + DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false), DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 78db1b833a..1b219fafc4 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1296,6 +1296,7 @@ struct X86CPU { bool hyperv_runtime; bool hyperv_synic; bool hyperv_stimer; + bool hyperv_frequencies; bool check_cpuid; bool enforce_cpuid; bool expose_kvm; diff --git a/target/i386/kvm.c b/target/i386/kvm.c index d23fff12f5..6c49954e68 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -632,11 +632,6 @@ static int hyperv_handle_properties(CPUState *cs) X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; - if (cpu->hyperv_time && - kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) <= 0) { - cpu->hyperv_time = false; - } - if (cpu->hyperv_relaxed_timing) { env->features[FEAT_HYPERV_EAX] |= HV_HYPERCALL_AVAILABLE; } @@ -645,26 +640,61 @@ static int hyperv_handle_properties(CPUState *cs) env->features[FEAT_HYPERV_EAX] |= HV_APIC_ACCESS_AVAILABLE; } if (cpu->hyperv_time) { + if (kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) <= 0) { + fprintf(stderr, "Hyper-V clocksources " + "(requested by 'hv-time' cpu flag) " + "are not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_HYPERCALL_AVAILABLE; env->features[FEAT_HYPERV_EAX] |= HV_TIME_REF_COUNT_AVAILABLE; env->features[FEAT_HYPERV_EAX] |= HV_REFERENCE_TSC_AVAILABLE; - - if (has_msr_hv_frequencies && tsc_is_stable_and_known(env)) { - env->features[FEAT_HYPERV_EAX] |= HV_ACCESS_FREQUENCY_MSRS; - env->features[FEAT_HYPERV_EDX] |= HV_FREQUENCY_MSRS_AVAILABLE; + } + if (cpu->hyperv_frequencies) { + if (!has_msr_hv_frequencies) { + fprintf(stderr, "Hyper-V frequency MSRs " + "(requested by 'hv-frequencies' cpu flag) " + "are not supported by kernel\n"); + return -ENOSYS; } + env->features[FEAT_HYPERV_EAX] |= HV_ACCESS_FREQUENCY_MSRS; + env->features[FEAT_HYPERV_EDX] |= HV_FREQUENCY_MSRS_AVAILABLE; } - if (cpu->hyperv_crash && has_msr_hv_crash) { + if (cpu->hyperv_crash) { + if (!has_msr_hv_crash) { + fprintf(stderr, "Hyper-V crash MSRs " + "(requested by 'hv-crash' cpu flag) " + "are not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EDX] |= HV_GUEST_CRASH_MSR_AVAILABLE; } env->features[FEAT_HYPERV_EDX] |= HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE; - if (cpu->hyperv_reset && has_msr_hv_reset) { + if (cpu->hyperv_reset) { + if (!has_msr_hv_reset) { + fprintf(stderr, "Hyper-V reset MSR " + "(requested by 'hv-reset' cpu flag) " + "is not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_RESET_AVAILABLE; } - if (cpu->hyperv_vpindex && has_msr_hv_vpindex) { + if (cpu->hyperv_vpindex) { + if (!has_msr_hv_vpindex) { + fprintf(stderr, "Hyper-V VP_INDEX MSR " + "(requested by 'hv-vpindex' cpu flag) " + "is not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_VP_INDEX_AVAILABLE; } - if (cpu->hyperv_runtime && has_msr_hv_runtime) { + if (cpu->hyperv_runtime) { + if (!has_msr_hv_runtime) { + fprintf(stderr, "Hyper-V VP_RUNTIME MSR " + "(requested by 'hv-runtime' cpu flag) " + "is not supported by kernel\n"); + return -ENOSYS; + } env->features[FEAT_HYPERV_EAX] |= HV_VP_RUNTIME_AVAILABLE; } if (cpu->hyperv_synic) { diff --git a/target/i386/sev.c b/target/i386/sev.c index 019d84cef2..c01167143f 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -748,9 +748,11 @@ sev_guest_init(const char *id) if (s->sev_fd < 0) { error_report("%s: Failed to open %s '%s'", __func__, devname, strerror(errno)); - goto err; } g_free(devname); + if (s->sev_fd < 0) { + goto err; + } ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status, &fw_error); diff --git a/target/i386/translate.c b/target/i386/translate.c index 0135415d92..c9ed8dc709 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -3802,7 +3802,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - tcg_gen_andc_tl(cpu_T0, cpu_regs[s->vex_v], cpu_T0); + tcg_gen_andc_tl(cpu_T0, cpu_T0, cpu_regs[s->vex_v]); gen_op_mov_reg_v(ot, reg, cpu_T0); gen_op_update1_cc(); set_cc_op(s, CC_OP_LOGICB + ot); @@ -4563,9 +4563,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) #endif rex_r = (~vex2 >> 4) & 8; if (b == 0xc5) { + /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */ vex3 = vex2; - b = x86_ldub_code(env, s); + b = x86_ldub_code(env, s) | 0x100; } else { + /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */ #ifdef TARGET_X86_64 s->rex_x = (~vex2 >> 3) & 8; s->rex_b = (~vex2 >> 2) & 8; diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index bf33d320bf..58435178a4 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -911,12 +911,62 @@ static int whpx_vcpu_run(CPUState *cpu) ret = 1; break; + case WHvRunVpExitReasonX64Cpuid: { + WHV_REGISTER_VALUE reg_values[5] = {0}; + WHV_REGISTER_NAME reg_names[5]; + UINT32 reg_count = 5; + UINT64 rip, rax, rcx, rdx, rbx; + + rip = vcpu->exit_ctx.VpContext.Rip + + vcpu->exit_ctx.VpContext.InstructionLength; + switch (vcpu->exit_ctx.CpuidAccess.Rax) { + case 1: + rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; + /* Advertise that we are running on a hypervisor */ + rcx = + vcpu->exit_ctx.CpuidAccess.DefaultResultRcx | + CPUID_EXT_HYPERVISOR; + + rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; + rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; + break; + default: + rax = vcpu->exit_ctx.CpuidAccess.DefaultResultRax; + rcx = vcpu->exit_ctx.CpuidAccess.DefaultResultRcx; + rdx = vcpu->exit_ctx.CpuidAccess.DefaultResultRdx; + rbx = vcpu->exit_ctx.CpuidAccess.DefaultResultRbx; + } + + reg_names[0] = WHvX64RegisterRip; + reg_names[1] = WHvX64RegisterRax; + reg_names[2] = WHvX64RegisterRcx; + reg_names[3] = WHvX64RegisterRdx; + reg_names[4] = WHvX64RegisterRbx; + + reg_values[0].Reg64 = rip; + reg_values[1].Reg64 = rax; + reg_values[2].Reg64 = rcx; + reg_values[3].Reg64 = rdx; + reg_values[4].Reg64 = rbx; + + hr = WHvSetVirtualProcessorRegisters(whpx->partition, + cpu->cpu_index, + reg_names, + reg_count, + reg_values); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set CpuidAccess state registers," + " hr=%08lx", hr); + } + ret = 0; + break; + } case WHvRunVpExitReasonNone: case WHvRunVpExitReasonUnrecoverableException: case WHvRunVpExitReasonInvalidVpRegisterValue: case WHvRunVpExitReasonUnsupportedFeature: case WHvRunVpExitReasonX64MsrAccess: - case WHvRunVpExitReasonX64Cpuid: case WHvRunVpExitReasonException: default: error_report("WHPX: Unexpected VP exit code %d", @@ -1272,6 +1322,33 @@ static int whpx_accel_init(MachineState *ms) goto error; } + memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); + prop.ExtendedVmExits.X64CpuidExit = 1; + hr = WHvSetPartitionProperty(whpx->partition, + WHvPartitionPropertyCodeExtendedVmExits, + &prop, + sizeof(WHV_PARTITION_PROPERTY)); + + if (FAILED(hr)) { + error_report("WHPX: Failed to enable partition extended X64CpuidExit" + " hr=%08lx", hr); + ret = -EINVAL; + goto error; + } + + UINT32 cpuidExitList[] = {1}; + hr = WHvSetPartitionProperty(whpx->partition, + WHvPartitionPropertyCodeCpuidExitList, + cpuidExitList, + RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32)); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set partition CpuidExitList hr=%08lx", + hr); + ret = -EINVAL; + goto error; + } + hr = WHvSetupPartition(whpx->partition); if (FAILED(hr)) { error_report("WHPX: Failed to setup partition, hr=%08lx", hr); diff --git a/target/s390x/helper.c b/target/s390x/helper.c index 615fa24ab9..e8548f340a 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -103,16 +103,18 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr) env->psw.addr = addr; env->psw.mask = mask; - if (tcg_enabled()) { - env->cc_op = (mask >> 44) & 3; + + /* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */ + if (!tcg_enabled()) { + return; } + env->cc_op = (mask >> 44) & 3; if ((old_mask ^ mask) & PSW_MASK_PER) { s390_cpu_recompute_watchpoints(CPU(s390_env_get_cpu(env))); } - /* KVM will handle all WAITs and trigger a WAIT exit on disabled_wait */ - if (tcg_enabled() && (mask & PSW_MASK_WAIT)) { + if (mask & PSW_MASK_WAIT) { s390_handle_wait(s390_env_get_cpu(env)); } } diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index f570896dc1..fb59d92def 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1778,6 +1778,8 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) qemu_mutex_lock_iothread(); + cpu_synchronize_state(cs); + switch (run->exit_reason) { case KVM_EXIT_S390_SIEIC: ret = handle_intercept(cpu); diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 1deeb6e6e4..a25deef5dd 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -325,7 +325,7 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr, r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw, exc); - if (rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) { + if (!r && rw == MMU_DATA_STORE && !(*flags & PAGE_WRITE)) { trigger_prot_fault(env, vaddr, asc, rw, exc); return -1; } diff --git a/tests/docker/common.rc b/tests/docker/common.rc index 7951555e3f..046f8a5921 100755 --- a/tests/docker/common.rc +++ b/tests/docker/common.rc @@ -30,7 +30,9 @@ build_qemu() $@" echo "Configure options:" echo $config_opts - $QEMU_SRC/configure $config_opts && make $MAKEFLAGS + $QEMU_SRC/configure $config_opts || \ + { cat config.log && test_fail "Failed to run 'configure'"; } + make $MAKEFLAGS } test_fail() diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index a00004319e..b706f42405 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -1,9 +1,16 @@ FROM fedora:27 ENV PACKAGES \ ccache gettext git tar PyYAML sparse flex bison python3 bzip2 hostname \ - glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \ - gcc gcc-c++ llvm clang make perl which bc findutils libaio-devel \ - nettle-devel libasan libubsan \ + gcc gcc-c++ llvm clang make perl which bc findutils glib2-devel \ + libaio-devel pixman-devel zlib-devel libfdt-devel libasan libubsan \ + bluez-libs-devel brlapi-devel bzip2-devel \ + device-mapper-multipath-devel glusterfs-api-devel gnutls-devel \ + gtk3-devel libattr-devel libcap-devel libcap-ng-devel libcurl-devel \ + libjpeg-devel libpng-devel librbd-devel libssh2-devel libusbx-devel \ + libxml2-devel lzo-devel ncurses-devel nettle-devel nss-devel \ + numactl-devel SDL2-devel snappy-devel spice-server-devel \ + systemtap-sdt-devel usbredir-devel virglrenderer-devel vte3-devel \ + xen-devel \ mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config \ mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1 \ mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2 \ diff --git a/tests/docker/run b/tests/docker/run index 9dd362bb98..7aebf4b569 100755 --- a/tests/docker/run +++ b/tests/docker/run @@ -29,7 +29,7 @@ export TEST_DIR=/tmp/qemu-test mkdir -p $TEST_DIR/{src,build,install} # Extract the source tarballs -tar -C $TEST_DIR/src -xf $BASE/qemu.tar || prep_fail "Failed to untar source" +tar -C $TEST_DIR/src -xf $BASE/qemu.tar || { echo "Failed to untar source"; exit 2; } if test -f $TEST_DIR/src/Makefile; then export FEATURES="$FEATURES dtc" fi diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out index 830c11880a..b01f9a90d7 100644 --- a/tests/qemu-iotests/051.pc.out +++ b/tests/qemu-iotests/051.pc.out @@ -117,20 +117,10 @@ Testing: -drive if=ide,media=cdrom QEMU X.Y.Z monitor - type 'help' for more information (qemu) quit -Testing: -drive if=scsi,media=cdrom -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive if=scsi,media=cdrom: warning: bus=0,unit=0 is deprecated with this machine type -quit - Testing: -drive if=ide QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: Initialization of device ide-hd failed: Device needs media, but drive is empty -Testing: -drive if=scsi -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive if=scsi: warning: bus=0,unit=0 is deprecated with this machine type -QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty - Testing: -drive if=virtio QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty @@ -170,20 +160,10 @@ Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on QEMU X.Y.Z monitor - type 'help' for more information (qemu) quit -Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on: warning: bus=0,unit=0 is deprecated with this machine type -quit - Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on QEMU X.Y.Z monitor - type 'help' for more information (qemu) QEMU_PROG: Initialization of device ide-hd failed: Block node is read-only -Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on: warning: bus=0,unit=0 is deprecated with this machine type -quit - Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on QEMU X.Y.Z monitor - type 'help' for more information (qemu) quit diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106 index bfe71f4e60..5e51f88a78 100755 --- a/tests/qemu-iotests/106 +++ b/tests/qemu-iotests/106 @@ -86,6 +86,30 @@ for growth_mode in falloc full off; do $QEMU_IMG resize -f "$IMGFMT" --shrink --preallocation=$growth_mode "$TEST_IMG" -${GROWTH_SIZE}K done +echo +echo '=== Testing image growth on 2G empty image ===' + +for growth_mode in falloc full; do + echo + echo "--- growth_mode=$growth_mode ---" + + # Maybe we want to do an lseek() to the end of the file before the + # preallocation; if the file has a length of 2 GB, that would + # return an integer that overflows to negative when put into a + # plain int. We should use the correct type for the result, and + # this tests we do. + + _make_test_img 2G + $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K + + actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') + actual_size=$(echo "$actual_size" | sed -e 's/^[^0-9]*\([0-9]\+\).*$/\1/') + + if [ $actual_size -lt $GROWTH_SIZE ]; then + echo "ERROR: Image should have at least ${GROWTH_SIZE}K, but has ${actual_size}K" + fi +done + # success, all done echo '*** done' rm -f $seq.full diff --git a/tests/qemu-iotests/106.out b/tests/qemu-iotests/106.out index 0a42312301..c459957660 100644 --- a/tests/qemu-iotests/106.out +++ b/tests/qemu-iotests/106.out @@ -47,4 +47,14 @@ qemu-img: Preallocation can only be used for growing images --- growth_mode=off --- Image resized. + +=== Testing image growth on 2G empty image === + +--- growth_mode=falloc --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 +Image resized. + +--- growth_mode=full --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 +Image resized. *** done diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122 index 45b359c2ba..6cf4fcb866 100755 --- a/tests/qemu-iotests/122 +++ b/tests/qemu-iotests/122 @@ -130,6 +130,53 @@ $QEMU_IO -c "read -P 0 1024k 1022k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _fil echo +echo "=== Corrupted size field in compressed cluster descriptor ===" +echo +# Create an empty image and fill half of it with compressed data. +# The L2 entries of the two compressed clusters are located at +# 0x800000 and 0x800008, their original values are 0x4008000000a00000 +# and 0x4008000000a00802 (5 sectors for compressed data each). +_make_test_img 8M -o cluster_size=2M +$QEMU_IO -c "write -c -P 0x11 0 2M" -c "write -c -P 0x11 2M 2M" "$TEST_IMG" \ + 2>&1 | _filter_qemu_io | _filter_testdir + +# Reduce size of compressed data to 4 sectors: this corrupts the image. +poke_file "$TEST_IMG" $((0x800000)) "\x40\x06" +$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir + +# 'qemu-img check' however doesn't see anything wrong because it +# doesn't try to decompress the data and the refcounts are consistent. +# TODO: update qemu-img so this can be detected. +_check_test_img + +# Increase size of compressed data to the maximum (8192 sectors). +# This makes QEMU read more data (8192 sectors instead of 5, host +# addresses [0xa00000, 0xdfffff]), but the decompression algorithm +# stops once we have enough to restore the uncompressed cluster, so +# the rest of the data is ignored. +poke_file "$TEST_IMG" $((0x800000)) "\x7f\xfe" +# Do it also for the second compressed cluster (L2 entry at 0x800008). +# In this case the compressed data would span 3 host clusters +# (host addresses: [0xa00802, 0xe00801]) +poke_file "$TEST_IMG" $((0x800008)) "\x7f\xfe" + +# Here the image is too small so we're asking QEMU to read beyond the +# end of the image. +$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir +# But if we grow the image we won't be reading beyond its end anymore. +$QEMU_IO -c "write -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir +$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir + +# The refcount data is however wrong because due to the increased size +# of the compressed data it now reaches the following host clusters. +# This can be repaired by qemu-img check by increasing the refcount of +# those clusters. +# TODO: update qemu-img to correct the compressed cluster size instead. +_check_test_img -r all +$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir +$QEMU_IO -c "read -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir + +echo echo "=== Full allocation with -S 0 ===" echo diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out index 47d8656db8..a6b7fe007e 100644 --- a/tests/qemu-iotests/122.out +++ b/tests/qemu-iotests/122.out @@ -99,6 +99,39 @@ read 1024/1024 bytes at offset 1047552 read 1046528/1046528 bytes at offset 1048576 1022 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +=== Corrupted size field in compressed cluster descriptor === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608 +wrote 2097152/2097152 bytes at offset 0 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 2097152/2097152 bytes at offset 2097152 +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read failed: Input/output error +No errors were found on the image. +read 4194304/4194304 bytes at offset 0 +4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 4194304/4194304 bytes at offset 4194304 +4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4194304/4194304 bytes at offset 0 +4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +ERROR cluster 6 refcount=1 reference=3 +ERROR cluster 7 refcount=1 reference=2 +Repairing cluster 6 refcount=1 reference=3 +Repairing cluster 7 refcount=1 reference=2 +Repairing OFLAG_COPIED data cluster: l2_entry=8000000000c00000 refcount=3 +Repairing OFLAG_COPIED data cluster: l2_entry=8000000000e00000 refcount=2 +The following inconsistencies were found and repaired: + + 0 leaked clusters + 4 corruptions + +Double checking the fixed image now... +No errors were found on the image. +read 4194304/4194304 bytes at offset 0 +4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 4194304/4194304 bytes at offset 4194304 +4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + === Full allocation with -S 0 === Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186 index 44cc01ed87..0aa4395a57 100755 --- a/tests/qemu-iotests/186 +++ b/tests/qemu-iotests/186 @@ -64,7 +64,7 @@ function check_info_block() { echo "info block" | do_run_qemu "$@" | _filter_win32 | _filter_hmp | _filter_qemu | - _filter_generated_node_ids + _filter_generated_node_ids | _filter_qom_path } @@ -133,10 +133,6 @@ check_info_block -drive if=ide,driver=null-co check_info_block -drive if=ide,media=cdrom check_info_block -drive if=ide,driver=null-co,media=cdrom -check_info_block -drive if=scsi,driver=null-co -check_info_block -drive if=scsi,media=cdrom -check_info_block -drive if=scsi,driver=null-co,media=cdrom - check_info_block -drive if=virtio,driver=null-co check_info_block -drive if=pflash,driver=null-co,size=1M diff --git a/tests/qemu-iotests/186.out b/tests/qemu-iotests/186.out index c8377fe146..716b01ac3d 100644 --- a/tests/qemu-iotests/186.out +++ b/tests/qemu-iotests/186.out @@ -7,7 +7,7 @@ Testing: -device floppy QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block /machine/peripheral-anon/device[1]: [not inserted] - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -23,7 +23,7 @@ Testing: -device ide-cd QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block /machine/peripheral-anon/device[1]: [not inserted] - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -39,7 +39,7 @@ Testing: -device scsi-cd QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block /machine/peripheral-anon/device[1]: [not inserted] - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -58,7 +58,7 @@ Testing: -blockdev driver=null-co,node-name=null -device ide-hd,drive=null QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block null: null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Cache mode: writeback (qemu) quit @@ -74,7 +74,7 @@ Testing: -blockdev driver=null-co,node-name=null -device scsi-hd,drive=null QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block null: null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Cache mode: writeback (qemu) quit @@ -90,7 +90,7 @@ Testing: -blockdev driver=null-co,node-name=null -device virtio-blk-pci,drive=nu QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block null: null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1]/virtio-backend + Attached to: PATH Cache mode: writeback (qemu) quit @@ -98,7 +98,7 @@ Testing: -blockdev driver=null-co,node-name=null -device virtio-blk-pci,drive=nu QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block null: null-co:// (null-co) - Attached to: /machine/peripheral/qdev_id/virtio-backend + Attached to: PATH Cache mode: writeback (qemu) quit @@ -106,7 +106,7 @@ Testing: -blockdev driver=null-co,node-name=null -device floppy,drive=null QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block null: null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -124,7 +124,7 @@ Testing: -blockdev driver=null-co,node-name=null -device ide-cd,drive=null QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block null: null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -142,7 +142,7 @@ Testing: -blockdev driver=null-co,node-name=null -device scsi-cd,drive=null QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block null: null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -191,7 +191,7 @@ none0 (null): null-co:// (null-co) Cache mode: writeback null: null-co:// (null-co) - Attached to: /machine/peripheral/qdev_id/virtio-backend + Attached to: PATH Cache mode: writeback (qemu) quit @@ -241,7 +241,7 @@ Testing: -drive if=none,driver=null-co,node-name=null -device ide-hd,drive=none0 QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0 (null): null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Cache mode: writeback (qemu) quit @@ -257,7 +257,7 @@ Testing: -drive if=none,driver=null-co,node-name=null -device scsi-hd,drive=none QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0 (null): null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Cache mode: writeback (qemu) quit @@ -273,7 +273,7 @@ Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,dri QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0 (null): null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1]/virtio-backend + Attached to: PATH Cache mode: writeback (qemu) quit @@ -281,7 +281,7 @@ Testing: -drive if=none,driver=null-co,node-name=null -device virtio-blk-pci,dri QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0 (null): null-co:// (null-co) - Attached to: /machine/peripheral/qdev_id/virtio-backend + Attached to: PATH Cache mode: writeback (qemu) quit @@ -289,7 +289,7 @@ Testing: -drive if=none,driver=null-co,node-name=null -device floppy,drive=none0 QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0 (null): null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -307,7 +307,7 @@ Testing: -drive if=none,driver=null-co,node-name=null -device ide-cd,drive=none0 QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0 (null): null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -325,7 +325,7 @@ Testing: -drive if=none,driver=null-co,node-name=null -device scsi-cd,drive=none QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0 (null): null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -353,7 +353,7 @@ Testing: -drive if=none -device floppy,drive=none0 QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0: [not inserted] - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -369,7 +369,7 @@ Testing: -drive if=none -device ide-cd,drive=none0 QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0: [not inserted] - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -385,7 +385,7 @@ Testing: -drive if=none -device scsi-cd,drive=none0 QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block none0: [not inserted] - Attached to: /machine/peripheral-anon/device[1] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -404,7 +404,7 @@ Testing: -drive if=floppy QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block floppy0: [not inserted] - Attached to: /machine/unattached/device[17] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -412,7 +412,7 @@ Testing: -drive if=floppy,driver=null-co QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block floppy0 (NODE_NAME): null-co:// (null-co) - Attached to: /machine/unattached/device[17] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -421,7 +421,7 @@ Testing: -drive if=ide,driver=null-co QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block ide0-hd0 (NODE_NAME): null-co:// (null-co) - Attached to: /machine/unattached/device[18] + Attached to: PATH Cache mode: writeback (qemu) quit @@ -429,7 +429,7 @@ Testing: -drive if=ide,media=cdrom QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block ide0-cd0: [not inserted] - Attached to: /machine/unattached/device[18] + Attached to: PATH Removable device: not locked, tray closed (qemu) quit @@ -437,35 +437,7 @@ Testing: -drive if=ide,driver=null-co,media=cdrom QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block ide0-cd0 (NODE_NAME): null-co:// (null-co, read-only) - Attached to: /machine/unattached/device[18] - Removable device: not locked, tray closed - Cache mode: writeback -(qemu) quit - -Testing: -drive if=scsi,driver=null-co -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive if=scsi,driver=null-co: warning: bus=0,unit=0 is deprecated with this machine type -info block -scsi0-hd0 (NODE_NAME): null-co:// (null-co) - Attached to: /machine/unattached/device[27]/scsi.0/legacy[0] - Cache mode: writeback -(qemu) quit - -Testing: -drive if=scsi,media=cdrom -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive if=scsi,media=cdrom: warning: bus=0,unit=0 is deprecated with this machine type -info block -scsi0-cd0: [not inserted] - Attached to: /machine/unattached/device[27]/scsi.0/legacy[0] - Removable device: not locked, tray closed -(qemu) quit - -Testing: -drive if=scsi,driver=null-co,media=cdrom -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -drive if=scsi,driver=null-co,media=cdrom: warning: bus=0,unit=0 is deprecated with this machine type -info block -scsi0-cd0 (NODE_NAME): null-co:// (null-co, read-only) - Attached to: /machine/unattached/device[27]/scsi.0/legacy[0] + Attached to: PATH Removable device: not locked, tray closed Cache mode: writeback (qemu) quit @@ -474,7 +446,7 @@ Testing: -drive if=virtio,driver=null-co QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block virtio0 (NODE_NAME): null-co:// (null-co) - Attached to: /machine/peripheral-anon/device[1]/virtio-backend + Attached to: PATH Cache mode: writeback (qemu) quit @@ -482,7 +454,7 @@ Testing: -drive if=pflash,driver=null-co,size=1M QEMU X.Y.Z monitor - type 'help' for more information (qemu) info block pflash0 (NODE_NAME): json:{"driver": "null-co", "size": "1M"} (null-co) - Attached to: /machine/unattached/device[2] + Attached to: PATH Cache mode: writeback (qemu) quit diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208 index 4e82b96c82..18f59ada94 100755 --- a/tests/qemu-iotests/208 +++ b/tests/qemu-iotests/208 @@ -28,7 +28,7 @@ with iotests.FilePath('disk.img') as disk_img_path, \ iotests.VM() as vm: img_size = '10M' - iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk_img_path, img_size) + iotests.qemu_img_create('-f', iotests.imgfmt, disk_img_path, img_size) iotests.log('Launching VM...') (vm.add_drive(disk_img_path, 'node-name=drive0-node', interface='none') diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index ec8033350d..aa94c6c7ea 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -538,8 +538,8 @@ if [ -z "$QEMU_PROG" ] then if [ -x "$build_iotests/qemu" ]; then export QEMU_PROG="$build_iotests/qemu" - elif [ -x "$build_root/$arch-softmmu/qemu-system-$arch" ]; then - export QEMU_PROG="$build_root/$arch-softmmu/qemu-system-$arch" + elif [ -x "$build_root/${qemu_arch}-softmmu/qemu-system-${qemu_arch}" ]; then + export QEMU_PROG="$build_root/${qemu_arch}-softmmu/qemu-system-${qemu_arch}" else pushd "$build_root" > /dev/null for binary in *-softmmu/qemu-system-* diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config index cdcda54546..102aa6878a 100644 --- a/tests/qemu-iotests/common.config +++ b/tests/qemu-iotests/common.config @@ -23,6 +23,7 @@ PATH=".:$PATH" HOSTOS=`uname -s` arch=`uname -m` +[[ "$arch" =~ "ppc64" ]] && qemu_arch=ppc64 || qemu_arch="$arch" export PWD=`pwd` diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index cb2be23340..c5f4bcf578 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -32,6 +32,11 @@ _filter_generated_node_ids() sed -re 's/\#block[0-9]{3,}/NODE_NAME/' } +_filter_qom_path() +{ + sed -e 's#\(Attached to: *\) /.*#\1 PATH#' +} + # replace occurrences of the actual TEST_DIR value with TEST_DIR _filter_testdir() { diff --git a/tests/test-crypto-tlssession.c b/tests/test-crypto-tlssession.c index 1a4a066d76..82f21c27f2 100644 --- a/tests/test-crypto-tlssession.c +++ b/tests/test-crypto-tlssession.c @@ -75,6 +75,7 @@ static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint, "server" : "client"), "dir", certdir, "verify-peer", "yes", + "priority", "NORMAL", /* We skip initial sanity checks here because we * want to make sure that problems are being * detected at the TLS session validation stage, diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c index 32743b2c96..bb88ee870f 100644 --- a/tests/test-io-channel-tls.c +++ b/tests/test-io-channel-tls.c @@ -78,6 +78,7 @@ static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint, "server" : "client"), "dir", certdir, "verify-peer", "yes", + "priority", "NORMAL", /* We skip initial sanity checks here because we * want to make sure that problems are being * detected at the TLS session validation stage, diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py index 686d88decf..3a2d508c35 100755 --- a/tests/vm/basevm.py +++ b/tests/vm/basevm.py @@ -107,10 +107,7 @@ class BaseVM(object): assert not isinstance(cmd, str) ssh_cmd += ["%s@127.0.0.1" % user] + list(cmd) logging.debug("ssh_cmd: %s", " ".join(ssh_cmd)) - r = subprocess.call(ssh_cmd, - stdin=sys.stdin if interactive else self._devnull, - stdout=sys.stdout if interactive else self._stdout, - stderr=sys.stderr if interactive else self._stderr) + r = subprocess.call(ssh_cmd) if check and r != 0: raise Exception("SSH command failed: %s" % cmd) return r diff --git a/ui/console.c b/ui/console.c index 530a491987..3fb2f4e09f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1191,11 +1191,22 @@ static const int qcode_to_keysym[Q_KEY_CODE__MAX] = { [Q_KEY_CODE_BACKSPACE] = QEMU_KEY_BACKSPACE, }; -bool kbd_put_qcode_console(QemuConsole *s, int qcode) +static const int ctrl_qcode_to_keysym[Q_KEY_CODE__MAX] = { + [Q_KEY_CODE_UP] = QEMU_KEY_CTRL_UP, + [Q_KEY_CODE_DOWN] = QEMU_KEY_CTRL_DOWN, + [Q_KEY_CODE_RIGHT] = QEMU_KEY_CTRL_RIGHT, + [Q_KEY_CODE_LEFT] = QEMU_KEY_CTRL_LEFT, + [Q_KEY_CODE_HOME] = QEMU_KEY_CTRL_HOME, + [Q_KEY_CODE_END] = QEMU_KEY_CTRL_END, + [Q_KEY_CODE_PGUP] = QEMU_KEY_CTRL_PAGEUP, + [Q_KEY_CODE_PGDN] = QEMU_KEY_CTRL_PAGEDOWN, +}; + +bool kbd_put_qcode_console(QemuConsole *s, int qcode, bool ctrl) { int keysym; - keysym = qcode_to_keysym[qcode]; + keysym = ctrl ? ctrl_qcode_to_keysym[qcode] : qcode_to_keysym[qcode]; if (keysym == 0) { return false; } @@ -1197,12 +1197,12 @@ static gboolean gd_text_key_down(GtkWidget *widget, QemuConsole *con = vc->gfx.dcl.con; if (key->keyval == GDK_KEY_Delete) { - kbd_put_qcode_console(con, Q_KEY_CODE_DELETE); + kbd_put_qcode_console(con, Q_KEY_CODE_DELETE, false); } else if (key->length) { kbd_put_string_console(con, key->string, key->length); } else { int qcode = gd_map_keycode(key->hardware_keycode); - kbd_put_qcode_console(con, qcode); + kbd_put_qcode_console(con, qcode, false); } return TRUE; } diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c index 5e1073a084..c3683e6b65 100644 --- a/ui/sdl2-gl.c +++ b/ui/sdl2-gl.c @@ -32,8 +32,6 @@ #include "ui/sdl2.h" #include "sysemu/sysemu.h" -#include <epoxy/gl.h> - static void sdl2_set_scanout_mode(struct sdl2_console *scon, bool scanout) { if (scon->scanout_mode == scanout) { diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c index 605d781971..1378b63dd9 100644 --- a/ui/sdl2-input.c +++ b/ui/sdl2-input.c @@ -60,32 +60,8 @@ void sdl2_process_key(struct sdl2_console *scon, qcode = qemu_input_map_usb_to_qcode[ev->keysym.scancode]; - if (!qemu_console_is_graphic(con)) { - if (ev->type == SDL_KEYDOWN) { - switch (ev->keysym.scancode) { - case SDL_SCANCODE_RETURN: - kbd_put_keysym_console(con, '\n'); - break; - case SDL_SCANCODE_BACKSPACE: - kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE); - break; - default: - kbd_put_qcode_console(con, qcode); - break; - } - } - return; - } - + /* modifier state tracking */ switch (ev->keysym.scancode) { -#if 0 - case SDL_SCANCODE_NUMLOCKCLEAR: - case SDL_SCANCODE_CAPSLOCK: - /* SDL does not send the key up event, so we generate it */ - qemu_input_event_send_key_qcode(con, qcode, true); - qemu_input_event_send_key_qcode(con, qcode, false); - return; -#endif case SDL_SCANCODE_LCTRL: case SDL_SCANCODE_LSHIFT: case SDL_SCANCODE_LALT: @@ -99,8 +75,26 @@ void sdl2_process_key(struct sdl2_console *scon, } else { modifiers_state[ev->keysym.scancode] = 1; } - /* fall though */ + break; default: + /* nothing */ + break; + } + + if (!qemu_console_is_graphic(con)) { + bool ctrl = (modifiers_state[SDL_SCANCODE_LCTRL] || + modifiers_state[SDL_SCANCODE_RCTRL]); + if (ev->type == SDL_KEYDOWN) { + switch (ev->keysym.scancode) { + case SDL_SCANCODE_RETURN: + kbd_put_keysym_console(con, '\n'); + break; + default: + kbd_put_qcode_console(con, qcode, ctrl); + break; + } + } + } else { qemu_input_event_send_key_qcode(con, qcode, ev->type == SDL_KEYDOWN); } diff --git a/util/memfd.c b/util/memfd.c index 07d579ea7d..b3ecbac19e 100644 --- a/util/memfd.c +++ b/util/memfd.c @@ -173,7 +173,13 @@ enum { MEMFD_TODO }; -bool qemu_memfd_check(void) +/** + * qemu_memfd_alloc_check(): + * + * Check if qemu_memfd_alloc() can allocate, including using a + * fallback implementation when host doesn't support memfd. + */ +bool qemu_memfd_alloc_check(void) { static int memfd_check = MEMFD_TODO; @@ -188,3 +194,29 @@ bool qemu_memfd_check(void) return memfd_check == MEMFD_OK; } + +/** + * qemu_memfd_check(): + * + * Check if host supports memfd. + */ +bool qemu_memfd_check(void) +{ +#ifdef CONFIG_LINUX + static int memfd_check = MEMFD_TODO; + + if (memfd_check == MEMFD_TODO) { + int mfd = memfd_create("test", 0); + if (mfd >= 0) { + memfd_check = MEMFD_OK; + close(mfd); + } else { + memfd_check = MEMFD_KO; + } + } + + return memfd_check == MEMFD_OK; +#else + return false; +#endif +} diff --git a/util/sys_membarrier.c b/util/sys_membarrier.c index 8dcb53e63e..1362c0c4c5 100644 --- a/util/sys_membarrier.c +++ b/util/sys_membarrier.c @@ -6,9 +6,9 @@ * Author: Paolo Bonzini <pbonzini@redhat.com> */ -#include <qemu/osdep.h> -#include <qemu/sys_membarrier.h> -#include <qemu/error-report.h> +#include "qemu/osdep.h" +#include "qemu/sys_membarrier.h" +#include "qemu/error-report.h" #ifdef CONFIG_LINUX #include <linux/membarrier.h> |