HvmInit分别用AMD65和IA32的实现对当前CPU平台进行识别,并确认是否支持VT技术。
HvmSwallowBluepill函数则对当前物理CPU上的所有逻辑CPU,进行虚拟设置,反转到虚拟机的运行状态。
CmDeliverToProcessor 函数调用KeSetSystemAffinityThread将当前线程调度到指定的CPU cProcessorNumber,并将IRQL提升到Dpc Level,调用回调函数CallbackProc,回调返回之后将IRQL降低并调度回原来的CPU。
NTSTATUS NTAPI CmDeliverToProcessor (
CCHAR cProcessorNumber,
PCALLBACK_PROC CallbackProc,
PVOID CallbackParam,
PNTSTATUS pCallbackStatus
)
HvmSwallowBluepill在调用CmDeliverToProcessor的时候使用了回调函数CmSubvert,该函数使用汇编代码编写。
CmSubvert函数首先保存8个通用寄存器到栈中,接着传递当前栈指针调用HvmSubvertCpu。
NTSTATUS NTAPI HvmSubvertCpu (
PVOID GuestRsp
)
HvmSubvertCpu 函数再次确认当前CPU实现了VT。紧接着为该CPU在宿主机运行分配栈空间,大小为HOST_STACK_SIZE_IN_PAGES=16 Pages。
在栈底部保留一个结构体struct CPU,保存当前CPU的全局描述符表和中断描述符表等信息。整个栈布局如下:
; Stack layout for vmxVmrun() call:
;
; ^ ^
; |