Skip to content

Commit 048d477

Browse files
liuwbryteise
authored andcommitted
ch: implement host device management helper functions
We only want to support VFIO at this stage, but it wouldn't hurt to implement as many functions as possible. They are mostly just wrappers around Libvirt's hostdev infrastructure anyway. Signed-off-by: Wei Liu <[email protected]>
1 parent 41a177c commit 048d477

File tree

3 files changed

+421
-0
lines changed

3 files changed

+421
-0
lines changed

src/ch/ch_domain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "virchrdev.h"
2626
#include "vircgroup.h"
2727

28+
#define CH_DEV_VFIO "/dev/vfio/vfio"
29+
2830
/* Give up waiting for mutex after 30 seconds */
2931
#define CH_JOB_WAIT_TIME (1000ull * 30)
3032

src/ch/ch_hostdev.c

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,320 @@
3939
#define VIR_FROM_THIS VIR_FROM_CH
4040

4141
VIR_LOG_INIT("ch.ch_hostdev");
42+
43+
bool
44+
chHostdevHostSupportsPassthroughVFIO(void)
45+
{
46+
/* condition 1 - host has IOMMU */
47+
if (!virHostHasIOMMU())
48+
return false;
49+
50+
/* condition 2 - /dev/vfio/vfio exists */
51+
if (!virFileExists(CH_DEV_VFIO))
52+
return false;
53+
54+
return true;
55+
}
56+
57+
bool
58+
chHostdevNeedsVFIO(const virDomainHostdevDef *hostdev)
59+
{
60+
return virHostdevIsVFIODevice(hostdev) ||
61+
virHostdevIsMdevDevice(hostdev);
62+
}
63+
64+
static bool
65+
chHostdevPreparePCIDevicesCheckSupport(virDomainHostdevDefPtr *hostdevs,
66+
size_t nhostdevs)
67+
{
68+
bool supportsPassthroughVFIO = chHostdevHostSupportsPassthroughVFIO();
69+
size_t i;
70+
71+
/* assign defaults for hostdev passthrough */
72+
for (i = 0; i < nhostdevs; i++) {
73+
virDomainHostdevDefPtr hostdev = hostdevs[i];
74+
int *backend = &hostdev->source.subsys.u.pci.backend;
75+
76+
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
77+
continue;
78+
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
79+
continue;
80+
81+
switch ((virDomainHostdevSubsysPCIBackendType)*backend) {
82+
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
83+
if (supportsPassthroughVFIO) {
84+
*backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
85+
} else {
86+
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
87+
_("host doesn't support passthrough of "
88+
"host PCI devices"));
89+
return false;
90+
}
91+
92+
break;
93+
94+
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
95+
if (!supportsPassthroughVFIO) {
96+
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
97+
_("host doesn't support VFIO PCI passthrough"));
98+
return false;
99+
}
100+
break;
101+
102+
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
103+
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
104+
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
105+
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s%s",
106+
_("host doesn't support passthrough: "),
107+
_(virDomainHostdevSubsysPCIBackendTypeToString(*backend)));
108+
return false;
109+
}
110+
}
111+
112+
return true;
113+
}
114+
115+
int
116+
chHostdevPrepareNVMeDisks(virCHDriverPtr driver,
117+
const char *name,
118+
virDomainDiskDefPtr *disks,
119+
size_t ndisks)
120+
{
121+
return virHostdevPrepareNVMeDevices(driver->hostdevMgr,
122+
CH_DRIVER_NAME,
123+
name, disks, ndisks);
124+
}
125+
126+
int
127+
chHostdevPreparePCIDevices(virCHDriverPtr driver,
128+
const char *name,
129+
const unsigned char *uuid,
130+
virDomainHostdevDefPtr *hostdevs,
131+
int nhostdevs,
132+
unsigned int flags)
133+
{
134+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
135+
136+
if (!chHostdevPreparePCIDevicesCheckSupport(hostdevs, nhostdevs))
137+
return -1;
138+
139+
return virHostdevPreparePCIDevices(hostdev_mgr, CH_DRIVER_NAME,
140+
name, uuid, hostdevs,
141+
nhostdevs, flags);
142+
}
143+
144+
int
145+
chHostdevPrepareUSBDevices(virCHDriverPtr driver,
146+
const char *name,
147+
virDomainHostdevDefPtr *hostdevs,
148+
int nhostdevs,
149+
unsigned int flags)
150+
{
151+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
152+
153+
return virHostdevPrepareUSBDevices(hostdev_mgr, CH_DRIVER_NAME, name,
154+
hostdevs, nhostdevs, flags);
155+
}
156+
157+
int
158+
chHostdevPrepareSCSIDevices(virCHDriverPtr driver,
159+
const char *name,
160+
virDomainHostdevDefPtr *hostdevs,
161+
int nhostdevs)
162+
{
163+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
164+
165+
return virHostdevPrepareSCSIDevices(hostdev_mgr, CH_DRIVER_NAME,
166+
name, hostdevs, nhostdevs);
167+
}
168+
169+
int
170+
chHostdevPrepareSCSIVHostDevices(virCHDriverPtr driver,
171+
const char *name,
172+
virDomainHostdevDefPtr *hostdevs,
173+
int nhostdevs)
174+
{
175+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
176+
177+
return virHostdevPrepareSCSIVHostDevices(hostdev_mgr, CH_DRIVER_NAME,
178+
name, hostdevs, nhostdevs);
179+
}
180+
181+
int
182+
chHostdevPrepareMediatedDevices(virCHDriverPtr driver,
183+
const char *name,
184+
virDomainHostdevDefPtr *hostdevs,
185+
int nhostdevs)
186+
{
187+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
188+
bool supportsVFIO;
189+
size_t i;
190+
191+
/* Checking for VFIO only is fine with mdev, as IOMMU isolation is achieved
192+
* by the physical parent device.
193+
*/
194+
supportsVFIO = virFileExists(CH_DEV_VFIO);
195+
196+
for (i = 0; i < nhostdevs; i++) {
197+
if (virHostdevIsMdevDevice(hostdevs[i])) {
198+
if (!supportsVFIO) {
199+
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
200+
_("Mediated host device assignment requires "
201+
"VFIO support"));
202+
return -1;
203+
}
204+
break;
205+
}
206+
}
207+
208+
return virHostdevPrepareMediatedDevices(hostdev_mgr, CH_DRIVER_NAME,
209+
name, hostdevs, nhostdevs);
210+
}
211+
212+
int
213+
chHostdevPrepareDomainDevices(virCHDriverPtr driver,
214+
virDomainDefPtr def,
215+
unsigned int flags)
216+
217+
{
218+
if (!def->nhostdevs && !def->ndisks)
219+
return 0;
220+
221+
if (chHostdevPrepareNVMeDisks(driver, def->name, def->disks, def->ndisks) < 0)
222+
return -1;
223+
224+
if (chHostdevPreparePCIDevices(driver, def->name, def->uuid,
225+
def->hostdevs, def->nhostdevs,
226+
flags) < 0)
227+
return -1;
228+
229+
if (chHostdevPrepareUSBDevices(driver, def->name,
230+
def->hostdevs, def->nhostdevs, flags) < 0)
231+
return -1;
232+
233+
if (chHostdevPrepareSCSIDevices(driver, def->name,
234+
def->hostdevs, def->nhostdevs) < 0)
235+
return -1;
236+
237+
if (chHostdevPrepareSCSIVHostDevices(driver, def->name,
238+
def->hostdevs, def->nhostdevs) < 0)
239+
return -1;
240+
241+
if (chHostdevPrepareMediatedDevices(driver, def->name,
242+
def->hostdevs, def->nhostdevs) < 0)
243+
return -1;
244+
245+
return 0;
246+
}
247+
248+
void
249+
chHostdevReAttachOneNVMeDisk(virCHDriverPtr driver,
250+
const char *name,
251+
virStorageSourcePtr src)
252+
{
253+
virHostdevReAttachOneNVMeDevice(driver->hostdevMgr,
254+
CH_DRIVER_NAME,
255+
name,
256+
src);
257+
}
258+
259+
void
260+
chHostdevReAttachNVMeDisks(virCHDriverPtr driver,
261+
const char *name,
262+
virDomainDiskDefPtr *disks,
263+
size_t ndisks)
264+
{
265+
virHostdevReAttachNVMeDevices(driver->hostdevMgr,
266+
CH_DRIVER_NAME,
267+
name, disks, ndisks);
268+
}
269+
270+
void
271+
chHostdevReAttachPCIDevices(virCHDriverPtr driver,
272+
const char *name,
273+
virDomainHostdevDefPtr *hostdevs,
274+
int nhostdevs)
275+
{
276+
virCHDriverConfigPtr cfg = virCHDriverGetConfig(driver);
277+
const char *oldStateDir = cfg->stateDir;
278+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
279+
280+
virHostdevReAttachPCIDevices(hostdev_mgr, CH_DRIVER_NAME, name,
281+
hostdevs, nhostdevs, oldStateDir);
282+
283+
virObjectUnref(cfg);
284+
}
285+
286+
void
287+
chHostdevReAttachUSBDevices(virCHDriverPtr driver,
288+
const char *name,
289+
virDomainHostdevDefPtr *hostdevs,
290+
int nhostdevs)
291+
{
292+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
293+
294+
virHostdevReAttachUSBDevices(hostdev_mgr, CH_DRIVER_NAME,
295+
name, hostdevs, nhostdevs);
296+
}
297+
298+
void
299+
chHostdevReAttachSCSIDevices(virCHDriverPtr driver,
300+
const char *name,
301+
virDomainHostdevDefPtr *hostdevs,
302+
int nhostdevs)
303+
{
304+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
305+
306+
virHostdevReAttachSCSIDevices(hostdev_mgr, CH_DRIVER_NAME,
307+
name, hostdevs, nhostdevs);
308+
}
309+
310+
void
311+
chHostdevReAttachSCSIVHostDevices(virCHDriverPtr driver,
312+
const char *name,
313+
virDomainHostdevDefPtr *hostdevs,
314+
int nhostdevs)
315+
{
316+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
317+
318+
virHostdevReAttachSCSIVHostDevices(hostdev_mgr, CH_DRIVER_NAME,
319+
name, hostdevs, nhostdevs);
320+
}
321+
322+
void
323+
chHostdevReAttachMediatedDevices(virCHDriverPtr driver,
324+
const char *name,
325+
virDomainHostdevDefPtr *hostdevs,
326+
int nhostdevs)
327+
{
328+
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
329+
330+
virHostdevReAttachMediatedDevices(hostdev_mgr, CH_DRIVER_NAME,
331+
name, hostdevs, nhostdevs);
332+
}
333+
334+
void
335+
chHostdevReAttachDomainDevices(virCHDriverPtr driver,
336+
virDomainDefPtr def)
337+
{
338+
if (!def->nhostdevs && !def->ndisks)
339+
return;
340+
341+
chHostdevReAttachNVMeDisks(driver, def->name, def->disks,
342+
def->ndisks);
343+
344+
chHostdevReAttachPCIDevices(driver, def->name, def->hostdevs,
345+
def->nhostdevs);
346+
347+
chHostdevReAttachUSBDevices(driver, def->name, def->hostdevs,
348+
def->nhostdevs);
349+
350+
chHostdevReAttachSCSIDevices(driver, def->name, def->hostdevs,
351+
def->nhostdevs);
352+
353+
chHostdevReAttachSCSIVHostDevices(driver, def->name, def->hostdevs,
354+
def->nhostdevs);
355+
356+
chHostdevReAttachMediatedDevices(driver, def->name, def->hostdevs,
357+
def->nhostdevs);
358+
}

0 commit comments

Comments
 (0)