static void vhost_vsock_stop(VirtIODevice *vdev) { VHostVSock *vsock = VHOST_VSOCK(vdev); BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; if (!k->set_guest_notifiers) { return; } ret = vhost_vsock_set_running(vsock, 0); if (ret < 0) { error_report("vhost vsock set running failed: %d", ret); return; } vhost_dev_stop(&vsock->vhost_dev, vdev); ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false); if (ret < 0) { error_report("vhost guest notifier cleanup failed: %d", ret); return; } vhost_dev_disable_notifiers(&vsock->vhost_dev, vdev); }
void vhost_net_stop(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { .fd = -1 }; for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } net->vc->info->poll(net->vc, true); vhost_dev_stop(&net->dev, dev); if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); } vhost_dev_disable_notifiers(&net->dev, dev); } void vhost_net_cleanup(struct vhost_net *net) { vhost_dev_cleanup(&net->dev); if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); } g_free(net); }
static int vhost_net_start_one(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { }; int r; net->dev.nvqs = 2; net->dev.vqs = net->vqs; r = vhost_dev_enable_notifiers(&net->dev, dev); if (r < 0) { goto fail_notifiers; } r = vhost_dev_start(&net->dev, dev); if (r < 0) { goto fail_start; } if (net->nc->info->poll) { net->nc->info->poll(net->nc, false); } if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { qemu_set_fd_handler(net->backend, NULL, NULL, NULL); file.fd = net->backend; for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { const VhostOps *vhost_ops = net->dev.vhost_ops; r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, &file); if (r < 0) { r = -errno; goto fail; } } } return 0; fail: file.fd = -1; if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { while (file.index-- > 0) { const VhostOps *vhost_ops = net->dev.vhost_ops; int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } } if (net->nc->info->poll) { net->nc->info->poll(net->nc, true); } vhost_dev_stop(&net->dev, dev); fail_start: vhost_dev_disable_notifiers(&net->dev, dev); fail_notifiers: return r; }
static void vhost_vsock_start(VirtIODevice *vdev) { VHostVSock *vsock = VHOST_VSOCK(vdev); BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret; int i; if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); return; } ret = vhost_dev_enable_notifiers(&vsock->vhost_dev, vdev); if (ret < 0) { error_report("Error enabling host notifiers: %d", -ret); return; } ret = k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, true); if (ret < 0) { error_report("Error binding guest notifier: %d", -ret); goto err_host_notifiers; } vsock->vhost_dev.acked_features = vdev->guest_features; ret = vhost_dev_start(&vsock->vhost_dev, vdev); if (ret < 0) { error_report("Error starting vhost: %d", -ret); goto err_guest_notifiers; } ret = vhost_vsock_set_running(vsock, 1); if (ret < 0) { error_report("Error starting vhost vsock: %d", -ret); goto err_dev_start; } /* guest_notifier_mask/pending not used yet, so just unmask * everything here. virtio-pci will do the right thing by * enabling/disabling irqfd. */ for (i = 0; i < vsock->vhost_dev.nvqs; i++) { vhost_virtqueue_mask(&vsock->vhost_dev, vdev, i, false); } return; err_dev_start: vhost_dev_stop(&vsock->vhost_dev, vdev); err_guest_notifiers: k->set_guest_notifiers(qbus->parent, vsock->vhost_dev.nvqs, false); err_host_notifiers: vhost_dev_disable_notifiers(&vsock->vhost_dev, vdev); }
static void vhost_net_stop_one(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { .fd = -1 }; if (!net->dev.started) { return; } for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } net->nc->info->poll(net->nc, true); vhost_dev_stop(&net->dev, dev); vhost_dev_disable_notifiers(&net->dev, dev); } int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, int total_queues) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); int r, i = 0; if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); r = -ENOSYS; goto err; } for (i = 0; i < total_queues; i++) { r = vhost_net_start_one(tap_get_vhost_net(ncs[i].peer), dev, i * 2); if (r < 0) { goto err; } } r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); if (r < 0) { error_report("Error binding guest notifier: %d", -r); goto err; } return 0; err: while (--i >= 0) { vhost_net_stop_one(tap_get_vhost_net(ncs[i].peer), dev); } return r; }
int vhost_net_start(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { }; int r; net->dev.nvqs = 2; net->dev.vqs = net->vqs; r = vhost_dev_enable_notifiers(&net->dev, dev); if (r < 0) { goto fail_notifiers; } if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr_mrg_rxbuf)); } r = vhost_dev_start(&net->dev, dev); if (r < 0) { goto fail_start; } net->vc->info->poll(net->vc, false); qemu_set_fd_handler(net->backend, NULL, NULL, NULL); file.fd = net->backend; for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); if (r < 0) { r = -errno; goto fail; } } return 0; fail: file.fd = -1; while (file.index-- > 0) { int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } net->vc->info->poll(net->vc, true); vhost_dev_stop(&net->dev, dev); if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) { tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr)); } fail_start: vhost_dev_disable_notifiers(&net->dev, dev); fail_notifiers: return r; }
static int vhost_net_start_one(struct vhost_net *net, VirtIODevice *dev, int vq_index) { struct vhost_vring_file file = { }; int r; if (net->dev.started) { return 0; } net->dev.nvqs = 2; net->dev.vqs = net->vqs; net->dev.vq_index = vq_index; r = vhost_dev_enable_notifiers(&net->dev, dev); if (r < 0) { goto fail_notifiers; } r = vhost_dev_start(&net->dev, dev); if (r < 0) { goto fail_start; } net->nc->info->poll(net->nc, false); qemu_set_fd_handler(net->backend, NULL, NULL, NULL); file.fd = net->backend; for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); if (r < 0) { r = -errno; goto fail; } } return 0; fail: file.fd = -1; while (file.index-- > 0) { int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } net->nc->info->poll(net->nc, true); vhost_dev_stop(&net->dev, dev); fail_start: vhost_dev_disable_notifiers(&net->dev, dev); fail_notifiers: return r; }
int vhost_scsi_common_start(VHostSCSICommon *vsc) { int ret, i; VirtIODevice *vdev = VIRTIO_DEVICE(vsc); BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); return -ENOSYS; } ret = vhost_dev_enable_notifiers(&vsc->dev, vdev); if (ret < 0) { return ret; } ret = k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, true); if (ret < 0) { error_report("Error binding guest notifier"); goto err_host_notifiers; } vsc->dev.acked_features = vdev->guest_features; ret = vhost_dev_start(&vsc->dev, vdev); if (ret < 0) { error_report("Error start vhost dev"); goto err_guest_notifiers; } /* guest_notifier_mask/pending not used yet, so just unmask * everything here. virtio-pci will do the right thing by * enabling/disabling irqfd. */ for (i = 0; i < vsc->dev.nvqs; i++) { vhost_virtqueue_mask(&vsc->dev, vdev, vsc->dev.vq_index + i, false); } return ret; err_guest_notifiers: k->set_guest_notifiers(qbus->parent, vsc->dev.nvqs, false); err_host_notifiers: vhost_dev_disable_notifiers(&vsc->dev, vdev); return ret; }
static void vhost_scsi_stop(VHostSCSI *s) { VirtIODevice *vdev = VIRTIO_DEVICE(s); BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); int ret = 0; if (k->set_guest_notifiers) { ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false); if (ret < 0) { error_report("vhost guest notifier cleanup failed: %d\n", ret); } } assert(ret >= 0); vhost_scsi_clear_endpoint(s); vhost_dev_stop(&s->dev, vdev); vhost_dev_disable_notifiers(&s->dev, vdev); }
void vhost_net_stop(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { .fd = -1 }; for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { int r = ioctl(net->dev.control, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } net->nc->info->poll(net->nc, true); vhost_dev_stop(&net->dev, dev); vhost_dev_disable_notifiers(&net->dev, dev); } void vhost_net_cleanup(struct vhost_net *net) { vhost_dev_cleanup(&net->dev); g_free(net); }
static int vhost_scsi_start(VHostSCSI *s) { int ret, abi_version, i; VirtIODevice *vdev = VIRTIO_DEVICE(s); BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); return -ENOSYS; } ret = ioctl(s->dev.control, VHOST_SCSI_GET_ABI_VERSION, &abi_version); if (ret < 0) { return -errno; } if (abi_version > VHOST_SCSI_ABI_VERSION) { error_report("vhost-scsi: The running tcm_vhost kernel abi_version:" " %d is greater than vhost_scsi userspace supports: %d, please" " upgrade your version of QEMU\n", abi_version, VHOST_SCSI_ABI_VERSION); return -ENOSYS; } ret = vhost_dev_enable_notifiers(&s->dev, vdev); if (ret < 0) { return ret; } s->dev.acked_features = vdev->guest_features; ret = vhost_dev_start(&s->dev, vdev); if (ret < 0) { error_report("Error start vhost dev"); goto err_notifiers; } ret = vhost_scsi_set_endpoint(s); if (ret < 0) { error_report("Error set vhost-scsi endpoint"); goto err_vhost_stop; } ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true); if (ret < 0) { error_report("Error binding guest notifier"); goto err_endpoint; } /* guest_notifier_mask/pending not used yet, so just unmask * everything here. virtio-pci will do the right thing by * enabling/disabling irqfd. */ for (i = 0; i < s->dev.nvqs; i++) { vhost_virtqueue_mask(&s->dev, vdev, i, false); } return ret; err_endpoint: vhost_scsi_clear_endpoint(s); err_vhost_stop: vhost_dev_stop(&s->dev, vdev); err_notifiers: vhost_dev_disable_notifiers(&s->dev, vdev); return ret; }
static void vhost_net_stop_one(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { .fd = -1 }; if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { const VhostOps *vhost_ops = net->dev.vhost_ops; int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } } if (net->nc->info->poll) { net->nc->info->poll(net->nc, true); } vhost_dev_stop(&net->dev, dev); vhost_dev_disable_notifiers(&net->dev, dev); } static bool vhost_net_device_endian_ok(VirtIODevice *vdev) { #ifdef TARGET_IS_BIENDIAN #ifdef HOST_WORDS_BIGENDIAN return virtio_is_big_endian(vdev); #else return !virtio_is_big_endian(vdev); #endif #else return true; #endif } int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, int total_queues) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); int r, e, i; if (!vhost_net_device_endian_ok(dev)) { error_report("vhost-net does not support cross-endian"); r = -ENOSYS; goto err; } if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); r = -ENOSYS; goto err; } for (i = 0; i < total_queues; i++) { vhost_net_set_vq_index(get_vhost_net(ncs[i].peer), i * 2); } r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); if (r < 0) { error_report("Error binding guest notifier: %d", -r); goto err; } for (i = 0; i < total_queues; i++) { r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev); if (r < 0) { goto err_start; } } return 0; err_start: while (--i >= 0) { vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); } e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); if (e < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e); fflush(stderr); } err: return r; }
static void vhost_net_stop_one(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { .fd = -1 }; if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { const VhostOps *vhost_ops = net->dev.vhost_ops; int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, &file); assert(r >= 0); } } if (net->nc->info->poll) { net->nc->info->poll(net->nc, true); } vhost_dev_stop(&net->dev, dev); vhost_dev_disable_notifiers(&net->dev, dev); } int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, int total_queues) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); int r, e, i; if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); r = -ENOSYS; goto err; } r = vhost_net_set_vnet_endian(dev, ncs[0].peer, true); if (r < 0) { goto err; } for (i = 0; i < total_queues; i++) { struct vhost_net *net; net = get_vhost_net(ncs[i].peer); vhost_net_set_vq_index(net, i * 2); /* Suppress the masking guest notifiers on vhost user * because vhost user doesn't interrupt masking/unmasking * properly. */ if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) { dev->use_guest_notifier_mask = false; } } r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); if (r < 0) { error_report("Error binding guest notifier: %d", -r); goto err_endian; } for (i = 0; i < total_queues; i++) { r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev); if (r < 0) { goto err_start; } if (ncs[i].peer->vring_enable) { /* restore vring enable state */ r = vhost_set_vring_enable(ncs[i].peer, ncs[i].peer->vring_enable); if (r < 0) { goto err_start; } } } return 0; err_start: while (--i >= 0) { vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); } e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); if (e < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e); fflush(stderr); } err_endian: vhost_net_set_vnet_endian(dev, ncs[0].peer, false); err: return r; }
static void vhost_net_stop_one(struct vhost_net *net, VirtIODevice *dev) { struct vhost_vring_file file = { .fd = -1 }; if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { const VhostOps *vhost_ops = net->dev.vhost_ops; int r = vhost_ops->vhost_net_set_backend(&net->dev, &file); assert(r >= 0); } } if (net->nc->info->poll) { net->nc->info->poll(net->nc, true); } vhost_dev_stop(&net->dev, dev); vhost_dev_disable_notifiers(&net->dev, dev); } int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, int total_queues) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); int r, e, i, j; if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); return -ENOSYS; } for (j = 0; j < total_queues; j++) { r = vhost_net_set_vnet_endian(dev, ncs[j].peer, true); if (r < 0) { goto err_endian; } vhost_net_set_vq_index(get_vhost_net(ncs[j].peer), j * 2); } r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); if (r < 0) { error_report("Error binding guest notifier: %d", -r); goto err_endian; } for (i = 0; i < total_queues; i++) { r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev); if (r < 0) { goto err_start; } } return 0; err_start: while (--i >= 0) { vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); } e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); if (e < 0) { fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e); fflush(stderr); } err_endian: while (--j >= 0) { vhost_net_set_vnet_endian(dev, ncs[j].peer, false); } return r; }