VirtualBox

Changeset 89216 in vbox for trunk/src/VBox/Devices/Bus


Ignore:
Timestamp:
May 21, 2021 11:17:05 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144558
Message:

Intel IOMMU: bugref:9967 Address translation, WIP.

File:
1 edited

Legend:

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

    r89201 r89216  
    12371237
    12381238/**
     1239 * Records a primary fault.
     1240 *
     1241 * @param   pDevIns     The IOMMU device instance.
     1242 * @param   enmDiag     The diagnostic reason.
     1243 * @param   uFrcdHi     The FRCD_HI_REG value for this fault.
     1244 * @param   uFrcdLo     The FRCD_LO_REG value for this fault.
     1245 */
     1246static void dmarPrimaryFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, uint64_t uFrcdHi, uint64_t uFrcdLo)
     1247{
     1248    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
     1249    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
     1250
     1251    DMAR_LOCK(pDevIns, pThisCC);
     1252
     1253    /* Update the diagnostic reason. */
     1254    pThis->enmDiag = enmDiag;
     1255
     1256    /* We don't support advance fault logging. */
     1257    Assert(!(dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG) & VTD_BF_GSTS_REG_AFLS_MASK));
     1258
     1259    if (dmarPrimaryFaultCanRecord(pDevIns, pThis))
     1260    {
     1261        /* Update the fault recording registers with the fault information. */
     1262        dmarRegWriteRaw64(pThis, DMAR_MMIO_OFF_FRCD_HI_REG, uFrcdHi);
     1263        dmarRegWriteRaw64(pThis, DMAR_MMIO_OFF_FRCD_LO_REG, uFrcdLo);
     1264
     1265        /* Set the Pending Primary Fault (PPF) field in the status register. */
     1266        dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_FSTS_REG, UINT32_MAX, VTD_BF_FSTS_REG_PPF_MASK);
     1267
     1268        /* Raise interrupt if necessary. */
     1269        dmarFaultEventRaiseInterrupt(pDevIns);
     1270    }
     1271
     1272    DMAR_UNLOCK(pDevIns, pThisCC);
     1273}
     1274
     1275
     1276/**
    12391277 * Records an interrupt request fault.
    12401278 *
     
    12451283 * @param   idxIntr         The interrupt index.
    12461284 */
    1247 static void dmarIrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDINTRFAULT enmIntrFault, uint16_t idDevice,
    1248                               uint16_t idxIntr)
    1249 {
    1250     PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
    1251     PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
    1252 
    1253     DMAR_LOCK(pDevIns, pThisCC);
    1254 
    1255     /* Update the diagnostic reason. */
    1256     pThis->enmDiag = enmDiag;
    1257 
    1258     /* We don't support advance fault logging. */
    1259     Assert(!(dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG) & VTD_BF_GSTS_REG_AFLS_MASK));
    1260 
    1261     if (dmarPrimaryFaultCanRecord(pDevIns, pThis))
    1262     {
    1263         /* Update the fault recording registers with the fault information. */
    1264         uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID, idDevice)
    1265                                | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR,  enmIntrFault)
    1266                                | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F,   1);
    1267         uint64_t const uFrcdLo = (uint64_t)idxIntr << 48;
    1268         dmarRegWriteRaw64(pThis, DMAR_MMIO_OFF_FRCD_HI_REG, uFrcdHi);
    1269         dmarRegWriteRaw64(pThis, DMAR_MMIO_OFF_FRCD_LO_REG, uFrcdLo);
    1270 
    1271         /* Set the Pending Primary Fault (PPF) field in the status register. */
    1272         dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_FSTS_REG, UINT32_MAX, VTD_BF_FSTS_REG_PPF_MASK);
    1273 
    1274         /* Raise interrupt if necessary. */
    1275         dmarFaultEventRaiseInterrupt(pDevIns);
    1276     }
    1277 
    1278     DMAR_UNLOCK(pDevIns, pThisCC);
     1285static void dmarIntrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDINTRFAULT enmIntrFault, uint16_t idDevice,
     1286                                uint16_t idxIntr)
     1287{
     1288    uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID, idDevice)
     1289                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR,  enmIntrFault)
     1290                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F,   1);
     1291    uint64_t const uFrcdLo = (uint64_t)idxIntr << 48;
     1292    dmarPrimaryFaultRecord(pDevIns, enmDiag, uFrcdHi, uFrcdLo);
    12791293}
    12801294
     
    12931307 * @param   pIrte           The IRTE that caused this fault.
    12941308 */
    1295 static void dmarIrFaultRecordQualified(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDINTRFAULT enmIntrFault, uint16_t idDevice,
    1296                                        uint16_t idxIntr, PCVTD_IRTE_T pIrte)
     1309static void dmarIntrFaultRecordQualified(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDINTRFAULT enmIntrFault, uint16_t idDevice,
     1310                                         uint16_t idxIntr, PCVTD_IRTE_T pIrte)
    12971311{
    12981312    Assert(vtdIrFaultIsQualified(enmIntrFault));
    12991313    Assert(pIrte);
    13001314    if (!(pIrte->au64[0] & VTD_BF_0_IRTE_FPD_MASK))
    1301         return dmarIrFaultRecord(pDevIns, enmDiag, enmIntrFault, idDevice, idxIntr);
     1315        return dmarIntrFaultRecord(pDevIns, enmDiag, enmIntrFault, idDevice, idxIntr);
     1316}
     1317
     1318
     1319/**
     1320 * Records an address translation fault.
     1321 *
     1322 * @param   pDevIns         The IOMMU device instance.
     1323 * @param   enmDiag         The diagnostic reason.
     1324 * @param   enmAddrFault    The address translation fault reason.
     1325 * @param   idDevice        The device ID (bus, device, function).
     1326 * @param   uFaultAddr      The page address of the faulted request.
     1327 * @param   enmReqType      The type of the faulted request.
     1328 * @param   uAddrType       The address type of the faulted request (only applicable
     1329 *                          when device-TLB is supported).
     1330 * @param   fHasPasid       Whether the faulted request has a PASID TLP prefix.
     1331 * @param   uPasid          The PASID value when a PASID TLP prefix is present.
     1332 * @param   fExec           Execute permission was requested by the faulted request.
     1333 * @param   fPriv           Supervisor privilege permission was requested by the
     1334 *                          faulted request.
     1335 */
     1336static void dmarAddrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDADDRFAULT enmAddrFault, uint16_t idDevice,
     1337                                uint64_t uFaultAddr, VTDREQTYPE enmReqType, uint8_t uAddrType, bool fHasPasid, uint32_t uPasid,
     1338                                bool fExec, bool fPriv)
     1339{
     1340    uint8_t const fType1 = enmReqType & RT_BIT(1);
     1341    uint8_t const fType2 = enmReqType & RT_BIT(0);
     1342    uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID,  idDevice)
     1343                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T2,   fType2)
     1344                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PP,   fHasPasid)
     1345                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_EXE,  fExec)
     1346                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PRIV, fPriv)
     1347                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR,   enmAddrFault)
     1348                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PV,   uPasid)
     1349                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_AT,   uAddrType)
     1350                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T1,   fType1)
     1351                           | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F,    1);
     1352    uint64_t const uFrcdLo = uFaultAddr & X86_PAGE_BASE_MASK;
     1353    dmarPrimaryFaultRecord(pDevIns, enmDiag, uFrcdHi, uFrcdLo);
    13021354}
    13031355
     
    17051757    DMAR_UNLOCK(pDevIns, pThisCC);
    17061758
    1707 
    17081759    if (uGstsReg & VTD_BF_GSTS_REG_TES_MASK)
    17091760    {
     1761        VTDREQTYPE enmReqType;
    17101762        if (fFlags & PDMIOMMU_MEM_F_READ)
     1763        {
    17111764            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemRead));
     1765            enmReqType = VTDREQTYPE_READ;
     1766        }
    17121767        else
     1768        {
    17131769            STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemWrite));
     1770            enmReqType = VTDREQTYPE_WRITE;
     1771        }
    17141772
    17151773        uint8_t const fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM);
     
    17211779                if (pThis->fExtCapReg & VTD_BF_ECAP_REG_ADMS_MASK)
    17221780                {
    1723 
    17241781                }
    17251782            }
     
    18991956                                return VINF_SUCCESS;
    19001957                            }
    1901                             dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Mode_Invalid,
    1902                                                        VTDINTRFAULT_IRTE_PRESENT_RSVD, idDevice, idxIntr, &Irte);
     1958                            dmarIntrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Mode_Invalid,
     1959                                                         VTDINTRFAULT_IRTE_PRESENT_RSVD, idDevice, idxIntr, &Irte);
    19031960                        }
    19041961                        else
    1905                             dmarIrFaultRecordQualified(pDevIns, enmIrDiag, VTDINTRFAULT_IRTE_PRESENT_RSVD, idDevice, idxIntr,
    1906                                                        &Irte);
     1962                            dmarIntrFaultRecordQualified(pDevIns, enmIrDiag, VTDINTRFAULT_IRTE_PRESENT_RSVD, idDevice, idxIntr,
     1963                                                         &Irte);
    19071964                    }
    19081965                    else
    1909                         dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, VTDINTRFAULT_IRTE_PRESENT_RSVD, idDevice,
    1910                                                    idxIntr, &Irte);
     1966                        dmarIntrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, VTDINTRFAULT_IRTE_PRESENT_RSVD,
     1967                                                     idDevice, idxIntr, &Irte);
    19111968                }
    19121969                else
    1913                     dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, VTDINTRFAULT_IRTE_NOT_PRESENT,
    1914                                                idDevice, idxIntr, &Irte);
     1970                    dmarIntrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, VTDINTRFAULT_IRTE_NOT_PRESENT,
     1971                                                 idDevice, idxIntr, &Irte);
    19151972            }
    19161973            else
    1917                 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, VTDINTRFAULT_IRTE_READ_FAILED, idDevice, idxIntr);
     1974                dmarIntrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, VTDINTRFAULT_IRTE_READ_FAILED, idDevice, idxIntr);
    19181975        }
    19191976        else
    1920             dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, VTDINTRFAULT_INTR_INDEX_INVALID, idDevice, idxIntr);
     1977            dmarIntrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, VTDINTRFAULT_INTR_INDEX_INVALID, idDevice, idxIntr);
    19211978    }
    19221979    else
    1923         dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Rsvd, VTDINTRFAULT_REMAPPABLE_INTR_RSVD, idDevice, 0 /* idxIntr */);
     1980        dmarIntrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Rsvd, VTDINTRFAULT_REMAPPABLE_INTR_RSVD, idDevice, 0 /* idxIntr */);
    19241981    return VERR_IOMMU_INTR_REMAP_DENIED;
    19251982}
     
    19652022                || !(uGstsReg & VTD_BF_GSTS_REG_CFIS_MASK))
    19662023            {
    1967                 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Cfi_Blocked, VTDINTRFAULT_CFI_BLOCKED, idDevice, 0 /* idxIntr */);
     2024                dmarIntrFaultRecord(pDevIns, kDmarDiag_Ir_Cfi_Blocked, VTDINTRFAULT_CFI_BLOCKED, idDevice, 0 /* idxIntr */);
    19682025                return VERR_IOMMU_INTR_REMAP_DENIED;
    19692026            }
     
    20092066        switch (off)
    20102067        {
    2011             case VTD_MMIO_OFF_GCMD_REG:         /* 32-bit */
     2068            case VTD_MMIO_OFF_GCMD_REG:             /* 32-bit */
    20122069            {
    20132070                rcStrict = dmarGcmdRegWrite(pDevIns, uRegWritten);
     
    20152072            }
    20162073
    2017             case VTD_MMIO_OFF_CCMD_REG:         /* 64-bit */
     2074            case VTD_MMIO_OFF_CCMD_REG:             /* 64-bit */
    20182075            case VTD_MMIO_OFF_CCMD_REG + 4:
    20192076            {
     
    20222079            }
    20232080
    2024             case VTD_MMIO_OFF_FSTS_REG:         /* 32-bit */
     2081            case VTD_MMIO_OFF_FSTS_REG:             /* 32-bit */
    20252082            {
    20262083                rcStrict = dmarFstsRegWrite(pDevIns, uRegWritten, uPrev);
     
    20282085            }
    20292086
    2030             case VTD_MMIO_OFF_FECTL_REG:        /* 32-bit */
     2087            case VTD_MMIO_OFF_FECTL_REG:            /* 32-bit */
    20312088            {
    20322089                rcStrict = dmarFectlRegWrite(pDevIns, uRegWritten);
     
    20342091            }
    20352092
    2036             case VTD_MMIO_OFF_IQT_REG:          /* 64-bit */
    2037             /*   VTD_MMIO_OFF_IQT_REG + 4: */   /* High 32-bits reserved. */
     2093            case VTD_MMIO_OFF_IQT_REG:              /* 64-bit */
     2094            /*   VTD_MMIO_OFF_IQT_REG + 4: */       /* High 32-bits reserved. */
    20382095            {
    20392096                rcStrict = dmarIqtRegWrite(pDevIns, offReg, uRegWritten);
     
    20412098            }
    20422099
    2043             case VTD_MMIO_OFF_IQA_REG:          /* 64-bit */
    2044             /*   VTD_MMIO_OFF_IQA_REG + 4: */   /* High 32-bits data. */
     2100            case VTD_MMIO_OFF_IQA_REG:              /* 64-bit */
     2101            /*   VTD_MMIO_OFF_IQA_REG + 4: */       /* High 32-bits data. */
    20452102            {
    20462103                rcStrict = dmarIqaRegWrite(pDevIns, offReg, uRegWritten);
     
    20482105            }
    20492106
    2050             case VTD_MMIO_OFF_ICS_REG:          /* 32-bit */
     2107            case VTD_MMIO_OFF_ICS_REG:              /* 32-bit */
    20512108            {
    20522109                rcStrict = dmarIcsRegWrite(pDevIns, uRegWritten);
     
    20542111            }
    20552112
    2056             case VTD_MMIO_OFF_IECTL_REG:        /* 32-bit */
     2113            case VTD_MMIO_OFF_IECTL_REG:            /* 32-bit */
    20572114            {
    20582115                rcStrict = dmarIectlRegWrite(pDevIns, uRegWritten);
     
    20602117            }
    20612118
    2062             case DMAR_MMIO_OFF_FRCD_HI_REG:     /* 64-bit */
     2119            case DMAR_MMIO_OFF_FRCD_HI_REG:         /* 64-bit */
    20632120            case DMAR_MMIO_OFF_FRCD_HI_REG + 4:
    20642121            {
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