分类: 虚拟化
2011-12-15 13:33:50
在Xen中,HYPERVISOR_multicall的响应函数是do_multicall,在这个函数的最后一行调用了一个hypercall_create_continuation函数,用来resume当前的hypercall。具体做的事情是为Guest OS准备好context(栈及寄存器),然后重新执行INT 82陷入指令。要让虚拟重新执行陷入指令的处理又分为再种情况:假如是PV的虚拟机,把EIP减2,重新执行int 0×82或者syscall指令;假如是HVM,那么不需要对EIP作处理,因为vmcall产生的是fault,指令会重新自动执行。
那么,Xen在什么时候需要创建Continuation呢?常见的代码形式是:
1 2 | 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为什么不会有这样的问题呢?那自然是因为其他的Hypercall在执行的时候可以保证当时所处的状态是“干净”的。
reference: http://blog.liuw.name/932
现在回想一下,错误也并不复杂,那么为什么自己竟然花了这么长时间才发现呢?现在把思路整理一下:
当出现错误时,先检查自己的程序是否修改正确。这一步是必须得,正确。
由于错误的外在表现是dom0不能启动,因此我走上了一个错误的道路,希望设置一个flag来标识dom0是否初始化完成,若完成则随机,否则不随机。
首先,这样的想法很肤浅,因为在内核初始化的时候,很多其他的hypercall,都是可以正确执行的,说明改变参数导致的错误并不general,而是针对multicall的,我没有理由怀疑是由于什么东西没初始化好才导致multicall出错。其次,我的随机只是在数值上改变了形参,不会出错的。
但是在设置flag的过程中,我也学习到了很多知识,比如我了解了内核初始化的流程,start_kernel, cpu_idle, init_post, free_mem, 内核保护数据等。我还懂得了设置per cpu data,以及使用它们,这对于我后来看懂源码帮助很大。我还学习到了,内核启动时printk太多东西会导致内核死掉,因为单线程时没有人去唤醒,所以kernel会一直wait。
我甚至还尝试了史上最笨蛋的方法,一个个排查kernel中调用multicall的位置,希望在kernel中找到某个特殊的调用点然后再探究原因,足足有20+个,虽然找到了是某个multicall的问题,但是还是没有找到原因,也不可能找到原因!因为这根本就不可能是问题。
虽然设置启动时的flags可以保证dom0启动,但这只是个巧合,虽然排查multicall也可以启动dom0,但那也只是巧合!
正确的思路是,我只修改了形参,kernel里100%是不会有问题的,entry.S中处理int82请求的汇编,那里应该仔细看一下,其实那里就提到了continuation,只不过我不懂,就忽略了,结果忽略的地方就是出问题的地方。然后是Xen里,我以为一进入do_multicall就还原参数,后面使用到的都是还原过后的参数是100%没问题的,但是没有想到的是,同一个multicall很有可能又被送入do_multicall再执行一遍!!!
所以说,效率低,一是因为自己只是储备不够,看到continuation不能立刻反应到“计算过程的重构”,二是看源码不认真,一知半解,其实之前也看到过hypercall_create_continuation的函数体,但只是一带而过,与其这样急躁,还不如静下心来,真正把代码的细节读懂。
PS:hypercall_create_continuation里还有传入个数不确定参数,并使用这些参数的处理方法,值得好好学习。“hi”
anitawang19892012-05-08 14:29:54