Virtualbox源码分析10 CPU manager2:APIs

10.1 R3Init相关APIs(CPUM.cpp)

CPUMR3Init 初始化CPUM

VMMR3DECL(int) CPUMR3Init(PVM pVM)
{
    //根据host CPU信息设置一些flag
    //获取host CPUID失败,直接返回
    if (!ASMHasCpuId())
    {
        return VERR_UNSUPPORTED_CPU;
    }
  	//获取MxCsr Mask
    pVM->cpum.s.fHostMxCsrMask = CPUMR3DeterminHostMxCsrMask();
    //获取VMX相关的MSR
    cpumR3GetHostHwvirtMsrs(&HostMsrs);
    //获取CPUID的所有leaves和sub leaves(后面初始化这些leaves,下一篇里会介绍这个函数
    CPUMR3CpuIdCollectLeaves(&paLeaves, &cLeaves);
  	
  	//CR4 mask
    pVM->cpum.s.CR4.AndMask = X86_CR4_OSXMMEEXCPT | X86_CR4_PVI | X86_CR4_VME;
    pVM->cpum.s.CR4.OrMask  = X86_CR4_OSFXSR;
  
  	//获取host是否支持XSAVE/XRSTOR指令
    //如果host支持XSave指令,才可以调用xgetbv指令
  	if ( pVM->cpum.s.HostFeatures.fXSaveRstor
        && pVM->cpum.s.HostFeatures.fOpSysXSaveRstor)
    {
      	//调用xgetbv获取AVX指令支持状态
        fXStateHostMask  = fXcr0Host = ASMGetXcr0();
        fXStateHostMask &= XSAVE_C_X87 | XSAVE_C_SSE | XSAVE_C_YMM | XSAVE_C_OPMASK | XSAVE_C_ZMM_HI256 | XSAVE_C_ZMM_16HI;
    }
    pVM->cpum.s.fXStateHostMask = fXStateHostMask;
  
    //获取CPU的相关信息 
    cpumR3CpuIdExplodeFeatures(paLeaves, cLeaves, &HostMsrs, &pVM->cpum.s.HostFeatures);
    pVM->cpum.s.GuestFeatures.enmCpuVendor = pVM->cpum.s.HostFeatures.enmCpuVendor;
    
   	//分配保存FPU/AVX寄存器的内存(用于XSAVE/XRSTOR的参数)
    //每个VCPU各自有两块内存,分别保存Guest和Host的FPU寄存器,用于切换Guest/Host
  	uint32_t cbMaxXState = pVM->cpum.s.HostFeatures.cbMaxExtendedState;
    cbMaxXState = RT_ALIGN(cbMaxXState, 128);
    uint8_t *pbXStates;
    rc = MMR3HyperAllocOnceNoRelEx(pVM, cbMaxXState * 2 * pVM->cCpus, PAGE_SIZE, MM_TAG_CPUM_CTX,
                                   MMHYPER_AONR_FLAGS_KERNEL_MAPPING, (void **)&pbXStates);
    for (VMCPUID i = 0; i < pVM->cCpus; i++)
    {
        PVMCPU pVCpu = pVM->apCpusR3[i];
				//分配一块内存分别映射R3 R0虚拟地址 给Guest
        pVCpu->cpum.s.Guest.pXStateR3 = (PX86XSAVEAREA)pbXStates;
        pVCpu->cpum.s.Guest.pXStateR0 = MMHyperR3ToR0(pVM, pbXStates);
        pbXStates += cbMaxXState;
				//分配一块内存分别映射R3 R0虚拟地址 给Host
        pVCpu->cpum.s.Host.pXStateR3  = (PX86XSAVEAREA)pbXStates;
        pVCpu->cpum.s.Host.pXStateR0  = MMHyperR3ToR0(pVM, pbXStates);
        pbXStates += cbMaxXState;
        pVCpu->cpum.s.Host.fXStateMask = fXStateHostMask;
    }
    
    //注册SSM的回调,当虚拟机保存或者继续当时候,回调用到这些回调里的函数
    rc = SSMR3RegisterInternal(pVM, "cpum", 1, CPUM_SAVED_STATE_VERSION, sizeof(CPUM),
                               NULL, cpumR3LiveExec, NULL,
                               NULL, cpumR3SaveExec, NULL,
                               cpumR3LoadPrep, cpumR3LoadExec, cpumR3LoadDone);
    
    //注册一些调试信息
    DBGFR3InfoRegisterInternalEx(pVM, "cpum",             "Displays the all the cpu states.",
                                 &cpumR3InfoAll, DBGFINFO_FLAGS_ALL_EMTS);
    rc = cpumR3DbgInit(pVM);
    
    //部分AMDCPU,需要标记在处理FXSAVE/FXRSTOR指令的时候会少保存部分寄存器
    //这部分CPU,设置pVCpu->cpum.s.fUseFlags |= CPUM_USE_FFXSR_LEAKY;
    cpumR3CheckLeakyFpu(pVM);
  
  	//初始化Guest OS CPUID和MSR信息,下一篇里介绍这个函数
    rc = cpumR3InitCpuIdAndMsrs(pVM, &HostMsrs);
  
    //申请VMX相关结构体内存
    if (pVM->cpum.s.GuestFeatures.fVmx)
        rc = cpumR3AllocVmxHwVirtState(pVM);
    else if (pVM->cpum.s.GuestFeatures.fSvm)
        rc = cpumR3AllocSvmHwVirtState(pVM);
    
    //调用CPUMR3ResetCpu初始化每个VCPU
    CPUMR3Reset(pVM);
}

cpumR3AllocVmxHwVirtState

//分派VMX使用的结构体
static int cpumR3AllocVmxHwVirtState(PVM pVM)
{
  //每个VCPU都有自己的VMX信息
	for (VMCPUID i = 0; i < pVM->cCpus; i++)
	{
     //嵌套Guest当前使用的VMCS
    pCtx->hwvirt.vmx.pVmcsR3 = (PVMXVVMCS)SUPR3ContAlloc(VMX_V_VMCS_PAGES,
                                                             &pCtx->hwvirt.vmx.pVmcsR0,
                                                             &pCtx->hwvirt.vmx.HCPhysVmcs);
    //嵌套Guest用于保存当前VMCS的shadow VMCS
     pCtx->hwvirt.vmx.pShadowVmcsR3 = (PVMXVVMCS)SUPR3ContAlloc(VMX_V_VMCS_PAGES,
                                                                   &pCtx->hwvirt.vmx.pShadowVmcsR0,
                                                                   &pCtx->hwvirt.vmx.HCPhysShadowVmcs);
    //虚拟APIC内存
    pCtx->hwvirt.vmx.pvVirtA picPageR3 = SUPR3ContAlloc(VMX_V_VIRT_APIC_PAGES,
                                                           &pCtx->hwvirt.vmx.pvVirtApicPageR0,
                                                           &pCtx->hwvirt.vmx.HCPhysVirtApicPage);
    //VMRead的bitmap
    pCtx->hwvirt.vmx.pvVmreadBitmapR3 = SUPR3ContAlloc(VMX_V_VMREAD_VMWRITE_BITMAP_PAGES,
                                                           &pCtx->hwvirt.vmx.pvVmreadBitmapR0,
                                                           &pCtx->hwvirt.vmx.HCPhysVmreadBitmap);
    //VMWRITE的bitmap
    pCtx->hwvirt.vmx.pvVmwriteBitmapR3 = SUPR3ContAlloc(VMX_V_VMREAD_VMWRITE_BITMAP_PAGES,
                                                            &pCtx->hwvirt.vmx.pvVmwriteBitmapR0,
                                                            &pCtx->hwvirt.vmx.HCPhysVmwriteBitmap);
    //VM-entry 的MSR-load 内存
    pCtx->hwvirt.vmx.pEntryMsrLoadAreaR3 = (PVMXAUTOMSR)SUPR3ContAlloc(VMX_V_AUTOMSR_AREA_PAGES,
                                                                           &pCtx->hwvirt.vmx.pEntryMsrLoadAreaR0,
                                                                           &pCtx->hwvirt.vmx.HCPhysEntryMsrLoadArea);
    //VM-exit的MSR-store内存
    pCtx->hwvirt.vmx.pExitMsrStoreAreaR3 = (PVMXAUTOMSR)SUPR3ContAlloc(VMX_V_AUTOMSR_AREA_PAGES,
                                                                           &pCtx->hwvirt.vmx.pExitMsrStoreAreaR0,
                                                                           &pCtx->hwvirt.vmx.HCPhysExitMsrStoreArea);
    //VM-exit的MSR-load内存
    pCtx->hwvirt.vmx.pExitMsrLoadAreaR3 = (PVMXAUTOMSR)SUPR3ContAlloc(VMX_V_AUTOMSR_AREA_PAGES,
                                                                          &pCtx->hwvirt.vmx.pExitMsrLoadAreaR0,
                                                                          &pCtx->hwvirt.vmx.HCPhysExitMsrLoadArea);
    //msr bitmap内存
    pCtx->hwvirt.vmx.pvMsrBitmapR3 = SUPR3ContAlloc(VMX_V_MSR_BITMAP_PAGES,
                                                        &pCtx->hwvirt.vmx.pvMsrBitmapR0,
                                                        &pCtx->hwvirt.vmx.HCPhysMsrBitmap);
    //I/O bitmap内存
    pCtx->hwvirt.vmx.pvIoBitmapR3 = SUPR3ContAlloc(VMX_V_IO_BITMAP_A_PAGES + VMX_V_IO_BITMAP_B_PAGES,
                                                       &pCtx->hwvirt.vmx.pvIoBitmapR0,
                                                       &pCtx->hwvirt.vmx.HCPhysIoBitmap);
	}
}

CPUMR3Term

//释放CPUMR3Init申请的内存
VMMR3DECL(int) CPUMR3Term(PVM pVM)
{
    if (pVM->cpum.s.GuestFeatures.fVmx)
        cpumR3FreeVmxHwVirtState(pVM);
    else if (pVM->cpum.s.GuestFeatures.fSvm)
        cpumR3FreeSvmHwVirtState(pVM);
}

CPUMR3InitCompleted

其他manager初始化完成之后,还需要根据其他manager的设置初始化部分设置

VMMR3DECL(int) CPUMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
{
  case VMINITCOMPLETED_RING3:
  {
		//????
    bool const fSupportsLongMode = VMR3IsLongModeAllowed(pVM);
    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
    {
      PVMCPU pVCpu = pVM->apCpusR3[idCpu];
      if (fSupportsLongMode)
        pVCpu->cpum.s.fUseFlags |= CPUM_USE_SUPPORTS_LONGMODE;
    }

    //初始化MSR寄存器的统计信息
    cpumR3MsrRegStats(pVM);

    //如果CPU支持VMX嵌套,需要初始化给嵌套Guest用的VMX timer
    if (pVM->cpum.s.GuestFeatures.fVmx)
    {
      for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
      {
        PVMCPU pVCpu = pVM->apCpusR3[idCpu];
        int rc = TMR3TimerCreateInternal(pVM, TMCLOCK_VIRTUAL_SYNC, cpumR3VmxPreemptTimerCallback, pVCpu,
                                         "Nested Guest VMX-preempt. timer", &pVCpu->cpum.s.pNestedVmxPreemptTimerR3);
        pVCpu->cpum.s.pNestedVmxPreemptTimerR0 = TMTimerR0Ptr(pVCpu->cpum.s.pNestedVmxPreemptTimerR3);
      }
    }
    break;
  }
}

CPUMR3ResetCpu

VMMR3DECL(void) CPUMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
{
    PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
    memset(pCtx, 0, RT_UOFFSETOF(CPUMCTX, pXStateR0));
    pCtx->cr0                       = X86_CR0_CD | X86_CR0_NW | X86_CR0_ET;  //0x60000010
    pCtx->eip                       = 0x0000fff0;
    pCtx->edx                       = 0x00000600;   /* P6 processor */
    pCtx->eflags.Bits.u1Reserved0   = 1;

  	//cs段寄存器
    pCtx->cs.Sel                    = 0xf000;
    pCtx->cs.ValidSel               = 0xf000;
    pCtx->cs.fFlags                 = CPUMSELREG_FLAGS_VALID;
    pCtx->cs.u64Base                = UINT64_C(0xffff0000);
    pCtx->cs.u32Limit               = 0x0000ffff;
    pCtx->cs.Attr.n.u1DescType      = 1; /* code/data segment */
    pCtx->cs.Attr.n.u1Present       = 1;
    pCtx->cs.Attr.n.u4Type          = X86_SEL_TYPE_ER_ACC;
	  //ds段寄存器
    pCtx->ds.fFlags                 = CPUMSELREG_FLAGS_VALID;
    pCtx->ds.u32Limit               = 0x0000ffff;
    pCtx->ds.Attr.n.u1DescType      = 1; /* code/data segment */
    pCtx->ds.Attr.n.u1Present       = 1;
    pCtx->ds.Attr.n.u4Type          = X86_SEL_TYPE_RW_ACC;
    //es
    pCtx->es.fFlags                 = CPUMSELREG_FLAGS_VALID;
    pCtx->es.u32Limit               = 0x0000ffff;
    pCtx->es.Attr.n.u1DescType      = 1; /* code/data segment */
    pCtx->es.Attr.n.u1Present       = 1;
    pCtx->es.Attr.n.u4Type          = X86_SEL_TYPE_RW_ACC;
    //fs
    pCtx->fs.fFlags                 = CPUMSELREG_FLAGS_VALID;
    pCtx->fs.u32Limit               = 0x0000ffff;
    pCtx->fs.Attr.n.u1DescType      = 1; /* code/data segment */
    pCtx->fs.Attr.n.u1Present       = 1;
    pCtx->fs.Attr.n.u4Type          = X86_SEL_TYPE_RW_ACC;
    //gs
    pCtx->gs.fFlags                 = CPUMSELREG_FLAGS_VALID;
    pCtx->gs.u32Limit               = 0x0000ffff;
    pCtx->gs.Attr.n.u1DescType      = 1; /* code/data segment */
    pCtx->gs.Attr.n.u1Present       = 1;
    pCtx->gs.Attr.n.u4Type          = X86_SEL_TYPE_RW_ACC;
    //ss
    pCtx->ss.fFlags                 = CPUMSELREG_FLAGS_VALID;
    pCtx->ss.u32Limit               = 0x0000ffff;
    pCtx->ss.Attr.n.u1Present       = 1;
    pCtx->ss.Attr.n.u1DescType      = 1; /* code/data segment */
    pCtx->ss.Attr.n.u4Type          = X86_SEL_TYPE_RW_ACC;
    
    pCtx->idtr.cbIdt                = 0xffff;
    pCtx->gdtr.cbGdt                = 0xffff;

    pCtx->ldtr.fFlags               = CPUMSELREG_FLAGS_VALID;
    pCtx->ldtr.u32Limit             = 0xffff;
    pCtx->ldtr.Attr.n.u1Present     = 1;
    pCtx->ldtr.Attr.n.u4Type        = X86_SEL_TYPE_SYS_LDT;

    pCtx->tr.fFlags                 = CPUMSELREG_FLAGS_VALID;
    pCtx->tr.u32Limit               = 0xffff;
    pCtx->tr.Attr.n.u1Present       = 1;
    pCtx->tr.Attr.n.u4Type          = X86_SEL_TYPE_SYS_386_TSS_BUSY;    /* Deduction, not properly documented by Intel. */

    pCtx->dr[6]                     = X86_DR6_INIT_VAL;
    pCtx->dr[7]                     = X86_DR7_INIT_VAL;

    PX86FXSTATE pFpuCtx = &pCtx->pXStateR3->x87; AssertReleaseMsg(RT_VALID_PTR(pFpuCtx), ("%p\n", pFpuCtx));
    pFpuCtx->FTW                    = 0x00;         /* All empty (abbridged tag reg edition). */
    pFpuCtx->FCW                    = 0x37f;
    pFpuCtx->MXCSR                  = 0x1F80;
    pFpuCtx->MXCSR_MASK             = pVM->cpum.s.GuestInfo.fMxCsrMask; /** @todo check if REM messes this up... */

    pCtx->aXcr[0]                   = XSAVE_C_X87;
    if (pVM->cpum.s.HostFeatures.cbMaxExtendedState >= RT_UOFFSETOF(X86XSAVEAREA, Hdr))
    {
        /* The entire FXSAVE state needs loading when we switch to XSAVE/XRSTOR
           as we don't know what happened before.  (Bother optimize later?) */
        pCtx->pXStateR3->Hdr.bmXState = XSAVE_C_X87 | XSAVE_C_SSE;
    }
 		pCtx->msrPAT                    = MSR_IA32_CR_PAT_INIT_VAL;
  
  	if (CPUMMICROARCH_IS_INTEL_CORE2(pVM->cpum.s.GuestFeatures.enmMicroarch))
        pVCpu->cpum.s.GuestMsrs.msr.PkgCStateCfgCtrl = 0x202a01;    /* From Mac Pro Harpertown, unlocked. */
    else if (pVM->cpum.s.GuestFeatures.enmMicroarch == kCpumMicroarch_Intel_Core_Yonah)
        pVCpu->cpum.s.GuestMsrs.msr.PkgCStateCfgCtrl = 0x26740c;    /* From MacBookPro1,1. */
  
  	CPUMSetGuestGif(pCtx, true);
    Assert(!pVM->cpum.s.GuestFeatures.fVmx || !pVM->cpum.s.GuestFeatures.fSvm);   /* Paranoia. */
    if (pVM->cpum.s.GuestFeatures.fVmx)
        cpumR3ResetVmxHwVirtState(pVCpu);
    else if (pVM->cpum.s.GuestFeatures.fSvm)
        cpumR3ResetSvmHwVirtState(pVCpu);
}

CPUMR3DisasmInstrCPU

这个API用于解码一条指令,结果保存在PDISCPUSTATE里

VMMR3DECL(int) CPUMR3DisasmInstrCPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTGCPTR GCPtrPC, PDISCPUSTATE pCpu,
                                    const char *pszPrefix)
{
   //根据GuestOS状态设置State(32/64,cs段等)
  	if (    (pCtx->cr0 & X86_CR0_PE)
        &&   pCtx->eflags.Bits.u1VM == 0)
    {
      	//32or64位保护模式
        State.f64Bits         = enmMode >= PGMMODE_AMD64 && pCtx->cs.Attr.n.u1Long;
        //cs段寄存器,方便读取指令
        State.GCPtrSegBase    = pCtx->cs.u64Base;
        State.GCPtrSegEnd     = pCtx->cs.u32Limit + 1 + (RTGCUINTPTR)pCtx->cs.u64Base;
        State.cbSegLimit      = pCtx->cs.u32Limit;
        enmDisCpuMode         = (State.f64Bits)
                              ? DISCPUMODE_64BIT
                              : pCtx->cs.Attr.n.u1DefBig
                              ? DISCPUMODE_32BIT
                              : DISCPUMODE_16BIT;
    }
    else
    {
        //没有开启分页,是实模式或者保护模式
        enmDisCpuMode         = DISCPUMODE_16BIT;
        State.GCPtrSegBase    = pCtx->cs.Sel * 16;
        State.GCPtrSegEnd     = 0xFFFFFFFF;
        State.cbSegLimit      = 0xFFFFFFFF;
    }
    //调用decode lib解析这条指令
    DISInstrWithReader(GCPtrPC, enmDisCpuMode, cpumR3DisasInstrRead, &State, pCpu, &cbInstr); 
}
//decode lib用的callback函数,读取一条指令
//pfnReadBytes(pDis, 0, 1, sizeof(pDis->abInstr));
static DECLCALLBACK(int) cpumR3DisasInstrRead(PDISCPUSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
{
  for (;;)
  {
    //获取GC
    RTGCUINTPTR GCPtr = pDis->uInstrAddr + offInstr + pState->GCPtrSegBase;
    //如果当前页面已经映射了HostGC地址,则不需要重新映射一次
    if (   !pState->pvPageR3
            || (GCPtr >> PAGE_SHIFT) != (pState->pvPageGC >> PAGE_SHIFT))
    {
      	 State->pvPageGC = GCPtr & PAGE_BASE_GC_MASK;
     			//GC page映射一个HostR3地址 (pState->pvPageR3)
         PGMPhysGCPtr2CCPtrReadOnly(pState->pVCpu, pState->pvPageGC, &pState->pvPageR3, &pState->PageMapLock);
		}
    //计算需要读取的大小,
    uint32_t cb = PAGE_SIZE - (GCPtr & PAGE_OFFSET_MASK);
    if (!pState->f64Bits)
    {
      RTGCUINTPTR cbSeg = pState->GCPtrSegEnd - GCPtr;
      if (cb > cbSeg && cbSeg)
        cb = cbSeg;
    }
    if (cb > cbMaxRead)
      cb = cbMaxRead;
    //读取cb字节
    memcpy(&pDis->abInstr[offInstr], (uint8_t *)pState->pvPageR3 + (GCPtr & PAGE_OFFSET_MASK), cb);
    offInstr  += (uint8_t)cb;
    //如果已经读完,则直接返回,否则继续读
    if (cb >= cbMinRead)
    {
      pDis->cbCachedInstr = offInstr;
      return VINF_SUCCESS;
    }
    cbMinRead -= (uint8_t)cb;
    cbMaxRead -= (uint8_t)cb;
	}
}

10.2 用于保存VM的API

CPUMInit的时候,调用SSMR3RegisterInternal,注册虚拟机做保存和继续的回掉,当VM保存/做快照/从快照启动等会调用相关的函数

CPUM_SAVED_STATE_VERSION

保存状态的版本,标记需要保存和恢复哪些寄存器

//默认是开启VMX
#define CPUM_SAVED_STATE_VERSION                CPUM_SAVED_STATE_VERSION_HWVIRT_VMX_IEM
/** The saved state version 包含VMX 状态. */
#define CPUM_SAVED_STATE_VERSION_HWVIRT_VMX_IEM 19
/** The saved state version 包含SVM 状态. */
#define CPUM_SAVED_STATE_VERSION_HWVIRT_SVM     18
/** The saved state version 包含XSAVE 状态. */
#define CPUM_SAVED_STATE_VERSION_XSAVE          17
/** The saved state version 包含正常的CPUID leaf状态. */
#define CPUM_SAVED_STATE_VERSION_GOOD_CPUID_COUNT 16
/** The saved state version 包含没有更新的CPUID leaf状态. */
#define CPUM_SAVED_STATE_VERSION_BAD_CPUID_COUNT 15
/** The saved state version before the CPUIDs changes. */
#define CPUM_SAVED_STATE_VERSION_PUT_STRUCT     14
/** The saved state version before using SSMR3PutStruct. */
#define CPUM_SAVED_STATE_VERSION_MEM            13
/** The saved state version before introducing the MSR size field. */
#define CPUM_SAVED_STATE_VERSION_NO_MSR_SIZE    12
/** The saved state version of 3.2, 3.1 and 3.3 trunk before the hidden
 * selector register change (CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID). */
#define CPUM_SAVED_STATE_VERSION_VER3_2         11
/** The saved state version of 3.0 and 3.1 trunk before the teleportation
 * changes. */
#define CPUM_SAVED_STATE_VERSION_VER3_0         10
/** The saved state version for the 2.1 trunk before the MSR changes. */
#define CPUM_SAVED_STATE_VERSION_VER2_1_NOMSR   9
/** The saved state version of 2.0, used for backwards compatibility. */
#define CPUM_SAVED_STATE_VERSION_VER2_0         8
/** The saved state version of 1.6, used for backwards compatibility. */
#define CPUM_SAVED_STATE_VERSION_VER1_6         6

cpumR3SaveExec

保存CPU的虚拟机状态

static DECLCALLBACK(int) cpumR3SaveExec(PVM pVM, PSSMHANDLE pSSM)
{
  	SSMR3PutU32(pSSM, pVM->cCpus);
    SSMR3PutU32(pSSM, sizeof(pVM->apCpusR3[0]->cpum.s.GuestMsrs.msr));
  	for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
    {
      //对每个VCPU
      //保存pVCpu->cpum.s.Guest到g_aCpumCtxFields全局变量里
      PCPUMCTX pGstCtx = &pVCpu->cpum.s.Guest;
        SSMR3PutStructEx(pSSM, pGstCtx,                  sizeof(*pGstCtx),                0, g_aCpumCtxFields, NULL);
      //pGstCtx->pXStateR3->x87保存到  g_aCpumX87Fields里
      SSMR3PutStructEx(pSSM, &pGstCtx->pXStateR3->x87, sizeof(pGstCtx->pXStateR3->x87), 0, g_aCpumX87Fields, NULL);
    }
    //根据XSAVE的mask保存相应寄存器
  	//保存YMM寄存器到g_aCpumYmmHiFields
  	if (pGstCtx->fXStateMask & XSAVE_C_YMM)
    {
      PCX86XSAVEYMMHI pYmmHiCtx = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_YMM_BIT, PCX86XSAVEYMMHI);
      SSMR3PutStructEx(pSSM, pYmmHiCtx, sizeof(*pYmmHiCtx), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumYmmHiFields, NULL);
    }
    // BNDREGS - MPX bound register state
    if (pGstCtx->fXStateMask & XSAVE_C_BNDREGS)
    {
      PCX86XSAVEBNDREGS pBndRegs = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_BNDREGS_BIT, PCX86XSAVEBNDREGS);
      SSMR3PutStructEx(pSSM, pBndRegs, sizeof(*pBndRegs), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumBndRegsFields, NULL);
    }
    //BNDCSR - MPX bound config and status state. 
    if (pGstCtx->fXStateMask & XSAVE_C_BNDCSR)
    {
      PCX86XSAVEBNDCFG pBndCfg = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_BNDCSR_BIT, PCX86XSAVEBNDCFG);
      SSMR3PutStructEx(pSSM, pBndCfg, sizeof(*pBndCfg), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumBndCfgFields, NULL);
    }
    //ZMM_Hi256 - Upper 256 bits of ZMM0-15 (AVX-512)
    if (pGstCtx->fXStateMask & XSAVE_C_ZMM_HI256)
    {
      PCX86XSAVEZMMHI256 pZmmHi256 = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_ZMM_HI256_BIT, PCX86XSAVEZMMHI256);
      SSMR3PutStructEx(pSSM, pZmmHi256, sizeof(*pZmmHi256), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumZmmHi256Fields, NULL);
    }
    // Hi16_ZMM - 512-bits ZMM16-31 state 
    if (pGstCtx->fXStateMask & XSAVE_C_ZMM_16HI)
    {
      PCX86XSAVEZMM16HI pZmm16Hi = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_ZMM_16HI_BIT, PCX86XSAVEZMM16HI);
      SSMR3PutStructEx(pSSM, pZmm16Hi, sizeof(*pZmm16Hi), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumZmm16HiFields, NULL);
    }
 		//VMX相关信息
 	 	if (pVM->cpum.s.GuestFeatures.fSvm)
    {
      Assert(pGstCtx->hwvirt.svm.CTX_SUFF(pVmcb));
      SSMR3PutU64(pSSM,    pGstCtx->hwvirt.svm.uMsrHSavePa);
      SSMR3PutGCPhys(pSSM, pGstCtx->hwvirt.svm.GCPhysVmcb);
      SSMR3PutU64(pSSM,    pGstCtx->hwvirt.svm.uPrevPauseTick);
      SSMR3PutU16(pSSM,    pGstCtx->hwvirt.svm.cPauseFilter);
      SSMR3PutU16(pSSM,    pGstCtx->hwvirt.svm.cPauseFilterThreshold);
      SSMR3PutBool(pSSM,   pGstCtx->hwvirt.svm.fInterceptEvents);
      SSMR3PutStructEx(pSSM, &pGstCtx->hwvirt.svm.HostState, sizeof(pGstCtx->hwvirt.svm.HostState), 0 /* fFlags */,
                       g_aSvmHwvirtHostState, NULL /* pvUser */);
      SSMR3PutMem(pSSM,    pGstCtx->hwvirt.svm.pVmcbR3,       SVM_VMCB_PAGES  << X86_PAGE_4K_SHIFT);
      SSMR3PutMem(pSSM,    pGstCtx->hwvirt.svm.pvMsrBitmapR3, SVM_MSRPM_PAGES << X86_PAGE_4K_SHIFT);
      SSMR3PutMem(pSSM,    pGstCtx->hwvirt.svm.pvIoBitmapR3,  SVM_IOPM_PAGES  << X86_PAGE_4K_SHIFT);
      SSMR3PutU32(pSSM,    pGstCtx->hwvirt.fLocalForcedActions);
      SSMR3PutBool(pSSM,   pGstCtx->hwvirt.fGif);
    }
    if (pVM->cpum.s.GuestFeatures.fVmx)
    {
      //保存GCPhysVmxon对应的物理内存
      SSMR3PutGCPhys(pSSM,   pGstCtx->hwvirt.vmx.GCPhysVmxon);
      //vmcs和shadowVMCS内容
      SSMR3PutGCPhys(pSSM,   pGstCtx->hwvirt.vmx.GCPhysVmcs);
      SSMR3PutGCPhys(pSSM,   pGstCtx->hwvirt.vmx.GCPhysShadowVmcs);
      //一些开关的保存
      SSMR3PutBool(pSSM,     pGstCtx->hwvirt.vmx.fInVmxRootMode);
      SSMR3PutBool(pSSM,     pGstCtx->hwvirt.vmx.fInVmxNonRootMode);
      SSMR3PutBool(pSSM,     pGstCtx->hwvirt.vmx.fInterceptEvents);
      SSMR3PutBool(pSSM,     pGstCtx->hwvirt.vmx.fNmiUnblockingIret);
      //vmcsR3/ShadowVmcsR3/xxxbitmap保存
      SSMR3PutStructEx(pSSM, pGstCtx->hwvirt.vmx.pVmcsR3, sizeof(VMXVVMCS), 0, g_aVmxHwvirtVmcs, NULL);
      SSMR3PutStructEx(pSSM, pGstCtx->hwvirt.vmx.pShadowVmcsR3, sizeof(VMXVVMCS), 0, g_aVmxHwvirtVmcs, NULL);
      SSMR3PutMem(pSSM,      pGstCtx->hwvirt.vmx.pvVmreadBitmapR3, VMX_V_VMREAD_VMWRITE_BITMAP_SIZE);
      SSMR3PutMem(pSSM,      pGstCtx->hwvirt.vmx.pvVmwriteBitmapR3, VMX_V_VMREAD_VMWRITE_BITMAP_SIZE);
      SSMR3PutMem(pSSM,      pGstCtx->hwvirt.vmx.pEntryMsrLoadAreaR3, VMX_V_AUTOMSR_AREA_SIZE);
      SSMR3PutMem(pSSM,      pGstCtx->hwvirt.vmx.pExitMsrStoreAreaR3, VMX_V_AUTOMSR_AREA_SIZE);
      SSMR3PutMem(pSSM,      pGstCtx->hwvirt.vmx.pExitMsrLoadAreaR3,  VMX_V_AUTOMSR_AREA_SIZE);
      SSMR3PutMem(pSSM,      pGstCtx->hwvirt.vmx.pvMsrBitmapR3, VMX_V_MSR_BITMAP_SIZE);
      SSMR3PutMem(pSSM,      pGstCtx->hwvirt.vmx.pvIoBitmapR3, VMX_V_IO_BITMAP_A_SIZE + VMX_V_IO_BITMAP_B_SIZE);
      //一些VMX设置到保存
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.uFirstPauseLoopTick);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.uPrevPauseTick);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.uEntryTick);
      SSMR3PutU16(pSSM,      pGstCtx->hwvirt.vmx.offVirtApicWrite);
      SSMR3PutBool(pSSM,     pGstCtx->hwvirt.vmx.fVirtNmiBlocking);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64FeatCtrl);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64Basic);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.PinCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.ProcCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.ProcCtls2.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.ExitCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.EntryCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.TruePinCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.TrueProcCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.TrueEntryCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.TrueExitCtls.u);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64Misc);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64VmcsEnum);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64VmFunc);
      SSMR3PutU64(pSSM,      pGstCtx->hwvirt.vmx.Msrs.u64EptVpidCaps);
    }
    SSMR3PutU32(pSSM, pVCpu->cpum.s.fUseFlags);
    SSMR3PutU32(pSSM, pVCpu->cpum.s.fChanged);
    //保存Guest的msr寄存器
    SSMR3PutMem(pSSM, &pVCpu->cpum.s.GuestMsrs, sizeof(pVCpu->cpum.s.GuestMsrs.msr));
  }
  //保存CPUID的所有leaves
  cpumR3SaveCpuId(pVM, pSSM);
}

cpumR3LoadPrep

//标记马上要开始load CPU相关信息
static DECLCALLBACK(int) cpumR3LoadPrep(PVM pVM, PSSMHANDLE pSSM)
{
  pVM->cpum.s.fPendingRestore = true;
}

cpumR3LoadExec

从保存的状态里恢复CPU相关信息,恢复顺序和cpumR3SaveExec相同

static DECLCALLBACK(int) cpumR3LoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
{
  //The special value for the final pass.
  if (uPass == SSM_PASS_FINAL)
  {
    	if (uVersion >= CPUM_SAVED_STATE_VERSION_XSAVE)  
      {
        	//需要LoadFPU寄存器
        	SSMR3GetStructEx(pSSM, &Ign, sizeof(Ign), fLoad | SSMSTRUCT_FLAGS_NO_TAIL_MARKER, paCpumCtx1Fields, NULL);
          SSMR3GetStructEx(pSSM, &HyperCtxIgnored, sizeof(HyperCtxIgnored),
                                 fLoad | SSMSTRUCT_FLAGS_NO_LEAD_MARKER, paCpumCtx2Fields, NULL);
        	
			}
      if (uVersion >= CPUM_SAVED_STATE_VERSION_VER2_1_NOMSR)
       {
            //Load VCPU个数
        	  uint32_t cCpus;
            rc = SSMR3GetU32(pSSM, &cCpus); AssertRCReturn(rc, rc);
       }
    		//load msr寄存器个数
    		uint32_t cbMsrs = 0;
        if (uVersion > CPUM_SAVED_STATE_VERSION_NO_MSR_SIZE)
        {
            rc = SSMR3GetU32(pSSM, &cbMsrs); 
        }
    		//pre-vCPU
        for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
        {
					if (uVersion >= CPUM_SAVED_STATE_VERSION_XSAVE)
          {
            //从各个全局变量里load FPU寄存器
            SSMR3GetStructEx(pSSM, &HyperCtxIgnored,         sizeof(HyperCtxIgnored),         0, g_aCpumCtxFields, NULL);
            SSMR3GetStructEx(pSSM, pGstCtx,                  sizeof(*pGstCtx),                0, g_aCpumCtxFields, NULL);
            SSMR3GetStructEx(pSSM, &pGstCtx->pXStateR3->x87, sizeof(pGstCtx->pXStateR3->x87), 0, g_aCpumX87Fields, NULL);
            //检查加载的FPU寄存器是否正确
            AssertLogRelMsgReturn(pGstCtx->aXcr[0] & XSAVE_C_X87, ("xcr0=%#RX64\n", pGstCtx->aXcr[0]), VERR_CPUM_INVALID_XCR0);
            ...
           	//SaveExec相反的操作,从全局变量里恢复相关寄存器
            if (pGstCtx->fXStateMask & XSAVE_C_YMM)
            {
              PX86XSAVEYMMHI pYmmHiCtx = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_YMM_BIT, PX86XSAVEYMMHI);
              SSMR3GetStructEx(pSSM, pYmmHiCtx, sizeof(*pYmmHiCtx), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumYmmHiFields, NULL);
            }
            if (pGstCtx->fXStateMask & XSAVE_C_BNDREGS)
            {
              PX86XSAVEBNDREGS pBndRegs = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_BNDREGS_BIT, PX86XSAVEBNDREGS);
              SSMR3GetStructEx(pSSM, pBndRegs, sizeof(*pBndRegs), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumBndRegsFields, NULL);
            }
            if (pGstCtx->fXStateMask & XSAVE_C_BNDCSR)
            {
              PX86XSAVEBNDCFG pBndCfg = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_BNDCSR_BIT, PX86XSAVEBNDCFG);
              SSMR3GetStructEx(pSSM, pBndCfg, sizeof(*pBndCfg), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumBndCfgFields, NULL);
            }
            if (pGstCtx->fXStateMask & XSAVE_C_ZMM_HI256)
            {
              PX86XSAVEZMMHI256 pZmmHi256 = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_ZMM_HI256_BIT, PX86XSAVEZMMHI256);
              SSMR3GetStructEx(pSSM, pZmmHi256, sizeof(*pZmmHi256), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumZmmHi256Fields, NULL);
            }
            if (pGstCtx->fXStateMask & XSAVE_C_ZMM_16HI)
            {
              PX86XSAVEZMM16HI pZmm16Hi = CPUMCTX_XSAVE_C_PTR(pGstCtx, XSAVE_C_ZMM_16HI_BIT, PX86XSAVEZMM16HI);
              SSMR3GetStructEx(pSSM, pZmm16Hi, sizeof(*pZmm16Hi), SSMSTRUCT_FLAGS_FULL_STRUCT, g_aCpumZmm16HiFields, NULL);
            }
            //恢复SVM相关的数据
            if (uVersion >= CPUM_SAVED_STATE_VERSION_HWVIRT_SVM)
            {
              if (pVM->cpum.s.GuestFeatures.fSvm)
              {
                Assert(pGstCtx->hwvirt.svm.CTX_SUFF(pVmcb));
                SSMR3GetU64(pSSM,      &pGstCtx->hwvirt.svm.uMsrHSavePa);
                SSMR3GetGCPhys(pSSM,   &pGstCtx->hwvirt.svm.GCPhysVmcb);
                SSMR3GetU64(pSSM,      &pGstCtx->hwvirt.svm.uPrevPauseTick);
                ...
              }
            }
            //恢复VMX相关的数据
            if (uVersion >= CPUM_SAVED_STATE_VERSION_HWVIRT_VMX_IEM)
            {
              if (pVM->cpum.s.GuestFeatures.fVmx)
              {
                SSMR3GetGCPhys(pSSM,   &pGstCtx->hwvirt.vmx.GCPhysVmxon);
                SSMR3GetGCPhys(pSSM,   &pGstCtx->hwvirt.vmx.GCPhysVmcs);
                ...
              }
            }
          } 
          //恢复一些flags
          SSMR3GetU32(pSSM, &pVCpu->cpum.s.fUseFlags);
          SSMR3GetU32(pSSM, &pVCpu->cpum.s.fChanged);
          //部分MSR寄存器信息
          if (uVersion > CPUM_SAVED_STATE_VERSION_NO_MSR_SIZE)
                rc = SSMR3GetMem(pSSM, &pVCpu->cpum.s.GuestMsrs.au64[0], cbMsrs);
          else if (uVersion >= CPUM_SAVED_STATE_VERSION_VER3_0)
          {
            SSMR3GetMem(pSSM, &pVCpu->cpum.s.GuestMsrs.au64[0], 2 * sizeof(uint64_t));
            rc = SSMR3Skip(pSSM, 62 * sizeof(uint64_t));
          }

          //重置Dr6 Dr7寄存器
          pGstCtx->dr[6] &= ~(X86_DR6_RAZ_MASK | X86_DR6_MBZ_MASK);
          pGstCtx->dr[6] |= X86_DR6_RA1_MASK;
          pGstCtx->dr[7] &= ~(X86_DR7_RAZ_MASK | X86_DR7_MBZ_MASK);
          pGstCtx->dr[7] |= X86_DR7_RA1_MASK;
          
        }//end of pre-vCPU
	}
  //fPendingRestore设置成false,已经完成restore
  pVM->cpum.s.fPendingRestore = false;
  
  //恢复CPUID leaves和GuestMsrs
  if (uVersion >= CPUM_SAVED_STATE_VERSION_VER3_2)
  {
    CPUMMSRS GuestMsrs;

    CPUMFEATURES BaseFeatures;
    bool const fVmxGstFeat = pVM->cpum.s.GuestFeatures.fVmx;
    if (fVmxGstFeat)
    {
      BaseFeatures = pVM->cpum.s.GuestFeatures;
      GuestMsrs.hwvirt.vmx = pVM->apCpusR3[0]->cpum.s.Guest.hwvirt.vmx.Msrs;
    }

    //恢复CPUID leaves和GuestMsrs
    rc = cpumR3LoadCpuId(pVM, pSSM, uVersion, &GuestMsrs);
    return rc;
  }
  return cpumR3LoadCpuIdPre32(pVM, pSSM, uVersion);
}

cpumR3LoadDone

static DECLCALLBACK(int) cpumR3LoadDone(PVM pVM, PSSMHANDLE pSSM)
{
  	//调到这个函数的时候fPendingRestore不能是1
  	if (pVM->cpum.s.fPendingRestore)
    {
        return VERR_INTERNAL_ERROR_2;
    }
  	//如果支持64bit Guest
  	bool const fSupportsLongMode = VMR3IsLongModeAllowed(pVM);
    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
    {
        PVMCPU pVCpu = pVM->apCpusR3[idCpu];
        //如果改变了EFER寄存器里的NX位,需要通知PGM修改相对应的全局变量
        PGMNotifyNxeChanged(pVCpu, RT_BOOL(pVCpu->cpum.s.Guest.msrEFER & MSR_K6_EFER_NXE));
        if (fSupportsLongMode)
            pVCpu->cpum.s.fUseFlags |= CPUM_USE_SUPPORTS_LONGMODE;
    }
}

CPUMR3IsStateRestorePending

//CPUM是否处于restore状态
VMMDECL(bool) CPUMR3IsStateRestorePending(PVM pVM)
{
    return pVM->cpum.s.fPendingRestore;
}

10.3 R0相关APIs

VMM\VMMR0\CPUMR0.cpp CPUMR0.asm

这里大部分工作: 1. 检测CPU是否能开启VBOX,2, 支持APIC虚拟化(后面介绍 ), 3.调试支持

CPUMR0InitVM

VMMR0_INT_DECL(int) CPUMR0InitVM(PVM pVM)
{
  	uint32_t u32CR0 = ASMGetCR0();
    if ((u32CR0 & (X86_CR0_PE | X86_CR0_PG)) != (X86_CR0_PE | X86_CR0_PG))
      return VERR_UNSUPPORTED_CPU_MODE;
    //部分CPU需要检查是否支持SYSENTER
    if (    (fFeatures & X86_CPUID_FEATURE_EDX_SEP)
            &&  (   u32Family   != 6    /* (> pentium pro) */
                 || u32Model    >= 3
                 || u32Stepping >= 3
                 || !ASMIsIntelCpu()))
    {

      uint32_t u32 = ASMRdMsr_Low(MSR_IA32_SYSENTER_CS);
      if (u32)
      {
        pVM->cpum.s.fHostUseFlags |= CPUM_USE_SYSENTER;
      }
    }
  
  	//host是否支持syscall
    uint32_t cExt = 0;
  	//获取Extended Function CPUID input的最大值.
    ASMCpuId(0x80000000, &cExt, &u32Dummy, &u32Dummy, &u32Dummy);
    if (ASMIsValidExtRange(cExt))
    {
      uint32_t fExtFeaturesEDX = ASMCpuId_EDX(0x80000001);
      //edx bit11标示是否支持syscall/sysret
      if (fExtFeaturesEDX & X86_CPUID_EXT_FEATURE_EDX_SYSCALL)
      {
#ifdef RT_ARCH_X86
        if (!ASMIsIntelCpu())
#endif
        {
          //64位CPU和32位AMDCPU 还需要检查MSR_K6_EFER_SCE寄存器是否打开
          uint64_t fEfer = ASMRdMsr(MSR_K6_EFER);
          if (fEfer & MSR_K6_EFER_SCE)
          {
            pVM->cpum.s.fHostUseFlags |= CPUM_USE_SYSCALL;
          }
        }
      }
    }

   //获取 Function CPUID input的最大值.
 	 uint32_t const cStdRange = ASMCpuId_EAX(0);
   if (   ASMIsValidStdRange(cStdRange)
      && cStdRange >= 7)
   {
     //获取cpuid(7)返回的edx
     uint32_t fEdxFeatures = ASMCpuId_EDX(7);
     if (   (fEdxFeatures & X86_CPUID_STEXT_FEATURE_EDX_ARCHCAP)
        && (fFeatures & X86_CPUID_FEATURE_EDX_MSR))
     {
       uint64_t const fArchVal = ASMRdMsr(MSR_IA32_ARCH_CAPABILITIES);
       pVM->cpum.s.GuestFeatures.fArchRdclNo
         = pVM->cpum.s.HostFeatures.fArchRdclNo             = RT_BOOL(fArchVal & MSR_IA32_ARCH_CAP_F_RDCL_NO);
       pVM->cpum.s.GuestFeatures.fArchIbrsAll
         = pVM->cpum.s.HostFeatures.fArchIbrsAll            = RT_BOOL(fArchVal & MSR_IA32_ARCH_CAP_F_IBRS_ALL);
       pVM->cpum.s.GuestFeatures.fArchRsbOverride
         = pVM->cpum.s.HostFeatures.fArchRsbOverride        = RT_BOOL(fArchVal & MSR_IA32_ARCH_CAP_F_RSBO);
       pVM->cpum.s.GuestFeatures.fArchVmmNeedNotFlushL1d
         = pVM->cpum.s.HostFeatures.fArchVmmNeedNotFlushL1d = RT_BOOL(fArchVal & MSR_IA32_ARCH_CAP_F_VMM_NEED_NOT_FLUSH_L1D);
       pVM->cpum.s.GuestFeatures.fArchMdsNo
         = pVM->cpum.s.HostFeatures.fArchMdsNo              = RT_BOOL(fArchVal & MSR_IA32_ARCH_CAP_F_MDS_NO);

       if (pVM->cpum.s.GuestFeatures.fArchCap)
         VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->cpum.s.GuestMsrs.msr.ArchCaps = fArchVal);
     }
     else
       pVM->cpum.s.HostFeatures.fArchCap = 0;
   }
  
}

CPUMR0ModuleInit

//只做了一件事情,初始化LocalAPIC, 后面会专门一篇介绍APIC虚拟化
VMMR0_INT_DECL(int) CPUMR0ModuleInit(void)
{
#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
    rc = cpumR0MapLocalApics();
#endif
}

CPUMR0Trap07Handler

支持Lazy FPU:

现代处理器采用多种技术来提高系统性能。其中一种技术是推迟保存和恢复任务交换机上的某些 CPU 上下文状态。

当操作系统发生线程切换的时候将发生任务/上下文切换。在任务切换时,处理器保存其当前执行上下文(各种寄存器、指令和堆栈指针等),并加载新进程的上下文。在执行此操作时,它可以延迟 FPU/SSE 上下文状态的还原,因为并非所有应用程序都使用浮点单元 (FPU)。如果新计划的进程不使用浮点 (FP) 指令,则不需要保存/还原 FPU 上下文状态。这可以节省宝贵的执行周期并提高性能。

在延迟还原方案下,在任务切换期间,进程执行的第一个 FP 指令将生成"设备不可用 (DNA)"异常;然后,DNA 异常处理程序将当前 FPU 上下文保存到旧任务的状态保存区域,并加载当前进程的新的 FPU 上下文。换句话说,FPU 状态的加载将延迟,直到当前任务调用 FP 指令 - Lazy FPU restore。

最近的处理器包括处理器扩展(“XSAVEOPT”),这些扩展在硬件中更高效地实现 FPU 还原,从而在无需依赖 DNA 异常的情况下,提供延迟 FPU 的性能优势。在支持XSAVEOPT的CPU上,不会产生这个DNA异常。

VMMR0_INT_DECL(int) CPUMR0Trap07Handler(PVMCC pVM, PVMCPUCC pVCpu)
{
  	//如果Guest的FPU state已经loaded过了,说明不是lazy FPU导致的异常
    //返回给Guest处理
    if (CPUMIsGuestFPUStateActive(pVCpu))
    {
        return VINF_EM_RAW_GUEST_TRAP;
    }
    //根据CR0的设置,决定是交给Guest处理还是LoadGuestFPU
    switch (pVCpu->cpum.s.Guest.cr0 & (X86_CR0_MP | X86_CR0_EM | X86_CR0_TS))
    {
        case X86_CR0_MP | X86_CR0_TS:
        case X86_CR0_MP | X86_CR0_TS | X86_CR0_EM:
            return VINF_EM_RAW_GUEST_TRAP;
        default:
            break;
    }
    return CPUMR0LoadGuestFPU(pVM, pVCpu);
}

CPUMR0LoadGuestFPU

保存Host FPU/XMM, load guest FPU/XMM

VMMR0_INT_DECL(int) CPUMR0LoadGuestFPU(PVM pVM, PVMCPU pVCpu)
{
    if (!pVM->cpum.s.HostFeatures.fLeakyFxSR)
    {
     		//for 部分AMD CPU enable了FFXSR
        rc = cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
    }
    else
    {
       //如果Host开启了MSR_K6_EFER_FFXSR(fast FXSAVE/FXSTOR),需要先关闭MSR_K6_EFER_FFXSR,然后再调用cpumR0SaveGuestRestoreHostFPUState(因为cpumR0SaveGuestRestoreHostFPUState里需要调用FXSAVE/FXSTOR指令,如果开启了FFXSR,则无法保存XMM state)
        uint64_t uHostEfer = ASMRdMsr(MSR_K6_EFER);
        if (!(uHostEfer & MSR_K6_EFER_FFXSR))
            rc = cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
        else
        {
            RTCCUINTREG const uSavedFlags = ASMIntDisableFlags();
            pVCpu->cpum.s.fUseFlags |= CPUM_USED_MANUAL_XMM_RESTORE;
            ASMWrMsr(MSR_K6_EFER, uHostEfer & ~MSR_K6_EFER_FFXSR);
            rc = cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
            ASMWrMsr(MSR_K6_EFER, uHostEfer | MSR_K6_EFER_FFXSR);
            ASMSetFlags(uSavedFlags);
        }
    }
}
cpumR0SaveHostRestoreGuestFPUState
这个函数是一个汇编函数,位于CPUMInternal.mac里
先调用XSAVE/FSSAVE指令把当前host的FPU/AVX/SSE寄存器保存到CPUMCPU.Host.pXStateR0
再从CPUMCPU.Guest.pXStateR0里执行xrstor/fxrstor指令加载FPU/AVX/SSE寄存器

CPUMR0FpuStateMaybeSaveGuestAndRestoreHost

保存Guest FPU,load host FPU

VMMR0_INT_DECL(bool) CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(PVMCPU pVCpu)
{
  	//如果Guest和HostCPU都支持FPU
  	if (pVCpu->cpum.s.fUseFlags & (CPUM_USED_FPU_GUEST | CPUM_USED_FPU_HOST))
    {
        fSavedGuest = RT_BOOL(pVCpu->cpum.s.fUseFlags & CPUM_USED_FPU_GUEST);
        //如果XMM state已经被手动restore的了(AMD only),调用cpumR0SaveGuestRestoreHostFPUState
        if (!(pVCpu->cpum.s.fUseFlags & CPUM_USED_MANUAL_XMM_RESTORE))
            cpumR0SaveGuestRestoreHostFPUState(&pVCpu->cpum.s);
        else
        {
          	//如果Host开启了MSR_K6_EFER_FFXSR(fast FXSAVE/FXSTOR),需要先关闭
            uint64_t uHostEfer = ASMRdMsr(MSR_K6_EFER);
            if (uHostEfer & MSR_K6_EFER_FFXSR)
            {
                RTCCUINTREG const uSavedFlags = ASMIntDisableFlags();
                ASMWrMsr(MSR_K6_EFER, uHostEfer & ~MSR_K6_EFER_FFXSR);
                cpumR0SaveGuestRestoreHostFPUState(&pVCpu->cpum.s);
                ASMWrMsr(MSR_K6_EFER, uHostEfer | MSR_K6_EFER_FFXSR);
                ASMSetFlags(uSavedFlags);
            }
            else
                cpumR0SaveGuestRestoreHostFPUState(&pVCpu->cpum.s);
            pVCpu->cpum.s.fUseFlags &= ~CPUM_USED_MANUAL_XMM_RESTORE;
        }
    }
}
 
cpumR0SaveGuestRestoreHostFPUState
这个函数是一个汇编函数,位于CPUMInternal.mac里
先调用XSAVE/FSSAVE指令把当前Guest的FPU/AVX/SSE寄存器保存到CPUMCPU.Guest.pXStateR0
再从CPUMCPU.Host.pXStateR0里执行xrstor/fxrstor指令加载FPU/AVX/SSE寄存器

CPUMR0FpuStateMaybeSaveGuestAndRestoreHost

上面函数的相反函数

VMMR0_INT_DECL(bool) CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(PVMCPUCC pVCpu)
{
	if (pVCpu->cpum.s.fUseFlags & (CPUM_USED_FPU_GUEST | CPUM_USED_FPU_HOST))
  {
    	if (!(pVCpu->cpum.s.fUseFlags & CPUM_USED_MANUAL_XMM_RESTORE))
            cpumR0SaveGuestRestoreHostFPUState(&pVCpu->cpum.s);
       else
       {
            //如果Host开启了MSR_K6_EFER_FFXSR(fast FXSAVE/FXSTOR),需要先关闭
            uint64_t uHostEfer = ASMRdMsr(MSR_K6_EFER);
            if (uHostEfer & MSR_K6_EFER_FFXSR)
            {
                RTCCUINTREG const uSavedFlags = ASMIntDisableFlags();
                ASMWrMsr(MSR_K6_EFER, uHostEfer & ~MSR_K6_EFER_FFXSR);
                cpumR0SaveGuestRestoreHostFPUState(&pVCpu->cpum.s);
                ASMWrMsr(MSR_K6_EFER, uHostEfer | MSR_K6_EFER_FFXSR);
                ASMSetFlags(uSavedFlags);
            }
            else
                cpumR0SaveGuestRestoreHostFPUState(&pVCpu->cpum.s);
            pVCpu->cpum.s.fUseFlags &= ~CPUM_USED_MANUAL_XMM_RESTORE;
        }
  }
}

CPUMR0DebugStateMaybeSaveGuestAndRestoreHost

后面是几个调试寄存器的保存和恢复

VMMR0_INT_DECL(bool) CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(PVMCPU pVCpu, bool fDr6)
{
  //Guest DRx寄存器保存到pVCpu->cpum.s.Guest里
  if (pVCpu->cpum.s.fUseFlags & CPUM_USED_DEBUG_REGS_GUEST)
  {
    pVCpu->cpum.s.Guest.dr[0] = ASMGetDR0();
    pVCpu->cpum.s.Guest.dr[1] = ASMGetDR1();
    pVCpu->cpum.s.Guest.dr[2] = ASMGetDR2();
    pVCpu->cpum.s.Guest.dr[3] = ASMGetDR3();
    if (fDr6)
      pVCpu->cpum.s.Guest.dr[6] = ASMGetDR6();
  }
  //从pVCpu->cpum.s.Host里恢复DRx寄存器
  if (pVCpu->cpum.s.fUseFlags & CPUM_USED_DEBUG_REGS_HOST)
  {
    	//重置DR7
      uint64_t uCurDR7 = ASMGetDR7();
      if (uCurDR7 != X86_DR7_INIT_VAL)
        ASMSetDR7(X86_DR7_INIT_VAL);

      ASMSetDR0(pVCpu->cpum.s.Host.dr0);
      ASMSetDR1(pVCpu->cpum.s.Host.dr1);
      ASMSetDR2(pVCpu->cpum.s.Host.dr2);
      ASMSetDR3(pVCpu->cpum.s.Host.dr3);
      ASMSetDR6(pVCpu->cpum.s.Host.dr6);
      ASMSetDR7(pVCpu->cpum.s.Host.dr7);

      ASMAtomicAndU32(&pVCpu->cpum.s.fUseFlags, ~CPUM_USED_DEBUG_REGS_HOST);
   }
}

CPUMR0DebugStateMaybeSaveGuest

VMMR0_INT_DECL(bool) CPUMR0DebugStateMaybeSaveGuest(PVMCPUCC pVCpu, bool fDr6)
{
  //Guest DRx寄存器保存到pVCpu->cpum.s.Guest里
	if (pVCpu->cpum.s.fUseFlags & CPUM_USED_DEBUG_REGS_GUEST)
    {
        pVCpu->cpum.s.Guest.dr[0] = ASMGetDR0();
        pVCpu->cpum.s.Guest.dr[1] = ASMGetDR1();
        pVCpu->cpum.s.Guest.dr[2] = ASMGetDR2();
        pVCpu->cpum.s.Guest.dr[3] = ASMGetDR3();
        if (fDr6)
            pVCpu->cpum.s.Guest.dr[6] = ASMGetDR6();
        return true;
    }
}

CPUMR0LoadGuestDebugState

VMMR0_INT_DECL(void) CPUMR0LoadGuestDebugState(PVMCPUCC pVCpu, bool fDr6)
{
	//DRx寄存器保存到pVCpu->cpum.s.Host里
	cpumR0SaveHostDebugState(pVCpu);
	//从pVCpu->cpum.s.Guest里恢复DRx寄存器 (DR7 不恢复)
	ASMSetDR0(pVCpu->cpum.s.Guest.dr[0]);
  ASMSetDR1(pVCpu->cpum.s.Guest.dr[1]);
  ASMSetDR2(pVCpu->cpum.s.Guest.dr[2]);
  ASMSetDR3(pVCpu->cpum.s.Guest.dr[3]);
  if (fDr6)
  	ASMSetDR6(pVCpu->cpum.s.Guest.dr[6]);
}
发布了26 篇原创文章 · 获赞 10 · 访问量 1259

猜你喜欢

转载自blog.csdn.net/qq_29684547/article/details/104095457
cpu