Hi, List,
As the mail I've sent a week before:
https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html
I'm willing to push this work forward so that the passthrough APIs
could be reused by qemu driver and libxl driver (which doesn't support
pci passthrough yet and tries to add this function recently), or other
drivers.
But since this work affacts a lot, I'm not sure if I can control it in
a correct way. I write a draft to describe what I'm considering how to
do, as in the following and in attachment. Hope to get your review,
comment and guidence to improve the work before start coding. Any
feedback will be very appreciated!
Thanks!
Chunyan
------------------------
DRAFT:
Write separate module for hostdev passthrough
1. Purposes:
* Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so
that they could be reused by other hypervisors too
* Maintain global in-use state of hostdevs
2. Module design (draft):
* New module name: hostdev_driver
* New module files: hostdev_driver.ch hostdev_conf.ch
* New Definitions:
## [src/driver.h]
typedef struct _virHostdevDriver virHostdevDriver;
typedef virHostdevDriver *virHostdevDriverPtr;
struct _virHosedevDriver {
const char *name;
virDrvOpen open;
virDrvClose close;
virDrvPrepareHostdevs prepareHostdevs;
virDrvPreparePciHostdevs preparePciHostdevs;
virDrvprepareUsbHostdevs prepareUsbHostdevs;
virDrvReattachHostdevs reattachHostdevs;
virDrvReattachPciHostdevs reattachPciHostdevs;
virDrvReattachUsbHostdevs reattachUsbHostdevs;
virDrvGetActivePciHostdevList getActivePciHostdevList;
virDrvGetActiveUsbHostdevList getActiveUsbHostdevList;
virDrvGetDomainActivePciHostdevList
getDomainActivePciHostdevList;
virDrvGetDomainActiveUsbHostdevList
getDomainActiveUsbHostdevList;
};
## [src/hostdev/hostdev_conf.h]
typedef struct _virHostdevDriverState virHostdevDriverState;
typedef virHostdevDriverState *virHostdevDriverStatePtr;
struct _virHostdevDriverState {
virMutex lock;
virPCIDeviceListPtr activePciHostdevs;
virPCIDeviceListPtr inactivePciHostdevs;
virUSBDeviceListPtr activeUsbHostdevs;
};
## [src/hostdev/hostdev_driver.c]
static virHostdevDriver hostdevDriver = {
.name = "hostdev",
.open = hostdevDriverOpen,
.close = hostdevDriverClose,
.prepareHostdevs = virPrepareHostdevs,
.preparePciHostdevs = virPreparePciHostdevs,
.prepareUsbHostdevs = virPrepareUsbHostdevs
.reattachHostdevs = virReattachHostdevs,
.reattachPciHostdevs = virReattachPciHostdevs,
.reattachUsbHostdevs = virReattachUsbHostdevs,
.getActivePciHostdevList = virGetActivePciHostdevList,
.getActiveUsbHostdevList = virGetActiveUsbHostdevList,
.getDomainActivePciHostdevList = virGetDomainActivePciHostdevList,
.getDomainActiveUsbHostdevList = virGetDomainActiveUsbHostdevList,
};
static virStateDriver hostdevStateDriver = {
.name = "hostdev",
.initialize = hostdevDriverStartup,
.cleanup = hostdevDriverCleanup,
.reload = hostdevDriverReload,
};
* Changed Definitions:
struct _virPCIDevice {
......
--- const char *used_by; /* The domain which uses the device */
+++ virDomainObjPtr used_by; /* include domname and conn info */
......
};
struct _virUSBDevice {
......
--- const char *used_by; /* name of the domain using this dev */
+++ virDomainObjPtr used_by; /* include domname and conn info */
};
* APIs:
typedef int
(*virDrvPrepareHostdevs)(virHostdevDriverPtr driver,
virDomainObjPtr vm,
unsigned int flags);
/*
- workflow:
call PrepareHostdevPciDevices and PrepareHostdevUsbDevices
to do specific work.
- reference:
int qemuPrepareHostDevices(virQEMUDriverPtr driver,
virDomainDefPtr def,
bool coldBoot);
- new parameter:
- flags:
- could set "coldBoot" for usb usage
- could set hypervisor tag since for qemu it will use
pci-stub, for libxl, it will use pciback.
*/
typedef int
(*virDrvPreparePciHostdevs)(virHostdevDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs,
unsigned int flags);
/*
- workflow:
1. check things (e.g. assignability to non-managed device)
2. detach managed device and reset work
3. set usedby to 'vm', update activePciHostdevs and
inactivePciHostdevs
- reference:
int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver,
const char *name,
const unsigned char *uuid,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs);
*/
typedef int
(*virDrvprepareUsbHostdevs)((virHostdevDriverPtr driver,
virDomainObjPtr vm,
virUSBDeviceListPtr list);
/*
- workflow:
check usb device, set usedby to 'vm', update activeUsbHostdevs
- reference:
int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver,
const char *name,
virUSBDeviceListPtr list);
*/
typedef void
(*virDrvReattachHostdevs)(virHostdevDriverPtr driver,
virDomainObjPtr vm);
/*
- workflow:
call reattachPciHostDevices and reattachUsbHostDevices to
do specific work.
- reference:
void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver,
virDomainDefPtr def)
*/
typedef void
(*virDrvReattachPciHostdevs) (virHostdevDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs);
/*
- workflow:
unbind and bind to original driver, free
usedby, activePciHostdevs and inactivePciHostdevs.
- reference:
void qemuDomainReAttachHostdevDevices(virQEMUDriverPtrdriver,
const char *name,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs)
*/
typedef void
(*virDrvReattachUsbHostdevs) (virHostdevDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs);
/*
- workflow:
free usedby, activePciHostdevs and inactivePciHostdevs.
- reference:
static void
qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver,
const char *name,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs)
*/
typedef virPCIDeviceListPtr
(*virDrvGetActivePciHostdevList) (virHostdevDriverPtr driver);
/*
- could be used to check if a pci hostdev is already in-use.
*/
typedef virUSBDeviceListPtr
(*virDrvGetActiveUsbHostdevList) (virHostdevDriverPtr driver);
/*
- could be used to check if a usb hostdev is already in-use.
*/
typedef virPCIDeviceListPtr
(*virDrvGetDomainActivePciHostdevList) (virHostdevDriverPtr driver);
/*
- could be used to reattach all in-use pci hostdevs by a
domain (e.g. when a domain shutdown)
*/
typedef virPCIDeviceListPtr
(*virDrvGetDomainActiveUsbHostdevList) (virHostdevDriverPtr driver);
/*
- could be used to reattach all in-use usb hostdevs by a
domain
*/
3. Use the module
* Register hostdev driver
- define 'virHostdevDriverTab' and 'virHostdevDriverTabCount'
- add hostdev driver register work in libvirtd.c daemonInitialize()
* add hostdev driver areas to _virConnect
struct _virConnect {
.......
virNWFilterDriverPtr nwfilterDriver;
+++ virHostdevDriverPtr hostdevDriver;
.......
void * nwfilterPrivateData;
+++ void * hostdevPrivateData;
.......
}
* add conn->hostdevDriver parser in libvirt.c: do_open()
Then hypervisor drivers can get use of hostdev driver APIs.
* moments that could be affacted:
- domain start/shutoff
- attach/detach hostdev to domain
--------------------------------------------