VirtualBox

Changeset 19472 in vbox


Ignore:
Timestamp:
May 7, 2009 9:21:39 AM (16 years ago)
Author:
vboxsync
Message:

Protect port I/O with a critical section.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r19263 r19472  
    4141
    4242/**
     43 * Try take the EMT/IOM lock, wait in ring-3 return VERR_SEM_BUSY in R0/RC.
     44 *
     45 * @retval  VINF_SUCCESS on success (always in ring-3).
     46 * @retval  VERR_SEM_BUSY in RC and R0 if the semaphore is busy.
     47 *
     48 * @param   pVM         VM handle.
     49 */
     50int iomLock(PVM pVM)
     51{
     52    Assert(!PGMIsLocked(pVM));
     53    int rc = PDMCritSectEnter(&pVM->iom.s.EmtLock, VERR_SEM_BUSY);
     54    return rc;
     55}
     56
     57
     58/**
     59 * Try take the EMT/IOM lock, no waiting.
     60 *
     61 * @retval  VINF_SUCCESS on success.
     62 * @retval  VERR_SEM_BUSY if busy.
     63 *
     64 * @param   pVM         VM handle.
     65 */
     66int iomTryLock(PVM pVM)
     67{
     68    int rc = PDMCritSectTryEnter(&pVM->iom.s.EmtLock);
     69    return rc;
     70}
     71
     72
     73/**
     74 * Release EMT/IOM lock.
     75 *
     76 * @param   pVM         VM handle.
     77 */
     78void iomUnlock(PVM pVM)
     79{
     80    PDMCritSectLeave(&pVM->iom.s.EmtLock);
     81}
     82
     83/**
    4384 * Returns the contents of register or immediate data of instruction's parameter.
    4485 *
     
    208249VMMDECL(int) IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue)
    209250{
     251    /* Take the IOM lock before performing any device I/O. */
     252    int rc = iomLock(pVM);
     253#ifndef IN_RING3
     254    if (rc == VERR_SEM_BUSY)
     255        return VINF_IOM_HC_IOPORT_READ;
     256#else
     257    AssertRC(rc);
     258#endif
     259
    210260#ifdef VBOX_WITH_STATISTICS
    211261    /*
     
    245295                STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
    246296# endif
     297            iomUnlock(pVM);
    247298            return VINF_IOM_HC_IOPORT_READ;
    248299        }
     
    253304            STAM_PROFILE_ADV_START(&pStats->CTX_SUFF_Z(ProfIn), a);
    254305#endif
    255         int rc = pRange->pfnInCallback(pRange->pDevIns, pRange->pvUser, Port, pu32Value, (unsigned)cbValue);
     306        rc = pRange->pfnInCallback(pRange->pDevIns, pRange->pvUser, Port, pu32Value, (unsigned)cbValue);
    256307#ifdef VBOX_WITH_STATISTICS
    257308        if (pStats)
     
    275326                default:
    276327                    AssertMsgFailed(("Invalid I/O port size %d. Port=%d\n", cbValue, Port));
     328                    iomUnlock(pVM);
    277329                    return VERR_IOM_INVALID_IOPORT_SIZE;
    278330            }
    279331        }
    280332        Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=%Rrc\n", Port, *pu32Value, cbValue, rc));
     333        iomUnlock(pVM);
    281334        return rc;
    282335    }
     
    293346            STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
    294347# endif
     348        iomUnlock(pVM);
    295349        return VINF_IOM_HC_IOPORT_READ;
    296350    }
     
    307361# ifndef IN_RING3
    308362        /* Ring-3 will have to create the statistics record. */
     363        iomUnlock(pVM);
    309364        return VINF_IOM_HC_IOPORT_READ;
    310365# else
     
    324379        default:
    325380            AssertMsgFailed(("Invalid I/O port size %d. Port=%d\n", cbValue, Port));
     381            iomUnlock(pVM);
    326382            return VERR_IOM_INVALID_IOPORT_SIZE;
    327383    }
    328384    Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", Port, *pu32Value, cbValue));
     385    iomUnlock(pVM);
    329386    return VINF_SUCCESS;
    330387}
     
    349406VMMDECL(int) IOMIOPortReadString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb)
    350407{
     408    /* Take the IOM lock before performing any device I/O. */
     409    int rc = iomLock(pVM);
     410#ifndef IN_RING3
     411    if (rc == VERR_SEM_BUSY)
     412        return VINF_IOM_HC_IOPORT_READ;
     413#endif
     414    AssertRC(rc);
     415
    351416#ifdef LOG_ENABLED
    352417    const RTGCUINTREG cTransfers = *pcTransfers;
     
    389454                STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
    390455# endif
     456            iomUnlock(pVM);
    391457            return VINF_IOM_HC_IOPORT_READ;
    392458        }
     
    411477        Log3(("IOMIOPortReadStr: Port=%RTiop pGCPtrDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",
    412478              Port, pGCPtrDst, pcTransfers, cTransfers, *pcTransfers, cb, rc));
     479        iomUnlock(pVM);
    413480        return rc;
    414481    }
     
    425492            STAM_COUNTER_INC(&pStats->CTX_MID_Z(In,ToR3));
    426493# endif
     494        iomUnlock(pVM);
    427495        return VINF_IOM_HC_IOPORT_READ;
    428496    }
     
    439507# ifndef IN_RING3
    440508        /* Ring-3 will have to create the statistics record. */
     509        iomUnlock(pVM);
    441510        return VINF_IOM_HC_IOPORT_READ;
    442511# else
     
    450519    Log3(("IOMIOPortReadStr: Port=%RTiop pGCPtrDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",
    451520          Port, pGCPtrDst, pcTransfers, cTransfers, *pcTransfers, cb));
     521    iomUnlock(pVM);
    452522    return VINF_SUCCESS;
    453523}
     
    471541VMMDECL(int) IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
    472542{
     543    /* Take the IOM lock before performing any device I/O. */
     544    int rc = iomLock(pVM);
     545#ifndef IN_RING3
     546    if (rc == VERR_SEM_BUSY)
     547        return VINF_IOM_HC_IOPORT_WRITE;
     548#endif
     549    AssertRC(rc);
     550
    473551/** @todo bird: When I get time, I'll remove the GC tree and link the GC entries to the ring-3 node. */
    474552#ifdef VBOX_WITH_STATISTICS
     
    509587                STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
    510588# endif
     589            iomUnlock(pVM);
    511590            return VINF_IOM_HC_IOPORT_WRITE;
    512591        }
     
    530609#endif
    531610        Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d rc=%Rrc\n", Port, u32Value, cbValue, rc));
     611        iomUnlock(pVM);
    532612        return rc;
    533613    }
     
    544624            STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
    545625# endif
     626        iomUnlock(pVM);
    546627        return VINF_IOM_HC_IOPORT_WRITE;
    547628    }
     
    559640# ifndef IN_RING3
    560641        /* R3 will have to create the statistics record. */
     642        iomUnlock(pVM);
    561643        return VINF_IOM_HC_IOPORT_WRITE;
    562644# else
     
    568650#endif
    569651    Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d nop\n", Port, u32Value, cbValue));
     652    iomUnlock(pVM);
    570653    return VINF_SUCCESS;
    571654}
     
    590673VMMDECL(int) IOMIOPortWriteString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb)
    591674{
     675    /* Take the IOM lock before performing any device I/O. */
     676    int rc = iomLock(pVM);
     677#ifndef IN_RING3
     678    if (rc == VERR_SEM_BUSY)
     679        return VINF_IOM_HC_IOPORT_WRITE;
     680#endif
     681    AssertRC(rc);
     682
    592683#ifdef LOG_ENABLED
    593684    const RTGCUINTREG cTransfers = *pcTransfers;
     
    630721                STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
    631722# endif
     723            iomUnlock(pVM);
    632724            return VINF_IOM_HC_IOPORT_WRITE;
    633725        }
     
    651743        Log3(("IOMIOPortWriteStr: Port=%RTiop pGCPtrSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",
    652744              Port, pGCPtrSrc, pcTransfers, cTransfers, *pcTransfers, cb, rc));
     745        iomUnlock(pVM);
    653746        return rc;
    654747    }
     
    665758            STAM_COUNTER_INC(&pStats->CTX_MID_Z(Out,ToR3));
    666759# endif
     760        iomUnlock(pVM);
    667761        return VINF_IOM_HC_IOPORT_WRITE;
    668762    }
     
    679773# ifndef IN_RING3
    680774        /* Ring-3 will have to create the statistics record. */
     775        iomUnlock(pVM);
    681776        return VINF_IOM_HC_IOPORT_WRITE;
    682777# else
     
    690785    Log3(("IOMIOPortWriteStr: Port=%RTiop pGCPtrSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n",
    691786          Port, pGCPtrSrc, pcTransfers, cTransfers, *pcTransfers, cb));
     787    iomUnlock(pVM);
    692788    return VINF_SUCCESS;
    693789}
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