Marek Marczykowski wrote: > For now only for PCI devices. Mostly copy-paste from old xen driver. > This one is (or will be) covered by Chanyan's work as well right? Regards, Jim > --- > src/libxl/libxl_driver.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 193 insertions(+) > > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index 40a7a6b..011edf8 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -42,6 +42,7 @@ > #include "libxl.h" > #include "libxl_driver.h" > #include "libxl_conf.h" > +#include "node_device_conf.h" > #include "xen_xm.h" > #include "virtypedparam.h" > #include "viruri.h" > @@ -3666,6 +3667,195 @@ libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, > return libxlDomainModifyDeviceFlags(dom, xml, flags, LIBXL_DEVICE_UPDATE); > } > > +static int > +libxlNodeDeviceGetPciInfo(virNodeDevicePtr dev, > + unsigned *domain, > + unsigned *bus, > + unsigned *slot, > + unsigned *function) > +{ > + virNodeDeviceDefPtr def = NULL; > + virNodeDevCapsDefPtr cap; > + char *xml = NULL; > + int ret = -1; > + > + xml = virNodeDeviceGetXMLDesc(dev, 0); > + if (!xml) > + goto out; > + > + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); > + if (!def) > + goto out; > + > + cap = def->caps; > + while (cap) { > + if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) { > + *domain = cap->data.pci_dev.domain; > + *bus = cap->data.pci_dev.bus; > + *slot = cap->data.pci_dev.slot; > + *function = cap->data.pci_dev.function; > + break; > + } > + > + cap = cap->next; > + } > + > + if (!cap) { > + virReportError(VIR_ERR_INVALID_ARG, > + _("device %s is not a PCI device"), dev->name); > + goto out; > + } > + > + ret = 0; > +out: > + virNodeDeviceDefFree(def); > + VIR_FREE(xml); > + return ret; > +} > + > +static int > +libxlNodeDeviceDettach(virNodeDevicePtr dev) > +{ > + virPCIDevicePtr pci; > + unsigned domain, bus, slot, function; > + int ret = -1; > + > + if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) > + return -1; > + > + pci = virPCIDeviceNew(domain, bus, slot, function); > + if (!pci) > + return -1; > + > + if (virPCIDeviceDetach(pci, NULL, NULL, "pciback") < 0) > + goto out; > + > + ret = 0; > +out: > + virPCIDeviceFree(pci); > + return ret; > +} > + > +static int > +libxlNodeDeviceAssignedDomainId(virNodeDevicePtr dev) > +{ > + int numdomains; > + int numpcidevs; > + int ret = -1, i, j; > + int *ids = NULL; > + char *bdf = NULL; > + char *xref = NULL; > + unsigned int domain, bus, slot, function; > + libxl_device_pci *pcidevs = NULL; > + virConnectPtr conn = dev->conn; > + libxlDriverPrivatePtr driver = conn->privateData; > + > + /* Get active domains */ > + numdomains = libxlNumDomains(conn); > + if (numdomains < 0) { > + return ret; > + } > + if (numdomains > 0){ > + if (VIR_ALLOC_N(ids, numdomains) < 0) { > + virReportOOMError(); > + goto out; > + } > + if ((numdomains = libxlListDomains(conn, &ids[0], numdomains)) < 0) { > + goto out; > + } > + } > + > + /* Get pci bdf */ > + if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) > + goto out; > + > + if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x", > + domain, bus, slot, function) < 0) { > + virReportOOMError(); > + goto out; > + } > + > + libxlDriverLock(driver); > + /* Check if bdf is assigned to one of active domains */ > + for (i = 0; i < numdomains; i++) { > + pcidevs = libxl_device_pci_list(driver->ctx, ids[i], &numpcidevs); > + if (pcidevs == NULL) { > + continue; > + } else { > + for (j = 0; j < numpcidevs; j++) { > + if (pcidevs[j].bus == bus && pcidevs[j].dev == slot && pcidevs[j].func == function) { > + ret = ids[i]; > + break; > + } > + } > + VIR_FREE(pcidevs); > + } > + } > + libxlDriverUnlock(driver); > + > + VIR_FREE(xref); > + VIR_FREE(bdf); > +out: > + VIR_FREE(ids); > + > + return ret; > +} > + > +static int > +libxlNodeDeviceReAttach(virNodeDevicePtr dev) > +{ > + virPCIDevicePtr pci; > + unsigned domain, bus, slot, function; > + int ret = -1; > + int domid; > + > + if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) > + return -1; > + > + pci = virPCIDeviceNew(domain, bus, slot, function); > + if (!pci) > + return -1; > + > + /* Check if device is assigned to an active guest */ > + if ((domid = libxlNodeDeviceAssignedDomainId(dev)) >= 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Device %s has been assigned to guest %d"), > + dev->name, domid); > + goto out; > + } > + > + if (virPCIDeviceReattach(pci, NULL, NULL, "pciback") < 0) > + goto out; > + > + ret = 0; > +out: > + virPCIDeviceFree(pci); > + return ret; > +} > + > +static int > +libxlNodeDeviceReset(virNodeDevicePtr dev) > +{ > + virPCIDevicePtr pci; > + unsigned domain, bus, slot, function; > + int ret = -1; > + > + if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) > + return -1; > + > + pci = virPCIDeviceNew(domain, bus, slot, function); > + if (!pci) > + return -1; > + > + if (virPCIDeviceReset(pci, NULL, NULL) < 0) > + goto out; > + > + ret = 0; > +out: > + virPCIDeviceFree(pci); > + return ret; > +} > + > static unsigned long long > libxlNodeGetFreeMemory(virConnectPtr conn) > { > @@ -4233,6 +4423,9 @@ static virDriver libxlDriver = { > .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */ > .domainEventRegister = libxlDomainEventRegister, /* 0.9.0 */ > .domainEventDeregister = libxlDomainEventDeregister, /* 0.9.0 */ > + .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.0.4 */ > + .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.0.4 */ > + .nodeDeviceReset = libxlNodeDeviceReset, /* 1.0.4 */ > .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */ > .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */ > .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */ > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list