Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1348835
  • 博文数量: 370
  • 博客积分: 10654
  • 博客等级: 中将
  • 技术积分: 4396
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 15:44
文章分类

全部博文(370)

文章存档

2012年(36)

2011年(195)

2010年(139)

分类: 虚拟化

2012-02-06 18:09:47

与系统调用类似,Xen中的hypercall是通过软中端(中断号0x82)来实现的:

超级调用号:xen/include/public/xen.h中定义了45个超级调用,其中有7个是平台相关调用。
超级调用表:xen/arch/x86/x86_32/entry.S中定义了超级调用表,通过超级调用号索引就可以方便的找到对应的处理函数。
超级调用页:超级调用页是Xen为Guest OS准备的一个页,可以做到不同Guest OS有不同的超级调用页内容。实现过程为
_HYPERVISOR_xxxx
==> 在超级调用页上找到相应的代码
==> _hypercall2()调用超级调用页内的代码
==> 通过hypercall_page_initialise实现HVM、Dom0、DomU的不同跳转
==> 调用hypercall()来检查有效性、执行相应的服务例程(do_xxhyper名_)并返回

超级调用只能由内核来调用,而应用程序是无法直接调用的。应用程序申请超级调用的过程为:

打开Xen提供的内核驱动:/proc/xen/privcmd;
通过ioctl系统调用来间接调用hypercall:

fd = open("/proc/xen/privcmd", O_RDWR); 
privcmd_hypercall_t hcall = { 
__HYPERVISOR_print_string, 
{message, 0, 0, 0, 0} 
}; 
ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, &hcall);

复杂一点的超级调用申请的过程为:(以_HYPERVISOR_domctl超级调用为例)

通过pyxc_domain_create()获取要创建的domain的相关信息;
通过xc_domain_create()创建控制结构体变量domctl;
通过do_domctl()生成超级调用请求;
传递请求到OS内核:do_xen_hypercall()
do_privcmd通过ioctl来完成由3环到1环的转变,并完成超级调用。


注意事项:

1.hypercall的添加是与内核相关的,所以必须修改内核代码;

2.添加hypercall后应该重新编译内核;

3.应该处于半虚拟化状态,因为全虚拟化中的hypercall调用方式与半虚拟化不同;

4.由于包含相关头文件,需要把/usr/include/xen文件夹拷贝到domU中,另外还有/usr/include/xenctrl.h文件。

总结

1.XEN的基本机制中,xenstore是域间共享,不调用hypercall;其他几种包括事件通道、granttable、内存管理等都与hypercall相关;

2.不同的系统中定义的hypercall数量不统一,有的多有的少,目前xen支持128个hyercall定义,但其实只有37个,另有7个作为保留;

3.XEN现有的hypercall中,有时一个hypercall可能实现多个功能,故其数量并不多。

4.与传统OS的系统调用相同,除了直接调用hypercall外,也可通过封装方便应用调用hypercall,如miniOS中的示例:xen/extras/minios/include/x86/x86 32/hypercall-x86 32.h,该文件定义了一系列hypercall的宏,如不带参数或一个参数、两个参数...四个参数的hypercall,;然后可在其他功能代码中直接调用这些定义的宏,实现对hypercall的调用;

5.HVM需要硬件技术支持,如intel的VT-d或AMD的SVM等,客户域OS启动过程中需要在dom0中有BIOS模拟器的支持(QEMU)。对系统调用部分,PV是通过中断读取hypercall页,而HVM则需要使用CPU的指令如通过CPUID指令访问一个虚拟机器的寄存器、访问hypercall页,然后像PV一样读取该页中相应的偏移量执行特权操作。当前HVM环境下并不是所有的XEN hypercall都可用(只实现一部分)。

hypercall与事件通道

hypercall是用于各域与XEN进行同步通信的;通过中断处理系统相关的特权操作,如建立页表、管理内存、访问I/O设备等。

而事件通道则是为各域之间进行异步交互设计的,是Xen用于在虚拟域之间以及虚拟域和VMM之间进行异步事件通知的机制。

两者关系:Xen中的物理中断(pIRQ)、虚拟中断(vIRQ)、虚拟处理器lbJ中断(vlpl)、虚拟域间通信(IDC)等均通过事件通道实现。虚拟域间通信是通过一个被称之为evtchn的驱动程序建立虚拟域间的事件通道。每个DomainU都和Domaino之间都存在一个域lbJ事件通道和一个共享内存区域,用来传递请求和数据。事件通道的端口及1/0请求信息,都存储在每个虚拟域的“共享内存页 (sharedpage)”结构体中。比如绑定PIRQ,绑定vIRQ,绑定两个域,分配端口,发送消息等等,这些操作最终都是通过调用entry.s中定义的Hypercalls来实现的。这与普通设备的驱动程序的读写操作最终通过系统调用来实现非常类似。在建立域间事件通道的过程中,evtchn驱动会调用HYPERVISOR_eventchannel_op超级调用,后者又会调用evtchn_bind_interdomain函数,在虚拟域0获得一个空闲的端口,并将该端口与新创建的虚拟域及其端口联系起来。


半虚拟化要求对客户OS进行的修改

Xen采用的半虚拟化技术需要对Guest OS进行相应修改。IA-32平台上Xen的半虚拟化技术总结如下:
(1)Guest OS使用特权指令的地方要修改为调用Xen提供的API:hypercalls。
(2)硬件中断被轻量级的事件机制取代;对于异常,Guest OS要调用hypercalls来注册自己的异常处理函数。陷阱的处理程序是注册到VMM上的,而不是直接注册到虚拟CPU上的,这样就节省了一步操作,否则要先引起虚拟硬件的陷阱,再由VMM处理。系统调用注册到处理器。大多数操作系统中,系统调用是通过一个查找表和一个特殊的陷阱队列来处理的。虚拟化后,陷阱队列引起VMM的处理。而Xen跨过这个效率不高的一步,允许虚拟机上的操作系统直接将它们系统调用的处理绑定到处理器上,避免了VMM处理陷阱队列而进行的上下文切换的开销。
(3)修改内存管理机制:在每个Guest OS的虚拟内存空间保留64M给Xen,物理内存的申请和释放要通过Xen。每个虚拟机可以对硬件页表进行只读访问,而更新页表的工作则由VMM完成。
(4)修改I/O使用方法:Xen只提供给VM一些通用快速的设备,VM只能根据Xen定义的API来访问设备。在半虚拟化系统中,设备是通过前端驱动和后端驱动提供的,而全虚拟化则不同,可能是由QEMU模拟或直接由一个驱动域提供设备驱动。

阅读(6406) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~