VirtualBox

Ignore:
Timestamp:
Jul 23, 2024 10:50:17 AM (6 months ago)
Author:
vboxsync
Message:

VMM/IEM: Added some simple TLB tracing (disabled by default). bugref:10727

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/IEMR3.cpp

    r105428 r105440  
    5050#include <iprt/assert.h>
    5151#include <iprt/getopt.h>
     52#ifdef IEM_WITH_TLB_TRACE
     53# include <iprt/mem.h>
     54#endif
    5255#include <iprt/string.h>
    5356
     
    6467static FNDBGFINFOARGVINT iemR3InfoITlb;
    6568static FNDBGFINFOARGVINT iemR3InfoDTlb;
     69#ifdef IEM_WITH_TLB_TRACE
     70static FNDBGFINFOARGVINT iemR3InfoTlbTrace;
     71#endif
    6672#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
    6773static FNDBGFINFOARGVINT iemR3InfoTb;
     
    203209    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
    204210    {
    205         PVMCPU pVCpu = pVM->apCpusR3[idCpu];
     211        PVMCPU const pVCpu = pVM->apCpusR3[idCpu];
    206212        AssertCompile(sizeof(pVCpu->iem.s) <= sizeof(pVCpu->iem.padding)); /* (tstVMStruct can't do it's job w/o instruction stats) */
    207213
     
    286292         */
    287293        pVCpu->iem.s.uTbNativeRecompileAtUsedCount = uTbNativeRecompileAtUsedCount;
     294#endif
     295
     296#ifdef IEM_WITH_TLB_TRACE
     297        /*
     298         * Allocate trace buffer.
     299         */
     300        pVCpu->iem.s.idxTlbTraceEntry      = 0;
     301        pVCpu->iem.s.cTlbTraceEntriesShift = 19;//16;
     302        pVCpu->iem.s.paTlbTraceEntries     = (PIEMTLBTRACEENTRY)RTMemPageAlloc(  RT_BIT_Z(pVCpu->iem.s.cTlbTraceEntriesShift)
     303                                                                               * sizeof(*pVCpu->iem.s.paTlbTraceEntries));
     304        AssertLogRelReturn(pVCpu->iem.s.paTlbTraceEntries, VERR_NO_PAGE_MEMORY);
    288305#endif
    289306    }
     
    958975    DBGFR3InfoRegisterInternalArgv(pVM, "itlb", "IEM instruction TLB", iemR3InfoITlb, DBGFINFO_FLAGS_RUN_ON_EMT);
    959976    DBGFR3InfoRegisterInternalArgv(pVM, "dtlb", "IEM instruction TLB", iemR3InfoDTlb, DBGFINFO_FLAGS_RUN_ON_EMT);
     977#ifdef IEM_WITH_TLB_TRACE
     978    DBGFR3InfoRegisterInternalArgv(pVM, "tlbtrace", "IEM TLB trace log", iemR3InfoTlbTrace, DBGFINFO_FLAGS_RUN_ON_EMT);
     979#endif
    960980#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
    961981    DBGFR3InfoRegisterInternalArgv(pVM, "tb",   "IEM translation block", iemR3InfoTb, DBGFINFO_FLAGS_RUN_ON_EMT);
     
    972992{
    973993    NOREF(pVM);
     994#ifdef IEM_WITH_TLB_TRACE
     995    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     996    {
     997        PVMCPU const pVCpu = pVM->apCpusR3[idCpu];
     998        RTMemPageFree(pVCpu->iem.s.paTlbTraceEntries,
     999                      RT_BIT_Z(pVCpu->iem.s.cTlbTraceEntriesShift) * sizeof(*pVCpu->iem.s.paTlbTraceEntries));
     1000    }
     1001#endif
    9741002    return VINF_SUCCESS;
    9751003}
     
    11621190#endif
    11631191
    1164     pHlp->pfnPrintf(pHlp, "%0*x: %s %#018RX64 -> %RGp / %p / %#05x %s%s%s%s%s%s%s/%s%s%s%s/%s %s%s\n",
    1165                     RT_ELEMENTS(pTlb->aEntries) >= 0x1000 ? 4 : RT_ELEMENTS(pTlb->aEntries) >= 0x100 ? 3 : 2, uSlot,
     1192    pHlp->pfnPrintf(pHlp, IEMTLB_SLOT_FMT ": %s %#018RX64 -> %RGp / %p / %#05x %s%s%s%s%s%s%s/%s%s%s%s/%s %s%s\n",
     1193                    uSlot,
    11661194                    (pTlbe->uTag & IEMTLB_REVISION_MASK) == uTlbRevision ? "valid  "
    11671195                    : (pTlbe->uTag & IEMTLB_REVISION_MASK) == 0          ? "empty  "
     
    14101438}
    14111439
     1440
     1441#ifdef IEM_WITH_TLB_TRACE
     1442/**
     1443 * @callback_method_impl{FNDBGFINFOARGVINT, tlbtrace}
     1444 */
     1445static DECLCALLBACK(void) iemR3InfoTlbTrace(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
     1446{
     1447    /*
     1448     * Parse arguments.
     1449     */
     1450    static RTGETOPTDEF const s_aOptions[] =
     1451    {
     1452        { "--cpu",                      'c', RTGETOPT_REQ_UINT32  },
     1453        { "--vcpu",                     'c', RTGETOPT_REQ_UINT32  },
     1454        { "--last",                     'l', RTGETOPT_REQ_UINT32  },
     1455        { "--limit",                    'l', RTGETOPT_REQ_UINT32  },
     1456        { "--stop-at-global-flush",     'g', RTGETOPT_REQ_NOTHING },
     1457    };
     1458
     1459    RTGETOPTSTATE State;
     1460    int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /*iFirst*/, 0 /*fFlags*/);
     1461    AssertRCReturnVoid(rc);
     1462
     1463    uint32_t        cLimit             = UINT32_MAX;
     1464    bool            fStopAtGlobalFlush = false;
     1465    PVMCPU const    pVCpuCall          = VMMGetCpu(pVM);
     1466    PVMCPU          pVCpu              = pVCpuCall;
     1467    if (!pVCpu)
     1468        pVCpu = VMMGetCpuById(pVM, 0);
     1469
     1470    RTGETOPTUNION   ValueUnion;
     1471    while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
     1472    {
     1473        switch (rc)
     1474        {
     1475            case 'c':
     1476                if (ValueUnion.u32 >= pVM->cCpus)
     1477                    pHlp->pfnPrintf(pHlp, "error: Invalid CPU ID: %u\n", ValueUnion.u32);
     1478                else if (!pVCpu || pVCpu->idCpu != ValueUnion.u32)
     1479                    pVCpu = VMMGetCpuById(pVM, ValueUnion.u32);
     1480                break;
     1481
     1482            case 'l':
     1483                cLimit = ValueUnion.u32;
     1484                break;
     1485
     1486            case 'g':
     1487                fStopAtGlobalFlush = true;
     1488                break;
     1489
     1490            case 'h':
     1491                pHlp->pfnPrintf(pHlp,
     1492                                "Usage: info tlbtrace [options]\n"
     1493                                "\n"
     1494                                "Options:\n"
     1495                                "  -c<n>, --cpu=<n>, --vcpu=<n>\n"
     1496                                "    Selects the CPU which TLB trace we're looking at. Default: Caller / 0\n"
     1497                                "  -l<n>, --last=<n>\n"
     1498                                "    Limit display to the last N entries. Default: all\n"
     1499                                "  -g,--stop-at-global-flush\n"
     1500                                "    Stop after the first global flush entry.\n"
     1501                                );
     1502                return;
     1503
     1504            default:
     1505                pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State);
     1506                return;
     1507        }
     1508    }
     1509
     1510    /*
     1511     * Get the details.
     1512     */
     1513    AssertReturnVoid(pVCpu);
     1514    Assert(pVCpu->iem.s.cTlbTraceEntriesShift <= 28);
     1515    uint32_t            idx         = pVCpu->iem.s.idxTlbTraceEntry;
     1516    uint32_t const      cShift      = RT_MIN(pVCpu->iem.s.cTlbTraceEntriesShift, 28);
     1517    uint32_t const      fMask       = RT_BIT_32(cShift) - 1;
     1518    uint32_t            cLeft       = RT_MIN(RT_MIN(idx, RT_BIT_32(cShift)), cLimit);
     1519    PCIEMTLBTRACEENTRY  paEntries   = pVCpu->iem.s.paTlbTraceEntries;
     1520    if (cLeft && paEntries)
     1521    {
     1522        /*
     1523         * Display the entries.
     1524         */
     1525        pHlp->pfnPrintf(pHlp, "TLB Trace for CPU %u:\n", pVCpu->idCpu);
     1526        while (cLeft-- > 0)
     1527        {
     1528            PCIEMTLBTRACEENTRY const pCur = &paEntries[--idx & fMask];
     1529            switch (pCur->enmType)
     1530            {
     1531                case kIemTlbTraceType_InvlPg:
     1532                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 invlpg %RGv slot=" IEMTLB_SLOT_FMT "\n",
     1533                                    idx, pCur->rip, pCur->u64Param, (uint32_t)IEMTLB_ADDR_TO_EVEN_INDEX(pCur->u64Param));
     1534                    break;
     1535                case kIemTlbTraceType_Flush:
     1536                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 flush %s rev=%#RX64\n", idx, pCur->rip,
     1537                                    pCur->bParam ? "data" : "code", pCur->u64Param);
     1538                    break;
     1539                case kIemTlbTraceType_FlushGlobal:
     1540                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 flush %s rev=%#RX64 grev=%#RX64\n", idx, pCur->rip,
     1541                                    pCur->bParam ? "data" : "code", pCur->u64Param, pCur->u64Param2);
     1542                    if (fStopAtGlobalFlush)
     1543                        return;
     1544                    break;
     1545                case kIemTlbTraceType_Load:
     1546                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 load %s %RGv slot=" IEMTLB_SLOT_FMT "\n",
     1547                                    idx, pCur->rip, pCur->bParam ? "data" : "code",
     1548                                    pCur->u64Param, (uint32_t)IEMTLB_ADDR_TO_EVEN_INDEX(pCur->u64Param));
     1549                    break;
     1550                case kIemTlbTraceType_LoadGlobal:
     1551                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 load %s %RGv slot=" IEMTLB_SLOT_FMT " (global)\n",
     1552                                    idx, pCur->rip, pCur->bParam ? "data" : "code",
     1553                                    pCur->u64Param, (uint32_t)IEMTLB_ADDR_TO_EVEN_INDEX(pCur->u64Param));
     1554                    break;
     1555                case kIemTlbTraceType_Load_Cr0:
     1556                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 load cr0 %08RX64 (was %08RX64)\n",
     1557                                    idx, pCur->rip, pCur->u64Param, pCur->u64Param2);
     1558                    break;
     1559                case kIemTlbTraceType_Load_Cr3:
     1560                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 load cr3 %016RX64 (was %016RX64)\n",
     1561                                    idx, pCur->rip, pCur->u64Param, pCur->u64Param2);
     1562                    break;
     1563                case kIemTlbTraceType_Load_Cr4:
     1564                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 load cr4 %08RX64 (was %08RX64)\n",
     1565                                    idx, pCur->rip, pCur->u64Param, pCur->u64Param2);
     1566                    break;
     1567                case kIemTlbTraceType_Load_Efer:
     1568                    pHlp->pfnPrintf(pHlp, "%u: %016RX64 load efer %016RX64 (was %016RX64)\n",
     1569                                    idx, pCur->rip, pCur->u64Param, pCur->u64Param2);
     1570                    break;
     1571                case kIemTlbTraceType_Invalid:
     1572                    pHlp->pfnPrintf(pHlp, "%u: Invalid!\n");
     1573                    break;
     1574            }
     1575        }
     1576    }
     1577    else
     1578        pHlp->pfnPrintf(pHlp, "No trace entries to display\n");
     1579}
     1580#endif /* IEM_WITH_TLB_TRACE */
     1581
    14121582#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
    14131583/**
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