VirtualBox

Changeset 89578 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jun 9, 2021 11:41:54 AM (4 years ago)
Author:
vboxsync
Message:

Intel IOMMU: bugref:9967 Implemented bulk memory access requests.

File:
1 edited

Legend:

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

    r89574 r89578  
    25652565
    25662566/**
     2567 * Gets the DMA access permissions and the address-translation request
     2568 * type given the PDM IOMMU memory access flags.
     2569 *
     2570 * @param   pDevIns         The IOMMU device instance.
     2571 * @param   fFlags          The access flags, see PDMIOMMU_MEM_F_XXX.
     2572 * @param   fBulk           Whether this is a bulk memory access (used for
     2573 *                          statistics).
     2574 * @param   penmReqType     Where to store the address-translation request type.
     2575 * @param   pfReqPerm       Where to store the DMA access permissions.
     2576 */
     2577static void dmarDrGetPermAndReqType(PPDMDEVINS pDevIns, uint32_t fFlags, bool fBulk, PVTDREQTYPE penmReqType, uint8_t *pfReqPerm)
     2578{
     2579    PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     2580    if (fFlags & PDMIOMMU_MEM_F_READ)
     2581    {
     2582        *penmReqType = VTDREQTYPE_READ;
     2583        *pfReqPerm   = DMAR_PERM_READ;
     2584#ifdef VBOX_WITH_STATISTICS
     2585        if (!fBulk)
     2586            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemRead));
     2587        else
     2588            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemBulkRead));
     2589#else
     2590        RT_NOREF2(pThis, fBulk);
     2591#endif
     2592    }
     2593    else
     2594    {
     2595        *penmReqType = VTDREQTYPE_WRITE;
     2596        *pfReqPerm   = DMAR_PERM_WRITE;
     2597#ifdef VBOX_WITH_STATISTICS
     2598        if (!fBulk)
     2599            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemWrite));
     2600        else
     2601            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemBulkWrite));
     2602#else
     2603        RT_NOREF2(pThis, fBulk);
     2604#endif
     2605    }
     2606}
     2607
     2608
     2609/**
     2610 * Handles DMA remapping based on the table translation mode (TTM).
     2611 *
     2612 * @returns VBox status code.
     2613 * @param   pDevIns         The IOMMU device instance.
     2614 * @param   uRtaddrReg      The current RTADDR_REG value.
     2615 * @param   pMemReqRemap    The DMA memory request remapping info.
     2616 */
     2617static int dmarDrMemReqRemap(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, PDMARMEMREQREMAP pMemReqRemap)
     2618{
     2619    int rc;
     2620    switch (pMemReqRemap->Aux.fTtm)
     2621    {
     2622        case VTD_TTM_LEGACY_MODE:
     2623        {
     2624            rc = dmarDrLegacyModeRemapAddr(pDevIns, uRtaddrReg, pMemReqRemap);
     2625            break;
     2626        }
     2627
     2628        case VTD_TTM_SCALABLE_MODE:
     2629        {
     2630            PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PCDMAR);
     2631            if (pThis->fExtCapReg & VTD_BF_ECAP_REG_SMTS_MASK)
     2632                rc = dmarDrScalableModeRemapAddr(pDevIns, uRtaddrReg, pMemReqRemap);
     2633            else
     2634            {
     2635                rc = VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2636                dmarAtFaultRecord(pDevIns, kDmarDiag_At_Rta_Smts_Not_Supported, &pMemReqRemap->In, &pMemReqRemap->Aux);
     2637            }
     2638            break;
     2639        }
     2640
     2641        case VTD_TTM_ABORT_DMA_MODE:
     2642        {
     2643            PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PCDMAR);
     2644            if (pThis->fExtCapReg & VTD_BF_ECAP_REG_ADMS_MASK)
     2645                dmarDrTargetAbort(pDevIns);
     2646            else
     2647                dmarAtFaultRecord(pDevIns, kDmarDiag_At_Rta_Adms_Not_Supported, &pMemReqRemap->In, &pMemReqRemap->Aux);
     2648            rc = VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2649            break;
     2650        }
     2651
     2652        default:
     2653        {
     2654            rc = VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     2655            dmarAtFaultRecord(pDevIns, kDmarDiag_At_Rta_Rsvd, &pMemReqRemap->In, &pMemReqRemap->Aux);
     2656            break;
     2657        }
     2658    }
     2659    return rc;
     2660}
     2661
     2662
     2663/**
    25672664 * Memory access bulk (one or more 4K pages) request from a device.
    25682665 *
     
    25802677                                                 uint32_t fFlags, PRTGCPHYS paGCPhysSpa)
    25812678{
    2582     RT_NOREF6(pDevIns, idDevice, cIovas, pauIovas, fFlags, paGCPhysSpa);
    2583     return VERR_NOT_IMPLEMENTED;
     2679    /* Validate. */
     2680    AssertPtr(pDevIns);
     2681    Assert(cIovas > 0);
     2682    AssertPtr(pauIovas);
     2683    AssertPtr(paGCPhysSpa);
     2684    Assert(!(fFlags & ~PDMIOMMU_MEM_F_VALID_MASK));
     2685
     2686    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     2687    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
     2688
     2689    DMAR_LOCK(pDevIns, pThisCC);
     2690    uint32_t const uGstsReg   = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_GSTS_REG);
     2691    uint64_t const uRtaddrReg = pThis->uRtaddrReg;
     2692    DMAR_UNLOCK(pDevIns, pThisCC);
     2693
     2694    if (uGstsReg & VTD_BF_GSTS_REG_TES_MASK)
     2695    {
     2696        VTDREQTYPE enmReqType;
     2697        uint8_t    fReqPerm;
     2698        dmarDrGetPermAndReqType(pDevIns, fFlags, true /* fBulk */, &enmReqType, &fReqPerm);
     2699
     2700        DMARMEMREQREMAP MemReqRemap;
     2701        RT_ZERO(MemReqRemap);
     2702        MemReqRemap.In.AddrRange.cb     = X86_PAGE_SIZE;
     2703        MemReqRemap.In.AddrRange.fPerm  = fReqPerm;
     2704        MemReqRemap.In.idDevice         = idDevice;
     2705        MemReqRemap.In.Pasid            = NIL_PCIPASID;
     2706        MemReqRemap.In.enmAddrType      = PCIADDRTYPE_UNTRANSLATED;
     2707        MemReqRemap.In.enmReqType       = enmReqType;
     2708        MemReqRemap.Aux.fTtm            = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM);
     2709        MemReqRemap.Out.AddrRange.uAddr = NIL_RTGCPHYS;
     2710
     2711        for (size_t i = 0; i < cIovas; i++)
     2712        {
     2713            MemReqRemap.In.AddrRange.uAddr = pauIovas[i] & X86_PAGE_BASE_MASK;
     2714            int const rc = dmarDrMemReqRemap(pDevIns, uRtaddrReg, &MemReqRemap);
     2715            if (RT_SUCCESS(rc))
     2716            {
     2717                paGCPhysSpa[i] = MemReqRemap.Out.AddrRange.uAddr | (pauIovas[i] & X86_PAGE_OFFSET_MASK);
     2718                Assert(MemReqRemap.Out.AddrRange.cb == MemReqRemap.In.AddrRange.cb);
     2719            }
     2720            else
     2721            {
     2722                LogFlowFunc(("idDevice=%#x uIova=%#RX64 fPerm=%#x rc=%Rrc\n", idDevice, pauIovas[i], fReqPerm, rc));
     2723                return rc;
     2724            }
     2725        }
     2726    }
     2727    else
     2728    {
     2729        /* Addresses are forwarded without translation when the translation is disabled. */
     2730        for (size_t i = 0; i < cIovas; i++)
     2731            paGCPhysSpa[i] = pauIovas[i];
     2732    }
     2733
     2734    return VINF_SUCCESS;
    25842735}
    25852736
     
    26222773        VTDREQTYPE enmReqType;
    26232774        uint8_t    fReqPerm;
    2624         if (fFlags & PDMIOMMU_MEM_F_READ)
    2625         {
    2626             enmReqType = VTDREQTYPE_READ;
    2627             fReqPerm   = DMAR_PERM_READ;
    2628             STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemRead));
    2629         }
    2630         else
    2631         {
    2632             enmReqType = VTDREQTYPE_WRITE;
    2633             fReqPerm   = DMAR_PERM_WRITE;
    2634             STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemWrite));
    2635         }
    2636 
    2637         uint8_t const fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM);
     2775        dmarDrGetPermAndReqType(pDevIns, fFlags, false /* fBulk */, &enmReqType, &fReqPerm);
     2776
    26382777        DMARMEMREQREMAP MemReqRemap;
    26392778        RT_ZERO(MemReqRemap);
     
    26452784        MemReqRemap.In.enmAddrType      = PCIADDRTYPE_UNTRANSLATED;
    26462785        MemReqRemap.In.enmReqType       = enmReqType;
    2647         MemReqRemap.Aux.fTtm            = fTtm;
     2786        MemReqRemap.Aux.fTtm            = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM);
    26482787        MemReqRemap.Out.AddrRange.uAddr = NIL_RTGCPHYS;
    26492788
    2650         int rc;
    2651         switch (fTtm)
    2652         {
    2653             case VTD_TTM_LEGACY_MODE:
    2654             {
    2655                 rc = dmarDrLegacyModeRemapAddr(pDevIns, uRtaddrReg, &MemReqRemap);
    2656                 break;
    2657             }
    2658 
    2659             case VTD_TTM_SCALABLE_MODE:
    2660             {
    2661                 if (pThis->fExtCapReg & VTD_BF_ECAP_REG_SMTS_MASK)
    2662                     rc = dmarDrScalableModeRemapAddr(pDevIns, uRtaddrReg, &MemReqRemap);
    2663                 else
    2664                 {
    2665                     rc = VERR_IOMMU_ADDR_TRANSLATION_FAILED;
    2666                     dmarAtFaultRecord(pDevIns, kDmarDiag_At_Rta_Smts_Not_Supported, &MemReqRemap.In, &MemReqRemap.Aux);
    2667                 }
    2668                 break;
    2669             }
    2670 
    2671             case VTD_TTM_ABORT_DMA_MODE:
    2672             {
    2673                 rc = VERR_IOMMU_ADDR_TRANSLATION_FAILED;
    2674                 if (pThis->fExtCapReg & VTD_BF_ECAP_REG_ADMS_MASK)
    2675                     dmarDrTargetAbort(pDevIns);
    2676                 else
    2677                     dmarAtFaultRecord(pDevIns, kDmarDiag_At_Rta_Adms_Not_Supported, &MemReqRemap.In, &MemReqRemap.Aux);
    2678                 break;
    2679             }
    2680 
    2681             default:
    2682             {
    2683                 rc = VERR_IOMMU_ADDR_TRANSLATION_FAILED;
    2684                 dmarAtFaultRecord(pDevIns, kDmarDiag_At_Rta_Rsvd, &MemReqRemap.In, &MemReqRemap.Aux);
    2685                 break;
    2686             }
    2687         }
    2688 
     2789        int const rc = dmarDrMemReqRemap(pDevIns, uRtaddrReg, &MemReqRemap);
    26892790        *pGCPhysSpa    = MemReqRemap.Out.AddrRange.uAddr;
    26902791        *pcbContiguous = MemReqRemap.Out.AddrRange.cb;
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