diff options
Diffstat (limited to 'usr.sbin/bhyve/pci_virtio_net.c')
-rw-r--r-- | usr.sbin/bhyve/pci_virtio_net.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c index adc2731285851..a0fcd9055e652 100644 --- a/usr.sbin/bhyve/pci_virtio_net.c +++ b/usr.sbin/bhyve/pci_virtio_net.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/select.h> #include <sys/uio.h> #include <sys/ioctl.h> +#include <machine/vmm_snapshot.h> #include <net/ethernet.h> #include <net/if.h> /* IFNAMSIZ */ @@ -134,6 +135,11 @@ static void pci_vtnet_reset(void *); static int pci_vtnet_cfgread(void *, int, int, uint32_t *); static int pci_vtnet_cfgwrite(void *, int, int, uint32_t); static void pci_vtnet_neg_features(void *, uint64_t); +#ifdef BHYVE_SNAPSHOT +static void pci_vtnet_pause(void *); +static void pci_vtnet_resume(void *); +static int pci_vtnet_snapshot(void *, struct vm_snapshot_meta *); +#endif static struct virtio_consts vtnet_vi_consts = { "vtnet", /* our name */ @@ -145,6 +151,11 @@ static struct virtio_consts vtnet_vi_consts = { pci_vtnet_cfgwrite, /* write PCI config */ pci_vtnet_neg_features, /* apply negotiated features */ VTNET_S_HOSTCAPS, /* our capabilities */ +#ifdef BHYVE_SNAPSHOT + pci_vtnet_pause, /* pause rx/tx threads */ + pci_vtnet_resume, /* resume rx/tx threads */ + pci_vtnet_snapshot, /* save / restore device state */ +#endif }; static void @@ -740,10 +751,80 @@ pci_vtnet_neg_features(void *vsc, uint64_t negotiated_features) assert(sc->be_vhdrlen == 0 || sc->be_vhdrlen == sc->vhdrlen); } +#ifdef BHYVE_SNAPSHOT +static void +pci_vtnet_pause(void *vsc) +{ + struct pci_vtnet_softc *sc = vsc; + + DPRINTF(("vtnet: device pause requested !\n")); + + /* Acquire the RX lock to block RX processing. */ + pthread_mutex_lock(&sc->rx_mtx); + + /* Wait for the transmit thread to finish its processing. */ + pthread_mutex_lock(&sc->tx_mtx); + while (sc->tx_in_progress) { + pthread_mutex_unlock(&sc->tx_mtx); + usleep(10000); + pthread_mutex_lock(&sc->tx_mtx); + } +} + +static void +pci_vtnet_resume(void *vsc) +{ + struct pci_vtnet_softc *sc = vsc; + + DPRINTF(("vtnet: device resume requested !\n")); + + pthread_mutex_unlock(&sc->tx_mtx); + /* The RX lock should have been acquired in vtnet_pause. */ + pthread_mutex_unlock(&sc->rx_mtx); +} + +static int +pci_vtnet_snapshot(void *vsc, struct vm_snapshot_meta *meta) +{ + int ret; + struct pci_vtnet_softc *sc = vsc; + + DPRINTF(("vtnet: device snapshot requested !\n")); + + /* + * Queues and consts should have been saved by the more generic + * vi_pci_snapshot function. We need to save only our features and + * config. + */ + + SNAPSHOT_VAR_OR_LEAVE(sc->vsc_features, meta, ret, done); + + /* Force reapply negociated features at restore time */ + if (meta->op == VM_SNAPSHOT_RESTORE) { + pci_vtnet_neg_features(sc, sc->vsc_features); + netbe_rx_enable(sc->vsc_be); + } + + SNAPSHOT_VAR_OR_LEAVE(sc->vsc_config, meta, ret, done); + SNAPSHOT_VAR_OR_LEAVE(sc->rx_merge, meta, ret, done); + + SNAPSHOT_VAR_OR_LEAVE(sc->vhdrlen, meta, ret, done); + SNAPSHOT_VAR_OR_LEAVE(sc->be_vhdrlen, meta, ret, done); + +done: + return (ret); +} +#endif + static struct pci_devemu pci_de_vnet = { .pe_emu = "virtio-net", .pe_init = pci_vtnet_init, .pe_barwrite = vi_pci_write, - .pe_barread = vi_pci_read + .pe_barread = vi_pci_read, +#ifdef BHYVE_SNAPSHOT + .pe_snapshot = vi_pci_snapshot, + .pe_pause = vi_pci_pause, + .pe_resume = vi_pci_resume, +#endif }; PCI_EMUL_SET(pci_de_vnet); |