假如我们加个参数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