Changeset 86210 in vbox for trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
- Timestamp:
- Sep 22, 2020 7:08:56 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r86209 r86210 1575 1575 }; 1576 1576 AssertCompile(RT_ELEMENTS(g_aRegAccess2) == (IOMMU_MMIO_OFF_QWORD_TABLE_2_END - IOMMU_MMIO_OFF_QWORD_TABLE_2_START) / 8); 1577 1578 1579 /** 1580 * Gets the register access structure given its MMIO offset. 1581 * 1582 * @returns The register access structure, or NULL if the offset is invalid. 1583 * @param off The MMIO offset of the register being accessed. 1584 */ 1585 static PCIOMMUREGACC iommuAmdGetRegAccessForOffset(uint32_t off) 1586 { 1587 /* Figure out which table the register belongs to and validate its index. */ 1588 PCIOMMUREGACC pReg; 1589 if (off < IOMMU_MMIO_OFF_QWORD_TABLE_0_END) 1590 { 1591 uint32_t const idxReg = off >> 3; 1592 Assert(idxReg < RT_ELEMENTS(g_aRegAccess0)); 1593 pReg = &g_aRegAccess0[idxReg]; 1594 } 1595 else if ( off < IOMMU_MMIO_OFF_QWORD_TABLE_1_END 1596 && off >= IOMMU_MMIO_OFF_QWORD_TABLE_1_START) 1597 { 1598 uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_1_START) >> 3; 1599 Assert(idxReg < RT_ELEMENTS(g_aRegAccess1)); 1600 pReg = &g_aRegAccess1[idxReg]; 1601 } 1602 else if ( off < IOMMU_MMIO_OFF_QWORD_TABLE_2_END 1603 && off >= IOMMU_MMIO_OFF_QWORD_TABLE_2_START) 1604 { 1605 uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_2_START) >> 3; 1606 Assert(idxReg < RT_ELEMENTS(g_aRegAccess2)); 1607 pReg = &g_aRegAccess2[idxReg]; 1608 } 1609 else 1610 return NULL; 1611 1612 return pReg; 1613 } 1577 1614 #endif 1578 1615 … … 1717 1754 } 1718 1755 #else 1719 /* 1720 * Figure out which table the register belongs to and validate its index. 1721 */ 1722 PCIOMMUREGACC pReg; 1723 if (off < IOMMU_MMIO_OFF_QWORD_TABLE_0_END) 1724 { 1725 uint32_t const idxReg = off >> 3; 1726 Assert(idxReg < RT_ELEMENTS(g_aRegAccess0)); 1727 pReg = &g_aRegAccess0[idxReg]; 1728 } 1729 else if ( off < IOMMU_MMIO_OFF_QWORD_TABLE_1_END 1730 && off >= IOMMU_MMIO_OFF_QWORD_TABLE_1_START) 1731 { 1732 uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_1_START) >> 3; 1733 Assert(idxReg < RT_ELEMENTS(g_aRegAccess1)); 1734 pReg = &g_aRegAccess1[idxReg]; 1735 } 1736 else if ( off < IOMMU_MMIO_OFF_QWORD_TABLE_2_END 1737 && off >= IOMMU_MMIO_OFF_QWORD_TABLE_2_START) 1738 { 1739 uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_2_START) >> 3; 1740 Assert(idxReg < RT_ELEMENTS(g_aRegAccess2)); 1741 pReg = &g_aRegAccess2[idxReg]; 1742 } 1756 PCIOMMUREGACC pReg = iommuAmdGetRegAccessForOffset(off); 1757 if (pReg) 1758 { /* likely */ } 1743 1759 else 1744 1760 { … … 1747 1763 } 1748 1764 1765 /* If a write handler doesn't exist, it's either a reserved or read-only register. */ 1766 if (pReg->pfnWrite) 1767 { /* likely */ } 1768 else 1769 { 1770 LogFunc(("Writing reserved or read-only register off=%#x (cb=%u) with %#RX64 -> Ignored\n", off, cb, uValue)); 1771 return VINF_SUCCESS; 1772 } 1773 1749 1774 /* 1750 * Ensure the register is writable and proceed.1751 * If a write handler doesn't exist, it's either a reserved or read-only register.1775 * If the write access is aligned and matches the register size, dispatch right away. 1776 * This handles all aligned, 32-bit writes as well as aligned 64-bit writes. 1752 1777 */ 1753 if (pReg->pfnWrite) 1778 if ( cb == pReg->cb 1779 && !(off & (cb - 1))) 1780 return pReg->pfnWrite(pDevIns, pThis, off, uValue); 1781 1782 /* 1783 * A 32-bit write for a 64-bit register. 1784 * We shouldn't get sizes other than 32 bits here as we've specified so with IOM. 1785 */ 1786 Assert(cb == 4); 1787 if (!(off & 7)) 1754 1788 { 1755 1789 /* 1756 * If the write access is aligned and matches the register size, dispatch right away.1757 * This handles all aligned, 32-bit writes as well as aligned 64-bit writes.1790 * Lower 32 bits of the register is being written. 1791 * Merge with higher 32 bits (after reading the full value from the register). 1758 1792 */ 1759 if ( cb == pReg->cb1760 && !(off & (cb - 1)))1761 return pReg->pfnWrite(pDevIns, pThis, off, uValue);1762 1763 /*1764 * A 32-bit write for a 64-bit register.1765 * We shouldn't get sizes other than 32 bits here as we've specified so with IOM.1766 */1767 Assert(cb == 4);1768 if (!(off & 7))1769 {1770 /*1771 * Lower 32 bits of the register is being written.1772 * Merge with higher 32 bits (after reading the full value from the register).1773 */1774 uint64_t u64Read;1775 if (pReg->pfnRead)1776 {1777 VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off, &u64Read);1778 if (RT_FAILURE(rcStrict))1779 {1780 LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict)));1781 return rcStrict;1782 }1783 }1784 else1785 u64Read = 0;1786 1787 uValue = (u64Read & UINT64_C(0xffffffff00000000)) | uValue;1788 return pReg->pfnWrite(pDevIns, pThis, off, uValue);1789 }1790 1791 /*1792 * Higher 32 bits of the register is being written.1793 * Merge with lower 32 bits (after reading the full value from the register).1794 */1795 Assert(!(off & 3));1796 Assert(off & 7);1797 Assert(off > 4);1798 1793 uint64_t u64Read; 1799 1794 if (pReg->pfnRead) 1800 1795 { 1801 VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off - 4, &u64Read);1796 VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off, &u64Read); 1802 1797 if (RT_FAILURE(rcStrict)) 1803 1798 { … … 1809 1804 u64Read = 0; 1810 1805 1811 uValue = (uValue << 32) | (u64Read & UINT64_C(0xffffffff)); 1812 return pReg->pfnWrite(pDevIns, pThis, off - 4, uValue); 1806 uValue = (u64Read & UINT64_C(0xffffffff00000000)) | uValue; 1807 return pReg->pfnWrite(pDevIns, pThis, off, uValue); 1808 } 1809 1810 /* 1811 * Higher 32 bits of the register is being written. 1812 * Merge with lower 32 bits (after reading the full value from the register). 1813 */ 1814 Assert(!(off & 3)); 1815 Assert(off & 7); 1816 Assert(off > 4); 1817 uint64_t u64Read; 1818 if (pReg->pfnRead) 1819 { 1820 VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off - 4, &u64Read); 1821 if (RT_FAILURE(rcStrict)) 1822 { 1823 LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict))); 1824 return rcStrict; 1825 } 1813 1826 } 1814 1827 else 1815 LogFunc(("Writing reserved or read-only register off=%#x (cb=%u) with %#RX64 -> Ignored\n", off, cb, uValue)); 1816 1817 return VINF_SUCCESS; 1828 u64Read = 0; 1829 1830 uValue = (uValue << 32) | (u64Read & UINT64_C(0xffffffff)); 1831 return pReg->pfnWrite(pDevIns, pThis, off - 4, uValue); 1818 1832 #endif 1819 1833 }
Note:
See TracChangeset
for help on using the changeset viewer.