diff options
57 files changed, 811 insertions, 403 deletions
diff --git a/arch_init.c b/arch_init.c index 77912e7a7d..80574a090c 100644 --- a/arch_init.c +++ b/arch_init.c @@ -164,20 +164,22 @@ static struct { uint8_t *encoded_buf; /* buffer for storing page content */ uint8_t *current_buf; - /* buffer used for XBZRLE decoding */ - uint8_t *decoded_buf; /* Cache for XBZRLE */ PageCache *cache; } XBZRLE = { .encoded_buf = NULL, .current_buf = NULL, - .decoded_buf = NULL, .cache = NULL, }; - +/* buffer used for XBZRLE decoding */ +static uint8_t *xbzrle_decoded_buf; int64_t xbzrle_cache_resize(int64_t new_size) { + if (new_size < TARGET_PAGE_SIZE) { + return -1; + } + if (XBZRLE.cache != NULL) { return cache_resize(XBZRLE.cache, new_size / TARGET_PAGE_SIZE) * TARGET_PAGE_SIZE; @@ -282,7 +284,9 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, if (!cache_is_cached(XBZRLE.cache, current_addr)) { if (!last_stage) { - cache_insert(XBZRLE.cache, current_addr, current_data); + if (cache_insert(XBZRLE.cache, current_addr, current_data) == -1) { + return -1; + } } acct_info.xbzrle_cache_miss++; return -1; @@ -602,6 +606,12 @@ uint64_t ram_bytes_total(void) return total; } +void free_xbzrle_decoded_buf(void) +{ + g_free(xbzrle_decoded_buf); + xbzrle_decoded_buf = NULL; +} + static void migration_end(void) { if (migration_bitmap) { @@ -615,8 +625,9 @@ static void migration_end(void) g_free(XBZRLE.cache); g_free(XBZRLE.encoded_buf); g_free(XBZRLE.current_buf); - g_free(XBZRLE.decoded_buf); XBZRLE.cache = NULL; + XBZRLE.encoded_buf = NULL; + XBZRLE.current_buf = NULL; } } @@ -655,8 +666,22 @@ static int ram_save_setup(QEMUFile *f, void *opaque) DPRINTF("Error creating cache\n"); return -1; } - XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE); - XBZRLE.current_buf = g_malloc(TARGET_PAGE_SIZE); + + /* We prefer not to abort if there is no memory */ + XBZRLE.encoded_buf = g_try_malloc0(TARGET_PAGE_SIZE); + if (!XBZRLE.encoded_buf) { + DPRINTF("Error allocating encoded_buf\n"); + return -1; + } + + XBZRLE.current_buf = g_try_malloc(TARGET_PAGE_SIZE); + if (!XBZRLE.current_buf) { + DPRINTF("Error allocating current_buf\n"); + g_free(XBZRLE.encoded_buf); + XBZRLE.encoded_buf = NULL; + return -1; + } + acct_clear(); } @@ -807,8 +832,8 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) unsigned int xh_len; int xh_flags; - if (!XBZRLE.decoded_buf) { - XBZRLE.decoded_buf = g_malloc(TARGET_PAGE_SIZE); + if (!xbzrle_decoded_buf) { + xbzrle_decoded_buf = g_malloc(TARGET_PAGE_SIZE); } /* extract RLE header */ @@ -825,10 +850,10 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) return -1; } /* load data and decode */ - qemu_get_buffer(f, XBZRLE.decoded_buf, xh_len); + qemu_get_buffer(f, xbzrle_decoded_buf, xh_len); /* decode RLE */ - ret = xbzrle_decode_buffer(XBZRLE.decoded_buf, xh_len, host, + ret = xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host, TARGET_PAGE_SIZE); if (ret == -1) { fprintf(stderr, "Failed to load XBZRLE page - decode error!\n"); diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 5af436c31d..fceee50adb 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -25,8 +25,17 @@ #include "audio.h" #include "audio_int.h" -#define LINE_IN_SAMPLES 1024 -#define LINE_OUT_SAMPLES 1024 +#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 +#define LINE_OUT_SAMPLES (480 * 4) +#else +#define LINE_OUT_SAMPLES (256 * 4) +#endif + +#if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 +#define LINE_IN_SAMPLES (480 * 4) +#else +#define LINE_IN_SAMPLES (256 * 4) +#endif typedef struct SpiceRateCtl { int64_t start_ticks; @@ -111,7 +120,11 @@ static int line_out_init (HWVoiceOut *hw, struct audsettings *as) SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); struct audsettings settings; +#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 + settings.freq = spice_server_get_best_playback_rate(NULL); +#else settings.freq = SPICE_INTERFACE_PLAYBACK_FREQ; +#endif settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN; settings.fmt = AUD_FMT_S16; settings.endianness = AUDIO_HOST_ENDIANNESS; @@ -122,6 +135,9 @@ static int line_out_init (HWVoiceOut *hw, struct audsettings *as) out->sin.base.sif = &playback_sif.base; qemu_spice_add_interface (&out->sin.base); +#if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 + spice_server_set_playback_rate(&out->sin, settings.freq); +#endif return 0; } @@ -232,7 +248,11 @@ static int line_in_init (HWVoiceIn *hw, struct audsettings *as) SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); struct audsettings settings; +#if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 + settings.freq = spice_server_get_best_record_rate(NULL); +#else settings.freq = SPICE_INTERFACE_RECORD_FREQ; +#endif settings.nchannels = SPICE_INTERFACE_RECORD_CHAN; settings.fmt = AUD_FMT_S16; settings.endianness = AUDIO_HOST_ENDIANNESS; @@ -243,6 +263,9 @@ static int line_in_init (HWVoiceIn *hw, struct audsettings *as) in->sin.base.sif = &record_sif.base; qemu_spice_add_interface (&in->sin.base); +#if SPICE_INTERFACE_RECORD_MAJOR > 2 || SPICE_INTERFACE_RECORD_MINOR >= 3 + spice_server_set_record_rate(&in->sin, settings.freq); +#endif return 0; } diff --git a/block/qcow2.c b/block/qcow2.c index 2da62b8a90..99a1ad13e6 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1689,26 +1689,6 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options, return ret; } -static int qcow2_make_empty(BlockDriverState *bs) -{ -#if 0 - /* XXX: not correct */ - BDRVQcowState *s = bs->opaque; - uint32_t l1_length = s->l1_size * sizeof(uint64_t); - int ret; - - memset(s->l1_table, 0, l1_length); - if (bdrv_pwrite(bs->file, s->l1_table_offset, s->l1_table, l1_length) < 0) - return -1; - ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length); - if (ret < 0) - return ret; - - l2_cache_reset(bs); -#endif - return 0; -} - static coroutine_fn int qcow2_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors, BdrvRequestFlags flags) { @@ -2252,7 +2232,6 @@ static BlockDriver bdrv_qcow2 = { .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_co_get_block_status = qcow2_co_get_block_status, .bdrv_set_key = qcow2_set_key, - .bdrv_make_empty = qcow2_make_empty, .bdrv_co_readv = qcow2_co_readv, .bdrv_co_writev = qcow2_co_writev, diff --git a/block/qed.c b/block/qed.c index 694e6e2ee0..b9ca7ac0da 100644 --- a/block/qed.c +++ b/block/qed.c @@ -731,11 +731,6 @@ static int64_t coroutine_fn bdrv_qed_co_get_block_status(BlockDriverState *bs, return cb.status; } -static int bdrv_qed_make_empty(BlockDriverState *bs) -{ - return -ENOTSUP; -} - static BDRVQEDState *acb_to_s(QEDAIOCB *acb) { return acb->common.bs->opaque; @@ -1617,7 +1612,6 @@ static BlockDriver bdrv_qed = { .bdrv_create = bdrv_qed_create, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_co_get_block_status = bdrv_qed_co_get_block_status, - .bdrv_make_empty = bdrv_qed_make_empty, .bdrv_aio_readv = bdrv_qed_aio_readv, .bdrv_aio_writev = bdrv_qed_aio_writev, .bdrv_co_write_zeroes = bdrv_qed_co_write_zeroes, diff --git a/block/vhdx-log.c b/block/vhdx-log.c index 8c9ae0d8e7..02755b8ded 100644 --- a/block/vhdx-log.c +++ b/block/vhdx-log.c @@ -965,8 +965,8 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s, cpu_to_le32s((uint32_t *)(buffer + 4)); /* now write to the log */ - vhdx_log_write_sectors(bs, &s->log, §ors_written, buffer, - desc_sectors + sectors); + ret = vhdx_log_write_sectors(bs, &s->log, §ors_written, buffer, + desc_sectors + sectors); if (ret < 0) { goto exit; } diff --git a/block/vhdx.c b/block/vhdx.c index 9ee0a612ff..55689cf641 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -374,7 +374,7 @@ static int vhdx_update_header(BlockDriverState *bs, BDRVVHDXState *s, inactive_header->log_guid = *log_guid; } - vhdx_write_header(bs->file, inactive_header, header_offset, true); + ret = vhdx_write_header(bs->file, inactive_header, header_offset, true); if (ret < 0) { goto exit; } @@ -1810,13 +1810,13 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options, creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL, &creator_items, NULL); signature = cpu_to_le64(VHDX_FILE_SIGNATURE); - bdrv_pwrite(bs, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature)); + ret = bdrv_pwrite(bs, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature)); if (ret < 0) { goto delete_and_exit; } if (creator) { - bdrv_pwrite(bs, VHDX_FILE_ID_OFFSET + sizeof(signature), creator, - creator_items * sizeof(gunichar2)); + ret = bdrv_pwrite(bs, VHDX_FILE_ID_OFFSET + sizeof(signature), + creator, creator_items * sizeof(gunichar2)); if (ret < 0) { goto delete_and_exit; } diff --git a/block/vmdk.c b/block/vmdk.c index 99ca60fdb9..e809e2ef46 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1942,6 +1942,53 @@ static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent) return info; } +static int vmdk_check(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) +{ + BDRVVmdkState *s = bs->opaque; + VmdkExtent *extent = NULL; + int64_t sector_num = 0; + int64_t total_sectors = bdrv_getlength(bs) / BDRV_SECTOR_SIZE; + int ret; + uint64_t cluster_offset; + + if (fix) { + return -ENOTSUP; + } + + for (;;) { + if (sector_num >= total_sectors) { + return 0; + } + extent = find_extent(s, sector_num, extent); + if (!extent) { + fprintf(stderr, + "ERROR: could not find extent for sector %" PRId64 "\n", + sector_num); + break; + } + ret = get_cluster_offset(bs, extent, NULL, + sector_num << BDRV_SECTOR_BITS, + 0, &cluster_offset); + if (ret == VMDK_ERROR) { + fprintf(stderr, + "ERROR: could not get cluster_offset for sector %" + PRId64 "\n", sector_num); + break; + } + if (ret == VMDK_OK && cluster_offset >= bdrv_getlength(extent->file)) { + fprintf(stderr, + "ERROR: cluster offset for sector %" + PRId64 " points after EOF\n", sector_num); + break; + } + sector_num += extent->cluster_sectors; + } + + result->corruptions++; + return 0; +} + static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs) { int i; @@ -2015,6 +2062,7 @@ static BlockDriver bdrv_vmdk = { .instance_size = sizeof(BDRVVmdkState), .bdrv_probe = vmdk_probe, .bdrv_open = vmdk_open, + .bdrv_check = vmdk_check, .bdrv_reopen_prepare = vmdk_reopen_prepare, .bdrv_read = vmdk_co_read, .bdrv_write = vmdk_co_write, diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 02b7016a04..25ec549e71 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -1448,7 +1448,7 @@ static const VMStateDescription vmstate_pxa2xx_i2c = { VMSTATE_UINT8(ibmr, PXA2xxI2CState), VMSTATE_UINT8(data, PXA2xxI2CState), VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState, - vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *), + vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState), VMSTATE_END_OF_LIST() } }; diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 456d437ac3..2237edb4eb 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -145,7 +145,7 @@ static void do_get_id_cmd(VirtIOBlockDataPlane *s, { char id[VIRTIO_BLK_ID_BYTES]; - /* Serial number not NUL-terminated when shorter than buffer */ + /* Serial number not NUL-terminated when longer than buffer */ strncpy(id, s->blk->serial ? s->blk->serial : "", sizeof(id)); iov_from_buf(iov, iov_cnt, 0, id, sizeof(id)); complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK); diff --git a/hw/display/qxl.c b/hw/display/qxl.c index e4f172e3fb..334c2719f8 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -19,6 +19,7 @@ */ #include <zlib.h> +#include <stdint.h> #include "qemu-common.h" #include "qemu/timer.h" @@ -1126,6 +1127,7 @@ static void qxl_reset_state(PCIQXLDevice *d) d->num_free_res = 0; d->last_release = NULL; memset(&d->ssd.dirty, 0, sizeof(d->ssd.dirty)); + qxl_update_irq(d); } static void qxl_soft_reset(PCIQXLDevice *d) @@ -1360,14 +1362,16 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm, { QXLDevSurfaceCreate surface; QXLSurfaceCreate *sc = &qxl->guest_primary.surface; - int size; - int requested_height = le32_to_cpu(sc->height); + uint32_t requested_height = le32_to_cpu(sc->height); int requested_stride = le32_to_cpu(sc->stride); - size = abs(requested_stride) * requested_height; - if (size > qxl->vgamem_size) { - qxl_set_guest_bug(qxl, "%s: requested primary larger then framebuffer" - " size", __func__); + if (requested_stride == INT32_MIN || + abs(requested_stride) * (uint64_t)requested_height + > qxl->vgamem_size) { + qxl_set_guest_bug(qxl, "%s: requested primary larger than framebuffer" + " stride %d x height %" PRIu32 " > %" PRIu32, + __func__, requested_stride, requested_height, + qxl->vgamem_size); return; } diff --git a/hw/i386/bios-linker-loader.c b/hw/i386/bios-linker-loader.c index fd23611008..aa56184e9a 100644 --- a/hw/i386/bios-linker-loader.c +++ b/hw/i386/bios-linker-loader.c @@ -18,11 +18,10 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu-common.h" #include "bios-linker-loader.h" #include "hw/nvram/fw_cfg.h" -#include <string.h> -#include <assert.h> #include "qemu/bswap.h" #define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 239aada193..9160ee7769 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -27,8 +27,6 @@ #include "qemu/log.h" #include "exec/address-spaces.h" -//#define DEBUG_MMIO -//#define DEBUG_UNASSIGNED #define DEBUG_UIC diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 77e1218447..1ba6c3ab70 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -3,6 +3,7 @@ obj-y += s390-virtio-hcall.o obj-y += sclp.o obj-y += event-facility.o obj-y += sclpquiesce.o +obj-y += sclpcpu.o obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 25951a020a..a73c0b924a 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -32,6 +32,8 @@ struct SCLPEventFacility { unsigned int receive_mask; }; +SCLPEvent cpu_hotplug; + /* return true if any child has event pending set */ static bool event_pending(SCLPEventFacility *ef) { @@ -335,6 +337,10 @@ static int init_event_facility(S390SCLPDevice *sdev) } qdev_init_nofail(quiesce); + object_initialize(&cpu_hotplug, sizeof(cpu_hotplug), TYPE_SCLP_CPU_HOTPLUG); + qdev_set_parent_bus(DEVICE(&cpu_hotplug), BUS(&event_facility->sbus)); + object_property_set_bool(OBJECT(&cpu_hotplug), true, "realized", NULL); + return 0; } diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 86d6ae0023..4e0c564c5c 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -15,6 +15,7 @@ #include "cpu.h" #include "sysemu/kvm.h" #include "exec/memory.h" +#include "sysemu/sysemu.h" #include "hw/s390x/sclp.h" @@ -31,7 +32,26 @@ static inline S390SCLPDevice *get_event_facility(void) static void read_SCP_info(SCCB *sccb) { ReadInfo *read_info = (ReadInfo *) sccb; + CPUState *cpu; int shift = 0; + int cpu_count = 0; + int i = 0; + + CPU_FOREACH(cpu) { + cpu_count++; + } + + /* CPU information */ + read_info->entries_cpu = cpu_to_be16(cpu_count); + read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries)); + read_info->highest_cpu = cpu_to_be16(max_cpus); + + for (i = 0; i < cpu_count; i++) { + read_info->entries[i].address = i; + read_info->entries[i].type = 0; + } + + read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO); while ((ram_size >> (20 + shift)) > 65535) { shift++; @@ -41,15 +61,46 @@ static void read_SCP_info(SCCB *sccb) sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); } +/* Provide information about the CPU */ +static void sclp_read_cpu_info(SCCB *sccb) +{ + ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb; + CPUState *cpu; + int cpu_count = 0; + int i = 0; + + CPU_FOREACH(cpu) { + cpu_count++; + } + + cpu_info->nr_configured = cpu_to_be16(cpu_count); + cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries)); + cpu_info->nr_standby = cpu_to_be16(0); + + /* The standby offset is 16-byte for each CPU */ + cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured + + cpu_info->nr_configured*sizeof(CPUEntry)); + + for (i = 0; i < cpu_count; i++) { + cpu_info->entries[i].address = i; + cpu_info->entries[i].type = 0; + } + + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); +} + static void sclp_execute(SCCB *sccb, uint64_t code) { S390SCLPDevice *sdev = get_event_facility(); - switch (code) { + switch (code & SCLP_CMD_CODE_MASK) { case SCLP_CMDW_READ_SCP_INFO: case SCLP_CMDW_READ_SCP_INFO_FORCED: read_SCP_info(sccb); break; + case SCLP_CMDW_READ_CPU_INFO: + sclp_read_cpu_info(sccb); + break; default: sdev->sclp_command_handler(sdev->ef, sccb, code); break; diff --git a/hw/s390x/sclpcpu.c b/hw/s390x/sclpcpu.c new file mode 100644 index 0000000000..b9c238a0da --- /dev/null +++ b/hw/s390x/sclpcpu.c @@ -0,0 +1,112 @@ +/* + * SCLP event type + * Signal CPU - Trigger SCLP interrupt for system CPU configure or + * de-configure + * + * Copyright IBM, Corp. 2013 + * + * Authors: + * Thang Pham <thang.pham@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at your + * option) any later version. See the COPYING file in the top-level directory. + * + */ +#include "sysemu/sysemu.h" +#include "hw/s390x/sclp.h" +#include "hw/s390x/event-facility.h" +#include "cpu.h" +#include "sysemu/cpus.h" +#include "sysemu/kvm.h" + +typedef struct ConfigMgtData { + EventBufferHeader ebh; + uint8_t reserved; + uint8_t event_qualifier; +} QEMU_PACKED ConfigMgtData; + +static qemu_irq irq_cpu_hotplug; /* Only used in this file */ + +#define EVENT_QUAL_CPU_CHANGE 1 + +void raise_irq_cpu_hotplug(void) +{ + qemu_irq_raise(irq_cpu_hotplug); +} + +static unsigned int send_mask(void) +{ + return SCLP_EVENT_MASK_CONFIG_MGT_DATA; +} + +static unsigned int receive_mask(void) +{ + return 0; +} + +static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, + int *slen) +{ + ConfigMgtData *cdata = (ConfigMgtData *) evt_buf_hdr; + if (*slen < sizeof(ConfigMgtData)) { + return 0; + } + + /* Event is no longer pending */ + if (!event->event_pending) { + return 0; + } + event->event_pending = false; + + /* Event header data */ + cdata->ebh.length = cpu_to_be16(sizeof(ConfigMgtData)); + cdata->ebh.type = SCLP_EVENT_CONFIG_MGT_DATA; + cdata->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED; + + /* Trigger a rescan of CPUs by setting event qualifier */ + cdata->event_qualifier = EVENT_QUAL_CPU_CHANGE; + *slen -= sizeof(ConfigMgtData); + + return 1; +} + +static void trigger_signal(void *opaque, int n, int level) +{ + SCLPEvent *event = opaque; + event->event_pending = true; + + /* Trigger SCLP read operation */ + sclp_service_interrupt(0); +} + +static int irq_cpu_hotplug_init(SCLPEvent *event) +{ + irq_cpu_hotplug = *qemu_allocate_irqs(trigger_signal, event, 1); + return 0; +} + +static void cpu_class_init(ObjectClass *oc, void *data) +{ + SCLPEventClass *k = SCLP_EVENT_CLASS(oc); + + k->init = irq_cpu_hotplug_init; + k->get_send_mask = send_mask; + k->get_receive_mask = receive_mask; + k->read_event_data = read_event_data; + k->write_event_data = NULL; +} + +static const TypeInfo sclp_cpu_info = { + .name = "sclp-cpu-hotplug", + .parent = TYPE_SCLP_EVENT, + .instance_size = sizeof(SCLPEvent), + .class_init = cpu_class_init, + .class_size = sizeof(SCLPEventClass), +}; + +static void sclp_cpu_register_types(void) +{ + type_register_static(&sclp_cpu_info); +} + +type_init(sclp_cpu_register_types) diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 481a447417..2edfa96c6d 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -93,7 +93,8 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap, unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); /* start address is aligned at the start of a word? */ - if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) { + if ((((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) && + (hpratio == 1)) { long k; long nr = BITS_TO_LONGS(pages); diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h index c6a544069c..8712dcd091 100644 --- a/include/exec/softmmu_template.h +++ b/include/exec/softmmu_template.h @@ -30,23 +30,26 @@ #define SUFFIX q #define LSUFFIX q #define SDATA_TYPE int64_t +#define DATA_TYPE uint64_t #elif DATA_SIZE == 4 #define SUFFIX l #define LSUFFIX l #define SDATA_TYPE int32_t +#define DATA_TYPE uint32_t #elif DATA_SIZE == 2 #define SUFFIX w #define LSUFFIX uw #define SDATA_TYPE int16_t +#define DATA_TYPE uint16_t #elif DATA_SIZE == 1 #define SUFFIX b #define LSUFFIX ub #define SDATA_TYPE int8_t +#define DATA_TYPE uint8_t #else #error unsupported data size #endif -#define DATA_TYPE glue(u, SDATA_TYPE) /* For the benefit of TCG generated code, we want to avoid the complication of ABI-specific return type promotion and always return a value extended diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h index a33edf4b0c..8ebacbbda0 100644 --- a/include/hw/ptimer.h +++ b/include/hw/ptimer.h @@ -27,14 +27,8 @@ void ptimer_stop(ptimer_state *s); extern const VMStateDescription vmstate_ptimer; -#define VMSTATE_PTIMER(_field, _state) { \ - .name = (stringify(_field)), \ - .version_id = (1), \ - .vmsd = &vmstate_ptimer, \ - .size = sizeof(ptimer_state *), \ - .flags = VMS_STRUCT|VMS_POINTER, \ - .offset = vmstate_offset_pointer(_state, _field, ptimer_state), \ -} +#define VMSTATE_PTIMER(_field, _state) \ + VMSTATE_STRUCT_POINTER_V(_field, _state, 1, vmstate_ptimer, ptimer_state) #define VMSTATE_PTIMER_ARRAY(_f, _s, _n) \ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, 0, \ diff --git a/include/hw/s390x/event-facility.h b/include/hw/s390x/event-facility.h index 7ce7079f9f..870edd46f6 100644 --- a/include/hw/s390x/event-facility.h +++ b/include/hw/s390x/event-facility.h @@ -17,10 +17,12 @@ #include <hw/qdev.h> #include "qemu/thread.h" +#include "hw/s390x/sclp.h" /* SCLP event types */ #define SCLP_EVENT_OPRTNS_COMMAND 0x01 #define SCLP_EVENT_MESSAGE 0x02 +#define SCLP_EVENT_CONFIG_MGT_DATA 0x04 #define SCLP_EVENT_PMSGCMD 0x09 #define SCLP_EVENT_ASCII_CONSOLE_DATA 0x1a #define SCLP_EVENT_SIGNAL_QUIESCE 0x1d @@ -28,6 +30,7 @@ /* SCLP event masks */ #define SCLP_EVENT_MASK_SIGNAL_QUIESCE 0x00000008 #define SCLP_EVENT_MASK_MSG_ASCII 0x00000040 +#define SCLP_EVENT_MASK_CONFIG_MGT_DATA 0x10000000 #define SCLP_EVENT_MASK_OP_CMD 0x80000000 #define SCLP_EVENT_MASK_MSG 0x40000000 #define SCLP_EVENT_MASK_PMSGCMD 0x00800000 @@ -43,6 +46,8 @@ #define SCLP_EVENT_GET_CLASS(obj) \ OBJECT_GET_CLASS(SCLPEventClass, (obj), TYPE_SCLP_EVENT) +#define TYPE_SCLP_CPU_HOTPLUG "sclp-cpu-hotplug" + typedef struct WriteEventMask { SCCBHeader h; uint16_t _reserved; diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index 231a38aa09..35112d92b1 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -17,21 +17,41 @@ #include <hw/sysbus.h> #include <hw/qdev.h> +#define SCLP_CMD_CODE_MASK 0xffff00ff + /* SCLP command codes */ #define SCLP_CMDW_READ_SCP_INFO 0x00020001 #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 +#define SCLP_READ_STORAGE_ELEMENT_INFO 0x00040001 +#define SCLP_ATTACH_STORAGE_ELEMENT 0x00080001 +#define SCLP_ASSIGN_STORAGE 0x000D0001 +#define SCLP_UNASSIGN_STORAGE 0x000C0001 #define SCLP_CMD_READ_EVENT_DATA 0x00770005 #define SCLP_CMD_WRITE_EVENT_DATA 0x00760005 #define SCLP_CMD_READ_EVENT_DATA 0x00770005 #define SCLP_CMD_WRITE_EVENT_DATA 0x00760005 #define SCLP_CMD_WRITE_EVENT_MASK 0x00780005 +/* SCLP Memory hotplug codes */ +#define SCLP_FC_ASSIGN_ATTACH_READ_STOR 0xE00000000000ULL +#define SCLP_STARTING_SUBINCREMENT_ID 0x10001 +#define SCLP_INCREMENT_UNIT 0x10000 +#define MAX_AVAIL_SLOTS 32 + +/* CPU hotplug SCLP codes */ +#define SCLP_HAS_CPU_INFO 0x0C00000000000000ULL +#define SCLP_CMDW_READ_CPU_INFO 0x00010001 +#define SCLP_CMDW_CONFIGURE_CPU 0x00110001 +#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001 + /* SCLP response codes */ #define SCLP_RC_NORMAL_READ_COMPLETION 0x0010 #define SCLP_RC_NORMAL_COMPLETION 0x0020 +#define SCLP_RC_SCCB_BOUNDARY_VIOLATION 0x0100 #define SCLP_RC_INVALID_SCLP_COMMAND 0x01f0 #define SCLP_RC_CONTAINED_EQUIPMENT_CHECK 0x0340 #define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300 +#define SCLP_RC_STANDBY_READ_COMPLETION 0x0410 #define SCLP_RC_INVALID_FUNCTION 0x40f0 #define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0 #define SCLP_RC_INVALID_SELECTION_MASK 0x70f0 @@ -71,12 +91,66 @@ typedef struct SCCBHeader { #define SCCB_DATA_LEN (SCCB_SIZE - sizeof(SCCBHeader)) +/* CPU information */ +typedef struct CPUEntry { + uint8_t address; + uint8_t reserved0[13]; + uint8_t type; + uint8_t reserved1; +} QEMU_PACKED CPUEntry; + typedef struct ReadInfo { SCCBHeader h; uint16_t rnmax; uint8_t rnsize; + uint8_t _reserved1[16 - 11]; /* 11-15 */ + uint16_t entries_cpu; /* 16-17 */ + uint16_t offset_cpu; /* 18-19 */ + uint8_t _reserved2[24 - 20]; /* 20-23 */ + uint8_t loadparm[8]; /* 24-31 */ + uint8_t _reserved3[48 - 32]; /* 32-47 */ + uint64_t facilities; /* 48-55 */ + uint8_t _reserved0[100 - 56]; + uint32_t rnsize2; + uint64_t rnmax2; + uint8_t _reserved4[120-112]; /* 112-119 */ + uint16_t highest_cpu; + uint8_t _reserved5[128 - 122]; /* 122-127 */ + struct CPUEntry entries[0]; } QEMU_PACKED ReadInfo; +typedef struct ReadCpuInfo { + SCCBHeader h; + uint16_t nr_configured; /* 8-9 */ + uint16_t offset_configured; /* 10-11 */ + uint16_t nr_standby; /* 12-13 */ + uint16_t offset_standby; /* 14-15 */ + uint8_t reserved0[24-16]; /* 16-23 */ + struct CPUEntry entries[0]; +} QEMU_PACKED ReadCpuInfo; + +typedef struct ReadStorageElementInfo { + SCCBHeader h; + uint16_t max_id; + uint16_t assigned; + uint16_t standby; + uint8_t _reserved0[16 - 14]; /* 14-15 */ + uint32_t entries[0]; +} QEMU_PACKED ReadStorageElementInfo; + +typedef struct AttachStorageElement { + SCCBHeader h; + uint8_t _reserved0[10 - 8]; /* 8-9 */ + uint16_t assigned; + uint8_t _reserved1[16 - 12]; /* 12-15 */ + uint32_t entries[0]; +} QEMU_PACKED AttachStorageElement; + +typedef struct AssignStorage { + SCCBHeader h; + uint16_t rn; +} QEMU_PACKED AssignStorage; + typedef struct SCCB { SCCBHeader h; char data[SCCB_DATA_LEN]; @@ -114,5 +188,6 @@ typedef struct S390SCLPDeviceClass { void s390_sclp_init(void); void sclp_service_interrupt(uint32_t sccb); +void raise_irq_cpu_hotplug(void); #endif diff --git a/include/migration/migration.h b/include/migration/migration.h index bfa3951a61..3e1e6c72bf 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -109,6 +109,7 @@ MigrationState *migrate_get_current(void); uint64_t ram_bytes_remaining(void); uint64_t ram_bytes_transferred(void); uint64_t ram_bytes_total(void); +void free_xbzrle_decoded_buf(void); void acct_update_position(QEMUFile *f, size_t size, bool zero); diff --git a/include/migration/page_cache.h b/include/migration/page_cache.h index 87894fea9f..d156f0d398 100644 --- a/include/migration/page_cache.h +++ b/include/migration/page_cache.h @@ -60,11 +60,13 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr); * cache_insert: insert the page into the cache. the page cache * will dup the data on insert. the previous value will be overwritten * + * Returns -1 on error + * * @cache pointer to the PageCache struct * @addr: page address * @pdata: pointer to the page */ -void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata); +int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata); /** * cache_resize: resize the page cache. In case of size reduction the extra diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index be193baba1..fbd16a03e6 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -314,9 +314,9 @@ extern const VMStateInfo vmstate_info_bitmap; .name = (stringify(_field)), \ .version_id = (_version), \ .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ + .size = sizeof(_type *), \ .flags = VMS_STRUCT|VMS_POINTER, \ - .offset = vmstate_offset_value(_state, _field, _type), \ + .offset = vmstate_offset_pointer(_state, _field, _type), \ } #define VMSTATE_STRUCT_POINTER_TEST_V(_field, _state, _test, _version, _vmsd, _type) { \ @@ -324,9 +324,9 @@ extern const VMStateInfo vmstate_info_bitmap; .version_id = (_version), \ .field_exists = (_test), \ .vmsd = &(_vmsd), \ - .size = sizeof(_type), \ + .size = sizeof(_type *), \ .flags = VMS_STRUCT|VMS_POINTER, \ - .offset = vmstate_offset_value(_state, _field, _type), \ + .offset = vmstate_offset_pointer(_state, _field, _type), \ } #define VMSTATE_ARRAY_OF_POINTER(_field, _state, _num, _version, _info, _type) {\ diff --git a/include/qemu/readline.h b/include/qemu/readline.h index a89fe4a9a9..49efe4e39b 100644 --- a/include/qemu/readline.h +++ b/include/qemu/readline.h @@ -5,7 +5,8 @@ #define READLINE_MAX_CMDS 64 #define READLINE_MAX_COMPLETIONS 256 -typedef void ReadLinePrintfFunc(void *opaque, const char *fmt, ...); +typedef void GCC_FMT_ATTR(2, 3) ReadLinePrintfFunc(void *opaque, + const char *fmt, ...); typedef void ReadLineFlushFunc(void *opaque); typedef void ReadLineFunc(void *opaque, const char *str, void *readline_opaque); @@ -1546,17 +1546,16 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size, static int kvm_handle_internal_error(CPUState *cpu, struct kvm_run *run) { - fprintf(stderr, "KVM internal error."); + fprintf(stderr, "KVM internal error. Suberror: %d\n", + run->internal.suberror); + if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) { int i; - fprintf(stderr, " Suberror: %d\n", run->internal.suberror); for (i = 0; i < run->internal.ndata; ++i) { fprintf(stderr, "extra data[%d]: %"PRIx64"\n", i, (uint64_t)run->internal.data[i]); } - } else { - fprintf(stderr, "\n"); } if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) { fprintf(stderr, "emulation failure\n"); diff --git a/linux-headers/asm-x86/hyperv.h b/linux-headers/asm-x86/hyperv.h index b8f1c0176c..3b400ee9f7 100644 --- a/linux-headers/asm-x86/hyperv.h +++ b/linux-headers/asm-x86/hyperv.h @@ -149,6 +149,9 @@ /* MSR used to read the per-partition time reference counter */ #define HV_X64_MSR_TIME_REF_COUNT 0x40000020 +/* A partition's reference time stamp counter (TSC) page */ +#define HV_X64_MSR_REFERENCE_TSC 0x40000021 + /* MSR used to retrieve the TSC frequency */ #define HV_X64_MSR_TSC_FREQUENCY 0x40000022 diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 5a49671845..999fb135e1 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -674,6 +674,7 @@ struct kvm_ppc_smmu_info { #define KVM_CAP_ARM_EL1_32BIT 93 #define KVM_CAP_SPAPR_MULTITCE 94 #define KVM_CAP_EXT_EMUL_CPUID 95 +#define KVM_CAP_HYPERV_TIME 96 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/migration.c b/migration.c index 7235c23ffe..25add6f9e2 100644 --- a/migration.c +++ b/migration.c @@ -105,6 +105,7 @@ static void process_incoming_migration_co(void *opaque) ret = qemu_loadvm_state(f); qemu_fclose(f); + free_xbzrle_decoded_buf(); if (ret < 0) { fprintf(stderr, "load of migration failed\n"); exit(EXIT_FAILURE); @@ -469,6 +470,7 @@ void qmp_migrate_cancel(Error **errp) void qmp_migrate_set_cache_size(int64_t value, Error **errp) { MigrationState *s = migrate_get_current(); + int64_t new_size; /* Check for truncation */ if (value != (size_t)value) { @@ -477,7 +479,21 @@ void qmp_migrate_set_cache_size(int64_t value, Error **errp) return; } - s->xbzrle_cache_size = xbzrle_cache_resize(value); + /* Cache should not be larger than guest ram size */ + if (value > ram_bytes_total()) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cache size", + "exceeds guest ram size "); + return; + } + + new_size = xbzrle_cache_resize(value); + if (new_size < 0) { + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cache size", + "is smaller than page size"); + return; + } + + s->xbzrle_cache_size = new_size; } int64_t qmp_query_migrate_cache_size(Error **errp) @@ -4888,7 +4888,8 @@ static void sortcmdlist(void) /* These functions just adapt the readline interface in a typesafe way. We * could cast function pointers but that discards compiler checks. */ -static void monitor_readline_printf(void *opaque, const char *fmt, ...) +static void GCC_FMT_ATTR(2, 3) monitor_readline_printf(void *opaque, + const char *fmt, ...) { va_list ap; va_start(ap, fmt); diff --git a/page_cache.c b/page_cache.c index a05db643cc..3ef6ee7ad2 100644 --- a/page_cache.c +++ b/page_cache.c @@ -60,8 +60,12 @@ PageCache *cache_init(int64_t num_pages, unsigned int page_size) return NULL; } - cache = g_malloc(sizeof(*cache)); - + /* We prefer not to abort if there is no memory */ + cache = g_try_malloc(sizeof(*cache)); + if (!cache) { + DPRINTF("Failed to allocate cache\n"); + return NULL; + } /* round down to the nearest power of 2 */ if (!is_power_of_2(num_pages)) { num_pages = pow2floor(num_pages); @@ -74,8 +78,14 @@ PageCache *cache_init(int64_t num_pages, unsigned int page_size) DPRINTF("Setting cache buckets to %" PRId64 "\n", cache->max_num_items); - cache->page_cache = g_malloc((cache->max_num_items) * - sizeof(*cache->page_cache)); + /* We prefer not to abort if there is no memory */ + cache->page_cache = g_try_malloc((cache->max_num_items) * + sizeof(*cache->page_cache)); + if (!cache->page_cache) { + DPRINTF("Failed to allocate cache->page_cache\n"); + g_free(cache); + return NULL; + } for (i = 0; i < cache->max_num_items; i++) { cache->page_cache[i].it_data = NULL; @@ -140,7 +150,7 @@ uint8_t *get_cached_data(const PageCache *cache, uint64_t addr) return cache_get_by_addr(cache, addr)->it_data; } -void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata) +int cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata) { CacheItem *it = NULL; @@ -151,16 +161,22 @@ void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata) /* actual update of entry */ it = cache_get_by_addr(cache, addr); - /* free old cached data if any */ - g_free(it->it_data); - + /* allocate page */ if (!it->it_data) { + it->it_data = g_try_malloc(cache->page_size); + if (!it->it_data) { + DPRINTF("Error allocating page\n"); + return -1; + } cache->num_items++; } - it->it_data = g_memdup(pdata, cache->page_size); + memcpy(it->it_data, pdata, cache->page_size); + it->it_age = ++cache->max_item_age; it->it_addr = addr; + + return 0; } int64_t cache_resize(PageCache *cache, int64_t new_num_pages) diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin Binary files differindex 68017e59ce..93202c536e 100644 --- a/pc-bios/bios-256k.bin +++ b/pc-bios/bios-256k.bin diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin Binary files differindex 4f4383b06a..d7899bd04c 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin Binary files differindex 36b197d190..d8cb9d2f23 100644 --- a/pc-bios/vgabios-cirrus.bin +++ b/pc-bios/vgabios-cirrus.bin diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin Binary files differindex aaa3b10c7c..fe57401cd9 100644 --- a/pc-bios/vgabios-qxl.bin +++ b/pc-bios/vgabios-qxl.bin diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin Binary files differindex d329e240f9..2aa659c423 100644 --- a/pc-bios/vgabios-stdvga.bin +++ b/pc-bios/vgabios-stdvga.bin diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin Binary files differindex 31d56a94d0..bed7068db0 100644 --- a/pc-bios/vgabios-vmware.bin +++ b/pc-bios/vgabios-vmware.bin diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin Binary files differindex b87f74de7c..928095f41f 100644 --- a/pc-bios/vgabios.bin +++ b/pc-bios/vgabios.bin diff --git a/qemu-doc.texi b/qemu-doc.texi index ce61f30d6e..ad31f2d2d0 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -547,10 +547,27 @@ File name of a base image (see @option{create} subcommand) @item backing_fmt Image format of the base image @item encryption -If this option is set to @code{on}, the image is encrypted. +If this option is set to @code{on}, the image is encrypted with 128-bit AES-CBC. + +The use of encryption in qcow and qcow2 images is considered to be flawed by +modern cryptography standards, suffering from a number of design problems: + +@itemize @minus +@item The AES-CBC cipher is used with predictable initialization vectors based +on the sector number. This makes it vulnerable to chosen plaintext attacks +which can reveal the existence of encrypted data. +@item The user passphrase is directly used as the encryption key. A poorly +chosen or short passphrase will compromise the security of the encryption. +@item In the event of the passphrase being compromised there is no way to +change the passphrase to protect data in any qcow images. The files must +be cloned, using a different encryption passphrase in the new file. The +original file must then be securely erased using a program like shred, +though even this is ineffective with many modern storage technologies. +@end itemize -Encryption uses the AES format which is very secure (128 bit keys). Use -a long password (16 characters) to get maximum protection. +Use of qcow / qcow2 encryption is thus strongly discouraged. Users are +recommended to use an alternative encryption technology such as the +Linux dm-crypt / LUKS system. @item cluster_size Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster diff --git a/qemu-img.texi b/qemu-img.texi index 526d56a458..f84590ebf0 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -409,10 +409,27 @@ File name of a base image (see @option{create} subcommand) @item backing_fmt Image format of the base image @item encryption -If this option is set to @code{on}, the image is encrypted. +If this option is set to @code{on}, the image is encrypted with 128-bit AES-CBC. -Encryption uses the AES format which is very secure (128 bit keys). Use -a long password (16 characters) to get maximum protection. +The use of encryption in qcow and qcow2 images is considered to be flawed by +modern cryptography standards, suffering from a number of design problems: + +@itemize @minus +@item The AES-CBC cipher is used with predictable initialization vectors based +on the sector number. This makes it vulnerable to chosen plaintext attacks +which can reveal the existence of encrypted data. +@item The user passphrase is directly used as the encryption key. A poorly +chosen or short passphrase will compromise the security of the encryption. +@item In the event of the passphrase being compromised there is no way to +change the passphrase to protect data in any qcow images. The files must +be cloned, using a different encryption passphrase in the new file. The +original file must then be securely erased using a program like shred, +though even this is ineffective with many modern storage technologies. +@end itemize + +Use of qcow / qcow2 encryption is thus strongly discouraged. Users are +recommended to use an alternative encryption technology such as the +Linux dm-crypt / LUKS system. @item cluster_size Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster @@ -219,7 +219,8 @@ static char *get_prompt(void) return prompt; } -static void readline_printf_func(void *opaque, const char *fmt, ...) +static void GCC_FMT_ATTR(2, 3) readline_printf_func(void *opaque, + const char *fmt, ...) { va_list ap; va_start(ap, fmt); diff --git a/roms/Makefile b/roms/Makefile index 1e04669af4..2721b02b13 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -72,11 +72,11 @@ seavgabios-%: build-seabios-config-vga-% build-seabios-config-%: config.% mkdir -p seabios/builds/$* cp $< seabios/builds/$*/.config - $(MAKE) $(MAKEFLAGS) -C seabios \ + $(MAKE) -C seabios \ CROSS_COMPILE=$(x86_64_cross_prefix) \ KCONFIG_CONFIG=$(CURDIR)/seabios/builds/$*/.config \ OUT=$(CURDIR)/seabios/builds/$*/ oldnoconfig - $(MAKE) $(MAKEFLAGS) -C seabios \ + $(MAKE) -C seabios \ CROSS_COMPILE=$(x86_64_cross_prefix) \ KCONFIG_CONFIG=$(CURDIR)/seabios/builds/$*/.config \ OUT=$(CURDIR)/seabios/builds/$*/ all @@ -90,12 +90,12 @@ lgplvgabios-%: build-lgplvgabios cp vgabios/VGABIOS-lgpl-latest.$*.bin ../pc-bios/vgabios-$*.bin build-lgplvgabios: - $(MAKE) $(MAKEFLAGS) -C vgabios $(vgabios_targets) + $(MAKE) -C vgabios $(vgabios_targets) .PHONY: sgabios sgabios: - $(MAKE) $(MAKEFLAGS) -C sgabios + $(MAKE) -C sgabios cp sgabios/sgabios.bin ../pc-bios @@ -114,12 +114,12 @@ efi-rom-%: build-pxe-roms build-efi-roms -o ../pc-bios/efi-$*.rom build-pxe-roms: ipxe/src/config/local/general.h - $(MAKE) $(MAKEFLAGS) -C ipxe/src GITVERSION="" \ + $(MAKE) -C ipxe/src GITVERSION="" \ CROSS_COMPILE=$(x86_64_cross_prefix) \ $(patsubst %,bin/%.rom,$(pxerom_targets)) build-efi-roms: build-pxe-roms ipxe/src/config/local/general.h - $(MAKE) $(MAKEFLAGS) -C ipxe/src GITVERSION="" \ + $(MAKE) -C ipxe/src GITVERSION="" \ CROSS_COMPILE=$(x86_64_cross_prefix) \ $(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \ $(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets)) @@ -129,15 +129,15 @@ ipxe/src/config/local/%: config.ipxe.% slof: - $(MAKE) $(MAKEFLAGS) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu + $(MAKE) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu cp SLOF/boot_rom.bin ../pc-bios/slof.bin clean: rm -rf seabios/.config seabios/out seabios/builds - $(MAKE) $(MAKEFLAGS) -C vgabios clean + $(MAKE) -C vgabios clean rm -f vgabios/VGABIOS-lgpl-latest* - $(MAKE) $(MAKEFLAGS) -C sgabios clean + $(MAKE) -C sgabios clean rm -f sgabios/.depend - $(MAKE) $(MAKEFLAGS) -C ipxe/src veryclean - $(MAKE) $(MAKEFLAGS) -C SLOF clean + $(MAKE) -C ipxe/src veryclean + $(MAKE) -C SLOF clean diff --git a/roms/seabios b/roms/seabios -Subproject 31b8b4eea9d9ad58a73b22a6060d3ac1c419c26 +Subproject 96917a8ed761f017fc8c72ba3b9181fbac03ac5 diff --git a/spice-qemu-char.c b/spice-qemu-char.c index 16439c5860..6624559952 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -212,7 +212,7 @@ static void spice_chr_close(struct CharDriverState *chr) g_free(s); } -static void spice_chr_set_fe_open(struct CharDriverState *chr, int fe_open) +static void spice_vmc_set_fe_open(struct CharDriverState *chr, int fe_open) { SpiceCharDriver *s = chr->opaque; if (fe_open) { @@ -222,6 +222,19 @@ static void spice_chr_set_fe_open(struct CharDriverState *chr, int fe_open) } } +static void spice_port_set_fe_open(struct CharDriverState *chr, int fe_open) +{ +#if SPICE_SERVER_VERSION >= 0x000c02 + SpiceCharDriver *s = chr->opaque; + + if (fe_open) { + spice_server_port_event(&s->sin, SPICE_PORT_EVENT_OPENED); + } else { + spice_server_port_event(&s->sin, SPICE_PORT_EVENT_CLOSED); + } +#endif +} + static void spice_chr_fe_event(struct CharDriverState *chr, int event) { #if SPICE_SERVER_VERSION >= 0x000c02 @@ -248,7 +261,9 @@ static void print_allowed_subtypes(void) fprintf(stderr, "\n"); } -static CharDriverState *chr_open(const char *subtype) +static CharDriverState *chr_open(const char *subtype, + void (*set_fe_open)(struct CharDriverState *, int)) + { CharDriverState *chr; SpiceCharDriver *s; @@ -262,7 +277,7 @@ static CharDriverState *chr_open(const char *subtype) chr->chr_write = spice_chr_write; chr->chr_add_watch = spice_chr_add_watch; chr->chr_close = spice_chr_close; - chr->chr_set_fe_open = spice_chr_set_fe_open; + chr->chr_set_fe_open = set_fe_open; chr->explicit_be_open = true; chr->chr_fe_event = spice_chr_fe_event; @@ -291,7 +306,7 @@ CharDriverState *qemu_chr_open_spice_vmc(const char *type) return NULL; } - return chr_open(type); + return chr_open(type, spice_vmc_set_fe_open); } #if SPICE_SERVER_VERSION >= 0x000c02 @@ -305,7 +320,7 @@ CharDriverState *qemu_chr_open_spice_port(const char *name) return NULL; } - chr = chr_open("port"); + chr = chr_open("port", spice_port_set_fe_open); s = chr->opaque; s->sin.portname = g_strdup(name); diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index d1751a40c6..722f11a04f 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -69,6 +69,7 @@ typedef struct X86CPU { bool hyperv_vapic; bool hyperv_relaxed_timing; int hyperv_spinlock_attempts; + bool hyperv_time; bool check_cpuid; bool enforce_cpuid; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e6f7eaf5cd..0e8812a11d 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -374,7 +374,6 @@ void disable_kvm_pv_eoi(void) void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { -#if defined(CONFIG_KVM) uint32_t vec[4]; #ifdef __x86_64__ @@ -382,7 +381,7 @@ void host_cpuid(uint32_t function, uint32_t count, : "=a"(vec[0]), "=b"(vec[1]), "=c"(vec[2]), "=d"(vec[3]) : "0"(function), "c"(count) : "cc"); -#else +#elif defined(__i386__) asm volatile("pusha \n\t" "cpuid \n\t" "mov %%eax, 0(%2) \n\t" @@ -392,6 +391,8 @@ void host_cpuid(uint32_t function, uint32_t count, "popa" : : "a"(function), "c"(count), "S"(vec) : "memory", "cc"); +#else + abort(); #endif if (eax) @@ -402,7 +403,6 @@ void host_cpuid(uint32_t function, uint32_t count, *ecx = vec[2]; if (edx) *edx = vec[3]; -#endif } #define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c))) @@ -1119,7 +1119,6 @@ void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w, } } -#ifdef CONFIG_KVM static int cpu_x86_fill_model_id(char *str) { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -1134,7 +1133,6 @@ static int cpu_x86_fill_model_id(char *str) } return 0; } -#endif /* Fill a x86_def_t struct with information about the host CPU, and * the CPU features supported by the host hardware + host kernel @@ -1143,7 +1141,6 @@ static int cpu_x86_fill_model_id(char *str) */ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) { -#ifdef CONFIG_KVM KVMState *s = kvm_state; uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -1160,46 +1157,19 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->stepping = eax & 0x0F; x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); - x86_cpu_def->features[FEAT_1_EDX] = - kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); - x86_cpu_def->features[FEAT_1_ECX] = - kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX); - - if (x86_cpu_def->level >= 7) { - x86_cpu_def->features[FEAT_7_0_EBX] = - kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX); - } else { - x86_cpu_def->features[FEAT_7_0_EBX] = 0; - } - x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); - x86_cpu_def->features[FEAT_8000_0001_EDX] = - kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); - x86_cpu_def->features[FEAT_8000_0001_ECX] = - kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); + x86_cpu_def->xlevel2 = + kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); cpu_x86_fill_model_id(x86_cpu_def->model_id); - /* Call Centaur's CPUID instruction. */ - if (!strcmp(x86_cpu_def->vendor, CPUID_VENDOR_VIA)) { - host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx); - eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); - if (eax >= 0xC0000001) { - /* Support VIA max extended level */ - x86_cpu_def->xlevel2 = eax; - host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->features[FEAT_C000_0001_EDX] = - kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); - } + FeatureWord w; + for (w = 0; w < FEATURE_WORDS; w++) { + FeatureWordInfo *wi = &feature_word_info[w]; + x86_cpu_def->features[w] = + kvm_arch_get_supported_cpuid(s, wi->cpuid_eax, wi->cpuid_ecx, + wi->cpuid_reg); } - - /* Other KVM-specific feature fields: */ - x86_cpu_def->features[FEAT_SVM] = - kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); - x86_cpu_def->features[FEAT_KVM] = - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); - -#endif /* CONFIG_KVM */ } static int unavailable_host_feature(FeatureWordInfo *f, uint32_t mask) @@ -1226,48 +1196,23 @@ static int unavailable_host_feature(FeatureWordInfo *f, uint32_t mask) * * This function may be called only if KVM is enabled. */ -static int kvm_check_features_against_host(X86CPU *cpu) +static int kvm_check_features_against_host(KVMState *s, X86CPU *cpu) { CPUX86State *env = &cpu->env; - x86_def_t host_def; - uint32_t mask; - int rv, i; - struct model_features_t ft[] = { - {&env->features[FEAT_1_EDX], - &host_def.features[FEAT_1_EDX], - FEAT_1_EDX }, - {&env->features[FEAT_1_ECX], - &host_def.features[FEAT_1_ECX], - FEAT_1_ECX }, - {&env->features[FEAT_8000_0001_EDX], - &host_def.features[FEAT_8000_0001_EDX], - FEAT_8000_0001_EDX }, - {&env->features[FEAT_8000_0001_ECX], - &host_def.features[FEAT_8000_0001_ECX], - FEAT_8000_0001_ECX }, - {&env->features[FEAT_C000_0001_EDX], - &host_def.features[FEAT_C000_0001_EDX], - FEAT_C000_0001_EDX }, - {&env->features[FEAT_7_0_EBX], - &host_def.features[FEAT_7_0_EBX], - FEAT_7_0_EBX }, - {&env->features[FEAT_SVM], - &host_def.features[FEAT_SVM], - FEAT_SVM }, - {&env->features[FEAT_KVM], - &host_def.features[FEAT_KVM], - FEAT_KVM }, - }; + int rv = 0; + FeatureWord w; assert(kvm_enabled()); - kvm_cpu_fill_host(&host_def); - for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i) { - FeatureWord w = ft[i].feat_word; + for (w = 0; w < FEATURE_WORDS; w++) { FeatureWordInfo *wi = &feature_word_info[w]; + uint32_t guest_feat = env->features[w]; + uint32_t host_feat = kvm_arch_get_supported_cpuid(s, wi->cpuid_eax, + wi->cpuid_ecx, + wi->cpuid_reg); + uint32_t mask; for (mask = 1; mask; mask <<= 1) { - if (*ft[i].guest_feat & mask && - !(*ft[i].host_feat & mask)) { + if (guest_feat & mask && !(host_feat & mask)) { unavailable_host_feature(wi, mask); rv = 1; } @@ -1656,18 +1601,6 @@ static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def, def = &builtin_x86_defs[i]; if (strcmp(name, def->name) == 0) { memcpy(x86_cpu_def, def, sizeof(*def)); - /* sysenter isn't supported in compatibility mode on AMD, - * syscall isn't supported in compatibility mode on Intel. - * Normally we advertise the actual CPU vendor, but you can - * override this using the 'vendor' property if you want to use - * KVM's sysenter/syscall emulation in compatibility mode and - * when doing cross vendor migration - */ - if (kvm_enabled()) { - uint32_t ebx = 0, ecx = 0, edx = 0; - host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); - x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx); - } return 0; } } @@ -1867,7 +1800,6 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) return cpu_list; } -#ifdef CONFIG_KVM static void filter_features_for_kvm(X86CPU *cpu) { CPUX86State *env = &cpu->env; @@ -1884,7 +1816,6 @@ static void filter_features_for_kvm(X86CPU *cpu) cpu->filtered_features[w] = requested_features & ~env->features[w]; } } -#endif static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp) { @@ -1898,12 +1829,6 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp) return; } - if (kvm_enabled()) { - def->features[FEAT_KVM] |= kvm_default_features; - } - def->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR; - - object_property_set_str(OBJECT(cpu), def->vendor, "vendor", errp); object_property_set_int(OBJECT(cpu), def->level, "level", errp); object_property_set_int(OBJECT(cpu), def->family, "family", errp); object_property_set_int(OBJECT(cpu), def->model, "model", errp); @@ -1921,6 +1846,31 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp) cpu->cache_info_passthrough = def->cache_info_passthrough; object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp); + + /* Special cases not set in the x86_def_t structs: */ + if (kvm_enabled()) { + env->features[FEAT_KVM] |= kvm_default_features; + } + env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR; + + /* sysenter isn't supported in compatibility mode on AMD, + * syscall isn't supported in compatibility mode on Intel. + * Normally we advertise the actual CPU vendor, but you can + * override this using the 'vendor' property if you want to use + * KVM's sysenter/syscall emulation in compatibility mode and + * when doing cross vendor migration + */ + const char *vendor = def->vendor; + char host_vendor[CPUID_VENDOR_SZ + 1]; + if (kvm_enabled()) { + uint32_t ebx = 0, ecx = 0, edx = 0; + host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); + x86_cpu_vendor_words2str(host_vendor, ebx, edx, ecx); + vendor = host_vendor; + } + + object_property_set_str(OBJECT(cpu), vendor, "vendor", errp); + } X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge, @@ -2588,15 +2538,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES; env->features[FEAT_SVM] &= TCG_SVM_FEATURES; } else { + KVMState *s = kvm_state; if ((cpu->check_cpuid || cpu->enforce_cpuid) - && kvm_check_features_against_host(cpu) && cpu->enforce_cpuid) { + && kvm_check_features_against_host(s, cpu) && cpu->enforce_cpuid) { error_setg(&local_err, "Host's CPU doesn't support requested features"); goto out; } -#ifdef CONFIG_KVM filter_features_for_kvm(cpu); -#endif } #ifndef CONFIG_USER_ONLY @@ -2751,6 +2700,7 @@ static Property x86_cpu_properties[] = { { .name = "hv-spinlocks", .info = &qdev_prop_spinlocks }, DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false), DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false), + DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false), DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, false), DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), DEFINE_PROP_END_OF_LIST() diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 1fcbc82698..1b94f0ffb7 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -862,6 +862,10 @@ typedef struct CPUX86State { uint64_t msr_fixed_counters[MAX_FIXED_COUNTERS]; uint64_t msr_gp_counters[MAX_GP_COUNTERS]; uint64_t msr_gp_evtsel[MAX_GP_COUNTERS]; + uint64_t msr_hv_hypercall; + uint64_t msr_hv_guest_os_id; + uint64_t msr_hv_vapic; + uint64_t msr_hv_tsc; /* exception/interrupt handling */ int error_code; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 0a21c3085d..e555040a97 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -72,6 +72,9 @@ static bool has_msr_misc_enable; static bool has_msr_bndcfgs; static bool has_msr_kvm_steal_time; static int lm_capable_kernel; +static bool has_msr_hv_hypercall; +static bool has_msr_hv_vapic; +static bool has_msr_hv_tsc; static bool has_msr_architectural_pmu; static uint32_t num_architectural_pmu_counters; @@ -437,8 +440,11 @@ static bool hyperv_hypercall_available(X86CPU *cpu) static bool hyperv_enabled(X86CPU *cpu) { - return hyperv_hypercall_available(cpu) || - cpu->hyperv_relaxed_timing; + CPUState *cs = CPU(cpu); + return kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV) > 0 && + (hyperv_hypercall_available(cpu) || + cpu->hyperv_time || + cpu->hyperv_relaxed_timing); } #define KVM_MAX_CPUID_ENTRIES 100 @@ -455,6 +461,7 @@ int kvm_arch_init_vcpu(CPUState *cs) uint32_t unused; struct kvm_cpuid_entry2 *c; uint32_t signature[3]; + int kvm_base = KVM_CPUID_SIGNATURE; int r; memset(&cpuid_data, 0, sizeof(cpuid_data)); @@ -462,26 +469,22 @@ int kvm_arch_init_vcpu(CPUState *cs) cpuid_i = 0; /* Paravirtualization CPUIDs */ - c = &cpuid_data.entries[cpuid_i++]; - c->function = KVM_CPUID_SIGNATURE; - if (!hyperv_enabled(cpu)) { - memcpy(signature, "KVMKVMKVM\0\0\0", 12); - c->eax = 0; - } else { + if (hyperv_enabled(cpu)) { + c = &cpuid_data.entries[cpuid_i++]; + c->function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS; memcpy(signature, "Microsoft Hv", 12); c->eax = HYPERV_CPUID_MIN; - } - c->ebx = signature[0]; - c->ecx = signature[1]; - c->edx = signature[2]; - - c = &cpuid_data.entries[cpuid_i++]; - c->function = KVM_CPUID_FEATURES; - c->eax = env->features[FEAT_KVM]; + c->ebx = signature[0]; + c->ecx = signature[1]; + c->edx = signature[2]; - if (hyperv_enabled(cpu)) { + c = &cpuid_data.entries[cpuid_i++]; + c->function = HYPERV_CPUID_INTERFACE; memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12); c->eax = signature[0]; + c->ebx = 0; + c->ecx = 0; + c->edx = 0; c = &cpuid_data.entries[cpuid_i++]; c->function = HYPERV_CPUID_VERSION; @@ -496,14 +499,21 @@ int kvm_arch_init_vcpu(CPUState *cs) if (cpu->hyperv_vapic) { c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE; + has_msr_hv_vapic = true; + } + if (cpu->hyperv_time && + kvm_check_extension(cs->kvm_state, KVM_CAP_HYPERV_TIME) > 0) { + c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE; + c->eax |= HV_X64_MSR_TIME_REF_COUNT_AVAILABLE; + c->eax |= 0x200; + has_msr_hv_tsc = true; } - c = &cpuid_data.entries[cpuid_i++]; c->function = HYPERV_CPUID_ENLIGHTMENT_INFO; if (cpu->hyperv_relaxed_timing) { c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED; } - if (cpu->hyperv_vapic) { + if (has_msr_hv_vapic) { c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED; } c->ebx = cpu->hyperv_spinlock_attempts; @@ -513,15 +523,22 @@ int kvm_arch_init_vcpu(CPUState *cs) c->eax = 0x40; c->ebx = 0x40; - c = &cpuid_data.entries[cpuid_i++]; - c->function = KVM_CPUID_SIGNATURE_NEXT; - memcpy(signature, "KVMKVMKVM\0\0\0", 12); - c->eax = 0; - c->ebx = signature[0]; - c->ecx = signature[1]; - c->edx = signature[2]; + kvm_base = KVM_CPUID_SIGNATURE_NEXT; + has_msr_hv_hypercall = true; } + memcpy(signature, "KVMKVMKVM\0\0\0", 12); + c = &cpuid_data.entries[cpuid_i++]; + c->function = KVM_CPUID_SIGNATURE | kvm_base; + c->eax = 0; + c->ebx = signature[0]; + c->ecx = signature[1]; + c->edx = signature[2]; + + c = &cpuid_data.entries[cpuid_i++]; + c->function = KVM_CPUID_FEATURES | kvm_base; + c->eax = env->features[FEAT_KVM]; + has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF); has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI); @@ -1220,12 +1237,19 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, env->msr_global_ctrl); } - if (hyperv_hypercall_available(cpu)) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0); - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0); + if (has_msr_hv_hypercall) { + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, + env->msr_hv_guest_os_id); + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, + env->msr_hv_hypercall); } - if (cpu->hyperv_vapic) { - kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0); + if (has_msr_hv_vapic) { + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, + env->msr_hv_vapic); + } + if (has_msr_hv_tsc) { + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_REFERENCE_TSC, + env->msr_hv_tsc); } /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see @@ -1511,6 +1535,17 @@ static int kvm_get_msrs(X86CPU *cpu) } } + if (has_msr_hv_hypercall) { + msrs[n++].index = HV_X64_MSR_HYPERCALL; + msrs[n++].index = HV_X64_MSR_GUEST_OS_ID; + } + if (has_msr_hv_vapic) { + msrs[n++].index = HV_X64_MSR_APIC_ASSIST_PAGE; + } + if (has_msr_hv_tsc) { + msrs[n++].index = HV_X64_MSR_REFERENCE_TSC; + } + msr_data.info.nmsrs = n; ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); if (ret < 0) { @@ -1618,6 +1653,18 @@ static int kvm_get_msrs(X86CPU *cpu) case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL0 + MAX_GP_COUNTERS - 1: env->msr_gp_evtsel[index - MSR_P6_EVNTSEL0] = msrs[i].data; break; + case HV_X64_MSR_HYPERCALL: + env->msr_hv_hypercall = msrs[i].data; + break; + case HV_X64_MSR_GUEST_OS_ID: + env->msr_hv_guest_os_id = msrs[i].data; + break; + case HV_X64_MSR_APIC_ASSIST_PAGE: + env->msr_hv_vapic = msrs[i].data; + break; + case HV_X64_MSR_REFERENCE_TSC: + env->msr_hv_tsc = msrs[i].data; + break; } } diff --git a/target-i386/machine.c b/target-i386/machine.c index 2de196428d..d548c055a9 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -554,6 +554,64 @@ static const VMStateDescription vmstate_mpx = { } }; +static bool hyperv_hypercall_enable_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return env->msr_hv_hypercall != 0 || env->msr_hv_guest_os_id != 0; +} + +static const VMStateDescription vmstate_msr_hypercall_hypercall = { + .name = "cpu/msr_hyperv_hypercall", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(env.msr_hv_hypercall, X86CPU), + VMSTATE_UINT64(env.msr_hv_guest_os_id, X86CPU), + VMSTATE_END_OF_LIST() + } +}; + +static bool hyperv_vapic_enable_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return env->msr_hv_vapic != 0; +} + +static const VMStateDescription vmstate_msr_hyperv_vapic = { + .name = "cpu/msr_hyperv_vapic", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(env.msr_hv_vapic, X86CPU), + VMSTATE_END_OF_LIST() + } +}; + +static bool hyperv_time_enable_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return env->msr_hv_tsc != 0; +} + +static const VMStateDescription vmstate_msr_hyperv_time = { + .name = "cpu/msr_hyperv_time", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(env.msr_hv_tsc, X86CPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_x86_cpu = { .name = "cpu", .version_id = 12, @@ -688,6 +746,15 @@ const VMStateDescription vmstate_x86_cpu = { } , { .vmsd = &vmstate_mpx, .needed = mpx_needed, + }, { + .vmsd = &vmstate_msr_hypercall_hypercall, + .needed = hyperv_hypercall_enable_needed, + }, { + .vmsd = &vmstate_msr_hyperv_vapic, + .needed = hyperv_vapic_enable_needed, + }, { + .vmsd = &vmstate_msr_hyperv_time, + .needed = hyperv_time_enable_needed, } , { /* empty */ } diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 68b5ab7056..96c2b4a7e9 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -78,11 +78,6 @@ typedef struct MchkQueue { uint16_t type; } MchkQueue; -/* Defined values for CPUS390XState.runtime_reg_dirty_mask */ -#define KVM_S390_RUNTIME_DIRTY_NONE 0 -#define KVM_S390_RUNTIME_DIRTY_PARTIAL 1 -#define KVM_S390_RUNTIME_DIRTY_FULL 2 - typedef struct CPUS390XState { uint64_t regs[16]; /* GP registers */ CPU_DoubleU fregs[16]; /* FP registers */ @@ -126,13 +121,6 @@ typedef struct CPUS390XState { uint64_t cputm; uint32_t todpr; - /* on S390 the runtime register set has two dirty states: - * a partial dirty state in which only the registers that - * are needed all the time are fetched. And a fully dirty - * state in which all runtime registers are fetched. - */ - uint32_t runtime_reg_dirty_mask; - CPU_COMMON /* reset does memset(0) up to here */ @@ -1076,7 +1064,6 @@ void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, uint32_t io_int_word); void kvm_s390_crw_mchk(S390CPU *cpu); void kvm_s390_enable_css_support(S390CPU *cpu); -int kvm_s390_get_registers_partial(CPUState *cpu); int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); int kvm_s390_cpu_restart(S390CPU *cpu); @@ -1094,10 +1081,6 @@ static inline void kvm_s390_crw_mchk(S390CPU *cpu) static inline void kvm_s390_enable_css_support(S390CPU *cpu) { } -static inline int kvm_s390_get_registers_partial(CPUState *cpu) -{ - return -ENOSYS; -} static inline int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index f7b772668c..f60ccdc326 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -152,33 +152,30 @@ int kvm_arch_put_registers(CPUState *cs, int level) } } - if (env->runtime_reg_dirty_mask == KVM_S390_RUNTIME_DIRTY_FULL) { - reg.id = KVM_REG_S390_CPU_TIMER; - reg.addr = (__u64)&(env->cputm); - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); - if (ret < 0) { - return ret; - } + /* Do we need to save more than that? */ + if (level == KVM_PUT_RUNTIME_STATE) { + return 0; + } - reg.id = KVM_REG_S390_CLOCK_COMP; - reg.addr = (__u64)&(env->ckc); - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); - if (ret < 0) { - return ret; - } + reg.id = KVM_REG_S390_CPU_TIMER; + reg.addr = (__u64)&(env->cputm); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + return ret; + } - reg.id = KVM_REG_S390_TODPR; - reg.addr = (__u64)&(env->todpr); - ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); - if (ret < 0) { - return ret; - } + reg.id = KVM_REG_S390_CLOCK_COMP; + reg.addr = (__u64)&(env->ckc); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + return ret; } - env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_NONE; - /* Do we need to save more than that? */ - if (level == KVM_PUT_RUNTIME_STATE) { - return 0; + reg.id = KVM_REG_S390_TODPR; + reg.addr = (__u64)&(env->todpr); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret < 0) { + return ret; } if (cap_sync_regs && @@ -216,50 +213,9 @@ int kvm_arch_get_registers(CPUState *cs) S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; struct kvm_one_reg reg; - int r; - - r = kvm_s390_get_registers_partial(cs); - if (r < 0) { - return r; - } - - reg.id = KVM_REG_S390_CPU_TIMER; - reg.addr = (__u64)&(env->cputm); - r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); - if (r < 0) { - return r; - } - - reg.id = KVM_REG_S390_CLOCK_COMP; - reg.addr = (__u64)&(env->ckc); - r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); - if (r < 0) { - return r; - } - - reg.id = KVM_REG_S390_TODPR; - reg.addr = (__u64)&(env->todpr); - r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); - if (r < 0) { - return r; - } - - env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_FULL; - return 0; -} - -int kvm_s390_get_registers_partial(CPUState *cs) -{ - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; struct kvm_sregs sregs; struct kvm_regs regs; - int ret; - int i; - - if (env->runtime_reg_dirty_mask) { - return 0; - } + int i, r; /* get the PSW */ env->psw.addr = cs->kvm_run->psw_addr; @@ -271,9 +227,9 @@ int kvm_s390_get_registers_partial(CPUState *cs) env->regs[i] = cs->kvm_run->s.regs.gprs[i]; } } else { - ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); - if (ret < 0) { - return ret; + r = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); + if (r < 0) { + return r; } for (i = 0; i < 16; i++) { env->regs[i] = regs.gprs[i]; @@ -289,9 +245,9 @@ int kvm_s390_get_registers_partial(CPUState *cs) env->cregs[i] = cs->kvm_run->s.regs.crs[i]; } } else { - ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); - if (ret < 0) { - return ret; + r = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs); + if (r < 0) { + return r; } for (i = 0; i < 16; i++) { env->aregs[i] = sregs.acrs[i]; @@ -299,14 +255,33 @@ int kvm_s390_get_registers_partial(CPUState *cs) } } - /* Finally the prefix */ + /* The prefix */ if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { env->psa = cs->kvm_run->s.regs.prefix; - } else { - /* no prefix without sync regs */ } - env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_PARTIAL; + /* One Regs */ + reg.id = KVM_REG_S390_CPU_TIMER; + reg.addr = (__u64)&(env->cputm); + r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (r < 0) { + return r; + } + + reg.id = KVM_REG_S390_CLOCK_COMP; + reg.addr = (__u64)&(env->ckc); + r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (r < 0) { + return r; + } + + reg.id = KVM_REG_S390_TODPR; + reg.addr = (__u64)&(env->todpr); + r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (r < 0) { + return r; + } + return 0; } @@ -442,15 +417,13 @@ static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run, uint8_t ipa0, uint8_t ipa1, uint8_t ipb) { CPUS390XState *env = &cpu->env; - CPUState *cs = CPU(cpu); if (ipa0 != 0xb2) { /* Not handled for now. */ return -1; } - kvm_s390_get_registers_partial(cs); - cs->kvm_vcpu_dirty = true; + cpu_synchronize_state(CPU(cpu)); switch (ipa1) { case PRIV_XSCH: @@ -537,11 +510,9 @@ static int handle_priv(S390CPU *cpu, struct kvm_run *run, static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) { - CPUState *cs = CPU(cpu); CPUS390XState *env = &cpu->env; - kvm_s390_get_registers_partial(cs); - cs->kvm_vcpu_dirty = true; + cpu_synchronize_state(CPU(cpu)); env->regs[2] = s390_virtio_hypercall(env); return 0; @@ -767,8 +738,7 @@ static int handle_tsch(S390CPU *cpu) struct kvm_run *run = cs->kvm_run; int ret; - kvm_s390_get_registers_partial(cs); - cs->kvm_vcpu_dirty = true; + cpu_synchronize_state(cs); ret = ioinst_handle_tsch(env, env->regs[1], run->s390_tsch.ipb); if (ret >= 0) { diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index 248726e82f..907d9d1744 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -2214,25 +2214,6 @@ static const TCGTargetOpDef s390_op_defs[] = { { -1 }, }; -/* ??? Linux kernels provide an AUXV entry AT_HWCAP that provides most of - this information. However, getting at that entry is not easy this far - away from main. Our options are: start searching from environ, but - that fails as soon as someone does a setenv in between. Read the data - from /proc/self/auxv. Or do the probing ourselves. The only thing - extra that AT_HWCAP gives us is HWCAP_S390_HIGH_GPRS, which indicates - that the kernel saves all 64-bits of the registers around traps while - in 31-bit mode. But this is true of all "recent" kernels (ought to dig - back and see from when this might not be true). */ - -#include <signal.h> - -static volatile sig_atomic_t got_sigill; - -static void sigill_handler(int sig) -{ - got_sigill = 1; -} - static void query_facilities(void) { unsigned long hwcap = qemu_getauxval(AT_HWCAP); diff --git a/tests/.gitignore b/tests/.gitignore index 1aed2249ff..9ba9d96b6b 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -4,6 +4,7 @@ check-qint check-qjson check-qlist check-qstring +check-qom-interface test-aio test-bitops test-throttle diff --git a/tests/libqtest.c b/tests/libqtest.c index 359d571a06..c9a4f89451 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -43,9 +43,8 @@ struct QTestState int qmp_fd; bool irq_level[MAX_IRQ]; GString *rx; - gchar *pid_file; /* QEMU PID file */ int child_pid; /* Child process created to execute QEMU */ - char *socket_path, *qmp_socket_path; + pid_t qemu_pid; /* QEMU process spawned by our child */ }; #define g_assert_no_errno(ret) do { \ @@ -90,13 +89,13 @@ static int socket_accept(int sock) return ret; } -static pid_t qtest_qemu_pid(QTestState *s) +static pid_t read_pid_file(const char *pid_file) { FILE *f; char buffer[1024]; pid_t pid = -1; - f = fopen(s->pid_file, "r"); + f = fopen(pid_file, "r"); if (f) { if (fgets(buffer, sizeof(buffer), f)) { pid = atoi(buffer); @@ -110,6 +109,8 @@ QTestState *qtest_init(const char *extra_args) { QTestState *s; int sock, qmpsock, i; + gchar *socket_path; + gchar *qmp_socket_path; gchar *pid_file; gchar *command; const char *qemu_binary; @@ -120,12 +121,12 @@ QTestState *qtest_init(const char *extra_args) s = g_malloc(sizeof(*s)); - s->socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid()); - s->qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid()); + socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid()); + qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid()); pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid()); - sock = init_socket(s->socket_path); - qmpsock = init_socket(s->qmp_socket_path); + sock = init_socket(socket_path); + qmpsock = init_socket(qmp_socket_path); pid = fork(); if (pid == 0) { @@ -136,8 +137,8 @@ QTestState *qtest_init(const char *extra_args) "-pidfile %s " "-machine accel=qtest " "-display none " - "%s", qemu_binary, s->socket_path, - s->qmp_socket_path, pid_file, + "%s", qemu_binary, socket_path, + qmp_socket_path, pid_file, extra_args ?: ""); execlp("/bin/sh", "sh", "-c", command, NULL); exit(1); @@ -145,9 +146,12 @@ QTestState *qtest_init(const char *extra_args) s->fd = socket_accept(sock); s->qmp_fd = socket_accept(qmpsock); + unlink(socket_path); + unlink(qmp_socket_path); + g_free(socket_path); + g_free(qmp_socket_path); s->rx = g_string_new(""); - s->pid_file = pid_file; s->child_pid = pid; for (i = 0; i < MAX_IRQ; i++) { s->irq_level[i] = false; @@ -157,8 +161,12 @@ QTestState *qtest_init(const char *extra_args) qtest_qmp_discard_response(s, ""); qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); + s->qemu_pid = read_pid_file(pid_file); + unlink(pid_file); + g_free(pid_file); + if (getenv("QTEST_STOP")) { - kill(qtest_qemu_pid(s), SIGSTOP); + kill(s->qemu_pid, SIGSTOP); } return s; @@ -168,21 +176,14 @@ void qtest_quit(QTestState *s) { int status; - pid_t pid = qtest_qemu_pid(s); - if (pid != -1) { - kill(pid, SIGTERM); - waitpid(pid, &status, 0); + if (s->qemu_pid != -1) { + kill(s->qemu_pid, SIGTERM); + waitpid(s->qemu_pid, &status, 0); } close(s->fd); close(s->qmp_fd); g_string_free(s->rx, true); - unlink(s->pid_file); - unlink(s->socket_path); - unlink(s->qmp_socket_path); - g_free(s->pid_file); - g_free(s->socket_path); - g_free(s->qmp_socket_path); g_free(s); } diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 72eaad5b08..734b6a6bb4 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -35,12 +35,8 @@ test_img = os.path.join(iotests.test_dir, 'test.img') class ImageCommitTestCase(iotests.QMPTestCase): '''Abstract base class for image commit test cases''' - def assert_no_active_commit(self): - result = self.vm.qmp('query-block-jobs') - self.assert_qmp(result, 'return', []) - def run_commit_test(self, top, base): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top=top, base=base) self.assert_qmp(result, 'return', {}) @@ -59,7 +55,7 @@ class ImageCommitTestCase(iotests.QMPTestCase): self.assert_qmp(event, 'data/len', self.image_len) self.vm.qmp('block-job-complete', device='drive0') - self.assert_no_active_commit() + self.assert_no_active_block_jobs() self.vm.shutdown() class TestSingleDrive(ImageCommitTestCase): @@ -91,19 +87,19 @@ class TestSingleDrive(ImageCommitTestCase): self.assert_qmp(result, 'error/class', 'DeviceNotFound') def test_top_same_base(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % backing_img) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % backing_img) def test_top_invalid(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='badfile', base='%s' % backing_img) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Top image file badfile not found') def test_base_invalid(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='%s' % mid_img, base='badfile') self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Base \'badfile\' not found') @@ -114,13 +110,13 @@ class TestSingleDrive(ImageCommitTestCase): self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed")) def test_top_and_base_reversed(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % mid_img) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % mid_img) def test_top_omitted(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0') self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', "Parameter 'top' is missing") @@ -181,19 +177,19 @@ class TestRelativePaths(ImageCommitTestCase): self.assert_qmp(result, 'error/class', 'DeviceNotFound') def test_top_same_base(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.mid_img, base='%s' % self.mid_img) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % self.mid_img) def test_top_invalid(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='badfile', base='%s' % self.backing_img) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Top image file badfile not found') def test_base_invalid(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.mid_img, base='badfile') self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Base \'badfile\' not found') @@ -204,7 +200,7 @@ class TestRelativePaths(ImageCommitTestCase): self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', self.backing_img_abs).find("verification failed")) def test_top_and_base_reversed(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() result = self.vm.qmp('block-commit', device='drive0', top='%s' % self.backing_img, base='%s' % self.mid_img) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % self.mid_img) @@ -229,7 +225,7 @@ class TestSetSpeed(ImageCommitTestCase): os.remove(backing_img) def test_set_speed(self): - self.assert_no_active_commit() + self.assert_no_active_block_jobs() self.vm.pause_drive('drive0') result = self.vm.qmp('block-commit', device='drive0', top=mid_img, speed=1024 * 1024) diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071 index 2a22546e1a..dbc07c6c4f 100755 --- a/tests/qemu-iotests/071 +++ b/tests/qemu-iotests/071 @@ -38,7 +38,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.rc . ./common.filter -_supported_fmt generic +_supported_fmt qcow2 _supported_proto generic _supported_os Linux diff --git a/util/osdep.c b/util/osdep.c index 62072b4be3..bd4f530ad1 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -46,7 +46,6 @@ extern int madvise(caddr_t, size_t, int); #endif #include "qemu-common.h" -#include "trace.h" #include "qemu/sockets.h" #include "monitor/monitor.h" |