Index: usr.sbin/bhyve/block_if.c =================================================================== --- usr.sbin/bhyve/block_if.c +++ usr.sbin/bhyve/block_if.c @@ -393,7 +393,8 @@ static void blockif_init(void) { - mevent_add(SIGCONT, EVF_SIGNAL, blockif_sigcont_handler, NULL); + mevent_add(SIGCONT, EVF_SIGNAL, blockif_sigcont_handler, NULL, + /*enabled=*/1); (void) signal(SIGCONT, SIG_IGN); } Index: usr.sbin/bhyve/gdb.c =================================================================== --- usr.sbin/bhyve/gdb.c +++ usr.sbin/bhyve/gdb.c @@ -1399,14 +1399,16 @@ warnx("Ignoring additional GDB connection."); } - read_event = mevent_add(s, EVF_READ, gdb_readable, NULL); + read_event = mevent_add(s, EVF_READ, gdb_readable, NULL, + /*enabled=*/1); if (read_event == NULL) { if (arg != NULL) err(1, "Failed to setup initial GDB connection"); pthread_mutex_unlock(&gdb_lock); return; } - write_event = mevent_add(s, EVF_WRITE, gdb_writable, NULL); + write_event = mevent_add(s, EVF_WRITE, gdb_writable, NULL, + /*enabled=*/1); if (write_event == NULL) { if (arg != NULL) err(1, "Failed to setup initial GDB connection"); @@ -1492,5 +1494,6 @@ #ifndef WITHOUT_CAPSICUM limit_gdb_socket(s); #endif - mevent_add(s, EVF_READ, new_connection, NULL); + mevent_add(s, EVF_READ, new_connection, NULL, + /*enabled=*/1); } Index: usr.sbin/bhyve/mevent.h =================================================================== --- usr.sbin/bhyve/mevent.h +++ usr.sbin/bhyve/mevent.h @@ -42,7 +42,7 @@ struct mevent *mevent_add(int fd, enum ev_type type, void (*func)(int, enum ev_type, void *), - void *param); + void *param, int enabled); int mevent_enable(struct mevent *evp); int mevent_disable(struct mevent *evp); int mevent_delete(struct mevent *evp); Index: usr.sbin/bhyve/mevent.c =================================================================== --- usr.sbin/bhyve/mevent.c +++ usr.sbin/bhyve/mevent.c @@ -62,10 +62,11 @@ #define MEVENT_MAX 64 -#define MEV_ADD 1 -#define MEV_ENABLE 2 -#define MEV_DISABLE 3 -#define MEV_DEL_PENDING 4 +#define MEV_ADD 1 +#define MEV_ENABLE 2 +#define MEV_DISABLE 3 +#define MEV_DEL_PENDING 4 +#define MEV_ADD_DISABLED 5 extern char *vmname; @@ -161,6 +162,9 @@ case MEV_ADD: ret = EV_ADD; /* implicitly enabled */ break; + case MEV_ADD_DISABLED: + ret = EV_ADD | EV_DISABLE; + break; case MEV_ENABLE: ret = EV_ENABLE; break; @@ -251,7 +255,8 @@ struct mevent * mevent_add(int tfd, enum ev_type type, - void (*func)(int, enum ev_type, void *), void *param) + void (*func)(int, enum ev_type, void *), void *param, + int enabled) { struct mevent *lp, *mevp; @@ -299,7 +304,7 @@ LIST_INSERT_HEAD(&change_head, mevp, me_list); mevp->me_cq = 1; - mevp->me_state = MEV_ADD; + mevp->me_state = enabled ? MEV_ADD : MEV_ADD_DISABLED; mevent_notify(); exit: @@ -449,7 +454,8 @@ /* * Add internal event handler for the pipe write fd */ - pipev = mevent_add(mevent_pipefd[0], EVF_READ, mevent_pipe_read, NULL); + pipev = mevent_add(mevent_pipefd[0], EVF_READ, mevent_pipe_read, NULL, + /*enabled=*/1); assert(pipev != NULL); for (;;) { Index: usr.sbin/bhyve/mevent_test.c =================================================================== --- usr.sbin/bhyve/mevent_test.c +++ usr.sbin/bhyve/mevent_test.c @@ -140,7 +140,8 @@ pthread_mutex_lock(&sync.e_mt); - mev = mevent_add(fd, EVF_READ, echoer_callback, &sync); + mev = mevent_add(fd, EVF_READ, echoer_callback, &sync, + /*enabled=*/1); if (mev == NULL) { printf("Could not allocate echoer event\n"); exit(4); @@ -219,7 +220,8 @@ exit(4); } - (void) mevent_add(s, EVF_READ, acceptor_callback, NULL); + (void) mevent_add(s, EVF_READ, acceptor_callback, NULL, + /*enabled=*/1); pthread_mutex_lock(&accept_mutex); @@ -236,7 +238,7 @@ */ first = 0; tevp = mevent_add(1, EVF_TIMER, timer_callback, - NULL); + NULL, /*enabled=*/1); } printf("incoming connection, spawning thread\n"); Index: usr.sbin/bhyve/net_backends.h =================================================================== --- usr.sbin/bhyve/net_backends.h +++ usr.sbin/bhyve/net_backends.h @@ -46,6 +46,8 @@ ssize_t netbe_send(net_backend_t *be, struct iovec *iov, int iovcnt); ssize_t netbe_recv(net_backend_t *be, struct iovec *iov, int iovcnt); ssize_t netbe_rx_discard(net_backend_t *be); +void netbe_rx_disable(net_backend_t *be); +void netbe_rx_enable(net_backend_t *be); /* Index: usr.sbin/bhyve/net_backends.c =================================================================== --- usr.sbin/bhyve/net_backends.c +++ usr.sbin/bhyve/net_backends.c @@ -110,6 +110,16 @@ ssize_t (*recv)(struct net_backend *be, struct iovec *iov, int iovcnt); /* + * Ask the backend to enable (state != 0) or disable (state == 0) + * receive operation in the backend. On return from a disable + * operation, it is guaranteed that the receive callback won't be + * called until receive is enabled again. Note however that it is up + * to the caller to make sure that netbe_recv() is not currently + * being executed by another thread. + */ + void (*recv_enable)(struct net_backend *be, int state); + + /* * Ask the backend for the virtio-net features it is able to * support. Possible features are TSO, UFO and checksum offloading * in both rx and tx direction and for both IPv4 and IPv6. @@ -209,7 +219,7 @@ errx(EX_OSERR, "Unable to apply rights for sandbox"); #endif - priv->mevp = mevent_add(be->fd, EVF_READ, cb, param); + priv->mevp = mevent_add(be->fd, EVF_READ, cb, param, /*enabled=*/1); if (priv->mevp == NULL) { WPRINTF(("Could not register event\n")); goto error; @@ -248,6 +258,18 @@ return (ret); } +static void +tap_recv_enable(struct net_backend *be, int state) +{ + struct tap_priv *priv = (struct tap_priv *)be->opaque; + + if (state) { + mevent_enable(priv->mevp); + } else { + mevent_disable(priv->mevp); + } +} + static uint64_t tap_get_cap(struct net_backend *be) { @@ -270,6 +292,7 @@ .cleanup = tap_cleanup, .send = tap_send, .recv = tap_recv, + .recv_enable = tap_recv_enable, .get_cap = tap_get_cap, .set_cap = tap_set_cap, }; @@ -282,6 +305,7 @@ .cleanup = tap_cleanup, .send = tap_send, .recv = tap_recv, + .recv_enable = tap_recv_enable, .get_cap = tap_get_cap, .set_cap = tap_set_cap, }; @@ -401,7 +425,7 @@ priv->cb_param = param; be->fd = priv->nmd->fd; - priv->mevp = mevent_add(be->fd, EVF_READ, cb, param); + priv->mevp = mevent_add(be->fd, EVF_READ, cb, param, /*enabled=*/1); if (priv->mevp == NULL) { WPRINTF(("Could not register event\n")); return (-1); @@ -571,6 +595,18 @@ return (totlen); } +static void +netmap_recv_enable(struct net_backend *be, int state) +{ + struct netmap_priv *priv = (struct netmap_priv *)be->opaque; + + if (state) { + mevent_enable(priv->mevp); + } else { + mevent_disable(priv->mevp); + } +} + static struct net_backend netmap_backend = { .prefix = "netmap", .priv_size = sizeof(struct netmap_priv), @@ -578,6 +614,7 @@ .cleanup = netmap_cleanup, .send = netmap_send, .recv = netmap_recv, + .recv_enable = netmap_recv_enable, .get_cap = netmap_get_cap, .set_cap = netmap_set_cap, }; @@ -590,6 +627,7 @@ .cleanup = netmap_cleanup, .send = netmap_send, .recv = netmap_recv, + .recv_enable = netmap_recv_enable, .get_cap = netmap_get_cap, .set_cap = netmap_set_cap, }; @@ -805,3 +843,16 @@ return netbe_recv(be, &iov, 1); } +void +netbe_rx_disable(struct net_backend *be) +{ + + return be->recv_enable(be, /*enable=*/0); +} + +void +netbe_rx_enable(struct net_backend *be) +{ + + return be->recv_enable(be, /*enable=*/1); +} Index: usr.sbin/bhyve/pci_e82545.c =================================================================== --- usr.sbin/bhyve/pci_e82545.c +++ usr.sbin/bhyve/pci_e82545.c @@ -594,7 +594,8 @@ if (sc->esc_ITR != 0) { sc->esc_mevpitr = mevent_add( (sc->esc_ITR + 3905) / 3906, /* 256ns -> 1ms */ - EVF_TIMER, e82545_itr_callback, sc); + EVF_TIMER, e82545_itr_callback, sc, + /*enabled=*/1); } } } @@ -622,7 +623,8 @@ if (sc->esc_ITR != 0) { sc->esc_mevpitr = mevent_add( (sc->esc_ITR + 3905) / 3906, /* 256ns -> 1ms */ - EVF_TIMER, e82545_itr_callback, sc); + EVF_TIMER, e82545_itr_callback, sc, + /*enabled=*/1); } } } Index: usr.sbin/bhyve/pci_virtio_console.c =================================================================== --- usr.sbin/bhyve/pci_virtio_console.c +++ usr.sbin/bhyve/pci_virtio_console.c @@ -345,7 +345,7 @@ sock->vss_conn_fd = -1; sock->vss_server_fd = s; sock->vss_server_evp = mevent_add(s, EVF_READ, pci_vtcon_sock_accept, - sock); + sock, /*enabled=*/1); if (sock->vss_server_evp == NULL) { error = -1; @@ -382,7 +382,8 @@ sock->vss_open = true; sock->vss_conn_fd = s; - sock->vss_conn_evp = mevent_add(s, EVF_READ, pci_vtcon_sock_rx, sock); + sock->vss_conn_evp = mevent_add(s, EVF_READ, pci_vtcon_sock_rx, sock, + /*enabled=*/1); pci_vtcon_open_port(sock->vss_port, true); } Index: usr.sbin/bhyve/pm.c =================================================================== --- usr.sbin/bhyve/pm.c +++ usr.sbin/bhyve/pm.c @@ -282,7 +282,7 @@ pm1_control |= PM1_SCI_EN; if (power_button == NULL) { power_button = mevent_add(SIGTERM, EVF_SIGNAL, - power_button_handler, ctx); + power_button_handler, ctx, /*enabled=*/1); old_power_handler = signal(SIGTERM, SIG_IGN); } break; Index: usr.sbin/bhyve/uart_emul.c =================================================================== --- usr.sbin/bhyve/uart_emul.c +++ usr.sbin/bhyve/uart_emul.c @@ -276,7 +276,8 @@ { ttyopen(&sc->tty); - sc->mev = mevent_add(sc->tty.rfd, EVF_READ, uart_drain, sc); + sc->mev = mevent_add(sc->tty.rfd, EVF_READ, uart_drain, sc, + /*enabled=*/1); assert(sc->mev != NULL); }