VirtualBox

Changeset 88668 in vbox


Ignore:
Timestamp:
Apr 23, 2021 4:17:04 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143982
Message:

AMD IOMMU: bugref:9654 Fix locking that got broken when the PDM lock was used instead of the device's own lock. We need to lock MMIO reads and writes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp

    r88642 r88668  
    173173
    174174/** Acquires the cache lock. */
    175 # define IOMMU_LOCK_CACHE(a_pDevIns, a_pThis) \
     175#define IOMMU_LOCK_CACHE(a_pDevIns, a_pThis) \
    176176    do { \
    177177        int const rcLock = PDMDevHlpCritSectEnter((a_pDevIns), &(a_pThis)->CritSectCache, VERR_SEM_BUSY); \
     
    200200
    201201/** Acquires the PDM lock. */
    202 #define IOMMU_LOCK(a_pDevIns, a_pThisCC)  \
     202#define IOMMU_LOCK(a_pDevIns, a_pThisCC, a_rcBusy)  \
    203203    do { \
    204         int const rcLock = (a_pThisCC)->CTX_SUFF(pIommuHlp)->pfnLock((a_pDevIns), VERR_SEM_BUSY); \
     204        int const rcLock = (a_pThisCC)->CTX_SUFF(pIommuHlp)->pfnLock((a_pDevIns), (a_rcBusy)); \
    205205        if (RT_LIKELY(rcLock == VINF_SUCCESS)) \
    206206        { /* likely */ } \
     
    27162716    Log4Func(("off=%#x cb=%u uValue=%#RX64\n", off, cb, uValue));
    27172717
    2718     PIOMMU        pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
    2719     PCIOMMUREGACC pReg  = iommuAmdGetRegAccess(off);
     2718    PIOMMU        pThis   = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     2719    PIOMMUCC      pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PIOMMUCC);
     2720    PCIOMMUREGACC pReg    = iommuAmdGetRegAccess(off);
    27202721    if (pReg)
    27212722    { /* likely */ }
     
    27432744    {
    27442745        if (!(off & 7))
    2745             return pReg->pfnWrite(pDevIns, pThis, off, uValue);
     2746        {
     2747            IOMMU_LOCK(pDevIns, pThisCC, VINF_IOM_R3_MMIO_WRITE);
     2748            VBOXSTRICTRC rcStrict = pReg->pfnWrite(pDevIns, pThis, off, uValue);
     2749            IOMMU_UNLOCK(pDevIns, pThisCC);
     2750            return rcStrict;
     2751        }
    27462752
    27472753        LogFunc(("Misaligned access while writing register at off=%#x (cb=%u) with %#RX64 -> Ignored\n", off, cb, uValue));
     
    27532759    if (!(off & 7))
    27542760    {
     2761        VBOXSTRICTRC rcStrict;
     2762        IOMMU_LOCK(pDevIns, pThisCC, VINF_IOM_R3_MMIO_WRITE);
     2763
    27552764        /*
    27562765         * Lower 32 bits of a 64-bit register or a 32-bit register is being written.
     
    27592768        uint64_t u64Read;
    27602769        if (pReg->pfnRead)
    2761         {
    2762             VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off, &u64Read);
    2763             if (RT_FAILURE(rcStrict))
    2764             {
    2765                 LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict)));
    2766                 return rcStrict;
    2767             }
    2768         }
     2770            rcStrict = pReg->pfnRead(pDevIns, pThis, off, &u64Read);
    27692771        else
     2772        {
     2773            rcStrict = VINF_SUCCESS;
    27702774            u64Read = 0;
    2771 
    2772         uValue = (u64Read & UINT64_C(0xffffffff00000000)) | uValue;
    2773         return pReg->pfnWrite(pDevIns, pThis, off, uValue);
     2775        }
     2776
     2777        if (RT_SUCCESS(rcStrict))
     2778        {
     2779            uValue = (u64Read & UINT64_C(0xffffffff00000000)) | uValue;
     2780            rcStrict = pReg->pfnWrite(pDevIns, pThis, off, uValue);
     2781        }
     2782        else
     2783            LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict)));
     2784
     2785        IOMMU_UNLOCK(pDevIns, pThisCC);
     2786        return rcStrict;
    27742787    }
    27752788
     
    27782791     * Merge with lower 32 bits (after reading the full 64-bits) and perform a 64-bit write.
    27792792     */
     2793    VBOXSTRICTRC rcStrict;
    27802794    Assert(!(off & 3));
    27812795    Assert(off & 7);
     
    27832797    uint64_t u64Read;
    27842798    if (pReg->pfnRead)
    2785     {
    2786         VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off - 4, &u64Read);
    2787         if (RT_FAILURE(rcStrict))
    2788         {
    2789             LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict)));
    2790             return rcStrict;
    2791         }
    2792     }
     2799        rcStrict = pReg->pfnRead(pDevIns, pThis, off - 4, &u64Read);
    27932800    else
     2801    {
     2802        rcStrict = VINF_SUCCESS;
    27942803        u64Read = 0;
    2795 
    2796     uValue = (uValue << 32) | (u64Read & UINT64_C(0xffffffff));
    2797     return pReg->pfnWrite(pDevIns, pThis, off - 4, uValue);
     2804    }
     2805
     2806    if (RT_SUCCESS(rcStrict))
     2807    {
     2808        uValue = (uValue << 32) | (u64Read & UINT64_C(0xffffffff));
     2809        rcStrict = pReg->pfnWrite(pDevIns, pThis, off - 4, uValue);
     2810    }
     2811    else
     2812        LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict)));
     2813
     2814    IOMMU_UNLOCK(pDevIns, pThisCC);
     2815    return rcStrict;
    27982816}
    27992817
     
    28242842    Log4Func(("off=%#x\n", off));
    28252843
    2826     PIOMMU      pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     2844    PIOMMU      pThis   = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     2845    PIOMMUCC    pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PIOMMUCC);
    28272846    PCPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
    28282847    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); NOREF(pPciDev);
     
    28512870     */
    28522871    if (!(off & 7))
    2853         return pReg->pfnRead(pDevIns, pThis, off, puResult);
     2872    {
     2873        IOMMU_LOCK(pDevIns, pThisCC, VINF_IOM_R3_MMIO_READ);
     2874        VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off, puResult);
     2875        IOMMU_UNLOCK(pDevIns, pThisCC);
     2876        return rcStrict;
     2877    }
    28542878
    28552879    /*
     
    28602884    Assert(off & 7);
    28612885    Assert(off >= 4);
     2886    IOMMU_LOCK(pDevIns, pThisCC, VINF_IOM_R3_MMIO_READ);
    28622887    VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off - 4, puResult);
     2888    IOMMU_UNLOCK(pDevIns, pThisCC);
    28632889    if (RT_SUCCESS(rcStrict))
    28642890        *puResult >>= 32;
     
    34583484    PIOMMUCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PIOMMUCC);
    34593485
    3460     IOMMU_LOCK(pDevIns, pThisCC);
     3486    IOMMU_LOCK(pDevIns, pThisCC, VERR_SEM_BUSY);
    34613487
    34623488    /* Figure out which device table segment is being accessed. */
     
    48524878                if (pCmdComWait->n.u1Interrupt)
    48534879                {
    4854                     IOMMU_LOCK(pDevIns, pThisR3);
     4880                    IOMMU_LOCK(pDevIns, pThisR3, VERR_IGNORED);
    48554881                    ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_COMPLETION_WAIT_INTR);
    48564882                    bool const fRaiseInt = pThis->Ctrl.n.u1CompWaitIntrEn;
    48574883                    IOMMU_UNLOCK(pDevIns, pThisR3);
    4858 
    48594884                    if (fRaiseInt)
    48604885                        iommuAmdMsiInterruptRaise(pDevIns);
     
    50835108         *        save on host memory a bit, we could (once PGM has the necessary APIs)
    50845109         *        lock the page mappings page mappings and access them directly. */
    5085         IOMMU_LOCK(pDevIns, pThisR3);
     5110        IOMMU_LOCK(pDevIns, pThisR3, VERR_IGNORED);
    50865111
    50875112        if (pThis->Status.n.u1CmdBufRunning)
     
    51045129                IOMMU_UNLOCK(pDevIns, pThisR3);
    51055130                int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCmdBufBase, pvCmds, cbCmdBuf);
    5106                 IOMMU_LOCK(pDevIns, pThisR3);
     5131                IOMMU_LOCK(pDevIns, pThisR3, VERR_IGNORED);
    51075132
    51085133                if (RT_SUCCESS(rc))
     
    52675292
    52685293    PIOMMUR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PIOMMUR3);
    5269     IOMMU_LOCK(pDevIns, pThisR3);
     5294    IOMMU_LOCK(pDevIns, pThisR3, VERR_IGNORED);
    52705295
    52715296    VBOXSTRICTRC rcStrict;
     
    66116636
    66126637    int rc;
    6613     IOMMU_LOCK(pDevIns, pThisR3);
     6638    IOMMU_LOCK(pDevIns, pThisR3, VERR_IGNORED);
    66146639
    66156640    /* Map MMIO regions if the IOMMU BAR is enabled. */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette