VirtualBox

Changeset 17432 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 6, 2009 2:04:24 AM (16 years ago)
Author:
vboxsync
Message:

PGM,GMM: Filling in missing bits and fixing some bugs.

Location:
trunk/src/VBox/VMM
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/GMM.cpp

    r17368 r17432  
    160160        return VERR_NO_TMP_MEMORY;
    161161
    162     pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    163     pReq->Hdr.cbReq = cb;
    164     pReq->enmAccount = enmAccount;
    165     pReq->cPages = cPages;
     162    pReq->Hdr.u32Magic  = SUPVMMR0REQHDR_MAGIC;
     163    pReq->Hdr.cbReq     = cb;
     164    pReq->enmAccount    = enmAccount;
     165    pReq->cPages        = cPages;
    166166    NOREF(pVM);
     167    *ppReq = pReq;
    167168    return VINF_SUCCESS;
     169}
     170
     171
     172/**
     173 * Re-prepares a GMMR0FreePages request.
     174 *
     175 * @returns VINF_SUCCESS or VERR_NO_TMP_MEMORY.
     176 * @param       pVM         Pointer to the shared VM structure.
     177 * @param       pReq        A request buffer previously returned by
     178 *                          GMMR3FreePagesPrepare().
     179 * @param       cPages      The number of pages originally passed to
     180 *                          GMMR3FreePagesPrepare().
     181 * @param       enmAccount  The account to charge.
     182 */
     183GMMR3DECL(void) GMMR3FreePagesRePrep(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cPages, GMMACCOUNT enmAccount)
     184{
     185    Assert(pReq->Hdr.u32Magic == SUPVMMR0REQHDR_MAGIC);
     186    pReq->Hdr.cbReq     = RT_OFFSETOF(GMMFREEPAGESREQ, aPages[cPages]);
     187    pReq->enmAccount    = enmAccount;
     188    pReq->cPages        = cPages;
     189    NOREF(pVM);
    168190}
    169191
     
    174196 *
    175197 * @returns VBox status code.
    176  * @param   pVM         Pointer to the shared VM structure.
    177  * @param   pReq        Pointer to the request (returned by GMMR3FreePagesPrepare).
    178  */
    179 GMMR3DECL(int) GMMR3FreePagesPerform(PVM pVM, PGMMFREEPAGESREQ pReq)
    180 {
     198 * @param   pVM             Pointer to the shared VM structure.
     199 * @param   pReq            Pointer to the request (returned by GMMR3FreePagesPrepare).
     200 * @param   cActualPages    The number of pages actually freed.
     201 */
     202GMMR3DECL(int) GMMR3FreePagesPerform(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cActualPages)
     203{
     204    /*
     205     * Adjust the request if we ended up with fewer pages than anticipated.
     206     */
     207    if (cActualPages != pReq->cPages)
     208    {
     209        AssertReturn(cActualPages < pReq->cPages, VERR_INTERNAL_ERROR);
     210        if (!cActualPages)
     211            return VINF_SUCCESS;
     212        pReq->cPages = cActualPages;
     213        pReq->Hdr.cbReq = RT_OFFSETOF(GMMFREEPAGESREQ, aPages[cActualPages]);
     214    }
     215
     216    /*
     217     * Do the job.
     218     */
    181219    int rc = VMMR3CallR0(pVM, VMMR0_DO_GMM_FREE_PAGES, 0, &pReq->Hdr);
    182220    if (RT_SUCCESS(rc))
  • trunk/src/VBox/VMM/PGMHandler.cpp

    r17132 r17432  
    9797    if (!pszModRC)
    9898        pszModRC = VMMGC_MAIN_MODULE_NAME;
    99 
    10099    if (!pszModR0)
    101100        pszModR0 = VMMR0_MAIN_MODULE_NAME;
     101#ifdef VBOX_WITH_NEW_PHYS_CODE
     102    AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER);
     103    AssertPtrReturn(pszHandlerR0, VERR_INVALID_POINTER);
     104    AssertPtrReturn(pszHandlerRC, VERR_INVALID_POINTER);
     105#endif
    102106
    103107    /*
     
    106110    R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0 = NIL_RTR0PTR;
    107111    int rc = VINF_SUCCESS;
    108     if (pszHandlerR0)
    109         rc = PDMR3LdrGetSymbolR0Lazy(pVM, pszModR0, pszHandlerR0, &pfnHandlerR0);
     112#ifndef VBOX_WITH_NEW_PHYS_CODE
     113  if (pszHandlerR0)
     114#endif
     115    rc = PDMR3LdrGetSymbolR0Lazy(pVM, pszModR0, pszHandlerR0, &pfnHandlerR0);
    110116    if (RT_SUCCESS(rc))
    111117    {
     
    114120         */
    115121        RTRCPTR pfnHandlerRC = NIL_RTRCPTR;
    116         if (pszHandlerRC)
    117             rc = PDMR3LdrGetSymbolRCLazy(pVM, pszModRC, pszHandlerRC, &pfnHandlerRC);
     122#ifndef VBOX_WITH_NEW_PHYS_CODE
     123      if (pszHandlerRC)
     124#endif
     125        rc = PDMR3LdrGetSymbolRCLazy(pVM, pszModRC, pszHandlerRC, &pfnHandlerRC);
    118126
    119127        if (RT_SUCCESS(rc))
     
    290298    {
    291299        case PGMVIRTHANDLERTYPE_ALL:
     300            AssertReleaseMsgFailedReturn(("PGMVIRTHANDLERTYPE_ALL: not implemented\n"), VERR_NOT_IMPLEMENTED);
     301            break;
    292302        case PGMVIRTHANDLERTYPE_WRITE:
    293303            if (!pfnHandlerR3)
  • trunk/src/VBox/VMM/PGMInternal.h

    r17421 r17432  
    10551055typedef PGMRAMRANGE *PPGMRAMRANGE;
    10561056
     1057#ifndef VBOX_WITH_NEW_PHYS_CODE
    10571058/** Return hc ptr corresponding to the ram range and physical offset */
    10581059#define PGMRAMRANGE_GETHCPTR(pRam, off) \
    10591060    (pRam->fFlags & MM_RAM_FLAGS_DYNAMIC_ALLOC) ? (RTHCPTR)((pRam)->paChunkR3Ptrs[(off) >> PGM_DYNAMIC_CHUNK_SHIFT] + ((off) & PGM_DYNAMIC_CHUNK_OFFSET_MASK)) \
    10601061                                                : (RTHCPTR)((RTR3UINTPTR)(pRam)->pvR3 + (off));
     1062#endif
    10611063
    10621064/**
     
    30403042
    30413043
    3042 void            pgmPhysFreePage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys);
    30433044int             pgmPhysPageLoadIntoTlb(PPGM pPGM, RTGCPHYS GCPhys);
    30443045int             pgmPhysPageLoadIntoTlbWithPage(PPGM pPGM, PPGMPAGE pPage, RTGCPHYS GCPhys);
  • trunk/src/VBox/VMM/PGMPhys.cpp

    r17421 r17432  
    4747
    4848/*******************************************************************************
     49*   Defined Constants And Macros                                               *
     50*******************************************************************************/
     51/** The number of pages to free in one batch. */
     52#define PGMPHYS_FREE_PAGE_BATCH_SIZE    128
     53
     54
     55/*******************************************************************************
    4956*   Internal Functions                                                         *
    5057*******************************************************************************/
    5158static DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
    52 
     59static int pgmPhysFreePage(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t *pcPendingPages, PPGMPAGE pPage, RTGCPHYS GCPhys);
    5360
    5461
     
    284291int pgmR3PhysRamReset(PVM pVM)
    285292{
     293#ifdef VBOX_WITH_NEW_PHYS_CODE
     294    /*
     295     * We batch up pages before freeing them.
     296     */
     297    uint32_t            cPendingPages = 0;
     298    PGMMFREEPAGESREQ    pReq;
     299    int rc = GMMR3FreePagesPrepare(pVM, &pReq, PGMPHYS_FREE_PAGE_BATCH_SIZE, GMMACCOUNT_BASE);
     300    AssertLogRelRCReturn(rc, rc);
     301#endif
     302
    286303    /*
    287304     * Walk the ram ranges.
     
    291308        uint32_t    iPage = pRam->cb >> PAGE_SHIFT; Assert((RTGCPHYS)iPage << PAGE_SHIFT == pRam->cb);
    292309#ifdef VBOX_WITH_NEW_PHYS_CODE
    293         int         rc;
    294310        if (!pVM->pgm.s.fRamPreAlloc)
    295311        {
     
    302318                    case PGMPAGETYPE_RAM:
    303319                        if (!PGM_PAGE_IS_ZERO(pPage))
    304                             pgmPhysFreePage(pVM, pPage, pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT));
     320                        {
     321                            rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPage, pRam->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT));
     322                            AssertLogRelRCReturn(rc, rc);
     323                        }
    305324                        break;
    306325
     
    379398    }
    380399
     400#ifdef VBOX_WITH_NEW_PHYS_CODE
     401    /*
     402     * Finish off any pages pending freeing.
     403     */
     404    if (cPendingPages)
     405    {
     406        rc = GMMR3FreePagesPerform(pVM, pReq, cPendingPages);
     407        AssertLogRelRCReturn(rc, rc);
     408    }
     409    GMMR3FreePagesCleanup(pReq);
     410#endif
     411
     412
    381413    return VINF_SUCCESS;
    382414}
     
    910942    if (fRamExists)
    911943    {
     944        uint32_t            cPendingPages = 0;
     945        PGMMFREEPAGESREQ    pReq;
     946        int rc = GMMR3FreePagesPrepare(pVM, &pReq, PGMPHYS_FREE_PAGE_BATCH_SIZE, GMMACCOUNT_BASE);
     947        AssertLogRelRCReturn(rc, rc);
     948
    912949        /* replace the pages, freeing all present RAM pages. */
    913950        PPGMPAGE pPageSrc = &pCur->RamRange.aPages[0];
     
    916953        while (cPagesLeft-- > 0)
    917954        {
    918             pgmPhysFreePage(pVM, pPageDst, GCPhys);
     955            rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPageDst, GCPhys);
     956            AssertLogRelRCReturn(rc, rc); /* We're done for if this goes wrong. */
    919957
    920958            RTHCPHYS const HCPhys = PGM_PAGE_GET_HCPHYS(pPageSrc);
     
    927965            pPageDst++;
    928966        }
     967
     968        if (cPendingPages)
     969        {
     970            rc = GMMR3FreePagesPerform(pVM, pReq, cPendingPages);
     971            AssertLogRelRCReturn(rc, rc);
     972        }
     973        GMMR3FreePagesCleanup(pReq);
    929974    }
    930975    else
     
    9811026            pRam = pRam->pNextR3;
    9821027
    983 #ifdef RT_STRICT
    9841028        RTHCPHYS const HCPhysZeroPg = pVM->pgm.s.HCPhysZeroPg;
    985 #endif
    9861029        Assert(HCPhysZeroPg != 0 && HCPhysZeroPg != NIL_RTHCPHYS);
    9871030        PPGMPAGE pPageDst = &pRam->aPages[(pCur->RamRange.GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
     
    9891032        while (cPagesLeft-- > 0)
    9901033        {
    991             PGM_PAGE_SET_HCPHYS(pPageDst, pVM->pgm.s.HCPhysZeroPg);
     1034            PGM_PAGE_SET_HCPHYS(pPageDst, HCPhysZeroPg);
    9921035            PGM_PAGE_SET_TYPE(pPageDst, PGMPAGETYPE_RAM);
    9931036            PGM_PAGE_SET_STATE(pPageDst, PGM_PAGE_STATE_ZERO);
     1037            PGM_PAGE_SET_PAGEID(pPageDst, NIL_GMM_PAGEID);
    9941038
    9951039            pPageDst++;
     
    14541498static DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
    14551499{
    1456     PPGMROMRANGE    pRom = (PPGMROMRANGE)pvUser;
    1457     const uint32_t  iPage = GCPhys - pRom->GCPhys;
     1500    PPGMROMRANGE    pRom     = (PPGMROMRANGE)pvUser;
     1501    const uint32_t  iPage    = (GCPhys - pRom->GCPhys) >> PAGE_SHIFT;
    14581502    Assert(iPage < (pRom->cb >> PAGE_SHIFT));
    14591503    PPGMROMPAGE     pRomPage = &pRom->aPages[iPage];
     
    15661610                        }
    15671611
    1568                     rc = GMMR3FreePagesPerform(pVM, pReq);
     1612                    rc = GMMR3FreePagesPerform(pVM, pReq, cDirty);
    15691613                    GMMR3FreePagesCleanup(pReq);
    15701614                    AssertRCReturn(rc, rc);
     
    24562500
    24572501/**
     2502 * Frees the specified RAM page and replaces it with the ZERO page.
     2503 *
     2504 * This is used by ballooning, remapping MMIO2 and RAM reset.
     2505 *
     2506 * @param   pVM         Pointer to the shared VM structure.
     2507 * @param   pReq        Pointer to the request.
     2508 * @param   pPage       Pointer to the page structure.
     2509 * @param   GCPhys      The guest physical address of the page, if applicable.
     2510 *
     2511 * @remarks The caller must own the PGM lock.
     2512 */
     2513static int pgmPhysFreePage(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t *pcPendingPages, PPGMPAGE pPage, RTGCPHYS GCPhys)
     2514{
     2515    /*
     2516     * Assert sanity.
     2517     */
     2518    Assert(PDMCritSectIsOwner(&pVM->pgm.s.CritSect));
     2519    if (RT_UNLIKELY(PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_RAM))
     2520    {
     2521        AssertMsgFailed(("GCPhys=%RGp pPage=%R[pgmpage]\n", GCPhys, pPage));
     2522        return VMSetError(pVM, VERR_PGM_PHYS_NOT_RAM, RT_SRC_POS, "GCPhys=%RGp type=%d", GCPhys, PGM_PAGE_GET_TYPE(pPage));
     2523    }
     2524
     2525    if (PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ZERO)
     2526        return VINF_SUCCESS;
     2527
     2528    const uint32_t idPage = PGM_PAGE_GET_PAGEID(pPage);
     2529    if (RT_UNLIKELY(    idPage == NIL_GMM_PAGEID
     2530                    ||  idPage > GMM_PAGEID_LAST
     2531                    ||  PGM_PAGE_GET_CHUNKID(pPage) == NIL_GMM_CHUNKID))
     2532    {
     2533        AssertMsgFailed(("GCPhys=%RGp pPage=%R[pgmpage]\n", GCPhys, pPage));
     2534        return VMSetError(pVM, VERR_PGM_PHYS_INVALID_PAGE_ID, RT_SRC_POS, "GCPhys=%RGp idPage=%#x", GCPhys, pPage);
     2535    }
     2536
     2537    /*
     2538     * pPage = ZERO page.
     2539     */
     2540    PGM_PAGE_SET_HCPHYS(pPage, pVM->pgm.s.HCPhysZeroPg);
     2541    PGM_PAGE_SET_STATE(pPage, PGM_PAGE_STATE_ZERO);
     2542    PGM_PAGE_SET_PAGEID(pPage, NIL_GMM_PAGEID);
     2543
     2544    /*
     2545     * Make sure it's not in the handy page array.
     2546     */
     2547    uint32_t i = pVM->pgm.s.cHandyPages;
     2548    while (i < RT_ELEMENTS(pVM->pgm.s.aHandyPages))
     2549    {
     2550        if (pVM->pgm.s.aHandyPages[i].idPage == idPage)
     2551        {
     2552            pVM->pgm.s.aHandyPages[i].idPage = NIL_GMM_PAGEID;
     2553            break;
     2554        }
     2555        if (pVM->pgm.s.aHandyPages[i].idSharedPage == idPage)
     2556        {
     2557            pVM->pgm.s.aHandyPages[i].idSharedPage = NIL_GMM_PAGEID;
     2558            break;
     2559        }
     2560        i++;
     2561    }
     2562
     2563    /*
     2564     * Push it onto the page array.
     2565     */
     2566    uint32_t iPage = *pcPendingPages;
     2567    Assert(iPage < PGMPHYS_FREE_PAGE_BATCH_SIZE);
     2568    *pcPendingPages += 1;
     2569
     2570    pReq->aPages[iPage].idPage = idPage;
     2571
     2572    if (iPage + 1 < PGMPHYS_FREE_PAGE_BATCH_SIZE)
     2573        return VINF_SUCCESS;
     2574
     2575    /*
     2576     * Flush the pages.
     2577     */
     2578    int rc = GMMR3FreePagesPerform(pVM, pReq, PGMPHYS_FREE_PAGE_BATCH_SIZE);
     2579    if (RT_SUCCESS(rc))
     2580    {
     2581        GMMR3FreePagesRePrep(pVM, pReq, PGMPHYS_FREE_PAGE_BATCH_SIZE, GMMACCOUNT_BASE);
     2582        *pcPendingPages = 0;
     2583    }
     2584    return rc;
     2585}
     2586
     2587
     2588/**
    24582589 * Converts a GC physical address to a HC ring-3 pointer, with some
    24592590 * additional checks.
     
    25092640                {
    25102641                    case PGM_PAGE_STATE_ALLOCATED:
     2642                        break;
    25112643                    case PGM_PAGE_STATE_ZERO:
    2512                         break;
    25132644                    case PGM_PAGE_STATE_SHARED:
    25142645                    case PGM_PAGE_STATE_WRITE_MONITORED:
     
    25252656            /** @todo mapping/locking hell; this isn't horribly efficient since
    25262657             *        pgmPhysPageLoadIntoTlb will repeate the lookup we've done here. */
    2527         }
     2658
     2659            Log6(("PGMR3PhysTlbGCPhys2Ptr: GCPhys=%RGp rc=%Rrc pPage=%R[pgmpage] *ppv=%p\n", GCPhys, rc, pPage, *ppv));
     2660        }
     2661        else
     2662            Log6(("PGMR3PhysTlbGCPhys2Ptr: GCPhys=%RGp rc=%Rrc pPage=%R[pgmpage]\n", GCPhys, rc, pPage));
     2663
    25282664        /* else: handler catching all access, no pointer returned. */
    25292665
  • trunk/src/VBox/VMM/VMMAll/PGMAll.cpp

    r17345 r17432  
    24622462VMMDECL(int) PGMRegisterStringFormatTypes(void)
    24632463{
    2464 #ifdef LOG_ENABLED
     2464#if !defined(IN_R0) || defined(LOG_ENABLED)
    24652465    int         rc = VINF_SUCCESS;
    24662466    unsigned    i;
     
    24962496VMMDECL(void) PGMDeregisterStringFormatTypes(void)
    24972497{
    2498 #ifdef LOG_ENABLED
     2498#if !defined(IN_R0) || defined(LOG_ENABLED)
    24992499    for (unsigned i = 0; i < RT_ELEMENTS(g_aPgmFormatTypes); i++)
    25002500        RTStrFormatTypeDeregister(g_aPgmFormatTypes[i].szType);
  • trunk/src/VBox/VMM/VMMAll/PGMAllBth.h

    r17422 r17432  
    45094509    int rc = VERR_INTERNAL_ERROR;
    45104510#  else
     4511    pgmLock(pVM);
    45114512    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhysCR3);
    45124513    AssertReturn(pPage, VERR_INTERNAL_ERROR);
    45134514    int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhysCR3 & GST_CR3_PAGE_MASK, (void **)&HCPtrGuestCR3);
    45144515    HCPhysGuestCR3 = PGM_PAGE_GET_HCPHYS(pPage);
     4516    pgmUnlock(pVM);
    45154517#  endif
    45164518# else  /* !VBOX_WITH_NEW_PHYS_CODE */
     
    45584560                    int rc2 = VERR_INTERNAL_ERROR;
    45594561#   else
     4562                    pgmLock(pVM);
    45604563                    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
    45614564                    AssertReturn(pPage, VERR_INTERNAL_ERROR);
    45624565                    int rc2 = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, (void **)&HCPtr);
    45634566                    HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
     4567                    pgmUnlock(pVM);
    45644568#   endif
    45654569#  else  /* !VBOX_WITH_NEW_PHYS_CODE */
  • trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp

    r17372 r17432  
    7474 * @param   pfnHandlerR0    The R0 handler.
    7575 * @param   pvUserR0        User argument to the R0 handler.
    76  * @param   pfnHandlerGC    The RC handler.
     76 * @param   pfnHandlerRC    The RC handler.
    7777 * @param   pvUserRC        User argument to the RC handler. This can be a value
    7878 *                          less that 0x10000 or a (non-null) pointer that is
     
    9595    switch (enmType)
    9696    {
     97        case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE:
     98            break;
    9799        case PGMPHYSHANDLERTYPE_MMIO:
    98         case PGMPHYSHANDLERTYPE_PHYSICAL_WRITE:
    99100        case PGMPHYSHANDLERTYPE_PHYSICAL_ALL:
     101            /* Simplification in PGMPhysRead among other places. */
     102            AssertMsgReturn(!(GCPhys & PAGE_OFFSET_MASK), ("%RGp\n", GCPhys), VERR_INVALID_PARAMETER);
     103            AssertMsgReturn((GCPhysLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK, ("%RGp\n", GCPhysLast), VERR_INVALID_PARAMETER);
    100104            break;
    101105        default:
     
    107111                    ("Not RC pointer! pvUserRC=%RRv\n", pvUserRC),
    108112                    VERR_INVALID_PARAMETER);
     113    AssertMsgReturn(    (RTR0UINTPTR)pvUserR0 < 0x10000
     114                    ||  MMHyperR3ToR0(pVM, MMHyperR0ToR3(pVM, pvUserR0)) == pvUserR0,
     115                    ("Not R0 pointer! pvUserR0=%RHv\n", pvUserR0),
     116                    VERR_INVALID_PARAMETER);
     117#ifdef VBOX_WITH_NEW_PHYS_CODE
     118    AssertPtrReturn(pfnHandlerR3, VERR_INVALID_POINTER);
     119    AssertReturn(pfnHandlerR0, VERR_INVALID_PARAMETER);
     120    AssertReturn(pfnHandlerRC, VERR_INVALID_PARAMETER);
     121#else
    109122    AssertReturn(pfnHandlerR3 || pfnHandlerR0 || pfnHandlerRC, VERR_INVALID_PARAMETER);
     123#endif
    110124
    111125    /*
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r17423 r17432  
    258258
    259259/**
    260  * Frees the specified RAM page.
    261  *
    262  * This is used by ballooning and remapping MMIO2.
    263  *
    264  * @param   pVM         Pointer to the shared VM structure.
    265  * @param   pPage       Pointer to the page structure.
    266  * @param   GCPhys      The guest physical address of the page, if applicable.
    267  */
    268 void pgmPhysFreePage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys)
    269 {
    270     AssertFatal(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM);
    271 
    272     /** @todo implement this... */
    273     AssertFatalFailed();
    274 }
    275 
    276 
    277 /**
    278260 * Makes sure that there is at least one handy page ready for use.
    279261 *
     
    380362int pgmPhysAllocPage(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys)
    381363{
     364    LogFlow(("pgmPhysAllocPage: %R[pgmpage] %RGp\n", pPage, GCPhys));
     365
    382366    /*
    383367     * Ensure that we've got a page handy, take it and use it.
     
    407391     */
    408392    const RTHCPHYS HCPhys = pVM->pgm.s.aHandyPages[iHandyPage].HCPhysGCPhys;
    409     pVM->pgm.s.aHandyPages[iHandyPage].HCPhysGCPhys = GCPhys;
     393    pVM->pgm.s.aHandyPages[iHandyPage].HCPhysGCPhys = GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK;
    410394
    411395    if (PGM_PAGE_IS_SHARED(pPage))
     
    952936            PPGMPAGEMAP pMap = pTlbe->pMap;
    953937            pMap->cRefs++;
    954 #if 0 /** @Todo implement locking properly */
     938#if 0 /** @todo implement locking properly */
    955939            if (RT_LIKELY(pPage->cLocks != PGM_PAGE_MAX_LOCKS))
    956940                if (RT_UNLIKELY(++pPage->cLocks == PGM_PAGE_MAX_LOCKS))
     
    10411025VMMDECL(int) PGMPhysGCPtr2CCPtr(PVM pVM, RTGCPTR GCPtr, void **ppv, PPGMPAGEMAPLOCK pLock)
    10421026{
     1027    VM_ASSERT_EMT(pVM);
    10431028    RTGCPHYS GCPhys;
    10441029    int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, &GCPhys);
     
    10741059VMMDECL(int) PGMPhysGCPtr2CCPtrReadOnly(PVM pVM, RTGCPTR GCPtr, void const **ppv, PPGMPAGEMAPLOCK pLock)
    10751060{
     1061    VM_ASSERT_EMT(pVM);
    10761062    RTGCPHYS GCPhys;
    10771063    int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, &GCPhys);
     
    11571143    AssertFailedReturn(VERR_NOT_IMPLEMENTED);
    11581144# else
     1145    pgmLock(pVM);
     1146
    11591147    PPGMRAMRANGE pRam;
    11601148    PPGMPAGE pPage;
    11611149    int rc = pgmPhysGetPageAndRangeEx(&pVM->pgm.s, GCPhys, &pPage, &pRam);
    1162     if (RT_FAILURE(rc))
    1163         return rc;
    1164 
    1165     void *pv;
    1166     rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pv);
    1167     if (RT_FAILURE(rc))
    1168         return rc;
    1169     *pR3Ptr = (RTR3PTR)pv;
    1170     return VINF_SUCCESS;
     1150    if (RT_SUCCESS(rc))
     1151        rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, (void **)&pR3Ptr);
     1152
     1153    pgmUnlock(pVM);
     1154    Assert(rc <= VINF_SUCCESS);
     1155    return rc;
    11711156# endif
    11721157
     
    12831268 * @param   GCPtr       The guest pointer to convert.
    12841269 * @param   pR3Ptr      Where to store the R3 virtual address.
     1270 *
     1271 * @deprecated
    12851272 */
    12861273VMMDECL(int) PGMPhysGCPtr2R3Ptr(PVM pVM, RTGCPTR GCPtr, PRTR3PTR pR3Ptr)
     
    12981285
    12991286
    1300 /**
    1301  * Converts a guest virtual address to a HC ring-3 pointer by specfied CR3 and
    1302  * flags.
    1303  *
    1304  * @returns VBox status code.
    1305  * @param   pVM         The VM Handle
    1306  * @param   GCPtr       The guest pointer to convert.
    1307  * @param   cr3         The guest CR3.
    1308  * @param   fFlags      Flags used for interpreting the PD correctly: X86_CR4_PSE and X86_CR4_PAE
    1309  * @param   pR3Ptr      Where to store the R3 pointer.
    1310  *
    1311  * @remark  This function is used by the REM at a time where PGM could
    1312  *          potentially not be in sync. It could also be used by a
    1313  *          future DBGF API to cpu state independent conversions.
    1314  */
    1315 VMMDECL(int) PGMPhysGCPtr2R3PtrByGstCR3(PVM pVM, RTGCPTR GCPtr, uint64_t cr3, unsigned fFlags, PRTR3PTR pR3Ptr)
    1316 {
    1317 #ifdef VBOX_WITH_NEW_PHYS_CODE
    1318     VM_ASSERT_EMT(pVM); /* no longer safe for use outside the EMT thread! */
    1319 #endif
    1320     /*
    1321      * PAE or 32-bit?
    1322      */
    1323     Assert(!CPUMIsGuestInLongMode(pVM));
    1324 
    1325     int rc;
    1326     if (!(fFlags & X86_CR4_PAE))
    1327     {
    1328         PX86PD pPD;
    1329         rc = PGM_GCPHYS_2_PTR(pVM, cr3 & X86_CR3_PAGE_MASK, &pPD);
    1330         if (RT_SUCCESS(rc))
    1331         {
    1332             X86PDE Pde = pPD->a[(RTGCUINTPTR)GCPtr >> X86_PD_SHIFT];
    1333             if (Pde.n.u1Present)
    1334             {
    1335                 if ((fFlags & X86_CR4_PSE) && Pde.b.u1Size)
    1336                 {   /* (big page) */
    1337                     rc = PGMPhysGCPhys2R3Ptr(pVM, pgmGstGet4MBPhysPage(&pVM->pgm.s, Pde) | ((RTGCUINTPTR)GCPtr & X86_PAGE_4M_OFFSET_MASK),
    1338                                              1 /* we always stay within one page */, pR3Ptr);
    1339                 }
    1340                 else
    1341                 {   /* (normal page) */
    1342                     PX86PT pPT;
    1343                     rc = PGM_GCPHYS_2_PTR(pVM, Pde.u & X86_PDE_PG_MASK, &pPT);
    1344                     if (RT_SUCCESS(rc))
    1345                     {
    1346                         X86PTE Pte = pPT->a[((RTGCUINTPTR)GCPtr >> X86_PT_SHIFT) & X86_PT_MASK];
    1347                         if (Pte.n.u1Present)
    1348                             return PGMPhysGCPhys2R3Ptr(pVM, (Pte.u & X86_PTE_PG_MASK) | ((RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK),
    1349                                                        1 /* we always stay within one page */, pR3Ptr);
    1350                         rc = VERR_PAGE_NOT_PRESENT;
    1351                     }
    1352                 }
    1353             }
    1354             else
    1355                 rc = VERR_PAGE_TABLE_NOT_PRESENT;
    1356         }
    1357     }
    1358     else
    1359     {
    1360         /** @todo long mode! */
    1361         Assert(PGMGetGuestMode(pVM) < PGMMODE_AMD64);
    1362 
    1363         PX86PDPT pPdpt;
    1364         rc = PGM_GCPHYS_2_PTR(pVM, cr3 & X86_CR3_PAE_PAGE_MASK, &pPdpt);
    1365         if (RT_SUCCESS(rc))
    1366         {
    1367             X86PDPE Pdpe = pPdpt->a[((RTGCUINTPTR)GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE];
    1368             if (Pdpe.n.u1Present)
    1369             {
    1370                 PX86PDPAE pPD;
    1371                 rc = PGM_GCPHYS_2_PTR(pVM, Pdpe.u & X86_PDPE_PG_MASK, &pPD);
    1372                 if (RT_SUCCESS(rc))
    1373                 {
    1374                     X86PDEPAE Pde = pPD->a[((RTGCUINTPTR)GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK];
    1375                     if (Pde.n.u1Present)
    1376                     {
    1377                         if ((fFlags & X86_CR4_PSE) && Pde.b.u1Size)
    1378                         {   /* (big page) */
    1379                             rc = PGMPhysGCPhys2R3Ptr(pVM, (Pde.u & X86_PDE2M_PAE_PG_MASK) | ((RTGCUINTPTR)GCPtr & X86_PAGE_2M_OFFSET_MASK),
    1380                                                      1 /* we always stay within one page */, pR3Ptr);
    1381                         }
    1382                         else
    1383                         {   /* (normal page) */
    1384                             PX86PTPAE pPT;
    1385                             rc = PGM_GCPHYS_2_PTR(pVM, (Pde.u & X86_PDE_PAE_PG_MASK), &pPT);
    1386                             if (RT_SUCCESS(rc))
    1387                             {
    1388                                 X86PTEPAE Pte = pPT->a[((RTGCUINTPTR)GCPtr >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK];
    1389                                 if (Pte.n.u1Present)
    1390                                     return PGMPhysGCPhys2R3Ptr(pVM, (Pte.u & X86_PTE_PAE_PG_MASK) | ((RTGCUINTPTR)GCPtr & PAGE_OFFSET_MASK),
    1391                                                                1 /* we always stay within one page */, pR3Ptr);
    1392                                 rc = VERR_PAGE_NOT_PRESENT;
    1393                             }
    1394                         }
    1395                     }
    1396                     else
    1397                         rc = VERR_PAGE_TABLE_NOT_PRESENT;
    1398                 }
    1399             }
    1400             else
    1401                 rc = VERR_PAGE_TABLE_NOT_PRESENT;
    1402         }
    1403     }
    1404     return rc;
    1405 }
    1406 
    14071287
    14081288#undef LOG_GROUP
     
    14391319#endif /* IN_RING3 */
    14401320
    1441 
    14421321#ifdef VBOX_WITH_NEW_PHYS_CODE
     1322
    14431323/**
    14441324 * Deals with reading from a page with one or more ALL access handlers.
     
    14481328 * @param   GCPhys      The physical address to start reading at.
    14491329 * @param   pvBuf       Where to put the bits we read.
    1450  * @param   cbRead      How much to read - less or equal to a page.
    1451  */
    1452 static void pgmPhysReadHandler(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
    1453 {
    1454     AssertFailed();
     1330 * @param   cb          How much to read - less or equal to a page.
     1331 */
     1332static void pgmPhysReadHandler(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void *pvBuf, size_t cb)
     1333{
     1334    /*
     1335     * The most frequent access here is MMIO and shadowed ROM.
     1336     *
     1337     * The current code ASSUMES all these access handlers are page sized
     1338     * and that we do NOT use any virtual ones.
     1339     */
     1340    if (    PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) == PGM_PAGE_HNDL_PHYS_STATE_ALL
     1341        &&  PGM_PAGE_GET_HNDL_VIRT_STATE(pPage) != PGM_PAGE_HNDL_VIRT_STATE_ALL)
     1342    {
     1343#ifdef IN_RING3
     1344        PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
     1345        AssertReleaseMsg(pCur, ("GCPhys=%RGp cb=%#x\n", GCPhys, cb));
     1346        Assert(GCPhys >= pCur->Core.Key && GCPhys <= pCur->Core.KeyLast);
     1347        Assert(pCur->CTX_SUFF(pfnHandler));
     1348
     1349        const void *pvSrc;
     1350        int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pPage, GCPhys, &pvSrc);
     1351        if (RT_SUCCESS(rc))
     1352        {
     1353            STAM_PROFILE_START(&pCur->Stat, h);
     1354            int rc = pCur->CTX_SUFF(pfnHandler)(pVM, GCPhys, (void *)pvSrc, pvBuf, cb, PGMACCESSTYPE_READ, pCur->CTX_SUFF(pvUser));
     1355            STAM_PROFILE_STOP(&pCur->Stat, h);
     1356            if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
     1357                memcpy(pvBuf, pvSrc, cb);
     1358            else
     1359                AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp\n", rc, GCPhys));
     1360        }
     1361        else
     1362        {
     1363            AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternalReadOnly failed on %RGp / %R[pgmpage] -> %Rrc\n",
     1364                                   GCPhys, pPage, rc));
     1365            memset(pvBuf, 0xff, cb);
     1366        }
     1367#else
     1368        AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cb=%#x\n", GCPhys, cb));
     1369#endif
     1370    }
     1371    else
     1372        AssertReleaseMsgFailed(("ALL access virtual handlers are not implemented here\n"));
    14551373}
    14561374
     
    18361754static void pgmPhysWriteHandler(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void const *pvBuf, size_t cbWrite)
    18371755{
    1838     AssertFailed();
     1756    void *pvDst = NULL;
     1757
     1758    /*
     1759     * Give priority to physical handlers (like #PF does).
     1760     *
     1761     * Hope for a lonely physical handler first that covers the whole
     1762     * write area. This should be a pretty frequent case with MMIO and
     1763     * the heavy usage of full page handlers in the page pool.
     1764     */
     1765    if (!PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage))
     1766    {
     1767        PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
     1768        if (pCur)
     1769        {
     1770            Assert(GCPhys >= pCur->Core.Key && GCPhys <= pCur->Core.KeyLast);
     1771            Assert(pCur->CTX_SUFF(pfnHandler));
     1772
     1773            size_t cbRange = pCur->Core.KeyLast - GCPhys + 1;
     1774            if (cbRange > cbWrite)
     1775                cbRange = cbWrite;
     1776
     1777#ifdef IN_RING3
     1778            int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst);
     1779            if (RT_SUCCESS(rc))
     1780            {
     1781                STAM_PROFILE_START(&pCur->Stat, h);
     1782                rc = pCur->CTX_SUFF(pfnHandler)(pVM, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, pCur->CTX_SUFF(pvUser));
     1783                STAM_PROFILE_STOP(&pCur->Stat, h);
     1784                if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
     1785                    memcpy(pvDst, pvBuf, cbRange);
     1786                else
     1787                    AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp %s\n", rc, GCPhys, pCur->pszDesc));
     1788            }
     1789            else
     1790                AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     1791                                       GCPhys, pPage, rc));
     1792#else
     1793            AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cbRange=%#x\n", GCPhys, cbRange));
     1794#endif
     1795            if (RT_LIKELY(cbRange == cbWrite))
     1796                return;
     1797
     1798            /* more fun to be had below */
     1799            GCPhys  += cbRange;
     1800            cbWrite -= cbRange;
     1801            pvBuf    = (uint8_t *)pvBuf + cbRange;
     1802        }
     1803        /* else: the handler is somewhere else in the page, deal with it below. */
     1804    }
     1805    /*
     1806     * A virtual handler without any interfering physical handlers.
     1807     * Hopefully it'll conver the whole write.
     1808     */
     1809    else if (!PGM_PAGE_HAS_ACTIVE_PHYSICAL_HANDLERS(pPage))
     1810    {
     1811        unsigned        iPage;
     1812        PPGMVIRTHANDLER pCur;
     1813        int rc = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pCur, &iPage);
     1814        if (RT_SUCCESS(rc))
     1815        {
     1816            size_t cbRange = (PAGE_OFFSET_MASK & pCur->Core.KeyLast) - (PAGE_OFFSET_MASK & GCPhys) + 1;
     1817            if (cbRange > cbWrite)
     1818                cbRange = cbWrite;
     1819
     1820#ifdef IN_RING3
     1821            int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst);
     1822            if (RT_SUCCESS(rc))
     1823            {
     1824                rc = VINF_PGM_HANDLER_DO_DEFAULT;
     1825                if (pCur->pfnHandlerR3)
     1826                {
     1827                    RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pCur->Core.Key & PAGE_BASE_GC_MASK)
     1828                                      + (iPage << PAGE_SHIFT)
     1829                                      + (GCPhys & PAGE_OFFSET_MASK);
     1830
     1831                    STAM_PROFILE_START(&pCur->Stat, h);
     1832                    rc = pCur->CTX_SUFF(pfnHandler)(pVM, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, /*pCur->CTX_SUFF(pvUser)*/ NULL);
     1833                    STAM_PROFILE_STOP(&pCur->Stat, h);
     1834                }
     1835                if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
     1836                    memcpy(pvDst, pvBuf, cbRange);
     1837                else
     1838                    AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp %s\n", rc, GCPhys, pCur->pszDesc));
     1839            }
     1840            else
     1841                AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     1842                                       GCPhys, pPage, rc));
     1843#else
     1844            AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cb=%#x\n", GCPhys, cbRange));
     1845#endif
     1846            if (RT_LIKELY(cbRange == cbWrite))
     1847                return;
     1848
     1849            /* more fun to be had below */
     1850            GCPhys  += cbRange;
     1851            cbWrite -= cbRange;
     1852            pvBuf    = (uint8_t *)pvBuf + cbRange;
     1853        }
     1854        /* else: the handler is somewhere else in the page, deal with it below. */
     1855    }
     1856
     1857    /*
     1858     * Deal with all the odd ends.
     1859     */
     1860    while (cbWrite > 0)
     1861    {
     1862        AssertReleaseMsgFailed(("%RGp %#x %R[pgmpage]\n", GCPhys, cbWrite, pPage));
     1863    }
    18391864}
    18401865
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