#include "virlog.h"
#include "virstring.h"
#include "domain_addr.h"
+#include "virhashcode.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
addrs->buses[addr->bus].slot[addr->slot].functions &= ~(1 << addr->function);
}
+
+static uint32_t
+virZPCIAddrKeyCode(const void *name,
+ uint32_t seed)
+{
+ unsigned int value = *((unsigned int *)name);
+ return virHashCodeGen(&value, sizeof(value), seed);
+}
+
+
+static bool
+virZPCIAddrKeyEqual(const void *namea,
+ const void *nameb)
+{
+ return *((unsigned int *)namea) == *((unsigned int *)nameb);
+}
+
+
+static void *
+virZPCIAddrKeyCopy(const void *name)
+{
+ unsigned int *copy;
+
+ if (VIR_ALLOC(copy) < 0)
+ return NULL;
+
+ *copy = *((unsigned int *)name);
+ return (void *)copy;
+}
+
+
+static void
+virZPCIAddrKeyFree(void *name)
+{
+ VIR_FREE(name);
+}
+
+
+static void
+virDomainPCIAddressSetExtensionFree(virDomainPCIAddressSetPtr addrs)
+{
+ if (!addrs || !addrs->zpciIds)
+ return;
+
+ virHashFree(addrs->zpciIds->uids);
+ virHashFree(addrs->zpciIds->fids);
+ VIR_FREE(addrs->zpciIds);
+}
+
+
+static int
+virDomainPCIAddressSetExtensionAlloc(virDomainPCIAddressSetPtr addrs,
+ virPCIDeviceAddressExtensionFlags extFlags)
+{
+ if (extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
+ if (addrs->zpciIds)
+ return 0;
+
+ if (VIR_ALLOC(addrs->zpciIds) < 0)
+ return -1;
+
+ if (!(addrs->zpciIds->uids = virHashCreateFull(10, NULL,
+ virZPCIAddrKeyCode,
+ virZPCIAddrKeyEqual,
+ virZPCIAddrKeyCopy,
+ virZPCIAddrKeyFree)))
+ goto error;
+
+ if (!(addrs->zpciIds->fids = virHashCreateFull(10, NULL,
+ virZPCIAddrKeyCode,
+ virZPCIAddrKeyEqual,
+ virZPCIAddrKeyCopy,
+ virZPCIAddrKeyFree)))
+ goto error;
+ }
+
+ return 0;
+
+ error:
+ virDomainPCIAddressSetExtensionFree(addrs);
+ return -1;
+}
+
+
virDomainPCIAddressSetPtr
-virDomainPCIAddressSetAlloc(unsigned int nbuses)
+virDomainPCIAddressSetAlloc(unsigned int nbuses,
+ virPCIDeviceAddressExtensionFlags extFlags)
{
virDomainPCIAddressSetPtr addrs;
goto error;
addrs->nbuses = nbuses;
+
+ if (virDomainPCIAddressSetExtensionAlloc(addrs, extFlags) < 0)
+ goto error;
+
return addrs;
error:
if (!addrs)
return;
+ virDomainPCIAddressSetExtensionFree(addrs);
VIR_FREE(addrs->buses);
VIR_FREE(addrs);
}
} virDomainPCIAddressBus;
typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
+typedef struct {
+ virHashTablePtr uids;
+ virHashTablePtr fids;
+} virDomainZPCIAddressIds;
+typedef virDomainZPCIAddressIds *virDomainZPCIAddressIdsPtr;
+
struct _virDomainPCIAddressSet {
virDomainPCIAddressBus *buses;
size_t nbuses;
bool areMultipleRootsSupported;
/* If true, the guest can use the pcie-to-pci-bridge controller */
bool isPCIeToPCIBridgeSupported;
+ virDomainZPCIAddressIdsPtr zpciIds;
};
typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet;
typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
-virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses);
+virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses,
+ virPCIDeviceAddressExtensionFlags extFlags);
void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
size_t i;
bool hasPCIeRoot = false;
virDomainControllerModelPCI defaultModel;
+ virPCIDeviceAddressExtensionFlags extFlags = VIR_PCI_ADDRESS_EXTENSION_NONE;
- if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI))
+ extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
+
+ if ((addrs = virDomainPCIAddressSetAlloc(nbuses, extFlags)) == NULL)
return NULL;
addrs->dryRun = dryRun;