为梦而战
全部博文(185)
分类: LINUX
2015-02-12 11:07:35
VirtIO 是一个用来实现“虚拟IO”的通用框架,典型的用于虚拟机上面实现虚拟的pci,网卡,磁盘等虚拟设备,kvm等都使用了这个技术。大概浏览了一下相关的内核代码,这个virtio应该是专门应用于那种“半虚拟化?(部分虚拟化)”的虚拟机的来虚拟各种通用io设备的,好像不是很适合单纯的用来虚拟设备。
参考资料
Virtio:针对 Linux 的 I/O 虚拟化框架 http://www.ibm.com/developerworks/cn/linux/l-virtio/index.html?ca=drs-cn-0304
KVM的virtio说明文档:
http://www.linux-kvm.org/wiki/images/d/dd/KvmForum2007%24kvm_pv_drv.pdf
内核相关示例源码有;
前段接口(guest端)的例子:
http://lxr.linux.no/linux+v2.6.35.7/drivers/lguest/lguest_device.c
如果想用virtio来实现一个虚拟设备大概流程是这样的:
1、自己实现scan设备的功能,然后调用register_virtio_device 函数来注册发现的虚拟设备。参考drivers/lguest/lguest_device.c 里面的scan_devices 函数。一个典型的实现是,虚拟机主机提供的共享内存配置,里面提供了虚拟设备的列表一样的配置,然后自己根据配置注册device。
注:pci总线等应该也是要扫描各个插槽,然后发现新的pci设备,然后创建device结构,再调用到驱动的probe函数里面的,应该各个总线都有发现新设备的机制,device一般是scan的时候创建。
2、为virtio_device 设备准备好 队列。参考drivers/s390/kvm/kvm_virtio.c 里面的 函数。特别的是要提供自己的 结构的notify函数。notify函数用于通知host主机队列里面已经有消息存在了,一般是hypercall ,就是通过vmcall指令或者traps(中断?)来通知主机。例如这个kvm代码。
/*
* When the virtio_ring code wants to notify the Host, it calls us here and we
* make a hypercall. We hand the address of the virtqueue so the Host
* knows which virtqueue we're talking about.
*/
static void (struct *)
{
struct * = ->;
(, ->);
}
69
/* This instruction is vmcall. On non-VT architectures, it will generate a
* trap that we will then rewrite to the appropriate instruction.
*/
#define ".byte 0x0f,0x01,0xc1"
/* For KVM hypercalls, a three-byte sequence of either the vmrun or the vmmrun
* instruction. The hypervisor may replace it with something else but only the
* instructions are guaranteed to be supported.
*
* Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
* The hypercall number should be placed in rax and the return value will be
* placed in rax. No other registers will be clobbered unless explicited
* noted by the particular hypercall.
*/
static long (unsigned int )
{
long ;
asm volatile(
: "=a"()
: "a"()
: "memory");
return ;
}
static long (unsigned int , unsigned long )
{
long ;
asm volatile(
: "=a"()
: "a"(), "b"()
: "memory");
return ;
}
3、应该/drivers/net/virtio_net.c 等代码已经实现了前端的网卡,磁盘等驱动了。所以只要你register_virtio_device注册了之后,客户机应该是可以看到相应的虚拟网卡的了。
这些驱动使用virtio的框架方法大概是这样的,
这个函数用来获取队列里面收到的消息。
把发送到消息缓存写到队列,然后 调用函数来通知host主机队列里面有消息需要它接受。 将调用到结构的notify函数,notify函数通过中断或者高级的虚拟机指令mcall通知到host主机。 host主机,根据实现可能是共享内存的hypercall的,就可以直接复制相应的内存过去就可以了。可以去看相应的虚拟机的hypercall的实现代码。
virtio的作用就是提供一种居于的通用的虚拟io框架。