Beispiel #1
0
/** Print the CPU 'revision', if available. */
static RTEXITCODE handlerCpuRevision(int argc, char **argv)
{
    NOREF(argc); NOREF(argv);

#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    uint32_t uEax, uEbx, uEcx, uEdx;
    ASMCpuId(0, &uEax, &uEbx, &uEcx, &uEdx);
    if (ASMIsValidStdRange(uEax) && uEax >= 1)
    {
        uint32_t uEax1 = ASMCpuId_EAX(1);
        uint32_t uVersion = (ASMGetCpuFamily(uEax1) << 24)
                          | (ASMGetCpuModel(uEax1, ASMIsIntelCpuEx(uEbx, uEcx, uEdx)) << 8)
                          | ASMGetCpuStepping(uEax1);
        int cch = RTPrintf("%#x\n", uVersion);
        return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    }
#endif
    return RTEXITCODE_FAILURE;
}
Beispiel #2
0
int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo)
{
    CPUMDBENTRY const *pEntry = NULL;
    int                rc;

    if (!strcmp(pszName, "host"))
    {
        /*
         * Create a CPU database entry for the host CPU.  This means getting
         * the CPUID bits from the real CPU and grabbing the closest matching
         * database entry for MSRs.
         */
        rc = CPUMR3CpuIdDetectUnknownLeafMethod(&pInfo->enmUnknownCpuIdMethod, &pInfo->DefCpuId);
        if (RT_FAILURE(rc))
            return rc;
        rc = CPUMR3CpuIdCollectLeaves(&pInfo->paCpuIdLeavesR3, &pInfo->cCpuIdLeaves);
        if (RT_FAILURE(rc))
            return rc;

        /* Lookup database entry for MSRs. */
        CPUMCPUVENDOR const enmVendor    = CPUMR3CpuIdDetectVendorEx(pInfo->paCpuIdLeavesR3[0].uEax,
                                                                     pInfo->paCpuIdLeavesR3[0].uEbx,
                                                                     pInfo->paCpuIdLeavesR3[0].uEcx,
                                                                     pInfo->paCpuIdLeavesR3[0].uEdx);
        uint32_t      const uStd1Eax     = pInfo->paCpuIdLeavesR3[1].uEax;
        uint8_t       const uFamily      = ASMGetCpuFamily(uStd1Eax);
        uint8_t       const uModel       = ASMGetCpuModel(uStd1Eax, enmVendor == CPUMCPUVENDOR_INTEL);
        uint8_t       const uStepping    = ASMGetCpuStepping(uStd1Eax);
        CPUMMICROARCH const enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx(enmVendor, uFamily, uModel, uStepping);

        for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
        {
            CPUMDBENTRY const *pCur = g_apCpumDbEntries[i];
            if ((CPUMCPUVENDOR)pCur->enmVendor == enmVendor)
            {
                /* Match against Family, Microarch, model and stepping.  Except
                   for family, always match the closer with preference given to
                   the later/older ones. */
                if (pCur->uFamily == uFamily)
                {
                    if (pCur->enmMicroarch == enmMicroarch)
                    {
                        if (pCur->uModel == uModel)
                        {
                            if (pCur->uStepping == uStepping)
                            {
                                /* Perfect match. */
                                pEntry = pCur;
                                break;
                            }

                            if (   !pEntry
                                || pEntry->uModel       != uModel
                                || pEntry->enmMicroarch != enmMicroarch
                                || pEntry->uFamily      != uFamily)
                                pEntry = pCur;
                            else if (  pCur->uStepping >= uStepping
                                     ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping
                                     : pCur->uStepping > pEntry->uStepping)
                                     pEntry = pCur;
                        }
                        else if (   !pEntry
                                 || pEntry->enmMicroarch != enmMicroarch
                                 || pEntry->uFamily      != uFamily)
                            pEntry = pCur;
                        else if (  pCur->uModel >= uModel
                                 ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel
                                 : pCur->uModel > pEntry->uModel)
                            pEntry = pCur;
                    }
                    else if (   !pEntry
                             || pEntry->uFamily != uFamily)
                        pEntry = pCur;
                    /* Special march matching rules applies to intel family 06h. */
                    else if (     enmVendor == CPUMCPUVENDOR_INTEL
                               && uFamily   == 6
                             ? cpumR3DbIsBetterIntelFam06Match(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch)
                             : cpumR3DbIsBetterMarchMatch(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch))
                        pEntry = pCur;
                }
                /* We don't do closeness matching on family, we use the first
                   entry for the CPU vendor instead. (P4 workaround.) */
                else if (!pEntry)
                    pEntry = pCur;
            }
        }

        if (pEntry)
            LogRel(("CPUM: Matched host CPU %s %#x/%#x/%#x %s with CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
                    CPUMR3CpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMR3MicroarchName(enmMicroarch),
                    pEntry->pszName,  CPUMR3CpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor), pEntry->uFamily, pEntry->uModel,
                    pEntry->uStepping, CPUMR3MicroarchName(pEntry->enmMicroarch) ));
        else
        {
            pEntry = g_apCpumDbEntries[0];
            LogRel(("CPUM: No matching processor database entry %s %#x/%#x/%#x %s, falling back on '%s'\n",
                    CPUMR3CpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMR3MicroarchName(enmMicroarch),
                    pEntry->pszName));
        }
    }
    else
    {
        /*
         * We're supposed to be emulating a specific CPU that is included in
         * our CPU database.  The CPUID tables needs to be copied onto the
         * heap so the caller can modify them and so they can be freed like
         * in the host case above.
         */
        for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
            if (!strcmp(pszName, g_apCpumDbEntries[i]->pszName))
            {
                pEntry = g_apCpumDbEntries[i];
                break;
            }
        if (!pEntry)
        {
            LogRel(("CPUM: Cannot locate any CPU by the name '%s'\n", pszName));
            return VERR_CPUM_DB_CPU_NOT_FOUND;
        }

        pInfo->cCpuIdLeaves = pEntry->cCpuIdLeaves;
        if (pEntry->cCpuIdLeaves)
        {
            pInfo->paCpuIdLeavesR3 = (PCPUMCPUIDLEAF)RTMemDup(pEntry->paCpuIdLeaves,
                                                              sizeof(pEntry->paCpuIdLeaves[0]) * pEntry->cCpuIdLeaves);
            if (!pInfo->paCpuIdLeavesR3)
                return VERR_NO_MEMORY;
        }
        else
            pInfo->paCpuIdLeavesR3 = NULL;

        pInfo->enmUnknownCpuIdMethod = pEntry->enmUnknownCpuId;
        pInfo->DefCpuId         = pEntry->DefUnknownCpuId;

        LogRel(("CPUM: Using CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
                pEntry->pszName, CPUMR3CpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor),
                pEntry->uFamily, pEntry->uModel, pEntry->uStepping, CPUMR3MicroarchName(pEntry->enmMicroarch) ));
    }

    pInfo->fMsrMask             = pEntry->fMsrMask;
    pInfo->iFirstExtCpuIdLeaf   = 0; /* Set by caller. */
    pInfo->uPadding             = 0;
    pInfo->uScalableBusFreq     = pEntry->uScalableBusFreq;
    pInfo->paCpuIdLeavesR0      = NIL_RTR0PTR;
    pInfo->paMsrRangesR0        = NIL_RTR0PTR;
    pInfo->paCpuIdLeavesRC      = NIL_RTRCPTR;
    pInfo->paMsrRangesRC        = NIL_RTRCPTR;

    /*
     * Copy the MSR range.
     */
    uint32_t        cMsrs   = 0;
    PCPUMMSRRANGE   paMsrs  = NULL;

    PCCPUMMSRRANGE  pCurMsr = pEntry->paMsrRanges;
    uint32_t        cLeft   = pEntry->cMsrRanges;
    while (cLeft-- > 0)
    {
        rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr);
        if (RT_FAILURE(rc))
        {
            Assert(!paMsrs); /* The above function frees this. */
            RTMemFree(pInfo->paCpuIdLeavesR3);
            pInfo->paCpuIdLeavesR3 = NULL;
            return rc;
        }
        pCurMsr++;
    }

    pInfo->paMsrRangesR3   = paMsrs;
    pInfo->cMsrRanges      = cMsrs;
    return VINF_SUCCESS;
}