VirtualBox

Changeset 6854 in vbox


Ignore:
Timestamp:
Feb 7, 2008 7:24:14 PM (17 years ago)
Author:
vboxsync
Message:

All the new ROM stuff. Had to change PGMROMPAGE a bit to make it easier to work with wrt. mapping.

Location:
trunk
Files:
9 edited

Legend:

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

    r6837 r6854  
    289289    PGMROMPROT_READ_RAM_WRITE_IGNORE,
    290290    /** Read from the shadow ROM page, ignore writes.
    291      * Map the shadow page read-write, no access handler. */
     291     * Map the shadow page read-write, disabled write access handler. */
    292292    PGMROMPROT_READ_RAM_WRITE_RAM,
    293293    /** The end of valid values. */
     
    296296    PGMROMPROT_32BIT_HACK = 0x7fffffff
    297297} PGMROMPROT;
     298
     299/**
     300 * Is the ROM mapped (true) or is the shadow RAM mapped (false).
     301 *
     302 * @returns boolean.
     303 * @param   enmProt     The PGMROMPROT value, must be valid.
     304 */
     305#define PGMROMPROT_IS_ROM(enmProt) \
     306    (    (enmProt) == PGMROMPROT_READ_ROM_WRITE_IGNORE \
     307      || (enmProt) == PGMROMPROT_READ_ROM_WRITE_RAM )
    298308
    299309
  • trunk/src/VBox/VMM/PGM.cpp

    r6829 r6854  
    17111711        }
    17121712    }
     1713
     1714#ifdef VBOX_WITH_NEW_PHYS_CODE
     1715    /*
     1716     * Zero shadow ROM pages.
     1717     */
     1718    rc = pgmR3PhysRomReset(pVM);
     1719#endif
    17131720
    17141721    /*
  • trunk/src/VBox/VMM/PGMHandler.cpp

    r5999 r6854  
    7070 * @param   pfnHandlerR3    The R3 handler.
    7171 * @param   pvUserR3        User argument to the R3 handler.
    72  * @param   pszModR0        The R0 handler module. NULL means default R0 module.
     72 * @param   pszModR0        The R0 handler module. NULL means the default R0 module.
    7373 * @param   pszHandlerR0    The R0 handler symbol name.
    7474 * @param   pvUserR0        User argument to the R0 handler.
    75  * @param   pszModGC        The GC handler module. NULL means default GC module.
     75 * @param   pszModGC        The GC handler module. NULL means the default GC module.
    7676 * @param   pszHandlerGC    The GC handler symbol name.
    7777 * @param   pvUserGC        User argument to the GC handler.
  • trunk/src/VBox/VMM/PGMInternal.h

    r6837 r6854  
    481481    /** MMIO2 page. (RWX) */
    482482    PGMPAGETYPE_MMIO2,
    483     /** Shadowed ROM in PGMROMPROT_READ_RAM_WRITE_RAM mode. (RWX) */
    484     PGMPAGETYPE_ROM_RAM,
     483    /** Shadowed ROM. (RWX) */
     484    PGMPAGETYPE_ROM_SHADOW,
    485485    /** ROM page. (R-X) */
    486486    PGMPAGETYPE_ROM,
     
    495495 * @{ */
    496496#define PGMPAGETYPE_IS_READABLE(type)   ( (type) <= PGMPAGETYPE_ROM )
    497 #define PGMPAGETYPE_IS_WRITEABLE(type)  ( (type) <= PGMPAGETYPE_ROM_RAM )
    498 #define PGMPAGETYPE_IS_RWX(type)        ( (type) <= PGMPAGETYPE_ROM_RAM )
     497#define PGMPAGETYPE_IS_WRITEABLE(type)  ( (type) <= PGMPAGETYPE_ROM_SHADOW )
     498#define PGMPAGETYPE_IS_RWX(type)        ( (type) <= PGMPAGETYPE_ROM_SHADOW )
    499499#define PGMPAGETYPE_IS_ROX(type)        ( (type) == PGMPAGETYPE_ROM )
    500500#define PGMPAGETYPE_IS_NP(type)         ( (type) == PGMPAGETYPE_MMIO )
     
    634634 * @param   pPage       Pointer to the physical guest page tracking structure.
    635635 */
    636 #define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage)   ( (pPage)->idPage & (RT_BIT_32(GMM_CHUNKID_SHIFT) - 1) )
     636#define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage)   ( (pPage)->idPage & GMM_PAGEID_IDX_MASK )
    637637/* later:
    638638#if GMM_CHUNKID_SHIFT <= 12
    639 # define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage)  ( (uint32_t)((pPage)->HCPhys & (RT_BIT_32(GMM_CHUNKID_SHIFT) - 1)) )
     639# define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage)  ( (uint32_t)((pPage)->HCPhys & GMM_PAGEID_IDX_MASK) )
    640640#else
    641641# define PGM_PAGE_GET_PAGE_IN_CHUNK(pPage)  (   (uint32_t)((pPage)->HCPhys & 0xfff) \
     
    751751 * Per page tracking structure for ROM image.
    752752 *
    753  * This is in addition to PGMPAGE, which will be set up with one
    754  * of the two pages described here.
     753 * A ROM image may have a shadow page, in which case we may have
     754 * two pages backing it. This structure contains the PGMPAGE for
     755 * both while PGMRAMRANGE have a copy of the active one. It is
     756 * important that these aren't out of sync in any regard other
     757 * than page pool tracking data.
    755758 */
    756759typedef struct PGMROMPAGE
    757760{
    758     /** The virgin page (read-only). */
    759     RTHCPHYS    HCPhysVirgin;
    760     /** The shadow page (read-write). */
    761     RTHCPHYS    HCPhysShadow;
    762     /** The page id of the virgin page. NIL_GMM_PAGEID if it's the zero page. */
    763     uint32_t    idPageVirgin;
    764     /** The page id of the shadow page. NIL_GMM_PAGEID if it's the zero page. */
    765     uint32_t    idPageShadow;
    766     /** The current protection status. */
     761    /** The page structure for the virgin ROM page. */
     762    PGMPAGE     Virgin;
     763    /** The page structure for the shadow RAM page. */
     764    PGMPAGE     Shadow;
     765    /** The current protection setting. */
    767766    PGMROMPROT  enmProt;
    768     uint32_t    u32Padding;             /**< Structure size padding.*/
     767    /** Pad the structure size to a multiple of 8. */
     768    uint32_t    u32Padding;
    769769} PGMROMPAGE;
     770/** Pointer to a ROM page tracking structure. */
     771typedef PGMROMPAGE *PPGMROMPAGE;
    770772
    771773
     
    23302332
    23312333int             pgmPhysPageLoadIntoTlb(PPGM pPGM, RTGCPHYS GCPhys);
     2334int             pgmPhysPageMakeWritable(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys);
     2335int             pgmPhysPageMap(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPPGMPAGEMAP ppMap, void **ppv);
    23322336#ifdef IN_RING3
    23332337int             pgmR3PhysChunkMap(PVM pVM, uint32_t idChunk, PPPGMCHUNKR3MAP ppChunk);
     2338int             pgmR3PhysRomReset(PVM pVM);
    23342339#ifndef VBOX_WITH_NEW_PHYS_CODE
    23352340int             pgmr3PhysGrowRange(PVM pVM, RTGCPHYS GCPhys);
  • trunk/src/VBox/VMM/PGMPhys.cpp

    r6840 r6854  
    4242
    4343
     44/*******************************************************************************
     45*   Internal Functions                                                         *
     46*******************************************************************************/
     47/*static - shut up warning */
     48DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
     49
     50
    4451
    4552/*
     
    407414     */
    408415    PPGMROMRANGE pRomNew;
    409     rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMROMRANGE, aPages[cPages]), sizeof(PGMROMPAGE), MM_TAG_PGM_PHYS, (void **)pRomNew);
     416    rc = MMHyperAlloc(pVM, RT_OFFSETOF(PGMROMRANGE, aPages[cPages]), 0, MM_TAG_PGM_PHYS, (void **)pRomNew);
    410417    if (RT_SUCCESS(rc))
    411418    {
     
    415422        if (RT_SUCCESS(rc))
    416423        {
     424            pgmLock(pVM);
     425
    417426            /*
    418427             * Initialize and insert the RAM range (if required).
    419428             */
     429            PPGMROMPAGE pRomPage = &pRomNew->aPages[0];
    420430            if (!fRamExists)
    421431            {
     
    428438
    429439                PPGMPAGE pPage = &pRamNew->aPages[0];
    430                 for (uint32_t iPage = 0; iPage < cPages; iPage++)
     440                for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++)
    431441                {
    432442                    pPage->fWrittenTo = 0;
     
    437447                    PGM_PAGE_SET_STATE(pPage,  PGM_PAGE_STATE_ALLOCATED);
    438448                    PGM_PAGE_SET_PAGEID(pPage, pReq->aPages[iPage].idPage);
     449
     450                    pRomPage->Virgin = *pPage;
    439451                }
    440452
     
    444456            {
    445457                PPGMPAGE pPage = &pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT];
    446                 for (uint32_t iPage = 0; iPage < cPages; iPage++)
     458                for (uint32_t iPage = 0; iPage < cPages; iPage++, pPage++, pRomPage++)
    447459                {
    448460                    PGM_PAGE_SET_TYPE(pPage,   PGMPAGETYPE_ROM);
     
    450462                    PGM_PAGE_SET_STATE(pPage,  PGM_PAGE_STATE_ALLOCATED);
    451463                    PGM_PAGE_SET_PAGEID(pPage, pReq->aPages[iPage].idPage);
     464
     465                    pRomPage->Virgin = *pPage;
    452466                }
    453467
    454468                pRamNew = pRam;
    455469            }
     470            pgmUnlock(pVM);
     471
    456472
    457473            /*
     
    459475             */
    460476            rc = PGMR3HandlerPhysicalRegister(pVM, PGMPHYSHANDLERTYPE_PHYSICAL_WRITE, GCPhys, GCPhysLast,
    461                                               NULL, NULL, /** @todo we actually need a ring-3 write handler here for shadowed ROMs, so hack REM! */
    462                                               NULL, "pgmGuestROMWriteHandler", 0,
    463                                               NULL, "pgmGuestROMWriteHandler", 0, pszDesc);
     477#if 0 /** @todo we actually need a ring-3 write handler here for shadowed ROMs, so hack REM! */
     478                                              pgmR3PhysRomWriteHandler, pRomNew,
     479#else
     480                                              NULL, NULL,
     481#endif
     482                                              NULL, "pgmGuestROMWriteHandler", MMHyperCCToR0(pVM, pRomNew),
     483                                              NULL, "pgmGuestROMWriteHandler", MMHyperCCToGC(pVM, pRomNew), pszDesc);
    464484            if (RT_SUCCESS(rc))
    465485            {
     486                pgmLock(pVM);
     487
    466488                /*
    467489                 * Copy the image over to the virgin pages.
    468490                 * This must be done after linking in the RAM range.
    469491                 */
    470                 for (uint32_t iPage = 0; iPage < cPages; iPage++)
     492                PPGMPAGE pRamPage = &pRamNew->aPages[(GCPhys - pRamNew->GCPhys) >> PAGE_SHIFT];
     493                for (uint32_t iPage = 0; iPage < cPages; iPage++, pRamPage++)
    471494                {
    472                     void *pvDst;
    473                     PGMPAGEMAPLOCK Lock;
    474                     int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhys + (iPage << PAGE_SHIFT), &pvDst, &Lock);
     495                    void *pvDstPage;
     496                    PPGMPAGEMAP pMapIgnored;
     497                    rc = pgmPhysPageMap(pVM, pRamPage, GCPhys + (iPage << PAGE_SHIFT), &pMapIgnored, &pvDstPage);
    475498                    if (RT_FAILURE(rc))
    476499                    {
     
    478501                        break;
    479502                    }
    480                     memcpy(pvDst, (const uint8_t *)pvBinary + (iPage << PAGE_SHIFT), PAGE_SIZE);
    481                     PGMPhysReleasePageMappingLock(pVM, &Lock);
     503                    memcpy(pvDstPage, (const uint8_t *)pvBinary + (iPage << PAGE_SHIFT), PAGE_SIZE);
    482504                }
    483505                if (RT_SUCCESS(rc))
     
    485507                    /*
    486508                     * Initialize the ROM range.
     509                     * Note that the Virgin member of the pages has already been initialized above.
    487510                     */
    488511                    pRomNew->GCPhys = GCPhys;
     
    495518                    for (unsigned iPage = 0; iPage < cPages; iPage++)
    496519                    {
    497                         pRomNew->aPages[iPage].HCPhysVirgin = pReq->aPages[iPage].HCPhysGCPhys;
    498                         pRomNew->aPages[iPage].HCPhysShadow = NIL_RTHCPHYS;
    499                         pRomNew->aPages[iPage].idPageVirgin = pReq->aPages[iPage].idPage;
    500                         pRomNew->aPages[iPage].idPageShadow = NIL_GMM_PAGEID;
     520                        PPGMROMPAGE pPage = &pRomNew->aPages[iPage];
     521
     522                        pPage->Shadow.HCPhys = 0;
     523                        pPage->Shadow.fWrittenTo = 0;
     524                        pPage->Shadow.fSomethingElse = 0;
     525                        pPage->Shadow.u29B = 0;
     526                        PGM_PAGE_SET_TYPE(  &pPage->Shadow, PGMPAGETYPE_ROM_SHADOW);
     527                        PGM_PAGE_SET_STATE( &pPage->Shadow, PGM_PAGE_STATE_ZERO);
     528                        PGM_PAGE_SET_PAGEID(&pPage->Shadow, pReq->aPages[iPage].idPage);
     529
    501530                        pRomNew->aPages[iPage].enmProt = PGMROMPROT_READ_ROM_WRITE_IGNORE;
    502531                    }
     
    525554
    526555                    GMMR3AllocatePagesCleanup(pReq);
     556                    pgmUnlock(pVM);
    527557                    return VINF_SUCCESS;
    528558                }
     
    530560                /* bail out */
    531561
     562                pgmUnlock(pVM);
    532563                int rc2 = PGMHandlerPhysicalDeregister(pVM, GCPhys);
    533564                AssertRC(rc2);
     565                pgmLock(pVM);
    534566            }
    535567
     
    544576    GMMR3FreeAllocatedPages(pVM, pReq);
    545577    GMMR3AllocatePagesCleanup(pReq);
     578    pgmUnlock(pVM);
    546579    return rc;
     580}
     581
     582
     583/**
     584 * \#PF Handler callback for ROM write accesses.
     585 *
     586 * @returns VINF_SUCCESS if the handler have carried out the operation.
     587 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
     588 * @param   pVM             VM Handle.
     589 * @param   GCPhys          The physical address the guest is writing to.
     590 * @param   pvPhys          The HC mapping of that address.
     591 * @param   pvBuf           What the guest is reading/writing.
     592 * @param   cbBuf           How much it's reading/writing.
     593 * @param   enmAccessType   The access type.
     594 * @param   pvUser          User argument.
     595 */
     596/*static - shut up warning */
     597 DECLCALLBACK(int) pgmR3PhysRomWriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
     598{
     599    PPGMROMRANGE    pRom = (PPGMROMRANGE)pvUser;
     600    const uint32_t  iPage = GCPhys - pRom->GCPhys;
     601    Assert(iPage < (pRom->cb >> PAGE_SHIFT));
     602    PPGMROMPAGE     pRomPage = &pRom->aPages[iPage];
     603    switch (pRomPage->enmProt)
     604    {
     605        /*
     606         * Ignore.
     607         */
     608        case PGMROMPROT_READ_ROM_WRITE_IGNORE:
     609        case PGMROMPROT_READ_RAM_WRITE_IGNORE:
     610            return VINF_SUCCESS;
     611
     612        /*
     613         * Write to the ram page.
     614         */
     615        case PGMROMPROT_READ_ROM_WRITE_RAM:
     616        case PGMROMPROT_READ_RAM_WRITE_RAM: /* yes this will get here too, it's *way* simpler that way. */
     617        {
     618            /* This should be impossible now, pvPhys doesn't work cross page anylonger. */
     619            Assert(((GCPhys - pRom->GCPhys + cbBuf - 1) >> PAGE_SHIFT) == iPage);
     620
     621            /*
     622             * Take the lock, do lazy allocation, map the page and copy the data.
     623             *
     624             * Note that we have to bypass the mapping TLB since it works on
     625             * guest physical addresses and entering the shadow page would
     626             * kind of screw things up...
     627             */
     628            int rc = pgmLock(pVM);
     629            AssertRC(rc);
     630
     631            if (RT_UNLIKELY(PGM_PAGE_GET_STATE(&pRomPage->Shadow) != PGM_PAGE_STATE_ALLOCATED))
     632            {
     633                rc = pgmPhysPageMakeWritable(pVM, &pRomPage->Shadow, GCPhys);
     634                if (RT_FAILURE(rc))
     635                {
     636                    pgmUnlock(pVM);
     637                    return rc;
     638                }
     639            }
     640
     641            void *pvDstPage;
     642            PPGMPAGEMAP pMapIgnored;
     643            rc = pgmPhysPageMap(pVM, &pRomPage->Shadow, GCPhys & X86_PTE_PG_MASK, &pMapIgnored, &pvDstPage);
     644            if (RT_SUCCESS(rc))
     645                memcpy((uint8_t *)pvDstPage + (GCPhys & PAGE_OFFSET_MASK), pvBuf, cbBuf);
     646
     647            pgmUnlock(pVM);
     648            return rc;
     649        }
     650
     651        default:
     652            AssertMsgFailedReturn(("enmProt=%d iPage=%d GCPhys=%RGp\n",
     653                                   pRom->aPages[iPage].enmProt, iPage, GCPhys),
     654                                  VERR_INTERNAL_ERROR);
     655    }
     656}
     657
     658
     659
     660/**
     661 * Called by PGMR3Reset to reset the shadow, switch to the virgin,
     662 * and verify that the virgin part is untouched.
     663 *
     664 * This is done after the normal memory has been cleared.
     665 *
     666 * @param   pVM         The VM handle.
     667 */
     668int pgmR3PhysRomReset(PVM pVM)
     669{
     670    for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
     671    {
     672        const uint32_t cPages = pRom->cb >> PAGE_SHIFT;
     673
     674        if (pRom->fFlags & PGMPHYS_ROM_FLAG_SHADOWED)
     675        {
     676            /*
     677             * Reset the physical handler.
     678             */
     679            int rc = PGMR3PhysRomProtect(pVM, pRom->GCPhys, pRom->cb, PGMROMPROT_READ_ROM_WRITE_IGNORE);
     680            AssertRCReturn(rc, rc);
     681
     682            /*
     683             * What we do with the shadow pages depends on the memory
     684             * preallocation option. If not enabled, we'll just throw
     685             * out all the dirty pages and replace them by the zero page.
     686             */
     687            if (1)///@todo !pVM->pgm.f.fRamPreAlloc)
     688            {
     689                /* Count dirty shadow pages. */
     690                uint32_t cDirty = 0;
     691                uint32_t iPage = cPages;
     692                while (iPage-- > 0)
     693                    if (PGM_PAGE_GET_STATE(&pRom->aPages[iPage].Shadow) != PGM_PAGE_STATE_ZERO)
     694                        cDirty++;
     695                if (cDirty)
     696                {
     697                    /* Free the dirty pages. */
     698                    PGMMFREEPAGESREQ pReq;
     699                    rc = GMMR3FreePagesPrepare(pVM, &pReq, cDirty, GMMACCOUNT_BASE);
     700                    AssertRCReturn(rc, rc);
     701
     702                    uint32_t iReqPage = 0;
     703                    for (iPage = 0; iPage < cPages; iPage++)
     704                        if (PGM_PAGE_GET_STATE(&pRom->aPages[iPage].Shadow) != PGM_PAGE_STATE_ZERO)
     705                        {
     706                            pReq->aPages[iReqPage].idPage = PGM_PAGE_GET_PAGEID(&pRom->aPages[iPage].Shadow);
     707                            iReqPage++;
     708                        }
     709
     710                    rc = GMMR3FreePagesPerform(pVM, pReq);
     711                    GMMR3FreePagesCleanup(pReq);
     712                    AssertRCReturn(rc, rc);
     713
     714                    /* setup the zero page. */
     715                    for (iPage = 0; iPage < cPages; iPage++)
     716                        if (PGM_PAGE_GET_STATE(&pRom->aPages[iPage].Shadow) != PGM_PAGE_STATE_ZERO)
     717                        {
     718                            PGM_PAGE_SET_STATE( &pRom->aPages[iPage].Shadow, PGM_PAGE_STATE_ZERO);
     719                            PGM_PAGE_SET_HCPHYS(&pRom->aPages[iPage].Shadow, pVM->pgm.s.HCPhysZeroPg);
     720                            PGM_PAGE_SET_PAGEID(&pRom->aPages[iPage].Shadow, NIL_GMM_PAGEID);
     721                            pRom->aPages[iPage].Shadow.fWrittenTo = false;
     722                            iReqPage++;
     723                        }
     724                }
     725            }
     726            else
     727            {
     728                /* clear all the pages. */
     729                pgmLock(pVM);
     730                for (uint32_t iPage = 0; iPage < cPages; iPage++)
     731                {
     732                    const RTGCPHYS GCPhys = pRom->GCPhys + (iPage << PAGE_SHIFT);
     733                    rc = pgmPhysPageMakeWritable(pVM, &pRom->aPages[iPage].Shadow, GCPhys);
     734                    if (RT_FAILURE(rc))
     735                        break;
     736
     737                    void *pvDstPage;
     738                    PPGMPAGEMAP pMapIgnored;
     739                    rc = pgmPhysPageMap(pVM, &pRom->aPages[iPage].Shadow, GCPhys, &pMapIgnored, &pvDstPage);
     740                    if (RT_FAILURE(rc))
     741                        break;
     742                    memset(pvDstPage, 0, PAGE_SIZE);
     743                }
     744                pgmUnlock(pVM);
     745                AssertRCReturn(rc, rc);
     746            }
     747        }
     748
     749#ifdef VBOX_STRICT
     750        /*
     751         * Verify that the virgin page is unchanged if possible.
     752         */
     753        if (pRom->pvOriginal)
     754        {
     755            uint8_t const *pbSrcPage = (uint8_t const *)pRom->pvOriginal;
     756            for (uint32_t iPage = 0; iPage < cPages; iPage++, pbSrcPage += PAGE_SIZE)
     757            {
     758                const RTGCPHYS GCPhys = pRom->GCPhys + (iPage << PAGE_SHIFT);
     759                PPGMPAGEMAP pMapIgnored;
     760                void *pvDstPage;
     761                int rc = pgmPhysPageMap(pVM, &pRom->aPages[iPage].Virgin, GCPhys, &pMapIgnored, &pvDstPage);
     762                if (RT_FAILURE(rc))
     763                    break;
     764                if (memcmp(pvDstPage, pbSrcPage, PAGE_SIZE))
     765                    LogRel(("pgmR3PhysRomReset: %RGp rom page changed (%s) - loaded saved state?\n",
     766                            GCPhys, pRom->pszDesc));
     767            }
     768        }
     769#endif
     770    }
     771
     772    return VINF_SUCCESS;
     773}
     774
     775
     776/**
     777 * Change the shadowing of a range of ROM pages.
     778 *
     779 * This is intended for implementing chipset specific memory registers
     780 * and will not be very strict about the input. It will silently ignore
     781 * any pages that are not the part of a shadowed ROM.
     782 *
     783 * @returns VBox status code.
     784 * @param   pVM         Pointer to the shared VM structure.
     785 * @param   GCPhys      Where to start. Page aligned.
     786 * @param   cb          How much to change. Page aligned.
     787 * @param   enmProt     The new ROM protection.
     788 */
     789PGMR3DECL(int) PGMR3PhysRomProtect(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, PGMROMPROT enmProt)
     790{
     791    /*
     792     * Check input
     793     */
     794    if (!cb)
     795        return VINF_SUCCESS;
     796    AssertReturn(!(GCPhys & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
     797    AssertReturn(!(cb & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
     798    RTGCPHYS GCPhysLast = GCPhys + (cb - 1);
     799    AssertReturn(GCPhysLast > GCPhys, VERR_INVALID_PARAMETER);
     800    AssertReturn(enmProt >= PGMROMPROT_INVALID && enmProt <= PGMROMPROT_END, VERR_INVALID_PARAMETER);
     801
     802    /*
     803     * Process the request.
     804     */
     805    bool fFlushedPool = false;
     806    for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
     807        if (    GCPhys     <= pRom->GCPhysLast
     808            &&  GCPhysLast >= pRom->GCPhys)
     809        {
     810            /*
     811             * Iterate the relevant pages and the ncessary make changes.
     812             */
     813            bool fChanges = false;
     814            uint32_t const cPages = pRom->GCPhysLast > GCPhysLast
     815                                  ? pRom->cb >> PAGE_SHIFT
     816                                  : (GCPhysLast - pRom->GCPhys) >> PAGE_SHIFT;
     817            for (uint32_t iPage = (GCPhys - pRom->GCPhys) >> PAGE_SHIFT;
     818                 iPage < cPages;
     819                 iPage++)
     820            {
     821                PPGMROMPAGE pRomPage = &pRom->aPages[iPage];
     822                if (PGMROMPROT_IS_ROM(pRomPage->enmProt) != PGMROMPROT_IS_ROM(enmProt))
     823                {
     824                    fChanges = true;
     825
     826                    /* flush the page pool first so we don't leave any usage references dangling. */
     827                    if (!fFlushedPool)
     828                    {
     829                        pgmPoolFlushAll(pVM);
     830                        fFlushedPool = true;
     831                    }
     832
     833                    PPGMPAGE pOld = PGMROMPROT_IS_ROM(pRomPage->enmProt) ? &pRomPage->Virgin : &pRomPage->Shadow;
     834                    PPGMPAGE pNew = PGMROMPROT_IS_ROM(pRomPage->enmProt) ? &pRomPage->Shadow : &pRomPage->Virgin;
     835                    PPGMPAGE pRamPage = pgmPhysGetPage(&pVM->pgm.s, pRom->GCPhys + (iPage << PAGE_SHIFT));
     836
     837                    *pOld = *pRamPage;
     838                    *pRamPage = *pNew;
     839                    /** @todo sync the volatile flags (handlers) when these have been moved out of HCPhys. */
     840                }
     841            }
     842
     843            /*
     844             * Reset the access handler if we made changes, no need
     845             * to optimize this.
     846             */
     847            if (fChanges)
     848            {
     849                int rc = PGMHandlerPhysicalReset(pVM, pRom->GCPhys);
     850                AssertRCReturn(rc, rc);
     851            }
     852
     853            /* Advance - cb isn't updated. */
     854            GCPhys = pRom->GCPhys + (cPages << PAGE_SHIFT);
     855        }
     856
     857    return VINF_SUCCESS;
    547858}
    548859
  • trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp

    r6829 r6854  
    993993}
    994994
    995 
    996995#ifndef IN_RING3
    997 
    998 # ifdef IN_RING0
    999 /** @todo try combine this with iom and em. */
    1000 
    1001 /**
    1002  * Read callback for disassembly function; supports reading bytes that cross a page boundary
    1003  *
    1004  * @returns VBox status code.
    1005  * @param   pSrc        GC source pointer
    1006  * @param   pDest       HC destination pointer
    1007  * @param   size        Number of bytes to read
    1008  * @param   pvUserdata  Callback specific user data (pCpu)
    1009  *
    1010  */
    1011 DECLCALLBACK(int) pgmReadBytes(RTHCUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata)
    1012 {
    1013     DISCPUSTATE  *pCpu     = (DISCPUSTATE *)pvUserdata;
    1014     PVM           pVM      = (PVM)pCpu->apvUserData[0];
    1015 
    1016     int rc = PGMPhysReadGCPtr(pVM, pDest, pSrc, size);
    1017     AssertRC(rc);
    1018     return rc;
    1019 }
    1020 
    1021 inline int pgmDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    1022 {
    1023     return DISCoreOneEx(InstrGC, pCpu->mode, pgmReadBytes, pVM, pCpu, pOpsize);
    1024 }
    1025 
    1026 # else /* !IN_RING0 (i.e. in IN_GC) */
    1027 inline int pgmDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    1028 {
    1029     return DISCoreOne(pCpu, InstrGC, pOpsize);
    1030 }
    1031 
    1032 #endif /* !IN_RING0 (i.e. in IN_GC) */
    1033 
    1034996
    1035997/**
     
    10431005 * @param   pvFault     The fault address (cr2).
    10441006 * @param   GCPhysFault The GC physical address corresponding to pvFault.
    1045  * @param   pvUser      User argument.
     1007 * @param   pvUser      User argument. Pointer to the ROM range structure.
    10461008 */
    10471009PGMDECL(int) pgmGuestROMWriteHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, RTGCPHYS GCPhysFault, void *pvUser)
    10481010{
    1049     DISCPUSTATE Cpu;
    1050     Cpu.mode = SELMIsSelector32Bit(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid) ? CPUMODE_32BIT : CPUMODE_16BIT;
    1051     if (Cpu.mode == CPUMODE_32BIT)
    1052     {
    1053         RTGCPTR GCPtrCode;
    1054         int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &GCPtrCode);
    1055         if (VBOX_SUCCESS(rc))
    1056         {
     1011    int rc;
     1012#ifdef VBOX_WITH_NEW_PHYS_CODE
     1013    PPGMROMRANGE pRom = (PPGMROMRANGE)pvUser;
     1014    uint32_t iPage = GCPhysFault - pRom->GCPhys;
     1015    Assert(iPage < (pRom->cb >> PAGE_SHIFT));
     1016    switch (pRom->aPages[iPage].enmProt)
     1017    {
     1018        case PGMROMPROT_READ_ROM_WRITE_IGNORE:
     1019        case PGMROMPROT_READ_RAM_WRITE_IGNORE:
     1020        {
     1021#endif
     1022            /*
     1023             * If it's a simple instruction which doesn't change the cpu state
     1024             * we will simply skip it. Otherwise we'll have to defer it to REM.
     1025             */
    10571026            uint32_t cbOp;
    1058             rc = pgmDisCoreOne(pVM, &Cpu, (RTGCUINTPTR)GCPtrCode, &cbOp);
    1059             if (VBOX_SUCCESS(rc))
     1027            DISCPUSTATE Cpu;
     1028            rc = EMInterpretDisasOne(pVM, pRegFrame, &Cpu, &cbOp);
     1029            if (     RT_SUCCESS(rc)
     1030                &&   Cpu.mode == CPUMODE_32BIT
     1031                &&  !(Cpu.prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG)))
    10601032            {
    1061                 /* ASSUMES simple instructions.
    1062                  * For instance 'pop [ROM_ADDRESS]' or 'and [ROM_ADDRESS], eax' better
    1063                  * not occure or we'll screw up the cpu state.
    1064                  */
    1065                 /** @todo We're assuming too much here I think. */
    1066                 if (!(Cpu.prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG)))
     1033                switch (Cpu.opcode)
    10671034                {
    1068                     /*
    1069                      * Move on to the next instruction.
    1070                      */
    1071                     pRegFrame->eip += cbOp;
    1072                     STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestROMWriteHandled);
    1073                     return VINF_SUCCESS;
     1035                    /** @todo Find other instructions we can safely skip, possibly
     1036                     * adding this kind of detection to DIS or EM. */
     1037                    case OP_MOV:
     1038                        pRegFrame->eip += cbOp;
     1039                        STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestROMWriteHandled);
     1040                        return VINF_SUCCESS;
    10741041                }
    1075                 LogFlow(("pgmGuestROMWriteHandler: wrong prefix!!\n"));
    10761042            }
    1077         }
    1078     }
     1043            else if (RT_UNLIKELY(rc == VERR_INTERNAL_ERROR))
     1044                return rc;
     1045#ifdef VBOX_WITH_NEW_PHYS_CODE
     1046            break;
     1047        }
     1048
     1049        case PGMROMPROT_READ_RAM_WRITE_RAM:
     1050            rc = PGMHandlerPhysicalPageTempOff(pVM, pRom->GCPhys, GCPhysFault & X86_PTE_PG_MASK);
     1051            AssertRC(rc);
     1052        case PGMROMPROT_READ_ROM_WRITE_RAM:
     1053            /* Handle it in ring-3 because it's *way* easier there. */
     1054            break;
     1055
     1056        default:
     1057            AssertMsgFailedReturn(("enmProt=%d iPage=%d GCPhysFault=%RGp\n",
     1058                                   pRom->aPages[iPage].enmProt, iPage, GCPhysFault),
     1059                                  VERR_INTERNAL_ERROR);
     1060    }
     1061#endif
    10791062
    10801063    STAM_COUNTER_INC(&pVM->pgm.s.StatGCGuestROMWriteUnhandled);
    10811064    return VINF_EM_RAW_EMULATE_INSTR;
    10821065}
    1083 #endif /* !IN_RING3 */
     1066
     1067#endif /* IN_RING3 */
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r6829 r6854  
    313313        STAM_COUNTER_INC(&pVM->pgm.s.StatPageReplaceShared);
    314314        pVM->pgm.s.cSharedPages--;
     315/** @todo err.. what about copying the page content? */
    315316    }
    316317    else
     
    319320        STAM_COUNTER_INC(&pVM->pgm.s.StatPageReplaceZero);
    320321        pVM->pgm.s.cZeroPages--;
     322/** @todo verify that the handy page is zero! */
    321323    }
    322324
     
    565567        PPGMPAGE pPage = pTlbe->pPage;
    566568        if (RT_UNLIKELY(pPage->u2State != PGM_PAGE_STATE_ALLOCATED))
     569        {
    567570            rc = pgmPhysPageMakeWritable(pVM, pPage, GCPhys);
     571            /** @todo stuff is missing here! */
     572        }
    568573        if (RT_SUCCESS(rc))
    569574        {
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r6837 r6854  
    547547    GEN_CHECK_OFF(PGMRAMRANGE, aPages[1]);
    548548    GEN_CHECK_SIZE(PGMROMPAGE);
    549     GEN_CHECK_OFF(PGMROMPAGE, HCPhysVirgin);
    550     GEN_CHECK_OFF(PGMROMPAGE, HCPhysShadow);
    551     GEN_CHECK_OFF(PGMROMPAGE, idPageVirgin);
    552     GEN_CHECK_OFF(PGMROMPAGE, idPageShadow);
     549    GEN_CHECK_OFF(PGMROMPAGE, Virgin);
     550    GEN_CHECK_OFF(PGMROMPAGE, Shadow);
    553551    GEN_CHECK_OFF(PGMROMPAGE, enmProt);
    554552    GEN_CHECK_SIZE(PGMROMRANGE);
  • trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp

    r6837 r6854  
    212212    CHECK_SIZE(PGMPAGE, 16);
    213213    CHECK_MEMBER_ALIGNMENT(PGMRAMRANGE, aPages, 16);
    214     CHECK_SIZE(PGMROMPAGE, 32);
    215     CHECK_MEMBER_ALIGNMENT(PGMROMRANGE, aPages, 32);
    216214
    217215    /* misc */
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