aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml14
-rw-r--r--Makefile22
-rwxr-xr-xconfigure5
-rw-r--r--hw/core/qdev-properties.c11
-rw-r--r--hw/ppc/spapr_iommu.c18
-rw-r--r--hw/vfio/common.c28
-rw-r--r--hw/vfio/pci-quirks.c9
-rw-r--r--hw/vfio/pci.c195
-rw-r--r--hw/vfio/pci.h7
-rw-r--r--hw/vfio/platform.c2
-rw-r--r--hw/vfio/trace-events3
-rw-r--r--include/exec/memory.h22
-rw-r--r--include/hw/qdev-properties.h4
-rw-r--r--memory.c13
-rw-r--r--migration/channel.c32
-rw-r--r--migration/channel.h3
-rw-r--r--migration/exec.c2
-rw-r--r--migration/fd.c2
-rw-r--r--migration/migration.c15
-rw-r--r--migration/migration.h2
-rw-r--r--migration/ram.c11
-rw-r--r--migration/rdma.c2
-rw-r--r--migration/savevm.c25
-rw-r--r--migration/socket.c4
-rw-r--r--migration/tls.c3
-rw-r--r--migration/trace-events2
-rw-r--r--qapi/common.json26
-rw-r--r--qapi/ui.json5
-rw-r--r--scripts/qapi.py43
-rwxr-xr-xscripts/qapi2texi.py11
-rw-r--r--scripts/qemu.py94
-rw-r--r--scripts/signrom.py4
-rw-r--r--target/ppc/kvm.c7
-rw-r--r--target/ppc/kvm_ppc.h6
-rw-r--r--tests/Makefile.include6
-rw-r--r--tests/docker/dockerfiles/fedora.docker3
-rw-r--r--tests/migration-test.c144
-rw-r--r--tests/qapi-schema/test-qapi.py43
m---------ui/keycodemapdb0
39 files changed, 621 insertions, 227 deletions
diff --git a/.travis.yml b/.travis.yml
index f583839755..708c886017 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
sudo: false
language: c
python:
- - "2.4"
+ - "2.6"
compiler:
- gcc
cache: ccache
@@ -115,15 +115,17 @@ matrix:
- sudo apt-get build-dep -qq qemu
- wget -O - http://people.linaro.org/~alex.bennee/qemu-submodule-git-seed.tar.xz | tar -xvJ
- git submodule update --init --recursive
- # Trusty System build with latest stable clang
+ # Trusty System build with latest stable clang & python 3.0
- sudo: required
addons:
dist: trusty
language: generic
compiler: none
+ python:
+ - "3.0"
env:
- COMPILER_NAME=clang CXX=clang++-3.9 CC=clang-3.9
- - CONFIG="--disable-linux-user --cc=clang-3.9 --cxx=clang++-3.9"
+ - CONFIG="--disable-linux-user --cc=clang-3.9 --cxx=clang++-3.9 --python=/usr/bin/python3"
before_install:
- wget -nv -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
- sudo apt-add-repository -y 'deb http://llvm.org/apt/trusty llvm-toolchain-trusty-3.9 main'
@@ -134,15 +136,17 @@ matrix:
- git submodule update --init --recursive
before_script:
- ./configure ${CONFIG} || cat config.log
- # Trusty Linux User build with latest stable clang
+ # Trusty Linux User build with latest stable clang & python 3.6
- sudo: required
addons:
dist: trusty
language: generic
compiler: none
+ python:
+ - "3.6"
env:
- COMPILER_NAME=clang CXX=clang++-3.9 CC=clang-3.9
- - CONFIG="--disable-system --cc=clang-3.9 --cxx=clang++-3.9"
+ - CONFIG="--disable-system --cc=clang-3.9 --cxx=clang++-3.9 --python=/usr/bin/python3"
before_install:
- wget -nv -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
- sudo apt-add-repository -y 'deb http://llvm.org/apt/trusty llvm-toolchain-trusty-3.9 main'
diff --git a/Makefile b/Makefile
index 7d35ea1a06..4ec7a3cb82 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,8 @@ ifneq ($(wildcard config-host.mak),)
all:
include config-host.mak
+PYTHON_UTF8 = LC_ALL= LANG=C LC_CTYPE=en_US.UTF-8 $(PYTHON)
+
git-submodule-update:
.PHONY: git-submodule-update
@@ -487,17 +489,17 @@ qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
"GEN","$@")
qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
"GEN","$@")
qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
"GEN","$@")
@@ -518,27 +520,27 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
qapi-types.c qapi-types.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o "." -b $<, \
"GEN","$@")
qapi-visit.c qapi-visit.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o "." -b $<, \
"GEN","$@")
qapi-event.c qapi-event.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-event.py \
$(gen-out-type) -o "." $<, \
"GEN","$@")
qmp-commands.h qmp-marshal.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o "." $<, \
"GEN","$@")
qmp-introspect.h qmp-introspect.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-introspect.py \
$(gen-out-type) -o "." $<, \
"GEN","$@")
@@ -811,10 +813,10 @@ qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
docs/interop/qemu-qmp-qapi.texi docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/scripts/qapi2texi.py $(qapi-py)
docs/interop/qemu-qmp-qapi.texi: $(qapi-modules)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
+ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
qemu.1: qemu-option-trace.texi
diff --git a/configure b/configure
index 302fdc92ff..886abe6a39 100755
--- a/configure
+++ b/configure
@@ -1604,9 +1604,8 @@ fi
# Note that if the Python conditional here evaluates True we will exit
# with status 1 which is a shell 'false' value.
-if ! $python -c 'import sys; sys.exit(sys.version_info < (2,6) or sys.version_info >= (3,))'; then
- error_exit "Cannot use '$python', Python 2.6 or later is required." \
- "Note that Python 3 or later is not yet supported." \
+if ! $python -c 'import sys; sys.exit(sys.version_info < (2,6))'; then
+ error_exit "Cannot use '$python', Python 2 >= 2.6 or Python 3 is required." \
"Use --python=/path/to/python to specify a supported Python."
fi
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 24c17800e3..5bbc2d98b5 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1317,3 +1317,14 @@ const PropertyInfo qdev_prop_link = {
.name = "link",
.create = create_link_property,
};
+
+/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
+
+const PropertyInfo qdev_prop_off_auto_pcibar = {
+ .name = "OffAutoPCIBAR",
+ .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
+ .enum_table = &OffAutoPCIBAR_lookup,
+ .get = get_enum,
+ .set = set_enum,
+ .set_default_value = set_default_value_enum,
+};
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 5ccd785d5a..aaa6010d5c 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -160,6 +160,19 @@ static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu)
return 1ULL << tcet->page_shift;
}
+static int spapr_tce_get_attr(IOMMUMemoryRegion *iommu,
+ enum IOMMUMemoryRegionAttr attr, void *data)
+{
+ sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
+
+ if (attr == IOMMU_ATTR_SPAPR_TCE_FD && kvmppc_has_cap_spapr_vfio()) {
+ *(int *) data = tcet->fd;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old,
IOMMUNotifierFlag new)
@@ -284,6 +297,10 @@ void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio)
tcet->need_vfio = need_vfio;
+ if (!need_vfio || (tcet->fd != -1 && kvmppc_has_cap_spapr_vfio())) {
+ return;
+ }
+
oldtable = tcet->table;
tcet->table = spapr_tce_alloc_table(tcet->liobn,
@@ -643,6 +660,7 @@ static void spapr_iommu_memory_region_class_init(ObjectClass *klass, void *data)
imrc->translate = spapr_tce_translate_iommu;
imrc->get_min_page_size = spapr_tce_get_min_page_size;
imrc->notify_flag_changed = spapr_tce_notify_flag_changed;
+ imrc->get_attr = spapr_tce_get_attr;
}
static const TypeInfo spapr_iommu_memory_region_info = {
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b77be3a8b3..ee9240daeb 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -435,7 +435,6 @@ static void vfio_listener_region_add(MemoryListener *listener,
end = int128_get64(int128_sub(llend, int128_one()));
if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
- VFIOHostDMAWindow *hostwin;
hwaddr pgsize = 0;
/* For now intersections are not allowed, we may relax this later */
@@ -457,6 +456,33 @@ static void vfio_listener_region_add(MemoryListener *listener,
vfio_host_win_add(container, section->offset_within_address_space,
section->offset_within_address_space +
int128_get64(section->size) - 1, pgsize);
+#ifdef CONFIG_KVM
+ if (kvm_enabled()) {
+ VFIOGroup *group;
+ IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
+ struct kvm_vfio_spapr_tce param;
+ struct kvm_device_attr attr = {
+ .group = KVM_DEV_VFIO_GROUP,
+ .attr = KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE,
+ .addr = (uint64_t)(unsigned long)&param,
+ };
+
+ if (!memory_region_iommu_get_attr(iommu_mr, IOMMU_ATTR_SPAPR_TCE_FD,
+ &param.tablefd)) {
+ QLIST_FOREACH(group, &container->group_list, container_next) {
+ param.groupfd = group->fd;
+ if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
+ error_report("vfio: failed to setup fd %d "
+ "for a group with fd %d: %s",
+ param.tablefd, param.groupfd,
+ strerror(errno));
+ return;
+ }
+ trace_vfio_spapr_group_attach(param.groupfd, param.tablefd);
+ }
+ }
+ }
+#endif
}
hostwin_found = false;
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index 60ad5fb91a..e5779a7ad3 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -542,7 +542,8 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev)
VFIOQuirk *quirk;
VFIONvidia3d0Quirk *data;
- if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) ||
+ if (vdev->no_geforce_quirks ||
+ !vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) ||
!vdev->bars[1].region.size) {
return;
}
@@ -660,7 +661,8 @@ static void vfio_probe_nvidia_bar5_quirk(VFIOPCIDevice *vdev, int nr)
VFIONvidiaBAR5Quirk *bar5;
VFIOConfigWindowQuirk *window;
- if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) ||
+ if (vdev->no_geforce_quirks ||
+ !vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) ||
!vdev->vga || nr != 5 || !vdev->bars[5].ioport) {
return;
}
@@ -754,7 +756,8 @@ static void vfio_probe_nvidia_bar0_quirk(VFIOPCIDevice *vdev, int nr)
VFIOQuirk *quirk;
VFIOConfigMirrorQuirk *mirror;
- if (!vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) ||
+ if (vdev->no_geforce_quirks ||
+ !vfio_pci_is(vdev, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID) ||
!vfio_is_vga(vdev) || nr != 0) {
return;
}
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 2c71295125..879510c046 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -1087,7 +1087,7 @@ static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar)
{
VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
VFIORegion *region = &vdev->bars[bar].region;
- MemoryRegion *mmap_mr, *mr;
+ MemoryRegion *mmap_mr, *region_mr, *base_mr;
PCIIORegion *r;
pcibus_t bar_addr;
uint64_t size = region->size;
@@ -1100,7 +1100,8 @@ static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar)
r = &pdev->io_regions[bar];
bar_addr = r->addr;
- mr = region->mem;
+ base_mr = vdev->bars[bar].mr;
+ region_mr = region->mem;
mmap_mr = &region->mmaps[0].mem;
/* If BAR is mapped and page aligned, update to fill PAGE_SIZE */
@@ -1111,12 +1112,15 @@ static void vfio_sub_page_bar_update_mapping(PCIDevice *pdev, int bar)
memory_region_transaction_begin();
- memory_region_set_size(mr, size);
+ if (vdev->bars[bar].size < size) {
+ memory_region_set_size(base_mr, size);
+ }
+ memory_region_set_size(region_mr, size);
memory_region_set_size(mmap_mr, size);
- if (size != region->size && memory_region_is_mapped(mr)) {
- memory_region_del_subregion(r->address_space, mr);
+ if (size != vdev->bars[bar].size && memory_region_is_mapped(base_mr)) {
+ memory_region_del_subregion(r->address_space, base_mr);
memory_region_add_subregion_overlap(r->address_space,
- bar_addr, mr, 0);
+ bar_addr, base_mr, 0);
}
memory_region_transaction_commit();
@@ -1218,8 +1222,8 @@ void vfio_pci_write_config(PCIDevice *pdev,
for (bar = 0; bar < PCI_ROM_SLOT; bar++) {
if (old_addr[bar] != pdev->io_regions[bar].addr &&
- pdev->io_regions[bar].size > 0 &&
- pdev->io_regions[bar].size < qemu_real_host_page_size) {
+ vdev->bars[bar].region.size > 0 &&
+ vdev->bars[bar].region.size < qemu_real_host_page_size) {
vfio_sub_page_bar_update_mapping(pdev, bar);
}
}
@@ -1352,6 +1356,98 @@ static void vfio_pci_fixup_msix_region(VFIOPCIDevice *vdev)
}
}
+static void vfio_pci_relocate_msix(VFIOPCIDevice *vdev, Error **errp)
+{
+ int target_bar = -1;
+ size_t msix_sz;
+
+ if (!vdev->msix || vdev->msix_relo == OFF_AUTOPCIBAR_OFF) {
+ return;
+ }
+
+ /* The actual minimum size of MSI-X structures */
+ msix_sz = (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE) +
+ (QEMU_ALIGN_UP(vdev->msix->entries, 64) / 8);
+ /* Round up to host pages, we don't want to share a page */
+ msix_sz = REAL_HOST_PAGE_ALIGN(msix_sz);
+ /* PCI BARs must be a power of 2 */
+ msix_sz = pow2ceil(msix_sz);
+
+ if (vdev->msix_relo == OFF_AUTOPCIBAR_AUTO) {
+ /*
+ * TODO: Lookup table for known devices.
+ *
+ * Logically we might use an algorithm here to select the BAR adding
+ * the least additional MMIO space, but we cannot programatically
+ * predict the driver dependency on BAR ordering or sizing, therefore
+ * 'auto' becomes a lookup for combinations reported to work.
+ */
+ if (target_bar < 0) {
+ error_setg(errp, "No automatic MSI-X relocation available for "
+ "device %04x:%04x", vdev->vendor_id, vdev->device_id);
+ return;
+ }
+ } else {
+ target_bar = (int)(vdev->msix_relo - OFF_AUTOPCIBAR_BAR0);
+ }
+
+ /* I/O port BARs cannot host MSI-X structures */
+ if (vdev->bars[target_bar].ioport) {
+ error_setg(errp, "Invalid MSI-X relocation BAR %d, "
+ "I/O port BAR", target_bar);
+ return;
+ }
+
+ /* Cannot use a BAR in the "shadow" of a 64-bit BAR */
+ if (!vdev->bars[target_bar].size &&
+ target_bar > 0 && vdev->bars[target_bar - 1].mem64) {
+ error_setg(errp, "Invalid MSI-X relocation BAR %d, "
+ "consumed by 64-bit BAR %d", target_bar, target_bar - 1);
+ return;
+ }
+
+ /* 2GB max size for 32-bit BARs, cannot double if already > 1G */
+ if (vdev->bars[target_bar].size > (1 * 1024 * 1024 * 1024) &&
+ !vdev->bars[target_bar].mem64) {
+ error_setg(errp, "Invalid MSI-X relocation BAR %d, "
+ "no space to extend 32-bit BAR", target_bar);
+ return;
+ }
+
+ /*
+ * If adding a new BAR, test if we can make it 64bit. We make it
+ * prefetchable since QEMU MSI-X emulation has no read side effects
+ * and doing so makes mapping more flexible.
+ */
+ if (!vdev->bars[target_bar].size) {
+ if (target_bar < (PCI_ROM_SLOT - 1) &&
+ !vdev->bars[target_bar + 1].size) {
+ vdev->bars[target_bar].mem64 = true;
+ vdev->bars[target_bar].type = PCI_BASE_ADDRESS_MEM_TYPE_64;
+ }
+ vdev->bars[target_bar].type |= PCI_BASE_ADDRESS_MEM_PREFETCH;
+ vdev->bars[target_bar].size = msix_sz;
+ vdev->msix->table_offset = 0;
+ } else {
+ vdev->bars[target_bar].size = MAX(vdev->bars[target_bar].size * 2,
+ msix_sz * 2);
+ /*
+ * Due to above size calc, MSI-X always starts halfway into the BAR,
+ * which will always be a separate host page.
+ */
+ vdev->msix->table_offset = vdev->bars[target_bar].size / 2;
+ }
+
+ vdev->msix->table_bar = target_bar;
+ vdev->msix->pba_bar = target_bar;
+ /* Requires 8-byte alignment, but PCI_MSIX_ENTRY_SIZE guarantees that */
+ vdev->msix->pba_offset = vdev->msix->table_offset +
+ (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE);
+
+ trace_vfio_msix_relo(vdev->vbasedev.name,
+ vdev->msix->table_bar, vdev->msix->table_offset);
+}
+
/*
* We don't have any control over how pci_add_capability() inserts
* capabilities into the chain. In order to setup MSI-X we need a
@@ -1430,6 +1526,8 @@ static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp)
vdev->msix = msix;
vfio_pci_fixup_msix_region(vdev);
+
+ vfio_pci_relocate_msix(vdev, errp);
}
static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
@@ -1440,9 +1538,9 @@ static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
vdev->msix->pending = g_malloc0(BITS_TO_LONGS(vdev->msix->entries) *
sizeof(unsigned long));
ret = msix_init(&vdev->pdev, vdev->msix->entries,
- vdev->bars[vdev->msix->table_bar].region.mem,
+ vdev->bars[vdev->msix->table_bar].mr,
vdev->msix->table_bar, vdev->msix->table_offset,
- vdev->bars[vdev->msix->pba_bar].region.mem,
+ vdev->bars[vdev->msix->pba_bar].mr,
vdev->msix->pba_bar, vdev->msix->pba_offset, pos,
&err);
if (ret < 0) {
@@ -1482,8 +1580,8 @@ static void vfio_teardown_msi(VFIOPCIDevice *vdev)
if (vdev->msix) {
msix_uninit(&vdev->pdev,
- vdev->bars[vdev->msix->table_bar].region.mem,
- vdev->bars[vdev->msix->pba_bar].region.mem);
+ vdev->bars[vdev->msix->table_bar].mr,
+ vdev->bars[vdev->msix->pba_bar].mr);
g_free(vdev->msix->pending);
}
}
@@ -1500,12 +1598,11 @@ static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled)
}
}
-static void vfio_bar_setup(VFIOPCIDevice *vdev, int nr)
+static void vfio_bar_prepare(VFIOPCIDevice *vdev, int nr)
{
VFIOBAR *bar = &vdev->bars[nr];
uint32_t pci_bar;
- uint8_t type;
int ret;
/* Skip both unimplemented BARs and the upper half of 64bit BARS. */
@@ -1524,23 +1621,52 @@ static void vfio_bar_setup(VFIOPCIDevice *vdev, int nr)
pci_bar = le32_to_cpu(pci_bar);
bar->ioport = (pci_bar & PCI_BASE_ADDRESS_SPACE_IO);
bar->mem64 = bar->ioport ? 0 : (pci_bar & PCI_BASE_ADDRESS_MEM_TYPE_64);
- type = pci_bar & (bar->ioport ? ~PCI_BASE_ADDRESS_IO_MASK :
- ~PCI_BASE_ADDRESS_MEM_MASK);
+ bar->type = pci_bar & (bar->ioport ? ~PCI_BASE_ADDRESS_IO_MASK :
+ ~PCI_BASE_ADDRESS_MEM_MASK);
+ bar->size = bar->region.size;
+}
+
+static void vfio_bars_prepare(VFIOPCIDevice *vdev)
+{
+ int i;
- if (vfio_region_mmap(&bar->region)) {
- error_report("Failed to mmap %s BAR %d. Performance may be slow",
- vdev->vbasedev.name, nr);
+ for (i = 0; i < PCI_ROM_SLOT; i++) {
+ vfio_bar_prepare(vdev, i);
}
+}
+
+static void vfio_bar_register(VFIOPCIDevice *vdev, int nr)
+{
+ VFIOBAR *bar = &vdev->bars[nr];
+ char *name;
- pci_register_bar(&vdev->pdev, nr, type, bar->region.mem);
+ if (!bar->size) {
+ return;
+ }
+
+ bar->mr = g_new0(MemoryRegion, 1);
+ name = g_strdup_printf("%s base BAR %d", vdev->vbasedev.name, nr);
+ memory_region_init_io(bar->mr, OBJECT(vdev), NULL, NULL, name, bar->size);
+ g_free(name);
+
+ if (bar->region.size) {
+ memory_region_add_subregion(bar->mr, 0, bar->region.mem);
+
+ if (vfio_region_mmap(&bar->region)) {
+ error_report("Failed to mmap %s BAR %d. Performance may be slow",
+ vdev->vbasedev.name, nr);
+ }
+ }
+
+ pci_register_bar(&vdev->pdev, nr, bar->type, bar->mr);
}
-static void vfio_bars_setup(VFIOPCIDevice *vdev)
+static void vfio_bars_register(VFIOPCIDevice *vdev)
{
int i;
for (i = 0; i < PCI_ROM_SLOT; i++) {
- vfio_bar_setup(vdev, i);
+ vfio_bar_register(vdev, i);
}
}
@@ -1549,8 +1675,13 @@ static void vfio_bars_exit(VFIOPCIDevice *vdev)
int i;
for (i = 0; i < PCI_ROM_SLOT; i++) {
+ VFIOBAR *bar = &vdev->bars[i];
+
vfio_bar_quirk_exit(vdev, i);
- vfio_region_exit(&vdev->bars[i].region);
+ vfio_region_exit(&bar->region);
+ if (bar->region.size) {
+ memory_region_del_subregion(bar->mr, bar->region.mem);
+ }
}
if (vdev->vga) {
@@ -1564,8 +1695,14 @@ static void vfio_bars_finalize(VFIOPCIDevice *vdev)
int i;
for (i = 0; i < PCI_ROM_SLOT; i++) {
+ VFIOBAR *bar = &vdev->bars[i];
+
vfio_bar_quirk_finalize(vdev, i);
- vfio_region_finalize(&vdev->bars[i].region);
+ vfio_region_finalize(&bar->region);
+ if (bar->size) {
+ object_unparent(OBJECT(bar->mr));
+ g_free(bar->mr);
+ }
}
if (vdev->vga) {
@@ -2734,6 +2871,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
/* QEMU can choose to expose the ROM or not */
memset(vdev->emulated_config_bits + PCI_ROM_ADDRESS, 0xff, 4);
+ /* QEMU can also add or extend BARs */
+ memset(vdev->emulated_config_bits + PCI_BASE_ADDRESS_0, 0xff, 6 * 4);
/*
* The PCI spec reserves vendor ID 0xffff as an invalid value. The
@@ -2804,13 +2943,15 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
vfio_pci_size_rom(vdev);
+ vfio_bars_prepare(vdev);
+
vfio_msix_early_setup(vdev, &err);
if (err) {
error_propagate(errp, err);
goto error;
}
- vfio_bars_setup(vdev);
+ vfio_bars_register(vdev);
ret = vfio_add_capabilities(vdev, errp);
if (ret) {
@@ -2989,6 +3130,8 @@ static Property vfio_pci_dev_properties[] = {
DEFINE_PROP_BOOL("x-no-kvm-intx", VFIOPCIDevice, no_kvm_intx, false),
DEFINE_PROP_BOOL("x-no-kvm-msi", VFIOPCIDevice, no_kvm_msi, false),
DEFINE_PROP_BOOL("x-no-kvm-msix", VFIOPCIDevice, no_kvm_msix, false),
+ DEFINE_PROP_BOOL("x-no-geforce-quirks", VFIOPCIDevice,
+ no_geforce_quirks, false),
DEFINE_PROP_UINT32("x-pci-vendor-id", VFIOPCIDevice, vendor_id, PCI_ANY_ID),
DEFINE_PROP_UINT32("x-pci-device-id", VFIOPCIDevice, device_id, PCI_ANY_ID),
DEFINE_PROP_UINT32("x-pci-sub-vendor-id", VFIOPCIDevice,
@@ -2999,6 +3142,8 @@ static Property vfio_pci_dev_properties[] = {
DEFINE_PROP_UNSIGNED_NODEFAULT("x-nv-gpudirect-clique", VFIOPCIDevice,
nv_gpudirect_clique,
qdev_prop_nv_gpudirect_clique, uint8_t),
+ DEFINE_PROP_OFF_AUTO_PCIBAR("x-msix-relocation", VFIOPCIDevice, msix_relo,
+ OFF_AUTOPCIBAR_OFF),
/*
* TODO - support passed fds... is this necessary?
* DEFINE_PROP_STRING("vfiofd", VFIOPCIDevice, vfiofd_name),
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index a8fb3b3422..f4aa13e021 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -33,6 +33,9 @@ typedef struct VFIOQuirk {
typedef struct VFIOBAR {
VFIORegion region;
+ MemoryRegion *mr;
+ size_t size;
+ uint8_t type;
bool ioport;
bool mem64;
QLIST_HEAD(, VFIOQuirk) quirks;
@@ -86,7 +89,7 @@ enum {
VFIO_INT_MSIX = 3,
};
-/* Cache of MSI-X setup plus extra mmap and memory region for split BAR map */
+/* Cache of MSI-X setup */
typedef struct VFIOMSIXInfo {
uint8_t table_bar;
uint8_t pba_bar;
@@ -132,6 +135,7 @@ typedef struct VFIOPCIDevice {
(1 << VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT)
int32_t bootindex;
uint32_t igd_gms;
+ OffAutoPCIBAR msix_relo;
uint8_t pm_cap;
uint8_t nv_gpudirect_clique;
bool pci_aer;
@@ -142,6 +146,7 @@ typedef struct VFIOPCIDevice {
bool no_kvm_intx;
bool no_kvm_msi;
bool no_kvm_msix;
+ bool no_geforce_quirks;
} VFIOPCIDevice;
uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index da84abf4fc..0d4bc0aae8 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -643,6 +643,8 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
vbasedev->dev = dev;
vbasedev->ops = &vfio_platform_ops;
+ qemu_mutex_init(&vdev->intp_mutex);
+
trace_vfio_platform_realize(vbasedev->sysfsdev ?
vbasedev->sysfsdev : vbasedev->name,
vdev->compat);
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index fae096c072..79f63a2ff6 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -16,6 +16,8 @@ vfio_msix_pba_disable(const char *name) " (%s)"
vfio_msix_pba_enable(const char *name) " (%s)"
vfio_msix_disable(const char *name) " (%s)"
vfio_msix_fixup(const char *name, int bar, uint64_t start, uint64_t end) " (%s) MSI-X region %d mmap fixup [0x%"PRIx64" - 0x%"PRIx64"]"
+vfio_msix_relo_cost(const char *name, int bar, uint64_t cost) " (%s) BAR %d cost 0x%"PRIx64""
+vfio_msix_relo(const char *name, int bar, uint64_t offset) " (%s) BAR %d offset 0x%"PRIx64""
vfio_msi_enable(const char *name, int nr_vectors) " (%s) Enabled %d MSI vectors"
vfio_msi_disable(const char *name) " (%s)"
vfio_pci_load_rom(const char *name, unsigned long size, unsigned long offset, unsigned long flags) "Device %s ROM:\n size: 0x%lx, offset: 0x%lx, flags: 0x%lx"
@@ -123,3 +125,4 @@ vfio_prereg_register(uint64_t va, uint64_t size, int ret) "va=0x%"PRIx64" size=0
vfio_prereg_unregister(uint64_t va, uint64_t size, int ret) "va=0x%"PRIx64" size=0x%"PRIx64" ret=%d"
vfio_spapr_create_window(int ps, uint64_t ws, uint64_t off) "pageshift=0x%x winsize=0x%"PRIx64" offset=0x%"PRIx64
vfio_spapr_remove_window(uint64_t off) "offset=0x%"PRIx64
+vfio_spapr_group_attach(int groupfd, int tablefd) "Attached groupfd %d to liobn fd %d"
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 07c5d6d597..3ef83991e9 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -190,6 +190,10 @@ struct MemoryRegionOps {
const MemoryRegionMmio old_mmio;
};
+enum IOMMUMemoryRegionAttr {
+ IOMMU_ATTR_SPAPR_TCE_FD
+};
+
typedef struct IOMMUMemoryRegionClass {
/* private */
struct DeviceClass parent_class;
@@ -210,6 +214,10 @@ typedef struct IOMMUMemoryRegionClass {
IOMMUNotifierFlag new_flags);
/* Set this up to provide customized IOMMU replay function */
void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
+
+ /* Get IOMMU misc attributes */
+ int (*get_attr)(IOMMUMemoryRegion *iommu, enum IOMMUMemoryRegionAttr,
+ void *data);
} IOMMUMemoryRegionClass;
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
@@ -927,6 +935,20 @@ void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n);
/**
+ * memory_region_iommu_get_attr: return an IOMMU attr if get_attr() is
+ * defined on the IOMMU.
+ *
+ * Returns 0 if succeded, error code otherwise.
+ *
+ * @iommu_mr: the memory region
+ * @attr: the requested attribute
+ * @data: a pointer to the requested attribute data
+ */
+int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
+ enum IOMMUMemoryRegionAttr attr,
+ void *data);
+
+/**
* memory_region_name: get a memory region's name
*
* Returns the string that was used to initialize the memory region.
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 5bbfec634b..1d61a35108 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -34,6 +34,7 @@ extern const PropertyInfo qdev_prop_pci_host_devaddr;
extern const PropertyInfo qdev_prop_uuid;
extern const PropertyInfo qdev_prop_arraylen;
extern const PropertyInfo qdev_prop_link;
+extern const PropertyInfo qdev_prop_off_auto_pcibar;
#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
.name = (_name), \
@@ -214,6 +215,9 @@ extern const PropertyInfo qdev_prop_link;
DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress)
#define DEFINE_PROP_MEMORY_REGION(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, MemoryRegion *)
+#define DEFINE_PROP_OFF_AUTO_PCIBAR(_n, _s, _f, _d) \
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_off_auto_pcibar, \
+ OffAutoPCIBAR)
#define DEFINE_PROP_UUID(_name, _state, _field) { \
.name = (_name), \
diff --git a/memory.c b/memory.c
index 449a1429b9..a4c603730a 100644
--- a/memory.c
+++ b/memory.c
@@ -1922,6 +1922,19 @@ void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
}
}
+int memory_region_iommu_get_attr(IOMMUMemoryRegion *iommu_mr,
+ enum IOMMUMemoryRegionAttr attr,
+ void *data)
+{
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
+
+ if (!imrc->get_attr) {
+ return -EINVAL;
+ }
+
+ return imrc->get_attr(iommu_mr, attr, data);
+}
+
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
{
uint8_t mask = 1 << client;
diff --git a/migration/channel.c b/migration/channel.c
index 70ec7ea3b7..c5eaf0fa0e 100644
--- a/migration/channel.c
+++ b/migration/channel.c
@@ -55,29 +55,29 @@ void migration_channel_process_incoming(QIOChannel *ioc)
* @s: Current migration state
* @ioc: Channel to which we are connecting
* @hostname: Where we want to connect
+ * @error: Error indicating failure to connect, free'd here
*/
void migration_channel_connect(MigrationState *s,
QIOChannel *ioc,
- const char *hostname)
+ const char *hostname,
+ Error *error)
{
trace_migration_set_outgoing_channel(
- ioc, object_get_typename(OBJECT(ioc)), hostname);
+ ioc, object_get_typename(OBJECT(ioc)), hostname, error);
- if (s->parameters.tls_creds &&
- *s->parameters.tls_creds &&
- !object_dynamic_cast(OBJECT(ioc),
- TYPE_QIO_CHANNEL_TLS)) {
- Error *local_err = NULL;
- migration_tls_channel_connect(s, ioc, hostname, &local_err);
- if (local_err) {
- migrate_fd_error(s, local_err);
- error_free(local_err);
- }
- } else {
- QEMUFile *f = qemu_fopen_channel_output(ioc);
+ if (!error) {
+ if (s->parameters.tls_creds &&
+ *s->parameters.tls_creds &&
+ !object_dynamic_cast(OBJECT(ioc),
+ TYPE_QIO_CHANNEL_TLS)) {
+ migration_tls_channel_connect(s, ioc, hostname, &error);
+ } else {
+ QEMUFile *f = qemu_fopen_channel_output(ioc);
- s->to_dst_file = f;
+ s->to_dst_file = f;
- migrate_fd_connect(s);
+ }
}
+ migrate_fd_connect(s, error);
+ error_free(error);
}
diff --git a/migration/channel.h b/migration/channel.h
index e4b40579a1..67a461c28a 100644
--- a/migration/channel.h
+++ b/migration/channel.h
@@ -22,5 +22,6 @@ void migration_channel_process_incoming(QIOChannel *ioc);
void migration_channel_connect(MigrationState *s,
QIOChannel *ioc,
- const char *hostname);
+ const char *hostname,
+ Error *error_in);
#endif
diff --git a/migration/exec.c b/migration/exec.c
index f3be1baf2e..c9537974ad 100644
--- a/migration/exec.c
+++ b/migration/exec.c
@@ -39,7 +39,7 @@ void exec_start_outgoing_migration(MigrationState *s, const char *command, Error
}
qio_channel_set_name(ioc, "migration-exec-outgoing");
- migration_channel_connect(s, ioc, NULL);
+ migration_channel_connect(s, ioc, NULL, NULL);
object_unref(OBJECT(ioc));
}
diff --git a/migration/fd.c b/migration/fd.c
index 30de4b9847..6284a97cba 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -39,7 +39,7 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
}
qio_channel_set_name(QIO_CHANNEL(ioc), "migration-fd-outgoing");
- migration_channel_connect(s, ioc, NULL);
+ migration_channel_connect(s, ioc, NULL, NULL);
object_unref(OBJECT(ioc));
}
diff --git a/migration/migration.c b/migration/migration.c
index c99a4e62d7..0fdb2e410d 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -2122,7 +2122,8 @@ fail_invalidate:
/* If not doing postcopy, vm_start() will be called: let's regain
* control on images.
*/
- if (s->state == MIGRATION_STATUS_ACTIVE) {
+ if (s->state == MIGRATION_STATUS_ACTIVE ||
+ s->state == MIGRATION_STATUS_DEVICE) {
Error *local_err = NULL;
qemu_mutex_lock_iothread();
@@ -2169,7 +2170,6 @@ static void migration_update_counters(MigrationState *s,
int64_t current_time)
{
uint64_t transferred, time_spent;
- int64_t threshold_size;
double bandwidth;
if (current_time < s->iteration_start_time + BUFFER_DELAY) {
@@ -2179,7 +2179,7 @@ static void migration_update_counters(MigrationState *s,
transferred = qemu_ftell(s->to_dst_file) - s->iteration_initial_bytes;
time_spent = current_time - s->iteration_start_time;
bandwidth = (double)transferred / time_spent;
- threshold_size = bandwidth * s->parameters.downtime_limit;
+ s->threshold_size = bandwidth * s->parameters.downtime_limit;
s->mbps = (((double) transferred * 8.0) /
((double) time_spent / 1000.0)) / 1000.0 / 1000.0;
@@ -2199,7 +2199,7 @@ static void migration_update_counters(MigrationState *s,
s->iteration_initial_bytes = qemu_ftell(s->to_dst_file);
trace_migrate_transferred(transferred, time_spent,
- bandwidth, threshold_size);
+ bandwidth, s->threshold_size);
}
/* Migration thread iteration status */
@@ -2378,10 +2378,15 @@ static void *migration_thread(void *opaque)
return NULL;
}
-void migrate_fd_connect(MigrationState *s)
+void migrate_fd_connect(MigrationState *s, Error *error_in)
{
s->expected_downtime = s->parameters.downtime_limit;
s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
+ if (error_in) {
+ migrate_fd_error(s, error_in);
+ migrate_fd_cleanup(s);
+ return;
+ }
qemu_file_set_blocking(s->to_dst_file, true);
qemu_file_set_rate_limit(s->to_dst_file,
diff --git a/migration/migration.h b/migration/migration.h
index 786d971ce2..d3b214e5ba 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -190,7 +190,7 @@ uint64_t migrate_max_downtime(void);
void migrate_set_error(MigrationState *s, const Error *error);
void migrate_fd_error(MigrationState *s, const Error *error);
-void migrate_fd_connect(MigrationState *s);
+void migrate_fd_connect(MigrationState *s, Error *error_in);
MigrationState *migrate_init(void);
bool migration_is_blocked(Error **errp);
diff --git a/migration/ram.c b/migration/ram.c
index cb1950f3eb..5a109efeda 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -907,11 +907,10 @@ static void migration_bitmap_sync(RAMState *rs)
* @rs: current RAM state
* @block: block that contains the page we want to send
* @offset: offset inside the block for the page
- * @p: pointer to the page
*/
-static int save_zero_page(RAMState *rs, RAMBlock *block, ram_addr_t offset,
- uint8_t *p)
+static int save_zero_page(RAMState *rs, RAMBlock *block, ram_addr_t offset)
{
+ uint8_t *p = block->host + offset;
int pages = -1;
if (is_zero_range(p, TARGET_PAGE_SIZE)) {
@@ -984,7 +983,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage)
}
}
} else {
- pages = save_zero_page(rs, block, offset, p);
+ pages = save_zero_page(rs, block, offset);
if (pages > 0) {
/* Must let xbzrle know, otherwise a previous (now 0'd) cached
* page would be stale
@@ -1160,7 +1159,7 @@ static int ram_save_compressed_page(RAMState *rs, PageSearchStatus *pss,
*/
if (block != rs->last_sent_block) {
flush_compressed_data(rs);
- pages = save_zero_page(rs, block, offset, p);
+ pages = save_zero_page(rs, block, offset);
if (pages == -1) {
/* Make sure the first page is sent out before other pages */
bytes_xmit = save_page_header(rs, rs->f, block, offset |
@@ -1180,7 +1179,7 @@ static int ram_save_compressed_page(RAMState *rs, PageSearchStatus *pss,
ram_release_pages(block->idstr, offset, pages);
}
} else {
- pages = save_zero_page(rs, block, offset, p);
+ pages = save_zero_page(rs, block, offset);
if (pages == -1) {
pages = compress_page_with_multi_thread(rs, block, offset);
} else {
diff --git a/migration/rdma.c b/migration/rdma.c
index 9d5a424011..da474fc19f 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -3758,7 +3758,7 @@ void rdma_start_outgoing_migration(void *opaque,
trace_rdma_start_outgoing_migration_after_rdma_connect();
s->to_dst_file = qemu_fopen_rdma(rdma, "wb");
- migrate_fd_connect(s);
+ migrate_fd_connect(s, NULL);
return;
err:
g_free(rdma);
diff --git a/migration/savevm.c b/migration/savevm.c
index b7908f62be..f202c3de3a 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -81,7 +81,7 @@ enum qemu_vm_cmd {
MIG_CMD_MAX
};
-#define MAX_VM_CMD_PACKAGED_SIZE (1ul << 24)
+#define MAX_VM_CMD_PACKAGED_SIZE UINT32_MAX
static struct mig_cmd_args {
ssize_t len; /* -1 = variable */
const char *name;
@@ -1376,7 +1376,8 @@ static int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis);
* *might* happen - it might be skipped if precopy transferred everything
* quickly.
*/
-static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis)
+static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis,
+ uint16_t len)
{
PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_ADVISE);
uint64_t remote_pagesize_summary, local_pagesize_summary, remote_tps;
@@ -1387,8 +1388,22 @@ static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis)
return -1;
}
- if (!migrate_postcopy_ram()) {
+ switch (len) {
+ case 0:
+ if (migrate_postcopy_ram()) {
+ error_report("RAM postcopy is enabled but have 0 byte advise");
+ return -EINVAL;
+ }
return 0;
+ case 8 + 8:
+ if (!migrate_postcopy_ram()) {
+ error_report("RAM postcopy is disabled but have 16 byte advise");
+ return -EINVAL;
+ }
+ break;
+ default:
+ error_report("CMD_POSTCOPY_ADVISE invalid length (%d)", len);
+ return -EINVAL;
}
if (!postcopy_ram_supported_by_host(mis)) {
@@ -1807,7 +1822,7 @@ static int loadvm_process_command(QEMUFile *f)
return loadvm_handle_cmd_packaged(mis);
case MIG_CMD_POSTCOPY_ADVISE:
- return loadvm_postcopy_handle_advise(mis);
+ return loadvm_postcopy_handle_advise(mis, len);
case MIG_CMD_POSTCOPY_LISTEN:
return loadvm_postcopy_handle_listen(mis);
@@ -2266,6 +2281,7 @@ void qmp_xen_save_devices_state(const char *filename, bool has_live, bool live,
}
qio_channel_set_name(QIO_CHANNEL(ioc), "migration-xen-save-state");
f = qemu_fopen_channel_output(QIO_CHANNEL(ioc));
+ object_unref(OBJECT(ioc));
ret = qemu_save_device_state(f);
qemu_fclose(f);
if (ret < 0) {
@@ -2313,6 +2329,7 @@ void qmp_xen_load_devices_state(const char *filename, Error **errp)
}
qio_channel_set_name(QIO_CHANNEL(ioc), "migration-xen-load-state");
f = qemu_fopen_channel_input(QIO_CHANNEL(ioc));
+ object_unref(OBJECT(ioc));
ret = qemu_loadvm_state(f);
qemu_fclose(f);
diff --git a/migration/socket.c b/migration/socket.c
index 3a8232dd2d..e090097077 100644
--- a/migration/socket.c
+++ b/migration/socket.c
@@ -79,12 +79,10 @@ static void socket_outgoing_migration(QIOTask *task,
if (qio_task_propagate_error(task, &err)) {
trace_migration_socket_outgoing_error(error_get_pretty(err));
- migrate_fd_error(data->s, err);
- error_free(err);
} else {
trace_migration_socket_outgoing_connected(data->hostname);
- migration_channel_connect(data->s, sioc, data->hostname);
}
+ migration_channel_connect(data->s, sioc, data->hostname, err);
object_unref(OBJECT(sioc));
}
diff --git a/migration/tls.c b/migration/tls.c
index 026a008667..a29b35b33c 100644
--- a/migration/tls.c
+++ b/migration/tls.c
@@ -118,11 +118,10 @@ static void migration_tls_outgoing_handshake(QIOTask *task,
if (qio_task_propagate_error(task, &err)) {
trace_migration_tls_outgoing_handshake_error(error_get_pretty(err));
- migrate_fd_error(s, err);
} else {
trace_migration_tls_outgoing_handshake_complete();
- migration_channel_connect(s, ioc, NULL);
}
+ migration_channel_connect(s, ioc, NULL, err);
object_unref(OBJECT(ioc));
}
diff --git a/migration/trace-events b/migration/trace-events
index 6f29fcc686..93961dea16 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -114,7 +114,7 @@ migrate_transferred(uint64_t tranferred, uint64_t time_spent, double bandwidth,
process_incoming_migration_co_end(int ret, int ps) "ret=%d postcopy-state=%d"
process_incoming_migration_co_postcopy_end_main(void) ""
migration_set_incoming_channel(void *ioc, const char *ioctype) "ioc=%p ioctype=%s"
-migration_set_outgoing_channel(void *ioc, const char *ioctype, const char *hostname) "ioc=%p ioctype=%s hostname=%s"
+migration_set_outgoing_channel(void *ioc, const char *ioctype, const char *hostname, void *err) "ioc=%p ioctype=%s hostname=%s err=%p"
# migration/rdma.c
qemu_rdma_accept_incoming_migration(void) ""
diff --git a/qapi/common.json b/qapi/common.json
index 6eb01821ef..d9b14dd429 100644
--- a/qapi/common.json
+++ b/qapi/common.json
@@ -100,3 +100,29 @@
{ 'alternate': 'StrOrNull',
'data': { 's': 'str',
'n': 'null' } }
+
+##
+# @OffAutoPCIBAR:
+#
+# An enumeration of options for specifying a PCI BAR
+#
+# @off: The specified feature is disabled
+#
+# @auto: The PCI BAR for the feature is automatically selected
+#
+# @bar0: PCI BAR0 is used for the feature
+#
+# @bar1: PCI BAR1 is used for the feature
+#
+# @bar2: PCI BAR2 is used for the feature
+#
+# @bar3: PCI BAR3 is used for the feature
+#
+# @bar4: PCI BAR4 is used for the feature
+#
+# @bar5: PCI BAR5 is used for the feature
+#
+# Since: 2.12
+##
+{ 'enum': 'OffAutoPCIBAR',
+ 'data': [ 'off', 'auto', 'bar0', 'bar1', 'bar2', 'bar3', 'bar4', 'bar5' ] }
diff --git a/qapi/ui.json b/qapi/ui.json
index 07b468f625..d6679aa8f5 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -748,6 +748,9 @@
# @ac_bookmarks: since 2.10
# altgr, altgr_r: dropped in 2.10
#
+# @muhenkan: since 2.12
+# @katakanahiragana: since 2.12
+#
# 'sysrq' was mistakenly added to hack around the fact that
# the ps2 driver was not generating correct scancodes sequences
# when 'alt+print' was pressed. This flaw is now fixed and the
@@ -775,7 +778,7 @@
'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause',
- 'ro', 'hiragana', 'henkan', 'yen',
+ 'ro', 'hiragana', 'henkan', 'yen', 'muhenkan', 'katakanahiragana',
'kp_comma', 'kp_equals', 'power', 'sleep', 'wake',
'audionext', 'audioprev', 'audiostop', 'audioplay', 'audiomute',
'volumeup', 'volumedown', 'mediaselect',
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 43a54bf40f..58f995b07f 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -11,13 +11,21 @@
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
+from __future__ import print_function
import errno
import getopt
import os
import re
import string
import sys
-from ordereddict import OrderedDict
+try:
+ from collections import OrderedDict
+except:
+ from ordereddict import OrderedDict
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
builtin_types = {
'null': 'QTYPE_QNULL',
@@ -244,7 +252,7 @@ class QAPIDoc(object):
"'Returns:' is only valid for commands")
def check(self):
- bogus = [name for name, section in self.args.iteritems()
+ bogus = [name for name, section in self.args.items()
if not section.member]
if bogus:
raise QAPISemError(
@@ -299,7 +307,7 @@ class QAPISchemaParser(object):
if not isinstance(pragma, dict):
raise QAPISemError(
info, "Value of 'pragma' must be a dictionary")
- for name, value in pragma.iteritems():
+ for name, value in pragma.items():
self._pragma(name, value, info)
else:
expr_elem = {'expr': expr,
@@ -1467,7 +1475,7 @@ class QAPISchema(object):
self._def_exprs()
self.check()
except QAPIError as err:
- print >>sys.stderr, err
+ print(err, file=sys.stderr)
exit(1)
def _def_entity(self, ent):
@@ -1565,7 +1573,7 @@ class QAPISchema(object):
def _make_members(self, data, info):
return [self._make_member(key, value, info)
- for (key, value) in data.iteritems()]
+ for (key, value) in data.items()]
def _def_struct_type(self, expr, info, doc):
name = expr['struct']
@@ -1597,11 +1605,11 @@ class QAPISchema(object):
name, info, doc, 'base', self._make_members(base, info)))
if tag_name:
variants = [self._make_variant(key, value)
- for (key, value) in data.iteritems()]
+ for (key, value) in data.items()]
members = []
else:
variants = [self._make_simple_variant(key, value, info)
- for (key, value) in data.iteritems()]
+ for (key, value) in data.items()]
typ = self._make_implicit_enum_type(name, info,
[v.name for v in variants])
tag_member = QAPISchemaObjectTypeMember('type', typ, False)
@@ -1616,7 +1624,7 @@ class QAPISchema(object):
name = expr['alternate']
data = expr['data']
variants = [self._make_variant(key, value)
- for (key, value) in data.iteritems()]
+ for (key, value) in data.items()]
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
self._def_entity(
QAPISchemaAlternateType(name, info, doc,
@@ -1670,7 +1678,7 @@ class QAPISchema(object):
assert False
def check(self):
- for ent in self._entity_dict.values():
+ for (name, ent) in sorted(self._entity_dict.items()):
ent.check(self)
def visit(self, visitor):
@@ -1726,7 +1734,10 @@ def c_enum_const(type_name, const_name, prefix=None):
type_name = prefix
return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper()
-c_name_trans = string.maketrans('.-', '__')
+if hasattr(str, 'maketrans'):
+ c_name_trans = str.maketrans('.-', '__')
+else:
+ c_name_trans = string.maketrans('.-', '__')
# Map @name to a valid C identifier.
@@ -1931,7 +1942,7 @@ def parse_command_line(extra_options='', extra_long_options=[]):
['source', 'header', 'prefix=',
'output-dir='] + extra_long_options)
except getopt.GetoptError as err:
- print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err))
+ print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr)
sys.exit(1)
output_dir = ''
@@ -1945,9 +1956,8 @@ def parse_command_line(extra_options='', extra_long_options=[]):
if o in ('-p', '--prefix'):
match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
if match.end() != len(a):
- print >>sys.stderr, \
- "%s: 'funny character '%s' in argument of --prefix" \
- % (sys.argv[0], a[match.end()])
+ print("%s: 'funny character '%s' in argument of --prefix" \
+ % (sys.argv[0], a[match.end()]), file=sys.stderr)
sys.exit(1)
prefix = a
elif o in ('-o', '--output-dir'):
@@ -1964,7 +1974,7 @@ def parse_command_line(extra_options='', extra_long_options=[]):
do_h = True
if len(args) != 1:
- print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
+ print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr)
sys.exit(1)
fname = args[0]
@@ -1992,8 +2002,7 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
if really:
return open(name, opt)
else:
- import StringIO
- return StringIO.StringIO()
+ return StringIO()
fdef = maybe_open(do_c, c_file, 'w')
fdecl = maybe_open(do_h, h_file, 'w')
diff --git a/scripts/qapi2texi.py b/scripts/qapi2texi.py
index 92e2af2cd6..bf1c57b2e2 100755
--- a/scripts/qapi2texi.py
+++ b/scripts/qapi2texi.py
@@ -4,6 +4,7 @@
# This work is licensed under the terms of the GNU LGPL, version 2+.
# See the COPYING file in the top-level directory.
"""This script produces the documentation of a qapi schema in texinfo format"""
+from __future__ import print_function
import re
import sys
@@ -145,7 +146,7 @@ def texi_member(member, suffix=''):
def texi_members(doc, what, base, variants, member_func):
"""Format the table of members"""
items = ''
- for section in doc.args.itervalues():
+ for section in doc.args.values():
# TODO Drop fallbacks when undocumented members are outlawed
if section.text:
desc = texi_format(section.text)
@@ -274,15 +275,15 @@ def texi_schema(schema):
def main(argv):
"""Takes schema argument, prints result to stdout"""
if len(argv) != 2:
- print >>sys.stderr, "%s: need exactly 1 argument: SCHEMA" % argv[0]
+ print("%s: need exactly 1 argument: SCHEMA" % argv[0], file=sys.stderr)
sys.exit(1)
schema = qapi.QAPISchema(argv[1])
if not qapi.doc_required:
- print >>sys.stderr, ("%s: need pragma 'doc-required' "
- "to generate documentation" % argv[0])
+ print("%s: need pragma 'doc-required' "
+ "to generate documentation" % argv[0], file=sys.stderr)
sys.exit(1)
- print texi_schema(schema)
+ print(texi_schema(schema))
if __name__ == '__main__':
diff --git a/scripts/qemu.py b/scripts/qemu.py
index 9bfdf6d37d..305a946562 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -15,9 +15,10 @@
import errno
import logging
import os
-import sys
import subprocess
import qmp.qmp
+import shutil
+import tempfile
LOG = logging.getLogger(__name__)
@@ -73,10 +74,11 @@ class QEMUMachine(object):
wrapper = []
if name is None:
name = "qemu-%d" % os.getpid()
- if monitor_address is None:
- monitor_address = os.path.join(test_dir, name + "-monitor.sock")
+ self._name = name
self._monitor_address = monitor_address
- self._qemu_log_path = os.path.join(test_dir, name + ".log")
+ self._vm_monitor = None
+ self._qemu_log_path = None
+ self._qemu_log_file = None
self._popen = None
self._binary = binary
self._args = list(args) # Force copy args in case we modify them
@@ -86,6 +88,9 @@ class QEMUMachine(object):
self._socket_scm_helper = socket_scm_helper
self._qmp = None
self._qemu_full_args = None
+ self._test_dir = test_dir
+ self._temp_dir = None
+ self._launched = False
# just in case logging wasn't configured by the main script:
logging.basicConfig()
@@ -146,12 +151,12 @@ class QEMUMachine(object):
raise
def is_running(self):
- return self._popen is not None and self._popen.returncode is None
+ return self._popen is not None and self._popen.poll() is None
def exitcode(self):
if self._popen is None:
return None
- return self._popen.returncode
+ return self._popen.poll()
def get_pid(self):
if not self.is_running():
@@ -159,8 +164,9 @@ class QEMUMachine(object):
return self._popen.pid
def _load_io_log(self):
- with open(self._qemu_log_path, "r") as iolog:
- self._iolog = iolog.read()
+ if self._qemu_log_path is not None:
+ with open(self._qemu_log_path, "r") as iolog:
+ self._iolog = iolog.read()
def _base_args(self):
if isinstance(self._monitor_address, tuple):
@@ -168,45 +174,54 @@ class QEMUMachine(object):
self._monitor_address[0],
self._monitor_address[1])
else:
- moncdev = 'socket,id=mon,path=%s' % self._monitor_address
+ moncdev = 'socket,id=mon,path=%s' % self._vm_monitor
return ['-chardev', moncdev,
'-mon', 'chardev=mon,mode=control',
'-display', 'none', '-vga', 'none']
def _pre_launch(self):
- self._qmp = qmp.qmp.QEMUMonitorProtocol(self._monitor_address,
+ self._temp_dir = tempfile.mkdtemp(dir=self._test_dir)
+ if self._monitor_address is not None:
+ self._vm_monitor = self._monitor_address
+ else:
+ self._vm_monitor = os.path.join(self._temp_dir,
+ self._name + "-monitor.sock")
+ self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log")
+ self._qemu_log_file = open(self._qemu_log_path, 'wb')
+
+ self._qmp = qmp.qmp.QEMUMonitorProtocol(self._vm_monitor,
server=True)
def _post_launch(self):
self._qmp.accept()
def _post_shutdown(self):
- if not isinstance(self._monitor_address, tuple):
- self._remove_if_exists(self._monitor_address)
- self._remove_if_exists(self._qemu_log_path)
+ if self._qemu_log_file is not None:
+ self._qemu_log_file.close()
+ self._qemu_log_file = None
+
+ self._qemu_log_path = None
+
+ if self._temp_dir is not None:
+ shutil.rmtree(self._temp_dir)
+ self._temp_dir = None
def launch(self):
- '''Launch the VM and establish a QMP connection'''
+ """
+ Launch the VM and make sure we cleanup and expose the
+ command line/output in case of exception
+ """
+
+ if self._launched:
+ raise QEMUMachineError('VM already launched')
+
self._iolog = None
self._qemu_full_args = None
- devnull = open(os.path.devnull, 'rb')
- qemulog = open(self._qemu_log_path, 'wb')
try:
- self._pre_launch()
- self._qemu_full_args = (self._wrapper + [self._binary] +
- self._base_args() + self._args)
- self._popen = subprocess.Popen(self._qemu_full_args,
- stdin=devnull,
- stdout=qemulog,
- stderr=subprocess.STDOUT,
- shell=False)
- self._post_launch()
+ self._launch()
+ self._launched = True
except:
- if self.is_running():
- self._popen.kill()
- self._popen.wait()
- self._load_io_log()
- self._post_shutdown()
+ self.shutdown()
LOG.debug('Error launching VM')
if self._qemu_full_args:
@@ -215,6 +230,19 @@ class QEMUMachine(object):
LOG.debug('Output: %r', self._iolog)
raise
+ def _launch(self):
+ '''Launch the VM and establish a QMP connection'''
+ devnull = open(os.path.devnull, 'rb')
+ self._pre_launch()
+ self._qemu_full_args = (self._wrapper + [self._binary] +
+ self._base_args() + self._args)
+ self._popen = subprocess.Popen(self._qemu_full_args,
+ stdin=devnull,
+ stdout=self._qemu_log_file,
+ stderr=subprocess.STDOUT,
+ shell=False)
+ self._post_launch()
+
def wait(self):
'''Wait for the VM to power off'''
self._popen.wait()
@@ -232,8 +260,8 @@ class QEMUMachine(object):
self._popen.kill()
self._popen.wait()
- self._load_io_log()
- self._post_shutdown()
+ self._load_io_log()
+ self._post_shutdown()
exitcode = self.exitcode()
if exitcode is not None and exitcode < 0:
@@ -244,6 +272,8 @@ class QEMUMachine(object):
command = ''
LOG.warn(msg, exitcode, command)
+ self._launched = False
+
def qmp(self, cmd, conv_keys=True, **args):
'''Invoke a QMP command and return the response dict'''
qmp_args = dict()
diff --git a/scripts/signrom.py b/scripts/signrom.py
index d1dabe0240..0497a1c32e 100644
--- a/scripts/signrom.py
+++ b/scripts/signrom.py
@@ -18,7 +18,7 @@ fin = open(sys.argv[1], 'rb')
fout = open(sys.argv[2], 'wb')
magic = fin.read(2)
-if magic != '\x55\xaa':
+if magic != b'\x55\xaa':
sys.exit("%s: option ROM does not begin with magic 55 aa" % sys.argv[1])
size_byte = ord(fin.read(1))
@@ -33,7 +33,7 @@ elif len(data) < size:
# Add padding if necessary, rounding the whole input to a multiple of
# 512 bytes according to the third byte of the input.
# size-1 because a final byte is added below to store the checksum.
- data = data.ljust(size-1, '\0')
+ data = data.ljust(size-1, b'\0')
else:
if ord(data[-1:]) != 0:
sys.stderr.write('WARNING: ROM includes nonzero checksum\n')
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 84284d5957..9842b3bb12 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -137,7 +137,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
cap_spapr_tce_64 = kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64);
cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE);
- cap_spapr_vfio = false;
+ cap_spapr_vfio = kvm_vm_check_extension(s, KVM_CAP_SPAPR_TCE_VFIO);
cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR);
@@ -2514,6 +2514,11 @@ int kvmppc_get_cap_safe_indirect_branch(void)
return cap_ppc_safe_indirect_branch;
}
+bool kvmppc_has_cap_spapr_vfio(void)
+{
+ return cap_spapr_vfio;
+}
+
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
{
uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 39830baa77..4d2789eef6 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -46,6 +46,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
int kvmppc_reset_htab(int shift_hint);
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
+bool kvmppc_has_cap_spapr_vfio(void);
#endif /* !CONFIG_USER_ONLY */
bool kvmppc_has_cap_epr(void);
int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function);
@@ -232,6 +233,11 @@ static inline bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path)
return true;
}
+static inline bool kvmppc_has_cap_spapr_vfio(void)
+{
+ return false;
+}
+
#endif /* !CONFIG_USER_ONLY */
static inline bool kvmppc_has_cap_epr(void)
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 83def6994c..f41da235ae 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -919,10 +919,10 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
$^ >$*.test.out 2>$*.test.err; \
echo $$? >$*.test.exit, \
"TEST","$*.out")
- @diff -q $(SRC_PATH)/$*.out $*.test.out
+ @diff $(SRC_PATH)/$*.out $*.test.out
@# Sanitize error messages (make them independent of build directory)
- @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -q $(SRC_PATH)/$*.err -
- @diff -q $(SRC_PATH)/$*.exit $*.test.exit
+ @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff $(SRC_PATH)/$*.err -
+ @diff $(SRC_PATH)/$*.exit $*.test.exit
.PHONY: check-tests/qapi-schema/doc-good.texi
check-tests/qapi-schema/doc-good.texi: tests/qapi-schema/doc-good.test.texi
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 32de731675..26ede4f1d6 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -1,6 +1,6 @@
FROM fedora:latest
ENV PACKAGES \
- ccache gettext git tar PyYAML sparse flex bison python2 bzip2 hostname \
+ ccache gettext git tar PyYAML sparse flex bison python3 bzip2 hostname \
glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
gcc gcc-c++ clang make perl which bc findutils libaio-devel \
nettle-devel libasan libubsan \
@@ -12,6 +12,7 @@ ENV PACKAGES \
mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1 \
mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2 \
mingw64-bzip2
+ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3
RUN dnf install -y $PACKAGES
RUN rpm -q $PACKAGES | sort > /packages.txt
diff --git a/tests/migration-test.c b/tests/migration-test.c
index 799e24ebc6..9efad95749 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -268,10 +268,9 @@ static uint64_t get_migration_pass(QTestState *who)
static void wait_for_migration_complete(QTestState *who)
{
- QDict *rsp, *rsp_return;
- bool completed;
-
- do {
+ while (true) {
+ QDict *rsp, *rsp_return;
+ bool completed;
const char *status;
rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
@@ -280,8 +279,11 @@ static void wait_for_migration_complete(QTestState *who)
completed = strcmp(status, "completed") == 0;
g_assert_cmpstr(status, !=, "failed");
QDECREF(rsp);
- usleep(1000 * 100);
- } while (!completed);
+ if (completed) {
+ return;
+ }
+ usleep(1000);
+ }
}
static void wait_for_migration_pass(QTestState *who)
@@ -290,16 +292,13 @@ static void wait_for_migration_pass(QTestState *who)
uint64_t pass;
/* Wait for the 1st sync */
- do {
+ while (!got_stop && !initial_pass) {
+ usleep(1000);
initial_pass = get_migration_pass(who);
- if (got_stop || initial_pass) {
- break;
- }
- usleep(1000 * 100);
- } while (true);
+ }
do {
- usleep(1000 * 100);
+ usleep(1000);
pass = get_migration_pass(who);
} while (pass == initial_pass && !got_stop);
}
@@ -369,37 +368,20 @@ static void migrate_check_parameter(QTestState *who, const char *parameter,
QDECREF(rsp);
}
-static void migrate_set_downtime(QTestState *who, const double value)
+static void migrate_set_parameter(QTestState *who, const char *parameter,
+ const char *value)
{
QDict *rsp;
gchar *cmd;
- char *expected;
- int64_t result_int;
- cmd = g_strdup_printf("{ 'execute': 'migrate_set_downtime',"
- "'arguments': { 'value': %g } }", value);
+ cmd = g_strdup_printf("{ 'execute': 'migrate-set-parameters',"
+ "'arguments': { '%s': %s } }",
+ parameter, value);
rsp = qtest_qmp(who, cmd);
g_free(cmd);
g_assert(qdict_haskey(rsp, "return"));
QDECREF(rsp);
- result_int = value * 1000L;
- expected = g_strdup_printf("%" PRId64, result_int);
- migrate_check_parameter(who, "downtime-limit", expected);
- g_free(expected);
-}
-
-static void migrate_set_speed(QTestState *who, const char *value)
-{
- QDict *rsp;
- gchar *cmd;
-
- cmd = g_strdup_printf("{ 'execute': 'migrate_set_speed',"
- "'arguments': { 'value': %s } }", value);
- rsp = qtest_qmp(who, cmd);
- g_free(cmd);
- g_assert(qdict_haskey(rsp, "return"));
- QDECREF(rsp);
- migrate_check_parameter(who, "max-bandwidth", value);
+ migrate_check_parameter(who, parameter, value);
}
static void migrate_set_capability(QTestState *who, const char *capability,
@@ -433,41 +415,52 @@ static void migrate(QTestState *who, const char *uri)
QDECREF(rsp);
}
+static void migrate_start_postcopy(QTestState *who)
+{
+ QDict *rsp;
+
+ rsp = wait_command(who, "{ 'execute': 'migrate-start-postcopy' }");
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+}
+
static void test_migrate_start(QTestState **from, QTestState **to,
const char *uri)
{
gchar *cmd_src, *cmd_dst;
char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
const char *arch = qtest_get_arch();
+ const char *accel = "kvm:tcg";
got_stop = false;
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
init_bootfile_x86(bootpath);
- cmd_src = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
- " -name pcsource,debug-threads=on"
+ cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
+ " -name source,debug-threads=on"
" -serial file:%s/src_serial"
" -drive file=%s,format=raw",
- tmpfs, bootpath);
- cmd_dst = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
- " -name pcdest,debug-threads=on"
+ accel, tmpfs, bootpath);
+ cmd_dst = g_strdup_printf("-machine accel=%s -m 150M"
+ " -name target,debug-threads=on"
" -serial file:%s/dest_serial"
" -drive file=%s,format=raw"
" -incoming %s",
- tmpfs, bootpath, uri);
+ accel, tmpfs, bootpath, uri);
} else if (strcmp(arch, "ppc64") == 0) {
- const char *accel;
/* On ppc64, the test only works with kvm-hv, but not with kvm-pr */
- accel = access("/sys/module/kvm_hv", F_OK) ? "tcg" : "kvm:tcg";
+ if (access("/sys/module/kvm_hv", F_OK)) {
+ accel = "tcg";
+ }
init_bootfile_ppc(bootpath);
cmd_src = g_strdup_printf("-machine accel=%s -m 256M"
- " -name pcsource,debug-threads=on"
+ " -name source,debug-threads=on"
" -serial file:%s/src_serial"
" -drive file=%s,if=pflash,format=raw",
accel, tmpfs, bootpath);
cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
- " -name pcdest,debug-threads=on"
+ " -name target,debug-threads=on"
" -serial file:%s/dest_serial"
" -incoming %s",
accel, tmpfs, uri);
@@ -495,13 +488,13 @@ static void test_migrate_end(QTestState *from, QTestState *to)
/* Destination still running, wait for a byte to change */
do {
qtest_memread(to, start_address, &dest_byte_b, 1);
- usleep(10 * 1000);
+ usleep(1000 * 10);
} while (dest_byte_a == dest_byte_b);
qtest_qmp_discard_response(to, "{ 'execute' : 'stop'}");
/* With it stopped, check nothing changes */
qtest_memread(to, start_address, &dest_byte_c, 1);
- sleep(1);
+ usleep(1000 * 200);
qtest_memread(to, start_address, &dest_byte_d, 1);
g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
@@ -515,11 +508,55 @@ static void test_migrate_end(QTestState *from, QTestState *to)
cleanup("dest_serial");
}
+static void deprecated_set_downtime(QTestState *who, const double value)
+{
+ QDict *rsp;
+ gchar *cmd;
+ char *expected;
+ int64_t result_int;
+
+ cmd = g_strdup_printf("{ 'execute': 'migrate_set_downtime',"
+ "'arguments': { 'value': %g } }", value);
+ rsp = qtest_qmp(who, cmd);
+ g_free(cmd);
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+ result_int = value * 1000L;
+ expected = g_strdup_printf("%" PRId64, result_int);
+ migrate_check_parameter(who, "downtime-limit", expected);
+ g_free(expected);
+}
+
+static void deprecated_set_speed(QTestState *who, const char *value)
+{
+ QDict *rsp;
+ gchar *cmd;
+
+ cmd = g_strdup_printf("{ 'execute': 'migrate_set_speed',"
+ "'arguments': { 'value': %s } }", value);
+ rsp = qtest_qmp(who, cmd);
+ g_free(cmd);
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+ migrate_check_parameter(who, "max-bandwidth", value);
+}
+
+static void test_deprecated(void)
+{
+ QTestState *from;
+
+ from = qtest_start("");
+
+ deprecated_set_downtime(from, 0.12345);
+ deprecated_set_speed(from, "12345");
+
+ qtest_quit(from);
+}
+
static void test_migrate(void)
{
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
- QDict *rsp;
test_migrate_start(&from, &to, uri);
@@ -530,8 +567,8 @@ static void test_migrate(void)
* quickly, but that it doesn't complete precopy even on a slow
* machine, so also set the downtime.
*/
- migrate_set_speed(from, "100000000");
- migrate_set_downtime(from, 0.001);
+ migrate_set_parameter(from, "max-bandwidth", "100000000");
+ migrate_set_parameter(from, "downtime-limit", "1");
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
@@ -540,9 +577,7 @@ static void test_migrate(void)
wait_for_migration_pass(from);
- rsp = wait_command(from, "{ 'execute': 'migrate-start-postcopy' }");
- g_assert(qdict_haskey(rsp, "return"));
- QDECREF(rsp);
+ migrate_start_postcopy(from);
if (!got_stop) {
qtest_qmp_eventwait(from, "STOP");
@@ -578,6 +613,7 @@ int main(int argc, char **argv)
module_call_init(MODULE_INIT_QOM);
qtest_add_func("/migration/postcopy/unix", test_migrate);
+ qtest_add_func("/migration/deprecated", test_deprecated);
ret = g_test_run();
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index fe0ca08d78..ac43d3458e 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -10,6 +10,7 @@
# See the COPYING file in the top-level directory.
#
+from __future__ import print_function
from qapi import *
from pprint import pprint
import os
@@ -18,51 +19,51 @@ import sys
class QAPISchemaTestVisitor(QAPISchemaVisitor):
def visit_enum_type(self, name, info, values, prefix):
- print 'enum %s %s' % (name, values)
+ print('enum %s %s' % (name, values))
if prefix:
- print ' prefix %s' % prefix
+ print(' prefix %s' % prefix)
def visit_object_type(self, name, info, base, members, variants):
- print 'object %s' % name
+ print('object %s' % name)
if base:
- print ' base %s' % base.name
+ print(' base %s' % base.name)
for m in members:
- print ' member %s: %s optional=%s' % \
- (m.name, m.type.name, m.optional)
+ print(' member %s: %s optional=%s' % \
+ (m.name, m.type.name, m.optional))
self._print_variants(variants)
def visit_alternate_type(self, name, info, variants):
- print 'alternate %s' % name
+ print('alternate %s' % name)
self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type,
gen, success_response, boxed):
- print 'command %s %s -> %s' % \
- (name, arg_type and arg_type.name, ret_type and ret_type.name)
- print ' gen=%s success_response=%s boxed=%s' % \
- (gen, success_response, boxed)
+ print('command %s %s -> %s' % \
+ (name, arg_type and arg_type.name, ret_type and ret_type.name))
+ print(' gen=%s success_response=%s boxed=%s' % \
+ (gen, success_response, boxed))
def visit_event(self, name, info, arg_type, boxed):
- print 'event %s %s' % (name, arg_type and arg_type.name)
- print ' boxed=%s' % boxed
+ print('event %s %s' % (name, arg_type and arg_type.name))
+ print(' boxed=%s' % boxed)
@staticmethod
def _print_variants(variants):
if variants:
- print ' tag %s' % variants.tag_member.name
+ print(' tag %s' % variants.tag_member.name)
for v in variants.variants:
- print ' case %s: %s' % (v.name, v.type.name)
+ print(' case %s: %s' % (v.name, v.type.name))
schema = QAPISchema(sys.argv[1])
schema.visit(QAPISchemaTestVisitor())
for doc in schema.docs:
if doc.symbol:
- print 'doc symbol=%s' % doc.symbol
+ print('doc symbol=%s' % doc.symbol)
else:
- print 'doc freeform'
- print ' body=\n%s' % doc.body.text
- for arg, section in doc.args.iteritems():
- print ' arg=%s\n%s' % (arg, section.text)
+ print('doc freeform')
+ print(' body=\n%s' % doc.body.text)
+ for arg, section in doc.args.items():
+ print(' arg=%s\n%s' % (arg, section.text))
for section in doc.sections:
- print ' section=%s\n%s' % (section.name, section.text)
+ print(' section=%s\n%s' % (section.name, section.text))
diff --git a/ui/keycodemapdb b/ui/keycodemapdb
-Subproject 10739aa26051a5d49d88132604539d3ed085e72
+Subproject 6b3d716e2b6472eb7189d3220552280ef3d832c