guest侧virtio probe + qemu侧 vhost_dev_init + kernel vhost + vhost user +unix域套接字

guest侧virtio probe

https://www.jianshu.com/p/e4b29d16bae4

https://kernelgo.org/virtio-overview.html

 https://blog.csdn.net/qq_15437629/article/details/82084470

virtio 虚拟化系列之一:从 virtio 论文开始

https://zhuanlan.zhihu.com/p/68154666

前端驱动通知后端:
内核流程mark一下PCI设备驱动流程这个后面可以学习一下,先扫描PCI bus发现是virtio设备再扫描virtio-busworker_thread --> process_one_work --> pciehp_power_thread --> pciehp_enable_slot --> 
pciehp_configure_device --> pci_bus_add_devices --> pci_bus_add_device --> device_attach --> 
__device_attach --> bus_for_each_drv --> __device_attach_driver --> driver_probe_device --> 
pci_device_probe --> local_pci_probe --> virtio_pci_probe --> register_virtio_device --> 
device_register --> device_add --> bus_probe_device --> device_initial_probe 
--> __device_attach --> bus_for_each_drv --> __device_attach_driver -->
driver_probe_device --> virtio_dev_probe --> virtnet_probe (网卡设备驱动加载的入口)

static int virtnet_probe(struct virtio_device *vdev) 
{
    ......
    virtio_device_ready(vdev);
}

qemu侧 vhost_dev_init---- vsock也有
hw/block/vhost-user-blk.c:318:    ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
hw/virtio/vhost-vsock.c:345:    ret = vhost_dev_init(&vsock->vhost_dev, (void *)(uintptr_t)vhostfd,
hw/virtio/vhost-vsock.c:348:        error_setg_errno(errp, -ret, "vhost-vsock: vhost_dev_init failed");
hw/virtio/vhost-user-fs.c:384:    ret = vhost_dev_init(&fs->vhost_dev, &fs->vhost_user,
hw/virtio/vhost-user-fs.c:387:        error_setg_errno(errp, -ret, "vhost_dev_init failed");
hw/virtio/vhost.c:1180:int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
hw/scsi/vhost-user-scsi.c:97:    ret = vhost_dev_init(&vsc->dev, &s->vhost_user,
hw/scsi/vhost-scsi.c:190:    ret = vhost_dev_init(&vsc->dev, (void *)(uintptr_t)vhostfd,
hw/net/vhost_net.c:174:    r = vhost_dev_init(&net->dev, options->opaque,
include/hw/virtio/vhost
kernel vhost + vhost user


 vhost_dev_init-->vhost_virtqueue_init-->vhost_virtqueue_init-->vhost_set_vring_call
    hw/virtio/vhost-user.c:1935:        .vhost_set_vring_call = vhost_user_set_vring_call,
    hw/virtio/vhost-backend.c:256:        .vhost_set_vring_call = vhost_kernel_set_vring_call,
kernel vhost 还是 vhost user
 
273 int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
274 {
275     int r = 0;
276 
277     switch (backend_type) {
278 #ifdef CONFIG_VHOST_KERNEL
279     case VHOST_BACKEND_TYPE_KERNEL:
280         dev->vhost_ops = &kernel_ops;
281         break;
282 #endif
283 #ifdef CONFIG_VHOST_USER
284     case VHOST_BACKEND_TYPE_USER:
285         dev->vhost_ops = &user_ops;
286         break;
287 #endif
288     default:
289         error_report("Unknown vhost backend type");
290         r = -1;
291     }
292 
293     return r;
294 }
 vhost_user设置unix域套接字
 vhost_user_backend_init()

---------........

---------vhost_setup_slave_channel(dev)

------------------.........

------------------qemu_set_fd_handler(u->slave_fd, slave_read, NULL, dev)

------------------.......

Qemu IO事件处理框架

qemu添加fd

用户添加fd的函数为qemu_set_fd_handler,参数中fd为本次添加的fd,后面分别是对该fd的处理函数(read or write),最后opaque为处理函数的参数。

https://www.cnblogs.com/ck1020/p/8782032.html


 vhost_user设置unix域套接字服务端

比如contrib/virtiofsd/fuse_virtio.c:722:int virtio_session_mount(struct fuse_session *se)  创建服务端
721 
722 int virtio_session_mount(struct fuse_session *se)
723 {
724         struct sockaddr_un un;
725 
726         if (strlen(se->vu_socket_path) >= sizeof(un.sun_path)) {
727                 fprintf(stderr, "Socket path too long
");
728                 return -1;
729         }
730 
731         /* Poison the fuse FD so we spot if we accidentally use it;
732          * DO NOT check for this value, check for se->vu_socket_path
733          */
734         se->fd = 0xdaff0d11;
735 
736         /* Create the Unix socket to communicate with qemu
737          * based on QEMU's vhost-user-bridge
738          */
739         unlink(se->vu_socket_path);
740         strcpy(un.sun_path, se->vu_socket_path);
741         size_t addr_len = sizeof(un.sun_family) + strlen(se->vu_socket_path);
742 
743         int listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
744         if (listen_sock == -1) {
745                perror("vhost socket creation");
746                return -1;
747         }
748         un.sun_family = AF_UNIX;
749 
750         if (bind(listen_sock, (struct sockaddr *) &un, addr_len) == -1) {
751                 perror("vhost socket bind");
752                 return -1;
753         }
754 
755         if (listen(listen_sock, 1) == -1) {
756                 perror("vhost socket listen");
757                 return -1;
758         }
759 
760         fprintf(stderr, "%s: Waiting for vhost-user socket connection...
", __func__);
761         int data_sock = accept(listen_sock, NULL, NULL);
762         if (data_sock == -1) {
763                 perror("vhost socket accept");
764                 close(listen_sock);
765                 return -1;
766         }
767         close(listen_sock);
768         fprintf(stderr, "%s: Received vhost-user socket connection
", __func__);
769         se->vu_socketfd = data_sock;

770 
771         /* TODO: Some cleanup/deallocation! */
772         se->virtio_dev = calloc(sizeof(struct fv_VuDev), 1);
773         se->virtio_dev->se = se;
774         vu_init(&se->virtio_dev->dev, se->vu_socketfd,
775                 fv_panic,
776                 fv_set_watch, fv_remove_watch,
777                 &fv_iface);
778 
779         return 0;
780 }
gueset kernel 会调用_class_init

前端驱动通知后端:
内核流程mark一下PCI设备驱动流程这个后面可以学习一下,先扫描PCI bus发现是virtio设备再扫描virtio-busworker_thread --> process_one_work --> pciehp_power_thread --> pciehp_enable_slot --> 
pciehp_configure_device --> pci_bus_add_devices --> pci_bus_add_device --> device_attach --> 
__device_attach --> bus_for_each_drv --> __device_attach_driver --> driver_probe_device --> 
pci_device_probe --> local_pci_probe --> virtio_pci_probe --> register_virtio_device --> 
device_register --> device_add --> bus_probe_device --> device_initial_probe 
--> __device_attach --> bus_for_each_drv --> __device_attach_driver -->
driver_probe_device --> virtio_dev_probe --> virtnet_probe (网卡设备驱动加载的入口)
static int virtnet_probe(struct virtio_device *vdev) 
{
    ......
    virtio_device_ready(vdev);
}

/**
 * virtio_device_ready - enable vq use in probe function
 * @vdev: the device
 *
 * Driver must call this to use vqs in the probe function.
 *
 * Note: vqs are enabled automatically after probe returns.
 */
static inline
void virtio_device_ready(struct virtio_device *dev)
{
        unsigned status = dev->config->get_status(dev);

        BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
        dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
}
 



原文地址:https://www.cnblogs.com/dream397/p/13867951.html