Build QEMU command line for pcihole64

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
This commit is contained in:
Ján Tomko 2013-08-12 13:48:34 +02:00
parent 01cda91809
commit 63ee776f8c
7 changed files with 102 additions and 0 deletions

View File

@ -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) },
};

View File

@ -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 */
};

View File

@ -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,
@ -7952,6 +7963,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];

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1047,6 +1047,16 @@ mymain(void)
QEMU_CAPS_KVM, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
QEMU_CAPS_VIRTIO_SCSI);
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);