Instead of relying on QEMU to assign PCI addresses and then querying them with 'info pci', manually assign all PCI addresses before starting the guest. These addresses are not stable across reboots. That will come in a later patch NB, the PIIX3 (IDE, FDC, ISA-Bridge) will always have slot 1 and VGA will always have slot 2. We declare the Virtio Balloon gets slot 3, and then all remaining slots are for configured devices. * src/qemu/qemu_conf.c: If -device is supported, then assign all PCI addresses when building the command line * src/qemu/qemu_driver.c: Don't query monitor for PCI addresses if they have already been assigned * tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args, tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args, tests/qemuxml2argvdata/qemuxml2argv-sound-device.args, tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args: Update to include PCI slot/bus information --- src/qemu/qemu_conf.c | 108 +++++++++++++++++++- src/qemu/qemu_driver.c | 13 ++- .../qemuxml2argv-hostdev-pci-address-device.args | 2 +- .../qemuxml2argv-net-virtio-device.args | 2 +- .../qemuxml2argv-sound-device.args | 2 +- .../qemuxml2argv-watchdog-device.args | 2 +- 6 files changed, 121 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index bb6e90f..415e6da 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1547,6 +1547,108 @@ qemuAssignDeviceAliases(virDomainDefPtr def) } +static void +qemuAssignDevicePCISlot(virDomainDeviceInfoPtr info, + int slot) +{ + info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + info->addr.pci.domain = 0; + info->addr.pci.bus = 0; + info->addr.pci.slot = slot; + info->addr.pci.function = 0; +} + +static void +qemuAssignDevicePCISlots(virDomainDefPtr def) +{ + int i; + /* + * slot = 0 -> Host bridge + * slot = 1 -> PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller) + * slot = 2 -> VGA + * slot = 3 -> VirtIO Balloon + */ + int nextslot = 4; + + for (i = 0; i < def->ndisks ; i++) { + if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + continue; + + /* Only VirtIO disks use PCI addrs */ + if (def->disks[i]->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) + continue; + + qemuAssignDevicePCISlot(&def->disks[i]->info, nextslot++); + } + + for (i = 0; i < def->nnets ; i++) { + if (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + continue; + qemuAssignDevicePCISlot(&def->nets[i]->info, nextslot++); + } + + for (i = 0; i < def->nsounds ; i++) { + if (def->sounds[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + continue; + /* Skip ISA sound card, and PCSPK */ + if (def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_SB16 || + def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) + continue; + + qemuAssignDevicePCISlot(&def->sounds[i]->info, nextslot++); + } + + for (i = 0; i < def->nhostdevs ; i++) { + if (def->hostdevs[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + continue; + if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) + continue; + + qemuAssignDevicePCISlot(&def->hostdevs[i]->info, nextslot++); + } + for (i = 0; i < def->nvideos ; i++) { + /* First VGA is hardcoded slot=2 */ + if (i == 0) + qemuAssignDevicePCISlot(&def->videos[i]->info, 2); + else + qemuAssignDevicePCISlot(&def->videos[i]->info, nextslot++); + } + for (i = 0; i < def->ncontrollers ; i++) { + if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) + continue; + /* FDC lives behind the ISA bridge */ + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC) + continue; + + /* First IDE controller lives on the PIIX3 at slot=1, function=1 */ + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE && + def->controllers[i]->idx == 0) { + qemuAssignDevicePCISlot(&def->controllers[i]->info, 1); + def->controllers[i]->info.addr.pci.function = 1; + } else { + qemuAssignDevicePCISlot(&def->controllers[i]->info, nextslot++); + } + } + for (i = 0; i < def->ninputs ; i++) { + /* Nada - none are PCI based (yet) */ + } + for (i = 0; i < def->nparallels ; i++) { + /* Nada - none are PCI based (yet) */ + } + for (i = 0; i < def->nserials ; i++) { + /* Nada - none are PCI based (yet) */ + } + for (i = 0; i < def->nchannels ; i++) { + /* Nada - none are PCI based (yet) */ + /* XXX virtio-serial will need one */ + } + if (def->watchdog) { + qemuAssignDevicePCISlot(&def->watchdog->info, nextslot++); + } +} + + static char *qemuDiskLegacyName(const virDomainDiskDefPtr disk) { char *devname; @@ -2609,10 +2711,12 @@ int qemudBuildCommandLine(virConnectPtr conn, uname_normalize(&ut); - if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) + if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { qemuAssignDeviceAliases(def); - else + qemuAssignDevicePCISlots(def); + } else { qemuAssignDiskAliases(def, qemuCmdFlags); + } virUUIDFormat(def->uuid, uuid); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 6aabe3e..3d33da3 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2697,6 +2697,11 @@ qemuPrepareMonitorChr(virConnectPtr conn, monConfig->type = VIR_DOMAIN_CHR_TYPE_UNIX; monConfig->data.nix.listen = 1; + if (!(monConfig->info.alias = strdup("monitor"))) { + virReportOOMError(conn); + return -1; + } + if (virAsprintf(&monConfig->data.nix.path, "%s/%s.monitor", driver->libDir, vm) < 0) { virReportOOMError(conn); @@ -2920,8 +2925,12 @@ static int qemudStartVMDaemon(virConnectPtr conn, if (qemuInitPasswords(driver, vm) < 0) goto abort; - if (qemuInitPCIAddresses(driver, vm) < 0) - goto abort; + /* If we have -device, then addresses are assigned explicitly. + * If not, then we have to detect dynamic ones here */ + if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) { + if (qemuInitPCIAddresses(driver, vm) < 0) + goto abort; + } qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuMonitorSetBalloon(priv->mon, vm->def->memory) < 0) { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args index f1865ee..611950a 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address-device.args @@ -1 +1 @@ -LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest2 -usb -device pci-assign,host=06:12.5,id=hostpci0 +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest2 -usb -device pci-assign,host=06:12.5,id=hostpci0,addr=4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args index 2b5e856..9324047 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-device.args @@ -1 +1 @@ -LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -netdev user,id=netdev0 -device virtio-net-pci,netdev=netdev0,id=virtio-nic0,mac=00:11:22:33:44:55 -usb +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -netdev user,id=netdev0 -device virtio-net-pci,netdev=netdev0,id=virtio-nic0,mac=00:11:22:33:44:55,addr=4 -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args index 31ac0ee..b9adec6 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-sound-device.args @@ -1 +1 @@ -LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -soundhw pcspk -device ES1370,id=sound1 -device sb16,id=sound2 -device AC97,id=sound3 +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -soundhw pcspk -device ES1370,id=sound1,addr=4 -device sb16,id=sound2 -device AC97,id=sound3,addr=5 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args b/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args index 5f3a428..f05111c 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-watchdog-device.args @@ -1 +1 @@ -LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -device ib700,id=watchdog0 -watchdog-action poweroff +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -device ib700,id=watchdog0,addr=4 -watchdog-action poweroff -- 1.6.5.2 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list