Auto-assign PCI addresses

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
This commit is contained in:
Daniel P. Berrange 2010-01-07 19:25:41 +00:00
parent febc591683
commit a44d0dc26c
6 changed files with 121 additions and 8 deletions

View File

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

View File

@ -2708,6 +2708,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);
@ -2931,8 +2936,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) {

View File

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

View File

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

View File

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

View File

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