Xen的设备驱动

半虚拟化Guest OS无论如何都需要修改才能运行,因此,虚拟化环境必须使用guest OS系统现有驱动要求就不存在了,然而让客户操作系统开发人员编写大量代码同样也不是一个很好的设计方案,因此Xen的方式是提供抽象设备,抽象设备实现了针对特定设备类的高级接口,如Xen提供了抽象的块设备,而不是提供SCSI设备和IDE设备,块设备只支持两种操作:读和写。
分离设备模型
对于Xen来说,支持商用PC中大量硬件产品是一件令人畏惧的任务,所幸大部分要支持的硬件一件被Domain0所支持。那么Xen将免费获得大量的硬件兼容能力。
操作系统中提供多路复用已经是十分平常的啦,操作系统提供一个真实设备的抽象。现代操作系统的特性之一便是用户应用程序通常互相不可见,两个进程可以使用同一个设备,而彼此无需知道对方的存在。Xen通过这种方法可以避免编写大量的新的和未经测试的代码。这种复用能力非常重要,高端系统尤其是大型机中的一些设备提供了虚拟化可知特性(virtulization-aware)特性,他们能够在固件中被区分出来,从而每个运行中的操作系统都可以之间与其通信,消费级别的设备这种虚拟化特性不常见。
在我的其他博客中有提到了I/0 Ring的机制,前面理解不够透彻,应为这方面的介绍的文章很少,这里加深了理解在再来介绍一下。Hypervisor提供了设备发现和Domain间移动数据的机制。Xen设备需要注意的内容之一是,他们实际并不是Xen的一部分。
Hypervisor提供了设备发现和Domain间转移数据的机制,驱动在一对 guest Domain之间被分割开来,这种成对的Domain通常由Domain0和DomainU组成,当然可以使用过Driver Domain来代替DomainU,Xen定义了接口,实现这一架构。
Xen的设备驱动_第1张图片
单独的共享内存环自身需要大量的查询操作,通常效率比较低,由于Xen允许异步通知的事件机制,从而消除了这种需求。最后一部分是XenStore,这是一个简单的分层结构,XenStore的一个主要用途就是发现设备,类似于OpenFirmware提供设备树。
Driver Domain
Xen提供了非Domain0的Domain委托访问硬件设备的机制,该Domain被称为Driver Domain,在不提供IOMMU或者提供IOMMU保护功能的类似硬件平台上,通常不能安全的实现这一目标。Hypervisor能够通过MMU来隔离用于内存映射的I/O的内存区域并将该内存区域授权给Driver Domain,它同样可以阻止处于Ring 1的过程使用I/O端操作指令,并且强迫这些指令被捕获通过Hypervisor模拟它们的实际I/O操作,从而增加了开销。但是没有二外的硬件支持的情况下,这一机制并不能放置Driver Domain发出的DMA请求,这使得传统的硬件上大部分驱动Domain是不安全的。
Xen的设备驱动_第2张图片
Driver Domain提供两大优势,首先是为系统提供了额外的隔离性。在标准配置下Domain 0具有以下两个职责:
1、支持硬件平台,并运行后端设备驱动
2、提供Xen的管理接口
通过减少Domain 0的代码,提高了系统的安全性和稳定性,并且另一个优势就是可以提供对更多设备的支持。
Share Memory Ring Buffer
Ring Buffer是一个相当标准的无锁数据结构,用于提供生产者的通信。Xen中使用的变体有些不同,它使用了自由运行计数器。典型的环形缓冲区有一个生存者和消费者指针,有消费者进行检测,有生产者进行累加,当一个指针越过了缓冲区末尾的时候,他需要卷回。这带来的开销相对较大,并且由于它涉及到许多边界编程,因此很容易照成错误。
Xen的设备驱动_第3张图片
如果能保证缓冲区的大小为2的幂指数,Xen中的缓存区就可以避免这一问题。意味着计数器的最低n位可以用作缓冲区中的索引值,计算器可以运行到大于缓冲区的大小,因此用户不需要动手计算溢出;只需将计算器的值进行简单的减法运算就可以算出缓冲区中的数据量。Xen的环形缓冲区只有两种数据:请求数据和响应数据通过驱动的两端来完成更新。通常来说会造成一些问题:如果响应数据快于请求数据,那么响应数据指针将会赶上请求指针,那么就会阻止请求数据的写入。Xen通过只允许覆盖写入的方式防止这种情况的发生,也就是说,响应只能写入哪些请求的buffer,如下图:
Xen的设备驱动_第4张图片
环形缓冲区只有在没有等待处理的请求时,才会出现没有空间可以填充响应数据的情况,但在这种情况下不许要产生任何响应。如果没有空间可以填充请求数据的时候,这以为着两种情况。或者环形缓冲区已经填满了请求,在这种情况需要请求指针等候片刻等后端程序处理这些请求;或者环形缓冲区包含了一些响应,在这种情况下前端驱动需要考虑在继续提交请求之前处理其中的一些响应。
Xen的设备驱动_第5张图片
为了使用环形缓冲区机制,驱动的两端都需要访问它,这意味着存储器必须能够共享,完成共享的机制就是Grant Table。Xen分离驱动模型约定是前端设备驱动需要提供grant reference,同时后端驱动来映射它,这意味着前端将不需要发出Hypercall来设置环形驱动缓冲区。除了一致性外,这同时提供了优势,使得HVM的guest Domain可以实现泛虚拟化驱动而不需要任何 Grant Table Hypercall。这同时有助于虚拟机的迁移,因此当前端驱动被移到另外一台机器上,他们的 为物理地址在同样的位置,从而方便重新映射。
Memory Barriers实现顺序操作
对于环形缓冲区的一些操作需要系统中的内存屏障。在纯粹的顺序架构(in-order)中,内存操作保证以他们被发射的顺序来完成,这也意味着,只要数据在计数器增加之前写入环形缓冲区,那么一切都将是正常的。X86开始是顺序架构,随着发展,它必须维护对传统代码的兼容性,因此现代X86处理器依然是强顺序类型。Xen支持的平台中并不是所有体系结构都是很顺序结构,例如IA64是一个弱顺序类型架构,为了防止重排序,大部分体系结构提供了内存屏障指令,它强制所有的load store或者load和store组织了必须在继续执行之前完成。
处理来自消息的通知
真实的硬件通过中断通道来通知CPU有异步事件发生,他们使CPU进入特权模式并跳转到被配置为该事件的处理程序的地方继续处理。Xen提供了类似的机制,也就是事件通道(event channels)的形式,他们被异步传递到guest OS ,与中断不通过,当客户机不在运行的时候他们被排队,而中断是不知道虚拟机的存在,因此立刻传递。在Xen中,事件机制同样代替为通知分离设备驱动的后端,应为通信双方是Domain间的通信。与中断比事件有两个主要的区别,它们是双向的,并且是面向连接的,中断请求被传递给指定的处理程序,但是连接的概念是不会出现的,什么可以发起中断请求时硬件层上的定义,中断符描述表指出一个程序需要哪些特权级别才可以触发一个中断,而硬件定义了哪个设备可以外部触发他们。
事件必须更好进行访问控制,一个恶意的客户机可能通过触发大量虚拟的事件而引发严重的问题,因此事件只能在给定的通道上由两个Domain之间传递连接的另一个Domian。当事件通道被一个Domain分配,它就明确规定了另一端Domain的序号。其他Domain必须明确要求绑定该事件通道上,那么这时事件才可以在通道两端传递。

你可能感兴趣的:(linux,Xen)