Archive for the ‘xen’ tag
Xen中的Continuation
我个人理解的计算机科学中的Continuation,即是把一个计算过程具体化(reifier),得到一组可以用来重构这个计算过程的结构。通常情况下,它包含了处理器的栈,还包含了当前的执行点(具体化一点,就是所有寄存器的值),这样处理器就可以在任何时候重构这个计算过程。
一些高级语言,如Python、Ruby、Haskell、LISP等,在VM中对Continuation提供了支持。目前使用的计算机,还是必须手工编写代码才能支持Continuation。
Xen提供了一个hypercall_create_continuation函数,用来resume当前的hypercall。具体做的事情无非就是为客户虚拟机准备好上下文(栈及寄存器),然后重新执行陷入指令。要让虚拟重新执行陷入指令的处理又分为再种情况:假如是PV的虚拟机,把EIP减2,重新执行int 0×82或者syscall指令;假如是HVM,那么不需要对EIP作处理,因为vmcall产生的是fault,指令会重新自动执行。
Xen中的Continuation仅仅用于重新执行hypercall,对栈和寄存器的操作比较少,速度是有保证的。
那么,Xen在什么时候需要创建Continuation呢?常见的代码形式是:
if ( hypercall_preempt_check() )
hypercall_create_continuation(...)
hypercall_preempt_check又是干什么的呢?假如当前物理CPU有等待处理的softirq,或者PV中的VCPU中有可投递的upcall(pending且!masked),那么它的返回值就为真。(HVM这里先不讨论)
即是说,Xen在执行某些Hypercall的时候,有可能处于一种不能抢占CPU的状态,所以必须让客户虚拟机重新再执行一次Hypercall。
受影响的Hypercall有:
__HYPERVISOR_hvm_op
__HYPERVISOR_mmuext_op
__HYPERVISOR_mmu_update
__HYPERVISOR_domctl
__HYPERVISOR_set_trap_table
__HYPERVISOR_memory_op
__HYPERVISOR_multicall
__HYPERVISOR_console_io
本人目前的看法是,这些Hypercall在有upcall或者softirq处于pending的状态时候执行的话,都会有影响虚拟机状态一致性的可能。以console io为例,虚拟机和consoled之间的事件通知,就是用的event channel机制。处于pending状态的event很可能就是IO通信产生的。假如虚拟机在调用__HYPERVISOR_console_io之前没有先把所有的event都处理完,那么就会造成数据的丢失。
但是其他的Hypercall为什么不会有这样的问题呢?那自然是因为其他的Hypercall在执行的时候可以保证当时所处的状态是“干净”的。
草草看了一下代码,写下了上面的文字。水平所限,错误在所难免,欢迎指正。
特权高就是好
Virtual Machine Introspection就是说只看不改。要是改一下数据会怎么样?
今天就干了这事,在Xen的层面把程序的代码内容给改掉了。简单点说,这就是一种代码注入。
有趣的地方是,改了的机器码最后反映到程序映像之中了。想了一下,大概是因为代码段是以文件映射的方式映射到内存之中的,程序退出的时候会让磁盘上的文件和内存中的内容同步。
往好的方面想,这样的功能是目前最强的hot patch方式。一方面可以on the fly地改进程,另一方面顺带把映像也改了。
往不好的方面想,这样的功能就太可怕了,自己的程序被改了也不知道,重新启动也不成。
不过我原来没有料到会有映像的同步。我一向的理解是这样的只读映射最后只需要把内容丢弃就可以了,代码以后有机会再看吧。
Xen更新页表的几个入口
这屁事搞了好几天了,这里记一下。
三个入口:
- do_mmu_update,个是最正规的ParaVirt入口,可以更新任何一级页表。
- do_update_va_mapping,直接更新virtual address对应的L1页表,只能用于L1页表。
- writable page table,实际上这是一个Xen的特性,不是一个具体的函数,也只能用于L1页表。Xen先把L1页表unhook让guest可写,然后ptwr_emulated_update为guest模拟写操作,Xen验证写入数据的合法性后再把页表重新hook上。
这是这几天看代码的一些小总结,不能保证完全正确。以后再写代码验证。
XenoLinux内核上面的方面都有采用。比如在Dom0进程要更新页表的时候(创建也好,销毁也好),通常是用do_mmu_update,效率比较高;但是在munmap单个页面的时候,通常是使用writable page table模式。
Milestone 2 is coming
New release, new features.
New stubdom target domb.
Working Dom0 daemon dombd, responsible for communicating with DomB.
Usable domain builder inside DomB.
Coming soon…