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