Xen 超级调用 和 事件通道

来源:互联网 发布:雉兔同笼编程 编辑:程序博客网 时间:2024/05/17 22:09

超调用

    在Xen系统中,Xen作为VMM位于最高特权级0环,而Guest OS内核只能位于次一级的1环。Guest OS内核特权级的降低使得它不能执行一些特权操作,而必须将其交由拥有更高特权级的Xen代为完成。为此,Xen向Guest OS提供了一系列的接口,使得Guest OS能够使用Xen提供的服务来完成特权操作,这些接口就是超级调用。    超调用是从客户机操作系统到VMM的系统调用,与系统调用类似,Xen启用了130号中断向量端口作为超调用的端口号。这一中断向量的DPL被设置为1,类型为中断门。这样,超调用能够由处于特权级1的客户操作系统发起,而不能从用户态发起。

超调用页

    在Xen3.0之前,超级调用的申明和使用时通过在每个调用的封装例程中直接执行软中断汇编指令(INT 0x82)完成的。随着Xen支持的Domain类型的不断增加,在封装例程中直接调用超级调用的方式已经不能满足要求。为此,在Xen 3.0之后采用了调用函数的方式,并建立超级调用页来实现超级调用的间接使用。    超调用页在虚拟机启动前被初始化,在虚拟机内核启动时,这个页被映射到客户机操作系统的一个固定的虚拟地址上。一个超调用页被划分成128块,每块长度为32字节。在初始化时,每一块都会写入一段发起超调用的汇编代码,第i块的汇编代码会将编号i作为参数来发起超调用。    通过宏定义了6个调用函数 _hypercall0()、_hypercall1()、_hypercall2()、_hypercall3()_hypercall4()_hypercall5(),分别对应1~6个参数。超级调用的封装例程则根据参数个数的不同分别调用上述函数。在上述函数中,并没有直接调用INT 0x82,而是通过Call指令调用位于一个特殊内存页面中的一段代码。即超级调用页。    #define HYPERCALL_STR(name) \        "call hypercall_page+("STR(__HYPERVISOR_##name)"*32)"    其中,参数name为超级调用名,由此可以获得相应的超级调用号。hypercall_page的值为超级调用页在Guest OS地址空间内的虚拟地址,与由超级调用号决定的页内位移相加的结果即为对应代码的地址。

ring3 申请超级调用

    由于3环应用程序无权申请超级调用,只能采取间接的方式使用超级调用,即将超级调用请求先传递到1环的Guest OS内核,再由Guest OS内核申请超级调用。Xen系统提供了一个特殊的内核驱动程序privcmd来完成这个工作。    利用ioctl去操作privcmd驱动。

事件通道

    事件通道是Xen用于Domain和Xen之间、Domain和Domain之间的异步事件通知机制。Xen体系结构上的物理中断、虚拟中断、虚拟处理器间中断,以及Domain域间通信均须通过事件通道实现。    struct shared_info{        ...        unsigned long evtchn_pending[];        unsigned long evtchn_mask[];        ...    }    数组evtchn_pending[]和evtchn_mask[]中分别保存与事件通道对应的两个标志位:PENDING位和MASK位。每个事件通道都在数组中对应这样一对标志位。其中PENDING位表示在事件通道中是否存在一个未处理的事件通知;MASK位表示是否屏蔽该事件通道的事件通知。    struct vcpu_info{         uint8_t evtchn_upcall_pending;         uint8_t evtchn_upcall_mask;         xen_ulong_t evtchn_pending_sel;         ...    }    将evtchn_upcall_mask置1,该VCPU将屏蔽所有的事件通道。    evtchn_pending_sel用于定位VCPU未处理的事件通知,因此也成为事件选择器。在X86平台上为32位,其中每一位代表evtchn_pending[]数组中一组32个事件通道。因此,可以将evtchn_pending_sel中的每一位看做evtchn_pending数组的下标指针。
原创粉丝点击