aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2011-12-04 12:38:06 +0200
committerAvi Kivity <avi@redhat.com>2011-12-04 12:38:06 +0200
commit30c044521889195f54a9f2c21310894f545994e8 (patch)
treef702871ad073a9709b9bbb85de7e361707ba6915
parent1c1f6b0eb72fb859ff19be930b4c8f6699f705a4 (diff)
parent1c8a881daaca6fe0646a425b0970fb3ad25f6732 (diff)
Merge commit 'v1.0' into nextqemu-kvm-1.0
* commit 'v1.0': (47 commits) Update version for 1.0 release Makefile: use full path for qapi-generated directory qapi: fix guardname generation Update version for 1.0-rc4 ccid: Fix buffer overrun in handling of VSC_ATR message Revert "fix out of tree build" configure: avoid screening of --{en, dis}able-usb-redir options cutils: Make strtosz & friends leave follow set to callers qemu-img: Tighten parsing of size arguments x86/cpuid: Tighten parsing of tsc_freq=FREQ vl: Tighten parsing of -m argument vl: Tighten parsing of -numa's parameter mem cutils: Drop broken support for zero strtosz default_suffix configure: tighten pie toolchain support test for tls variables usb-redir: Don't try to write to the chardev after a close event usb-redir: Device disconnect + re-connect robustness fixes usb-redir: Call qemu_chr_fe_open/close spice-qemu-char: Generate chardev open/close events qemu-char: rename qemu_chr_event to qemu_chr_be_event and make it public 9pfs: improve portability to older systems ... Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Makefile2
-rw-r--r--VERSION2
-rw-r--r--block/qcow.c12
-rw-r--r--block/sheepdog.c2
-rw-r--r--block/vdi.c15
-rw-r--r--block/vmdk.c16
-rw-r--r--block/vpc.c18
-rw-r--r--block/vvfat.c17
-rwxr-xr-xconfigure22
-rw-r--r--cutils.c81
-rw-r--r--hw/9pfs/virtio-9p-local.c14
-rw-r--r--hw/ccid-card-passthru.c1
-rw-r--r--hw/eepro100.c10
-rw-r--r--hw/pci-hotplug.c3
-rw-r--r--hw/rtl8139.c14
-rw-r--r--hw/s390-virtio-bus.c5
-rw-r--r--hw/scsi-bus.c11
-rw-r--r--hw/scsi-generic.c5
-rw-r--r--hw/scsi.h2
-rw-r--r--hw/syborg_virtio.c4
-rw-r--r--hw/usb-bt.c3
-rw-r--r--hw/usb-bus.c29
-rw-r--r--hw/usb-ehci.c58
-rw-r--r--hw/usb-hub.c22
-rw-r--r--hw/usb-msd.c4
-rw-r--r--hw/virtio-blk.c7
-rw-r--r--hw/virtio-pci.c9
-rw-r--r--hw/virtio.c24
-rw-r--r--hw/virtio.h1
-rw-r--r--net/slirp.c9
-rw-r--r--oslib-posix.c5
-rw-r--r--qemu-char.c26
-rw-r--r--qemu-char.h10
-rw-r--r--qemu-img.c10
-rw-r--r--qemu-os-posix.h3
-rw-r--r--scripts/qapi.py7
-rw-r--r--spice-qemu-char.c36
-rw-r--r--target-i386/cpuid.c29
-rw-r--r--tcg/tci/tcg-target.c4
-rw-r--r--tcg/tci/tcg-target.h4
-rw-r--r--usb-linux.c25
-rw-r--r--usb-redir.c29
-rw-r--r--vl.c9
43 files changed, 426 insertions, 193 deletions
diff --git a/Makefile b/Makefile
index 812c4c3ea..a0cd7076e 100644
--- a/Makefile
+++ b/Makefile
@@ -168,7 +168,7 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
$(qapi-obj-y): $(GENERATED_HEADERS)
-qapi-dir := qapi-generated
+qapi-dir := $(BUILD_DIR)/qapi-generated
test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
diff --git a/VERSION b/VERSION
index 82fd64152..d3827e75a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.15.93
+1.0
diff --git a/block/qcow.c b/block/qcow.c
index adecee06c..4814ed0ce 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -26,6 +26,7 @@
#include "module.h"
#include <zlib.h>
#include "aes.h"
+#include "migration.h"
/**************************************************************/
/* QEMU COW block driver with compression and encryption support */
@@ -74,6 +75,7 @@ typedef struct BDRVQcowState {
AES_KEY aes_encrypt_key;
AES_KEY aes_decrypt_key;
CoMutex lock;
+ Error *migration_blocker;
} BDRVQcowState;
static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
@@ -160,6 +162,12 @@ static int qcow_open(BlockDriverState *bs, int flags)
bs->backing_file[len] = '\0';
}
+ /* Disable migration when qcow images are used */
+ error_set(&s->migration_blocker,
+ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ "qcow", bs->device_name, "live migration");
+ migrate_add_blocker(s->migration_blocker);
+
qemu_co_mutex_init(&s->lock);
return 0;
@@ -604,10 +612,14 @@ static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
static void qcow_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
+
g_free(s->l1_table);
g_free(s->l2_cache);
g_free(s->cluster_cache);
g_free(s->cluster_data);
+
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
}
static int qcow_create(const char *filename, QEMUOptionParameter *options)
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 9f8060960..62f1f3a0c 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1116,6 +1116,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
/* send a header */
ret = do_write(s->fd, &hdr, sizeof(hdr));
if (ret) {
+ qemu_co_mutex_unlock(&s->lock);
error_report("failed to send a req, %s", strerror(errno));
return -EIO;
}
@@ -1123,6 +1124,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
if (wlen) {
ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
if (ret) {
+ qemu_co_mutex_unlock(&s->lock);
error_report("failed to send a data, %s", strerror(errno));
return -EIO;
}
diff --git a/block/vdi.c b/block/vdi.c
index 684a4a87b..02da6b44d 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -52,6 +52,7 @@
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
+#include "migration.h"
#if defined(CONFIG_UUID)
#include <uuid/uuid.h>
@@ -203,6 +204,8 @@ typedef struct {
uint32_t bmap_sector;
/* VDI header (converted to host endianness). */
VdiHeader header;
+
+ Error *migration_blocker;
} BDRVVdiState;
/* Change UUID from little endian (IPRT = VirtualBox format) to big endian
@@ -454,6 +457,12 @@ static int vdi_open(BlockDriverState *bs, int flags)
goto fail_free_bmap;
}
+ /* Disable migration when vdi images are used */
+ error_set(&s->migration_blocker,
+ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ "vdi", bs->device_name, "live migration");
+ migrate_add_blocker(s->migration_blocker);
+
return 0;
fail_free_bmap:
@@ -939,6 +948,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
static void vdi_close(BlockDriverState *bs)
{
+ BDRVVdiState *s = bs->opaque;
+
+ g_free(s->bmap);
+
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
}
static coroutine_fn int vdi_co_flush(BlockDriverState *bs)
diff --git a/block/vmdk.c b/block/vmdk.c
index 96f7d5d90..f5441591d 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -26,6 +26,7 @@
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
+#include "migration.h"
#include <zlib.h>
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
@@ -97,6 +98,7 @@ typedef struct BDRVVmdkState {
int num_extents;
/* Extent array with num_extents entries, ascend ordered by address */
VmdkExtent *extents;
+ Error *migration_blocker;
} BDRVVmdkState;
typedef struct VmdkMetaData {
@@ -659,7 +661,14 @@ static int vmdk_open(BlockDriverState *bs, int flags)
}
s->parent_cid = vmdk_read_cid(bs, 1);
qemu_co_mutex_init(&s->lock);
- return ret;
+
+ /* Disable migration when VMDK images are used */
+ error_set(&s->migration_blocker,
+ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ "vmdk", bs->device_name, "live migration");
+ migrate_add_blocker(s->migration_blocker);
+
+ return 0;
fail:
vmdk_free_extents(bs);
@@ -1504,7 +1513,12 @@ exit:
static void vmdk_close(BlockDriverState *bs)
{
+ BDRVVmdkState *s = bs->opaque;
+
vmdk_free_extents(bs);
+
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
}
static coroutine_fn int vmdk_co_flush(BlockDriverState *bs)
diff --git a/block/vpc.c b/block/vpc.c
index 39a324705..89a5ee266 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -25,6 +25,7 @@
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
+#include "migration.h"
/**************************************************************/
@@ -128,6 +129,8 @@ typedef struct BDRVVPCState {
uint64_t last_bitmap;
#endif
+
+ Error *migration_blocker;
} BDRVVPCState;
static uint32_t vpc_checksum(uint8_t* buf, size_t size)
@@ -228,6 +231,13 @@ static int vpc_open(BlockDriverState *bs, int flags)
#endif
qemu_co_mutex_init(&s->lock);
+
+ /* Disable migration when VHD images are used */
+ error_set(&s->migration_blocker,
+ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ "vpc", bs->device_name, "live migration");
+ migrate_add_blocker(s->migration_blocker);
+
return 0;
fail:
return err;
@@ -352,8 +362,11 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
// Initialize the block's bitmap
memset(bitmap, 0xff, s->bitmap_size);
- bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
+ ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
s->bitmap_size);
+ if (ret < 0) {
+ return ret;
+ }
// Write new footer (the old one will be overwritten)
s->free_data_block_offset += s->block_size + s->bitmap_size;
@@ -651,6 +664,9 @@ static void vpc_close(BlockDriverState *bs)
#ifdef CACHE
g_free(s->pageentry_u8);
#endif
+
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
}
static QEMUOptionParameter vpc_create_options[] = {
diff --git a/block/vvfat.c b/block/vvfat.c
index 131680f6f..a310ce8c3 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -27,6 +27,7 @@
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
+#include "migration.h"
#ifndef S_IWGRP
#define S_IWGRP 0
@@ -350,6 +351,8 @@ typedef struct BDRVVVFATState {
array_t commits;
const char* path;
int downcase_short_names;
+
+ Error *migration_blocker;
} BDRVVVFATState;
/* take the sector position spos and convert it to Cylinder/Head/Sector position
@@ -1073,6 +1076,15 @@ DLOG(if (stderr == NULL) {
// assert(is_consistent(s));
qemu_co_mutex_init(&s->lock);
+
+ /* Disable migration when vvfat is used rw */
+ if (s->qcow) {
+ error_set(&s->migration_blocker,
+ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ "vvfat (rw)", bs->device_name, "live migration");
+ migrate_add_blocker(s->migration_blocker);
+ }
+
return 0;
}
@@ -2829,6 +2841,11 @@ static void vvfat_close(BlockDriverState *bs)
array_free(&(s->directory));
array_free(&(s->mapping));
g_free(s->cluster_buffer);
+
+ if (s->qcow) {
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
+ }
}
static BlockDriver bdrv_vvfat = {
diff --git a/configure b/configure
index 02b04d4e0..7ecf44e0b 100755
--- a/configure
+++ b/configure
@@ -583,6 +583,14 @@ for opt do
;;
--sysconfdir=*) sysconfdir="$optarg"
;;
+ --sbindir=*|--libexecdir=*|--sharedstatedir=*|--localstatedir=*|\
+ --oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\
+ --htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
+ # These switches are silently ignored, for compatibility with
+ # autoconf-generated configure scripts. This allows QEMU's
+ # configure to be used by RPM and similar macros that set
+ # lots of directory switches by default.
+ ;;
--disable-sdl) sdl="no"
;;
--enable-sdl) sdl="yes"
@@ -783,8 +791,6 @@ for opt do
;;
--enable-opengl) opengl="yes"
;;
- --*dir)
- ;;
--disable-rbd) rbd="no"
;;
--enable-rbd) rbd="yes"
@@ -1149,7 +1155,17 @@ fi
if test "$pie" != "no" ; then
cat > $TMPC << EOF
-int main(void) { return 0; }
+
+#ifdef __linux__
+# define THREAD __thread
+#else
+# define THREAD
+#endif
+
+static THREAD int tls_var;
+
+int main(void) { return tls_var; }
+
EOF
if compile_prog "-fPIE -DPIE" "-pie"; then
QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
diff --git a/cutils.c b/cutils.c
index 5d995bc4e..6db6304bb 100644
--- a/cutils.c
+++ b/cutils.c
@@ -315,19 +315,34 @@ int fcntl_setfl(int fd, int flag)
}
#endif
+static int64_t suffix_mul(char suffix, int64_t unit)
+{
+ switch (qemu_toupper(suffix)) {
+ case STRTOSZ_DEFSUFFIX_B:
+ return 1;
+ case STRTOSZ_DEFSUFFIX_KB:
+ return unit;
+ case STRTOSZ_DEFSUFFIX_MB:
+ return unit * unit;
+ case STRTOSZ_DEFSUFFIX_GB:
+ return unit * unit * unit;
+ case STRTOSZ_DEFSUFFIX_TB:
+ return unit * unit * unit * unit;
+ }
+ return -1;
+}
+
/*
* Convert string to bytes, allowing either B/b for bytes, K/k for KB,
- * M/m for MB, G/g for GB or T/t for TB. Default without any postfix
- * is MB. End pointer will be returned in *end, if not NULL. A valid
- * value must be terminated by whitespace, ',' or '\0'. Return -1 on
- * error.
+ * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
+ * in *end, if not NULL. Return -1 on error.
*/
int64_t strtosz_suffix_unit(const char *nptr, char **end,
const char default_suffix, int64_t unit)
{
int64_t retval = -1;
char *endptr;
- unsigned char c, d;
+ unsigned char c;
int mul_required = 0;
double val, mul, integral, fraction;
@@ -340,59 +355,17 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,
if (fraction != 0) {
mul_required = 1;
}
- /*
- * Any whitespace character is fine for terminating the number,
- * in addition we accept ',' to handle strings where the size is
- * part of a multi token argument.
- */
c = *endptr;
- d = c;
- if (qemu_isspace(c) || c == '\0' || c == ',') {
- c = 0;
- if (default_suffix) {
- d = default_suffix;
- } else {
- d = c;
- }
+ mul = suffix_mul(c, unit);
+ if (mul >= 0) {
+ endptr++;
+ } else {
+ mul = suffix_mul(default_suffix, unit);
+ assert(mul >= 0);
}
- switch (qemu_toupper(d)) {
- case STRTOSZ_DEFSUFFIX_B:
- mul = 1;
- if (mul_required) {
- goto fail;
- }
- break;
- case STRTOSZ_DEFSUFFIX_KB:
- mul = unit;
- break;
- case 0:
- if (mul_required) {
- goto fail;
- }
- case STRTOSZ_DEFSUFFIX_MB:
- mul = unit * unit;
- break;
- case STRTOSZ_DEFSUFFIX_GB:
- mul = unit * unit * unit;
- break;
- case STRTOSZ_DEFSUFFIX_TB:
- mul = unit * unit * unit * unit;
- break;
- default:
+ if (mul == 1 && mul_required) {
goto fail;
}
- /*
- * If not terminated by whitespace, ',', or \0, increment endptr
- * to point to next character, then check that we are terminated
- * by an appropriate separating character, ie. whitespace, ',', or
- * \0. If not, we are seeing trailing garbage, thus fail.
- */
- if (c != 0) {
- endptr++;
- if (!qemu_isspace(*endptr) && *endptr != ',' && *endptr != 0) {
- goto fail;
- }
- }
if ((val * mul >= INT64_MAX) || val < 0) {
goto fail;
}
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 7f1c0894d..99ef0cd33 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -583,8 +583,7 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
char buffer[PATH_MAX];
char *path = fs_path->data;
- return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf,
- AT_SYMLINK_NOFOLLOW);
+ return qemu_utimens(rpath(s, path, buffer), buf);
}
static int local_remove(FsContext *ctx, const char *path)
@@ -694,6 +693,7 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
mode_t st_mode, uint64_t *st_gen)
{
int err;
+#ifdef FS_IOC_GETVERSION
V9fsFidOpenState fid_open;
/*
@@ -709,15 +709,22 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
}
err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
local_close(ctx, &fid_open);
+#else
+ err = -ENOTTY;
+#endif
return err;
}
static int local_init(FsContext *ctx)
{
- int err;
+ int err = 0;
struct statfs stbuf;
ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
+#ifdef FS_IOC_GETVERSION
+ /*
+ * use ioc_getversion only if the iocl is definied
+ */
err = statfs(ctx->fs_root, &stbuf);
if (!err) {
switch (stbuf.f_type) {
@@ -729,6 +736,7 @@ static int local_init(FsContext *ctx)
break;
}
}
+#endif
return err;
}
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 2cbc81b9f..9f51c6cb0 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -150,6 +150,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
error_report("ATR size exceeds spec, ignoring");
ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
VSC_GENERAL_ERROR);
+ break;
}
memcpy(card->atr, data, scr_msg_header->length);
card->atr_length = scr_msg_header->length;
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 7d59e7136..29ec5b44f 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -976,7 +976,15 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
case CU_STATSADDR:
/* Load dump counters address. */
s->statsaddr = e100_read_reg4(s, SCBPointer);
- TRACE(OTHER, logout("val=0x%02x (status address)\n", val));
+ TRACE(OTHER, logout("val=0x%02x (dump counters address)\n", val));
+ if (s->statsaddr & 3) {
+ /* Memory must be Dword aligned. */
+ logout("unaligned dump counters address\n");
+ /* Handling of misaligned addresses is undefined.
+ * Here we align the address by ignoring the lower bits. */
+ /* TODO: Test unaligned dump counter address on real hardware. */
+ s->statsaddr &= ~3;
+ }
break;
case CU_SHOWSTATS:
/* Dump statistical counters. */
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index b59be2a59..12f61fea6 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -91,7 +91,8 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
*/
dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
dinfo->bus = scsibus->busnr;
- scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false);
+ scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
+ false, -1);
if (!scsidev) {
return -1;
}
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 4c379932e..aa8ed0a91 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -1971,7 +1971,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
cplus_tx_ring_desc += 16 * descriptor;
DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at "
- "%08x0x%08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1],
+ "%08x %08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1],
s->TxAddr[0], cplus_tx_ring_desc);
uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
@@ -2713,8 +2713,6 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
{
RTL8139State *s = opaque;
- addr &= 0xff;
-
switch (addr)
{
case MAC0 ... MAC0+5:
@@ -2800,8 +2798,6 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
{
RTL8139State *s = opaque;
- addr &= 0xfe;
-
switch (addr)
{
case IntrMask:
@@ -2900,8 +2896,6 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
{
RTL8139State *s = opaque;
- addr &= 0xfc;
-
switch (addr)
{
case RxMissed:
@@ -2969,8 +2963,6 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
RTL8139State *s = opaque;
int ret;
- addr &= 0xff;
-
switch (addr)
{
case MAC0 ... MAC0+5:
@@ -3043,8 +3035,6 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
RTL8139State *s = opaque;
uint32_t ret;
- addr &= 0xfe; /* mask lower bit */
-
switch (addr)
{
case IntrMask:
@@ -3120,8 +3110,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
RTL8139State *s = opaque;
uint32_t ret;
- addr &= 0xfc; /* also mask low 2 bits */
-
switch (addr)
{
case RxMissed:
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 0ce6406b6..c4b9a99e6 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -254,10 +254,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
/* Update guest supported feature bitmap */
features = bswap32(ldl_be_phys(dev->feat_offs));
- if (vdev->set_features) {
- vdev->set_features(vdev, features);
- }
- vdev->guest_features = features;
+ virtio_set_features(vdev, features);
}
VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 3a2a7bb72..64e709ee9 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -162,7 +162,7 @@ void scsi_qdev_register(SCSIDeviceInfo *info)
/* handle legacy '-drive if=scsi,...' cmd line args */
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
- int unit, bool removable)
+ int unit, bool removable, int bootindex)
{
const char *driver;
DeviceState *dev;
@@ -170,6 +170,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
dev = qdev_create(&bus->qbus, driver);
qdev_prop_set_uint32(dev, "scsi-id", unit);
+ if (bootindex >= 0) {
+ qdev_prop_set_int32(dev, "bootindex", bootindex);
+ }
if (qdev_prop_exists(dev, "removable")) {
qdev_prop_set_bit(dev, "removable", removable);
}
@@ -195,7 +198,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
continue;
}
qemu_opts_loc_restore(dinfo->opts);
- if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) {
+ if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) {
res = -1;
break;
}
@@ -1367,8 +1370,8 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
char path[100];
- snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev),
- d->channel, d->id, d->lun);
+ snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel,
+ qdev_fw_name(dev), d->id, d->lun);
return strdup(path);
}
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 9594cc127..e62044f39 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -413,6 +413,10 @@ static int scsi_generic_initfn(SCSIDevice *s)
/* define device state */
s->type = scsiid.scsi_type;
DPRINTF("device type %d\n", s->type);
+ if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
+ add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
+ }
+
switch (s->type) {
case TYPE_TAPE:
s->blocksize = get_stream_blocksize(s->conf.bs);
@@ -459,6 +463,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
static SCSIDeviceInfo scsi_generic_info = {
.qdev.name = "scsi-generic",
+ .qdev.fw_name = "disk",
.qdev.desc = "pass through generic scsi device (/dev/sg*)",
.qdev.size = sizeof(SCSIDevice),
.qdev.reset = scsi_generic_reset,
diff --git a/hw/scsi.h b/hw/scsi.h
index 61c64d5c7..ab6e95232 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -128,7 +128,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
}
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
- int unit, bool removable);
+ int unit, bool removable, int bootindex);
int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
/*
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 00c7be8c8..6de952c93 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -131,9 +131,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
}
switch (offset >> 2) {
case SYBORG_VIRTIO_GUEST_FEATURES:
- if (vdev->set_features)
- vdev->set_features(vdev, value);
- vdev->guest_features = value;
+ virtio_set_features(vdev, value);
break;
case SYBORG_VIRTIO_QUEUE_BASE:
if (value == 0)
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 529fa3355..f30eec1ea 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -528,6 +528,9 @@ USBDevice *usb_bt_init(HCIInfo *hci)
if (!hci)
return NULL;
dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle");
+ if (!dev) {
+ return NULL;
+ }
s = DO_UPCAST(struct USBBtState, dev, dev);
s->dev.opaque = s;
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 93f640d37..8cafb76ff 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -9,6 +9,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
static char *usb_get_dev_path(DeviceState *dev);
static char *usb_get_fw_dev_path(DeviceState *qdev);
+static int usb_qdev_exit(DeviceState *qdev);
static struct BusInfo usb_bus_info = {
.name = "USB",
@@ -75,12 +76,23 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
dev->auto_attach = 1;
QLIST_INIT(&dev->strings);
rc = usb_claim_port(dev);
- if (rc == 0) {
- rc = dev->info->init(dev);
+ if (rc != 0) {
+ goto err;
}
- if (rc == 0 && dev->auto_attach) {
+ rc = dev->info->init(dev);
+ if (rc != 0) {
+ goto err;
+ }
+ if (dev->auto_attach) {
rc = usb_device_attach(dev);
+ if (rc != 0) {
+ goto err;
+ }
}
+ return 0;
+
+err:
+ usb_qdev_exit(qdev);
return rc;
}
@@ -139,10 +151,17 @@ USBDevice *usb_create(USBBus *bus, const char *name)
USBDevice *usb_create_simple(USBBus *bus, const char *name)
{
USBDevice *dev = usb_create(bus, name);
+ int rc;
+
if (!dev) {
- hw_error("Failed to create USB device '%s'\n", name);
+ error_report("Failed to create USB device '%s'\n", name);
+ return NULL;
+ }
+ rc = qdev_init(&dev->qdev);
+ if (rc < 0) {
+ error_report("Failed to initialize USB device '%s'\n", name);
+ return NULL;
}
- qdev_init_nofail(&dev->qdev);
return dev;
}
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 3eea94d09..a946e1d1f 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -437,37 +437,39 @@ struct EHCIState {
} while(0)
static const char *ehci_state_names[] = {
- [ EST_INACTIVE ] = "INACTIVE",
- [ EST_ACTIVE ] = "ACTIVE",
- [ EST_EXECUTING ] = "EXECUTING",
- [ EST_SLEEPING ] = "SLEEPING",
- [ EST_WAITLISTHEAD ] = "WAITLISTHEAD",
- [ EST_FETCHENTRY ] = "FETCH ENTRY",
- [ EST_FETCHQH ] = "FETCH QH",
- [ EST_FETCHITD ] = "FETCH ITD",
- [ EST_ADVANCEQUEUE ] = "ADVANCEQUEUE",
- [ EST_FETCHQTD ] = "FETCH QTD",
- [ EST_EXECUTE ] = "EXECUTE",
- [ EST_WRITEBACK ] = "WRITEBACK",
- [ EST_HORIZONTALQH ] = "HORIZONTALQH",
+ [EST_INACTIVE] = "INACTIVE",
+ [EST_ACTIVE] = "ACTIVE",
+ [EST_EXECUTING] = "EXECUTING",
+ [EST_SLEEPING] = "SLEEPING",
+ [EST_WAITLISTHEAD] = "WAITLISTHEAD",
+ [EST_FETCHENTRY] = "FETCH ENTRY",
+ [EST_FETCHQH] = "FETCH QH",
+ [EST_FETCHITD] = "FETCH ITD",
+ [EST_ADVANCEQUEUE] = "ADVANCEQUEUE",
+ [EST_FETCHQTD] = "FETCH QTD",
+ [EST_EXECUTE] = "EXECUTE",
+ [EST_WRITEBACK] = "WRITEBACK",
+ [EST_HORIZONTALQH] = "HORIZONTALQH",
};
static const char *ehci_mmio_names[] = {
- [ CAPLENGTH ] = "CAPLENGTH",
- [ HCIVERSION ] = "HCIVERSION",
- [ HCSPARAMS ] = "HCSPARAMS",
- [ HCCPARAMS ] = "HCCPARAMS",
- [ USBCMD ] = "USBCMD",
- [ USBSTS ] = "USBSTS",
- [ USBINTR ] = "USBINTR",
- [ FRINDEX ] = "FRINDEX",
- [ PERIODICLISTBASE ] = "P-LIST BASE",
- [ ASYNCLISTADDR ] = "A-LIST ADDR",
- [ PORTSC_BEGIN ] = "PORTSC #0",
- [ PORTSC_BEGIN + 4] = "PORTSC #1",
- [ PORTSC_BEGIN + 8] = "PORTSC #2",
- [ PORTSC_BEGIN + 12] = "PORTSC #3",
- [ CONFIGFLAG ] = "CONFIGFLAG",
+ [CAPLENGTH] = "CAPLENGTH",
+ [HCIVERSION] = "HCIVERSION",
+ [HCSPARAMS] = "HCSPARAMS",
+ [HCCPARAMS] = "HCCPARAMS",
+ [USBCMD] = "USBCMD",
+ [USBSTS] = "USBSTS",
+ [USBINTR] = "USBINTR",
+ [FRINDEX] = "FRINDEX",
+ [PERIODICLISTBASE] = "P-LIST BASE",
+ [ASYNCLISTADDR] = "A-LIST ADDR",
+ [PORTSC_BEGIN] = "PORTSC #0",
+ [PORTSC_BEGIN + 4] = "PORTSC #1",
+ [PORTSC_BEGIN + 8] = "PORTSC #2",
+ [PORTSC_BEGIN + 12] = "PORTSC #3",
+ [PORTSC_BEGIN + 16] = "PORTSC #4",
+ [PORTSC_BEGIN + 20] = "PORTSC #5",
+ [CONFIGFLAG] = "CONFIGFLAG",
};
static const char *nr2str(const char **n, size_t len, uint32_t nr)
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 3eb0f1aa0..e1959372e 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -171,6 +171,8 @@ static void usb_hub_detach(USBPort *port1)
USBHubState *s = port1->opaque;
USBHubPort *port = &s->ports[port1->index];
+ usb_wakeup(&s->dev);
+
/* Let upstream know the device on this port is gone */
s->dev.port->ops->child_detach(s->dev.port, port1->dev);
@@ -220,7 +222,22 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
static void usb_hub_handle_reset(USBDevice *dev)
{
- /* XXX: do it */
+ USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+ USBHubPort *port;
+ int i;
+
+ for (i = 0; i < NUM_PORTS; i++) {
+ port = s->ports + i;
+ port->wPortStatus = PORT_STAT_POWER;
+ port->wPortChange = 0;
+ if (port->port.dev && port->port.dev->attached) {
+ port->wPortStatus |= PORT_STAT_CONNECTION;
+ port->wPortChange |= PORT_STAT_C_CONNECTION;
+ if (port->port.dev->speed == USB_SPEED_LOW) {
+ port->wPortStatus |= PORT_STAT_LOW_SPEED;
+ }
+ }
+ }
}
static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
@@ -495,9 +512,8 @@ static int usb_hub_initfn(USBDevice *dev)
&port->port, s, i, &usb_hub_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
usb_port_location(&port->port, dev->port, i+1);
- port->wPortStatus = PORT_STAT_POWER;
- port->wPortChange = 0;
}
+ usb_hub_handle_reset(dev);
return 0;
}
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 68e375678..4c0695012 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -546,7 +546,8 @@ static int usb_msd_initfn(USBDevice *dev)
usb_desc_init(dev);
scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
- s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
+ s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
+ s->conf.bootindex);
if (!s->scsi_dev) {
return -1;
}
@@ -562,7 +563,6 @@ static int usb_msd_initfn(USBDevice *dev)
}
}
- add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0");
return 0;
}
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 19e89e71e..d6d1f87cd 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -485,6 +485,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
struct virtio_blk_config blkcfg;
uint64_t capacity;
int cylinders, heads, secs;
+ int blk_size = s->conf->logical_block_size;
bdrv_get_geometry(s->bs, &capacity);
bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
@@ -492,14 +493,14 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
stq_raw(&blkcfg.capacity, capacity);
stl_raw(&blkcfg.seg_max, 128 - 2);
stw_raw(&blkcfg.cylinders, cylinders);
+ stl_raw(&blkcfg.blk_size, blk_size);
+ stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
+ stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
blkcfg.heads = heads;
blkcfg.sectors = secs & ~s->sector_mask;
- blkcfg.blk_size = s->conf->logical_block_size;
blkcfg.size_max = 0;
blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
blkcfg.alignment_offset = 0;
- blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size;
- blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size;
memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
}
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index ef8bb14d0..f13e1d59d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -285,14 +285,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
case VIRTIO_PCI_GUEST_FEATURES:
/* Guest does not negotiate properly? We have to assume nothing. */
if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
- if (vdev->bad_features)
- val = proxy->host_features & vdev->bad_features(vdev);
- else
- val = 0;
+ val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
}
- if (vdev->set_features)
- vdev->set_features(vdev, val);
- vdev->guest_features = val;
+ virtio_set_features(vdev, val);
break;
case VIRTIO_PCI_QUEUE_PFN:
pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
diff --git a/hw/virtio.c b/hw/virtio.c
index 7011b5b39..81ecc40b3 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
}
}
+int virtio_set_features(VirtIODevice *vdev, uint32_t val)
+{
+ uint32_t supported_features =
+ vdev->binding->get_features(vdev->binding_opaque);
+ bool bad = (val & ~supported_features) != 0;
+
+ val &= supported_features;
+ if (vdev->set_features) {
+ vdev->set_features(vdev, val);
+ }
+ vdev->guest_features = val;
+ return bad ? -1 : 0;
+}
+
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
int num, i, ret;
uint32_t features;
- uint32_t supported_features =
- vdev->binding->get_features(vdev->binding_opaque);
+ uint32_t supported_features;
if (vdev->binding->load_config) {
ret = vdev->binding->load_config(vdev->binding_opaque, f);
@@ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
qemu_get_8s(f, &vdev->isr);
qemu_get_be16s(f, &vdev->queue_sel);
qemu_get_be32s(f, &features);
- if (features & ~supported_features) {
+
+ if (virtio_set_features(vdev, features) < 0) {
+ supported_features = vdev->binding->get_features(vdev->binding_opaque);
error_report("Features 0x%x unsupported. Allowed features: 0x%x",
features, supported_features);
return -1;
}
- if (vdev->set_features)
- vdev->set_features(vdev, features);
- vdev->guest_features = features;
vdev->config_len = qemu_get_be32(f);
qemu_get_buffer(f, vdev->config, vdev->config_len);
diff --git a/hw/virtio.h b/hw/virtio.h
index 2d18209fb..25f55647b 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -185,6 +185,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
void virtio_set_status(VirtIODevice *vdev, uint8_t val);
void virtio_reset(void *opaque);
void virtio_update_irq(VirtIODevice *vdev);
+int virtio_set_features(VirtIODevice *vdev, uint32_t val);
void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
void *opaque);
diff --git a/net/slirp.c b/net/slirp.c
index c6cda5dcb..6646ecb1c 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -305,7 +305,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
{
struct in_addr host_addr = { .s_addr = INADDR_ANY };
int host_port;
- char buf[256] = "";
+ char buf[256];
const char *src_str, *p;
SlirpState *s;
int is_udp = 0;
@@ -325,11 +325,10 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
return;
}
- if (!src_str || !src_str[0])
- goto fail_syntax;
-
p = src_str;
- get_str_sep(buf, sizeof(buf), &p, ':');
+ if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+ goto fail_syntax;
+ }
if (!strcmp(buf, "tcp") || buf[0] == '\0') {
is_udp = 0;
diff --git a/oslib-posix.c b/oslib-posix.c
index 6f297626c..ce755496b 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -162,8 +162,7 @@ int qemu_pipe(int pipefd[2])
return ret;
}
-int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
- int flags)
+int qemu_utimens(const char *path, const struct timespec *times)
{
struct timeval tv[2], tv_now;
struct stat st;
@@ -171,7 +170,7 @@ int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
#ifdef CONFIG_UTIMENSAT
int ret;
- ret = utimensat(dirfd, path, times, flags);
+ ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
if (ret != -1 || errno != ENOSYS) {
return ret;
}
diff --git a/qemu-char.c b/qemu-char.c
index b562bf88a..27abcb918 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -106,7 +106,7 @@
static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
QTAILQ_HEAD_INITIALIZER(chardevs);
-static void qemu_chr_event(CharDriverState *s, int event)
+void qemu_chr_be_event(CharDriverState *s, int event)
{
/* Keep track if the char device is open */
switch (event) {
@@ -126,7 +126,7 @@ static void qemu_chr_event(CharDriverState *s, int event)
static void qemu_chr_generic_open_bh(void *opaque)
{
CharDriverState *s = opaque;
- qemu_chr_event(s, CHR_EVENT_OPENED);
+ qemu_chr_be_event(s, CHR_EVENT_OPENED);
qemu_bh_delete(s->bh);
s->bh = NULL;
}
@@ -359,7 +359,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
bdrv_commit_all();
break;
case 'b':
- qemu_chr_event(chr, CHR_EVENT_BREAK);
+ qemu_chr_be_event(chr, CHR_EVENT_BREAK);
break;
case 'c':
/* Switch to the next registered device */
@@ -580,7 +580,7 @@ static void fd_chr_read(void *opaque)
if (size == 0) {
/* FD has been closed. Remove it from the active list. */
qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
return;
}
if (size > 0) {
@@ -613,7 +613,7 @@ static void fd_chr_close(struct CharDriverState *chr)
}
g_free(s);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
/* open a character device to a unix fd */
@@ -715,7 +715,7 @@ static void stdio_read(void *opaque)
if (size == 0) {
/* stdin has been closed. Remove it from the active list. */
qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
return;
}
if (size > 0) {
@@ -977,7 +977,7 @@ static void pty_chr_close(struct CharDriverState *chr)
qemu_del_timer(s->timer);
qemu_free_timer(s->timer);
g_free(s);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
@@ -1355,7 +1355,7 @@ static void pp_close(CharDriverState *chr)
ioctl(fd, PPRELEASE);
close(fd);
g_free(drv);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
@@ -1500,7 +1500,7 @@ static void win_chr_close(CharDriverState *chr)
else
qemu_del_polling_cb(win_chr_poll, chr);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
static int win_chr_init(CharDriverState *chr, const char *filename)
@@ -2108,7 +2108,7 @@ static void udp_chr_close(CharDriverState *chr)
closesocket(s->fd);
}
g_free(s);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr)
@@ -2213,7 +2213,7 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
} else {
if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
/* Handle IAC break commands by sending a serial break */
- qemu_chr_event(chr, CHR_EVENT_BREAK);
+ qemu_chr_be_event(chr, CHR_EVENT_BREAK);
s->do_telnetopt++;
}
s->do_telnetopt++;
@@ -2321,7 +2321,7 @@ static void tcp_chr_read(void *opaque)
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
closesocket(s->fd);
s->fd = -1;
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
} else if (size > 0) {
if (s->do_telnetopt)
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
@@ -2433,7 +2433,7 @@ static void tcp_chr_close(CharDriverState *chr)
closesocket(s->listen_fd);
}
g_free(s);
- qemu_chr_event(chr, CHR_EVENT_CLOSED);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
diff --git a/qemu-char.h b/qemu-char.h
index 7efcf99f5..8ca1e2d54 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -212,6 +212,16 @@ int qemu_chr_be_can_write(CharDriverState *s);
*/
void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
+
+/**
+ * @qemu_chr_be_event:
+ *
+ * Send an event from the back end to the front end.
+ *
+ * @event the event to send
+ */
+void qemu_chr_be_event(CharDriverState *s, int event);
+
void qemu_chr_add_handlers(CharDriverState *s,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
diff --git a/qemu-img.c b/qemu-img.c
index 86127f0b1..8bdae6649 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -332,8 +332,9 @@ static int img_create(int argc, char **argv)
/* Get image size, if specified */
if (optind < argc) {
int64_t sval;
- sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);
- if (sval < 0) {
+ char *end;
+ sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
+ if (sval < 0 || *end) {
error_report("Invalid image size specified! You may use k, M, G or "
"T suffixes for ");
error_report("kilobytes, megabytes, gigabytes and terabytes.");
@@ -710,8 +711,9 @@ static int img_convert(int argc, char **argv)
case 'S':
{
int64_t sval;
- sval = strtosz_suffix(optarg, NULL, STRTOSZ_DEFSUFFIX_B);
- if (sval < 0) {
+ char *end;
+ sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
+ if (sval < 0 || *end) {
error_report("Invalid minimum zero buffer size for sparse output specified");
return 1;
}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 920499d83..8e1149d96 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -44,7 +44,6 @@ typedef struct timeval qemu_timeval;
#endif
#endif
typedef struct timespec qemu_timespec;
-int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times,
- int flags);
+int qemu_utimens(const char *path, const qemu_timespec *times);
#endif
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 52999763e..6e05469e6 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -200,6 +200,7 @@ def basename(filename):
return filename.split("/")[-1]
def guardname(filename):
- if filename.startswith('./'):
- filename = filename[2:]
- return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H'
+ guard = basename(filename).rsplit(".", 1)[0]
+ for substr in [".", " ", "-"]:
+ guard = guard.replace(substr, "_")
+ return guard.upper() + '_H'
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index ac522022c..7e8eaa9fd 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -69,11 +69,40 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
return bytes;
}
+static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
+{
+ SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+
+#if SPICE_SERVER_VERSION < 0x000901
+ /*
+ * spice-server calls the state callback for the agent channel when the
+ * spice client connects / disconnects. Given that not the client but
+ * the server is doing the parsing of the messages this is wrong as the
+ * server is still listening. Worse, this causes the parser in the server
+ * to go out of sync, so we ignore state calls for subtype vdagent
+ * spicevmc chardevs. For the full story see:
+ * http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
+ */
+ if (strcmp(sin->subtype, "vdagent") == 0) {
+ return;
+ }
+#endif
+
+ if ((scd->chr->opened && connected) ||
+ (!scd->chr->opened && !connected)) {
+ return;
+ }
+
+ qemu_chr_be_event(scd->chr,
+ connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED);
+}
+
static SpiceCharDeviceInterface vmc_interface = {
.base.type = SPICE_INTERFACE_CHAR_DEVICE,
.base.description = "spice virtual channel char device",
.base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
.base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
+ .state = vmc_state,
.write = vmc_write,
.read = vmc_read,
};
@@ -197,7 +226,12 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
chr->chr_guest_open = spice_chr_guest_open;
chr->chr_guest_close = spice_chr_guest_close;
- qemu_chr_generic_open(chr);
+#if SPICE_SERVER_VERSION < 0x000901
+ /* See comment in vmc_state() */
+ if (strcmp(subtype, "vdagent") == 0) {
+ qemu_chr_generic_open(chr);
+ }
+#endif
*_chr = chr;
return 0;
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 21e589675..0b3af9060 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -107,14 +107,33 @@ 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__
+ asm volatile("cpuid"
+ : "=a"(vec[0]), "=b"(vec[1]),
+ "=c"(vec[2]), "=d"(vec[3])
+ : "0"(function), "c"(count) : "cc");
+#else
+ asm volatile("pusha \n\t"
+ "cpuid \n\t"
+ "mov %%eax, 0(%2) \n\t"
+ "mov %%ebx, 4(%2) \n\t"
+ "mov %%ecx, 8(%2) \n\t"
+ "mov %%edx, 12(%2) \n\t"
+ "popa"
+ : : "a"(function), "c"(count), "S"(vec)
+ : "memory", "cc");
+#endif
+
if (eax)
- *eax = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EAX);
+ *eax = vec[0];
if (ebx)
- *ebx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EBX);
+ *ebx = vec[1];
if (ecx)
- *ecx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_ECX);
+ *ecx = vec[2];
if (edx)
- *edx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EDX);
+ *edx = vec[3];
#endif
}
@@ -692,7 +711,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
tsc_freq = strtosz_suffix_unit(val, &err,
STRTOSZ_DEFSUFFIX_B, 1000);
- if (!*val || *err) {
+ if (tsc_freq < 0 || *err) {
fprintf(stderr, "bad numerical value %s\n", val);
goto error;
}
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index 942910e14..fc0880cec 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -373,10 +373,6 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
};
#endif
-static void flush_icache_range(unsigned long start, unsigned long stop)
-{
-}
-
static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend)
{
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index cb5858c9c..03e0fd1a7 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -157,4 +157,8 @@ void tci_disas(uint8_t opc);
unsigned long tcg_qemu_tb_exec(CPUState *env, uint8_t *tb_ptr);
#define tcg_qemu_tb_exec tcg_qemu_tb_exec
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+}
+
#endif /* TCG_TARGET_H */
diff --git a/usb-linux.c b/usb-linux.c
index d4426ea73..ab4c6930c 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -148,6 +148,25 @@ static int usb_host_read_file(char *line, size_t line_size,
const char *device_file, const char *device_name);
static int usb_linux_update_endp_table(USBHostDevice *s);
+static int usb_host_do_reset(USBHostDevice *dev)
+{
+ struct timeval s, e;
+ uint32_t usecs;
+ int ret;
+
+ gettimeofday(&s, NULL);
+ ret = ioctl(dev->fd, USBDEVFS_RESET);
+ gettimeofday(&e, NULL);
+ usecs = (e.tv_sec - s.tv_sec) * 1000000;
+ usecs += e.tv_usec - s.tv_usec;
+ if (usecs > 1000000) {
+ /* more than a second, something is fishy, broken usb device? */
+ fprintf(stderr, "husb: device %d:%d reset took %d.%06d seconds\n",
+ dev->bus_num, dev->addr, usecs / 1000000, usecs % 1000000);
+ }
+ return ret;
+}
+
static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
{
struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
@@ -606,7 +625,7 @@ static void usb_host_handle_reset(USBDevice *dev)
trace_usb_host_reset(s->bus_num, s->addr);
- ioctl(s->fd, USBDEVFS_RESET);
+ usb_host_do_reset(s);;
usb_host_claim_interfaces(s, 0);
usb_linux_update_endp_table(s);
@@ -1370,7 +1389,7 @@ static int usb_host_close(USBHostDevice *dev)
if (dev->dev.attached) {
usb_device_detach(&dev->dev);
}
- ioctl(dev->fd, USBDEVFS_RESET);
+ usb_host_do_reset(dev);
close(dev->fd);
dev->fd = -1;
return 0;
@@ -1381,7 +1400,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data)
USBHostDevice *s = container_of(n, USBHostDevice, exit);
if (s->fd != -1) {
- ioctl(s->fd, USBDEVFS_RESET);
+ usb_host_do_reset(s);;
}
}
diff --git a/usb-redir.c b/usb-redir.c
index c74b1560b..fb91c926a 100644
--- a/usb-redir.c
+++ b/usb-redir.c
@@ -225,6 +225,10 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
{
USBRedirDevice *dev = priv;
+ if (!dev->cs->opened) {
+ return 0;
+ }
+
return qemu_chr_fe_write(dev->cs, data, count);
}
@@ -814,6 +818,8 @@ static int usbredir_initfn(USBDevice *udev)
/* We'll do the attach once we receive the speed from the usb-host */
udev->auto_attach = 0;
+ /* Let the backend know we are ready */
+ qemu_chr_fe_open(dev->cs);
qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event, dev);
@@ -837,6 +843,7 @@ static void usbredir_handle_destroy(USBDevice *udev)
{
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+ qemu_chr_fe_close(dev->cs);
qemu_chr_delete(dev->cs);
/* Note must be done after qemu_chr_close, as that causes a close event */
qemu_bh_delete(dev->open_close_bh);
@@ -878,6 +885,11 @@ static void usbredir_device_connect(void *priv,
{
USBRedirDevice *dev = priv;
+ if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+ ERROR("Received device connect while already connected\n");
+ return;
+ }
+
switch (device_connect->speed) {
case usb_redir_speed_low:
DPRINTF("attaching low speed device\n");
@@ -906,19 +918,26 @@ static void usbredir_device_connect(void *priv,
static void usbredir_device_disconnect(void *priv)
{
USBRedirDevice *dev = priv;
+ int i;
/* Stop any pending attaches */
qemu_del_timer(dev->attach_timer);
if (dev->dev.attached) {
usb_device_detach(&dev->dev);
- usbredir_cleanup_device_queues(dev);
/*
* Delay next usb device attach to give the guest a chance to see
* see the detach / attach in case of quick close / open succession
*/
dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
}
+
+ /* Reset state so that the next dev connected starts with a clean slate */
+ usbredir_cleanup_device_queues(dev);
+ memset(dev->endpoint, 0, sizeof(dev->endpoint));
+ for (i = 0; i < MAX_ENDPOINTS; i++) {
+ QTAILQ_INIT(&dev->endpoint[i].bufpq);
+ }
}
static void usbredir_interface_info(void *priv,
@@ -1010,6 +1029,10 @@ static void usbredir_iso_stream_status(void *priv, uint32_t id,
DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
ep, id);
+ if (!dev->dev.attached) {
+ return;
+ }
+
dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
if (iso_stream_status->status == usb_redir_stall) {
DPRINTF("iso stream stopped by peer ep %02X\n", ep);
@@ -1027,6 +1050,10 @@ static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
DPRINTF("interrupt recv status %d ep %02X id %u\n",
interrupt_receiving_status->status, ep, id);
+ if (!dev->dev.attached) {
+ return;
+ }
+
dev->endpoint[EP2I(ep)].interrupt_error =
interrupt_receiving_status->status;
if (interrupt_receiving_status->status == usb_redir_stall) {
diff --git a/vl.c b/vl.c
index 6a01e7455..fdefa8671 100644
--- a/vl.c
+++ b/vl.c
@@ -954,8 +954,8 @@ static void numa_add(const char *optarg)
node_mem[nodenr] = 0;
} else {
int64_t sval;
- sval = strtosz(option, NULL);
- if (sval < 0) {
+ sval = strtosz(option, &endptr);
+ if (sval < 0 || *endptr) {
fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg);
exit(1);
}
@@ -2547,9 +2547,10 @@ int main(int argc, char **argv, char **envp)
break;
case QEMU_OPTION_m: {
int64_t value;
+ char *end;
- value = strtosz(optarg, NULL);
- if (value < 0) {
+ value = strtosz(optarg, &end);
+ if (value < 0 || *end) {
fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
exit(1);
}