On 22.05.2013 16:36, Jim Fehlig wrote:
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?
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 */
>
--
Best Regards,
Marek Marczykowski
Invisible Things Lab