Skip to content

Commit

Permalink
qemu: auto-add pci-root controller for pc machine types
Browse files Browse the repository at this point in the history
<controller type='pci' index='0' model='pci-root'/>
is auto-added to pc* machine types.
Without this controller PCI bus 0 is not available and
no PCI addresses are assigned by default.

Since older libvirt supported PCI bus 0 even without
this controller, it is removed from the XML when migrating.
  • Loading branch information
janotomko committed Apr 25, 2013
1 parent d350a34 commit b33eb0d
Show file tree
Hide file tree
Showing 163 changed files with 277 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/conf/domain_conf.c
Expand Up @@ -9811,7 +9811,7 @@ virDomainLookupVcpuPin(virDomainDefPtr def,
return NULL;
}

static int
int
virDomainDefMaybeAddController(virDomainDefPtr def,
int type,
int idx,
Expand Down
6 changes: 6 additions & 0 deletions src/conf/domain_conf.h
Expand Up @@ -2563,6 +2563,12 @@ int virDomainObjListExport(virDomainObjListPtr doms,
virDomainVcpuPinDefPtr virDomainLookupVcpuPin(virDomainDefPtr def,
int vcpuid);

int
virDomainDefMaybeAddController(virDomainDefPtr def,
int type,
int idx,
int model);

char *virDomainDefGetDefaultEmulator(virDomainDefPtr def, virCapsPtr caps);

#endif /* __DOMAIN_CONF_H */
1 change: 1 addition & 0 deletions src/libvirt_private.syms
Expand Up @@ -116,6 +116,7 @@ virDomainDefFree;
virDomainDefGenSecurityLabelDef;
virDomainDefGetDefaultEmulator;
virDomainDefGetSecurityLabelDef;
virDomainDefMaybeAddController;
virDomainDefParseFile;
virDomainDefParseNode;
virDomainDefParseString;
Expand Down
57 changes: 39 additions & 18 deletions src/qemu/qemu_command.c
Expand Up @@ -1209,6 +1209,7 @@ typedef uint8_t qemuDomainPCIAddressBus[QEMU_PCI_ADDRESS_SLOT_LAST];
struct _qemuDomainPCIAddressSet {
qemuDomainPCIAddressBus *used;
virDevicePCIAddress lastaddr;
size_t nbuses; /* allocation of 'used' */
};


Expand All @@ -1219,6 +1220,10 @@ struct _qemuDomainPCIAddressSet {
static bool qemuPCIAddressValidate(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UNUSED,
virDevicePCIAddressPtr addr)
{
if (addrs->nbuses == 0) {
virReportError(VIR_ERR_XML_ERROR, "%s", _("No PCI buses available"));
return false;
}
if (addr->domain != 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Only PCI domain 0 is available"));
Expand Down Expand Up @@ -1334,7 +1339,15 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
qemuDomainObjPrivatePtr priv = NULL;

if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
if (!(addrs = qemuDomainPCIAddressSetCreate(def)))
int nbuses = 0;
int i;

for (i = 0; i < def->ncontrollers; i++) {
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
nbuses++;
}

if (!(addrs = qemuDomainPCIAddressSetCreate(def, nbuses)))
goto cleanup;

if (qemuAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
Expand Down Expand Up @@ -1379,16 +1392,25 @@ int qemuDomainAssignAddresses(virDomainDefPtr def,
return qemuDomainAssignPCIAddresses(def, qemuCaps, obj);
}

qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def)
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
unsigned int nbuses)
{
qemuDomainPCIAddressSetPtr addrs;
int i;

if (VIR_ALLOC(addrs) < 0)
goto no_memory;

if (VIR_ALLOC_N(addrs->used, 1) < 0)
if (VIR_ALLOC_N(addrs->used, nbuses) < 0)
goto no_memory;

addrs->nbuses = nbuses;

/* reserve slot 0 in every bus - it's used by the host bridge on bus 0
* and unusable on PCI bridges */
for (i = 0; i < nbuses; i++)
addrs->used[i][0] = 0xFF;

if (virDomainDeviceInfoIterate(def, qemuCollectPCIAddress, addrs) < 0)
goto error;

Expand Down Expand Up @@ -1617,12 +1639,6 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
virDevicePCIAddressPtr addrptr;
unsigned int *func = &tmp_addr.function;


/* Reserve slot 0 for the host bridge */
memset(&tmp_addr, 0, sizeof(tmp_addr));
if (qemuDomainPCIAddressReserveSlot(addrs, &tmp_addr) < 0)
goto error;

/* Verify that first IDE and USB controllers (if any) is on the PIIX3, fn 1 */
for (i = 0; i < def->ncontrollers ; i++) {
/* First IDE controller lives on the PIIX3 at slot=1, function=1 */
Expand Down Expand Up @@ -1674,16 +1690,18 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
/* PIIX3 (ISA bridge, IDE controller, something else unknown, USB controller)
* hardcoded slot=1, multifunction device
*/
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 1;
for (*func = 0; *func < QEMU_PCI_ADDRESS_FUNCTION_LAST; (*func)++) {
if ((*func == 1 && reservedIDE) ||
(*func == 2 && reservedUSB))
/* we have reserved this pci address */
continue;
if (addrs->nbuses) {
memset(&tmp_addr, 0, sizeof(tmp_addr));
tmp_addr.slot = 1;
for (*func = 0; *func < QEMU_PCI_ADDRESS_FUNCTION_LAST; (*func)++) {
if ((*func == 1 && reservedIDE) ||
(*func == 2 && reservedUSB))
/* we have reserved this pci address */
continue;

if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr) < 0)
goto error;
if (qemuDomainPCIAddressReserveAddr(addrs, &tmp_addr) < 0)
goto error;
}
}

if (def->nvideos > 0) {
Expand Down Expand Up @@ -1775,6 +1793,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,

/* Device controllers (SCSI, USB, but not IDE, FDC or CCID) */
for (i = 0; i < def->ncontrollers ; i++) {
/* PCI root has no address */
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
continue;
/* FDC lives behind the ISA bridge; CCID is a usb device */
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC ||
def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID)
Expand Down
3 changes: 2 additions & 1 deletion src/qemu/qemu_command.h
Expand Up @@ -196,7 +196,8 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
int qemuDomainAssignPCIAddresses(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
virDomainObjPtr obj);
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
unsigned int nbuses);
int qemuDomainPCIAddressReserveSlot(qemuDomainPCIAddressSetPtr addrs,
virDevicePCIAddressPtr addr);
int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
Expand Down
74 changes: 71 additions & 3 deletions src/qemu/qemu_domain.c
Expand Up @@ -668,11 +668,49 @@ qemuDomainDefPostParse(virDomainDefPtr def,
virCapsPtr caps,
void *opaque ATTRIBUTE_UNUSED)
{
bool addPCIRoot = false;

/* check for emulator and create a default one if needed */
if (!def->emulator &&
!(def->emulator = virDomainDefGetDefaultEmulator(def, caps)))
return -1;

/* Add implicit PCI root controller if the machine has one */
switch (def->os.arch) {
case VIR_ARCH_I686:
case VIR_ARCH_X86_64:
if (!def->os.machine)
break;
if (STRPREFIX(def->os.machine, "pc-q35") ||
STREQ(def->os.machine, "q35") ||
STREQ(def->os.machine, "isapc"))
break;
if (!STRPREFIX(def->os.machine, "pc-0.") &&
!STRPREFIX(def->os.machine, "pc-1.") &&
!STREQ(def->os.machine, "pc") &&
!STRPREFIX(def->os.machine, "rhel"))
break;
addPCIRoot = true;
break;

case VIR_ARCH_ALPHA:
case VIR_ARCH_PPC:
case VIR_ARCH_PPC64:
case VIR_ARCH_PPCEMB:
case VIR_ARCH_SH4:
case VIR_ARCH_SH4EB:
addPCIRoot = true;
break;
default:
break;
}

if (addPCIRoot &&
virDomainDefMaybeAddController(
def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
return -1;

return 0;
}

Expand Down Expand Up @@ -1255,7 +1293,8 @@ qemuDomainDefFormatBuf(virQEMUDriverPtr driver,

if ((flags & VIR_DOMAIN_XML_MIGRATABLE)) {
int i;
virDomainControllerDefPtr usb = NULL;
int remove = 0;
virDomainControllerDefPtr usb = NULL, pci = NULL;

/* If only the default USB controller is present, we can remove it
* and make the XML compatible with older versions of libvirt which
Expand All @@ -1274,20 +1313,49 @@ qemuDomainDefFormatBuf(virQEMUDriverPtr driver,
if (usb && usb->idx == 0 && usb->model == -1) {
VIR_DEBUG("Removing default USB controller from domain '%s'"
" for migration compatibility", def->name);
remove++;
} else {
usb = NULL;
}

/* Remove the default PCI controller if there is only one present
* and its model is pci-root */
for (i = 0; i < def->ncontrollers; i++) {
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
if (pci) {
pci = NULL;
break;
}
pci = def->controllers[i];
}
}

if (pci && pci->idx == 0 &&
pci->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
VIR_DEBUG("Removing default 'pci-root' from domain '%s'"
" for migration compatibility", def->name);
remove++;
} else {
pci = NULL;
}

if (remove) {
controllers = def->controllers;
ncontrollers = def->ncontrollers;
if (VIR_ALLOC_N(def->controllers, ncontrollers - 1) < 0) {
if (VIR_ALLOC_N(def->controllers, ncontrollers - remove) < 0) {
controllers = NULL;
virReportOOMError();
goto cleanup;
}

def->ncontrollers = 0;
for (i = 0; i < ncontrollers; i++) {
if (controllers[i] != usb)
if (controllers[i] != usb && controllers[i] != pci)
def->controllers[def->ncontrollers++] = controllers[i];
}
}


}

ret = virDomainDefFormatInternal(def, flags, buf);
Expand Down
1 change: 1 addition & 0 deletions tests/domainsnapshotxml2xmlout/disk_snapshot.xml
Expand Up @@ -72,6 +72,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
Expand Down
1 change: 1 addition & 0 deletions tests/domainsnapshotxml2xmlout/external_vm.xml
Expand Up @@ -37,6 +37,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
Expand Down
1 change: 1 addition & 0 deletions tests/domainsnapshotxml2xmlout/full_domain.xml
Expand Up @@ -30,6 +30,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
Expand Down
1 change: 1 addition & 0 deletions tests/domainsnapshotxml2xmlout/metadata.xml
Expand Up @@ -34,6 +34,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
Expand Down
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-blkdeviotune.xml
Expand Up @@ -37,6 +37,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml
Expand Up @@ -32,6 +32,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-blkiotune.xml
Expand Up @@ -24,6 +24,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-boot-cdrom.xml
Expand Up @@ -23,6 +23,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-boot-floppy.xml
Expand Up @@ -29,6 +29,7 @@
<controller type='usb' index='0'/>
<controller type='fdc' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.xml
Expand Up @@ -23,6 +23,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml
Expand Up @@ -26,6 +26,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-boot-network.xml
Expand Up @@ -22,6 +22,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-boot-order.xml
Expand Up @@ -43,6 +43,7 @@
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='fdc' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<interface type='user'>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
Expand Down
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-channel-guestfwd.xml
Expand Up @@ -21,6 +21,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<channel type='pipe'>
<source path='/tmp/guestfwd'/>
<target type='guestfwd' address='10.0.2.1' port='4600'/>
Expand Down
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml
Expand Up @@ -24,6 +24,7 @@
<controller type='virtio-serial' index='1'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<channel type='pty'>
<target type='virtio' name='org.linux-kvm.port.foo'/>
<address type='virtio-serial' controller='1' bus='0' port='3'/>
Expand Down
1 change: 1 addition & 0 deletions tests/qemuxml2argvdata/qemuxml2argv-clock-localtime.xml
Expand Up @@ -22,6 +22,7 @@
</disk>
<controller type='usb' index='0'/>
<controller type='ide' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>

0 comments on commit b33eb0d

Please sign in to comment.