aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/sheepdog.c70
-rwxr-xr-xconfigure29
-rw-r--r--hw/e1000.c12
-rw-r--r--hw/pc_piix.c8
-rw-r--r--hw/qxl-render.c4
-rw-r--r--hw/qxl.c57
-rw-r--r--hw/qxl.h5
-rw-r--r--hw/rtl8139.c24
-rw-r--r--hw/usb/hcd-uhci.c10
-rw-r--r--hw/usb/redirect.c24
-rw-r--r--hw/vfio_pci.c498
-rw-r--r--hw/vfio_pci_int.h114
-rw-r--r--hw/virtio-net.c5
-rw-r--r--net.c11
-rw-r--r--net/clients.h (renamed from net/socket.h)28
-rw-r--r--net/dump.c2
-rw-r--r--net/dump.h33
-rw-r--r--net/hub.c1
-rw-r--r--net/hub.h2
-rw-r--r--net/slirp.c3
-rw-r--r--net/slirp.h3
-rw-r--r--net/socket.c3
-rw-r--r--net/tap-win32.c2
-rw-r--r--net/tap.c3
-rw-r--r--net/tap.h6
-rw-r--r--net/vde.c3
-rw-r--r--net/vde.h37
-rw-r--r--qemu-ga.c6
-rw-r--r--ui/spice-core.c51
-rw-r--r--ui/spice-display.c38
-rw-r--r--ui/spice-display.h5
-rw-r--r--ui/vnc.c4
32 files changed, 479 insertions, 622 deletions
diff --git a/block/sheepdog.c b/block/sheepdog.c
index f35ff5bbe1..93061744d6 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -201,12 +201,12 @@ static inline uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
return hval;
}
-static inline int is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
+static inline bool is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
{
return inode->vdi_id == inode->data_vdi_id[idx];
}
-static inline int is_data_obj(uint64_t oid)
+static inline bool is_data_obj(uint64_t oid)
{
return !(VDI_BIT & oid);
}
@@ -231,7 +231,7 @@ static inline uint64_t vid_to_data_oid(uint32_t vid, uint32_t idx)
return ((uint64_t)vid << VDI_SPACE_SHIFT) | idx;
}
-static inline int is_snapshot(struct SheepdogInode *inode)
+static inline bool is_snapshot(struct SheepdogInode *inode)
{
return !!inode->snap_ctime;
}
@@ -281,7 +281,7 @@ struct SheepdogAIOCB {
Coroutine *coroutine;
void (*aio_done_func)(SheepdogAIOCB *);
- int canceled;
+ bool canceled;
int nr_pending;
};
@@ -292,8 +292,8 @@ typedef struct BDRVSheepdogState {
uint32_t max_dirty_data_idx;
char name[SD_MAX_VDI_LEN];
- int is_snapshot;
- uint8_t cache_enabled;
+ bool is_snapshot;
+ bool cache_enabled;
char *addr;
char *port;
@@ -417,7 +417,7 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
*/
acb->ret = -EIO;
qemu_coroutine_enter(acb->coroutine, NULL);
- acb->canceled = 1;
+ acb->canceled = true;
}
static AIOPool sd_aio_pool = {
@@ -439,7 +439,7 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
acb->nb_sectors = nb_sectors;
acb->aio_done_func = NULL;
- acb->canceled = 0;
+ acb->canceled = false;
acb->coroutine = qemu_coroutine_self();
acb->ret = 0;
acb->nr_pending = 0;
@@ -613,7 +613,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
}
static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
- struct iovec *iov, int niov, int create,
+ struct iovec *iov, int niov, bool create,
enum AIOCBState aiocb_type);
@@ -646,7 +646,7 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid)
QLIST_REMOVE(aio_req, aio_siblings);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
ret = add_aio_request(s, aio_req, acb->qiov->iov,
- acb->qiov->niov, 0, acb->aiocb_type);
+ acb->qiov->niov, false, acb->aiocb_type);
if (ret < 0) {
error_report("add_aio_request is failed");
free_aio_req(s, aio_req);
@@ -943,7 +943,7 @@ out:
}
static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
- struct iovec *iov, int niov, int create,
+ struct iovec *iov, int niov, bool create,
enum AIOCBState aiocb_type)
{
int nr_copies = s->inode.nr_copies;
@@ -1022,7 +1022,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
unsigned int datalen, uint64_t offset,
- int write, int create, uint8_t cache)
+ bool write, bool create, bool cache)
{
SheepdogObjReq hdr;
SheepdogObjRsp *rsp = (SheepdogObjRsp *)&hdr;
@@ -1071,18 +1071,18 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
}
static int read_object(int fd, char *buf, uint64_t oid, int copies,
- unsigned int datalen, uint64_t offset, uint8_t cache)
+ unsigned int datalen, uint64_t offset, bool cache)
{
- return read_write_object(fd, buf, oid, copies, datalen, offset, 0, 0,
- cache);
+ return read_write_object(fd, buf, oid, copies, datalen, offset, false,
+ false, cache);
}
static int write_object(int fd, char *buf, uint64_t oid, int copies,
- unsigned int datalen, uint64_t offset, int create,
- uint8_t cache)
+ unsigned int datalen, uint64_t offset, bool create,
+ bool cache)
{
- return read_write_object(fd, buf, oid, copies, datalen, offset, 1, create,
- cache);
+ return read_write_object(fd, buf, oid, copies, datalen, offset, true,
+ create, cache);
}
static int sd_open(BlockDriverState *bs, const char *filename, int flags)
@@ -1117,7 +1117,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
goto out;
}
- s->cache_enabled = 1;
+ s->cache_enabled = true;
s->flush_fd = connect_to_sdog(s->addr, s->port);
if (s->flush_fd < 0) {
error_report("failed to connect");
@@ -1127,7 +1127,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
if (snapid || tag[0] != '\0') {
dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
- s->is_snapshot = 1;
+ s->is_snapshot = true;
}
fd = connect_to_sdog(s->addr, s->port);
@@ -1270,7 +1270,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
BDRVSheepdogState *s;
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
uint32_t snapid;
- int prealloc = 0;
+ bool prealloc = false;
const char *vdiname;
s = g_malloc0(sizeof(BDRVSheepdogState));
@@ -1292,9 +1292,9 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
backing_file = options->value.s;
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
if (!options->value.s || !strcmp(options->value.s, "off")) {
- prealloc = 0;
+ prealloc = false;
} else if (!strcmp(options->value.s, "full")) {
- prealloc = 1;
+ prealloc = true;
} else {
error_report("Invalid preallocation mode: '%s'",
options->value.s);
@@ -1422,7 +1422,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
s->inode.vdi_size = offset;
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
- s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
+ s->inode.nr_copies, datalen, 0, false, s->cache_enabled);
close(fd);
if (ret < 0) {
@@ -1461,7 +1461,7 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
data_len, offset, 0, 0, offset);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
- ret = add_aio_request(s, aio_req, &iov, 1, 0, AIOCB_WRITE_UDATA);
+ ret = add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
if (ret) {
free_aio_req(s, aio_req);
acb->ret = -EIO;
@@ -1515,7 +1515,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
memcpy(&s->inode, buf, sizeof(s->inode));
- s->is_snapshot = 0;
+ s->is_snapshot = false;
ret = 0;
dprintf("%" PRIx32 " was newly created.\n", s->inode.vdi_id);
@@ -1570,7 +1570,7 @@ static int coroutine_fn sd_co_rw_vector(void *p)
while (done != total) {
uint8_t flags = 0;
uint64_t old_oid = 0;
- int create = 0;
+ bool create = false;
oid = vid_to_data_oid(inode->data_vdi_id[idx], idx);
@@ -1585,10 +1585,10 @@ static int coroutine_fn sd_co_rw_vector(void *p)
break;
case AIOCB_WRITE_UDATA:
if (!inode->data_vdi_id[idx]) {
- create = 1;
+ create = true;
} else if (!is_data_obj_writable(inode, idx)) {
/* Copy-On-Write */
- create = 1;
+ create = true;
old_oid = oid;
flags = SD_FLAG_CMD_COW;
}
@@ -1722,7 +1722,7 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
if (rsp->result == SD_RES_INVALID_PARMS) {
dprintf("disable write cache since the server doesn't support it\n");
- s->cache_enabled = 0;
+ s->cache_enabled = false;
closesocket(s->flush_fd);
return 0;
}
@@ -1773,7 +1773,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
}
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
- s->inode.nr_copies, datalen, 0, 0, s->cache_enabled);
+ s->inode.nr_copies, datalen, 0, false, s->cache_enabled);
if (ret < 0) {
error_report("failed to write snapshot's inode.");
goto cleanup;
@@ -1860,7 +1860,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
goto out;
}
- s->is_snapshot = 1;
+ s->is_snapshot = true;
g_free(buf);
g_free(old_s);
@@ -1978,8 +1978,8 @@ out:
static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
int64_t pos, int size, int load)
{
- int fd, create;
- int ret = 0, remaining = size;
+ bool create;
+ int fd, ret = 0, remaining = size;
unsigned int data_len;
uint64_t vmstate_oid;
uint32_t vdi_index;
diff --git a/configure b/configure
index c4a78376b6..353d7889f7 100755
--- a/configure
+++ b/configure
@@ -185,6 +185,7 @@ libdir="\${prefix}/lib"
libexecdir="\${prefix}/libexec"
includedir="\${prefix}/include"
sysconfdir="\${prefix}/etc"
+local_statedir="\${prefix}/var"
confsuffix="/qemu"
slirp="yes"
fmod_lib=""
@@ -554,6 +555,7 @@ EOF
qemu_docdir="\${prefix}"
bindir="\${prefix}"
sysconfdir="\${prefix}"
+ local_statedir="\${prefix}"
confsuffix=""
libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga"
fi
@@ -630,7 +632,9 @@ for opt do
;;
--sysconfdir=*) sysconfdir="$optarg"
;;
- --sbindir=*|--sharedstatedir=*|--localstatedir=*|\
+ --localstatedir=*) local_statedir="$optarg"
+ ;;
+ --sbindir=*|--sharedstatedir=*|\
--oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\
--htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
# These switches are silently ignored, for compatibility with
@@ -1028,6 +1032,7 @@ echo " --datadir=PATH install firmware in PATH$confsuffix"
echo " --docdir=PATH install documentation in PATH$confsuffix"
echo " --bindir=PATH install binaries in PATH"
echo " --sysconfdir=PATH install config in PATH$confsuffix"
+echo " --localstatedir=PATH install local state in PATH"
echo " --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]"
echo " --enable-debug-tcg enable TCG debugging"
echo " --disable-debug-tcg disable TCG debugging (default)"
@@ -2716,20 +2721,14 @@ int main(void) { spice_server_new(); return 0; }
EOF
spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
- if $pkg_config --atleast-version=0.8.2 spice-server >/dev/null 2>&1 && \
- $pkg_config --atleast-version=0.8.1 spice-protocol > /dev/null 2>&1 && \
+ if $pkg_config --atleast-version=0.12.0 spice-server >/dev/null 2>&1 && \
+ $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1 && \
compile_prog "$spice_cflags" "$spice_libs" ; then
spice="yes"
libs_softmmu="$libs_softmmu $spice_libs"
QEMU_CFLAGS="$QEMU_CFLAGS $spice_cflags"
spice_protocol_version=$($pkg_config --modversion spice-protocol)
spice_server_version=$($pkg_config --modversion spice-server)
- if $pkg_config --atleast-version=0.12.0 spice-protocol >/dev/null 2>&1; then
- spice_qxl_io_monitors_config_async="yes"
- fi
- if $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1; then
- spice_qxl_client_monitors_config="yes"
- fi
else
if test "$spice" = "yes" ; then
feature_not_found "spice"
@@ -3117,6 +3116,7 @@ echo "library directory `eval echo $libdir`"
echo "libexec directory `eval echo $libexecdir`"
echo "include directory `eval echo $includedir`"
echo "config directory `eval echo $sysconfdir`"
+echo "local state directory `eval echo $local_statedir`"
if test "$mingw32" = "no" ; then
echo "Manual directory `eval echo $mandir`"
echo "ELF interp prefix $interp_prefix"
@@ -3226,6 +3226,7 @@ echo "sysconfdir=$sysconfdir" >> $config_host_mak
echo "qemu_confdir=$qemu_confdir" >> $config_host_mak
echo "qemu_datadir=$qemu_datadir" >> $config_host_mak
echo "qemu_docdir=$qemu_docdir" >> $config_host_mak
+echo "qemu_localstatedir=$local_statedir" >> $config_host_mak
echo "CONFIG_QEMU_HELPERDIR=\"$libexecdir\"" >> $config_host_mak
echo "ARCH=$ARCH" >> $config_host_mak
@@ -3474,14 +3475,6 @@ if test "$spice" = "yes" ; then
echo "CONFIG_SPICE=y" >> $config_host_mak
fi
-if test "$spice_qxl_io_monitors_config_async" = "yes" ; then
- echo "CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC=y" >> $config_host_mak
-fi
-
-if test "$spice_qxl_client_monitors_config" = "yes" ; then
- echo "CONFIG_QXL_CLIENT_MONITORS_CONFIG=y" >> $config_host_mak
-fi
-
if test "$smartcard" = "yes" ; then
echo "CONFIG_SMARTCARD=y" >> $config_host_mak
fi
@@ -3733,7 +3726,6 @@ case "$target_arch2" in
;;
x86_64)
TARGET_BASE_ARCH=i386
- target_phys_bits=64
target_long_alignment=8
;;
alpha)
@@ -3836,7 +3828,6 @@ case "$target_arch2" in
target_long_alignment=8
;;
unicore32)
- target_phys_bits=32
;;
xtensa|xtensaeb)
TARGET_ARCH=xtensa
diff --git a/hw/e1000.c b/hw/e1000.c
index ec3a7c4ecc..63fee10794 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1079,11 +1079,23 @@ static bool is_version_1(void *opaque, int version_id)
return version_id == 1;
}
+static int e1000_post_load(void *opaque, int version_id)
+{
+ E1000State *s = opaque;
+
+ /* nc.link_down can't be migrated, so infer link_down according
+ * to link status bit in mac_reg[STATUS] */
+ s->nic->nc.link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;
+
+ return 0;
+}
+
static const VMStateDescription vmstate_e1000 = {
.name = "e1000",
.version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
+ .post_load = e1000_post_load,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, E1000State),
VMSTATE_UNUSED_TEST(is_version_1, 4), /* was instance id */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index fd5898fba6..82364ab0d5 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -371,6 +371,14 @@ static QEMUMachine pc_machine_v1_3 = {
.driver = "ivshmem",\
.property = "use64",\
.value = "0",\
+ },{\
+ .driver = "qxl",\
+ .property = "revision",\
+ .value = stringify(3),\
+ },{\
+ .driver = "qxl-vga",\
+ .property = "revision",\
+ .value = stringify(3),\
}
static QEMUMachine pc_machine_v1_2 = {
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index e2e3fe2d37..b66c168ef6 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -99,7 +99,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
{
VGACommonState *vga = &qxl->vga;
int i;
- DisplaySurface *surface = vga->ds->surface;
if (qxl->guest_primary.resized) {
qxl->guest_primary.resized = 0;
@@ -112,9 +111,6 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
qxl->guest_primary.qxl_stride,
qxl->guest_primary.bytes_pp,
qxl->guest_primary.bits_pp);
- }
- if (surface->width != qxl->guest_primary.surface.width ||
- surface->height != qxl->guest_primary.surface.height) {
if (qxl->guest_primary.qxl_stride > 0) {
qemu_free_displaysurface(vga->ds);
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
diff --git a/hw/qxl.c b/hw/qxl.c
index 33169f348a..1d16863c5e 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -29,11 +29,6 @@
#include "qxl.h"
-#ifndef CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC
-/* spice-protocol is too old, add missing definitions */
-#define QXL_IO_MONITORS_CONFIG_ASYNC (QXL_IO_FLUSH_RELEASE + 1)
-#endif
-
/*
* NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
* such can be changed by the guest, so to avoid a guest trigerrable
@@ -262,9 +257,6 @@ static void qxl_spice_destroy_surfaces(PCIQXLDevice *qxl, qxl_async_io async)
static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
{
trace_qxl_spice_monitors_config(qxl->id);
-/* 0x000b01 == 0.11.1 */
-#if SPICE_SERVER_VERSION >= 0x000b01 && \
- defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC)
if (replay) {
/*
* don't use QXL_COOKIE_TYPE_IO:
@@ -286,10 +278,6 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
(uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_IO,
QXL_IO_MONITORS_CONFIG_ASYNC));
}
-#else
- fprintf(stderr, "qxl: too old spice-protocol/spice-server for "
- "QXL_IO_MONITORS_CONFIG_ASYNC\n");
-#endif
}
void qxl_spice_reset_image_cache(PCIQXLDevice *qxl)
@@ -948,8 +936,6 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token)
}
}
-#if SPICE_SERVER_VERSION >= 0x000b04
-
/* called from spice server thread context only */
static void interface_set_client_capabilities(QXLInstance *sin,
uint8_t client_present,
@@ -971,11 +957,6 @@ static void interface_set_client_capabilities(QXLInstance *sin,
qxl_send_events(qxl, QXL_INTERRUPT_CLIENT);
}
-#endif
-
-#if defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG) \
- && SPICE_SERVER_VERSION >= 0x000b05
-
static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
{
/*
@@ -1044,7 +1025,6 @@ static int interface_client_monitors_config(QXLInstance *sin,
qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);
return 1;
}
-#endif
static const QXLInterface qxl_interface = {
.base.type = SPICE_INTERFACE_QXL,
@@ -1067,13 +1047,8 @@ static const QXLInterface qxl_interface = {
.flush_resources = interface_flush_resources,
.async_complete = interface_async_complete,
.update_area_complete = interface_update_area_complete,
-#if SPICE_SERVER_VERSION >= 0x000b04
.set_client_capabilities = interface_set_client_capabilities,
-#endif
-#if SPICE_SERVER_VERSION >= 0x000b05 && \
- defined(CONFIG_QXL_CLIENT_MONITORS_CONFIG)
.client_monitors_config = interface_client_monitors_config,
-#endif
};
static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -1461,12 +1436,12 @@ static void ioport_write(void *opaque, target_phys_addr_t addr,
qxl_async_io async = QXL_SYNC;
uint32_t orig_io_port = io_port;
- if (d->guest_bug && !io_port == QXL_IO_RESET) {
+ if (d->guest_bug && io_port != QXL_IO_RESET) {
return;
}
if (d->revision <= QXL_REVISION_STABLE_V10 &&
- io_port >= QXL_IO_FLUSH_SURFACES_ASYNC) {
+ io_port > QXL_IO_FLUSH_RELEASE) {
qxl_set_guest_bug(d, "unsupported io %d for revision %d\n",
io_port, d->revision);
return;
@@ -1547,20 +1522,13 @@ async_common:
if (d->ram->update_surface > d->ssd.num_surfaces) {
qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: invalid surface id %d\n",
d->ram->update_surface);
- return;
+ break;
}
- if (update.left >= update.right || update.top >= update.bottom) {
+ if (update.left >= update.right || update.top >= update.bottom ||
+ update.left < 0 || update.top < 0) {
qxl_set_guest_bug(d,
"QXL_IO_UPDATE_AREA: invalid area (%ux%u)x(%ux%u)\n",
update.left, update.top, update.right, update.bottom);
- return;
- }
-
- if (update.left < 0 || update.top < 0 || update.left >= update.right ||
- update.top >= update.bottom) {
- qxl_set_guest_bug(d, "QXL_IO_UPDATE_AREA: "
- "invalid area(%d,%d,%d,%d)\n", update.left,
- update.right, update.top, update.bottom);
break;
}
if (async == QXL_ASYNC) {
@@ -1811,7 +1779,7 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
{
- intptr_t vram_start;
+ uintptr_t vram_start;
int i;
if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
@@ -1822,7 +1790,7 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
qxl->shadow_rom.surface0_area_size);
- vram_start = (intptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
+ vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
/* dirty the off-screen surfaces */
for (i = 0; i < qxl->ssd.num_surfaces; i++) {
@@ -1854,7 +1822,6 @@ static void qxl_vm_change_state_handler(void *opaque, int running,
RunState state)
{
PCIQXLDevice *qxl = opaque;
- qemu_spice_vm_change_state_handler(&qxl->ssd, running, state);
if (running) {
/*
@@ -1971,14 +1938,10 @@ static int qxl_init_common(PCIQXLDevice *qxl)
pci_device_rev = QXL_REVISION_STABLE_V10;
io_size = 32; /* PCI region size must be pow2 */
break;
-/* 0x000b01 == 0.11.1 */
-#if SPICE_SERVER_VERSION >= 0x000b01 && \
- defined(CONFIG_QXL_IO_MONITORS_CONFIG_ASYNC)
case 4: /* qxl-4 */
pci_device_rev = QXL_REVISION_STABLE_V12;
io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1);
break;
-#endif
default:
error_report("Invalid revision %d for qxl device (max %d)",
qxl->revision, QXL_DEFAULT_REVISION);
@@ -2044,7 +2007,11 @@ static int qxl_init_common(PCIQXLDevice *qxl)
qxl->ssd.qxl.base.sif = &qxl_interface.base;
qxl->ssd.qxl.id = qxl->id;
- qemu_spice_add_interface(&qxl->ssd.qxl.base);
+ if (qemu_spice_add_interface(&qxl->ssd.qxl.base) != 0) {
+ error_report("qxl interface %d.%d not supported by spice-server\n",
+ SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR);
+ return -1;
+ }
qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl);
init_pipe_signaling(qxl);
diff --git a/hw/qxl.h b/hw/qxl.h
index 5553824bee..e583cfb750 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -129,12 +129,7 @@ typedef struct PCIQXLDevice {
} \
} while (0)
-#if 0
-/* spice-server 0.12 is still in development */
#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12
-#else
-#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V10
-#endif
/* qxl.c */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index b7c82ee027..6b28fea96a 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -167,7 +167,7 @@ enum IntrStatusBits {
PCIErr = 0x8000,
PCSTimeout = 0x4000,
RxFIFOOver = 0x40,
- RxUnderrun = 0x20,
+ RxUnderrun = 0x20, /* Packet Underrun / Link Change */
RxOverflow = 0x10,
TxErr = 0x08,
TxOK = 0x04,
@@ -3003,7 +3003,8 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
break;
case MediaStatus:
- ret = 0xd0;
+ /* The LinkDown bit of MediaStatus is inverse with link status */
+ ret = 0xd0 | (~s->BasicModeStatus & 0x04);
DPRINTF("MediaStatus read 0x%x\n", ret);
break;
@@ -3258,6 +3259,10 @@ static int rtl8139_post_load(void *opaque, int version_id)
s->cplus_enabled = s->CpCmd != 0;
}
+ /* nc.link_down can't be migrated, so infer link_down according
+ * to link status bit in BasicModeStatus */
+ s->nic->nc.link_down = (s->BasicModeStatus & 0x04) == 0;
+
return 0;
}
@@ -3449,12 +3454,27 @@ static void pci_rtl8139_uninit(PCIDevice *dev)
qemu_del_net_client(&s->nic->nc);
}
+static void rtl8139_set_link_status(NetClientState *nc)
+{
+ RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+ if (nc->link_down) {
+ s->BasicModeStatus &= ~0x04;
+ } else {
+ s->BasicModeStatus |= 0x04;
+ }
+
+ s->IntrStatus |= RxUnderrun;
+ rtl8139_update_irq(s);
+}
+
static NetClientInfo net_rtl8139_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = rtl8139_can_receive,
.receive = rtl8139_receive,
.cleanup = rtl8139_cleanup,
+ .link_status_changed = rtl8139_set_link_status,
};
static int pci_rtl8139_init(PCIDevice *dev)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index cdc8bc3fba..c2f08e3735 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -826,8 +826,16 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
USBEndpoint *ep;
/* Is active ? */
- if (!(td->ctrl & TD_CTRL_ACTIVE))
+ if (!(td->ctrl & TD_CTRL_ACTIVE)) {
+ /*
+ * ehci11d spec page 22: "Even if the Active bit in the TD is already
+ * cleared when the TD is fetched ... an IOC interrupt is generated"
+ */
+ if (td->ctrl & TD_CTRL_IOC) {
+ *int_mask |= 0x01;
+ }
return TD_RESULT_NEXT_QH;
+ }
async = uhci_async_find_td(s, addr, td);
if (async) {
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index b10241a139..2283565b0c 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -862,15 +862,11 @@ static void usbredir_chardev_close_bh(void *opaque)
}
}
-static void usbredir_chardev_open(USBRedirDevice *dev)
+static void usbredir_create_parser(USBRedirDevice *dev)
{
uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
int flags = 0;
- /* Make sure any pending closes are handled (no-op if none pending) */
- usbredir_chardev_close_bh(dev);
- qemu_bh_cancel(dev->chardev_close_bh);
-
DPRINTF("creating usbredirparser\n");
dev->parser = qemu_oom_check(usbredirparser_create());
@@ -982,7 +978,10 @@ static void usbredir_chardev_event(void *opaque, int event)
switch (event) {
case CHR_EVENT_OPENED:
DPRINTF("chardev open\n");
- usbredir_chardev_open(dev);
+ /* Make sure any pending closes are handled (no-op if none pending) */
+ usbredir_chardev_close_bh(dev);
+ qemu_bh_cancel(dev->chardev_close_bh);
+ usbredir_create_parser(dev);
break;
case CHR_EVENT_CLOSED:
DPRINTF("chardev close\n");
@@ -1615,12 +1614,17 @@ static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
}
/*
- * Our chardev should be open already at this point, otherwise
- * the usbredir channel will be broken (ie spice without seamless)
+ * If our chardev is not open already at this point the usbredir connection
+ * has been broken (non seamless migration, or restore from disk).
+ *
+ * In this case create a temporary parser to receive the migration data,
+ * and schedule the close_bh to report the device as disconnected to the
+ * guest and to destroy the parser again.
*/
if (dev->parser == NULL) {
- ERROR("get_parser called with closed chardev, failing migration\n");
- return -1;
+ WARNING("usb-redir connection broken during migration\n");
+ usbredir_create_parser(dev);
+ qemu_bh_schedule(dev->chardev_close_bh);
}
data = g_malloc(len);
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index a1eeced8fd..639371e7a2 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -33,9 +33,11 @@
#include "memory.h"
#include "msi.h"
#include "msix.h"
+#include "pci.h"
+#include "qemu-common.h"
#include "qemu-error.h"
+#include "qemu-queue.h"
#include "range.h"
-#include "vfio_pci_int.h"
/* #define DEBUG_VFIO */
#ifdef DEBUG_VFIO
@@ -46,6 +48,99 @@
do { } while (0)
#endif
+typedef struct VFIOBAR {
+ off_t fd_offset; /* offset of BAR within device fd */
+ int fd; /* device fd, allows us to pass VFIOBAR as opaque data */
+ MemoryRegion mem; /* slow, read/write access */
+ MemoryRegion mmap_mem; /* direct mapped access */
+ void *mmap;
+ size_t size;
+ uint32_t flags; /* VFIO region flags (rd/wr/mmap) */
+ uint8_t nr; /* cache the BAR number for debug */
+} VFIOBAR;
+
+typedef struct VFIOINTx {
+ bool pending; /* interrupt pending */
+ bool kvm_accel; /* set when QEMU bypass through KVM enabled */
+ uint8_t pin; /* which pin to pull for qemu_set_irq */
+ EventNotifier interrupt; /* eventfd triggered on interrupt */
+ EventNotifier unmask; /* eventfd for unmask on QEMU bypass */
+ PCIINTxRoute route; /* routing info for QEMU bypass */
+ uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */
+ QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */
+} VFIOINTx;
+
+struct VFIODevice;
+
+typedef struct VFIOMSIVector {
+ EventNotifier interrupt; /* eventfd triggered on interrupt */
+ struct VFIODevice *vdev; /* back pointer to device */
+ int virq; /* KVM irqchip route for QEMU bypass */
+ bool use;
+} VFIOMSIVector;
+
+enum {
+ VFIO_INT_NONE = 0,
+ VFIO_INT_INTx = 1,
+ VFIO_INT_MSI = 2,
+ VFIO_INT_MSIX = 3,
+};
+
+struct VFIOGroup;
+
+typedef struct VFIOContainer {
+ int fd; /* /dev/vfio/vfio, empowered by the attached groups */
+ struct {
+ /* enable abstraction to support various iommu backends */
+ union {
+ MemoryListener listener; /* Used by type1 iommu */
+ };
+ void (*release)(struct VFIOContainer *);
+ } iommu_data;
+ QLIST_HEAD(, VFIOGroup) group_list;
+ QLIST_ENTRY(VFIOContainer) next;
+} VFIOContainer;
+
+/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */
+typedef struct VFIOMSIXInfo {
+ uint8_t table_bar;
+ uint8_t pba_bar;
+ uint16_t entries;
+ uint32_t table_offset;
+ uint32_t pba_offset;
+ MemoryRegion mmap_mem;
+ void *mmap;
+} VFIOMSIXInfo;
+
+typedef struct VFIODevice {
+ PCIDevice pdev;
+ int fd;
+ VFIOINTx intx;
+ unsigned int config_size;
+ off_t config_offset; /* Offset of config space region within device fd */
+ unsigned int rom_size;
+ off_t rom_offset; /* Offset of ROM region within device fd */
+ int msi_cap_size;
+ VFIOMSIVector *msi_vectors;
+ VFIOMSIXInfo *msix;
+ int nr_vectors; /* Number of MSI/MSIX vectors currently in use */
+ int interrupt; /* Current interrupt type */
+ VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
+ PCIHostDeviceAddress host;
+ QLIST_ENTRY(VFIODevice) next;
+ struct VFIOGroup *group;
+ bool reset_works;
+} VFIODevice;
+
+typedef struct VFIOGroup {
+ int fd;
+ int groupid;
+ VFIOContainer *container;
+ QLIST_HEAD(, VFIODevice) device_list;
+ QLIST_ENTRY(VFIOGroup) next;
+ QLIST_ENTRY(VFIOGroup) container_next;
+} VFIOGroup;
+
#define MSIX_CAP_LENGTH 12
static QLIST_HEAD(, VFIOContainer)
@@ -72,8 +167,6 @@ static void vfio_disable_irqindex(VFIODevice *vdev, int index)
};
ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
-
- vdev->interrupt = VFIO_INT_NONE;
}
/*
@@ -92,6 +185,34 @@ static void vfio_unmask_intx(VFIODevice *vdev)
ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
}
+/*
+ * Disabling BAR mmaping can be slow, but toggling it around INTx can
+ * also be a huge overhead. We try to get the best of both worlds by
+ * waiting until an interrupt to disable mmaps (subsequent transitions
+ * to the same state are effectively no overhead). If the interrupt has
+ * been serviced and the time gap is long enough, we re-enable mmaps for
+ * performance. This works well for things like graphics cards, which
+ * may not use their interrupt at all and are penalized to an unusable
+ * level by read/write BAR traps. Other devices, like NICs, have more
+ * regular interrupts and see much better latency by staying in non-mmap
+ * mode. We therefore set the default mmap_timeout such that a ping
+ * is just enough to keep the mmap disabled. Users can experiment with
+ * other options with the x-intx-mmap-timeout-ms parameter (a value of
+ * zero disables the timer).
+ */
+static void vfio_intx_mmap_enable(void *opaque)
+{
+ VFIODevice *vdev = opaque;
+
+ if (vdev->intx.pending) {
+ qemu_mod_timer(vdev->intx.mmap_timer,
+ qemu_get_clock_ms(vm_clock) + vdev->intx.mmap_timeout);
+ return;
+ }
+
+ vfio_mmap_set_enabled(vdev, true);
+}
+
static void vfio_intx_interrupt(void *opaque)
{
VFIODevice *vdev = opaque;
@@ -106,6 +227,11 @@ static void vfio_intx_interrupt(void *opaque)
vdev->intx.pending = true;
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 1);
+ vfio_mmap_set_enabled(vdev, false);
+ if (vdev->intx.mmap_timeout) {
+ qemu_mod_timer(vdev->intx.mmap_timer,
+ qemu_get_clock_ms(vm_clock) + vdev->intx.mmap_timeout);
+ }
}
static void vfio_eoi(VFIODevice *vdev)
@@ -122,26 +248,14 @@ static void vfio_eoi(VFIODevice *vdev)
vfio_unmask_intx(vdev);
}
-typedef struct QEMU_PACKED VFIOIRQSetFD {
- struct vfio_irq_set irq_set;
- int32_t fd;
-} VFIOIRQSetFD;
-
static int vfio_enable_intx(VFIODevice *vdev)
{
- VFIOIRQSetFD irq_set_fd = {
- .irq_set = {
- .argsz = sizeof(irq_set_fd),
- .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
- .index = VFIO_PCI_INTX_IRQ_INDEX,
- .start = 0,
- .count = 1,
- },
- };
uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1);
- int ret;
+ int ret, argsz;
+ struct vfio_irq_set *irq_set;
+ int32_t *pfd;
- if (vdev->intx.disabled || !pin) {
+ if (!pin) {
return 0;
}
@@ -154,24 +268,28 @@ static int vfio_enable_intx(VFIODevice *vdev)
return ret;
}
- irq_set_fd.fd = event_notifier_get_fd(&vdev->intx.interrupt);
- qemu_set_fd_handler(irq_set_fd.fd, vfio_intx_interrupt, NULL, vdev);
+ argsz = sizeof(*irq_set) + sizeof(*pfd);
+
+ irq_set = g_malloc0(argsz);
+ irq_set->argsz = argsz;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;
+ irq_set->start = 0;
+ irq_set->count = 1;
+ pfd = (int32_t *)&irq_set->data;
+
+ *pfd = event_notifier_get_fd(&vdev->intx.interrupt);
+ qemu_set_fd_handler(*pfd, vfio_intx_interrupt, NULL, vdev);
- if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd)) {
+ ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ g_free(irq_set);
+ if (ret) {
error_report("vfio: Error: Failed to setup INTx fd: %m\n");
+ qemu_set_fd_handler(*pfd, NULL, NULL, vdev);
+ event_notifier_cleanup(&vdev->intx.interrupt);
return -errno;
}
- /*
- * Disable mmaps so we can trap on BAR accesses. We interpret any
- * access as a response to an interrupt and unmask the physical
- * device. The device will re-assert if the interrupt is still
- * pending. We'll likely retrigger on the host multiple times per
- * guest interrupt, but without EOI notification it's better than
- * nothing. Acceleration paths through KVM will avoid this.
- */
- vfio_mmap_set_enabled(vdev, false);
-
vdev->interrupt = VFIO_INT_INTx;
DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
@@ -184,6 +302,7 @@ static void vfio_disable_intx(VFIODevice *vdev)
{
int fd;
+ qemu_del_timer(vdev->intx.mmap_timer);
vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
@@ -254,10 +373,6 @@ static int vfio_enable_vectors(VFIODevice *vdev, bool msix)
g_free(irq_set);
- if (!ret) {
- vdev->interrupt = msix ? VFIO_INT_MSIX : VFIO_INT_MSI;
- }
-
return ret;
}
@@ -272,15 +387,6 @@ static int vfio_msix_vector_use(PCIDevice *pdev,
vdev->host.domain, vdev->host.bus, vdev->host.slot,
vdev->host.function, nr);
- if (vdev->interrupt != VFIO_INT_MSIX) {
- vfio_disable_interrupts(vdev);
- }
-
- if (!vdev->msi_vectors) {
- vdev->msi_vectors = g_malloc0(vdev->msix->entries *
- sizeof(VFIOMSIVector));
- }
-
vector = &vdev->msi_vectors[nr];
vector->vdev = vdev;
vector->use = true;
@@ -313,43 +419,35 @@ static int vfio_msix_vector_use(PCIDevice *pdev,
* increase them as needed.
*/
if (vdev->nr_vectors < nr + 1) {
- int i;
-
vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX);
vdev->nr_vectors = nr + 1;
ret = vfio_enable_vectors(vdev, true);
if (ret) {
error_report("vfio: failed to enable vectors, %d\n", ret);
}
-
- /* We don't know if we've missed interrupts in the interim... */
- for (i = 0; i < vdev->msix->entries; i++) {
- if (vdev->msi_vectors[i].use) {
- msix_notify(&vdev->pdev, i);
- }
- }
} else {
- VFIOIRQSetFD irq_set_fd = {
- .irq_set = {
- .argsz = sizeof(irq_set_fd),
- .flags = VFIO_IRQ_SET_DATA_EVENTFD |
- VFIO_IRQ_SET_ACTION_TRIGGER,
- .index = VFIO_PCI_MSIX_IRQ_INDEX,
- .start = nr,
- .count = 1,
- },
- .fd = event_notifier_get_fd(&vector->interrupt),
- };
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd);
+ int argsz;
+ struct vfio_irq_set *irq_set;
+ int32_t *pfd;
+
+ argsz = sizeof(*irq_set) + sizeof(*pfd);
+
+ irq_set = g_malloc0(argsz);
+ irq_set->argsz = argsz;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+ VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+ irq_set->start = nr;
+ irq_set->count = 1;
+ pfd = (int32_t *)&irq_set->data;
+
+ *pfd = event_notifier_get_fd(&vector->interrupt);
+
+ ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ g_free(irq_set);
if (ret) {
error_report("vfio: failed to modify vector, %d\n", ret);
}
-
- /*
- * If we were connected to the hardware PBA we could skip this,
- * until then, a spurious interrupt is better than starvation.
- */
- msix_notify(&vdev->pdev, nr);
}
return 0;
@@ -359,17 +457,9 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
{
VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev);
VFIOMSIVector *vector = &vdev->msi_vectors[nr];
- VFIOIRQSetFD irq_set_fd = {
- .irq_set = {
- .argsz = sizeof(irq_set_fd),
- .flags = VFIO_IRQ_SET_DATA_EVENTFD |
- VFIO_IRQ_SET_ACTION_TRIGGER,
- .index = VFIO_PCI_MSIX_IRQ_INDEX,
- .start = nr,
- .count = 1,
- },
- .fd = -1,
- };
+ int argsz;
+ struct vfio_irq_set *irq_set;
+ int32_t *pfd;
DPRINTF("%s(%04x:%02x:%02x.%x) vector %d released\n", __func__,
vdev->host.domain, vdev->host.bus, vdev->host.slot,
@@ -381,7 +471,23 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
* bouncing through userspace and let msix.c drop it? Not sure.
*/
msix_vector_unuse(pdev, nr);
- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set_fd);
+
+ argsz = sizeof(*irq_set) + sizeof(*pfd);
+
+ irq_set = g_malloc0(argsz);
+ irq_set->argsz = argsz;
+ irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+ VFIO_IRQ_SET_ACTION_TRIGGER;
+ irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
+ irq_set->start = nr;
+ irq_set->count = 1;
+ pfd = (int32_t *)&irq_set->data;
+
+ *pfd = -1;
+
+ ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+
+ g_free(irq_set);
if (vector->virq < 0) {
qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt),
@@ -419,18 +525,21 @@ static MSIMessage msi_get_msg(PCIDevice *pdev, unsigned int vector)
return msg;
}
-/* So should this */
-static void msi_set_qsize(PCIDevice *pdev, uint8_t size)
+static void vfio_enable_msix(VFIODevice *vdev)
{
- uint8_t *config = pdev->config + pdev->msi_cap;
- uint16_t flags;
-
- flags = pci_get_word(config + PCI_MSI_FLAGS);
- flags = le16_to_cpu(flags);
- flags &= ~PCI_MSI_FLAGS_QSIZE;
- flags |= (size & 0x7) << 4;
- flags = cpu_to_le16(flags);
- pci_set_word(config + PCI_MSI_FLAGS, flags);
+ vfio_disable_interrupts(vdev);
+
+ vdev->msi_vectors = g_malloc0(vdev->msix->entries * sizeof(VFIOMSIVector));
+
+ vdev->interrupt = VFIO_INT_MSIX;
+
+ if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use,
+ vfio_msix_vector_release)) {
+ error_report("vfio: msix_set_vector_notifiers failed\n");
+ }
+
+ DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
+ vdev->host.bus, vdev->host.slot, vdev->host.function);
}
static void vfio_enable_msi(VFIODevice *vdev)
@@ -503,19 +612,43 @@ retry:
return;
}
- msi_set_qsize(&vdev->pdev, vdev->nr_vectors);
+ vdev->interrupt = VFIO_INT_MSI;
DPRINTF("%s(%04x:%02x:%02x.%x) Enabled %d MSI vectors\n", __func__,
vdev->host.domain, vdev->host.bus, vdev->host.slot,
vdev->host.function, vdev->nr_vectors);
}
-static void vfio_disable_msi_x(VFIODevice *vdev, bool msix)
+static void vfio_disable_msi_common(VFIODevice *vdev)
+{
+ g_free(vdev->msi_vectors);
+ vdev->msi_vectors = NULL;
+ vdev->nr_vectors = 0;
+ vdev->interrupt = VFIO_INT_NONE;
+
+ vfio_enable_intx(vdev);
+}
+
+static void vfio_disable_msix(VFIODevice *vdev)
+{
+ msix_unset_vector_notifiers(&vdev->pdev);
+
+ if (vdev->nr_vectors) {
+ vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX);
+ }
+
+ vfio_disable_msi_common(vdev);
+
+ DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__,
+ vdev->host.domain, vdev->host.bus, vdev->host.slot,
+ vdev->host.function, msix ? "x" : "");
+}
+
+static void vfio_disable_msi(VFIODevice *vdev)
{
int i;
- vfio_disable_irqindex(vdev, msix ? VFIO_PCI_MSIX_IRQ_INDEX :
- VFIO_PCI_MSI_IRQ_INDEX);
+ vfio_disable_irqindex(vdev, VFIO_PCI_MSI_IRQ_INDEX);
for (i = 0; i < vdev->nr_vectors; i++) {
VFIOMSIVector *vector = &vdev->msi_vectors[i];
@@ -534,26 +667,13 @@ static void vfio_disable_msi_x(VFIODevice *vdev, bool msix)
NULL, NULL, NULL);
}
- if (msix) {
- msix_vector_unuse(&vdev->pdev, i);
- }
-
event_notifier_cleanup(&vector->interrupt);
}
- g_free(vdev->msi_vectors);
- vdev->msi_vectors = NULL;
- vdev->nr_vectors = 0;
-
- if (!msix) {
- msi_set_qsize(&vdev->pdev, 0); /* Actually still means 1 vector */
- }
-
- DPRINTF("%s(%04x:%02x:%02x.%x, msi%s)\n", __func__,
- vdev->host.domain, vdev->host.bus, vdev->host.slot,
- vdev->host.function, msix ? "x" : "");
+ vfio_disable_msi_common(vdev);
- vfio_enable_intx(vdev);
+ DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
+ vdev->host.bus, vdev->host.slot, vdev->host.function);
}
/*
@@ -601,7 +721,7 @@ static void vfio_bar_write(void *opaque, target_phys_addr_t addr,
* which access will service the interrupt, so we're potentially
* getting quite a few host interrupts per guest interrupt.
*/
- vfio_eoi(DO_UPCAST(VFIODevice, bars[bar->nr], bar));
+ vfio_eoi(container_of(bar, VFIODevice, bars[bar->nr]));
}
static uint64_t vfio_bar_read(void *opaque,
@@ -641,7 +761,7 @@ static uint64_t vfio_bar_read(void *opaque,
__func__, bar->nr, addr, size, data);
/* Same as write above */
- vfio_eoi(DO_UPCAST(VFIODevice, bars[bar->nr], bar));
+ vfio_eoi(container_of(bar, VFIODevice, bars[bar->nr]));
return data;
}
@@ -739,7 +859,7 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
if (!was_enabled && is_enabled) {
vfio_enable_msi(vdev);
} else if (was_enabled && !is_enabled) {
- vfio_disable_msi_x(vdev, false);
+ vfio_disable_msi(vdev);
}
}
@@ -752,9 +872,9 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
is_enabled = msix_enabled(pdev);
if (!was_enabled && is_enabled) {
- /* vfio_msix_vector_use handles this automatically */
+ vfio_enable_msix(vdev);
} else if (was_enabled && !is_enabled) {
- vfio_disable_msi_x(vdev, true);
+ vfio_disable_msix(vdev);
}
}
}
@@ -762,45 +882,52 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
/*
* DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86
*/
-static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova,
- ram_addr_t size, void *vaddr, bool readonly)
+static int vfio_dma_unmap(VFIOContainer *container,
+ target_phys_addr_t iova, ram_addr_t size)
{
- struct vfio_iommu_type1_dma_map map = {
- .argsz = sizeof(map),
- .flags = VFIO_DMA_MAP_FLAG_READ,
- .vaddr = (__u64)(intptr_t)vaddr,
+ struct vfio_iommu_type1_dma_unmap unmap = {
+ .argsz = sizeof(unmap),
+ .flags = 0,
.iova = iova,
.size = size,
};
- if (!readonly) {
- map.flags |= VFIO_DMA_MAP_FLAG_WRITE;
- }
-
- if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) {
- DPRINTF("VFIO_MAP_DMA: %d\n", -errno);
+ if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) {
+ DPRINTF("VFIO_UNMAP_DMA: %d\n", -errno);
return -errno;
}
return 0;
}
-static int vfio_dma_unmap(VFIOContainer *container,
- target_phys_addr_t iova, ram_addr_t size)
+static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova,
+ ram_addr_t size, void *vaddr, bool readonly)
{
- struct vfio_iommu_type1_dma_unmap unmap = {
- .argsz = sizeof(unmap),
- .flags = 0,
+ struct vfio_iommu_type1_dma_map map = {
+ .argsz = sizeof(map),
+ .flags = VFIO_DMA_MAP_FLAG_READ,
+ .vaddr = (__u64)(uintptr_t)vaddr,
.iova = iova,
.size = size,
};
- if (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) {
- DPRINTF("VFIO_UNMAP_DMA: %d\n", -errno);
- return -errno;
+ if (!readonly) {
+ map.flags |= VFIO_DMA_MAP_FLAG_WRITE;
}
- return 0;
+ /*
+ * Try the mapping, if it fails with EBUSY, unmap the region and try
+ * again. This shouldn't be necessary, but we sometimes see it in
+ * the the VGA ROM space.
+ */
+ if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0 ||
+ (errno == EBUSY && vfio_dma_unmap(container, iova, size) == 0 &&
+ ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0)) {
+ return 0;
+ }
+
+ DPRINTF("VFIO_MAP_DMA: %d\n", -errno);
+ return -errno;
}
static void vfio_listener_dummy1(MemoryListener *listener)
@@ -942,10 +1069,10 @@ static void vfio_disable_interrupts(VFIODevice *vdev)
vfio_disable_intx(vdev);
break;
case VFIO_INT_MSI:
- vfio_disable_msi_x(vdev, false);
+ vfio_disable_msi(vdev);
break;
case VFIO_INT_MSIX:
- vfio_disable_msi_x(vdev, true);
+ vfio_disable_msix(vdev);
break;
}
}
@@ -956,14 +1083,6 @@ static int vfio_setup_msi(VFIODevice *vdev, int pos)
bool msi_64bit, msi_maskbit;
int ret, entries;
- /*
- * TODO: don't peek into msi_supported, let msi_init fail and
- * check for ENOTSUP
- */
- if (!msi_supported) {
- return 0;
- }
-
if (pread(vdev->fd, &ctrl, sizeof(ctrl),
vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) {
return -errno;
@@ -979,6 +1098,9 @@ static int vfio_setup_msi(VFIODevice *vdev, int pos)
ret = msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit);
if (ret < 0) {
+ if (ret == -ENOTSUP) {
+ return 0;
+ }
error_report("vfio: msi_init failed\n");
return ret;
}
@@ -1045,33 +1167,19 @@ static int vfio_setup_msix(VFIODevice *vdev, int pos)
{
int ret;
- /*
- * TODO: don't peek into msi_supported, let msix_init fail and
- * check for ENOTSUP
- */
- if (!msi_supported) {
- return 0;
- }
-
ret = msix_init(&vdev->pdev, vdev->msix->entries,
&vdev->bars[vdev->msix->table_bar].mem,
vdev->msix->table_bar, vdev->msix->table_offset,
&vdev->bars[vdev->msix->pba_bar].mem,
vdev->msix->pba_bar, vdev->msix->pba_offset, pos);
if (ret < 0) {
+ if (ret == -ENOTSUP) {
+ return 0;
+ }
error_report("vfio: msix_init failed\n");
return ret;
}
- ret = msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use,
- vfio_msix_vector_release);
- if (ret) {
- error_report("vfio: msix_set_vector_notifiers failed %d\n", ret);
- msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem,
- &vdev->bars[vdev->msix->pba_bar].mem);
- return ret;
- }
-
return 0;
}
@@ -1080,12 +1188,6 @@ static void vfio_teardown_msi(VFIODevice *vdev)
msi_uninit(&vdev->pdev);
if (vdev->msix) {
- /* FIXME: Why can't unset just silently do nothing?? */
- if (vdev->pdev.msix_vector_use_notifier &&
- vdev->pdev.msix_vector_release_notifier) {
- msix_unset_vector_notifiers(&vdev->pdev);
- }
-
msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem,
&vdev->bars[vdev->msix->pba_bar].mem);
}
@@ -1766,17 +1868,8 @@ static int vfio_initfn(PCIDevice *pdev)
}
if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) {
- if (vdev->intx.intx && strcmp(vdev->intx.intx, "off")) {
- error_report("vfio: Unknown option x-intx=%s, "
- "valid options: \"off\".\n", vdev->intx.intx);
- ret = -EINVAL;
- goto out_teardown;
- }
-
- if (vdev->intx.intx && !strcmp(vdev->intx.intx, "off")) {
- vdev->intx.disabled = true;
- }
-
+ vdev->intx.mmap_timer = qemu_new_timer_ms(vm_clock,
+ vfio_intx_mmap_enable, vdev);
ret = vfio_enable_intx(vdev);
if (ret) {
goto out_teardown;
@@ -1802,6 +1895,9 @@ static void vfio_exitfn(PCIDevice *pdev)
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
vfio_disable_interrupts(vdev);
+ if (vdev->intx.mmap_timer) {
+ qemu_free_timer(vdev->intx.mmap_timer);
+ }
vfio_teardown_msi(vdev);
vfio_unmap_bars(vdev);
vfio_put_device(vdev);
@@ -1812,21 +1908,37 @@ static void vfio_pci_reset(DeviceState *dev)
{
PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev);
VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev);
+ uint16_t cmd;
- if (!vdev->reset_works) {
- return;
- }
+ DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain,
+ vdev->host.bus, vdev->host.slot, vdev->host.function);
+
+ vfio_disable_interrupts(vdev);
- if (ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
- error_report("vfio: Error unable to reset physical device "
- "(%04x:%02x:%02x.%x): %m\n", vdev->host.domain,
- vdev->host.bus, vdev->host.slot, vdev->host.function);
+ /*
+ * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master.
+ * Also put INTx Disable in known state.
+ */
+ cmd = vfio_pci_read_config(pdev, PCI_COMMAND, 2);
+ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+ PCI_COMMAND_INTX_DISABLE);
+ vfio_pci_write_config(pdev, PCI_COMMAND, cmd, 2);
+
+ if (vdev->reset_works) {
+ if (ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
+ error_report("vfio: Error unable to reset physical device "
+ "(%04x:%02x:%02x.%x): %m\n", vdev->host.domain,
+ vdev->host.bus, vdev->host.slot, vdev->host.function);
+ }
}
+
+ vfio_enable_intx(vdev);
}
static Property vfio_pci_dev_properties[] = {
DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host),
- DEFINE_PROP_STRING("x-intx", VFIODevice, intx.intx),
+ DEFINE_PROP_UINT32("x-intx-mmap-timeout-ms", VFIODevice,
+ intx.mmap_timeout, 1100),
/*
* TODO - support passed fds... is this necessary?
* DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
diff --git a/hw/vfio_pci_int.h b/hw/vfio_pci_int.h
deleted file mode 100644
index 3812d8d7f1..0000000000
--- a/hw/vfio_pci_int.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * vfio based device assignment support
- *
- * Copyright Red Hat, Inc. 2012
- *
- * Authors:
- * Alex Williamson <alex.williamson@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#ifndef HW_VFIO_PCI_INT_H
-#define HW_VFIO_PCI_INT_H
-
-#include "qemu-common.h"
-#include "qemu-queue.h"
-#include "pci.h"
-#include "event_notifier.h"
-
-typedef struct VFIOBAR {
- off_t fd_offset; /* offset of BAR within device fd */
- int fd; /* device fd, allows us to pass VFIOBAR as opaque data */
- MemoryRegion mem; /* slow, read/write access */
- MemoryRegion mmap_mem; /* direct mapped access */
- void *mmap;
- size_t size;
- uint32_t flags; /* VFIO region flags (rd/wr/mmap) */
- uint8_t nr; /* cache the BAR number for debug */
-} VFIOBAR;
-
-typedef struct VFIOINTx {
- bool pending; /* interrupt pending */
- bool kvm_accel; /* set when QEMU bypass through KVM enabled */
- uint8_t pin; /* which pin to pull for qemu_set_irq */
- EventNotifier interrupt; /* eventfd triggered on interrupt */
- EventNotifier unmask; /* eventfd for unmask on QEMU bypass */
- PCIINTxRoute route; /* routing info for QEMU bypass */
- bool disabled;
- char *intx;
-} VFIOINTx;
-
-struct VFIODevice;
-
-typedef struct VFIOMSIVector {
- EventNotifier interrupt; /* eventfd triggered on interrupt */
- struct VFIODevice *vdev; /* back pointer to device */
- int virq; /* KVM irqchip route for QEMU bypass */
- bool use;
-} VFIOMSIVector;
-
-enum {
- VFIO_INT_NONE = 0,
- VFIO_INT_INTx = 1,
- VFIO_INT_MSI = 2,
- VFIO_INT_MSIX = 3,
-};
-
-struct VFIOGroup;
-
-typedef struct VFIOContainer {
- int fd; /* /dev/vfio/vfio, empowered by the attached groups */
- struct {
- /* enable abstraction to support various iommu backends */
- union {
- MemoryListener listener; /* Used by type1 iommu */
- };
- void (*release)(struct VFIOContainer *);
- } iommu_data;
- QLIST_HEAD(, VFIOGroup) group_list;
- QLIST_ENTRY(VFIOContainer) next;
-} VFIOContainer;
-
-/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */
-typedef struct VFIOMSIXInfo {
- uint8_t table_bar;
- uint8_t pba_bar;
- uint16_t entries;
- uint32_t table_offset;
- uint32_t pba_offset;
- MemoryRegion mmap_mem;
- void *mmap;
-} VFIOMSIXInfo;
-
-typedef struct VFIODevice {
- PCIDevice pdev;
- int fd;
- VFIOINTx intx;
- unsigned int config_size;
- off_t config_offset; /* Offset of config space region within device fd */
- unsigned int rom_size;
- off_t rom_offset; /* Offset of ROM region within device fd */
- int msi_cap_size;
- VFIOMSIVector *msi_vectors;
- VFIOMSIXInfo *msix;
- int nr_vectors; /* Number of MSI/MSIX vectors currently in use */
- int interrupt; /* Current interrupt type */
- VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
- PCIHostDeviceAddress host;
- QLIST_ENTRY(VFIODevice) next;
- struct VFIOGroup *group;
- bool reset_works;
-} VFIODevice;
-
-typedef struct VFIOGroup {
- int fd;
- int groupid;
- VFIOContainer *container;
- QLIST_HEAD(, VFIODevice) device_list;
- QLIST_ENTRY(VFIOGroup) next;
- QLIST_ENTRY(VFIOGroup) container_next;
-} VFIOGroup;
-
-#endif /* HW_VFIO_PCI_INT_H */
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 247d7bef56..8342391d90 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -973,6 +973,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
}
}
n->mac_table.first_multi = i;
+
+ /* nc.link_down can't be migrated, so infer link_down according
+ * to link status bit in n->status */
+ n->nic->nc.link_down = (n->status & VIRTIO_NET_S_LINK_UP) == 0;
+
return 0;
}
diff --git a/net.c b/net.c
index a187a7b3db..ae4bc0d431 100644
--- a/net.c
+++ b/net.c
@@ -21,17 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "net.h"
-
#include "config-host.h"
-#include "net/tap.h"
-#include "net/socket.h"
-#include "net/dump.h"
-#include "net/slirp.h"
-#include "net/vde.h"
+#include "net.h"
+#include "net/clients.h"
#include "net/hub.h"
+#include "net/slirp.h"
#include "net/util.h"
+
#include "monitor.h"
#include "qemu-common.h"
#include "qemu_socket.h"
diff --git a/net/socket.h b/net/clients.h
index 3f8a092459..c58cc6087c 100644
--- a/net/socket.h
+++ b/net/clients.h
@@ -21,13 +21,35 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifndef QEMU_NET_SOCKET_H
-#define QEMU_NET_SOCKET_H
+#ifndef QEMU_NET_CLIENTS_H
+#define QEMU_NET_CLIENTS_H
#include "net.h"
#include "qapi-types.h"
+int net_init_dump(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+
+#ifdef CONFIG_SLIRP
+int net_init_slirp(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+#endif
+
+int net_init_hubport(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+
int net_init_socket(const NetClientOptions *opts, const char *name,
NetClientState *peer);
-#endif /* QEMU_NET_SOCKET_H */
+int net_init_tap(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+
+int net_init_bridge(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+
+#ifdef CONFIG_VDE
+int net_init_vde(const NetClientOptions *opts, const char *name,
+ NetClientState *peer);
+#endif
+
+#endif /* QEMU_NET_CLIENTS_H */
diff --git a/net/dump.c b/net/dump.c
index 004231d481..e0a5d74644 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
-#include "dump.h"
+#include "clients.h"
#include "qemu-common.h"
#include "qemu-error.h"
#include "qemu-log.h"
diff --git a/net/dump.h b/net/dump.h
deleted file mode 100644
index 33f152b460..0000000000
--- a/net/dump.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef QEMU_NET_DUMP_H
-#define QEMU_NET_DUMP_H
-
-#include "net.h"
-#include "qapi-types.h"
-
-int net_init_dump(const NetClientOptions *opts, const char *name,
- NetClientState *peer);
-
-#endif /* QEMU_NET_DUMP_H */
diff --git a/net/hub.c b/net/hub.c
index 650a8b4a40..be413012bb 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -14,6 +14,7 @@
#include "monitor.h"
#include "net.h"
+#include "clients.h"
#include "hub.h"
#include "iov.h"
diff --git a/net/hub.h b/net/hub.h
index 26a1ade1f9..4cbfdb128b 100644
--- a/net/hub.h
+++ b/net/hub.h
@@ -17,8 +17,6 @@
#include "qemu-common.h"
-int net_init_hubport(const NetClientOptions *opts, const char *name,
- NetClientState *peer);
NetClientState *net_hub_add_port(int hub_id, const char *name);
NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
void net_hub_info(Monitor *mon);
diff --git a/net/slirp.c b/net/slirp.c
index 8db66ea539..bf86a446c3 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -30,7 +30,8 @@
#include <sys/wait.h>
#endif
#include "net.h"
-#include "net/hub.h"
+#include "clients.h"
+#include "hub.h"
#include "monitor.h"
#include "qemu_socket.h"
#include "slirp/libslirp.h"
diff --git a/net/slirp.h b/net/slirp.h
index 5f685c4fb1..2ca09b65b7 100644
--- a/net/slirp.h
+++ b/net/slirp.h
@@ -31,9 +31,6 @@
#ifdef CONFIG_SLIRP
-int net_init_slirp(const NetClientOptions *opts, const char *name,
- NetClientState *peer);
-
void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict);
void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict);
diff --git a/net/socket.c b/net/socket.c
index f3d7878264..b75d567695 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -21,11 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "net/socket.h"
-
#include "config-host.h"
#include "net.h"
+#include "clients.h"
#include "monitor.h"
#include "qemu-char.h"
#include "qemu-common.h"
diff --git a/net/tap-win32.c b/net/tap-win32.c
index c0ea954ca1..f1801e22d2 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -26,7 +26,7 @@
* distribution); if not, see <http://www.gnu.org/licenses/>.
*/
-#include "net/tap.h"
+#include "tap.h"
#include "qemu-common.h"
#include "net.h"
diff --git a/net/tap.c b/net/tap.c
index a88ae8f61a..df89caaac6 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -23,7 +23,7 @@
* THE SOFTWARE.
*/
-#include "net/tap.h"
+#include "tap.h"
#include "config-host.h"
@@ -34,6 +34,7 @@
#include <net/if.h>
#include "net.h"
+#include "clients.h"
#include "monitor.h"
#include "sysemu.h"
#include "qemu-char.h"
diff --git a/net/tap.h b/net/tap.h
index 0fb018c4b7..d44d83ae73 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -32,9 +32,6 @@
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
-int net_init_tap(const NetClientOptions *opts, const char *name,
- NetClientState *peer);
-
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required);
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen);
@@ -58,7 +55,4 @@ int tap_get_fd(NetClientState *nc);
struct vhost_net;
struct vhost_net *tap_get_vhost_net(NetClientState *nc);
-int net_init_bridge(const NetClientOptions *opts, const char *name,
- NetClientState *peer);
-
#endif /* QEMU_NET_TAP_H */
diff --git a/net/vde.c b/net/vde.c
index b91a6c799b..275bda92c3 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -21,13 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "net/vde.h"
-
#include "config-host.h"
#include <libvdeplug.h>
#include "net.h"
+#include "clients.h"
#include "qemu-char.h"
#include "qemu-common.h"
#include "qemu-option.h"
diff --git a/net/vde.h b/net/vde.h
deleted file mode 100644
index 6ce6698937..0000000000
--- a/net/vde.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef QEMU_NET_VDE_H
-#define QEMU_NET_VDE_H
-
-#include "qemu-common.h"
-#include "qapi-types.h"
-
-#ifdef CONFIG_VDE
-
-int net_init_vde(const NetClientOptions *opts, const char *name,
- NetClientState *peer);
-
-#endif /* CONFIG_VDE */
-
-#endif /* QEMU_NET_VDE_H */
diff --git a/qemu-ga.c b/qemu-ga.c
index b7474708f0..9b59a52461 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -40,8 +40,8 @@
#else
#define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0"
#endif
-#define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
-#define QGA_STATEDIR_DEFAULT "/tmp"
+#define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run"
+#define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid"
#define QGA_SENTINEL_BYTE 0xFF
struct GAState {
@@ -255,7 +255,7 @@ static bool ga_open_pidfile(const char *pidfile)
g_critical("Failed to truncate pid file");
goto fail;
}
- sprintf(pidstr, "%d", getpid());
+ snprintf(pidstr, sizeof(pidstr), "%d\n", getpid());
if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
g_critical("Failed to write pid file");
goto fail;
diff --git a/ui/spice-core.c b/ui/spice-core.c
index ba0d0bdbc2..51473650c0 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -223,7 +223,6 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
client = qdict_new();
server = qdict_new();
-#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
add_addr_info(client, (struct sockaddr *)&info->paddr_ext,
info->plen_ext);
@@ -232,12 +231,7 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
} else {
error_report("spice: %s, extended address is expected",
__func__);
-#endif
- add_addr_info(client, &info->paddr, info->plen);
- add_addr_info(server, &info->laddr, info->llen);
-#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
}
-#endif
if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
qdict_put(server, "auth", qstring_from_str(auth));
@@ -276,7 +270,6 @@ static SpiceCoreInterface core_interface = {
.channel_event = channel_event,
};
-#ifdef SPICE_INTERFACE_MIGRATION
typedef struct SpiceMigration {
SpiceMigrateInstance sin;
struct {
@@ -313,7 +306,6 @@ static void migrate_end_complete_cb(SpiceMigrateInstance *sin)
monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL);
spice_migration_completed = true;
}
-#endif
/* config string parsing */
@@ -393,17 +385,13 @@ static SpiceChannelList *qmp_query_spice_channels(void)
chan = g_malloc0(sizeof(*chan));
chan->value = g_malloc0(sizeof(*chan->value));
-#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
if (item->info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
paddr = (struct sockaddr *)&item->info->paddr_ext;
plen = item->info->plen_ext;
} else {
-#endif
paddr = &item->info->paddr;
plen = item->info->plen;
-#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
}
-#endif
getnameinfo(paddr, plen,
host, sizeof(host), port, sizeof(port),
@@ -473,13 +461,10 @@ SpiceInfo *qmp_query_spice(Error **errp)
info->tls_port = tls_port;
}
-#if SPICE_SERVER_VERSION >= 0x000a03 /* 0.10.3 */
info->mouse_mode = spice_server_is_server_mouse(spice_server) ?
SPICE_QUERY_MOUSE_MODE_SERVER :
SPICE_QUERY_MOUSE_MODE_CLIENT;
-#else
- info->mouse_mode = SPICE_QUERY_MOUSE_MODE_UNKNOWN;
-#endif
+
/* for compatibility with the original command */
info->has_channels = true;
info->channels = qmp_query_spice_channels();
@@ -492,19 +477,11 @@ static void migration_state_notifier(Notifier *notifier, void *data)
MigrationState *s = data;
if (migration_is_active(s)) {
-#ifdef SPICE_INTERFACE_MIGRATION
spice_server_migrate_start(spice_server);
-#endif
} else if (migration_has_finished(s)) {
-#ifndef SPICE_INTERFACE_MIGRATION
- spice_server_migrate_switch(spice_server);
- monitor_protocol_event(QEVENT_SPICE_MIGRATE_COMPLETED, NULL);
- spice_migration_completed = true;
-#else
spice_server_migrate_end(spice_server, true);
} else if (migration_has_failed(s)) {
spice_server_migrate_end(spice_server, false);
-#endif
}
}
@@ -513,16 +490,11 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
MonitorCompletion *cb, void *opaque)
{
int ret;
-#ifdef SPICE_INTERFACE_MIGRATION
+
spice_migrate.connect_complete.cb = cb;
spice_migrate.connect_complete.opaque = opaque;
ret = spice_server_migrate_connect(spice_server, hostname,
port, tls_port, subject);
-#else
- ret = spice_server_migrate_info(spice_server, hostname,
- port, tls_port, subject);
- cb(opaque, NULL);
-#endif
return ret;
}
@@ -561,7 +533,6 @@ static int add_channel(const char *name, const char *value, void *opaque)
static void vm_change_state_handler(void *opaque, int running,
RunState state)
{
-#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */
if (running) {
qemu_spice_display_start();
spice_server_vm_start(spice_server);
@@ -569,7 +540,6 @@ static void vm_change_state_handler(void *opaque, int running,
spice_server_vm_stop(spice_server);
qemu_spice_display_stop();
}
-#endif
}
void qemu_spice_init(void)
@@ -585,9 +555,7 @@ void qemu_spice_init(void)
int port, tls_port, len, addr_flags;
spice_image_compression_t compression;
spice_wan_compression_t wan_compr;
-#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */
bool seamless_migration;
-#endif
qemu_thread_get_self(&me);
@@ -672,16 +640,11 @@ void qemu_spice_init(void)
spice_server_set_ticket(spice_server, password, 0, 0, 0);
}
if (qemu_opt_get_bool(opts, "sasl", 0)) {
-#if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */
if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 ||
spice_server_set_sasl(spice_server, 1) == -1) {
error_report("spice: failed to enable sasl");
exit(1);
}
-#else
- error_report("spice: sasl is not available (spice >= 0.9 required)");
- exit(1);
-#endif
}
if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
auth = "none";
@@ -726,15 +689,11 @@ void qemu_spice_init(void)
qemu_opt_foreach(opts, add_channel, &tls_port, 0);
-#if SPICE_SERVER_VERSION >= 0x000a02 /* 0.10.2 */
spice_server_set_name(spice_server, qemu_name);
spice_server_set_uuid(spice_server, qemu_uuid);
-#endif
-#if SPICE_SERVER_VERSION >= 0x000b02 /* 0.11.2 */
seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0);
spice_server_set_seamless_migration(spice_server, seamless_migration);
-#endif
if (0 != spice_server_init(spice_server, &core_interface)) {
error_report("failed to initialize spice server");
exit(1);
@@ -743,11 +702,9 @@ void qemu_spice_init(void)
migration_state.notify = migration_state_notifier;
add_migration_state_change_notifier(&migration_state);
-#ifdef SPICE_INTERFACE_MIGRATION
spice_migrate.sin.base.sif = &migrate_interface.base;
spice_migrate.connect_complete.cb = NULL;
qemu_spice_add_interface(&spice_migrate.sin.base);
-#endif
qemu_spice_input_init();
qemu_spice_audio_init();
@@ -815,15 +772,11 @@ int qemu_spice_set_pw_expire(time_t expires)
int qemu_spice_display_add_client(int csock, int skipauth, int tls)
{
-#if SPICE_SERVER_VERSION >= 0x000a01
if (tls) {
return spice_server_add_ssl_client(spice_server, csock, skipauth);
} else {
return spice_server_add_client(spice_server, csock, skipauth);
}
-#else
- return -1;
-#endif
}
static void spice_register_config(void)
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 50fbefb067..b61764f381 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -126,21 +126,6 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd)
ssd->worker->wakeup(ssd->worker);
}
-#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
-static void qemu_spice_start(SimpleSpiceDisplay *ssd)
-{
- trace_qemu_spice_start(ssd->qxl.id);
- ssd->worker->start(ssd->worker);
-}
-
-static void qemu_spice_stop(SimpleSpiceDisplay *ssd)
-{
- trace_qemu_spice_stop(ssd->qxl.id);
- ssd->worker->stop(ssd->worker);
-}
-
-#else
-
static int spice_display_is_running;
void qemu_spice_display_start(void)
@@ -153,15 +138,9 @@ void qemu_spice_display_stop(void)
spice_display_is_running = false;
}
-#endif
-
int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd)
{
-#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
- return ssd->running;
-#else
return spice_display_is_running;
-#endif
}
static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
@@ -364,22 +343,6 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC);
}
-void qemu_spice_vm_change_state_handler(void *opaque, int running,
- RunState state)
-{
-#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
- SimpleSpiceDisplay *ssd = opaque;
-
- if (running) {
- ssd->running = true;
- qemu_spice_start(ssd);
- } else {
- qemu_spice_stop(ssd);
- ssd->running = false;
- }
-#endif
-}
-
void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
{
ssd->ds = ds;
@@ -623,7 +586,6 @@ void qemu_spice_display_init(DisplayState *ds)
qemu_spice_add_interface(&sdpy.qxl.base);
assert(sdpy.worker);
- qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy);
qemu_spice_create_host_memslot(&sdpy);
qemu_spice_create_host_primary(&sdpy);
}
diff --git a/ui/spice-display.h b/ui/spice-display.h
index dea41c1b71..d7669277fd 100644
--- a/ui/spice-display.h
+++ b/ui/spice-display.h
@@ -83,9 +83,6 @@ struct SimpleSpiceDisplay {
QXLRect dirty;
int notify;
-#if SPICE_SERVER_VERSION < 0x000b02 /* before 0.11.2 */
- int running;
-#endif
/*
* All struct members below this comment can be accessed from
@@ -133,8 +130,6 @@ void qemu_spice_create_primary_surface(SimpleSpiceDisplay *ssd, uint32_t id,
void qemu_spice_destroy_primary_surface(SimpleSpiceDisplay *ssd,
uint32_t id, qxl_async_io async);
void qemu_spice_wakeup(SimpleSpiceDisplay *ssd);
-#if SPICE_SERVER_VERSION >= 0x000b02 /* before 0.11.2 */
void qemu_spice_display_start(void);
void qemu_spice_display_stop(void);
-#endif
int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd);
diff --git a/ui/vnc.c b/ui/vnc.c
index 01b2dafea2..33e6386a6e 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -372,6 +372,10 @@ VncInfo *qmp_query_vnc(Error **errp)
}
}
+ if (vnc_display->lsock == -1) {
+ return info;
+ }
+
if (getsockname(vnc_display->lsock, (struct sockaddr *)&sa,
&salen) == -1) {
error_set(errp, QERR_UNDEFINED_ERROR);