VirtualBox

Changeset 4388 in vbox for trunk/src/VBox/VMM/MMPhys.cpp


Ignore:
Timestamp:
Aug 27, 2007 2:26:05 PM (17 years ago)
Author:
vboxsync
Message:

Shadow ROM emulation. Clear the RESERVED flag for ROM.

File:
1 edited

Legend:

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

    r4071 r4388  
    278278 *                              This must be cbRange bytes big.
    279279 *                              It will be copied and doesn't have to stick around.
     280 *                              It will be copied and doesn't have to stick around if fShadow is clear.
     281 * @param   fShadow             Whether to emulate ROM shadowing. This involves leaving
     282 *                              the ROM writable for a while during the POST and refreshing
     283 *                              it at reset. When this flag is set, the memory pointed to by
     284 *                              pvBinary has to stick around for the lifespan of the VM.
    280285 * @param   pszDesc             Pointer to description string. This must not be freed.
    281286 * @remark  There is no way to remove the rom, automatically on device cleanup or
    282287 *          manually from the device yet. At present I doubt we need such features...
    283288 */
    284 MMR3DECL(int) MMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const void *pvBinary, const char *pszDesc)
     289MMR3DECL(int) MMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const void *pvBinary,
     290                                  bool fShadow, const char *pszDesc)
    285291{
    286292    /*
     
    340346    memcpy(pvCopy, pvBinary, cbRange);
    341347
    342     /** @note we rely on the MM_RAM_FLAGS_ROM flag in PGMPhysRead now. Don't change to reserved! */
    343     /** @todo r=bird: Noone ever talked about changing *to* _RESERVED. The question is whether
    344      * we should *clear* _RESERVED. I've no idea what the state of that flag is for ROM areas right
    345      * now, but I will find out later. */
     348    const unsigned fSet = fShadow ? MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2 : MM_RAM_FLAGS_ROM;
    346349    for (; iPage < iPageEnd; iPage++)
    347         pCur->aPhysPages[iPage].Phys |= MM_RAM_FLAGS_ROM; /** @todo should be clearing _RESERVED? */
    348     int rc = PGMR3PhysSetFlags(pVM, GCPhys, cbRange, MM_RAM_FLAGS_ROM, ~0); /** @todo should be clearing _RESERVED? */
     350    {
     351        pCur->aPhysPages[iPage].Phys &= ~MM_RAM_FLAGS_RESERVED;
     352        pCur->aPhysPages[iPage].Phys |= fSet;
     353    }
     354    int rc = PGMR3PhysSetFlags(pVM, GCPhys, cbRange, fSet, ~MM_RAM_FLAGS_RESERVED);
    349355    AssertRC(rc);
    350356    if (VBOX_SUCCESS(rc))
    351357    {
    352358        /*
    353          * Prevent changes to the ROM memory when executing in raw mode by
    354          * registering a GC only write access handler.
     359         * To prevent the shadow page table mappings from being RW in raw-mode, we
     360         * must currently employ a little hack. We register an write access handler
     361         * and thereby ensures a RO mapping of the pages. This is NOT very nice,
     362         * and wasn't really my intention when writing the code, consider it a PGM bug.
    355363         *
    356364         * ASSUMES that REMR3NotifyPhysRomRegister doesn't call cpu_register_physical_memory
     
    360368                                          NULL, NULL,
    361369                                          NULL, "pgmGuestROMWriteHandler", 0,
    362                                           NULL, "pgmGuestROMWriteHandler", 0, "ROM Write Access Handler");
     370                                          NULL, "pgmGuestROMWriteHandler", 0, pszDesc);
    363371        AssertRC(rc);
    364372    }
    365373
    366     REMR3NotifyPhysRomRegister(pVM, GCPhys, cbRange, pvCopy);
     374    /*
     375     * Create a ROM range it so we can make a 'info rom' thingy and more importantly
     376     * reload and protect/unprotect shadow ROM correctly.
     377     */
     378    if (VBOX_SUCCESS(rc))
     379    {
     380        PMMROMRANGE pRomRange = (PMMROMRANGE)MMR3HeapAlloc(pVM, MM_TAG_MM, sizeof(*pRomRange));
     381        AssertReturn(pRomRange, VERR_NO_MEMORY);
     382        pRomRange->GCPhys = GCPhys;
     383        pRomRange->cbRange = cbRange;
     384        pRomRange->pszDesc = pszDesc;
     385        pRomRange->fShadow = fShadow;
     386        pRomRange->fWritable = fShadow;
     387        pRomRange->pvBinary = fShadow ? pvBinary : NULL;
     388        pRomRange->pvCopy = pvCopy;
     389
     390        /* sort it for 'info rom' readability.  */
     391        PMMROMRANGE pPrev = NULL;
     392        PMMROMRANGE pCur = pVM->mm.s.pRomHead;
     393        while (pCur && pCur->GCPhys < GCPhys)
     394        {
     395            pPrev = pCur;
     396            pCur = pCur->pNext;
     397        }
     398        pRomRange->pNext = pCur;
     399        if (pPrev)
     400            pPrev->pNext = pRomRange;
     401        else
     402            pVM->mm.s.pRomHead = pRomRange;
     403    }
     404
     405    REMR3NotifyPhysRomRegister(pVM, GCPhys, cbRange, pvCopy, fShadow);
    367406    return rc; /* we're sloppy with error cleanup here, but we're toast anyway if this fails. */
    368407}
     
    438477 * This usually means the size of the first contigous block of physical memory.
    439478 *
    440  * @returns
    441  * @param   pVM
     479 * @returns The guest base RAM size.
     480 * @param   pVM         The VM handle.
    442481 * @thread  Any.
    443482 */
     
    447486}
    448487
     488
     489/**
     490 * Called by MMR3Reset to reset the shadow ROM.
     491 *
     492 * Resetting involves reloading the ROM into RAM and make it
     493 * wriable again (as it was made read only at the end of the POST).
     494 *
     495 * @param   pVM         The VM handle.
     496 */
     497void mmR3PhysRomReset(PVM pVM)
     498{
     499    for (PMMROMRANGE pCur = pVM->mm.s.pRomHead; pCur; pCur = pCur->pNext)
     500        if (pCur->fShadow)
     501        {
     502            memcpy(pCur->pvCopy, pCur->pvBinary, pCur->cbRange);
     503            if (!pCur->fWritable)
     504            {
     505                int rc = PGMHandlerPhysicalDeregister(pVM, pCur->GCPhys);
     506                AssertRC(rc);
     507                pCur->fWritable = true;
     508
     509                rc = PGMR3PhysSetFlags(pVM, pCur->GCPhys, pCur->cbRange, MM_RAM_FLAGS_MMIO2, ~0); /* ROM -> ROM + MMIO2 */
     510                AssertRC(rc);
     511
     512                REMR3NotifyPhysRomRegister(pVM, pCur->GCPhys, pCur->cbRange, pCur->pvCopy, true /* read-write now */);
     513            }
     514        }
     515}
     516
     517
     518/**
     519 * Write-protects a shadow ROM range.
     520 *
     521 * This is called late in the POST for shadow ROM ranges.
     522 *
     523 * @returns VBox status code.
     524 * @param   pVM         The VM handle.
     525 * @param   GCPhys      Start of the registered shadow ROM range
     526 * @param   cbRange     The length of the registered shadow ROM range.
     527 *                      This can be NULL (not sure about the BIOS interface yet).
     528 */
     529MMR3DECL(int) MMR3PhysRomProtect(PVM pVM, RTGCPHYS GCPhys, RTUINT cbRange)
     530{
     531    for (PMMROMRANGE pCur = pVM->mm.s.pRomHead; pCur; pCur = pCur->pNext)
     532        if (    pCur->GCPhys == GCPhys
     533            &&  (   pCur->cbRange == cbRange
     534                 || !cbRange))
     535        {
     536            if (pCur->fWritable)
     537            {
     538                cbRange = pCur->cbRange;
     539                int rc = PGMR3HandlerPhysicalRegister(pVM, PGMPHYSHANDLERTYPE_PHYSICAL_WRITE, GCPhys, GCPhys + cbRange - 1,
     540                                                      NULL, NULL,
     541                                                      NULL, "pgmGuestROMWriteHandler", 0,
     542                                                      NULL, "pgmGuestROMWriteHandler", 0, pCur->pszDesc);
     543                AssertRCReturn(rc, rc);
     544                pCur->fWritable = false;
     545
     546                rc = PGMR3PhysSetFlags(pVM, GCPhys, cbRange, 0, ~MM_RAM_FLAGS_MMIO2); /* ROM + MMIO2 -> ROM */
     547                AssertRCReturn(rc, rc);
     548                /* Don't bother with the MM page flags here because I don't think they are
     549                   really used beyond conflict checking at ROM, RAM, Reservation, etc. */
     550
     551                REMR3NotifyPhysRomRegister(pVM, GCPhys, cbRange, pCur->pvCopy, false /* read-only now */);
     552            }
     553            return VINF_SUCCESS;
     554        }
     555    AssertMsgFailed(("GCPhys=%VGp cbRange=%#x\n", GCPhys, cbRange));
     556    return VERR_INVALID_PARAMETER;
     557}
     558
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