Intel VMCS学习总结
VMX
分为root模式和non root模式,
VMCS通过VMPTRST,VMPTRLD修改。
VMREAD,VMWRITE修改VMCS内容。
VMXON,VMXOFF打开关闭VMX。
VMLAUNCH,VMRESUME
VMCS状态的状态管理?
VMPTRLD,转化为active,current
active,current
VMCS的几个区域:
1.Guest-state area
2.Host-state area
3.VM-execution cotrol fields
4.vm-exit control fields
5.vm-entry cotrol fields
6.vm-exit information fileds
Intel寄存器说明:
IDTR:中断描述表指针
GDTR:全局段描述表指针
LDTR:局部段描述表指针
segment selector:包含index,LDTorGDT,访问权限。
CS,SS,DS,ES,FS,GS
TSS段:TSS段的作用。TR寄存器指定。
RSP RIP PFLAGS 栈指针,代码段指针,标示位。
EAX,EBX,ECX,等通用寄存器。
CR0,CR1,CR3,CR4等控制寄存器。CR3指向页表。
这些寄存器必须被保存:理论上必须被保存的状态信息,在虚拟机退出并重新启动时能够正常运行。
实际上硬件VMCS会自动保存和恢复哪些寄存器呢?
CR0,CR3,CR4
RSP RIP PFLAGS
LDTR
TR
GDTR
IDTR
MSR:
CS, SS, DS, ES, FS, GS
CR1,CR2为什么不保留?
CR2保存的是导致缺页中断的线性地址,CR1目前没有使用。
有哪些寄存器,硬件没有自动保存呢?
EAX,EBX,ECX,等通用寄存器。
为什么硬件没有自动保存呢?
由于这些是通用寄存器,并且必须利用这些寄存器借助软件模拟特定指令。
vmx_vcpu_run中的处理:
asm(
/* Store host registers /
"push %%" _ASM_DX "; push %%" _ASM_BP ";"
"push %%" _ASM_CX " \n\t" / 在Host OS的栈中保存一个空间,当vm exit的时候,先保存cx到栈上 */
"push %%" _ASM_CX " \n\t" //保存hostos当前的寄存器信息到内核栈中
Compare asm_sp with host_rsp(%0) in the VMX. //Save the SP from the host OS into the VMX's rsp.
Jump to address 1f. //跳转到地址1f
Move asm_sp into host_rsp(%0). //将asm_sp移动至host_rsp(%0)
__ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t" //把sp的值保存在vmcs中
"1: \n\t"
/* Reload cr2 if changed */ //判断vmx中的CR2和实际的CR2,如果不一致,修改CR2
"mov %ccr2, %%" _ASM_AX " \n\t"
"mov %%cr2, %%" _ASM_DX " \n\t"
"cmp %%" _ASM_AX ", %%" _ASM_DX " \n\t"
"je 2f \n\t"
"mov %%" _ASM_AX", %%cr2 \n\t"
"2: \n\t"
Determine whether vmlaunch of vmresume is necessary. //此处判断的原因是由于还可以访问vmx
/* Load the guest registers without disturbing the flags. */ // Revert the ax, bx, dx, si, di and bp fields from the guest VMX structure to the CPU registers
"Move the contents of register (%0) in the guest VMX structure into register AX." _ASM_AX "\n\t"
"Move data from register (%0) in VMX to BX." _ASM_BX "\n\t"
"Transfer value from (%0) in VMX to DX." _ASM_DX "\n\t"
"Retrieve value from (%0) in VMX and store in SI." _ASM_SI "\n\t"
"Fetch data from (%0) in VMX into DI." _ASM_DI "\n\t"
"Multiply content of (%0) in VMX by BP and store result." _ASM_BP "\n\t"
#ifdef CONFIG_X86_64 /为64位扩展了寄存器组/
"执行目标地址值的操作\n完成目标地址值的操作\n完成目标地址值的操作\n完成目标地址值的操作\n完成目标地址值的操作\n完成目标地址值的操作\n完成目标地址值的操作\n完成目标地址值的操作"
#endif
mov %basercx, _ASM_CX " \n\t" // instruction clears src_reg (ecx)
//why cx is after? because cx stores vmx pointer.
/* Enter guest mode */ //基于前面lanched的判定结果, 进入non-root模式
"jne 1f \n"
执行jne指令至内存地址0x01ff并换行
"jmp 2f \n"
执行jmp指令至内存地址0x02ff并换行
"1: "
通过__ex函数执行ASM_VMX_VMLAUNCH指令并换行
"2: "
通过__ex函数执行ASM_VMX_VMRESUME指令并换行
/* 保存Guest寄存器、加载Host寄存器并保持标志位 */ 退出程序
"mov %0, %cwordsize \n\t" //将CX寄存器的数据压入栈中
"pop %0 \n\t" //从栈中弹出CX寄存器的数据,并更新基址使其指向VMX段
将寄存器需保存至vmx段中
将寄存器需保存至bx段中
关于cx寄存器的存放位置,请注意其需被放置于栈中
dx寄存器为何需特别处理?
si寄存器为何特别设计?
di寄存器为何需特别注意?
bp寄存器为何需特别处理?
#ifdef CONFIG_X86_64
将%%r8赋值为%cr8
将%%r9赋值为%cr9
将%%r10赋值为%cr10
将%%r11赋值为%cr11
将%%r12赋值为%cr12
将%%r13赋值为%cr13
将%%r14赋值为%cr14
将%%r15赋值为%cr15
#endif
"mov %%cr2, %%" _ASM_AX " \n\t"
"mov %%" _ASM_AX ", %ccr2 \n\t" //保存cr2寄存器到vmx中的cr2
以下是改写后的文本
#ifdef CONFIG_X86_64
[r8]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R8])),
[r9]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R9])),
[r10]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R10])),
[r11]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R11])),
[r12]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R12])),
[r13]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R13])),
[r14]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R14])),
[r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),
#endif
[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)),
[wordsize]"i"(sizeof(ulong))
: "cc", "memory" //被影响的寄存器,cx,dx,bp在栈中保存
#ifdef CONFIG_X86_64
, "rax", "rbx", "rdi", "rsi"
, "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
#else
, "eax", "ebx", "edi", "esi"
#endif
);
Guest non-register state
PDPTES EPT页表,指向EPT页表
Guest interrupt status
RVI VAPCI的支持,正在请求的最高优先级中断
SVI VAPCI的支持,正在处理的最高优先级中断
Host State
VM Entry的时候,会自动保存的HostOS的状态。
CR0,CR3,CR4
RSP,RIP
CS,SS,DS,ES,FS,GS,TR
GDTR,IDTR
VM execution control
Pin-based VM execution Control,指定什么情况下中断导致虚拟机退出。
外部中断,NMI中断都会导致VM exits
Process posted interrupts,VAPIC的支持,
通过posted-interrupt nodification vector,更新apic页表。
Process-based Vm execution control,控制那些指令会导致VM exit。
Excepion Bitmap,确定哪些异常导致VM exit
IO Bitmap Address,确定哪些IO操作导致VM exit
TSC Offest:TSC偏差
MSR-Bitmap Address:
VM-Entry controls fields
event injection,触发向虚拟机中发中断
VM exit information fields
Exit Reason:
Exit qualification:更详细的推出原因
Guest Liner address
Guest physical address:用于EPT页表失效的情况。
Vm-exit interuption information:中断退出情况下的信息
vm-exit interrupt error code:硬件异常的error code
vm-exit instruction length: 因为执行指令导致的退出
vm-exit instruction information:
