VirtualBox

Changeset 4330 in vbox for trunk/src


Ignore:
Timestamp:
Aug 24, 2007 12:47:24 AM (17 years ago)
Author:
vboxsync
Message:

Added PAE and AMD64 (long mode) support to the dpd* and dpt* commands. (Needed it for debugging shadow paging.)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGConsole.cpp

    r4253 r4330  
    31253125
    31263126/**
    3127  * The 'dpd*' commands.
     3127 * Best guess at which paging mode currently applies to the guest
     3128 * paging structures.
     3129 *
     3130 * This have to come up with a decent answer even when the guest
     3131 * is in non-paged protected mode or real mode.
     3132 *
     3133 * @returns cr3.
     3134 * @param   pDbgc   The DBGC instance.
     3135 * @param   pfPAE   Where to store the page address extension indicator.
     3136 * @param   pfLME   Where to store the long mode enabled indicator.
     3137 * @param   pfPSE   Where to store the page size extension indicator.
     3138 * @param   pfPGE   Where to store the page global enabled indicator.
     3139 * @param   pfNXE   Where to store the no-execution enabled inidicator.
     3140 */
     3141static RTGCPHYS dbgcGetGuestPageMode(PDBGC pDbgc, bool *pfPAE, bool *pfLME, bool *pfPSE, bool *pfPGE, bool *pfNXE)
     3142{
     3143    RTGCUINTREG cr4 = CPUMGetGuestCR4(pDbgc->pVM);
     3144    *pfPSE = !!(cr4 & X86_CR4_PSE);
     3145    *pfPGE = !!(cr4 & X86_CR4_PGE);
     3146    *pfPAE = !!(cr4 & X86_CR4_PAE);
     3147    *pfLME = CPUMGetGuestMode(pDbgc->pVM) == CPUMMODE_LONG;
     3148    *pfNXE = false; /* GUEST64 GUESTNX */
     3149    return CPUMGetGuestCR3(pDbgc->pVM);
     3150}
     3151
     3152
     3153/**
     3154 * Determin the shadow paging mode.
     3155 *
     3156 * @returns cr3.
     3157 * @param   pDbgc   The DBGC instance.
     3158 * @param   pfPAE   Where to store the page address extension indicator.
     3159 * @param   pfLME   Where to store the long mode enabled indicator.
     3160 * @param   pfPSE   Where to store the page size extension indicator.
     3161 * @param   pfPGE   Where to store the page global enabled indicator.
     3162 * @param   pfNXE   Where to store the no-execution enabled inidicator.
     3163 */
     3164static RTHCPHYS dbgcGetShadowPageMode(PDBGC pDbgc, bool *pfPAE, bool *pfLME, bool *pfPSE, bool *pfPGE, bool *pfNXE)
     3165{
     3166    *pfPSE = true;
     3167    *pfPGE = false;
     3168    switch (PGMGetShadowMode(pDbgc->pVM))
     3169    {
     3170        default:
     3171        case PGMMODE_32_BIT:
     3172            *pfPAE = *pfLME = *pfNXE = false;
     3173            break;
     3174        case PGMMODE_PAE:
     3175            *pfLME = *pfNXE = false;
     3176            *pfPAE = true;
     3177            break;
     3178        case PGMMODE_PAE_NX:
     3179            *pfLME = false;
     3180            *pfPAE = *pfNXE = true;
     3181            break;
     3182        case PGMMODE_AMD64:
     3183            *pfNXE = false;
     3184            *pfPAE = *pfLME = true;
     3185            break;
     3186        case PGMMODE_AMD64_NX:
     3187            *pfPAE = *pfLME = *pfNXE = true;
     3188            break;
     3189    }
     3190    return PGMGetHyperCR3(pDbgc->pVM);
     3191}
     3192
     3193
     3194/**
     3195 * The 'dpd', 'dpda', 'dpdb', 'dpdg' and 'dpdh' commands.
    31283196 *
    31293197 * @returns VBox status.
     
    31493217        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    31503218
    3151 
    3152     /*
    3153      * Where to start dumping page directory entries?
    3154      */
     3219    /*
     3220     * Guest or shadow page directories? Get the paging parameters.
     3221     */
     3222    bool fGuest = pCmd->pszCmd[3] != 'h';
     3223    if (!pCmd->pszCmd[3] || !pCmd->pszCmd[3] == 'a')
     3224        fGuest = paArgs[0].enmType == DBGCVAR_TYPE_NUMBER
     3225               ? pDbgc->fRegCtxGuest
     3226               : DBGCVAR_ISGCPOINTER(paArgs[0].enmType);
     3227
     3228    bool fPAE, fLME, fPSE, fPGE, fNXE;
     3229    uint64_t cr3 = fGuest
     3230                 ? dbgcGetGuestPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE)
     3231                 : dbgcGetShadowPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE);
     3232    const unsigned cbEntry = fPAE ? sizeof(X86PTEPAE) : sizeof(X86PTE);
     3233
     3234    /*
     3235     * Setup default arugment if none was specified.
     3236     * Fix address / index confusion.
     3237     */
     3238    DBGCVAR VarDefault;
     3239    if (!cArgs)
     3240    {
     3241        if (pCmd->pszCmd[3] == 'a')
     3242        {
     3243            if (fLME || fPAE)
     3244                return DBGCCmdHlpPrintf(pCmdHlp, "Default argument for 'dpda' hasn't been fully implemented yet. Try with an address or use one of the other commands.\n");
     3245            if (fGuest)
     3246                DBGCVAR_INIT_GC_PHYS(&VarDefault, cr3);
     3247            else
     3248                DBGCVAR_INIT_HC_PHYS(&VarDefault, cr3);
     3249        }
     3250        else
     3251            DBGCVAR_INIT_GC_FLAT(&VarDefault, 0);
     3252        paArgs = &VarDefault;
     3253        cArgs = 1;
     3254    }
     3255    else if (paArgs[0].enmType == DBGCVAR_TYPE_NUMBER)
     3256    {
     3257        Assert(pCmd->pszCmd[3] != 'a');
     3258        VarDefault = paArgs[0];
     3259        if (VarDefault.u.u64Number <= 1024)
     3260        {
     3261            if (fPAE)
     3262                return DBGCCmdHlpPrintf(pCmdHlp, "PDE indexing is only implemented for 32-bit paging.\n");
     3263            if (VarDefault.u.u64Number >= PAGE_SIZE / cbEntry)
     3264                return DBGCCmdHlpPrintf(pCmdHlp, "PDE index is out of range [0..%d].\n", PAGE_SIZE / cbEntry - 1);
     3265            VarDefault.u.u64Number <<= X86_PD_SHIFT;
     3266        }
     3267        VarDefault.enmType = DBGCVAR_TYPE_GC_FLAT;
     3268        paArgs = &VarDefault;
     3269    }
     3270
     3271    /*
     3272     * Locate the PDE to start displaying at.
     3273     *
     3274     * The 'dpda' command takes the address of a PDE, while the others are guest
     3275     * virtual address which PDEs should be displayed. So, 'dpda' is rather simple
     3276     * while the others require us to do all the tedious walking thru the paging
     3277     * hierarchy to find the intended PDE.
     3278     */
     3279    unsigned    iEntry = ~0U;           /* The page directory index. ~0U for 'dpta'. */
     3280    DBGCVAR     VarGCPtr;               /* The GC address corresponding to the current PDE (iEntry != ~0U). */
     3281    DBGCVAR     VarPDEAddr;             /* The address of the current PDE. */
     3282    unsigned    cEntries;               /* The number of entries to display. */
     3283    unsigned    cEntriesMax;            /* The max number of entries to display. */
    31553284    int         rc;
    3156     unsigned    cEntriesMax = PAGE_SIZE / sizeof(VBOXPDE);
    3157     unsigned    cEntries = PAGE_SIZE / sizeof(VBOXPDE);
    3158     unsigned    off = ~0;
    3159     uint32_t    u32CR4 = X86_CR4_PSE;
    3160     DBGCVAR     VarAddr;
    3161     if (cArgs == 0 || pCmd->pszCmd[3] != 'a')
    3162     {
     3285    if (pCmd->pszCmd[3] == 'a')
     3286    {
     3287        VarPDEAddr = paArgs[0];
     3288        switch (VarPDEAddr.enmRangeType)
     3289        {
     3290            case DBGCVAR_RANGE_BYTES:       cEntries = VarPDEAddr.u64Range / cbEntry; break;
     3291            case DBGCVAR_RANGE_ELEMENTS:    cEntries = VarPDEAddr.u64Range; break;
     3292            default:                        cEntries = 10; break;
     3293        }
     3294        cEntriesMax = PAGE_SIZE / cbEntry;
     3295    }
     3296    else
     3297    {
     3298        /*
     3299         * Determin the range.
     3300         */
     3301        switch (paArgs[0].enmRangeType)
     3302        {
     3303            case DBGCVAR_RANGE_BYTES:       cEntries = paArgs[0].u64Range / PAGE_SIZE; break;
     3304            case DBGCVAR_RANGE_ELEMENTS:    cEntries = paArgs[0].u64Range; break;
     3305            default:                        cEntries = 10; break;
     3306        }
     3307
    31633308        /*
    3164          * Get defaults.
     3309         * Normalize the input address, it must be a flat GC address.
    31653310         */
    3166         off = 0;
    3167         if (    pCmd->pszCmd[3] == 'g'
    3168             ||  (pDbgc->fRegCtxGuest && (!pCmd->pszCmd[3] || pCmd->pszCmd[3] == 'a')))
    3169         {
    3170             u32CR4 = CPUMGetGuestCR4(pVM);
    3171             rc = pCmdHlp->pfnEval(pCmdHlp, &VarAddr, "%%%%cr3");
    3172         }
     3311        rc = pCmdHlp->pfnEval(pCmdHlp, &VarGCPtr, "%%(%Dv)", &paArgs[0]);
     3312        if (VBOX_FAILURE(rc))
     3313            return DBGCCmdHlpVBoxError(pCmdHlp, rc, "%%(%Dv)", &paArgs[0]);
     3314        if (VarGCPtr.enmType == DBGCVAR_TYPE_HC_FLAT)
     3315        {
     3316            VarGCPtr.u.GCFlat = (uintptr_t)VarGCPtr.u.pvHCFlat;
     3317            VarGCPtr.enmType = DBGCVAR_TYPE_GC_FLAT;
     3318        }
     3319        if (fPAE)
     3320            VarGCPtr.u.GCFlat &= ~(((RTGCPTR)1 << X86_PD_PAE_SHIFT) - 1);
    31733321        else
    3174         {
    3175             /** @todo fix hypervisor CR4 value! */
    3176             //u32CR4 = CPUMGetHyperCR4(pVM);
    3177             u32CR4 = X86_CR4_PGE | X86_CR4_PSE;
    3178             rc = pCmdHlp->pfnEval(pCmdHlp, &VarAddr, "#%%%%.cr3");
    3179         }
    3180         if (VBOX_FAILURE(rc))
    3181             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "(Getting (.)cr3.)");
    3182 
    3183         if (cArgs > 0)
    3184         {
    3185             cEntries = 3;
    3186             if (!DBGCVAR_ISPOINTER(paArgs[0].enmType))
    3187             {
    3188                 /*
    3189                  * Add index.
    3190                  */
    3191                 rc = pCmdHlp->pfnEval(pCmdHlp, &VarAddr, "%DV + %#x", &VarAddr, paArgs[0].u.u64Number * sizeof(VBOXPTE));
    3192                 if (VBOX_FAILURE(rc))
    3193                     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%DV + %#x", &VarAddr, paArgs[0].u.u64Number * sizeof(VBOXPTE));
    3194                 if (paArgs[0].u.u64Number >= PAGE_SIZE / sizeof(VBOXPDE))
    3195                     off = ~0;
    3196                 else
    3197                 {
    3198                     off = (unsigned)paArgs[0].u.u64Number;
    3199                     cEntriesMax = PAGE_SIZE / sizeof(VBOXPDE) - off;
    3200                 }
    3201             }
    3202             else
    3203             {
    3204                 /*
    3205                  * Pointer which we want the page directory entry for.
    3206                  * Start by making sure it's a GC pointer.
    3207                  */
    3208                 DBGCVAR VarTmp;
    3209                 rc = pCmdHlp->pfnEval(pCmdHlp, &VarTmp, "%%(%Dv)", &paArgs[0]);
    3210                 if (VBOX_FAILURE(rc))
    3211                     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%%(%Dv) failed.", &paArgs[0]);
    3212 
    3213                 rc = pCmdHlp->pfnEval(pCmdHlp, &VarAddr, "%DV + %#x", &VarAddr, (VarTmp.u.GCFlat >> PGDIR_SHIFT) * sizeof(VBOXPTE));
    3214                 if (VBOX_FAILURE(rc))
    3215                     return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%DV + %#x", &VarAddr, (VarTmp.u.GCFlat >> PGDIR_SHIFT) * sizeof(VBOXPTE));
    3216                 off = VarTmp.u.GCFlat >> PGDIR_SHIFT;
    3217                 cEntriesMax = PAGE_SIZE / sizeof(VBOXPDE) - off;
    3218             }
    3219         }
    3220     }
    3221     else
    3222         VarAddr = paArgs[0];
    3223 
    3224     /*
    3225      * Range.
    3226      */
    3227     unsigned i = cArgs;
    3228     while (i-- > 0)
    3229     {
    3230         if (paArgs[i].enmRangeType == DBGCVAR_RANGE_ELEMENTS)
    3231         {
    3232             cEntries = (unsigned)RT_MIN(paArgs[i].u64Range, cEntriesMax);
    3233             break;
    3234         }
    3235         else if (paArgs[i].enmRangeType == DBGCVAR_RANGE_BYTES)
    3236         {
    3237             cEntries = (unsigned)RT_MIN(paArgs[i].u64Range / sizeof(VBOXPDE), cEntriesMax);
    3238             break;
    3239         }
    3240     }
    3241 
    3242     /*
    3243      * Dump loop.
    3244      */
    3245     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, off != ~0U ? "%DV (index %#x):\n" : "%DV:\n", &VarAddr, off);
    3246     if (VBOX_FAILURE(rc))
    3247         return rc;
    3248     for (;;)
     3322            VarGCPtr.u.GCFlat &= ~(((RTGCPTR)1 << X86_PD_SHIFT) - 1);
     3323
     3324        /*
     3325         * Do the paging walk until we get to the page directory.
     3326         */
     3327        DBGCVAR VarCur;
     3328        if (fGuest)
     3329            DBGCVAR_INIT_GC_PHYS(&VarCur, cr3);
     3330        else
     3331            DBGCVAR_INIT_HC_PHYS(&VarCur, cr3);
     3332        if (fLME)
     3333        {
     3334            /* Page Map Level 4 Lookup. */
     3335            /* Check if it's a valid address first? */
     3336            VarCur.u.u64Number &= X86_PTE_PAE_PG_MASK;
     3337            VarCur.u.u64Number += (((uint64_t)VarGCPtr.u.GCFlat >> X86_PML4_SHIFT) & X86_PML4_MASK) * sizeof(X86PML4E);
     3338            X86PML4E Pml4e;
     3339            rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pml4e, sizeof(Pml4e), &VarCur, NULL);
     3340            if (VBOX_FAILURE(rc))
     3341                return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PML4E memory at %DV.\n", &VarCur);
     3342            if (!Pml4e.n.u1Present)
     3343                return DBGCCmdHlpPrintf(pCmdHlp, "Page directory pointer table is not present for %Dv.\n", &VarGCPtr);
     3344
     3345            VarCur.u.u64Number = Pml4e.u & X86_PML4E_PG_MASK;
     3346            Assert(fPAE);
     3347        }
     3348        if (fPAE)
     3349        {
     3350            /* Page directory pointer table. */
     3351            X86PDPE Pdpe;
     3352            VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK) * sizeof(Pdpe);
     3353            rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pdpe, sizeof(Pdpe), &VarCur, NULL);
     3354            if (VBOX_FAILURE(rc))
     3355                return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDPE memory at %DV.\n", &VarCur);
     3356            if (!Pdpe.n.u1Present)
     3357                return DBGCCmdHlpPrintf(pCmdHlp, "Page directory is not present for %Dv.\n", &VarGCPtr);
     3358
     3359            iEntry = (VarGCPtr.u.GCFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
     3360            VarPDEAddr = VarCur;
     3361            VarPDEAddr.u.u64Number = Pdpe.u & X86_PDPE_PG_MASK;
     3362            VarPDEAddr.u.u64Number += iEntry * sizeof(X86PDEPAE);
     3363        }
     3364        else
     3365        {
     3366            /* 32-bit legacy - CR3 == page directory. */
     3367            iEntry = (VarGCPtr.u.GCFlat >> X86_PD_SHIFT) & X86_PD_MASK;
     3368            VarPDEAddr = VarCur;
     3369            VarPDEAddr.u.u64Number += iEntry * sizeof(X86PDE);
     3370        }
     3371        cEntriesMax = (PAGE_SIZE - iEntry) / cbEntry;
     3372        iEntry /= cbEntry;
     3373    }
     3374
     3375    /* adjust cEntries */
     3376    cEntries = RT_MAX(1, cEntries);
     3377    cEntries = RT_MIN(cEntries, cEntriesMax);
     3378
     3379    /*
     3380     * The display loop.
     3381     */
     3382    DBGCCmdHlpPrintf(pCmdHlp, iEntry != ~0U ? "%DV (index %#x):\n" : "%DV:\n",
     3383                     &VarPDEAddr, iEntry);
     3384    do
    32493385    {
    32503386        /*
    32513387         * Read.
    32523388         */
    3253         VBOXPDE Pde;
    3254         rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, sizeof(Pde), &VarAddr, NULL);
     3389        X86PDEPAE Pde;
     3390        Pde.u = 0;
     3391        rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, cbEntry, &VarPDEAddr, NULL);
    32553392        if (VBOX_FAILURE(rc))
    3256             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Reading memory at %DV.\n", &VarAddr);
     3393            return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Reading PDE memory at %DV.\n", &VarPDEAddr);
    32573394
    32583395        /*
    32593396         * Display.
    32603397         */
    3261         if (off != ~0U)
    3262         {
    3263             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%03x %08x: ", off, off << PGDIR_SHIFT);
    3264             off++;
    3265         }
    3266         if ((u32CR4 & X86_CR4_PSE) && Pde.b.u1Size)
    3267             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3268                 "%08x big phys=%08x %s %s %s %s %s avl=%02x %s %s %s %s\n",
    3269                 Pde.u, Pde.b.u10PageNo << PGDIR_SHIFT, Pde.b.u1Present ? "p " : "np", Pde.b.u1Write ? "w" : "r",
    3270                 Pde.b.u1User ? "u" : "s", Pde.b.u1Accessed ? "a " : "na", Pde.b.u1Dirty ? "d " : "nd",
    3271                 Pde.b.u3Available, Pde.b.u1Global ? "G" : " ", Pde.b.u1WriteThru ? "pwt" : "   ",
    3272                 Pde.b.u1CacheDisable ? "pcd" : "   ", Pde.b.u1PAT ? "pat" : "");
     3398        if (iEntry != ~0U)
     3399        {
     3400            DBGCCmdHlpPrintf(pCmdHlp, "%03x %DV: ", iEntry, &VarGCPtr);
     3401            iEntry++;
     3402        }
     3403        if (fPSE && Pde.b.u1Size)
     3404            DBGCCmdHlpPrintf(pCmdHlp,
     3405                             fPAE
     3406                             ? "%016llx big phys=%016llx %s %s %s %s %s avl=%02x %s %s %s %s %s"
     3407                             :   "%08llx big phys=%08llx %s %s %s %s %s avl=%02x %s %s %s %s %s",
     3408                             Pde.u,
     3409                             Pde.u & X86_PDE_PAE_PG_MASK,
     3410                             Pde.b.u1Present        ? "p "  : "np",
     3411                             Pde.b.u1Write          ? "w"   : "r",
     3412                             Pde.b.u1User           ? "u"   : "s",
     3413                             Pde.b.u1Accessed       ? "a "  : "na",
     3414                             Pde.b.u1Dirty          ? "d "  : "nd",
     3415                             Pde.b.u3Available,
     3416                             Pde.b.u1Global         ? (fPGE ? "g" : "G") : " ",
     3417                             Pde.b.u1WriteThru      ? "pwt" : "   ",
     3418                             Pde.b.u1CacheDisable   ? "pcd" : "   ",
     3419                             Pde.b.u1PAT            ? "pat" : "",
     3420                             Pde.b.u1NoExecute      ? (fNXE ? "nx" : "NX") : "  ");
    32733421        else
    3274             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3275                 "%08x 4kb phys=%08x %s %s %s %s %s avl=%02x %s %s %s %s\n",
    3276                 Pde.u, Pde.n.u20PageNo << PAGE_SHIFT, Pde.n.u1Present ? "p " : "np", Pde.n.u1Write ? "w" : "r",
    3277                 Pde.n.u1User ? "u" : "s", Pde.n.u1Accessed ? "a " : "na", Pde.u & BIT(6) ? "6 " : "  ",
    3278                 Pde.n.u3Available, Pde.u & BIT(8) ? "8" : " ", Pde.n.u1WriteThru ? "pwt" : "   ",
    3279                 Pde.n.u1CacheDisable ? "pcd" : "   ", Pde.u & BIT(7) ? "7" : "");
     3422            DBGCCmdHlpPrintf(pCmdHlp,
     3423                             fPAE
     3424                             ? "%016llx 4kb phys=%016llx %s %s %s %s %s avl=%02x %s %s %s %s"
     3425                             :   "%08llx 4kb phys=%08llx %s %s %s %s %s avl=%02x %s %s %s %s",
     3426                             Pde.u,
     3427                             Pde.u & X86_PDE_PAE_PG_MASK,
     3428                             Pde.n.u1Present        ? "p "  : "np",
     3429                             Pde.n.u1Write          ? "w"   : "r",
     3430                             Pde.n.u1User           ? "u"   : "s",
     3431                             Pde.n.u1Accessed       ? "a "  : "na",
     3432                             Pde.u & BIT(6)         ? "6 "  : "  ",
     3433                             Pde.n.u3Available,
     3434                             Pde.u & BIT(8)         ? "8"   : " ",
     3435                             Pde.n.u1WriteThru      ? "pwt" : "   ",
     3436                             Pde.n.u1CacheDisable   ? "pcd" : "   ",
     3437                             Pde.u & BIT(7)         ? "7"   : "",
     3438                             Pde.n.u1NoExecute      ? (fNXE ? "nx" : "NX") : "  ");
     3439        if (Pde.u & UINT64_C(0x7fff000000000000))
     3440            DBGCCmdHlpPrintf(pCmdHlp, " weird=%RX64", (Pde.u & UINT64_C(0x7fff000000000000)));
     3441        rc = DBGCCmdHlpPrintf(pCmdHlp, "\n");
    32803442        if (VBOX_FAILURE(rc))
    32813443            return rc;
    32823444
    32833445        /*
    3284          * Next
     3446         * Advance.
    32853447         */
    3286         if (cEntries-- <= 1)
    3287             break;
    3288         rc = pCmdHlp->pfnEval(pCmdHlp, &VarAddr, "%DV + %#x", &VarAddr, sizeof(VBOXPDE));
    3289         if (VBOX_FAILURE(rc))
    3290             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%DV + %#x", &VarAddr, sizeof(VBOXPDE));
    3291     }
     3448        VarPDEAddr.u.u64Number += cbEntry;
     3449        if (iEntry != ~0U)
     3450            VarGCPtr.u.GCFlat += 1 << (fPAE ? X86_PD_PAE_SHIFT : X86_PD_SHIFT);
     3451    } while (cEntries-- > 0);
    32923452
    32933453    NOREF(pResult);
    32943454    return VINF_SUCCESS;
    32953455}
     3456
    32963457
    32973458/**
     
    33393500        ||  (pCmd->pszCmd[3] != 'a' && !(paArgs[0].enmType == DBGCVAR_TYPE_NUMBER || DBGCVAR_ISPOINTER(paArgs[0].enmType)))
    33403501        )
    3341         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "internal error: The parser doesn't do its job properly yet.. It might help to use the '%%' operator.\n");
     3502        return DBGCCmdHlpPrintf(pCmdHlp, "internal error: The parser doesn't do its job properly yet.. It might help to use the '%%' operator.\n");
    33423503    if (!pVM)
    3343         return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: No VM.\n");
    3344 
    3345 
    3346     /*
    3347      * Where to start dumping page directory entries?
    3348      */
     3504        return DBGCCmdHlpPrintf(pCmdHlp, "error: No VM.\n");
     3505
     3506    /*
     3507     * Guest or shadow page tables? Get the paging parameters.
     3508     */
     3509    bool fGuest = pCmd->pszCmd[3] != 'h';
     3510    if (!pCmd->pszCmd[3] || !pCmd->pszCmd[3] == 'a')
     3511        fGuest = paArgs[0].enmType == DBGCVAR_TYPE_NUMBER
     3512               ? pDbgc->fRegCtxGuest
     3513               : DBGCVAR_ISGCPOINTER(paArgs[0].enmType);
     3514           
     3515    bool fPAE, fLME, fPSE, fPGE, fNXE;
     3516    uint64_t cr3 = fGuest
     3517                 ? dbgcGetGuestPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE)
     3518                 : dbgcGetShadowPageMode(pDbgc, &fPAE, &fLME, &fPSE, &fPGE, &fNXE);
     3519    const unsigned cbEntry = fPAE ? sizeof(X86PTEPAE) : sizeof(X86PTE);
     3520
     3521    /*
     3522     * Locate the PTE to start displaying at.
     3523     *
     3524     * The 'dpta' command takes the address of a PTE, while the others are guest
     3525     * virtual address which PTEs should be displayed. So, 'pdta' is rather simple
     3526     * while the others require us to do all the tedious walking thru the paging
     3527     * hierarchy to find the intended PTE.
     3528     */
     3529    unsigned    iEntry = ~0U;           /* The page table index. ~0U for 'dpta'. */
     3530    DBGCVAR     VarGCPtr;               /* The GC address corresponding to the current PTE (iEntry != ~0U). */
     3531    DBGCVAR     VarPTEAddr;             /* The address of the current PTE. */
     3532    unsigned    cEntries;               /* The number of entries to display. */
     3533    unsigned    cEntriesMax;            /* The max number of entries to display. */
    33493534    int         rc;
    3350     unsigned    cEntriesMax = PAGE_SIZE / sizeof(VBOXPDE);
    3351     unsigned    cEntries = PAGE_SIZE / sizeof(VBOXPDE);
    3352     unsigned    off = ~0;
    3353     DBGCVAR     VarGCPtr;               /* only valid with off == ~0 */
    3354     DBGCVAR     VarPTEAddr;
    3355     if (pCmd->pszCmd[3] != 'a')
    3356     {
     3535    if (pCmd->pszCmd[3] == 'a')
     3536    {
     3537        VarPTEAddr = paArgs[0];
     3538        switch (VarPTEAddr.enmRangeType)
     3539        {
     3540            case DBGCVAR_RANGE_BYTES:       cEntries = VarPTEAddr.u64Range / cbEntry; break;
     3541            case DBGCVAR_RANGE_ELEMENTS:    cEntries = VarPTEAddr.u64Range; break;
     3542            default:                        cEntries = 10; break;
     3543        }
     3544        cEntriesMax = PAGE_SIZE / cbEntry;
     3545    }
     3546    else
     3547    {
     3548        /*
     3549         * Determin the range.
     3550         */
     3551        switch (paArgs[0].enmRangeType)
     3552        {
     3553            case DBGCVAR_RANGE_BYTES:       cEntries = paArgs[0].u64Range / PAGE_SIZE; break;
     3554            case DBGCVAR_RANGE_ELEMENTS:    cEntries = paArgs[0].u64Range; break;
     3555            default:                        cEntries = 10; break;
     3556        }
     3557
    33573558        /*
    3358          * Get page directory and cr4.
    3359          */
    3360         bool        fHyper;
    3361         uint32_t    u32CR4;
    3362         off = 0;
    3363         if (    pCmd->pszCmd[3] == 'g'
    3364             ||  (pDbgc->fRegCtxGuest && (!pCmd->pszCmd[3] || pCmd->pszCmd[3] == 'a')))
    3365         {
    3366             u32CR4 = CPUMGetGuestCR4(pVM);
    3367             rc = pCmdHlp->pfnEval(pCmdHlp, &VarPTEAddr, "%%%%cr3");
    3368             fHyper = false;
    3369         }
    3370         else
    3371         {
    3372             /** @todo fix hypervisor CR4 value! */
    3373             //u32CR4 = CPUMGetHyperCR4(pVM);
    3374             u32CR4 = X86_CR4_PGE | X86_CR4_PSE;
    3375             rc = pCmdHlp->pfnEval(pCmdHlp, &VarPTEAddr, "#%%%%.cr3");
    3376             fHyper = true;
    3377         }
    3378         if (VBOX_FAILURE(rc))
    3379             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "(Getting (.)cr3.)");
    3380 
    3381         /*
    3382          * Find page directory entry for the address.
    3383          * Make sure it's a flat address first.
     3559         * Normalize the input address, it must be a flat GC address.
    33843560         */
    33853561        rc = pCmdHlp->pfnEval(pCmdHlp, &VarGCPtr, "%%(%Dv)", &paArgs[0]);
    33863562        if (VBOX_FAILURE(rc))
    3387             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%%(%Dv)", &paArgs[0]);
    3388 
    3389         rc = pCmdHlp->pfnEval(pCmdHlp, &VarPTEAddr, "(%Dv) + %#x", &VarPTEAddr, (VarGCPtr.u.GCFlat >> PGDIR_SHIFT) * sizeof(VBOXPDE));
    3390         if (VBOX_FAILURE(rc))
    3391             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "(%Dv) + %#x", &VarPTEAddr, (VarGCPtr.u.GCFlat >> PGDIR_SHIFT) * sizeof(VBOXPDE));
    3392 
     3563            return DBGCCmdHlpVBoxError(pCmdHlp, rc, "%%(%Dv)", &paArgs[0]);
     3564        if (VarGCPtr.enmType == DBGCVAR_TYPE_HC_FLAT)
     3565        {
     3566            VarGCPtr.u.GCFlat = (uintptr_t)VarGCPtr.u.pvHCFlat;
     3567            VarGCPtr.enmType = DBGCVAR_TYPE_GC_FLAT;
     3568        }
     3569        VarGCPtr.u.GCFlat &= ~(RTGCPTR)PAGE_OFFSET_MASK;
    33933570
    33943571        /*
    3395          * Now read the page directory entry for this GC address.
     3572         * Do the paging walk until we get to the page table.
    33963573         */
    3397         VBOXPDE Pde;
    3398         rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, sizeof(Pde), &VarPTEAddr, NULL);
    3399         if (VBOX_FAILURE(rc))
    3400             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Reading memory at %DV.\n", &VarPTEAddr);
    3401 
    3402         /*
    3403          * Check for presentness and handle big using dpd[gh].
    3404          */
    3405         if ((u32CR4 & X86_CR4_PSE) && Pde.b.u1Size)
    3406             return pCmdHlp->pfnExec(pCmdHlp, "dpd%s %Dv L3", &pCmd->pszCmd[3], &VarGCPtr);
    3407 
    3408         if (!Pde.n.u1Present)
    3409             return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Page table for %Dv is not present.\n", &VarGCPtr);
    3410 
    3411         /*
    3412          * Calc page table address and setup offset and counts.
    3413          */
    3414         rc = pCmdHlp->pfnEval(pCmdHlp, &VarPTEAddr, fHyper ? "#%%%%%#x" : "%%%%%#x", Pde.u & X86_PDE_PG_MASK);
    3415         if (VBOX_FAILURE(rc))
    3416             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, fHyper ? "#%%%%%#x" : "%%%%%#x", Pde.u & X86_PDE_PG_MASK);
    3417 
    3418         cEntries    = 10;
    3419         off         = (VarGCPtr.u.GCFlat >> PAGE_SHIFT) & PTE_MASK;
    3420         cEntriesMax = PAGE_SIZE / sizeof(VBOXPDE) - off;
    3421         VarGCPtr.u.GCFlat &= ~PAGE_OFFSET_MASK; /* Make it page table base address. */
    3422     }
    3423     else
    3424         VarPTEAddr = paArgs[0];
    3425 
    3426     /*
    3427      * Range.
    3428      */
    3429     unsigned i = cArgs;
    3430     while (i-- > 0)
    3431     {
    3432         if (paArgs[i].enmRangeType == DBGCVAR_RANGE_ELEMENTS)
    3433         {
    3434             cEntries = (unsigned)RT_MIN(paArgs[i].u64Range, cEntriesMax);
    3435             break;
    3436         }
    3437         else if (paArgs[i].enmRangeType == DBGCVAR_RANGE_BYTES)
    3438         {
    3439             cEntries = (unsigned)RT_MIN(paArgs[i].u64Range / sizeof(VBOXPDE), cEntriesMax);
    3440             break;
    3441         }
    3442     }
    3443 
    3444     /*
    3445      * Dump loop.
    3446      */
    3447     rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, off != ~0U ? "%DV (base %DV / index %#x):\n" : "%DV:\n", &VarPTEAddr, &VarGCPtr, off);
    3448     if (VBOX_FAILURE(rc))
    3449         return rc;
    3450     rc = pCmdHlp->pfnEval(pCmdHlp, &VarPTEAddr, "%DV + %#x", &VarPTEAddr, sizeof(VBOXPTE) * off);
    3451     if (VBOX_FAILURE(rc))
    3452         return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%DV + %#x", &VarPTEAddr, sizeof(VBOXPTE) * off);
    3453     for (;;)
     3574        DBGCVAR VarCur;
     3575        if (fGuest)
     3576            DBGCVAR_INIT_GC_PHYS(&VarCur, cr3);
     3577        else
     3578            DBGCVAR_INIT_HC_PHYS(&VarCur, cr3);
     3579        if (fLME)
     3580        {
     3581            /* Page Map Level 4 Lookup. */
     3582            /* Check if it's a valid address first? */
     3583            VarCur.u.u64Number &= X86_PTE_PAE_PG_MASK;
     3584            VarCur.u.u64Number += (((uint64_t)VarGCPtr.u.GCFlat >> X86_PML4_SHIFT) & X86_PML4_MASK) * sizeof(X86PML4E);
     3585            X86PML4E Pml4e;
     3586            rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pml4e, sizeof(Pml4e), &VarCur, NULL);
     3587            if (VBOX_FAILURE(rc))
     3588                return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PML4E memory at %DV.\n", &VarCur);
     3589            if (!Pml4e.n.u1Present)
     3590                return DBGCCmdHlpPrintf(pCmdHlp, "Page directory pointer table is not present for %Dv.\n", &VarGCPtr);
     3591
     3592            VarCur.u.u64Number = Pml4e.u & X86_PML4E_PG_MASK;
     3593            Assert(fPAE);
     3594        }
     3595        if (fPAE)
     3596        {
     3597            /* Page directory pointer table. */
     3598            X86PDPE Pdpe;
     3599            VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PDPTR_SHIFT) & X86_PDPTR_MASK) * sizeof(Pdpe);
     3600            rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pdpe, sizeof(Pdpe), &VarCur, NULL);
     3601            if (VBOX_FAILURE(rc))
     3602                return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDPE memory at %DV.\n", &VarCur);
     3603            if (!Pdpe.n.u1Present)
     3604                return DBGCCmdHlpPrintf(pCmdHlp, "Page directory is not present for %Dv.\n", &VarGCPtr);
     3605
     3606            VarCur.u.u64Number = Pdpe.u & X86_PDPE_PG_MASK;
     3607
     3608            /* Page directory (PAE). */
     3609            X86PDEPAE Pde;
     3610            VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK) * sizeof(Pde);
     3611            rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, sizeof(Pde), &VarCur, NULL);
     3612            if (VBOX_FAILURE(rc))
     3613                return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDE memory at %DV.\n", &VarCur);
     3614            if (!Pde.n.u1Present)
     3615                return DBGCCmdHlpPrintf(pCmdHlp, "Page table is not present for %Dv.\n", &VarGCPtr);
     3616            if (fPSE && Pde.n.u1Size)
     3617                return pCmdHlp->pfnExec(pCmdHlp, "dpd%s %Dv L3", &pCmd->pszCmd[3], &VarGCPtr);
     3618
     3619            iEntry = (VarGCPtr.u.GCFlat >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK;
     3620            VarPTEAddr = VarCur;
     3621            VarPTEAddr.u.u64Number = Pde.u & X86_PDE_PAE_PG_MASK;
     3622            VarPTEAddr.u.u64Number += iEntry * sizeof(X86PTEPAE);
     3623        }
     3624        else
     3625        {
     3626            /* Page directory (legacy). */
     3627            X86PDE Pde;
     3628            VarCur.u.u64Number += ((VarGCPtr.u.GCFlat >> X86_PD_SHIFT) & X86_PD_MASK) * sizeof(Pde);
     3629            rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pde, sizeof(Pde), &VarCur, NULL);
     3630            if (VBOX_FAILURE(rc))
     3631                return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PDE memory at %DV.\n", &VarCur);
     3632            if (!Pde.n.u1Present)
     3633                return DBGCCmdHlpPrintf(pCmdHlp, "Page table is not present for %Dv.\n", &VarGCPtr);
     3634            if (fPSE && Pde.n.u1Size)
     3635                return pCmdHlp->pfnExec(pCmdHlp, "dpd%s %Dv L3", &pCmd->pszCmd[3], &VarGCPtr);
     3636
     3637            iEntry = (VarGCPtr.u.GCFlat >> X86_PT_SHIFT) & X86_PT_MASK;
     3638            VarPTEAddr = VarCur;
     3639            VarPTEAddr.u.u64Number = Pde.u & X86_PDE_PG_MASK;
     3640            VarPTEAddr.u.u64Number += iEntry * sizeof(X86PTE);
     3641        }
     3642        cEntriesMax = (PAGE_SIZE - iEntry) / cbEntry;
     3643        iEntry /= cbEntry;
     3644    }
     3645
     3646    /* adjust cEntries */
     3647    cEntries = RT_MAX(1, cEntries);
     3648    cEntries = RT_MIN(cEntries, cEntriesMax);
     3649
     3650    /*
     3651     * The display loop.
     3652     */
     3653    DBGCCmdHlpPrintf(pCmdHlp, iEntry != ~0U ? "%DV (base %DV / index %#x):\n" : "%DV:\n",
     3654                     &VarPTEAddr, &VarGCPtr, iEntry);
     3655    do
    34543656    {
    34553657        /*
    34563658         * Read.
    34573659         */
    3458         VBOXPTE Pte;
    3459         rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pte, sizeof(Pte), &VarPTEAddr, NULL);
     3660        X86PTEPAE Pte;
     3661        Pte.u = 0;
     3662        rc = pCmdHlp->pfnMemRead(pCmdHlp, pVM, &Pte, cbEntry, &VarPTEAddr, NULL);
    34603663        if (VBOX_FAILURE(rc))
    3461             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "Reading memory at %DV.\n", &VarPTEAddr);
     3664            return DBGCCmdHlpVBoxError(pCmdHlp, rc, "Reading PTE memory at %DV.\n", &VarPTEAddr);
    34623665
    34633666        /*
    34643667         * Display.
    34653668         */
    3466         if (off != ~0U)
    3467         {
    3468             rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "%03x %DV: ", off, &VarGCPtr);
    3469             off++;
    3470         }
    3471         rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
    3472             "%08x 4kb phys=%08x %s %s %s %s %s avl=%02x %s %s %s %s\n",
    3473             Pte.u, Pte.n.u20PageNo << PAGE_SHIFT, Pte.n.u1Present ? "p " : "np", Pte.n.u1Write ? "w" : "r",
    3474             Pte.n.u1User ? "u" : "s", Pte.n.u1Accessed ? "a " : "na", Pte.n.u1Dirty ? "d " : "nd",
    3475             Pte.n.u3Available, Pte.n.u1Global ? "G" : " ", Pte.n.u1WriteThru ? "pwt" : "   ",
    3476             Pte.n.u1CacheDisable ? "pcd" : "   ", Pte.n.u1PAT ? "pat" : "   ");
     3669        if (iEntry != ~0U)
     3670        {
     3671            DBGCCmdHlpPrintf(pCmdHlp, "%03x %DV: ", iEntry, &VarGCPtr);
     3672            iEntry++;
     3673        }
     3674        DBGCCmdHlpPrintf(pCmdHlp,
     3675                         fPAE
     3676                         ? "%016llx 4kb phys=%016llx %s %s %s %s %s avl=%02x %s %s %s %s %s"
     3677                         :   "%08llx 4kb phys=%08llx %s %s %s %s %s avl=%02x %s %s %s %s %s",
     3678                         Pte.u,
     3679                         Pte.u & X86_PTE_PAE_PG_MASK,
     3680                         Pte.n.u1Present         ? "p " : "np",
     3681                         Pte.n.u1Write           ? "w" : "r",
     3682                         Pte.n.u1User            ? "u" : "s",
     3683                         Pte.n.u1Accessed        ? "a " : "na",
     3684                         Pte.n.u1Dirty           ? "d " : "nd",
     3685                         Pte.n.u3Available,
     3686                         Pte.n.u1Global          ? (fPGE ? "g" : "G") : " ",
     3687                         Pte.n.u1WriteThru       ? "pwt" : "   ",
     3688                         Pte.n.u1CacheDisable    ? "pcd" : "   ",
     3689                         Pte.n.u1PAT             ? "pat" : "   ",
     3690                         Pte.n.u1NoExecute       ? (fNXE ? "nx" : "NX") : "  "
     3691                         );
     3692        if (Pte.u & UINT64_C(0x7fff000000000000))
     3693            DBGCCmdHlpPrintf(pCmdHlp, " weird=%RX64", (Pte.u & UINT64_C(0x7fff000000000000)));
     3694        rc = DBGCCmdHlpPrintf(pCmdHlp, "\n");
    34773695        if (VBOX_FAILURE(rc))
    34783696            return rc;
    34793697
    34803698        /*
    3481          * Next
     3699         * Advance.
    34823700         */
    3483         if (cEntries-- <= 1)
    3484             break;
    3485         rc = pCmdHlp->pfnEval(pCmdHlp, &VarPTEAddr, "%DV + %#x", &VarPTEAddr, sizeof(VBOXPDE));
    3486         if (VBOX_FAILURE(rc))
    3487             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%DV + %#x", &VarPTEAddr, sizeof(VBOXPDE));
    3488         rc = pCmdHlp->pfnEval(pCmdHlp, &VarGCPtr, "%DV + %#x", &VarGCPtr, PAGE_SIZE);
    3489         if (VBOX_FAILURE(rc))
    3490             return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "%DV + %#x", &VarGCPtr, sizeof(VBOXPDE));
    3491     }
     3701        VarPTEAddr.u.u64Number += cbEntry;
     3702        if (iEntry != ~0U)
     3703            VarGCPtr.u.GCFlat += PAGE_SIZE;
     3704    } while (cEntries-- > 0);
    34923705
    34933706    NOREF(pResult);
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