qemu_hostdev.c 34.2 KB
Newer Older
1 2 3
/*
 * qemu_hostdev.c: QEMU hostdev management
 *
4
 * Copyright (C) 2006-2007, 2009-2013 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include "qemu_hostdev.h"
27
#include "virlog.h"
28
#include "virerror.h"
29
#include "viralloc.h"
30
#include "virpci.h"
31
#include "virusb.h"
32
#include "virnetdev.h"
33

34 35
#define VIR_FROM_THIS VIR_FROM_QEMU

36
static virPCIDeviceListPtr
37 38
qemuGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, int nhostdevs)
{
39
    virPCIDeviceListPtr list;
40 41
    int i;

42
    if (!(list = virPCIDeviceListNew()))
43 44 45 46
        return NULL;

    for (i = 0 ; i < nhostdevs ; i++) {
        virDomainHostdevDefPtr hostdev = hostdevs[i];
47
        virPCIDevicePtr dev;
48 49 50 51 52 53

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

54 55 56 57
        dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain,
                              hostdev->source.subsys.u.pci.addr.bus,
                              hostdev->source.subsys.u.pci.addr.slot,
                              hostdev->source.subsys.u.pci.addr.function);
58
        if (!dev) {
59
            virObjectUnref(list);
60 61 62
            return NULL;
        }

63 64
        if (virPCIDeviceListAdd(list, dev) < 0) {
            virPCIDeviceFree(dev);
65
            virObjectUnref(list);
66 67 68
            return NULL;
        }

69
        virPCIDeviceSetManaged(dev, hostdev->managed);
70
        if (hostdev->source.subsys.u.pci.backend
71
            == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
72 73 74 75
            virPCIDeviceSetStubDriver(dev, "vfio-pci");
        } else {
            virPCIDeviceSetStubDriver(dev, "pci-stub");
        }
76 77 78 79 80
    }

    return list;
}

81 82 83
/*
 * Pre-condition: driver->activePciHostdevs is locked
 */
84
static virPCIDeviceListPtr
85
qemuGetActivePciHostDeviceList(virQEMUDriverPtr driver,
86 87 88
                               virDomainHostdevDefPtr *hostdevs,
                               int nhostdevs)
{
89
    virPCIDeviceListPtr list;
90 91
    int i;

92
    if (!(list = virPCIDeviceListNew()))
93 94 95 96
        return NULL;

    for (i = 0 ; i < nhostdevs ; i++) {
        virDomainHostdevDefPtr hostdev = hostdevs[i];
97 98
        virPCIDevicePtr dev;
        virPCIDevicePtr activeDev;
99 100 101 102 103 104

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

105 106 107 108
        dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain,
                              hostdev->source.subsys.u.pci.addr.bus,
                              hostdev->source.subsys.u.pci.addr.slot,
                              hostdev->source.subsys.u.pci.addr.function);
109
        if (!dev) {
110
            virObjectUnref(list);
111 112 113
            return NULL;
        }

114 115 116
        if ((activeDev = virPCIDeviceListFind(driver->activePciHostdevs, dev))) {
            if (virPCIDeviceListAdd(list, activeDev) < 0) {
                virPCIDeviceFree(dev);
117
                virObjectUnref(list);
118 119 120 121
                return NULL;
            }
        }

122
        virPCIDeviceFree(dev);
123 124 125 126
    }

    return list;
}
127

128
int qemuUpdateActivePciHostdevs(virQEMUDriverPtr driver,
129 130
                                virDomainDefPtr def)
{
131 132
    virDomainHostdevDefPtr hostdev = NULL;
    int i;
133
    int ret = -1;
134 135 136 137

    if (!def->nhostdevs)
        return 0;

138 139 140
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);

141
    for (i = 0; i < def->nhostdevs; i++) {
142
        virPCIDevicePtr dev = NULL;
143 144 145 146 147 148 149
        hostdev = def->hostdevs[i];

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

150 151 152 153
        dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain,
                              hostdev->source.subsys.u.pci.addr.bus,
                              hostdev->source.subsys.u.pci.addr.slot,
                              hostdev->source.subsys.u.pci.addr.function);
154 155

        if (!dev)
156
            goto cleanup;
157

158
        virPCIDeviceSetManaged(dev, hostdev->managed);
159
        if (hostdev->source.subsys.u.pci.backend
160
            == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
161 162 163 164
            virPCIDeviceSetStubDriver(dev, "vfio-pci");
        } else {
            virPCIDeviceSetStubDriver(dev, "pci-stub");
        }
165
        virPCIDeviceSetUsedBy(dev, def->name);
166 167

        /* Setup the original states for the PCI device */
168 169 170
        virPCIDeviceSetUnbindFromStub(dev, hostdev->origstates.states.pci.unbind_from_stub);
        virPCIDeviceSetRemoveSlot(dev, hostdev->origstates.states.pci.remove_slot);
        virPCIDeviceSetReprobe(dev, hostdev->origstates.states.pci.reprobe);
171

172 173
        if (virPCIDeviceListAdd(driver->activePciHostdevs, dev) < 0) {
            virPCIDeviceFree(dev);
174
            goto cleanup;
175 176 177
        }
    }

178 179 180 181
cleanup:
    virObjectUnlock(driver->activePciHostdevs);
    virObjectUnlock(driver->inactivePciHostdevs);
    return ret;
182 183 184
}

int
185
qemuUpdateActiveUsbHostdevs(virQEMUDriverPtr driver,
186 187 188 189
                            virDomainDefPtr def)
{
    virDomainHostdevDefPtr hostdev = NULL;
    int i;
190
    int ret = -1;
191 192 193 194

    if (!def->nhostdevs)
        return 0;

195
    virObjectLock(driver->activeUsbHostdevs);
196
    for (i = 0; i < def->nhostdevs; i++) {
197
        virUSBDevicePtr usb = NULL;
198 199 200 201 202 203 204
        hostdev = def->hostdevs[i];

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
            continue;

205 206 207
        usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus,
                              hostdev->source.subsys.u.usb.device,
                              NULL);
208 209 210 211 212 213 214 215
        if (!usb) {
            VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s",
                     hostdev->source.subsys.u.usb.bus,
                     hostdev->source.subsys.u.usb.device,
                     def->name);
            continue;
        }

216
        virUSBDeviceSetUsedBy(usb, def->name);
217

218 219
        if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) {
            virUSBDeviceFree(usb);
220
            goto cleanup;
221 222
        }
    }
223 224 225 226
    ret = 0;
cleanup:
    virObjectUnlock(driver->activeUsbHostdevs);
    return ret;
227 228
}

229 230 231
static int
qemuDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, char **sysfs_path)
{
232
    virPCIDeviceAddress config_address;
233

234 235 236 237
    config_address.domain = hostdev->source.subsys.u.pci.addr.domain;
    config_address.bus = hostdev->source.subsys.u.pci.addr.bus;
    config_address.slot = hostdev->source.subsys.u.pci.addr.slot;
    config_address.function = hostdev->source.subsys.u.pci.addr.function;
238

239
    return virPCIDeviceAddressGetSysfsFile(&config_address, sysfs_path);
240 241 242 243 244 245 246 247 248 249 250
}

int
qemuDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev)
{
    char *sysfs_path = NULL;
    int ret = -1;

    if (qemuDomainHostdevPciSysfsPath(hostdev, &sysfs_path) < 0)
        return ret;

251
    ret = virPCIIsVirtualFunction(sysfs_path);
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267

    VIR_FREE(sysfs_path);

    return ret;
}

static int
qemuDomainHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev,
                           int *vf)
{
    int ret = -1;
    char *sysfs_path = NULL;

    if (qemuDomainHostdevPciSysfsPath(hostdev, &sysfs_path) < 0)
        return ret;

268 269 270
    if (virPCIIsVirtualFunction(sysfs_path) == 1) {
        if (virPCIGetVirtualFunctionInfo(sysfs_path, linkdev,
                                         vf) < 0)
271 272
            goto cleanup;
    } else {
273
        if (virPCIGetNetName(sysfs_path, linkdev) < 0)
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
            goto cleanup;
        *vf = -1;
    }

    ret = 0;

cleanup:
    VIR_FREE(sysfs_path);

    return ret;
}

static int
qemuDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf,
                                          virNetDevVPortProfilePtr virtPort,
289
                                          const virMacAddrPtr macaddr,
290 291 292 293 294 295 296 297
                                          const unsigned char *uuid,
                                          int associate)
{
    int ret = -1;

    if (!virtPort)
        return ret;

298
    switch (virtPort->virtPortType) {
299 300 301 302
    case VIR_NETDEV_VPORT_PROFILE_NONE:
    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
    case VIR_NETDEV_VPORT_PROFILE_LAST:
303 304 305 306 307
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("virtualport type %s is "
                         "currently not supported on interfaces of type "
                         "hostdev"),
                       virNetDevVPortTypeToString(virtPort->virtPortType));
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
        break;

    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
        if (associate)
            ret = virNetDevVPortProfileAssociate(NULL, virtPort, macaddr,
                                                 linkdev, vf, uuid,
                                                 VIR_NETDEV_VPORT_PROFILE_OP_CREATE, false);
        else
            ret = virNetDevVPortProfileDisassociate(NULL, virtPort,
                                                    macaddr, linkdev, vf,
                                                    VIR_NETDEV_VPORT_PROFILE_OP_DESTROY);
        break;
    }

    return ret;
}

int
qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
                                  const unsigned char *uuid,
                                  char *stateDir)
{
    char *linkdev = NULL;
331
    virNetDevVlanPtr vlan;
332 333 334 335 336 337 338 339 340
    virNetDevVPortProfilePtr virtPort;
    int ret = -1;
    int vf = -1;
    int vlanid = -1;
    int port_profile_associate = 1;
    int isvf;

    isvf = qemuDomainHostdevIsVirtualFunction(hostdev);
    if (isvf <= 0) {
341 342 343
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Interface type hostdev is currently supported on"
                         " SR-IOV Virtual Functions only"));
344 345 346 347 348 349
        return ret;
    }

    if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
        return ret;

350
    vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
351 352
    virtPort = virDomainNetGetActualVirtPortProfile(
                                 hostdev->parent.data.net);
353 354 355 356 357 358 359 360
    if (virtPort) {
        if (vlan) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("direct setting of the vlan tag is not allowed "
                             "for hostdev devices using %s mode"),
                           virNetDevVPortTypeToString(virtPort->virtPortType));
            goto cleanup;
        }
361
        ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
362
                            virtPort, &hostdev->parent.data.net->mac, uuid,
363
                            port_profile_associate);
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
    } else {
        /* Set only mac and vlan */
        if (vlan) {
            if (vlan->nTags != 1 || vlan->trunk) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("vlan trunking is not supported "
                                 "by SR-IOV network devices"));
                goto cleanup;
            }
            if (vf == -1) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("vlan can only be set for SR-IOV VFs, but "
                                 "%s is not a VF"), linkdev);
                goto cleanup;
            }
            vlanid = vlan->tag[0];
        } else  if (vf >= 0) {
            vlanid = 0; /* assure any current vlan tag is reset */
        }

384
        ret = virNetDevReplaceNetConfig(linkdev, vf,
385 386 387 388
                                        &hostdev->parent.data.net->mac,
                                        vlanid, stateDir);
    }
cleanup:
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
    VIR_FREE(linkdev);
    return ret;
}

int
qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
                                  char *stateDir)
{
    char *linkdev = NULL;
    virNetDevVPortProfilePtr virtPort;
    int ret = -1;
    int vf = -1;
    int port_profile_associate = 0;
    int isvf;

    isvf = qemuDomainHostdevIsVirtualFunction(hostdev);
    if (isvf <= 0) {
406 407 408
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Interface type hostdev is currently supported on"
                         " SR-IOV Virtual Functions only"));
409 410 411 412 413 414 415 416 417 418
        return ret;
    }

    if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
        return ret;

    virtPort = virDomainNetGetActualVirtPortProfile(
                                 hostdev->parent.data.net);
    if (virtPort)
        ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
419
                                          &hostdev->parent.data.net->mac, NULL,
420 421 422 423 424 425 426 427 428
                                          port_profile_associate);
    else
        ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);

    VIR_FREE(linkdev);

    return ret;
}

429
int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
430
                                 const char *name,
431
                                 const unsigned char *uuid,
432 433 434
                                 virDomainHostdevDefPtr *hostdevs,
                                 int nhostdevs)
{
435
    virPCIDeviceListPtr pcidevs;
436
    int last_processed_hostdev_vf = -1;
437 438
    int i;
    int ret = -1;
439
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
440

441 442 443
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);

444
    if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs)))
445
        goto cleanup;
446

447
    /* We have to use 9 loops here. *All* devices must
448 449 450 451 452 453
     * be detached before we reset any of them, because
     * in some cases you have to reset the whole PCI,
     * which impacts all devices on it. Also, all devices
     * must be reset before being marked as active.
     */

454
    /* Loop 1: validate that non-managed device isn't in use, eg
455 456 457 458
     * by checking that device is either un-bound, or bound
     * to pci-stub.ko
     */

459 460 461
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
        virPCIDevicePtr other;
462

463
        if (!virPCIDeviceIsAssignable(dev, !cfg->relaxedACS)) {
464 465
            virReportError(VIR_ERR_OPERATION_INVALID,
                           _("PCI device %s is not assignable"),
466
                           virPCIDeviceGetName(dev));
467 468 469 470 471
            goto cleanup;
        }
        /* The device is in use by other active domain if
         * the dev is in list driver->activePciHostdevs.
         */
472 473
        if ((other = virPCIDeviceListFind(driver->activePciHostdevs, dev))) {
            const char *other_name = virPCIDeviceGetUsedBy(other);
474 475

            if (other_name)
476 477
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("PCI device %s is in use by domain %s"),
478
                               virPCIDeviceGetName(dev), other_name);
479
            else
480 481
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("PCI device %s is already in use"),
482
                               virPCIDeviceGetName(dev));
483 484 485 486
            goto cleanup;
        }
    }

487
    /* Loop 2: detach managed devices (i.e. bind to appropriate stub driver) */
488 489 490
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
        if (virPCIDeviceGetManaged(dev) &&
491
            virPCIDeviceDetach(dev, driver->activePciHostdevs, NULL, NULL) < 0)
492
            goto reattachdevs;
493 494
    }

495 496
    /* Loop 3: Now that all the PCI hostdevs have been detached, we
     * can safely reset them */
497 498 499 500
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
        if (virPCIDeviceReset(dev, driver->activePciHostdevs,
                              driver->inactivePciHostdevs) < 0)
501
            goto reattachdevs;
502 503
    }

504 505 506 507 508 509 510 511 512 513 514
    /* Loop 4: For SRIOV network devices, Now that we have detached the
     * the network device, set the netdev config */
    for (i = 0; i < nhostdevs; i++) {
         virDomainHostdevDefPtr hostdev = hostdevs[i];
         if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
             continue;
         if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
             continue;
         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
             hostdev->parent.data.net) {
             if (qemuDomainHostdevNetConfigReplace(hostdev, uuid,
515
                                                   cfg->stateDir) < 0) {
516 517 518 519 520 521 522
                 goto resetvfnetconfig;
             }
         }
         last_processed_hostdev_vf = i;
    }

    /* Loop 5: Now mark all the devices as active */
523 524 525
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
        if (virPCIDeviceListAdd(driver->activePciHostdevs, dev) < 0)
526
            goto inactivedevs;
527 528
    }

529
    /* Loop 6: Now remove the devices from inactive list. */
530 531 532
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
         virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
         virPCIDeviceListDel(driver->inactivePciHostdevs, dev);
533 534
    }

535
    /* Loop 7: Now set the used_by_domain of the device in
536 537
     * driver->activePciHostdevs as domain name.
     */
538 539
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev, activeDev;
540

541 542
        dev = virPCIDeviceListGet(pcidevs, i);
        activeDev = virPCIDeviceListFind(driver->activePciHostdevs, dev);
543

544
        if (activeDev)
545
            virPCIDeviceSetUsedBy(activeDev, name);
546 547
    }

548
    /* Loop 8: Now set the original states for hostdev def */
549
    for (i = 0; i < nhostdevs; i++) {
550 551
        virPCIDevicePtr dev;
        virPCIDevicePtr pcidev;
552 553 554 555 556 557 558
        virDomainHostdevDefPtr hostdev = hostdevs[i];

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

559 560 561 562
        dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain,
                              hostdev->source.subsys.u.pci.addr.bus,
                              hostdev->source.subsys.u.pci.addr.slot,
                              hostdev->source.subsys.u.pci.addr.function);
563 564 565 566 567

        /* original states "unbind_from_stub", "remove_slot",
         * "reprobe" were already set by pciDettachDevice in
         * loop 2.
         */
568
        if ((pcidev = virPCIDeviceListFind(pcidevs, dev))) {
569
            hostdev->origstates.states.pci.unbind_from_stub =
570
                virPCIDeviceGetUnbindFromStub(pcidev);
571
            hostdev->origstates.states.pci.remove_slot =
572
                virPCIDeviceGetRemoveSlot(pcidev);
573
            hostdev->origstates.states.pci.reprobe =
574
                virPCIDeviceGetReprobe(pcidev);
575 576
        }

577
        virPCIDeviceFree(dev);
578 579
    }

580
    /* Loop 9: Now steal all the devices from pcidevs */
581 582
    while (virPCIDeviceListCount(pcidevs) > 0)
        virPCIDeviceListStealIndex(pcidevs, 0);
583

584
    ret = 0;
585 586 587 588
    goto cleanup;

inactivedevs:
    /* Only steal all the devices from driver->activePciHostdevs. We will
589
     * free them in virObjectUnref().
590
     */
591 592 593
    while (virPCIDeviceListCount(pcidevs) > 0) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, 0);
        virPCIDeviceListSteal(driver->activePciHostdevs, dev);
594
    }
595

596 597 598 599 600
resetvfnetconfig:
    for (i = 0; i < last_processed_hostdev_vf; i++) {
         virDomainHostdevDefPtr hostdev = hostdevs[i];
         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
             hostdev->parent.data.net) {
601
             qemuDomainHostdevNetConfigRestore(hostdev, cfg->stateDir);
602 603 604
         }
    }

605
reattachdevs:
606 607
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
608 609 610 611 612

        /* NB: This doesn't actually re-bind to original driver, just
         * unbinds from the stub driver
         */
        virPCIDeviceReattach(dev, driver->activePciHostdevs, NULL, NULL);
613 614
    }

615
cleanup:
616 617
    virObjectUnlock(driver->activePciHostdevs);
    virObjectUnlock(driver->inactivePciHostdevs);
618
    virObjectUnref(pcidevs);
619
    virObjectUnref(cfg);
620 621 622
    return ret;
}

623
int
624
qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver,
625
                             const char *name,
626
                             virUSBDeviceListPtr list)
627
{
628
    int i, j;
629
    unsigned int count;
630
    virUSBDevicePtr tmp;
631

632
    virObjectLock(driver->activeUsbHostdevs);
633
    count = virUSBDeviceListCount(list);
634 635

    for (i = 0; i < count; i++) {
636 637 638
        virUSBDevicePtr usb = virUSBDeviceListGet(list, i);
        if ((tmp = virUSBDeviceListFind(driver->activeUsbHostdevs, usb))) {
            const char *other_name = virUSBDeviceGetUsedBy(tmp);
639 640

            if (other_name)
641 642
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("USB device %s is in use by domain %s"),
643
                               virUSBDeviceGetName(tmp), other_name);
644
            else
645 646
                virReportError(VIR_ERR_OPERATION_INVALID,
                               _("USB device %s is already in use"),
647
                               virUSBDeviceGetName(tmp));
648
            goto error;
649 650
        }

651
        virUSBDeviceSetUsedBy(usb, name);
652
        VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs",
653
                  virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb), name);
654 655
        /*
         * The caller is responsible to steal these usb devices
656
         * from the virUSBDeviceList that passed in on success,
657 658
         * perform rollback on failure.
         */
659
        if (virUSBDeviceListAdd(driver->activeUsbHostdevs, usb) < 0)
660
            goto error;
661
    }
662 663

    virObjectUnlock(driver->activeUsbHostdevs);
664
    return 0;
665 666 667

error:
    for (j = 0; j < i; j++) {
668 669
        tmp = virUSBDeviceListGet(list, i);
        virUSBDeviceListSteal(driver->activeUsbHostdevs, tmp);
670
    }
671
    virObjectUnlock(driver->activeUsbHostdevs);
672
    return -1;
673 674
}

675 676 677
int
qemuFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
                         bool mandatory,
678
                         virUSBDevicePtr *usb)
679 680 681 682 683
{
    unsigned vendor = hostdev->source.subsys.u.usb.vendor;
    unsigned product = hostdev->source.subsys.u.usb.product;
    unsigned bus = hostdev->source.subsys.u.usb.bus;
    unsigned device = hostdev->source.subsys.u.usb.device;
684
    bool autoAddress = hostdev->source.subsys.u.usb.autoAddress;
685
    int rc;
686

687
    *usb = NULL;
688

689
    if (vendor && bus) {
690 691 692 693
        rc = virUSBDeviceFind(vendor, product, bus, device,
                              NULL,
                              autoAddress ? false : mandatory,
                              usb);
694
        if (rc < 0) {
695
            return -1;
696 697 698 699 700 701 702 703 704 705 706 707 708 709
        } else if (!autoAddress) {
            goto out;
        } else {
            VIR_INFO("USB device %x:%x could not be found at previous"
                     " address (bus:%u device:%u)",
                     vendor, product, bus, device);
        }
    }

    /* When vendor is specified, its USB address is either unspecified or the
     * device could not be found at the USB device where it had been
     * automatically found before.
     */
    if (vendor) {
710
        virUSBDeviceListPtr devs;
711

712
        rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs);
713 714 715 716
        if (rc < 0)
            return -1;

        if (rc == 1) {
717 718
            *usb = virUSBDeviceListGet(devs, 0);
            virUSBDeviceListSteal(devs, *usb);
719
        }
720
        virObjectUnref(devs);
721

722 723 724
        if (rc == 0) {
            goto out;
        } else if (rc > 1) {
725 726 727 728 729 730 731 732 733 734 735
            if (autoAddress) {
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("Multiple USB devices for %x:%x were found,"
                                 " but none of them is at bus:%u device:%u"),
                               vendor, product, bus, device);
            } else {
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("Multiple USB devices for %x:%x, "
                                 "use <address> to specify one"),
                               vendor, product);
            }
736 737
            return -1;
        }
738

739 740
        hostdev->source.subsys.u.usb.bus = virUSBDeviceGetBus(*usb);
        hostdev->source.subsys.u.usb.device = virUSBDeviceGetDevno(*usb);
741 742 743 744 745 746 747 748 749 750
        hostdev->source.subsys.u.usb.autoAddress = true;

        if (autoAddress) {
            VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved"
                     " from bus:%u device:%u)",
                     vendor, product,
                     hostdev->source.subsys.u.usb.bus,
                     hostdev->source.subsys.u.usb.device,
                     bus, device);
        }
751
    } else if (!vendor && bus) {
752
        if (virUSBDeviceFindByBus(bus, device, NULL, mandatory, usb) < 0)
753
            return -1;
754 755
    }

756 757
out:
    if (!*usb)
758
        hostdev->missing = true;
759
    return 0;
760 761
}

762
static int
763
qemuPrepareHostUSBDevices(virQEMUDriverPtr driver,
764 765
                          virDomainDefPtr def,
                          bool coldBoot)
766 767
{
    int i, ret = -1;
768 769
    virUSBDeviceListPtr list;
    virUSBDevicePtr tmp;
770 771
    virDomainHostdevDefPtr *hostdevs = def->hostdevs;
    int nhostdevs = def->nhostdevs;
772 773 774 775 776 777

    /* To prevent situation where USB device is assigned to two domains
     * we need to keep a list of currently assigned USB devices.
     * This is done in several loops which cannot be joined into one big
     * loop. See qemuPrepareHostdevPCIDevices()
     */
778
    if (!(list = virUSBDeviceListNew()))
779 780
        goto cleanup;

781
    /* Loop 1: build temporary list
782 783 784
     */
    for (i = 0 ; i < nhostdevs ; i++) {
        virDomainHostdevDefPtr hostdev = hostdevs[i];
785
        bool required = true;
786
        virUSBDevicePtr usb;
787 788 789 790 791 792

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
            continue;

793 794 795 796 797 798
        if (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_OPTIONAL ||
            (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE &&
             !coldBoot))
            required = false;

        if (qemuFindHostdevUSBDevice(hostdev, required, &usb) < 0)
799
            goto cleanup;
800

801 802
        if (usb && virUSBDeviceListAdd(list, usb) < 0) {
            virUSBDeviceFree(usb);
803
            goto cleanup;
804 805 806
        }
    }

807
    /* Mark devices in temporary list as used by @name
808 809 810
     * and add them do driver list. However, if something goes
     * wrong, perform rollback.
     */
811
    if (qemuPrepareHostdevUSBDevices(driver, def->name, list) < 0)
812
        goto cleanup;
813

814
    /* Loop 2: Temporary list was successfully merged with
815 816 817
     * driver list, so steal all items to avoid freeing them
     * in cleanup label.
     */
818 819 820
    while (virUSBDeviceListCount(list) > 0) {
        tmp = virUSBDeviceListGet(list, 0);
        virUSBDeviceListSteal(list, tmp);
821 822 823 824 825
    }

    ret = 0;

cleanup:
826
    virObjectUnref(list);
827
    return ret;
828 829
}

830
int qemuPrepareHostDevices(virQEMUDriverPtr driver,
831 832
                           virDomainDefPtr def,
                           bool coldBoot)
833 834 835 836
{
    if (!def->nhostdevs)
        return 0;

837 838
    if (qemuPrepareHostdevPCIDevices(driver, def->name, def->uuid,
                                     def->hostdevs, def->nhostdevs) < 0)
839 840
        return -1;

841
    if (qemuPrepareHostUSBDevices(driver, def, coldBoot) < 0)
842 843 844 845 846 847
        return -1;

    return 0;
}


848 849 850 851
/*
 * Pre-condition: driver->inactivePciHostdevs & driver->activePciHostdevs
 * are locked
 */
852
void qemuReattachPciDevice(virPCIDevicePtr dev, virQEMUDriverPtr driver)
853 854 855
{
    int retries = 100;

856 857 858
    /* If the device is not managed and was attached to guest
     * successfully, it must have been inactive.
     */
859 860 861
    if (!virPCIDeviceGetManaged(dev)) {
        if (virPCIDeviceListAdd(driver->inactivePciHostdevs, dev) < 0)
            virPCIDeviceFree(dev);
862
        return;
863
    }
864

865
    while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device")
866 867 868 869 870
           && retries) {
        usleep(100*1000);
        retries--;
    }

871 872
    if (virPCIDeviceReattach(dev, driver->activePciHostdevs,
                             driver->inactivePciHostdevs, "pci-stub") < 0) {
873 874 875 876
        virErrorPtr err = virGetLastError();
        VIR_ERROR(_("Failed to re-attach PCI device: %s"),
                  err ? err->message : _("unknown error"));
        virResetError(err);
877
    }
878
    virPCIDeviceFree(dev);
879 880 881
}


882
void qemuDomainReAttachHostdevDevices(virQEMUDriverPtr driver,
883
                                      const char *name,
884 885 886
                                      virDomainHostdevDefPtr *hostdevs,
                                      int nhostdevs)
{
887
    virPCIDeviceListPtr pcidevs;
888
    int i;
889
    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
890

891 892 893
    virObjectLock(driver->activePciHostdevs);
    virObjectLock(driver->inactivePciHostdevs);

894 895 896
    if (!(pcidevs = qemuGetActivePciHostDeviceList(driver,
                                                   hostdevs,
                                                   nhostdevs))) {
897
        virErrorPtr err = virGetLastError();
898
        VIR_ERROR(_("Failed to allocate PCI device list: %s"),
899 900
                  err ? err->message : _("unknown error"));
        virResetError(err);
901
        goto cleanup;
902 903
    }

904 905 906 907
    /* Again 4 loops; mark all devices as inactive before reset
     * them and reset all the devices before re-attach.
     * Attach mac and port profile parameters to devices
     */
908 909 910
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
        virPCIDevicePtr activeDev = NULL;
911 912 913 914

        /* Never delete the dev from list driver->activePciHostdevs
         * if it's used by other domain.
         */
915
        activeDev = virPCIDeviceListFind(driver->activePciHostdevs, dev);
916
        if (activeDev &&
917 918
            STRNEQ_NULLABLE(name, virPCIDeviceGetUsedBy(activeDev))) {
            virPCIDeviceListSteal(pcidevs, dev);
919
            continue;
920
        }
921

922
        /* virObjectUnref() will take care of freeing the dev. */
923
        virPCIDeviceListSteal(driver->activePciHostdevs, dev);
924 925
    }

926 927 928 929 930 931 932 933 934 935 936 937
    /*
     * For SRIOV net host devices, unset mac and port profile before
     * reset and reattach device
     */
    for (i = 0; i < nhostdevs; i++) {
         virDomainHostdevDefPtr hostdev = hostdevs[i];
         if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
             continue;
         if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
             continue;
         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
             hostdev->parent.data.net) {
938
             qemuDomainHostdevNetConfigRestore(hostdev, cfg->stateDir);
939 940 941
         }
    }

942 943 944 945
    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
        if (virPCIDeviceReset(dev, driver->activePciHostdevs,
                              driver->inactivePciHostdevs) < 0) {
946 947 948 949 950 951 952
            virErrorPtr err = virGetLastError();
            VIR_ERROR(_("Failed to reset PCI device: %s"),
                      err ? err->message : _("unknown error"));
            virResetError(err);
        }
    }

953 954
    while (virPCIDeviceListCount(pcidevs) > 0) {
        virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0);
955 956 957
        qemuReattachPciDevice(dev, driver);
    }

958
    virObjectUnref(pcidevs);
959
cleanup:
960 961
    virObjectUnlock(driver->activePciHostdevs);
    virObjectUnlock(driver->inactivePciHostdevs);
962
    virObjectUnref(cfg);
963 964
}

965
static void
966
qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver,
967 968 969 970 971 972
                                 const char *name,
                                 virDomainHostdevDefPtr *hostdevs,
                                 int nhostdevs)
{
    int i;

973
    virObjectLock(driver->activeUsbHostdevs);
974 975
    for (i = 0; i < nhostdevs; i++) {
        virDomainHostdevDefPtr hostdev = hostdevs[i];
976
        virUSBDevicePtr usb, tmp;
977 978 979 980 981 982
        const char *used_by = NULL;

        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
            continue;
983 984
        if (hostdev->missing)
            continue;
985

986 987 988
        usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus,
                              hostdev->source.subsys.u.usb.device,
                              NULL);
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003

        if (!usb) {
            VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s",
                     hostdev->source.subsys.u.usb.bus,
                     hostdev->source.subsys.u.usb.device,
                     name);
            continue;
        }

        /* Delete only those USB devices which belongs
         * to domain @name because qemuProcessStart() might
         * have failed because USB device is already taken.
         * Therefore we want to steal only those devices from
         * the list which were taken by @name */

1004 1005
        tmp = virUSBDeviceListFind(driver->activeUsbHostdevs, usb);
        virUSBDeviceFree(usb);
1006 1007 1008 1009 1010 1011 1012 1013 1014

        if (!tmp) {
            VIR_WARN("Unable to find device %03d.%03d "
                     "in list of active USB devices",
                     hostdev->source.subsys.u.usb.bus,
                     hostdev->source.subsys.u.usb.device);
            continue;
        }

1015
        used_by = virUSBDeviceGetUsedBy(tmp);
1016 1017 1018 1019 1020 1021
        if (STREQ_NULLABLE(used_by, name)) {
            VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs",
                      hostdev->source.subsys.u.usb.bus,
                      hostdev->source.subsys.u.usb.device,
                      name);

1022
            virUSBDeviceListDel(driver->activeUsbHostdevs, tmp);
1023 1024
        }
    }
1025
    virObjectUnlock(driver->activeUsbHostdevs);
1026
}
1027

1028
void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver,
1029 1030 1031 1032 1033
                                   virDomainDefPtr def)
{
    if (!def->nhostdevs)
        return;

1034 1035
    qemuDomainReAttachHostdevDevices(driver, def->name, def->hostdevs,
                                     def->nhostdevs);
1036 1037 1038

    qemuDomainReAttachHostUsbDevices(driver, def->name, def->hostdevs,
                                     def->nhostdevs);
1039
}