假如我们加个参数vhost=on,vhost定义了一堆api,qemu把virtio收发包和用于通知收发包的功能offload给kernel vhost-net了,这包就不用从kernel到用户态的qemu,再从qemu共享给guest,直接从kernel共享给guest,减少一次kernel到用户态qemu的复制开销。
qemu对vhost-net初始化,重点关注qemu把address_space发给kernel vhost-net了,同时内核创建了一个线程叫做vhost-worker,是真正收发包干活的。
- vhost_dev_init
- ├─vhost_virtqueue_init
- | └─vhost_set_vring_call
- └─memory_listener_register
- └─listener_add_address_space
- ├─vhost_begin
- ├─vhost_log_global_start
- | └─vhost_migration_log
- | └─vhost_dev_set_log
- | └─vhost_kernel_set_vring_add
- ├─vhost_log_start
- ├─vhost_region_addnop
- | └─vhost_region_add_section
- └─vhost_commit
- └─vhost_kernel_set_mem_table(VHOST_SET_MEM_TABLE)
- └─调用到内核vhost_set_memory
- └─vhost_new_umem_range
通知机制这样处理,把负责通知的fd分别给了kvm和vhost-net,以后kvm就通知给vhost-net了,不再和qemu通信。如果qemu模拟中断,处理中断注入和开关中断 。还有一点就把把内核vring的三个地址设置和用户态qemu一样,而qemu又来于guest中virtio-net driver写pci配置,所以最终host kernel vhost net就和guest中driver指向同一个地址了。
- vhost_net_start
- ├─virtio_pci_set_guest_notifiers
- | └─virtio_pci_set_guest_notifier
- ├─vhos