VirtualBox

Changeset 72300 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
May 23, 2018 3:13:06 PM (7 years ago)
Author:
vboxsync
Message:

NEM,STAM: Partition memory statistics for NEM. bugref:9044

  • STAM: Redid the way we handle statistics requiring fetching data from ring-0 (or elsewhere) by introducing a refresh group concept. We'll refresh the statistics for a group if needed and only once per enumeration/query. There's a new registration API for these.
  • NEM: Added memory balance statistics for the partition. Some failed fumbling thru VID.DLL/SYS, before realizing that hypercall is the only way to get at them.
  • NEM: Added a hypervisor input/output page buffer for non-EMT threads so we can get statistics. Put the related data and code into separate structure to save duplication.
Location:
trunk/src/VBox/VMM
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp

    r72291 r72300  
    9090 */
    9191#include "../VMMAll/NEMAllNativeTemplate-win.cpp.h"
     92
     93/**
     94 * Worker for NEMR0InitVM that allocates a hypercall page.
     95 *
     96 * @returns VBox status code.
     97 * @param   pHypercallData  The hypercall data page to initialize.
     98 */
     99static int nemR0InitHypercallData(PNEMR0HYPERCALLDATA pHypercallData)
     100{
     101    int rc = RTR0MemObjAllocPage(&pHypercallData->hMemObj, PAGE_SIZE, false /*fExecutable*/);
     102    if (RT_SUCCESS(rc))
     103    {
     104        pHypercallData->HCPhysPage = RTR0MemObjGetPagePhysAddr(pHypercallData->hMemObj, 0 /*iPage*/);
     105        AssertStmt(pHypercallData->HCPhysPage != NIL_RTHCPHYS, rc = VERR_INTERNAL_ERROR_3);
     106        pHypercallData->pbPage     = (uint8_t *)RTR0MemObjAddress(pHypercallData->hMemObj);
     107        AssertStmt(pHypercallData->pbPage, rc = VERR_INTERNAL_ERROR_3);
     108        if (RT_SUCCESS(rc))
     109            return VINF_SUCCESS;
     110
     111        /* bail out */
     112        RTR0MemObjFree(pHypercallData->hMemObj, true /*fFreeMappings*/);
     113    }
     114    pHypercallData->hMemObj     = NIL_RTR0MEMOBJ;
     115    pHypercallData->HCPhysPage  = NIL_RTHCPHYS;
     116    pHypercallData->pbPage      = NULL;
     117    return rc;
     118}
     119
     120/**
     121 * Worker for NEMR0CleanupVM and NEMR0InitVM that cleans up a hypercall page.
     122 *
     123 * @param   pHypercallData  The hypercall data page to uninitialize.
     124 */
     125static void nemR0DeleteHypercallData(PNEMR0HYPERCALLDATA pHypercallData)
     126{
     127    /* Check pbPage here since it's NULL, whereas the hMemObj can be either
     128       NIL_RTR0MEMOBJ or 0 (they aren't necessarily the same). */
     129    if (pHypercallData->pbPage != NULL)
     130    {
     131        RTR0MemObjFree(pHypercallData->hMemObj, true /*fFreeMappings*/);
     132        pHypercallData->pbPage = NULL;
     133    }
     134    pHypercallData->hMemObj    = NIL_RTR0MEMOBJ;
     135    pHypercallData->HCPhysPage = NIL_RTHCPHYS;
     136}
    92137
    93138
     
    127172        {
    128173            /*
    129              * Allocate a page for each VCPU to place hypercall data on.
     174             * Allocate a page for non-EMT threads to use for hypercalls (update
     175             * statistics and such) and a critical section protecting it.
    130176             */
    131             for (VMCPUID i = 0; i < pGVM->cCpus; i++)
     177            rc = RTCritSectInit(&pGVM->nem.s.HypercallDataCritSect);
     178            if (RT_SUCCESS(rc))
    132179            {
    133                 PGVMCPU pGVCpu = &pGVM->aCpus[i];
    134                 rc = RTR0MemObjAllocPage(&pGVCpu->nem.s.hHypercallDataMemObj, PAGE_SIZE, false /*fExecutable*/);
     180                rc = nemR0InitHypercallData(&pGVM->nem.s.HypercallData);
    135181                if (RT_SUCCESS(rc))
    136182                {
    137                     pGVCpu->nem.s.HCPhysHypercallData = RTR0MemObjGetPagePhysAddr(pGVCpu->nem.s.hHypercallDataMemObj, 0 /*iPage*/);
    138                     pGVCpu->nem.s.pbHypercallData     = (uint8_t *)RTR0MemObjAddress(pGVCpu->nem.s.hHypercallDataMemObj);
    139                     AssertStmt(pGVCpu->nem.s.HCPhysHypercallData != NIL_RTHCPHYS, rc = VERR_INTERNAL_ERROR_3);
    140                     AssertStmt(pGVCpu->nem.s.pbHypercallData, rc = VERR_INTERNAL_ERROR_3);
     183                    /*
     184                     * Allocate a page for each VCPU to place hypercall data on.
     185                     */
     186                    for (VMCPUID i = 0; i < pGVM->cCpus; i++)
     187                    {
     188                        rc = nemR0InitHypercallData(&pGVM->aCpus[i].nem.s.HypercallData);
     189                        if (RT_FAILURE(rc))
     190                        {
     191                            while (i-- > 0)
     192                                nemR0DeleteHypercallData(&pGVM->aCpus[i].nem.s.HypercallData);
     193                            break;
     194                        }
     195                    }
     196                    if (RT_SUCCESS(rc))
     197                    {
     198                        /*
     199                         * So far, so good.
     200                         */
     201                        return rc;
     202                    }
     203
     204                    /*
     205                     * Bail out.
     206                     */
     207                    nemR0DeleteHypercallData(&pGVM->nem.s.HypercallData);
    141208                }
    142                 else
    143                     pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ;
    144                 if (RT_FAILURE(rc))
    145                 {
    146                     /* bail. */
    147                     do
    148                     {
    149                         RTR0MemObjFree(pGVCpu->nem.s.hHypercallDataMemObj, true /*fFreeMappings*/);
    150                         pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ;
    151                         pGVCpu->nem.s.HCPhysHypercallData  = NIL_RTHCPHYS;
    152                         pGVCpu->nem.s.pbHypercallData      = NULL;
    153                     } while (i-- > 0);
    154                     return rc;
    155                 }
     209                RTCritSectDelete(&pGVM->nem.s.HypercallDataCritSect);
    156210            }
    157             /*
    158              * So far, so good.
    159              */
    160             return rc;
    161         }
    162 
    163         rc = VERR_NEM_MISSING_KERNEL_API;
    164     }
    165 
    166     RT_NOREF(pGVM, pVM);
     211        }
     212        else
     213            rc = VERR_NEM_MISSING_KERNEL_API;
     214    }
     215
     216    RT_NOREF(pVM);
    167217    return rc;
    168218}
     
    309359    VMCPUID i = pGVM->cCpus;
    310360    while (i-- > 0)
    311     {
    312         PGVMCPU pGVCpu = &pGVM->aCpus[i];
    313         if (pGVCpu->nem.s.pbHypercallData)
    314         {
    315             pGVCpu->nem.s.pbHypercallData = NULL;
    316             int rc = RTR0MemObjFree(pGVCpu->nem.s.hHypercallDataMemObj, true /*fFreeMappings*/);
    317             AssertRC(rc);
    318         }
    319         pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ;
    320         pGVCpu->nem.s.HCPhysHypercallData  = NIL_RTHCPHYS;
    321     }
     361        nemR0DeleteHypercallData(&pGVM->aCpus[i].nem.s.HypercallData);
     362
     363    /* The non-EMT one too. */
     364    if (RTCritSectIsInitialized(&pGVM->nem.s.HypercallDataCritSect))
     365        RTCritSectDelete(&pGVM->nem.s.HypercallDataCritSect);
     366    nemR0DeleteHypercallData(&pGVM->nem.s.HypercallData);
    322367}
    323368
     
    372417     * Ring-3 is not allowed to fill in the host physical addresses of the call.
    373418     */
    374     HV_INPUT_MAP_GPA_PAGES *pMapPages = (HV_INPUT_MAP_GPA_PAGES *)pGVCpu->nem.s.pbHypercallData;
     419    HV_INPUT_MAP_GPA_PAGES *pMapPages = (HV_INPUT_MAP_GPA_PAGES *)pGVCpu->nem.s.HypercallData.pbPage;
    375420    AssertPtrReturn(pMapPages, VERR_INTERNAL_ERROR_3);
    376421    pMapPages->TargetPartitionId    = pGVM->nem.s.idHvPartition;
     
    387432
    388433    uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallMapGpaPages | ((uint64_t)cPages << 32),
    389                                                pGVCpu->nem.s.HCPhysHypercallData, 0);
     434                                               pGVCpu->nem.s.HypercallData.HCPhysPage, 0);
    390435    Log6(("NEMR0MapPages: %RGp/%RGp L %u prot %#x -> %#RX64\n",
    391436          GCPhysDst, GCPhysSrc - cPages * X86_PAGE_SIZE, cPages, fFlags, uResult));
     
    454499     * Compose and make the hypercall.
    455500     */
    456     HV_INPUT_UNMAP_GPA_PAGES *pUnmapPages = (HV_INPUT_UNMAP_GPA_PAGES *)pGVCpu->nem.s.pbHypercallData;
     501    HV_INPUT_UNMAP_GPA_PAGES *pUnmapPages = (HV_INPUT_UNMAP_GPA_PAGES *)pGVCpu->nem.s.HypercallData.pbPage;
    457502    AssertPtrReturn(pUnmapPages, VERR_INTERNAL_ERROR_3);
    458503    pUnmapPages->TargetPartitionId    = pGVM->nem.s.idHvPartition;
     
    461506
    462507    uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallUnmapGpaPages | ((uint64_t)cPages << 32),
    463                                                pGVCpu->nem.s.HCPhysHypercallData, 0);
     508                                               pGVCpu->nem.s.HypercallData.HCPhysPage, 0);
    464509    Log6(("NEMR0UnmapPages: %RGp L %u -> %#RX64\n", GCPhys, cPages, uResult));
    465510    if (uResult == ((uint64_t)cPages << 32))
     
    467512#if 1       /* Do we need to do this? Hopefully not... */
    468513        uint64_t volatile uR = g_pfnHvlInvokeHypercall(HvCallUncommitGpaPages | ((uint64_t)cPages << 32),
    469                                                        pGVCpu->nem.s.HCPhysHypercallData, 0);
     514                                                       pGVCpu->nem.s.HypercallData.HCPhysPage, 0);
    470515        AssertMsg(uR == ((uint64_t)cPages << 32), ("uR=%#RX64\n", uR)); NOREF(uR);
    471516#endif
     
    527572{
    528573    PVMCPU                     pVCpu  = &pGVM->pVM->aCpus[pGVCpu->idCpu];
    529     HV_INPUT_SET_VP_REGISTERS *pInput = (HV_INPUT_SET_VP_REGISTERS *)pGVCpu->nem.s.pbHypercallData;
     574    HV_INPUT_SET_VP_REGISTERS *pInput = (HV_INPUT_SET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage;
    530575    AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
    531576
     
    10961141     * Set the registers.
    10971142     */
    1098     Assert((uintptr_t)&pInput->Elements[iReg] - (uintptr_t)pGVCpu->nem.s.pbHypercallData < PAGE_SIZE); /* max is 127 */
     1143    Assert((uintptr_t)&pInput->Elements[iReg] - (uintptr_t)pGVCpu->nem.s.HypercallData.pbPage < PAGE_SIZE); /* max is 127 */
    10991144
    11001145    /*
     
    11021147     */
    11031148    uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallSetVpRegisters, iReg),
    1104                                                pGVCpu->nem.s.HCPhysHypercallData, 0 /*GCPhysOutput*/);
     1149                                               pGVCpu->nem.s.HypercallData.HCPhysPage, 0 /*GCPhysOutput*/);
    11051150    AssertLogRelMsgReturn(uResult == HV_MAKE_CALL_REP_RET(iReg),
    11061151                          ("uResult=%RX64 iRegs=%#x\n", uResult, iReg),
     
    11561201NEM_TMPL_STATIC int nemR0WinImportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat)
    11571202{
    1158     HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s.pbHypercallData;
     1203    HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage;
    11591204    AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
    11601205
     
    13391384
    13401385    HV_REGISTER_VALUE *paValues = (HV_REGISTER_VALUE *)((uint8_t *)pInput + cbInput);
    1341     Assert((uintptr_t)&paValues[cRegs] - (uintptr_t)pGVCpu->nem.s.pbHypercallData < PAGE_SIZE); /* (max is around 168 registers) */
     1386    Assert((uintptr_t)&paValues[cRegs] - (uintptr_t)pGVCpu->nem.s.HypercallData.pbPage < PAGE_SIZE); /* (max is around 168 registers) */
    13421387    RT_BZERO(paValues, cRegs * sizeof(paValues[0]));
    13431388
     
    13461391     */
    13471392    uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallGetVpRegisters, cRegs),
    1348                                                pGVCpu->nem.s.HCPhysHypercallData,
    1349                                                pGVCpu->nem.s.HCPhysHypercallData + cbInput);
     1393                                               pGVCpu->nem.s.HypercallData.HCPhysPage,
     1394                                               pGVCpu->nem.s.HypercallData.HCPhysPage + cbInput);
    13501395    AssertLogRelMsgReturn(uResult == HV_MAKE_CALL_REP_RET(cRegs),
    13511396                          ("uResult=%RX64 cRegs=%#x\n", uResult, cRegs),
     
    18931938}
    18941939
     1940
     1941/**
     1942 * Updates statistics in the VM structure.
     1943 *
     1944 * @returns VBox status code.
     1945 * @param   pGVM        The ring-0 VM handle.
     1946 * @param   pVM         The cross context VM handle.
     1947 * @param   idCpu       The calling EMT, or NIL.  Necessary for getting the hypercall
     1948 *                      page and arguments.
     1949 */
     1950VMMR0_INT_DECL(int)  NEMR0UpdateStatistics(PGVM pGVM, PVM pVM, VMCPUID idCpu)
     1951{
     1952    /*
     1953     * Validate the call.
     1954     */
     1955    int rc;
     1956    if (idCpu == NIL_VMCPUID)
     1957        rc = GVMMR0ValidateGVMandVM(pGVM, pVM);
     1958    else
     1959        rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, idCpu);
     1960    if (RT_SUCCESS(rc))
     1961    {
     1962        AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
     1963
     1964        PNEMR0HYPERCALLDATA pHypercallData = idCpu != NIL_VMCPUID
     1965                                           ? &pGVM->aCpus[idCpu].nem.s.HypercallData
     1966                                           : &pGVM->nem.s.HypercallData;
     1967        if (   RT_VALID_PTR(pHypercallData->pbPage)
     1968            && pHypercallData->HCPhysPage != NIL_RTHCPHYS)
     1969        {
     1970            if (idCpu == NIL_VMCPUID)
     1971                rc = RTCritSectEnter(&pGVM->nem.s.HypercallDataCritSect);
     1972            if (RT_SUCCESS(rc))
     1973            {
     1974                /*
     1975                 * Query the memory statistics for the partition.
     1976                 */
     1977                HV_INPUT_GET_MEMORY_BALANCE  *pInput = (HV_INPUT_GET_MEMORY_BALANCE *)pHypercallData->pbPage;
     1978                pInput->TargetPartitionId                               = pGVM->nem.s.idHvPartition;
     1979                pInput->ProximityDomainInfo.Flags.ProximityPreferred    = 0;
     1980                pInput->ProximityDomainInfo.Flags.ProxyimityInfoValid   = 0;
     1981                pInput->ProximityDomainInfo.Flags.Reserved              = 0;
     1982                pInput->ProximityDomainInfo.Id                          = 0;
     1983
     1984                HV_OUTPUT_GET_MEMORY_BALANCE *pOutput = (HV_OUTPUT_GET_MEMORY_BALANCE *)(pInput + 1);
     1985                RT_ZERO(*pOutput);
     1986
     1987                uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallGetMemoryBalance,
     1988                                                           pHypercallData->HCPhysPage,
     1989                                                           pHypercallData->HCPhysPage + sizeof(*pInput));
     1990                if (uResult == HV_STATUS_SUCCESS)
     1991                {
     1992                    pVM->nem.s.R0Stats.cPagesAvailable = pOutput->PagesAvailable;
     1993                    pVM->nem.s.R0Stats.cPagesInUse     = pOutput->PagesInUse;
     1994                    rc = VINF_SUCCESS;
     1995                }
     1996                else
     1997                {
     1998                    LogRel(("HvCallGetMemoryBalance -> %#RX64 (%#RX64 %#RX64)!!\n",
     1999                            uResult, pOutput->PagesAvailable, pOutput->PagesInUse));
     2000                    rc = VINF_NEM_IPE_0;
     2001                }
     2002
     2003                if (idCpu == NIL_VMCPUID)
     2004                    RTCritSectLeave(&pGVM->nem.s.HypercallDataCritSect);
     2005            }
     2006        }
     2007        else
     2008            rc = VERR_WRONG_ORDER;
     2009    }
     2010    return rc;
     2011}
     2012
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r71223 r72300  
    20622062            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
    20632063            break;
     2064
     2065        case VMMR0_DO_NEM_UPDATE_STATISTICS:
     2066            if (u64Arg || pReqHdr)
     2067                return VERR_INVALID_PARAMETER;
     2068            rc = NEMR0UpdateStatistics(pGVM, pVM, idCpu);
     2069            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
     2070            break;
    20642071# endif
    20652072#endif
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r72208 r72300  
    21082108                        /** @todo this really isn't nice, should properly handle this */
    21092109                        rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
     2110Log(("EM: TRPMR3InjectEvent -> %d\n", rc2));
    21102111                        if (pVM->em.s.fIemExecutesAll && (   rc2 == VINF_EM_RESCHEDULE_REM
    21112112                                                          || rc2 == VINF_EM_RESCHEDULE_HM
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r72290 r72300  
    725725            uint32_t iMin, iMax; } s_aUnknowns[] =
    726726        {
    727             { 0x0003, 0x000f },
     727            { 0x0004, 0x000f },
    728728            { 0x1003, 0x100f },
    729729            { 0x2000, 0x200f },
     
    10081008
    10091009/**
    1010  * Wrapper for different WHvSetPartitionProperty signatures.
    1011  */
    1012 DECLINLINE(HRESULT) WHvSetPartitionPropertyWrapper(WHV_PARTITION_HANDLE hPartition, WHV_PARTITION_PROPERTY_CODE enmProp,
    1013                                                    WHV_PARTITION_PROPERTY *pInput, uint32_t cbInput)
    1014 {
    1015     return g_pfnWHvSetPartitionProperty(hPartition, enmProp, pInput, cbInput - RT_UOFFSETOF(WHV_PARTITION_PROPERTY, ExtendedVmExits));
    1016 }
    1017 
    1018 
    1019 /**
    10201010 * Creates and sets up a Hyper-V (exo) partition.
    10211011 *
     
    10541044    RT_ZERO(Property);
    10551045    Property.ProcessorCount = pVM->cCpus;
    1056     hrc = WHvSetPartitionPropertyWrapper(hPartition, WHvPartitionPropertyCodeProcessorCount, &Property, sizeof(Property));
     1046    hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeProcessorCount, &Property, sizeof(Property));
    10571047    if (SUCCEEDED(hrc))
    10581048    {
     
    10631053        Property.ExtendedVmExits.ExceptionExit = pVM->nem.s.fExtendedXcptExit;
    10641054#endif
    1065         hrc = WHvSetPartitionPropertyWrapper(hPartition, WHvPartitionPropertyCodeExtendedVmExits, &Property, sizeof(Property));
     1055        hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeExtendedVmExits, &Property, sizeof(Property));
    10661056        if (SUCCEEDED(hrc))
    10671057        {
     
    11631153                            STAMR3RegisterF(pVM, &pNemCpu->StatBreakOnStatus,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of status code breaks",           "/NEM/CPU%u/BreakOnStatus", iCpu);
    11641154                        }
     1155
     1156                        PUVM pUVM = pVM->pUVM;
     1157                        STAMR3RegisterRefresh(pUVM, &pVM->nem.s.R0Stats.cPagesAvailable, STAMTYPE_U64, STAMVISIBILITY_ALWAYS,
     1158                                              STAMUNIT_PAGES, STAM_REFRESH_GRP_NEM, "Free pages available to the hypervisor",
     1159                                              "/NEM/R0Stats/cPagesAvailable");
     1160                        STAMR3RegisterRefresh(pUVM, &pVM->nem.s.R0Stats.cPagesInUse,     STAMTYPE_U64, STAMVISIBILITY_ALWAYS,
     1161                                              STAMUNIT_PAGES, STAM_REFRESH_GRP_NEM, "Pages in use by hypervisor",
     1162                                              "/NEM/R0Stats/cPagesInUse");
    11651163                    }
    11661164                }
     
    12121210    Property.ProcessorVendor = pVM->nem.s.enmCpuVendor == CPUMCPUVENDOR_AMD ? WHvProcessorVendorAmd
    12131211                             : WHvProcessorVendorIntel;
    1214     hrc = WHvSetPartitionPropertyWrapper(hPartition, WHvPartitionPropertyCodeProcessorVendor, &Property, sizeof(Property));
     1212    hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeProcessorVendor, &Property, sizeof(Property));
    12151213    if (FAILED(hrc))
    12161214        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     
    12221220    RT_ZERO(Property);
    12231221    Property.ProcessorClFlushSize = pVM->nem.s.cCacheLineFlushShift;
    1224     hrc = WHvSetPartitionPropertyWrapper(hPartition, WHvPartitionPropertyCodeProcessorClFlushSize, &Property, sizeof(Property));
     1222    hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeProcessorClFlushSize, &Property, sizeof(Property));
    12251223    if (FAILED(hrc))
    12261224        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     
    12361234    RT_ZERO(Property);
    12371235    Property.ProcessorFeatures.AsUINT64 = pVM->nem.s.uCpuFeatures.u64;
    1238     hrc = WHvSetPartitionPropertyWrapper(hPartition, WHvPartitionPropertyCodeProcessorFeatures, &Property, sizeof(Property));
     1236    hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeProcessorFeatures, &Property, sizeof(Property));
    12391237    if (FAILED(hrc))
    12401238        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     
    13311329    {
    13321330        LogRel(("NEM: Successfully set up partition (device handle %p, partition ID %#llx)\n", hPartitionDevice, idHvPartition));
     1331
     1332#if 1
     1333        VMMR3CallR0Emt(pVM, &pVM->aCpus[0], VMMR0_DO_NEM_UPDATE_STATISTICS, 0, NULL);
     1334        LogRel(("NEM: Memory balance: %#RX64 out of %#RX64 pages in use\n",
     1335                pVM->nem.s.R0Stats.cPagesInUse, pVM->nem.s.R0Stats.cPagesAvailable));
     1336#endif
     1337
     1338        /*
     1339         * Register statistics on shared pages.
     1340         */
     1341        /** @todo HvCallMapStatsPage */
    13331342        return VINF_SUCCESS;
    13341343    }
  • trunk/src/VBox/VMM/VMMR3/STAM.cpp

    r69111 r72300  
    144144static void                 stamR3LookupDestroyTree(PSTAMLOOKUP pRoot);
    145145#endif
    146 static int                  stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
    147                                             STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
     146static int                  stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset,
     147                                            PFNSTAMR3CALLBACKPRINT pfnPrint, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
     148                                            const char *pszName, STAMUNIT enmUnit, const char *pszDesc, uint8_t iRefreshGrp);
    148149static int                  stamR3ResetOne(PSTAMDESC pDesc, void *pvArg);
    149150static DECLCALLBACK(void)   stamR3EnumLogPrintf(PSTAMR3PRINTONEARGS pvArg, const char *pszFormat, ...);
     
    158159static int                  stamR3EnumU(PUVM pUVM, const char *pszPat, bool fUpdateRing0, int (pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg);
    159160static void                 stamR3Ring0StatsRegisterU(PUVM pUVM);
    160 static void                 stamR3Ring0StatsUpdateU(PUVM pUVM, const char *pszPat);
    161 static void                 stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions);
    162161
    163162#ifdef VBOX_WITH_DEBUGGER
     
    389388 * @param   pszDesc     Sample description.
    390389 */
    391 VMMR3DECL(int)  STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
     390VMMR3DECL(int)  STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName,
     391                                STAMUNIT enmUnit, const char *pszDesc)
    392392{
    393393    AssertReturn(enmType != STAMTYPE_CALLBACK, VERR_INVALID_PARAMETER);
    394394    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
    395     return stamR3RegisterU(pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc);
     395    return stamR3RegisterU(pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc, STAM_REFRESH_GRP_NONE);
    396396}
    397397
     
    419419 * @param   pszDesc     Sample description.
    420420 */
    421 VMMR3DECL(int)  STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
     421VMMR3DECL(int)  STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName,
     422                               STAMUNIT enmUnit, const char *pszDesc)
    422423{
    423424    AssertReturn(enmType != STAMTYPE_CALLBACK, VERR_INVALID_PARAMETER);
    424     return stamR3RegisterU(pVM->pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc);
     425    return stamR3RegisterU(pVM->pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc,
     426                           STAM_REFRESH_GRP_NONE);
    425427}
    426428
     
    576578        return VERR_NO_MEMORY;
    577579
    578     int rc = stamR3RegisterU(pVM->pUVM, pvSample, pfnReset, pfnPrint, STAMTYPE_CALLBACK, enmVisibility, pszFormattedName, enmUnit, pszDesc);
     580    int rc = stamR3RegisterU(pVM->pUVM, pvSample, pfnReset, pfnPrint, STAMTYPE_CALLBACK, enmVisibility, pszFormattedName,
     581                             enmUnit, pszDesc, STAM_REFRESH_GRP_NONE);
    579582    RTStrFree(pszFormattedName);
    580583    return rc;
     584}
     585
     586
     587/**
     588 * Same as STAMR3RegisterFU, except there is an extra refresh group parameter.
     589 *
     590 * @returns VBox status code.
     591 * @param   pUVM        Pointer to the user mode VM structure.
     592 * @param   pvSample    Pointer to the sample.
     593 * @param   enmType     Sample type. This indicates what pvSample is pointing at.
     594 * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
     595 * @param   enmUnit     Sample unit.
     596 * @param   iRefreshGrp The refresh group, STAM_REFRESH_GRP_XXX.
     597 * @param   pszDesc     Sample description.
     598 * @param   pszName     The sample name format string.
     599 * @param   ...         Arguments to the format string.
     600 */
     601VMMR3DECL(int) STAMR3RegisterRefresh(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
     602                                     uint8_t iRefreshGrp, const char *pszDesc, const char *pszName, ...)
     603{
     604    va_list args;
     605    va_start(args, pszName);
     606    int rc = STAMR3RegisterRefreshV(pUVM, pvSample, enmType, enmVisibility, enmUnit, iRefreshGrp, pszDesc, pszName, args);
     607    va_end(args);
     608    return rc;
     609}
     610
     611
     612/**
     613 * Same as STAMR3RegisterVU, except there is an extra refresh group parameter.
     614 *
     615 * @returns VBox status code.
     616 * @param   pUVM        The user mode VM structure.
     617 * @param   pvSample    Pointer to the sample.
     618 * @param   enmType     Sample type. This indicates what pvSample is pointing at.
     619 * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
     620 * @param   enmUnit     Sample unit.
     621 * @param   iRefreshGrp The refresh group, STAM_REFRESH_GRP_XXX.
     622 * @param   pszDesc     Sample description.
     623 * @param   pszName     The sample name format string.
     624 * @param   va          Arguments to the format string.
     625 */
     626VMMR3DECL(int) STAMR3RegisterRefreshV(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
     627                                      uint8_t iRefreshGrp, const char *pszDesc, const char *pszName, va_list va)
     628{
     629    AssertReturn(enmType != STAMTYPE_CALLBACK, VERR_INVALID_PARAMETER);
     630
     631    char   szFormattedName[STAM_MAX_NAME_LEN + 8];
     632    size_t cch = RTStrPrintfV(szFormattedName, sizeof(szFormattedName), pszName, va);
     633    AssertReturn(cch <= STAM_MAX_NAME_LEN, VERR_OUT_OF_RANGE);
     634
     635    UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
     636    return stamR3RegisterU(pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc, iRefreshGrp);
    581637}
    582638
     
    12511307 * @param   enmUnit     Sample unit.
    12521308 * @param   pszDesc     Sample description.
     1309 * @param   iRefreshGrp The refresh group, STAM_REFRESH_GRP_XXX.
    12531310 * @remark  There is currently no device or driver variant of this API. Add one if it should become necessary!
    12541311 */
    12551312static int stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
    12561313                           STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    1257                            const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
     1314                           const char *pszName, STAMUNIT enmUnit, const char *pszDesc, uint8_t iRefreshGrp)
    12581315{
    12591316    AssertReturn(pszName[0] == '/', VERR_INVALID_NAME);
     
    12631320    AssertReturn(pszName[cchName - 1] != '/', VERR_INVALID_NAME);
    12641321    AssertReturn(memchr(pszName, '\\', cchName) == NULL, VERR_INVALID_NAME);
     1322    AssertReturn(iRefreshGrp == STAM_REFRESH_GRP_NONE || iRefreshGrp < 64, VERR_INVALID_PARAMETER);
    12651323
    12661324    STAM_LOCK_WR(pUVM);
     
    14161474        }
    14171475        pNew->enmUnit       = enmUnit;
     1476        pNew->iRefreshGroup = iRefreshGrp;
    14181477        pNew->pszDesc       = NULL;
    14191478        if (pszDesc)
     
    23792438}
    23802439
     2440static void stamR3RefreshGroup(PUVM pUVM, uint8_t iRefreshGroup, uint64_t *pbmRefreshedGroups)
     2441{
     2442    *pbmRefreshedGroups |= RT_BIT_64(iRefreshGroup);
     2443
     2444    PVM pVM = pUVM->pVM;
     2445    if (pVM && pVM->pSession)
     2446    {
     2447        switch (iRefreshGroup)
     2448        {
     2449            /*
     2450             * GVMM
     2451             */
     2452            case STAM_REFRESH_GRP_GVMM:
     2453            {
     2454                GVMMQUERYSTATISTICSSREQ Req;
     2455                Req.Hdr.cbReq    = sizeof(Req);
     2456                Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     2457                Req.pSession     = pVM->pSession;
     2458                int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_GVMM_QUERY_STATISTICS, 0, &Req.Hdr);
     2459                if (RT_SUCCESS(rc))
     2460                {
     2461                    pUVM->stam.s.GVMMStats = Req.Stats;
     2462
     2463                    /*
     2464                     * Check if the number of host CPUs has changed (it will the first
     2465                     * time around and normally never again).
     2466                     */
     2467                    if (RT_UNLIKELY(pUVM->stam.s.GVMMStats.cHostCpus > pUVM->stam.s.cRegisteredHostCpus))
     2468                    {
     2469                        if (RT_UNLIKELY(pUVM->stam.s.GVMMStats.cHostCpus > pUVM->stam.s.cRegisteredHostCpus))
     2470                        {
     2471                            STAM_UNLOCK_RD(pUVM);
     2472                            STAM_LOCK_WR(pUVM);
     2473                            uint32_t cCpus = pUVM->stam.s.GVMMStats.cHostCpus;
     2474                            for (uint32_t iCpu = pUVM->stam.s.cRegisteredHostCpus; iCpu < cCpus; iCpu++)
     2475                            {
     2476                                char   szName[120];
     2477                                size_t cchBase = RTStrPrintf(szName, sizeof(szName), "/GVMM/HostCpus/%u", iCpu);
     2478                                stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].idCpu, NULL, NULL,
     2479                                                STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_NONE,
     2480                                                "Host CPU ID", STAM_REFRESH_GRP_GVMM);
     2481                                strcpy(&szName[cchBase], "/idxCpuSet");
     2482                                stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].idxCpuSet, NULL, NULL,
     2483                                                STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_NONE,
     2484                                                "CPU Set index", STAM_REFRESH_GRP_GVMM);
     2485                                strcpy(&szName[cchBase], "/DesiredHz");
     2486                                stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].uDesiredHz, NULL, NULL,
     2487                                                STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_HZ,
     2488                                                "The desired frequency", STAM_REFRESH_GRP_GVMM);
     2489                                strcpy(&szName[cchBase], "/CurTimerHz");
     2490                                stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].uTimerHz, NULL, NULL,
     2491                                                STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_HZ,
     2492                                                "The current timer frequency", STAM_REFRESH_GRP_GVMM);
     2493                                strcpy(&szName[cchBase], "/PPTChanges");
     2494                                stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].cChanges, NULL, NULL,
     2495                                                STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES,
     2496                                                "RTTimerChangeInterval calls", STAM_REFRESH_GRP_GVMM);
     2497                                strcpy(&szName[cchBase], "/PPTStarts");
     2498                                stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].cStarts, NULL, NULL,
     2499                                                STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES,
     2500                                                "RTTimerStart calls", STAM_REFRESH_GRP_GVMM);
     2501                            }
     2502                            pUVM->stam.s.cRegisteredHostCpus = cCpus;
     2503                            STAM_UNLOCK_WR(pUVM);
     2504                            STAM_LOCK_RD(pUVM);
     2505                        }
     2506                    }
     2507                }
     2508                break;
     2509            }
     2510
     2511            /*
     2512             * GMM
     2513             */
     2514            case STAM_REFRESH_GRP_GMM:
     2515            {
     2516                GMMQUERYSTATISTICSSREQ Req;
     2517                Req.Hdr.cbReq    = sizeof(Req);
     2518                Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     2519                Req.pSession     = pVM->pSession;
     2520                int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_GMM_QUERY_STATISTICS, 0, &Req.Hdr);
     2521                if (RT_SUCCESS(rc))
     2522                    pUVM->stam.s.GMMStats = Req.Stats;
     2523                break;
     2524            }
     2525
     2526            /*
     2527             * NEM.
     2528             */
     2529            case STAM_REFRESH_GRP_NEM:
     2530                SUPR3CallVMMR0(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_NEM_UPDATE_STATISTICS, NULL);
     2531                break;
     2532
     2533            default:
     2534                AssertMsgFailed(("iRefreshGroup=%d\n", iRefreshGroup));
     2535        }
     2536    }
     2537}
     2538
     2539
     2540/**
     2541 * Refreshes the statistics behind the given entry, if necessary.
     2542 *
     2543 * This helps implement fetching global ring-0 stats into ring-3 accessible
     2544 * storage.  GVMM, GMM and NEM makes use of this.
     2545 *
     2546 * @param   pUVM                The user mode VM handle.
     2547 * @param   pCur                The statistics descriptor which group to check
     2548 *                              and maybe update.
     2549 * @param   pbmRefreshedGroups  Bitmap tracking what has already been updated.
     2550 */
     2551DECLINLINE(void) stamR3Refresh(PUVM pUVM, PSTAMDESC pCur, uint64_t *pbmRefreshedGroups)
     2552{
     2553    uint8_t const iRefreshGroup = pCur->iRefreshGroup;
     2554    if (RT_LIKELY(iRefreshGroup == STAM_REFRESH_GRP_NONE))
     2555    { /* likely */ }
     2556    else if (!(*pbmRefreshedGroups & RT_BIT_64(iRefreshGroup)))
     2557        stamR3RefreshGroup(pUVM, iRefreshGroup, pbmRefreshedGroups);
     2558}
     2559
    23812560
    23822561/**
     
    24132592            if (piExpression && i > *piExpression)
    24142593            {
    2415                 check if we can skip some expressions
     2594                Check if we can skip some expressions.
     2595                Requires the expressions to be sorted.
    24162596            }*/
    24172597            return true;
     
    24902670                       int (*pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg)
    24912671{
    2492     int rc = VINF_SUCCESS;
    2493     PSTAMDESC pCur;
     2672    int         rc                = VINF_SUCCESS;
     2673    uint64_t    bmRefreshedGroups = 0;
     2674    PSTAMDESC   pCur;
    24942675
    24952676    /*
     
    24982679    if (!pszPat || !*pszPat || !strcmp(pszPat, "*"))
    24992680    {
    2500         if (fUpdateRing0)
    2501             stamR3Ring0StatsUpdateU(pUVM, "*");
    2502 
    25032681        STAM_LOCK_RD(pUVM);
    25042682        RTListForEach(&pUVM->stam.s.List, pCur, STAMDESC, ListEntry)
    25052683        {
     2684            if (fUpdateRing0)
     2685                stamR3Refresh(pUVM, pCur, &bmRefreshedGroups);
    25062686            rc = pfnCallback(pCur, pvArg);
    25072687            if (rc)
     
    25162696    else if (!strchr(pszPat, '|'))
    25172697    {
    2518         if (fUpdateRing0)
    2519             stamR3Ring0StatsUpdateU(pUVM, pszPat);
    2520 
    25212698        STAM_LOCK_RD(pUVM);
    25222699#ifdef STAM_WITH_LOOKUP_TREE
     
    25252702            pCur = stamR3LookupFindDesc(pUVM->stam.s.pRoot, pszPat);
    25262703            if (pCur)
     2704            {
     2705                if (fUpdateRing0)
     2706                    stamR3Refresh(pUVM, pCur, &bmRefreshedGroups);
    25272707                rc = pfnCallback(pCur, pvArg);
     2708            }
    25282709        }
    25292710        else
     
    25372718                    if (RTStrSimplePatternMatch(pszPat, pCur->pszName))
    25382719                    {
     2720                        if (fUpdateRing0)
     2721                            stamR3Refresh(pUVM, pCur, &bmRefreshedGroups);
    25392722                        rc = pfnCallback(pCur, pvArg);
    25402723                        if (rc)
     
    25562739            if (RTStrSimplePatternMatch(pszPat, pCur->pszName))
    25572740            {
     2741                if (fUpdateRing0)
     2742                    stamR3Refresh(pUVM, pCur, &bmRefreshedGroups);
    25582743                rc = pfnCallback(pCur, pvArg);
    25592744                if (rc)
     
    25822767         * Perform the enumeration.
    25832768         */
    2584         if (fUpdateRing0)
    2585             stamR3Ring0StatsUpdateMultiU(pUVM, papszExpressions, cExpressions);
    2586 
    25872769        STAM_LOCK_RD(pUVM);
    25882770        unsigned iExpression = 0;
     
    25912773            if (stamR3MultiMatch(papszExpressions, cExpressions, &iExpression, pCur->pszName))
    25922774            {
     2775                if (fUpdateRing0)
     2776                    stamR3Refresh(pUVM, pCur, &bmRefreshedGroups);
    25932777                rc = pfnCallback(pCur, pvArg);
    25942778                if (rc)
     
    26172801        stamR3RegisterU(pUVM, (uint8_t *)&pUVM->stam.s.GVMMStats + g_aGVMMStats[i].offVar, NULL, NULL,
    26182802                        g_aGVMMStats[i].enmType, STAMVISIBILITY_ALWAYS, g_aGVMMStats[i].pszName,
    2619                         g_aGVMMStats[i].enmUnit, g_aGVMMStats[i].pszDesc);
     2803                        g_aGVMMStats[i].enmUnit, g_aGVMMStats[i].pszDesc, STAM_REFRESH_GRP_GVMM);
    26202804    pUVM->stam.s.cRegisteredHostCpus = 0;
    26212805
     
    26242808        stamR3RegisterU(pUVM, (uint8_t *)&pUVM->stam.s.GMMStats + g_aGMMStats[i].offVar, NULL, NULL,
    26252809                        g_aGMMStats[i].enmType, STAMVISIBILITY_ALWAYS, g_aGMMStats[i].pszName,
    2626                         g_aGMMStats[i].enmUnit, g_aGMMStats[i].pszDesc);
    2627 }
    2628 
    2629 
    2630 /**
    2631  * Updates the ring-0 statistics (the copy).
    2632  *
    2633  * @param   pUVM        Pointer to the user mode VM structure.
    2634  * @param   pszPat      The pattern.
    2635  */
    2636 static void stamR3Ring0StatsUpdateU(PUVM pUVM, const char *pszPat)
    2637 {
    2638     stamR3Ring0StatsUpdateMultiU(pUVM, &pszPat, 1);
    2639 }
    2640 
    2641 
    2642 /**
    2643  * Updates the ring-0 statistics.
    2644  *
    2645  * The ring-0 statistics aren't directly addressable from ring-3 and must be
    2646  * copied when needed.
    2647  *
    2648  * @param   pUVM                Pointer to the user mode VM structure.
    2649  * @param   papszExpressions    The patterns (for knowing when to skip).
    2650  * @param   cExpressions        Number of patterns.
    2651  */
    2652 static void stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions)
    2653 {
    2654     PVM pVM = pUVM->pVM;
    2655     if (!pVM || !pVM->pSession)
    2656         return;
    2657 
    2658     /*
    2659      * GVMM
    2660      */
    2661     bool fUpdate = false;
    2662     for (unsigned i = 0; i < RT_ELEMENTS(g_aGVMMStats); i++)
    2663         if (stamR3MultiMatch(papszExpressions, cExpressions, NULL, g_aGVMMStats[i].pszName))
    2664         {
    2665             fUpdate = true;
    2666             break;
    2667         }
    2668     if (!fUpdate)
    2669     {
    2670         /** @todo check the cpu leaves - rainy day. */
    2671     }
    2672     if (fUpdate)
    2673     {
    2674         GVMMQUERYSTATISTICSSREQ Req;
    2675         Req.Hdr.cbReq = sizeof(Req);
    2676         Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    2677         Req.pSession = pVM->pSession;
    2678         int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_GVMM_QUERY_STATISTICS, 0, &Req.Hdr);
    2679         if (RT_SUCCESS(rc))
    2680         {
    2681             pUVM->stam.s.GVMMStats = Req.Stats;
    2682 
    2683             /*
    2684              * Check if the number of host CPUs has changed (it will the first
    2685              * time around and normally never again).
    2686              */
    2687             if (RT_UNLIKELY(pUVM->stam.s.GVMMStats.cHostCpus > pUVM->stam.s.cRegisteredHostCpus))
    2688             {
    2689                 STAM_LOCK_WR(pUVM);
    2690                 if (RT_UNLIKELY(pUVM->stam.s.GVMMStats.cHostCpus > pUVM->stam.s.cRegisteredHostCpus))
    2691                 {
    2692                     uint32_t cCpus = pUVM->stam.s.GVMMStats.cHostCpus;
    2693                     for (uint32_t iCpu  = pUVM->stam.s.cRegisteredHostCpus; iCpu < cCpus; iCpu++)
    2694                     {
    2695                         char   szName[120];
    2696                         size_t cchBase = RTStrPrintf(szName, sizeof(szName), "/GVMM/HostCpus/%u", iCpu);
    2697                         stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].idCpu, NULL, NULL,
    2698                                         STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_NONE, "Host CPU ID");
    2699                         strcpy(&szName[cchBase], "/idxCpuSet");
    2700                         stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].idxCpuSet, NULL, NULL,
    2701                                         STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_NONE, "CPU Set index");
    2702                         strcpy(&szName[cchBase], "/DesiredHz");
    2703                         stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].uDesiredHz, NULL, NULL,
    2704                                         STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_HZ, "The desired frequency");
    2705                         strcpy(&szName[cchBase], "/CurTimerHz");
    2706                         stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].uTimerHz, NULL, NULL,
    2707                                         STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_HZ, "The current timer frequency");
    2708                         strcpy(&szName[cchBase], "/PPTChanges");
    2709                         stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].cChanges, NULL, NULL,
    2710                                         STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES, "RTTimerChangeInterval calls");
    2711                         strcpy(&szName[cchBase], "/PPTStarts");
    2712                         stamR3RegisterU(pUVM, &pUVM->stam.s.GVMMStats.aHostCpus[iCpu].cStarts, NULL, NULL,
    2713                                         STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES, "RTTimerStart calls");
    2714                     }
    2715                     pUVM->stam.s.cRegisteredHostCpus = cCpus;
    2716                 }
    2717                 STAM_UNLOCK_WR(pUVM);
    2718             }
    2719         }
    2720     }
    2721 
    2722     /*
    2723      * GMM
    2724      */
    2725     fUpdate = false;
    2726     for (unsigned i = 0; i < RT_ELEMENTS(g_aGMMStats); i++)
    2727         if (stamR3MultiMatch(papszExpressions, cExpressions, NULL, g_aGMMStats[i].pszName))
    2728         {
    2729             fUpdate = true;
    2730             break;
    2731         }
    2732     if (fUpdate)
    2733     {
    2734         GMMQUERYSTATISTICSSREQ Req;
    2735         Req.Hdr.cbReq    = sizeof(Req);
    2736         Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    2737         Req.pSession     = pVM->pSession;
    2738         int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_GMM_QUERY_STATISTICS, 0, &Req.Hdr);
    2739         if (RT_SUCCESS(rc))
    2740             pUVM->stam.s.GMMStats = Req.Stats;
    2741     }
     2810                        g_aGMMStats[i].enmUnit, g_aGMMStats[i].pszDesc, STAM_REFRESH_GRP_GMM);
    27422811}
    27432812
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r72221 r72300  
    2727#ifdef RT_OS_WINDOWS
    2828#include <iprt/nt/hyperv.h>
     29#include <iprt/critsect.h>
    2930#endif
    3031
     
    160161    NEMWINIOCTL                 IoCtlMessageSlotHandleAndGetNext;
    161162
     163    /** Statistics updated by NEMR0UpdateStatistics. */
     164    struct
     165    {
     166        uint64_t                cPagesAvailable;
     167        uint64_t                cPagesInUse;
     168    } R0Stats;
    162169#endif /* RT_OS_WINDOWS */
    163170} NEM;
     
    256263
    257264#ifdef IN_RING0
     265# ifdef RT_OS_WINDOWS
     266/**
     267 * Windows: Hypercall input/ouput page info.
     268 */
     269typedef struct NEMR0HYPERCALLDATA
     270{
     271    /** Host physical address of the hypercall input/output page. */
     272    RTHCPHYS                    HCPhysPage;
     273    /** Pointer to the hypercall input/output page. */
     274    uint8_t                    *pbPage;
     275    /** Handle to the memory object of the hypercall input/output page. */
     276    RTR0MEMOBJ                  hMemObj;
     277} NEMR0HYPERCALLDATA;
     278/** Pointer to a Windows hypercall input/output page info. */
     279typedef NEMR0HYPERCALLDATA *PNEMR0HYPERCALLDATA;
     280# endif /* RT_OS_WINDOWS */
    258281
    259282/**
     
    263286{
    264287# ifdef RT_OS_WINDOWS
    265     /** @name Hypercall input/ouput page.
    266      * @{ */
    267     /** Host physical address of the hypercall input/output page. */
    268     RTHCPHYS                    HCPhysHypercallData;
    269     /** Pointer to the hypercall input/output page. */
    270     uint8_t                    *pbHypercallData;
    271     /** Handle to the memory object of the hypercall input/output page. */
    272     RTR0MEMOBJ                  hHypercallDataMemObj;
    273     /** @} */
     288    /** Hypercall input/ouput page. */
     289    NEMR0HYPERCALLDATA          HypercallData;
    274290# else
    275291    uint32_t                    uDummy;
     
    298314    NEMWINIOCTL                 IoCtlMessageSlotHandleAndGetNext;
    299315
     316    /** Hypercall input/ouput page for non-EMT. */
     317    NEMR0HYPERCALLDATA          HypercallData;
     318    /** Critical section protecting use of HypercallData. */
     319    RTCRITSECT                  HypercallDataCritSect;
     320
    300321# else
    301322    uint32_t                    uDummy;
  • trunk/src/VBox/VMM/include/STAMInternal.h

    r69474 r72300  
    124124    /** Unit. */
    125125    STAMUNIT            enmUnit;
     126    /** The refresh group number (STAM_REFRESH_GRP_XXX). */
     127    uint8_t             iRefreshGroup;
    126128    /** Description. */
    127129    const char         *pszDesc;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette