From: Michael Ellerman Date: Mon, 12 Dec 2011 23:39:32 +0000 (+1100) Subject: qemu: Add spapr-vio address assignment X-Git-Tag: v0.9.9-rc1~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d64955a91a09878d4e0b709a63e0826ca562fb3a;p=thirdparty%2Flibvirt.git qemu: Add spapr-vio address assignment Add logic to assign addresses for devices with spapr-vio addresses. We also do validation of addresses specified by the user, ie. ensuring that there are not duplicate addresses on the bus. Signed-off-by: Michael Ellerman --- diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 02a456b78a..9d3bc23aaa 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -683,6 +683,89 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virBitmapPtr qemuCaps) return -1; } +static int +qemuSpaprVIOFindByReg(virDomainDefPtr def ATTRIBUTE_UNUSED, + virDomainDeviceInfoPtr info, void *opaque) +{ + virDomainDeviceInfoPtr target = opaque; + + if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) + return 0; + + /* Match a dev that has a reg, is not us, and has a matching reg */ + if (info->addr.spaprvio.has_reg && info != target && + info->addr.spaprvio.reg == target->addr.spaprvio.reg) + /* Has to be < 0 so virDomainDeviceInfoIterate() will exit */ + return -1; + + return 0; +} + +static int +qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info, + unsigned long long default_reg) +{ + bool user_reg; + int rc; + + if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) + return 0; + + /* Check if the user has assigned the reg already, if so use it */ + user_reg = info->addr.spaprvio.has_reg; + if (!user_reg) { + info->addr.spaprvio.reg = default_reg; + info->addr.spaprvio.has_reg = true; + } + + rc = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info); + while (rc != 0) { + if (user_reg) { + qemuReportError(VIR_ERR_XML_ERROR, + _("spapr-vio address %#llx already in use"), + info->addr.spaprvio.reg); + return -EEXIST; + } + + /* We assigned the reg, so try a new value */ + info->addr.spaprvio.reg += 0x1000; + rc = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info); + } + + return 0; +} + +static int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def) +{ + int i, rc; + + /* Default values match QEMU. See spapr_(llan|vscsi|vty).c */ + + for (i = 0 ; i < def->nnets; i++) { + rc = qemuAssignSpaprVIOAddress(def, &def->nets[i]->info, + 0x1000ul); + if (rc) + return rc; + } + + for (i = 0 ; i < def->ncontrollers; i++) { + rc = qemuAssignSpaprVIOAddress(def, &def->controllers[i]->info, + 0x2000ul); + if (rc) + return rc; + } + + for (i = 0 ; i < def->nserials; i++) { + rc = qemuAssignSpaprVIOAddress(def, &def->serials[i]->info, + 0x30000000ul); + if (rc) + return rc; + } + + /* No other devices are currently supported on spapr-vio */ + + return 0; +} #define QEMU_PCI_ADDRESS_LAST_SLOT 31 #define QEMU_PCI_ADDRESS_LAST_FUNCTION 8 @@ -812,6 +895,12 @@ cleanup: int qemuDomainAssignAddresses(virDomainDefPtr def) { + int rc; + + rc = qemuDomainAssignSpaprVIOAddresses(def); + if (rc) + return rc; + return qemuDomainAssignPCIAddresses(def); }