Changeset 89578 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jun 9, 2021 11:41:54 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r89574 r89578 2565 2565 2566 2566 /** 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 */ 2577 static 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 */ 2617 static 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 /** 2567 2664 * Memory access bulk (one or more 4K pages) request from a device. 2568 2665 * … … 2580 2677 uint32_t fFlags, PRTGCPHYS paGCPhysSpa) 2581 2678 { 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; 2584 2735 } 2585 2736 … … 2622 2773 VTDREQTYPE enmReqType; 2623 2774 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 2638 2777 DMARMEMREQREMAP MemReqRemap; 2639 2778 RT_ZERO(MemReqRemap); … … 2645 2784 MemReqRemap.In.enmAddrType = PCIADDRTYPE_UNTRANSLATED; 2646 2785 MemReqRemap.In.enmReqType = enmReqType; 2647 MemReqRemap.Aux.fTtm = fTtm;2786 MemReqRemap.Aux.fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM); 2648 2787 MemReqRemap.Out.AddrRange.uAddr = NIL_RTGCPHYS; 2649 2788 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); 2689 2790 *pGCPhysSpa = MemReqRemap.Out.AddrRange.uAddr; 2690 2791 *pcbContiguous = MemReqRemap.Out.AddrRange.cb;
Note:
See TracChangeset
for help on using the changeset viewer.