Changeset 108447 in vbox for trunk/src/VBox/VMM/VMMAll/GICAll.cpp
- Timestamp:
- Mar 5, 2025 9:04:20 AM (7 weeks ago)
- svn:sync-xref-src-repo-rev:
- 167821
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/GICAll.cpp
r108443 r108447 1813 1813 1814 1814 1815 #if 1 1816 /** 1817 * Gets the highest priority pending interrupt that can be signalled to the PE. 1818 * 1819 * @returns The interrupt ID or GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT if no interrupt 1820 * is pending or not in a state to be signalled to the PE. 1821 * @param pGicDev The GIC distributor state. 1822 * @param pGicCpu The GIC redistributor and CPU interface state. 1823 * @param fGroup0 Whether to consider group 0 interrupts. 1824 * @param fGroup1 Whether to consider group 1 interrupts. 1825 * @param pidxIntr Where to store the distributor interrupt index for the 1826 * returned interrupt ID. UINT16_MAX if this function returns 1827 * GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT. Optional, can be 1828 * NULL. 1829 * @param pbPriority Where to store the priority of the returned interrupt ID. 1830 * GIC_IDLE_PRIORITY if this function returns 1831 * GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT. 1832 */ 1833 static uint16_t gicGetHighestPrioPendingIntrEx(PCGICDEV pGicDev, PCGICCPU pGicCpu, bool fGroup0, bool fGroup1, 1834 uint16_t *pidxIntr, uint8_t *pbPriority) 1835 { 1836 #define GIC_DIST_INTR_COUNT RT_ELEMENTS(pGicDev->bmIntrPending) 1837 #define GIC_REDIST_INTR_COUNT RT_ELEMENTS(pGicCpu->bmIntrPending) 1838 1839 /* 1840 * Collect interrupts that are pending, enabled and inactive. 1841 * Discard interrupts if the group they belong to is disabled. 1842 */ 1843 uint32_t bmIntrPending[GIC_REDIST_INTR_COUNT + GIC_DIST_INTR_COUNT]; 1844 for (uint16_t i = 0; i < GIC_REDIST_INTR_COUNT; i++) 1845 { 1846 bmIntrPending[i] = (pGicCpu->bmIntrPending[i] & pGicCpu->bmIntrEnabled[i]) & ~pGicCpu->bmIntrActive[i]; 1847 if (!fGroup1) 1848 bmIntrPending[i] &= ~pGicCpu->bmIntrGroup[i]; 1849 if (!fGroup0) 1850 bmIntrPending[i] &= pGicCpu->bmIntrGroup[i]; 1851 } 1852 for (uint16_t i = 0; i < GIC_DIST_INTR_COUNT; i++) 1853 { 1854 uint16_t const idxPending = i + GIC_REDIST_INTR_COUNT; 1855 bmIntrPending[idxPending] = (pGicDev->bmIntrPending[i] & pGicDev->bmIntrEnabled[i]) & ~pGicDev->bmIntrActive[i]; 1856 if (!fGroup1) 1857 bmIntrPending[idxPending] &= ~pGicDev->bmIntrGroup[i]; 1858 if (!fGroup0) 1859 bmIntrPending[idxPending] &= pGicDev->bmIntrGroup[i]; 1860 } 1861 1862 /* 1863 * Among the collected interrupts, pick the one with the highest, non-idle priority. 1864 */ 1865 uint16_t uIntId = GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT; 1866 uint16_t idxHighest = UINT16_MAX; 1867 uint8_t uPriority = GIC_IDLE_PRIORITY; 1868 /* Redistributor. */ 1869 { 1870 const void *pvIntrs = &bmIntrPending[0]; 1871 uint32_t const cIntrs = sizeof(pGicCpu->bmIntrPending) * 8; AssertCompile(!(cIntrs % 32)); 1872 int32_t idxIntr = ASMBitFirstSet(pvIntrs, cIntrs); 1873 if (idxIntr >= 0) 1874 { 1875 do 1876 { 1877 if (pGicCpu->abIntrPriority[idxIntr] < uPriority) 1878 { 1879 idxHighest = (uint16_t)idxIntr; 1880 uPriority = pGicCpu->abIntrPriority[idxIntr]; 1881 } 1882 idxIntr = ASMBitNextSet(pvIntrs, cIntrs, idxIntr); 1883 } while (idxIntr != -1); 1884 if (uPriority != GIC_IDLE_PRIORITY) 1885 uIntId = gicReDistGetIntIdFromIndex(idxHighest); 1886 } 1887 } 1888 /* Distributor. */ 1889 { 1890 const void *pvIntrs = &bmIntrPending[GIC_REDIST_INTR_COUNT]; 1891 uint32_t const cIntrs = sizeof(pGicDev->bmIntrPending) * 8; AssertCompile(!(cIntrs % 32)); 1892 int32_t idxIntr = ASMBitFirstSet(pvIntrs, cIntrs); 1893 if (idxIntr >= 0) 1894 { 1895 do 1896 { 1897 if (pGicDev->abIntrPriority[idxIntr] < uPriority) 1898 { 1899 idxHighest = (uint16_t)idxIntr; 1900 uPriority = pGicDev->abIntrPriority[idxIntr]; 1901 } 1902 idxIntr = ASMBitNextSet(pvIntrs, cIntrs, idxIntr); 1903 } while (idxIntr != -1); 1904 if (uPriority != GIC_IDLE_PRIORITY) 1905 uIntId = gicDistGetIntIdFromIndex(idxHighest); 1906 } 1907 } 1908 1909 /* Sanity check if the interrupt ID is within known ranges. */ 1910 Assert( GIC_IS_INTR_SGI_OR_PPI(uIntId) 1911 || GIC_IS_INTR_EXT_PPI(uIntId) 1912 || GIC_IS_INTR_SPI(uIntId) 1913 || GIC_IS_INTR_EXT_PPI(uIntId) 1914 || GIC_IS_INTR_EXT_SPI(uIntId) 1915 || uIntId == GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT); 1916 /* Ensure that if no interrupt is pending, the idle priority is returned. */ 1917 Assert(uIntId != GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT || uPriority == GIC_IDLE_PRIORITY); 1918 1919 if (pbPriority) 1920 *pbPriority = uPriority; 1921 if (pidxIntr) 1922 *pidxIntr = idxHighest; 1923 1924 LogFlowFunc(("uIntId=%u [idxHighest=%u uPriority=%u]\n", uIntId, idxHighest, uPriority)); 1925 return uIntId; 1926 1927 #undef GIC_DIST_INTR_COUNT 1928 #undef GIC_REDIST_INTR_COUNT 1929 } 1930 #else 1815 1931 /** 1816 1932 * Gets the highest priority pending interrupt that can be signalled to the PE. … … 1853 1969 return uIntId; 1854 1970 } 1971 #endif 1855 1972 1856 1973 … … 3380 3497 #else 3381 3498 AssertReleaseFailed(); 3382 *pu64Value = gicGetHighestPrioPendingIntr(pVCpu, pGicDev, false /*fGroup0*/, true /*fGroup1*/); 3499 *pu64Value = gicGetHighestPrioPendingIntrEx(pGicDev, pGicCpu, false /*fGroup0*/, true /*fGroup1*/, NULL /*pidxIntr*/, 3500 NULL /*pbPriority*/); 3383 3501 #endif 3384 3502 break;
Note:
See TracChangeset
for help on using the changeset viewer.