Changeset 89029 in vbox
- Timestamp:
- May 13, 2021 8:26:23 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 144368
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r89028 r89029 868 868 * @param offReg The MMIO offset of the register. 869 869 * @param uReg The 32-bit value to write. 870 */ 871 static uint32_t dmarRegWrite32(PDMAR pThis, uint16_t offReg, uint32_t uReg) 870 * @param puPrev Where to store the register value prior to writing. 871 */ 872 static uint32_t dmarRegWrite32(PDMAR pThis, uint16_t offReg, uint32_t uReg, uint32_t *puPrev) 872 873 { 873 874 /* Read current value from the 32-bit register. */ … … 876 877 uint32_t fRw1cMask; 877 878 dmarRegReadRaw32Ex(pThis, offReg, &uCurReg, &fRwMask, &fRw1cMask); 879 *puPrev = uCurReg; 878 880 879 881 uint32_t const fRoBits = uCurReg & ~fRwMask; /* Preserve current read-only and reserved bits. */ … … 896 898 * @param offReg The MMIO offset of the register. 897 899 * @param uReg The 64-bit value to write. 898 */ 899 static uint64_t dmarRegWrite64(PDMAR pThis, uint16_t offReg, uint64_t uReg) 900 * @param puPrev Where to store the register value prior to writing. 901 */ 902 static uint64_t dmarRegWrite64(PDMAR pThis, uint16_t offReg, uint64_t uReg, uint64_t *puPrev) 900 903 { 901 904 /* Read current value from the 64-bit register. */ … … 904 907 uint64_t fRw1cMask; 905 908 dmarRegReadRaw64Ex(pThis, offReg, &uCurReg, &fRwMask, &fRw1cMask); 909 *puPrev = uCurReg; 906 910 907 911 uint64_t const fRoBits = uCurReg & ~fRwMask; /* Preserve current read-only and reserved bits. */ … … 1227 1231 { 1228 1232 uFstsReg |= VTD_BF_FSTS_REG_PFO_MASK; 1229 dmarRegWrite 32(pThis, VTD_MMIO_OFF_FSTS_REG, uFstsReg);1233 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_FSTS_REG, uFstsReg); 1230 1234 return false; 1231 1235 } … … 1399 1403 * ESRTPS is supported. */ 1400 1404 pThis->uRtaddrReg = dmarRegReadRaw64(pThis, VTD_MMIO_OFF_RTADDR_REG); 1405 dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_GSTS_REG, UINT32_MAX, VTD_BF_GSTS_REG_RTPS_MASK); 1401 1406 } 1402 1407 … … 1462 1467 1463 1468 /** 1469 * Handles writes to FECTL_REG. 1470 * 1471 * @returns Strict VBox status code. 1472 * @param pDevIns The IOMMU device instance. 1473 * @param uFectlReg The value written to FECTL_REG. 1474 */ 1475 static VBOXSTRICTRC dmarFectlRegWrite(PPDMDEVINS pDevIns, uint32_t uFectlReg) 1476 { 1477 /* 1478 * If software unmasks the interrupt when the interrupt is pending, we must raise 1479 * the interrupt now (which will consequently clear the interrupt pending (IP) bit). 1480 */ 1481 if ( (uFectlReg & VTD_BF_FECTL_REG_IP_MASK) 1482 && ~(uFectlReg & VTD_BF_FECTL_REG_IM_MASK)) 1483 dmarEventRaiseInterrupt(pDevIns, DMAREVENTTYPE_FAULT); 1484 return VINF_SUCCESS; 1485 } 1486 1487 1488 /** 1489 * Handles writes to FSTS_REG. 1490 * 1491 * @returns Strict VBox status code. 1492 * @param pDevIns The IOMMU device instance. 1493 * @param uFstsReg The value written to FSTS_REG. 1494 * @param uPrev The value in FSTS_REG prior to writing it. 1495 */ 1496 static VBOXSTRICTRC dmarFstsRegWrite(PPDMDEVINS pDevIns, uint32_t uFstsReg, uint32_t uPrev) 1497 { 1498 /* 1499 * If software clears other status bits in FSTS_REG (pertaining to primary fault logging), 1500 * the interrupt pending (IP) bit must be cleared. 1501 * 1502 * See Intel VT-d spec. 10.4.10 "Fault Event Control Register". 1503 */ 1504 uint32_t const fChanged = uPrev ^ uFstsReg; 1505 if (fChanged & ( VTD_BF_FSTS_REG_ICE_MASK | VTD_BF_FSTS_REG_ITE_MASK 1506 | VTD_BF_FSTS_REG_IQE_MASK | VTD_BF_FSTS_REG_PFO_MASK)) 1507 { 1508 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1509 dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_FECTL_REG, ~VTD_BF_FECTL_REG_IP_MASK, 0 /* fOrMask */); 1510 } 1511 return VINF_SUCCESS; 1512 } 1513 1514 1515 /** 1464 1516 * Handles writes to IQT_REG. 1465 1517 * … … 1562 1614 /* 1563 1615 * If software unmasks the interrupt when the interrupt is pending, we must raise 1564 * the interrupt now (which will consequently clear the interrupt pending bit).1616 * the interrupt now (which will consequently clear the interrupt pending (IP) bit). 1565 1617 */ 1566 1618 if ( (uIectlReg & VTD_BF_IECTL_REG_IP_MASK) 1567 1619 && ~(uIectlReg & VTD_BF_IECTL_REG_IM_MASK)) 1568 1620 dmarEventRaiseInterrupt(pDevIns, DMAREVENTTYPE_INV_COMPLETE); 1621 return VINF_SUCCESS; 1622 } 1623 1624 1625 /** 1626 * Handles writes to FRCD_REG (High 64-bits). 1627 * 1628 * @returns Strict VBox status code. 1629 * @param pDevIns The IOMMU device instance. 1630 * @param offReg The MMIO register offset. 1631 * @param cbReg The size of the MMIO access (in bytes). 1632 * @param uFrcdHiReg The value written to FRCD_REG. 1633 * @param uPrev The value in FRCD_REG prior to writing it. 1634 */ 1635 static VBOXSTRICTRC dmarFrcdHiRegWrite(PPDMDEVINS pDevIns, uint16_t offReg, uint8_t cbReg, uint64_t uFrcdHiReg, uint64_t uPrev) 1636 { 1637 /* We only care about responding to high 32-bits, low 32-bits are read-only. */ 1638 if (offReg + cbReg > DMAR_MMIO_OFF_FRCD_HI_REG + 4) 1639 { 1640 /* 1641 * If software cleared the RW1C F (fault) bit in all FRCD_REGs, hardware clears the 1642 * Primary Pending Fault (PPF) and the interrupt pending (IP) bits. Our implementation 1643 * has only 1 FRCD register. 1644 * 1645 * See Intel VT-d spec. 10.4.10 "Fault Event Control Register". 1646 */ 1647 AssertCompile(DMAR_FRCD_REG_COUNT == 1); 1648 uint64_t const fChanged = uPrev ^ uFrcdHiReg; 1649 if (fChanged & VTD_BF_1_FRCD_REG_F_MASK) 1650 { 1651 Assert(!(uFrcdHiReg & VTD_BF_1_FRCD_REG_F_MASK)); /* Software should only ever be able to clear this bit. */ 1652 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1653 dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_FSTS_REG, ~VTD_BF_FSTS_REG_PPF_MASK, 0 /* fOrMask */); 1654 dmarRegChangeRaw32(pThis, VTD_MMIO_OFF_FECTL_REG, ~VTD_BF_FECTL_REG_IP_MASK, 0 /* fOrMask */); 1655 } 1656 } 1569 1657 return VINF_SUCCESS; 1570 1658 } … … 1888 1976 DMAR_LOCK_RET(pDevIns, pThisCC, VINF_IOM_R3_MMIO_WRITE); 1889 1977 1890 uint64_t const uRegWritten = cb == 8 ? dmarRegWrite64(pThis, offReg, *(uint64_t *)pv) 1891 : dmarRegWrite32(pThis, offReg, *(uint32_t *)pv); 1978 uint64_t uPrev = 0; 1979 uint64_t const uRegWritten = cb == 8 ? dmarRegWrite64(pThis, offReg, *(uint64_t *)pv, &uPrev) 1980 : dmarRegWrite32(pThis, offReg, *(uint32_t *)pv, (uint32_t *)&uPrev); 1892 1981 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 1893 1982 switch (off) … … 1906 1995 } 1907 1996 1997 case VTD_MMIO_OFF_FSTS_REG: /* 32-bit */ 1998 { 1999 rcStrict = dmarFstsRegWrite(pDevIns, uRegWritten, uPrev); 2000 break; 2001 } 2002 2003 case VTD_MMIO_OFF_FECTL_REG: /* 32-bit */ 2004 { 2005 rcStrict = dmarFectlRegWrite(pDevIns, uRegWritten); 2006 break; 2007 } 2008 1908 2009 case VTD_MMIO_OFF_IQT_REG: /* 64-bit */ 1909 2010 /* VTD_MMIO_OFF_IQT_REG + 4: */ /* High 32-bits reserved. */ … … 1920 2021 } 1921 2022 1922 case VTD_MMIO_OFF_ICS_REG: /* 32-bit */2023 case VTD_MMIO_OFF_ICS_REG: /* 32-bit */ 1923 2024 { 1924 2025 rcStrict = dmarIcsRegWrite(pDevIns, uRegWritten); … … 1929 2030 { 1930 2031 rcStrict = dmarIectlRegWrite(pDevIns, uRegWritten); 2032 break; 2033 } 2034 2035 case DMAR_MMIO_OFF_FRCD_HI_REG: /* 64-bit */ 2036 case DMAR_MMIO_OFF_FRCD_HI_REG + 4: 2037 { 2038 rcStrict = dmarFrcdHiRegWrite(pDevIns, offReg, cb, uRegWritten, uPrev); 1931 2039 break; 1932 2040 }
Note:
See TracChangeset
for help on using the changeset viewer.