找回密码
 注册账号

QQ登录

微信登录

关于VMCS(VIRTUAL-MACHINE CONTROL STRUCTURES)

摘要: 有人有好的相关资料么?先谢谢了!
有人有好的相关资料么?先谢谢了!关于VMCS(VIRTUAL-MACHINE CONTROL STRUCTURES)

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当前的寄存器信息到内核栈中


                "cmp %%" _ASM_SP ", %c[host_rsp](%0) \n\t"       //把HostOS的SP的保存在vmx中的rsp
                "je 1f \n\t"
                "mov %%" _ASM_SP ", %c[host_rsp](%0) \n\t"

                __ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t"       //把sp的值保存在vmcs中


                "1: \n\t"
                /* Reload cr2 if changed */                                          //判断vmx中的CR2和实际的CR2,如果不一致,修改CR2
                "mov %c[cr2](%0), %%" _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"


                /* Check if vmlaunch of vmresume is needed */     //在这里判断是因为这里还可以访问vmx
                "cmpl $0, %c[launched](%0) \n\t"

               /* Load guest registers.  Don't clobber flags. */       //把vmx数据结构中的ax,bx,dx,si,di,bp恢复到寄存器
                "mov %c[rax](%0), %%" _ASM_AX " \n\t"              
                "mov %c[rbx](%0), %%" _ASM_BX " \n\t"
                "mov %c[rdx](%0), %%" _ASM_DX " \n\t"
                "mov %c[rsi](%0), %%" _ASM_SI " \n\t"
                "mov %c[rdi](%0), %%" _ASM_DI " \n\t"
                "mov %c[rbp](%0), %%" _ASM_BP " \n\t"


#ifdef CONFIG_X86_64                                                             //64位增加的寄存器
                "mov %c[r8](%0),  %%r8  \n\t"
                "mov %c[r9](%0),  %%r9  \n\t"
                "mov %c[r10](%0), %%r10 \n\t"
                "mov %c[r11](%0), %%r11 \n\t"
                "mov %c[r12](%0), %%r12 \n\t"
                "mov %c[r13](%0), %%r13 \n\t"
                "mov %c[r14](%0), %%r14 \n\t"
                "mov %c[r15](%0), %%r15 \n\t"
#endif

                "mov %c[rcx](%0), %%" _ASM_CX " \n\t" /* kills %0 (ecx) */    //为什么cx放在后面?因为cx本身存放vmx的指针


                /* Enter guest mode */                                                          //根据前面lanched的判断结果,进入non-root模式
                "jne 1f \n\t"
                __ex(ASM_VMX_VMLAUNCH) "\n\t"
                "jmp 2f \n\t"
                "1: " __ex(ASM_VMX_VMRESUME) "\n\t"
                "2: "



                /* Save guest registers, load host registers, keep flags */       退出了
                "mov %0, %c[wordsize](%%" _ASM_SP ") \n\t"                 //把cx保存在栈中遇留的寄存器
                "pop %0 \n\t"                                                                         //把cx从栈中恢复,这个时候cx指向vmx


                "mov %%" _ASM_AX ", %c[rax](%0) \n\t"                         //把寄存器需要保存在vmx中
                "mov %%" _ASM_BX ", %c[rbx](%0) \n\t"
                __ASM_SIZE(pop) " %c[rcx](%0) \n\t"                              //cx为什么要特殊处理?  cx存放在栈中
                "mov %%" _ASM_DX ", %c[rdx](%0) \n\t"
                "mov %%" _ASM_SI ", %c[rsi](%0) \n\t"
                "mov %%" _ASM_DI ", %c[rdi](%0) \n\t"
                "mov %%" _ASM_BP ", %c[rbp](%0) \n\t"

#ifdef CONFIG_X86_64
                "mov %%r8,  %c[r8](%0) \n\t"
                "mov %%r9,  %c[r9](%0) \n\t"
                "mov %%r10, %c[r10](%0) \n\t"
                "mov %%r11, %c[r11](%0) \n\t"
                "mov %%r12, %c[r12](%0) \n\t"
                "mov %%r13, %c[r13](%0) \n\t"
                "mov %%r14, %c[r14](%0) \n\t"
                "mov %%r15, %c[r15](%0) \n\t"
#endif

                "mov %%cr2, %%" _ASM_AX "   \n\t"
                "mov %%" _ASM_AX ", %c[cr2](%0) \n\t"                 //保存cr2寄存器到vmx中的cr2


                "pop  %%" _ASM_BP "; pop  %%" _ASM_DX " \n\t"        //从内核栈上恢复bp,dx
                "setbe %c[fail](%0) \n\t"
                ".pushsection .rodata \n\t"
                ".global vmx_return \n\t"
                "vmx_return: " _ASM_PTR " 2b \n\t"
                ".popsection"
              : : "c"(vmx), "d"((unsigned long)HOST_RSP),                            输入参数,vmx变量存在在ecx中,HOSTRSP存放在edx中。
                [launched]"i"(offsetof(struct vcpu_vmx, __launched)),
                [fail]"i"(offsetof(struct vcpu_vmx, fail)),
                [host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)),
                [rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),
                [rbx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBX])),
                [rcx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RCX])),
                [rdx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDX])),
                [rsi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RSI])),
                [rdi]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RDI])),
                [rbp]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBP])),


#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:  因为执行指令导致的退出


评论 支持 反对

举报

谢谢您的分享!
评论 支持 反对

举报

以后多分享一些这样的有价值的帖子啊
评论 支持 反对

举报

好东西一定要看看!
评论 支持 反对

举报

以后多分享一些这样的有价值的帖子啊
评论 支持 反对

举报

以后多分享一些这样的有价值的帖子啊
评论 支持 反对

举报

大家都不容易!
评论 支持 反对

举报

谢谢您的分享!
评论 支持 反对

举报

谢谢您的分享!
评论 支持 反对

举报

返回顶部