QEMU commit 3984890 introduced the "pci-hole64-size" property,
to i440FX-pcihost and q35-pcihost with a default setting of 2 GB.
Translate <pcihole64>x<pcihole64/> to:
-global q35-pcihost.pci-hole64-size=x for q35 machines and
-global i440FX-pcihost.pci-hole64-size=x for i440FX-based machines.
Error out on other machine types or if the size was specified
but the pcihost device lacks 'pci-hole64-size' property.
https://bugzilla.redhat.com/show_bug.cgi?id=990418
---
src/qemu/qemu_capabilities.c | 14 ++++++
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 58 ++++++++++++++++++++++
.../qemuxml2argv-pcihole64-none.args | 4 ++
.../qemuxml2argv-pcihole64-q35.args | 9 ++++
tests/qemuxml2argvdata/qemuxml2argv-pcihole64.args | 5 ++
tests/qemuxml2argvtest.c | 10 ++++
7 files changed, 102 insertions(+)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcihole64-none.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcihole64.args
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 47cc07a..87c9a96 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -235,6 +235,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"vnc-share-policy", /* 150 */
"device-del-event",
"dmi-to-pci-bridge",
+ "i440fx-pci-hole64-size",
+ "q35-pci-hole64-size",
);
struct _virQEMUCaps {
@@ -1436,6 +1438,14 @@ static struct virQEMUCapsStringFlags
virQEMUCapsObjectPropsScsiGeneric[] = {
{ "bootindex", QEMU_CAPS_DEVICE_SCSI_GENERIC_BOOTINDEX },
};
+static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsI440FXPciHost[] = {
+ { "pci-hole64-size", QEMU_CAPS_I440FX_PCI_HOLE64_SIZE },
+};
+
+static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsQ35PciHost[] = {
+ { "pci-hole64-size", QEMU_CAPS_Q35_PCI_HOLE64_SIZE },
+};
+
struct virQEMUCapsObjectTypeProps {
const char *type;
struct virQEMUCapsStringFlags *props;
@@ -1473,6 +1483,10 @@ static struct virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] =
{
ARRAY_CARDINALITY(virQEMUCapsObjectPropsUsbHost) },
{ "scsi-generic", virQEMUCapsObjectPropsScsiGeneric,
ARRAY_CARDINALITY(virQEMUCapsObjectPropsScsiGeneric) },
+ { "i440FX-pcihost", virQEMUCapsObjectPropsI440FXPciHost,
+ ARRAY_CARDINALITY(virQEMUCapsObjectPropsI440FXPciHost) },
+ { "q35-pcihost", virQEMUCapsObjectPropsQ35PciHost,
+ ARRAY_CARDINALITY(virQEMUCapsObjectPropsQ35PciHost) },
};
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 074e55d..69f3395 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -191,6 +191,8 @@ enum virQEMUCapsFlags {
QEMU_CAPS_VNC_SHARE_POLICY = 150, /* set display sharing policy */
QEMU_CAPS_DEVICE_DEL_EVENT = 151, /* DEVICE_DELETED event */
QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE = 152, /* -device i82801b11-bridge */
+ QEMU_CAPS_I440FX_PCI_HOLE64_SIZE = 153, /* i440FX-pcihost.pci-hole64-size */
+ QEMU_CAPS_Q35_PCI_HOLE64_SIZE = 154, /* q35-pcihost.pci-hole64-size */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8b628d6..5ad73fd 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2399,6 +2399,17 @@ qemuDomainMachineIsQ35(virDomainDefPtr def)
}
+static bool
+qemuDomainMachineIsI440FX(virDomainDefPtr def)
+{
+ return (STREQ(def->os.machine, "pc") ||
+ STRPREFIX(def->os.machine, "pc-0.") ||
+ STRPREFIX(def->os.machine, "pc-1.") ||
+ STRPREFIX(def->os.machine, "pc-i440") ||
+ STRPREFIX(def->os.machine, "rhel"));
+}
+
+
static int
qemuDomainValidateDevicePCISlotsQ35(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
@@ -7919,6 +7930,53 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandAddArgList(cmd, "-bootloader", def->os.bootloader, NULL);
}
+ for (i = 0; i < def->ncontrollers; i++) {
+ virDomainControllerDefPtr cont = def->controllers[i];
+ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
+ cont->opts.pciopts.pcihole64) {
+ const char *hoststr = NULL;
+ bool cap = false;
+ bool machine = false;
+
+ switch (cont->model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+ hoststr = "i440FX-pcihost";
+ cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_I440FX_PCI_HOLE64_SIZE);
+ machine = qemuDomainMachineIsI440FX(def);
+ break;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
+ hoststr = "q35-pcihost";
+ cap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_Q35_PCI_HOLE64_SIZE);
+ machine = qemuDomainMachineIsQ35(def);
+ break;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("64-bit PCI hole setting is only for root"
+ " PCI controllers"));
+ goto error;
+ }
+
+ if (!machine) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Setting the 64-bit PCI hole size is not "
+ "supported for machine '%s'"),
def->os.machine);
+ goto error;
+ }
+ if (!cap) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("64-bit PCI hole size setting is not supported
"
+ "with this QEMU binary"));
+ goto error;
+ }
+
+ virCommandAddArg(cmd, "-global");
+ virCommandAddArgFormat(cmd, "%s.pci-hole64-size=%luK", hoststr,
+ cont->opts.pciopts.pcihole64size);
+ }
+ }
+
for (i = 0; i < def->ndisks; i++) {
virDomainDiskDefPtr disk = def->disks[i];
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-none.args
b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-none.args
new file mode 100644
index 0000000..e878d2f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-none.args
@@ -0,0 +1,4 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/libexec/qemu-kvm -S -M pc-1.2 -m 2048 -smp 2 -nographic -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args
b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args
new file mode 100644
index 0000000..6d33b65
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64-q35.args
@@ -0,0 +1,9 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/libexec/qemu-kvm -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi \
+-boot c -global q35-pcihost.pci-hole64-size=1048576K \
+-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x2 \
+-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-sata0-0-0 \
+-device ide-drive,unit=0,drive=drive-sata0-0-0,id=sata0-0-0 \
+-vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcihole64.args
b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64.args
new file mode 100644
index 0000000..3165139
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pcihole64.args
@@ -0,0 +1,5 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/libexec/qemu-kvm -S -M pc-1.2 -m 2048 -smp 2 -nographic -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi \
+-boot c -global i440FX-pcihost.pci-hole64-size=1048576K -usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 679124e..f274ced 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1037,6 +1037,16 @@ mymain(void)
DO_TEST_PARSE_ERROR("pci-root-address",
QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
+ DO_TEST("pcihole64", QEMU_CAPS_DEVICE, QEMU_CAPS_I440FX_PCI_HOLE64_SIZE);
+ DO_TEST_FAILURE("pcihole64-none", QEMU_CAPS_DEVICE);
+ DO_TEST("pcihole64-q35",
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+ QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+ QEMU_CAPS_DRIVE, QEMU_CAPS_ICH9_AHCI,
+ QEMU_CAPS_VGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
+ QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL,
+ QEMU_CAPS_Q35_PCI_HOLE64_SIZE);
+
virObjectUnref(driver.config);
virObjectUnref(driver.caps);
virObjectUnref(driver.xmlopt);
--
1.8.1.5