1 /*
2  * qemu_hostdev.c: QEMU hostdev management
3  *
4  * Copyright (C) 2006-2007, 2009-2014 Red Hat, Inc.
5  * Copyright (C) 2006 Daniel P. Berrange
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 
24 #include <fcntl.h>
25 #include <sys/ioctl.h>
26 
27 #include "qemu_hostdev.h"
28 #include "qemu_domain.h"
29 #include "virlog.h"
30 #include "virerror.h"
31 #include "viralloc.h"
32 #include "virpci.h"
33 #include "virusb.h"
34 #include "virscsi.h"
35 #include "virnetdev.h"
36 #include "virfile.h"
37 #include "virhostdev.h"
38 #include "virutil.h"
39 
40 #define VIR_FROM_THIS VIR_FROM_QEMU
41 
42 VIR_LOG_INIT("qemu.qemu_hostdev");
43 
44 
45 int
qemuHostdevUpdateActivePCIDevices(virQEMUDriver * driver,virDomainDef * def)46 qemuHostdevUpdateActivePCIDevices(virQEMUDriver *driver,
47                                   virDomainDef *def)
48 {
49     virHostdevManager *mgr = driver->hostdevMgr;
50 
51     if (!def->nhostdevs)
52         return 0;
53 
54     return virHostdevUpdateActivePCIDevices(mgr, def->hostdevs, def->nhostdevs,
55                                             QEMU_DRIVER_NAME, def->name);
56 }
57 
58 int
qemuHostdevUpdateActiveUSBDevices(virQEMUDriver * driver,virDomainDef * def)59 qemuHostdevUpdateActiveUSBDevices(virQEMUDriver *driver,
60                                   virDomainDef *def)
61 {
62     virHostdevManager *mgr = driver->hostdevMgr;
63 
64     if (!def->nhostdevs)
65         return 0;
66 
67     return virHostdevUpdateActiveUSBDevices(mgr, def->hostdevs, def->nhostdevs,
68                                             QEMU_DRIVER_NAME, def->name);
69 }
70 
71 int
qemuHostdevUpdateActiveSCSIDevices(virQEMUDriver * driver,virDomainDef * def)72 qemuHostdevUpdateActiveSCSIDevices(virQEMUDriver *driver,
73                                    virDomainDef *def)
74 {
75     virHostdevManager *mgr = driver->hostdevMgr;
76 
77     if (!def->nhostdevs)
78         return 0;
79 
80     return virHostdevUpdateActiveSCSIDevices(mgr, def->hostdevs, def->nhostdevs,
81                                              QEMU_DRIVER_NAME, def->name);
82 }
83 
84 
85 int
qemuHostdevUpdateActiveMediatedDevices(virQEMUDriver * driver,virDomainDef * def)86 qemuHostdevUpdateActiveMediatedDevices(virQEMUDriver *driver,
87                                        virDomainDef *def)
88 {
89     virHostdevManager *mgr = driver->hostdevMgr;
90 
91     if (!def->nhostdevs)
92         return 0;
93 
94     return virHostdevUpdateActiveMediatedDevices(mgr, def->hostdevs,
95                                                  def->nhostdevs,
96                                                  QEMU_DRIVER_NAME, def->name);
97 }
98 
99 
100 int
qemuHostdevUpdateActiveNVMeDisks(virQEMUDriver * driver,virDomainDef * def)101 qemuHostdevUpdateActiveNVMeDisks(virQEMUDriver *driver,
102                                  virDomainDef *def)
103 {
104     return virHostdevUpdateActiveNVMeDevices(driver->hostdevMgr,
105                                              QEMU_DRIVER_NAME,
106                                              def->name,
107                                              def->disks,
108                                              def->ndisks);
109 }
110 
111 
112 int
qemuHostdevUpdateActiveDomainDevices(virQEMUDriver * driver,virDomainDef * def)113 qemuHostdevUpdateActiveDomainDevices(virQEMUDriver *driver,
114                                      virDomainDef *def)
115 {
116     if (!def->nhostdevs && !def->ndisks)
117         return 0;
118 
119     if (qemuHostdevUpdateActiveNVMeDisks(driver, def) < 0)
120         return -1;
121 
122     if (qemuHostdevUpdateActivePCIDevices(driver, def) < 0)
123         return -1;
124 
125     if (qemuHostdevUpdateActiveUSBDevices(driver, def) < 0)
126         return -1;
127 
128     if (qemuHostdevUpdateActiveSCSIDevices(driver, def) < 0)
129         return -1;
130 
131     if (qemuHostdevUpdateActiveMediatedDevices(driver, def) < 0)
132         return -1;
133 
134     return 0;
135 }
136 
137 
138 bool
qemuHostdevNeedsVFIO(const virDomainHostdevDef * hostdev)139 qemuHostdevNeedsVFIO(const virDomainHostdevDef *hostdev)
140 {
141     return virHostdevIsVFIODevice(hostdev) ||
142         virHostdevIsMdevDevice(hostdev);
143 }
144 
145 
146 bool
qemuHostdevHostSupportsPassthroughVFIO(void)147 qemuHostdevHostSupportsPassthroughVFIO(void)
148 {
149     /* condition 1 - host has IOMMU */
150     if (!virHostHasIOMMU())
151         return false;
152 
153     /* condition 2 - /dev/vfio/vfio exists */
154     if (!virFileExists(QEMU_DEV_VFIO))
155         return false;
156 
157     return true;
158 }
159 
160 
161 static bool
qemuHostdevPreparePCIDevicesCheckSupport(virDomainHostdevDef ** hostdevs,size_t nhostdevs,virQEMUCaps * qemuCaps)162 qemuHostdevPreparePCIDevicesCheckSupport(virDomainHostdevDef **hostdevs,
163                                          size_t nhostdevs,
164                                          virQEMUCaps *qemuCaps)
165 {
166     bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
167     size_t i;
168 
169     /* assign defaults for hostdev passthrough */
170     for (i = 0; i < nhostdevs; i++) {
171         virDomainHostdevDef *hostdev = hostdevs[i];
172         int *backend = &hostdev->source.subsys.u.pci.backend;
173 
174         if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
175             continue;
176         if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
177             continue;
178 
179         switch ((virDomainHostdevSubsysPCIBackendType)*backend) {
180         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
181             if (supportsPassthroughVFIO &&
182                 virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
183                 *backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
184             } else {
185                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
186                                _("host doesn't support passthrough of "
187                                  "host PCI devices"));
188                 return false;
189             }
190 
191             break;
192 
193         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
194             if (!supportsPassthroughVFIO) {
195                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
196                                _("host doesn't support VFIO PCI passthrough"));
197                 return false;
198             }
199             break;
200 
201         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
202             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
203                            _("host doesn't support legacy PCI passthrough"));
204             return false;
205 
206         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
207         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
208             break;
209         }
210     }
211 
212     return true;
213 }
214 
215 int
qemuHostdevPrepareOneNVMeDisk(virQEMUDriver * driver,const char * name,virStorageSource * src)216 qemuHostdevPrepareOneNVMeDisk(virQEMUDriver *driver,
217                               const char *name,
218                               virStorageSource *src)
219 {
220     return virHostdevPrepareOneNVMeDevice(driver->hostdevMgr,
221                                           QEMU_DRIVER_NAME,
222                                           name,
223                                           src);
224 }
225 
226 int
qemuHostdevPrepareNVMeDisks(virQEMUDriver * driver,const char * name,virDomainDiskDef ** disks,size_t ndisks)227 qemuHostdevPrepareNVMeDisks(virQEMUDriver *driver,
228                             const char *name,
229                             virDomainDiskDef **disks,
230                             size_t ndisks)
231 {
232     return virHostdevPrepareNVMeDevices(driver->hostdevMgr,
233                                         QEMU_DRIVER_NAME,
234                                         name, disks, ndisks);
235 }
236 
237 int
qemuHostdevPreparePCIDevices(virQEMUDriver * driver,const char * name,const unsigned char * uuid,virDomainHostdevDef ** hostdevs,int nhostdevs,virQEMUCaps * qemuCaps,unsigned int flags)238 qemuHostdevPreparePCIDevices(virQEMUDriver *driver,
239                              const char *name,
240                              const unsigned char *uuid,
241                              virDomainHostdevDef **hostdevs,
242                              int nhostdevs,
243                              virQEMUCaps *qemuCaps,
244                              unsigned int flags)
245 {
246     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
247 
248     if (!qemuHostdevPreparePCIDevicesCheckSupport(hostdevs, nhostdevs, qemuCaps))
249         return -1;
250 
251     return virHostdevPreparePCIDevices(hostdev_mgr, QEMU_DRIVER_NAME,
252                                        name, uuid, hostdevs,
253                                        nhostdevs, flags);
254 }
255 
256 int
qemuHostdevPrepareUSBDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs,unsigned int flags)257 qemuHostdevPrepareUSBDevices(virQEMUDriver *driver,
258                              const char *name,
259                              virDomainHostdevDef **hostdevs,
260                              int nhostdevs,
261                              unsigned int flags)
262 {
263     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
264 
265     return virHostdevPrepareUSBDevices(hostdev_mgr, QEMU_DRIVER_NAME, name,
266                                        hostdevs, nhostdevs, flags);
267 }
268 
269 int
qemuHostdevPrepareSCSIDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)270 qemuHostdevPrepareSCSIDevices(virQEMUDriver *driver,
271                               const char *name,
272                               virDomainHostdevDef **hostdevs,
273                               int nhostdevs)
274 {
275     size_t i;
276     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
277 
278     /* Loop 1: Add the shared scsi host device to shared device
279      * table.
280      */
281     for (i = 0; i < nhostdevs; i++) {
282         virDomainDeviceDef dev;
283 
284         if (!virHostdevIsSCSIDevice(hostdevs[i]))
285             continue;
286 
287         dev.type = VIR_DOMAIN_DEVICE_HOSTDEV;
288         dev.data.hostdev = hostdevs[i];
289 
290         if (qemuAddSharedDevice(driver, &dev, name) < 0)
291             return -1;
292 
293         if (qemuSetUnprivSGIO(&dev) < 0)
294             return -1;
295     }
296 
297     return virHostdevPrepareSCSIDevices(hostdev_mgr, QEMU_DRIVER_NAME,
298                                         name, hostdevs, nhostdevs);
299 }
300 
301 int
qemuHostdevPrepareSCSIVHostDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)302 qemuHostdevPrepareSCSIVHostDevices(virQEMUDriver *driver,
303                                    const char *name,
304                                    virDomainHostdevDef **hostdevs,
305                                    int nhostdevs)
306 {
307     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
308 
309     return virHostdevPrepareSCSIVHostDevices(hostdev_mgr, QEMU_DRIVER_NAME,
310                                              name, hostdevs, nhostdevs);
311 }
312 
313 int
qemuHostdevPrepareMediatedDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)314 qemuHostdevPrepareMediatedDevices(virQEMUDriver *driver,
315                                   const char *name,
316                                   virDomainHostdevDef **hostdevs,
317                                   int nhostdevs)
318 {
319     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
320     bool supportsVFIO;
321     size_t i;
322 
323     /* Checking for VFIO only is fine with mdev, as IOMMU isolation is achieved
324      * by the physical parent device.
325      */
326     supportsVFIO = virFileExists(QEMU_DEV_VFIO);
327 
328     for (i = 0; i < nhostdevs; i++) {
329         if (virHostdevIsMdevDevice(hostdevs[i])) {
330             if (!supportsVFIO) {
331                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
332                                _("Mediated host device assignment requires "
333                                  "VFIO support"));
334                 return -1;
335             }
336             break;
337         }
338     }
339 
340     return virHostdevPrepareMediatedDevices(hostdev_mgr, QEMU_DRIVER_NAME,
341                                             name, hostdevs, nhostdevs);
342 }
343 
344 int
qemuHostdevPrepareDomainDevices(virQEMUDriver * driver,virDomainDef * def,virQEMUCaps * qemuCaps,unsigned int flags)345 qemuHostdevPrepareDomainDevices(virQEMUDriver *driver,
346                                 virDomainDef *def,
347                                 virQEMUCaps *qemuCaps,
348                                 unsigned int flags)
349 {
350     if (!def->nhostdevs && !def->ndisks)
351         return 0;
352 
353     if (qemuHostdevPrepareNVMeDisks(driver, def->name, def->disks, def->ndisks) < 0)
354         return -1;
355 
356     if (qemuHostdevPreparePCIDevices(driver, def->name, def->uuid,
357                                      def->hostdevs, def->nhostdevs,
358                                      qemuCaps, flags) < 0)
359         return -1;
360 
361     if (qemuHostdevPrepareUSBDevices(driver, def->name,
362                                      def->hostdevs, def->nhostdevs, flags) < 0)
363         return -1;
364 
365     if (qemuHostdevPrepareSCSIDevices(driver, def->name,
366                                       def->hostdevs, def->nhostdevs) < 0)
367         return -1;
368 
369     if (qemuHostdevPrepareSCSIVHostDevices(driver, def->name,
370                                            def->hostdevs, def->nhostdevs) < 0)
371         return -1;
372 
373     if (qemuHostdevPrepareMediatedDevices(driver, def->name,
374                                           def->hostdevs, def->nhostdevs) < 0)
375         return -1;
376 
377     return 0;
378 }
379 
380 void
qemuHostdevReAttachOneNVMeDisk(virQEMUDriver * driver,const char * name,virStorageSource * src)381 qemuHostdevReAttachOneNVMeDisk(virQEMUDriver *driver,
382                                const char *name,
383                                virStorageSource *src)
384 {
385     virHostdevReAttachOneNVMeDevice(driver->hostdevMgr,
386                                     QEMU_DRIVER_NAME,
387                                     name,
388                                     src);
389 }
390 
391 void
qemuHostdevReAttachNVMeDisks(virQEMUDriver * driver,const char * name,virDomainDiskDef ** disks,size_t ndisks)392 qemuHostdevReAttachNVMeDisks(virQEMUDriver *driver,
393                              const char *name,
394                              virDomainDiskDef **disks,
395                              size_t ndisks)
396 {
397     virHostdevReAttachNVMeDevices(driver->hostdevMgr,
398                                   QEMU_DRIVER_NAME,
399                                   name, disks, ndisks);
400 }
401 
402 void
qemuHostdevReAttachPCIDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)403 qemuHostdevReAttachPCIDevices(virQEMUDriver *driver,
404                               const char *name,
405                               virDomainHostdevDef **hostdevs,
406                               int nhostdevs)
407 {
408     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
409 
410     virHostdevReAttachPCIDevices(hostdev_mgr, QEMU_DRIVER_NAME, name,
411                                  hostdevs, nhostdevs);
412 }
413 
414 void
qemuHostdevReAttachUSBDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)415 qemuHostdevReAttachUSBDevices(virQEMUDriver *driver,
416                               const char *name,
417                               virDomainHostdevDef **hostdevs,
418                               int nhostdevs)
419 {
420     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
421 
422     virHostdevReAttachUSBDevices(hostdev_mgr, QEMU_DRIVER_NAME,
423                                   name, hostdevs, nhostdevs);
424 }
425 
426 void
qemuHostdevReAttachSCSIDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)427 qemuHostdevReAttachSCSIDevices(virQEMUDriver *driver,
428                                const char *name,
429                                virDomainHostdevDef **hostdevs,
430                                int nhostdevs)
431 {
432     size_t i;
433     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
434 
435     for (i = 0; i < nhostdevs; i++) {
436         virDomainHostdevDef *hostdev = hostdevs[i];
437         virDomainDeviceDef dev;
438 
439         dev.type = VIR_DOMAIN_DEVICE_HOSTDEV;
440         dev.data.hostdev = hostdev;
441 
442         ignore_value(qemuRemoveSharedDevice(driver, &dev, name));
443     }
444 
445     virHostdevReAttachSCSIDevices(hostdev_mgr, QEMU_DRIVER_NAME,
446                                   name, hostdevs, nhostdevs);
447 }
448 
449 void
qemuHostdevReAttachSCSIVHostDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)450 qemuHostdevReAttachSCSIVHostDevices(virQEMUDriver *driver,
451                                     const char *name,
452                                     virDomainHostdevDef **hostdevs,
453                                     int nhostdevs)
454 {
455     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
456 
457     virHostdevReAttachSCSIVHostDevices(hostdev_mgr, QEMU_DRIVER_NAME,
458                                        name, hostdevs, nhostdevs);
459 }
460 
461 void
qemuHostdevReAttachMediatedDevices(virQEMUDriver * driver,const char * name,virDomainHostdevDef ** hostdevs,int nhostdevs)462 qemuHostdevReAttachMediatedDevices(virQEMUDriver *driver,
463                                    const char *name,
464                                    virDomainHostdevDef **hostdevs,
465                                    int nhostdevs)
466 {
467     virHostdevManager *hostdev_mgr = driver->hostdevMgr;
468 
469     virHostdevReAttachMediatedDevices(hostdev_mgr, QEMU_DRIVER_NAME,
470                                       name, hostdevs, nhostdevs);
471 }
472 
473 void
qemuHostdevReAttachDomainDevices(virQEMUDriver * driver,virDomainDef * def)474 qemuHostdevReAttachDomainDevices(virQEMUDriver *driver,
475                                  virDomainDef *def)
476 {
477     if (!def->nhostdevs && !def->ndisks)
478         return;
479 
480     qemuHostdevReAttachNVMeDisks(driver, def->name, def->disks,
481                                  def->ndisks);
482 
483     qemuHostdevReAttachPCIDevices(driver, def->name, def->hostdevs,
484                                   def->nhostdevs);
485 
486     qemuHostdevReAttachUSBDevices(driver, def->name, def->hostdevs,
487                                   def->nhostdevs);
488 
489     qemuHostdevReAttachSCSIDevices(driver, def->name, def->hostdevs,
490                                    def->nhostdevs);
491 
492     qemuHostdevReAttachSCSIVHostDevices(driver, def->name, def->hostdevs,
493                                         def->nhostdevs);
494 
495     qemuHostdevReAttachMediatedDevices(driver, def->name, def->hostdevs,
496                                        def->nhostdevs);
497 }
498