VirtualBox

Changeset 64255 in vbox


Ignore:
Timestamp:
Oct 13, 2016 3:18:21 PM (8 years ago)
Author:
vboxsync
Message:

SUP,VMM,IPRT: SUPDrv and GIP major version bump! Added processor group info to GIP along with a new RDTSCP-based method for getting the current CPU (for the timesup code).

Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/sup.h

    r62476 r64255  
    230230     * indicate stable data. Use this to make sure that the data items you fetch
    231231     * are consistent. */
    232     volatile uint32_t   u32TransactionId;
     232    volatile uint32_t       u32TransactionId;
    233233    /** The interval in TSC ticks between two NanoTS updates.
    234234     * This is the average interval over the last 2, 4 or 8 updates + a little slack.
    235235     * The slack makes the time go a tiny tiny bit slower and extends the interval enough
    236236     * to avoid ending up with too many 1ns increments. */
    237     volatile uint32_t   u32UpdateIntervalTSC;
     237    volatile uint32_t       u32UpdateIntervalTSC;
    238238    /** Current nanosecond timestamp. */
    239     volatile uint64_t   u64NanoTS;
     239    volatile uint64_t       u64NanoTS;
    240240    /** The TSC at the time of u64NanoTS. */
    241     volatile uint64_t   u64TSC;
     241    volatile uint64_t       u64TSC;
    242242    /** Current CPU Frequency. */
    243     volatile uint64_t   u64CpuHz;
     243    volatile uint64_t       u64CpuHz;
    244244    /** The TSC delta with reference to the master TSC, subtract from RDTSC. */
    245     volatile int64_t    i64TSCDelta;
     245    volatile int64_t        i64TSCDelta;
    246246    /** Number of errors during updating.
    247247     * Typical errors are under/overflows. */
    248     volatile uint32_t   cErrors;
     248    volatile uint32_t       cErrors;
    249249    /** Index of the head item in au32TSCHistory. */
    250     volatile uint32_t   iTSCHistoryHead;
     250    volatile uint32_t       iTSCHistoryHead;
    251251    /** Array of recent TSC interval deltas.
    252252     * The most recent item is at index iTSCHistoryHead.
    253253     * This history is used to calculate u32UpdateIntervalTSC.
    254254     */
    255     volatile uint32_t   au32TSCHistory[8];
     255    volatile uint32_t       au32TSCHistory[8];
    256256    /** The interval between the last two NanoTS updates. (experiment for now) */
    257     volatile uint32_t   u32PrevUpdateIntervalNS;
     257    volatile uint32_t       u32PrevUpdateIntervalNS;
    258258
    259259    /** Reserved for future per processor data. */
    260     volatile uint32_t   au32Reserved0[5];
    261 
     260    volatile uint32_t       u32Reserved;
    262261    /** The TSC value read while doing TSC delta measurements across CPUs. */
    263     volatile uint64_t   u64TSCSample;
    264 
     262    volatile uint64_t       u64TSCSample;
    265263    /** Reserved for future per processor data. */
    266     volatile uint32_t   au32Reserved1[1];
    267 
    268     /** @todo Add topology/NUMA info. */
     264    volatile uint32_t       au32Reserved1[3];
     265
    269266    /** The CPU state. */
    270267    SUPGIPCPUSTATE volatile enmState;
     
    273270    /** The CPU set index of this CPU. */
    274271    int16_t                 iCpuSet;
     272    /** CPU group number (always zero, except on windows). */
     273    uint16_t                iCpuGroup;
     274    /** CPU group number (same as iCpuSet, except on windows). */
     275    uint16_t                iCpuGroupMember;
    275276    /** The APIC ID of this CPU. */
    276277    uint16_t                idApic;
     278    /** @todo Add topology/NUMA info. */
     279    uint32_t                iReservedForNumaNode;
    277280} SUPGIPCPU;
    278281AssertCompileSize(RTCPUID, 4);
     
    280283AssertCompileMemberAlignment(SUPGIPCPU, u64NanoTS, 8);
    281284AssertCompileMemberAlignment(SUPGIPCPU, u64TSC, 8);
     285AssertCompileMemberAlignment(SUPGIPCPU, u64TSCSample, 8);
    282286
    283287/** Pointer to per cpu data.
     
    314318
    315319/** @name SUPGIPGETCPU_XXX - methods that aCPUs can be indexed.
     320 *
     321 * @note    Linux offers information via selector 0x78, and Windows via selector
     322 *          0x53.  But since they both support RDTSCP as well, and because most
     323 *          CPUs now have RDTSCP, we prefer it over LSL.  We can implement more
     324 *          alternatives if it becomes necessary.
     325 *
    316326 * @{
    317327 */
     
    335345 * does with RDTSCP. */
    336346#define SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS   RT_BIT_32(2)
    337 /* Linux also offers information via selector 0x78, but we'll settle for
    338    RDTSCP for now. */
     347/** Windows specific RDTSCP variant, where CH gives you the group and CL gives
     348 * you the CPU number within that group.
     349 *
     350 * Use SUPGLOBALINFOPAGE::aidFirstCpuFromCpuGroup to get the group base CPU set
     351 * index, then translate the sum of thru aiCpuFromCpuSetIdx to find the aCPUs
     352 * entry.
     353 *
     354 * @note The group number is actually 16-bit wide (ECX[23:8]), but we simplify
     355 *       it since we only support 256 CPUs/groups at the moment.
     356 */
     357#define SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL RT_BIT_32(3)
    339358/** @} */
    340359
     
    381400    /** The highest number of CPUs possible. */
    382401    uint16_t            cPossibleCpus;
    383     uint16_t            u16Padding0;
     402    /** The highest number of CPU groups possible. */
     403    uint16_t            cPossibleCpuGroups;
    384404    /** The max CPU ID (RTMpGetMaxCpuId). */
    385405    RTCPUID             idCpuMax;
     
    399419    /** CPU set index to CPU table index. */
    400420    uint16_t            aiCpuFromCpuSetIdx[RTCPUSET_MAX_CPUS];
     421    /** Table indexed by CPU group index to get the CPU set index of the first
     422     *  CPU. */
     423    uint16_t            aiFirstCpuSetIdxFromCpuGroup[RTCPUSET_MAX_CPUS];
    401424
    402425    /** Array of per-cpu data.
     
    415438AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 256);
    416439#endif
     440AssertCompile(sizeof(SUPGLOBALINFOPAGE) <= 0x1000); /* Keeping it less or equal to a page for raw-mode (saved state). */
    417441
    418442/** Pointer to the global info page.
     
    426450 * Upper 16 bits is the major version. Major version is only changed with
    427451 * incompatible changes in the GIP. */
    428 #define SUPGLOBALINFOPAGE_VERSION   0x00060001
     452#define SUPGLOBALINFOPAGE_VERSION   0x00070000
    429453
    430454/**
     
    569593    AssertFailed();
    570594    return UINT64_MAX;
     595}
     596
     597
     598/**
     599 * Gets the pointer to the per CPU data for a CPU given by its set index.
     600 *
     601 * @returns Pointer to the corresponding per CPU structure, or NULL if invalid.
     602 * @param   pGip        The GIP pointer.
     603 * @param   iCpuSet     The CPU set index of the CPU which we want.
     604 */
     605DECLINLINE(PSUPGIPCPU) SUPGetGipCpuBySetIndex(PSUPGLOBALINFOPAGE pGip, uint32_t iCpuSet)
     606{
     607    if (RT_LIKELY(   pGip
     608                  && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC))
     609    {
     610        if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     611        {
     612            uint16_t iCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     613            if (RT_LIKELY(iCpu < pGip->cCpus))
     614                return &pGip->aCPUs[iCpu];
     615        }
     616    }
     617    return NULL;
    571618}
    572619
  • trunk/include/iprt/mangling.h

    r62915 r64255  
    21042104# define RTTimeNanoTSLegacyAsyncUseRdtscp                       RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscp)
    21052105# define RTTimeNanoTSLegacyAsyncUseRdtscp_EndProc               RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscp_EndProc)
     2106# define RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl           RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl)
     2107# define RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl_EndProc   RT_MANGLER(RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl_EndProc)
    21062108# define RTTimeNanoTSLegacyAsyncUseIdtrLim                      RT_MANGLER(RTTimeNanoTSLegacyAsyncUseIdtrLim)
    21072109# define RTTimeNanoTSLegacyAsyncUseIdtrLim_EndProc              RT_MANGLER(RTTimeNanoTSLegacyAsyncUseIdtrLim_EndProc)
     
    21222124# define RTTimeNanoTSLFenceAsyncUseRdtscp                       RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscp)
    21232125# define RTTimeNanoTSLFenceAsyncUseRdtscp_EndProc               RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscp_EndProc)
     2126# define RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl           RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl)
     2127# define RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl_EndProc   RT_MANGLER(RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl_EndProc)
    21242128# define RTTimeNanoTSLFenceAsyncUseIdtrLim                      RT_MANGLER(RTTimeNanoTSLFenceAsyncUseIdtrLim)
    21252129# define RTTimeNanoTSLFenceAsyncUseIdtrLim_EndProc              RT_MANGLER(RTTimeNanoTSLFenceAsyncUseIdtrLim_EndProc)
  • trunk/include/iprt/nt/nt.h

    r64237 r64255  
    23902390/*NTSYSAPI ULONG NTAPI RtlNtStatusToDosError(NTSTATUS rcNt);*/
    23912391
     2392/** @def RTL_QUERY_REGISTRY_TYPECHECK
     2393 * WDK 8.1+, backported in updates, ignored in older. */
     2394#if !defined(RTL_QUERY_REGISTRY_TYPECHECK) || defined(DOXYGEN_RUNNING)
     2395# define RTL_QUERY_REGISTRY_TYPECHECK       UINT32_C(0x00000100)
     2396#endif
     2397/** @def RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
     2398 * WDK 8.1+, backported in updates, ignored in older. */
     2399#if !defined(RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) || defined(DOXYGEN_RUNNING)
     2400# define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT 24
     2401#endif
     2402
    23922403
    23932404RT_C_DECLS_END
  • trunk/include/iprt/time.h

    r62860 r64255  
    954954RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicId(PRTTIMENANOTSDATA pData);
    955955RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
     956RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
    956957RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
    957958RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
     
    960961RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicId(PRTTIMENANOTSDATA pData);
    961962RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
     963RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
    962964RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
    963965RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
  • trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp

    r64236 r64255  
    274274            && RT_IS_POWER_OF_TWO(RTCPUSET_MAX_CPUS))
    275275        {
     276            PSUPGIPCPU pGipCpu = SUPGetGipCpuBySetIndex(pGip, iCpuSet);
     277
    276278            /*
    277279             * Check whether the IDTR.LIMIT contains a CPU number.
     
    305307                    && (ASMCpuId_EDX(UINT32_C(0x80000001)) & X86_CPUID_EXT_FEATURE_EDX_RDTSCP) )
    306308                {
    307                     uint32_t uAux;
     309                    uint32_t const  uGroupedAux = (uint8_t)pGipCpu->iCpuGroupMember | ((uint32_t)pGipCpu->iCpuGroup << 8);
     310                    uint32_t        uAux;
    308311                    ASMReadTscWithAux(&uAux);
    309312                    if ((uAux & (RTCPUSET_MAX_CPUS - 1)) == idCpu)
     
    313316                        if ((uAux & (RTCPUSET_MAX_CPUS - 1)) == idCpu)
    314317                            fSupported |= SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS;
     318                    }
     319
     320                    if (   (uAux & UINT16_MAX) == uGroupedAux
     321                        && pGipCpu->iCpuGroupMember <= UINT8_MAX)
     322                    {
     323                        ASMNopPause();
     324                        ASMReadTscWithAux(&uAux);
     325                        if ((uAux & UINT16_MAX) == uGroupedAux)
     326                            fSupported |= SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL;
    315327                    }
    316328                }
     
    12591271static void supdrvGipMpEventOnlineOrInitOnCpu(PSUPDRVDEVEXT pDevExt, RTCPUID idCpu)
    12601272{
    1261     int         iCpuSet = 0;
    1262     uint16_t    idApic = UINT16_MAX;
    1263     uint32_t    i = 0;
    1264     uint64_t    u64NanoTS = 0;
    1265     PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
     1273    PSUPGLOBALINFOPAGE  pGip      = pDevExt->pGip;
     1274    int                 iCpuSet   = 0;
     1275    uint16_t            idApic    = UINT16_MAX;
     1276    uint32_t            i        = 0;
     1277    uint64_t            u64NanoTS = 0;
    12661278
    12671279    AssertPtrReturnVoid(pGip);
     
    13011313    ASMAtomicWriteS16(&pGip->aCPUs[i].iCpuSet, (int16_t)iCpuSet);
    13021314    ASMAtomicWriteSize(&pGip->aCPUs[i].idCpu,  idCpu);
     1315
     1316    pGip->aCPUs[i].iCpuGroup = 0;
     1317    pGip->aCPUs[i].iCpuGroupMember = iCpuSet;
     1318#ifdef RT_OS_WINDOWS
     1319    pGip->aCPUs[i].iCpuGroup = supdrvOSGipGetGroupFromCpu(pDevExt, idCpu, &pGip->aCPUs[i].iCpuGroupMember);
     1320#endif
    13031321
    13041322    /*
     
    16831701    pCpu->i64TSCDelta        = pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED ? INT64_MAX : 0;
    16841702
    1685     ASMAtomicWriteSize(&pCpu->enmState, SUPGIPCPUSTATE_INVALID);
    1686     ASMAtomicWriteU32(&pCpu->idCpu,     NIL_RTCPUID);
    1687     ASMAtomicWriteS16(&pCpu->iCpuSet,   -1);
    1688     ASMAtomicWriteU16(&pCpu->idApic,    UINT16_MAX);
     1703    ASMAtomicWriteSize(&pCpu->enmState,             SUPGIPCPUSTATE_INVALID);
     1704    ASMAtomicWriteU32(&pCpu->idCpu,                 NIL_RTCPUID);
     1705    ASMAtomicWriteS16(&pCpu->iCpuSet,               -1);
     1706    ASMAtomicWriteU16(&pCpu->iCpuGroup,             0);
     1707    ASMAtomicWriteU16(&pCpu->iCpuGroupMember,       UINT16_MAX);
     1708    ASMAtomicWriteU16(&pCpu->idApic,                UINT16_MAX);
     1709    ASMAtomicWriteU32(&pCpu->iReservedForNumaNode,  0);
    16891710
    16901711    /*
     
    17641785    pGip->cPresentCpus            = RTMpGetPresentCount();
    17651786    pGip->cPossibleCpus           = RTMpGetCount();
     1787    pGip->cPossibleCpuGroups      = 1;
    17661788    pGip->idCpuMax                = RTMpGetMaxCpuId();
    17671789    for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromApicId); i++)
     
    17691791    for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx); i++)
    17701792        pGip->aiCpuFromCpuSetIdx[i] = UINT16_MAX;
     1793    pGip->aiFirstCpuSetIdxFromCpuGroup[0] = 0;
     1794    for (i = 1; i < RT_ELEMENTS(pGip->aiFirstCpuSetIdxFromCpuGroup); i++)
     1795        pGip->aiFirstCpuSetIdxFromCpuGroup[i] = UINT16_MAX;
     1796#ifdef RT_OS_WINDOWS
     1797    supdrvOSInitGipGroupTable(pDevExt, pGip);
     1798#endif
    17711799    for (i = 0; i < cCpus; i++)
    17721800        supdrvGipInitCpu(pGip, &pGip->aCPUs[i], u64NanoTS, 0 /*uCpuHz*/);
     
    23942422     * run.
    23952423     */
    2396     if (RT_UNLIKELY(iTick == 1))
     2424    if (RT_LIKELY(iTick != 1))
     2425    { /* likely*/ }
     2426    else
    23972427    {
    23982428        iCpu = supdrvGipFindOrAllocCpuIndexForCpuId(pGip, idCpu);
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r62664 r64255  
    215215 *          - nothing.
    216216 */
    217 #define SUPDRV_IOC_VERSION                              0x00260000
     217#define SUPDRV_IOC_VERSION                              0x00270000
    218218
    219219/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r62664 r64255  
    800800void VBOXCALL   supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser);
    801801
     802/**
     803 * Called during GIP initialization to set up the group table and group count.
     804 *
     805 * This is currently only implemented on windows [lazy bird].
     806 *
     807 * @param   pDevExt             The device globals.
     808 * @param   pGip                The GIP which group table needs initialization.
     809 *                              It's only partially initialized at this point.
     810 */
     811void VBOXCALL   supdrvOSInitGipGroupTable(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip);
     812
     813/**
     814 * Gets the CPU group and member indexes for the given CPU ID.
     815 *
     816 * This is currently only implemented on windows [lazy bird].
     817 *
     818 * @returns CPU group number.
     819 * @param   pDevExt             The device globals.
     820 * @param   idCpu               The ID of the CPU.
     821 * @param   piCpuGroupMember    Where to return the group member number.
     822 */
     823uint16_t VBOXCALL supdrvOSGipGetGroupFromCpu(PSUPDRVDEVEXT pDevExt, RTCPUID idCpu, uint16_t *piCpuGroupMember);
     824
    802825void VBOXCALL   supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession);
    803826bool VBOXCALL   supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc);
  • trunk/src/VBox/HostDrivers/Support/testcase/tstGIP-2.cpp

    r62490 r64255  
    131131                SUPR3GipSetFlags(SUPGIP_FLAGS_TESTING_ENABLE, UINT32_MAX);
    132132
    133             RTPrintf("tstGIP-2: cCpus=%d  u32UpdateHz=%RU32  u32UpdateIntervalNS=%RU32  u64NanoTSLastUpdateHz=%RX64  u64CpuHz=%RU64  uCpuHzRef=%RU64  u32Mode=%d (%s)  fTestMode=%RTbool  u32Version=%#x\n",
     133            RTPrintf("tstGIP-2: u32Mode=%d (%s)  fTestMode=%RTbool  u32Version=%#x  fGetGipCpu=%#RX32\n",
     134                     g_pSUPGlobalInfoPage->u32Mode,
     135                     SUPGetGIPModeName(g_pSUPGlobalInfoPage),
     136                     fTestMode,
     137                     g_pSUPGlobalInfoPage->u32Version,
     138                     g_pSUPGlobalInfoPage->fGetGipCpu);
     139            RTPrintf("tstGIP-2: cCpus=%d  cPossibleCpus=%d cPossibleCpuGroups=%d cPresentCpus=%d cOnlineCpus=%d\n",
    134140                     g_pSUPGlobalInfoPage->cCpus,
     141                     g_pSUPGlobalInfoPage->cPossibleCpus,
     142                     g_pSUPGlobalInfoPage->cPossibleCpuGroups,
     143                     g_pSUPGlobalInfoPage->cPresentCpus,
     144                     g_pSUPGlobalInfoPage->cOnlineCpus);
     145            RTPrintf("tstGIP-2: u32UpdateHz=%RU32  u32UpdateIntervalNS=%RU32  u64NanoTSLastUpdateHz=%RX64  u64CpuHz=%RU64  uCpuHzRef=%RU64\n",
    135146                     g_pSUPGlobalInfoPage->u32UpdateHz,
    136147                     g_pSUPGlobalInfoPage->u32UpdateIntervalNS,
    137148                     g_pSUPGlobalInfoPage->u64NanoTSLastUpdateHz,
    138149                     g_pSUPGlobalInfoPage->u64CpuHz,
    139                      uCpuHzRef,
    140                      g_pSUPGlobalInfoPage->u32Mode,
    141                      SUPGetGIPModeName(g_pSUPGlobalInfoPage),
    142                      fTestMode,
    143                      g_pSUPGlobalInfoPage->u32Version);
     150                     uCpuHzRef);
     151
    144152            RTPrintf(fHex
    145153                     ? "tstGIP-2:     it: u64NanoTS        delta     u64TSC           UpIntTSC H  TransId      CpuHz      %sTSC Interval History...\n"
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r62677 r64255  
    359359#endif /* VBOXDRV_WITH_FAST_IO */
    360360
     361/** Default ZERO value. */
     362static ULONG                        g_fOptDefaultZero = 0;
     363/** Registry values.
     364 * We wrap these in a struct to ensure they are followed by a little zero
     365 * padding in order to limit the chance of trouble on unpatched systems.  */
     366struct
     367{
     368    /** The ForceAsync registry value. */
     369    ULONG                           fOptForceAsyncTsc;
     370    /** Padding. */
     371    uint64_t                        au64Padding[2];
     372}                                   g_Options = { FALSE, 0, 0 };
     373/** Registry query table for RtlQueryRegistryValues. */
     374static RTL_QUERY_REGISTRY_TABLE     g_aRegValues[] =
     375{
     376    {
     377        /* .QueryRoutine = */   NULL,
     378        /* .Flags = */          RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK,
     379        /* .Name = */           L"ForceAsyncTsc",
     380        /* .EntryContext = */   &g_Options.fOptForceAsyncTsc,
     381        /* .DefaultType = */    (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD,
     382        /* .DefaultData = */    &g_fOptDefaultZero,
     383        /* .DefaultLength = */  sizeof(g_fOptDefaultZero),
     384    },
     385    {   NULL, 0, NULL, NULL, 0, NULL, 0 } /* terminator entry. */
     386};
     387
     388/** Pointer to KeQueryMaximumGroupCount. */
     389static PFNKEQUERYMAXIMUMGROUPCOUNT      g_pfnKeQueryMaximumGroupCount = NULL;
     390/** Pointer to KeGetProcessorIndexFromNumber. */
     391static PFNKEGETPROCESSORINDEXFROMNUMBER g_pfnKeGetProcessorIndexFromNumber = NULL;
     392/** Pointer to KeGetProcessorNumberFromIndex. */
     393static PFNKEGETPROCESSORNUMBERFROMINDEX g_pfnKeGetProcessorNumberFromIndex = NULL;
     394
    361395#ifdef VBOX_WITH_HARDENING
    362396/** Pointer to the stub device instance. */
     
    554588
    555589    /*
     590     * Query options first so any overflows on unpatched machines will do less
     591     * harm (see MS11-011 / 2393802 / 2011-03-18).
     592     *
     593     * Unfortunately, pRegPath isn't documented as zero terminated, even if it
     594     * quite likely always is, so we have to make a copy here.
     595     */
     596    NTSTATUS rcNt;
     597    PWSTR pwszCopy = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, pRegPath->Length + sizeof(WCHAR), 'VBox');
     598    if (pwszCopy)
     599    {
     600        memcpy(pwszCopy, pRegPath->Buffer, pRegPath->Length);
     601        pwszCopy[pRegPath->Length / sizeof(WCHAR)] = '\0';
     602        rcNt = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, pwszCopy,
     603                                      g_aRegValues, NULL /*pvContext*/, NULL /*pvEnv*/);
     604        ExFreePoolWithTag(pwszCopy, 'VBox');
     605        /* Probably safe to ignore rcNt here. */
     606    }
     607
     608    /*
     609     * Resolve methods we want but isn't available everywhere.
     610     */
     611    UNICODE_STRING RoutineName;
     612    RtlInitUnicodeString(&RoutineName, L"KeQueryMaximumGroupCount");
     613    g_pfnKeQueryMaximumGroupCount = (PFNKEQUERYMAXIMUMGROUPCOUNT)MmGetSystemRoutineAddress(&RoutineName);
     614
     615    RtlInitUnicodeString(&RoutineName, L"KeGetProcessorIndexFromNumber");
     616    g_pfnKeGetProcessorIndexFromNumber = (PFNKEGETPROCESSORINDEXFROMNUMBER)MmGetSystemRoutineAddress(&RoutineName);
     617
     618    RtlInitUnicodeString(&RoutineName, L"KeGetProcessorNumberFromIndex");
     619    g_pfnKeGetProcessorNumberFromIndex = (PFNKEGETPROCESSORNUMBERFROMINDEX)MmGetSystemRoutineAddress(&RoutineName);
     620
     621    Assert(   (g_pfnKeGetProcessorNumberFromIndex != NULL) == (g_pfnKeGetProcessorIndexFromNumber != NULL)
     622           && (g_pfnKeGetProcessorNumberFromIndex != NULL) == (g_pfnKeQueryMaximumGroupCount != NULL)); /* all or nothing. */
     623
     624    /*
    556625     * Initialize the runtime (IPRT).
    557626     */
    558     NTSTATUS rcNt;
    559627    int vrc = RTR0Init(0);
    560628    if (RT_SUCCESS(vrc))
     
    16431711
    16441712
     1713void VBOXCALL supdrvOSInitGipGroupTable(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip)
     1714{
     1715    NOREF(pDevExt);
     1716
     1717    /*
     1718     * The indexes are assigned in group order (see initterm-r0drv-nt.cpp).
     1719     */
     1720    if (   g_pfnKeQueryMaximumGroupCount
     1721        && g_pfnKeGetProcessorIndexFromNumber)
     1722    {
     1723        unsigned cGroups = g_pfnKeQueryMaximumGroupCount();
     1724        AssertStmt(cGroups > 0, cGroups = 1);
     1725        AssertStmt(cGroups < RT_ELEMENTS(pGip->aiFirstCpuSetIdxFromCpuGroup),
     1726                   cGroups = RT_ELEMENTS(pGip->aiFirstCpuSetIdxFromCpuGroup));
     1727        pGip->cPossibleCpuGroups = cGroups;
     1728
     1729        KEPROCESSORINDEX idxCpuMin = 0;
     1730        for (unsigned iGroup = 0; iGroup < cGroups; iGroup++)
     1731        {
     1732            PROCESSOR_NUMBER ProcNum;
     1733            ProcNum.Group    = (USHORT)iGroup;
     1734            ProcNum.Number   = 0;
     1735            ProcNum.Reserved = 0;
     1736            KEPROCESSORINDEX idxCpu = g_pfnKeGetProcessorIndexFromNumber(&ProcNum);
     1737            Assert(idxCpu != INVALID_PROCESSOR_INDEX);
     1738            Assert(idxCpu >= idxCpuMin);
     1739            idxCpuMin = idxCpu;
     1740            pGip->aiFirstCpuSetIdxFromCpuGroup[iGroup] = (uint16_t)idxCpu;
     1741        }
     1742    }
     1743    else
     1744    {
     1745        Assert(!g_pfnKeQueryMaximumGroupCount);
     1746        Assert(!g_pfnKeGetProcessorIndexFromNumber);
     1747
     1748        pGip->cPossibleCpuGroups              = 1;
     1749        pGip->aiFirstCpuSetIdxFromCpuGroup[0] = 0;
     1750    }
     1751}
     1752
     1753
     1754uint16_t VBOXCALL supdrvOSGipGetGroupFromCpu(PSUPDRVDEVEXT pDevExt, RTCPUID idCpu, uint16_t *piCpuGroupMember)
     1755{
     1756    NOREF(pDevExt);
     1757
     1758    /*
     1759     * This is just a wrapper around KeGetProcessorNumberFromIndex.
     1760     */
     1761    if (g_pfnKeGetProcessorNumberFromIndex)
     1762    {
     1763        PROCESSOR_NUMBER ProcNum = { UINT16_MAX, UINT8_MAX, 0 };
     1764        NTSTATUS rcNt = g_pfnKeGetProcessorNumberFromIndex(idCpu, &ProcNum);
     1765        if (NT_SUCCESS(rcNt))
     1766        {
     1767            Assert(ProcNum.Group < g_pfnKeQueryMaximumGroupCount());
     1768            *piCpuGroupMember = ProcNum.Number;
     1769            return ProcNum.Group;
     1770        }
     1771
     1772        AssertMsgFailed(("rcNt=%#x for idCpu=%u\n", rcNt, idCpu));
     1773    }
     1774
     1775    *piCpuGroupMember = 0;
     1776    return idCpu;
     1777}
     1778
     1779
    16451780/**
    16461781 * Initializes any OS specific object creator fields.
     
    16801815{
    16811816    RT_NOREF1(pDevExt);
    1682     return false;
     1817    return g_Options.fOptForceAsyncTsc != 0;
    16831818}
    16841819
  • trunk/src/VBox/Runtime/common/time/timesup.cpp

    r62556 r64255  
    203203                          : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
    204204                          ? RTTimeNanoTSLFenceAsyncUseRdtscp
     205                          : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
     206                          ? RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl
    205207                          : pGip->fGetGipCpu & SUPGIPGETCPU_APIC_ID
    206208                          ? RTTimeNanoTSLFenceAsyncUseApicId
     
    239241                pfnWorker = pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
    240242                          ? RTTimeNanoTSLegacyAsyncUseRdtscp
     243                          : pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
     244                          ? RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl
    241245                          : pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
    242246                          ? RTTimeNanoTSLegacyAsyncUseIdtrLim
  • trunk/src/VBox/Runtime/common/time/timesupref.cpp

    r62477 r64255  
    112112RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseIdtrLim);
    113113
     114# undef  TMPL_GET_CPU_METHOD
     115# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
     116# undef  rtTimeNanoTSInternalRef
     117# define rtTimeNanoTSInternalRef RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl
     118# include "timesupref.h"
     119RT_EXPORT_SYMBOL(RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl);
     120
    114121#else  /* IN_RC || IN_RING0: Disable interrupts and call getter function. */
    115122
     
    196203RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseIdtrLim);
    197204
     205# undef  TMPL_GET_CPU_METHOD
     206# define TMPL_GET_CPU_METHOD     SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
     207# undef  rtTimeNanoTSInternalRef
     208# define rtTimeNanoTSInternalRef RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl
     209# include "timesupref.h"
     210RT_EXPORT_SYMBOL(RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl);
     211
    198212#else  /* IN_RC || IN_RING0: Disable interrupts and call getter function. */
    199213
  • trunk/src/VBox/Runtime/common/time/timesupref.h

    r62477 r64255  
    9191            uint8_t  const  idApic   = ASMGetApicId();
    9292            uint16_t const  iGipCpu  = pGip->aiCpuFromApicId[idApic];
    93 # elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
     93# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS \
     94    || TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
    9495#  if TMPL_MODE != TMPL_MODE_ASYNC
    9596            uint32_t const  u32TransactionId = pGip->aCPUs[0].u32TransactionId;
     
    9798            uint32_t        uAux;
    9899            ASMReadTscWithAux(&uAux);
     100#  if TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
    99101            uint16_t const  iCpuSet  = uAux & (RTCPUSET_MAX_CPUS - 1);
     102#  else
     103            uint16_t const  iCpuSet  = pGip->aiFirstCpuSetIdxFromCpuGroup[(uAux >> 8) & UINT8_MAX] + (uAux & UINT8_MAX);
     104#  endif
    100105            uint16_t const  iGipCpu  = pGip->aiCpuFromCpuSetIdx[iCpuSet];
    101106# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
     
    124129#elif TMPL_MODE != TMPL_MODE_ASYNC \
    125130   && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID \
    126    && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
     131   && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS \
     132   && TMPL_GET_CPU_METHOD != SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
    127133                uint32_t const u32TransactionId = pGip->aCPUs[0].u32TransactionId;
    128134                ASMCompilerBarrier();
     
    149155#endif
    150156                uint64_t u64PrevNanoTS          = ASMAtomicUoReadU64(pData->pu64Prev);
    151 #if TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
     157#if TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS \
     158 || TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
    152159                ASMCompilerBarrier();
    153160                uint32_t uAux2;
     
    168175# if   TMPL_GET_CPU_METHOD == SUPGIPGETCPU_APIC_ID
    169176                if (RT_LIKELY(ASMGetApicId() == idApic))
    170 # elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
     177# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS \
     178    || TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL
    171179                if (RT_LIKELY(uAux2 == uAux))
    172180# elif TMPL_GET_CPU_METHOD == SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS
  • trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp

    r62478 r64255  
    119119            else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS)
    120120                pfnWorker = fLFence ? RTTimeNanoTSLFenceAsyncUseRdtscp      : RTTimeNanoTSLegacyAsyncUseRdtscp;
     121            else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL)
     122                pfnWorker = fLFence ? RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl : RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl;
    121123            else
    122124                pfnWorker = fLFence ? RTTimeNanoTSLFenceAsyncUseApicId      : RTTimeNanoTSLegacyAsyncUseApicId;
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