Changeset 88427 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Apr 9, 2021 10:14:43 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r88417 r88427 94 94 /** DMAR implementation's major version number (exposed to software). */ 95 95 #define DMAR_VER_MAJOR 1 96 /** Number of domains supported (0=16, 1=64, 2=256, 3=1024, 4=4K, 5=16K, 6=64K,97 * 7=(Reserved). */98 #define DMAR_CAP_ND 299 /** Large page support level (0=2M, 1=1GB pages). */100 #define DMAR_CAP_LARGE_PAGE_LVL 0101 /** Maximum address mask value (9 for 2M, 18 for 1G). */102 #define DMAR_CAP_MAMV (X86_PAGE_2M_SHIFT - X86_PAGE_4K_SHIFT)103 /** Maximum handle mask value (must be 0 to 0xf). */104 #define DMAR_ECAP_MHMV 0xf105 96 /** @} */ 106 97 … … 127 118 IOMMMIOHANDLE hMmio; 128 119 129 /** DMAR registers (group 0). */120 /** Registers (group 0). */ 130 121 uint8_t abRegs0[DMAR_MMIO_GROUP_0_SIZE]; 131 /** DMAR registers (group 1). */122 /** Registers (group 1). */ 132 123 uint8_t abRegs1[DMAR_MMIO_GROUP_1_SIZE]; 124 125 /** @name Register copies for a tiny bit faster and more convenient access. 126 * @{ */ 127 /** Copy of CAP_REG. */ 128 uint64_t fCap; 129 /** Copy of ECAP_REG. */ 130 uint64_t fExtCap; 131 /** @} */ 133 132 134 133 #ifdef VBOX_WITH_STATISTICS … … 458 457 static uint8_t vtdGetSupGstAddrBits(uint8_t uSagaw) 459 458 { 460 if ( uSagaw > 0 && uSagaw < 4)459 if (RT_LIKELY(uSagaw > 0 && uSagaw < 4)) 461 460 return 30 + (uSagaw * 9); 461 return 0; 462 } 463 464 465 /** 466 * Gets the supported adjusted guest-address width (SAGAW) given the maximum guest 467 * address width (MGAW). 468 * 469 * @returns The CAP.SAGAW value. 470 * @param uMgaw The CAP_REG.MGAW value. 471 */ 472 static uint8_t vtdGetSupGstAddrWidth(uint8_t uMgaw) 473 { 474 switch (uMgaw + 1) 475 { 476 case 39: return 1; 477 case 48: return 2; 478 case 57: return 3; 479 } 462 480 return 0; 463 481 } … … 779 797 #ifdef IN_RING3 780 798 /** 781 * Initializes registers in the DMAR unit that are constant through the lifetime of 782 * the VM (immutable by software and not mutated by hardware once initialized). 799 * Initializes all registers in the DMAR unit. 783 800 * 784 801 * @param pDevIns The IOMMU device instance. 785 802 */ 786 static void dmarR3RegsInit Immutable(PPDMDEVINS pDevIns)803 static void dmarR3RegsInit(PPDMDEVINS pDevIns) 787 804 { 788 805 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 806 RT_ZERO(pThis->abRegs0); 807 RT_ZERO(pThis->abRegs1); 808 809 /* 810 * Initialize registers not mutable by software prior to initializing other registers. 811 */ 789 812 /* VER_REG */ 790 813 { … … 793 816 dmarRegWriteRaw64(pThis, VTD_MMIO_OFF_VER_REG, uVer); 794 817 } 818 819 uint8_t const fFlts = 1; /* First-Level translation support. */ 820 uint8_t const fSlts = 1; /* Second-Level translation support. */ 821 uint8_t const fPt = 1; /* Pass-Through support. */ 822 uint8_t const fNest = 0; /* Nested translation support. */ 823 uint8_t const fSmts = fFlts & fSlts & fPt; /* Scalable mode translation support.*/ 824 795 825 /* CAP_REG */ 796 826 { 827 uint8_t const fFl1gp = 1; /* First-Level 1GB pages support. */ 828 uint8_t const fFl5lp = 1; /* First-level 5-level paging support (PML5E). */ 829 uint8_t const fSl2mp = fSlts & 1; /* Second-Level 2MB pages support. */ 830 uint8_t const fSl2gp = fSlts & 1; /* Second-Level 1GB pages support. */ 831 uint8_t const fSllps = fSl2mp /* Second-Level large page Support. */ 832 | ((fSl2mp & fFl1gp) & RT_BIT(1)); 833 uint8_t const fMamv = (fSl2gp ? /* Maximum address mask value (for second-level invalidations). */ 834 X86_PAGE_1G_SHIFT : X86_PAGE_2M_SHIFT) - X86_PAGE_4K_SHIFT; 835 uint8_t const fNd = 2; /* Number of domains (0=16, 1=64, 2=256, 3=1K, 4=4K, 5=16K, 6=64K, 836 7=Reserved). */ 837 uint8_t const fPsi = 1; /* Page selective invalidation. */ 797 838 uint8_t cGstPhysAddrBits; 798 839 uint8_t cGstLinearAddrBits; 799 840 PDMDevHlpCpuGetGuestAddrWidths(pDevIns, &cGstPhysAddrBits, &cGstLinearAddrBits); 800 841 NOREF(cGstLinearAddrBits); 801 uint64_t const uCap = RT_BF_MAKE(VTD_BF_CAP_REG_ND, DMAR_CAP_ND) 802 | RT_BF_MAKE(VTD_BF_CAP_REG_AFL, 0) /* Advanced Fault Logging not supported. */ 803 | RT_BF_MAKE(VTD_BF_CAP_REG_RWBF, 0) /* Software need not flush write-buffers. */ 804 | RT_BF_MAKE(VTD_BF_CAP_REG_PLMR, 0) /* Protected Low-Memory Region not supported. */ 805 | RT_BF_MAKE(VTD_BF_CAP_REG_PHMR, 0) /* Protected High-Memory Region not supported. */ 806 | RT_BF_MAKE(VTD_BF_CAP_REG_CM, 1) /** @todo Figure out if required when we impl. caching. */ 807 | RT_BF_MAKE(VTD_BF_CAP_REG_SAGAW, 0) /* 0 as Second-level Translation not supported. */ 808 | RT_BF_MAKE(VTD_BF_CAP_REG_MGAW, cGstPhysAddrBits - 1) 809 | RT_BF_MAKE(VTD_BF_CAP_REG_ZLR, 1) /** @todo Zero-length read? */ 810 | RT_BF_MAKE(VTD_BF_CAP_REG_FRO, DMAR_MMIO_OFF_FRCD_LO_REG >> 4) 811 | RT_BF_MAKE(VTD_BF_CAP_REG_SLLPS, DMAR_CAP_LARGE_PAGE_LVL) 812 | RT_BF_MAKE(VTD_BF_CAP_REG_PSI, 1) 813 | RT_BF_MAKE(VTD_BF_CAP_REG_NFR, DMAR_FRCD_REG_COUNT - 1) 814 | RT_BF_MAKE(VTD_BF_CAP_REG_MAMV, DMAR_CAP_MAMV) 815 | RT_BF_MAKE(VTD_BF_CAP_REG_DWD, 1) 816 | RT_BF_MAKE(VTD_BF_CAP_REG_FL1GP, 0) /* 0 as First-level Translation not supported. */ 817 | RT_BF_MAKE(VTD_BF_CAP_REG_PI, 0) /* Posted Interrupts not supported. */ 818 | RT_BF_MAKE(VTD_BF_CAP_REG_FL5LP, 0); /* 0 as First-level Translation not supported. */ 819 dmarRegWriteRaw64(pThis, VTD_MMIO_OFF_CAP_REG, uCap); 842 uint8_t const uMgaw = cGstPhysAddrBits - 1; /* Maximum guest address width. */ 843 uint8_t const uSagaw = vtdGetSupGstAddrWidth(uMgaw); /* Supported adjust guest address width. */ 844 845 pThis->fCap = RT_BF_MAKE(VTD_BF_CAP_REG_ND, fNd) 846 | RT_BF_MAKE(VTD_BF_CAP_REG_AFL, 0) /* Advanced fault logging not supported. */ 847 | RT_BF_MAKE(VTD_BF_CAP_REG_RWBF, 0) /* Software need not flush write-buffers. */ 848 | RT_BF_MAKE(VTD_BF_CAP_REG_PLMR, 0) /* Protected Low-Memory Region not supported. */ 849 | RT_BF_MAKE(VTD_BF_CAP_REG_PHMR, 0) /* Protected High-Memory Region not supported. */ 850 | RT_BF_MAKE(VTD_BF_CAP_REG_CM, 1) /** @todo Figure out if required when we impl. caching. */ 851 | RT_BF_MAKE(VTD_BF_CAP_REG_SAGAW, fSlts & uSagaw) 852 | RT_BF_MAKE(VTD_BF_CAP_REG_MGAW, uMgaw) 853 | RT_BF_MAKE(VTD_BF_CAP_REG_ZLR, 1) /** @todo Figure out if/how to support zero-length reads. */ 854 | RT_BF_MAKE(VTD_BF_CAP_REG_FRO, DMAR_MMIO_OFF_FRCD_LO_REG >> 4) 855 | RT_BF_MAKE(VTD_BF_CAP_REG_SLLPS, fSlts & fSllps) 856 | RT_BF_MAKE(VTD_BF_CAP_REG_PSI, fPsi) 857 | RT_BF_MAKE(VTD_BF_CAP_REG_NFR, DMAR_FRCD_REG_COUNT - 1) 858 | RT_BF_MAKE(VTD_BF_CAP_REG_MAMV, fPsi & fMamv) 859 | RT_BF_MAKE(VTD_BF_CAP_REG_DWD, 1) 860 | RT_BF_MAKE(VTD_BF_CAP_REG_FL1GP, fFlts & fFl1gp) 861 | RT_BF_MAKE(VTD_BF_CAP_REG_PI, 0) /* Posted Interrupts not supported. */ 862 | RT_BF_MAKE(VTD_BF_CAP_REG_FL5LP, fFlts & fFl5lp); 863 dmarRegWriteRaw64(pThis, VTD_MMIO_OFF_CAP_REG, pThis->fCap); 820 864 } 865 821 866 /* ECAP_REG */ 822 867 { 823 uint64_t const uCap = RT_BF_MAKE(VTD_BF_ECAP_REG_C, 0) /* Accesses don't snoop CPU cache. */ 824 | RT_BF_MAKE(VTD_BF_ECAP_REG_QI, 1) 825 | RT_BF_MAKE(VTD_BF_ECAP_REG_DT, 0) /* Device-TLBs not supported. */ 826 | RT_BF_MAKE(VTD_BF_ECAP_REG_IR, 1) 827 | RT_BF_MAKE(VTD_BF_ECAP_REG_EIM, 0) /* Extended Interrupt Mode (32-bit APIC ID) not supported. */ 828 | RT_BF_MAKE(VTD_BF_ECAP_REG_PT, 1) 829 | RT_BF_MAKE(VTD_BF_ECAP_REG_SC, 0) /* Snoop Control not supported. */ 830 | RT_BF_MAKE(VTD_BF_ECAP_REG_IRO, DMAR_MMIO_OFF_IVA_REG >> 4) 831 | RT_BF_MAKE(VTD_BF_ECAP_REG_MHMV, DMAR_ECAP_MHMV) 832 | RT_BF_MAKE(VTD_BF_ECAP_REG_MTS, 0) /* Memory Type not supported. */ 833 | RT_BF_MAKE(VTD_BF_ECAP_REG_NEST, 0) /* Nested Translation not supported. */ 834 | RT_BF_MAKE(VTD_BF_ECAP_REG_PRS, 0) /* Page Request not supported. */ 835 | RT_BF_MAKE(VTD_BF_ECAP_REG_ERS, 0) /* Execute Request not supported. */ 836 | RT_BF_MAKE(VTD_BF_ECAP_REG_SRS, 0) /* Supervisor Request not supported. */ 837 | RT_BF_MAKE(VTD_BF_ECAP_REG_SRS, 0) /* Supervisor Request not supported. */ 838 | RT_BF_MAKE(VTD_BF_ECAP_REG_NWFS, 0) /* 0 as DT not supported. */ 839 | RT_BF_MAKE(VTD_BF_ECAP_REG_EAFS, 0) /* 0 as SMTS not supported. */ 840 | RT_BF_MAKE(VTD_BF_ECAP_REG_PSS, 0) /* 0 as SMTS not supported. */ 841 | RT_BF_MAKE(VTD_BF_ECAP_REG_PASID, 0) /* 0 as SMTS not supported. */ 842 | RT_BF_MAKE(VTD_BF_ECAP_REG_DIT, 0) /* 0 as DT not supported. */ 843 | RT_BF_MAKE(VTD_BF_ECAP_REG_PDS, 0) /* 0 as DT not supported. */ 844 | RT_BF_MAKE(VTD_BF_ECAP_REG_SMTS, 0) /** @todo SMTS? Figure out if we can do this or requires PASID? */ 845 | RT_BF_MAKE(VTD_BF_ECAP_REG_VCS, 0) /* 0 as PASID not supported. */ 846 | RT_BF_MAKE(VTD_BF_ECAP_REG_SLADS, 0) /* 0 as SMTS not supported. */ 847 | RT_BF_MAKE(VTD_BF_ECAP_REG_SLTS, 0) /** @todo SLTS? Figure out if we can do this */ 848 | RT_BF_MAKE(VTD_BF_ECAP_REG_FLTS, 0) /** @todo FLTS? Figure out if we can do this */ 849 | RT_BF_MAKE(VTD_BF_ECAP_REG_SMPWCS, 0) /* 0 as SMTS not supported. */ 850 | RT_BF_MAKE(VTD_BF_ECAP_REG_RPS, 0); /* 0 as SMTS not supported. */ 851 dmarRegWriteRaw64(pThis, VTD_MMIO_OFF_ECAP_REG, uCap); 868 uint8_t const fIr = 1; /* Interrupt remapping support. */ 869 uint8_t const fMhmv = 0xf; /* Maximum handle mask value. */ 870 uint16_t const offIro = DMAR_MMIO_OFF_IVA_REG >> 4; /* MMIO offset of IOTLB registers. */ 871 uint8_t const fSrs = 1; /* Supervisor request support. */ 872 uint8_t const fEim = 1; /* Extended interrupt mode.*/ 873 874 pThis->fExtCap = RT_BF_MAKE(VTD_BF_ECAP_REG_C, 0) /* Accesses don't snoop CPU cache. */ 875 | RT_BF_MAKE(VTD_BF_ECAP_REG_QI, 1) 876 | RT_BF_MAKE(VTD_BF_ECAP_REG_DT, 0) /* Device-TLBs not supported. */ 877 | RT_BF_MAKE(VTD_BF_ECAP_REG_IR, fIr) 878 | RT_BF_MAKE(VTD_BF_ECAP_REG_EIM, fIr & fEim) 879 | RT_BF_MAKE(VTD_BF_ECAP_REG_PT, fPt) 880 | RT_BF_MAKE(VTD_BF_ECAP_REG_SC, 0) /* Snoop control not supported. */ 881 | RT_BF_MAKE(VTD_BF_ECAP_REG_IRO, offIro) 882 | RT_BF_MAKE(VTD_BF_ECAP_REG_MHMV, fIr & fMhmv) 883 | RT_BF_MAKE(VTD_BF_ECAP_REG_MTS, 0) /* Memory type not supported. */ 884 | RT_BF_MAKE(VTD_BF_ECAP_REG_NEST, fNest) 885 | RT_BF_MAKE(VTD_BF_ECAP_REG_PRS, 0) /* 0 as DT not supported. */ 886 | RT_BF_MAKE(VTD_BF_ECAP_REG_ERS, 0) /* Execute request not supported. */ 887 | RT_BF_MAKE(VTD_BF_ECAP_REG_SRS, fSmts & fSrs) 888 | RT_BF_MAKE(VTD_BF_ECAP_REG_NWFS, 0) /* 0 as DT not supported. */ 889 | RT_BF_MAKE(VTD_BF_ECAP_REG_EAFS, 0) /* 0 as PASID not supported. */ 890 | RT_BF_MAKE(VTD_BF_ECAP_REG_PSS, 0) /* 0 as PASID not supported. */ 891 | RT_BF_MAKE(VTD_BF_ECAP_REG_PASID, 0) /* PASID support. */ 892 | RT_BF_MAKE(VTD_BF_ECAP_REG_DIT, 0) /* 0 as DT not supported. */ 893 | RT_BF_MAKE(VTD_BF_ECAP_REG_PDS, 0) /* 0 as DT not supported. */ 894 | RT_BF_MAKE(VTD_BF_ECAP_REG_SMTS, fSmts) 895 | RT_BF_MAKE(VTD_BF_ECAP_REG_VCS, 0) /* 0 as PASID not supported (commands seem PASID specific). */ 896 | RT_BF_MAKE(VTD_BF_ECAP_REG_SLADS, 0) /* Second-level accessed/dirty not supported. */ 897 | RT_BF_MAKE(VTD_BF_ECAP_REG_SLTS, fSlts) 898 | RT_BF_MAKE(VTD_BF_ECAP_REG_FLTS, fFlts) 899 | RT_BF_MAKE(VTD_BF_ECAP_REG_SMPWCS, 0) /* 0 as PASID not supported. */ 900 | RT_BF_MAKE(VTD_BF_ECAP_REG_RPS, 0); /* 0 as PASID not supported. */ 901 dmarRegWriteRaw64(pThis, VTD_MMIO_OFF_ECAP_REG, pThis->fExtCap); 852 902 } 853 } 854 855 856 /** 857 * Initializes all registers in the DMAR unit. 858 * 859 * @param pDevIns The IOMMU device instance. 860 */ 861 static void dmarR3RegsInit(PPDMDEVINS pDevIns) 862 { 863 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 864 RT_ZERO(pThis->abRegs0); 865 RT_ZERO(pThis->abRegs1); 866 867 /* Initialize immutable registers prior to other registers. */ 868 dmarR3RegsInitImmutable(pDevIns); 869 903 904 /* 905 * Initialize registers mutable by software. 906 */ 870 907 /* FECTL_REG */ 871 908 { … … 873 910 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_FECTL_REG, uCtl); 874 911 } 912 875 913 /* ICETL_REG */ 876 914 { … … 894 932 RT_NOREF1(pDevIns); 895 933 LogFlowFunc(("\n")); 934 935 dmarR3RegsInit(pDevIns); 896 936 } 897 937 … … 994 1034 AssertRCReturn(rc, rc); 995 1035 996 # 1036 #ifdef VBOX_WITH_STATISTICS 997 1037 /* 998 1038 * Statistics. … … 1018 1058 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMemBulkWriteR3, STAMTYPE_COUNTER, "R3/MemBulkWrite", STAMUNIT_OCCURENCES, "Number of memory bulk write translation requests in R3."); 1019 1059 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMemBulkWriteRZ, STAMTYPE_COUNTER, "RZ/MemBulkWrite", STAMUNIT_OCCURENCES, "Number of memory bulk write translation requests in RZ."); 1020 # 1060 #endif 1021 1061 1022 1062 /* 1023 * Initialize all DMAR registers (order is important).1063 * Initialize registers. 1024 1064 */ 1025 1065 dmarR3RegsInit(pDevIns); 1026 1066 1027 uint64_t const fCap = dmarRegRead64(pThis, VTD_MMIO_OFF_CAP_REG); 1028 uint64_t const fExtCap = dmarRegRead64(pThis, VTD_MMIO_OFF_ECAP_REG); 1029 uint8_t const uMaxGstAddrBits = RT_BF_GET(fCap, VTD_BF_CAP_REG_MGAW) + 1; 1030 uint8_t const uSupGstAddrBits = vtdGetSupGstAddrBits(RT_BF_GET(fCap, VTD_BF_CAP_REG_SAGAW)); 1031 LogRel(("%s: CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%u bits)\n", DMAR_LOG_PFX, fCap, fExtCap, uMaxGstAddrBits, 1032 uSupGstAddrBits)); 1067 uint8_t const cMaxGstAddrBits = RT_BF_GET(pThis->fCap, VTD_BF_CAP_REG_MGAW) + 1; 1068 uint8_t const cSupGstAddrBits = vtdGetSupGstAddrBits(RT_BF_GET(pThis->fCap, VTD_BF_CAP_REG_SAGAW)); 1069 LogRel(("%s: CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%u bits)\n", DMAR_LOG_PFX, pThis->fCap, pThis->fExtCap, 1070 cMaxGstAddrBits, cSupGstAddrBits)); 1033 1071 return VINF_SUCCESS; 1034 1072 }
Note:
See TracChangeset
for help on using the changeset viewer.