徒手hypervisor(二)

来源:互联网 发布:python变量赋值 引用 编辑:程序博客网 时间:2024/05/01 23:26

最简单hypervisor说明:

最简单的hypervisor仅仅能处理HVC call,一共就只有一条指令。不过HVC call执行的过程还是比较复杂的。在ARM上,只有在PL1及更高的privilege level才能执行HVC call,这一点和x86上是不同的,在x86上hypervisor call既可以在user space执行,也可以在kernel space执行。当kernel执行HVC call的时候,cpsr寄存器把CPU mode切换到HYP mode,并disable interrupt,返回地址(lr),栈指针(sp)和系统状态寄存器(cpsr)保存到相应的HYP bank寄存器中。然后pc寄存器会指向HVBAR加offset 0x14的地址Addr,这个时候需要注意了。因为HYP mode有自己的MMU,如果HYP的MMU enable了,地址Addr就是一个虚拟地址,它会经过HYP的MMU翻译得到一个物理地址,pc寄存器实际访问的就是最后的那个物理地址,但如果HYP的MMU没有打开,那么pc就指向物理地址Addr,并执行这个地址上的code。对于我们最简单的hypervisor,MMU自然是没有打开,因此它会Addr当做一个物理地址,直接访问。HVBAR存的是HYP Exception Vector的基址,通常的Vector的每一项都是一个跳转指令,而在最简单的hypervisor里面,直接放了eret指令。尽管这有点违背设计的初衷,但一点也不影响实际的执行。Eret这个指令和HYP call刚好是相对应的,就像call和ret相对一样。当hypervisor执行eret指令的时候,首先cpsr寄存器被恢复,CPU mode也由HYP mode切换回SVC mode,然后sp被恢复,pc指向bank的lr,kernel开始继续执行HVC call的下一条指令。就像一个函数调用返回一样,只是这样的调用会引起上线文的切换(context switch)。

在ARM上r0-r12这些通用寄存器在不同的mode下面都是共享的,但是不同的mode都有自己的lr和sp,互不影响。举个例子,我不想eret到HVC call的下一条指令,而是eret到任意一个kernel 虚拟地址Va。如果要实现这个操作,在hypervisor里面修改lr是没有用的,真正需要修改成Va的是hyperviosr里面的bank寄存器hyp_lr,只有当这个寄存器被修改成Va的时候,eret才会跳转到kernel的虚拟地址Va。

HYP Exception Vector也不是仅仅只有0x14这一项,只不过HVC call会去找这个这一项。完整的HYP Exception Vector如下图所示:

0 0
原创粉丝点击