Changeset 108470 in vbox for trunk/src/VBox/VMM/VMMAll/GICAll.cpp
- Timestamp:
- Mar 7, 2025 7:23:33 AM (6 weeks ago)
- svn:sync-xref-src-repo-rev:
- 167846
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/GICAll.cpp
r108466 r108470 1829 1829 * GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT. 1830 1830 */ 1831 static uint16_t gicGetHighestPrio PendingIntrEx(PCGICDEV pGicDev, PCGICCPU pGicCpu, bool fGroup0, bool fGroup1,1832 uint16_t *pidxIntr, uint8_t *pbPriority)1831 static uint16_t gicGetHighestPriorityPendingIntrEx(PCGICDEV pGicDev, PCGICCPU pGicCpu, bool fGroup0, bool fGroup1, 1832 uint16_t *pidxIntr, uint8_t *pbPriority) 1833 1833 { 1834 1834 #define GIC_DIST_INTR_COUNT RT_ELEMENTS(pGicDev->bmIntrPending) … … 1980 1980 * @param fGroup1 Whether to consider group 1 interrupts. 1981 1981 */ 1982 static uint16_t gicAckHighestPrio PendingIntr(PGICDEV pGicDev, PVMCPUCC pVCpu, bool fGroup0, bool fGroup1)1982 static uint16_t gicAckHighestPriorityPendingIntr(PGICDEV pGicDev, PVMCPUCC pVCpu, bool fGroup0, bool fGroup1) 1983 1983 { 1984 1984 Assert(fGroup0 || fGroup1); 1985 1985 LogFlowFunc(("fGroup0=%RTbool fGroup1=%RTbool\n", fGroup0, fGroup1)); 1986 1986 1987 /* Get highest priority pending interrupt from the distributor. */ 1988 uint8_t bPriority; 1989 uint16_t idxIntr; 1990 PGICCPU pGicCpu = VMCPU_TO_GICCPU(pVCpu); 1991 uint16_t const uIntId = gicGetHighestPrioPendingIntrEx(pGicDev, pGicCpu, fGroup0, fGroup1, &idxIntr, &bPriority); 1992 1993 /* If the priority must be higher than the priority mask for the interrupt to be signalled/acknowledged. */ 1994 if (pGicCpu->bIntrPriorityMask <= bPriority) 1995 return GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT; 1996 1997 /* Acknowledge the interrupt. */ 1987 /* 1988 * Get the pending interrupt with the highest priority for the given group. 1989 */ 1990 uint8_t bIntrPriority; 1991 uint16_t idxIntr; 1992 PGICCPU pGicCpu = VMCPU_TO_GICCPU(pVCpu); 1993 uint16_t const uIntId = gicGetHighestPriorityPendingIntrEx(pGicDev, pGicCpu, fGroup0, fGroup1, &idxIntr, &bIntrPriority); 1994 1998 1995 if (uIntId != GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT) 1999 1996 { 1997 /* 1998 * The interrupt priority must be higher than the priority mask of the CPU interface for the 1999 * interrupt to be signalled/acknowledged. Here, we must NOT use priority grouping when comparing 2000 * the priority of a pending interrupt with this priority mask (threshold). 2001 * 2002 * See ARM GIC spec. 4.8.6 "Priority masking". 2003 */ 2004 if (bIntrPriority >= pGicCpu->bIntrPriorityMask) 2005 return GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT; 2006 2007 /* 2008 * The group priority of the pending interrupt must be higher than that of the running priority. 2009 * The number of bits for the group priority depends on the the binary point registers. 2010 * We mask the sub-priority bits and only compare the group priority. 2011 * 2012 * When the binary point registers indicates no preemption, we must allow interrupts that have 2013 * a higher priority than the idle. Hence the two different masks here. 2014 * 2015 * See ARM GIC spec. 4.8.3 "Priority grouping". 2016 * See ARM GIC spec. 4.8.5 "Preemption". 2017 */ 2018 static uint8_t const s_afGroupPriorityMasks[8] = { 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 }; 2019 static uint8_t const s_afRunningPriorityMasks[8] = { 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0xff }; 2020 uint8_t const idxPriorityMask = (fGroup0 || (pGicCpu->uIccCtlr & ARMV8_ICC_CTLR_EL1_AARCH64_CBPR)) 2021 ? pGicCpu->bBinaryPtGroup0 & 7 2022 : pGicCpu->bBinaryPtGroup1 & 7; 2023 uint8_t const fGroupPriorityMask = s_afGroupPriorityMasks[idxPriorityMask]; 2024 uint8_t const fRunningPriorityMask = s_afRunningPriorityMasks[idxPriorityMask]; 2025 uint8_t const bRunningPriority = pGicCpu->abRunningPriorities[pGicCpu->idxRunningPriority]; 2026 uint8_t const bRunningGroupPriority = bRunningPriority & fRunningPriorityMask; 2027 uint8_t const bIntrGroupPriority = bIntrPriority & fGroupPriorityMask; 2028 if (bIntrGroupPriority >= bRunningGroupPriority) 2029 return GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT; 2030 2031 /* 2032 * Acknowledge the interrupt. 2033 */ 2000 2034 bool const fIsRedistIntId = GIC_IS_INTR_SGI_OR_PPI(uIntId) || GIC_IS_INTR_EXT_PPI(uIntId); 2001 2035 if (fIsRedistIntId) 2002 2036 { 2003 /** @todo Check if the interrupt has sufficient priority (preemption level2004 * checking?). */2005 2006 2037 /* Mark the interrupt as active. */ 2007 2038 AssertMsg(idxIntr < sizeof(pGicCpu->bmIntrActive) * 8, ("idxIntr=%u\n", idxIntr)); … … 2013 2044 LogFlowFunc(("Dropping interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n", 2014 2045 pGicCpu->abRunningPriorities[pGicCpu->idxRunningPriority], 2015 b Priority,2046 bIntrPriority, 2016 2047 pGicCpu->idxRunningPriority, pGicCpu->idxRunningPriority + 1)); 2017 pGicCpu->abRunningPriorities[++pGicCpu->idxRunningPriority] = b Priority;2048 pGicCpu->abRunningPriorities[++pGicCpu->idxRunningPriority] = bIntrPriority; 2018 2049 2019 2050 /* If it is an edge-triggered interrupt, mark it as no longer pending. */ … … 2023 2054 ASMBitClear(&pGicCpu->bmIntrPending[0], idxIntr); 2024 2055 2025 /* Update the redistributor IRQ state to reflect change inactive interrupt. */2056 /* Update the redistributor IRQ state to reflect change to the active interrupt. */ 2026 2057 gicReDistUpdateIrqState(pGicDev, pVCpu); 2027 2058 } 2028 2059 else 2029 2060 { 2030 /** @todo Check if the interrupt has sufficient priority (preemption level2031 * checking?). */2032 2033 2061 /* Sanity check if the interrupt ID belongs to the distirbutor. */ 2034 2062 Assert(GIC_IS_INTR_SPI(uIntId) || GIC_IS_INTR_EXT_SPI(uIntId)); … … 2043 2071 LogFlowFunc(("Dropping interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n", 2044 2072 pGicCpu->abRunningPriorities[pGicCpu->idxRunningPriority], 2045 b Priority,2073 bIntrPriority, 2046 2074 pGicCpu->idxRunningPriority, pGicCpu->idxRunningPriority + 1)); 2047 pGicCpu->abRunningPriorities[++pGicCpu->idxRunningPriority] = b Priority;2075 pGicCpu->abRunningPriorities[++pGicCpu->idxRunningPriority] = bIntrPriority; 2048 2076 2049 2077 /* If it is an edge-triggered interrupt, mark it as no longer pending. */ … … 2053 2081 ASMBitClear(&pGicDev->bmIntrPending[0], idxIntr); 2054 2082 2055 /* Update the distributor IRQ state to reflect change inactive interrupt. */2083 /* Update the distributor IRQ state to reflect change to the active interrupt. */ 2056 2084 gicDistUpdateIrqState(pVCpu->CTX_SUFF(pVM), pGicDev); 2057 2085 } 2058 2086 } 2059 2087 else 2060 Assert(b Priority == GIC_IDLE_PRIORITY);2088 Assert(bIntrPriority == GIC_IDLE_PRIORITY); 2061 2089 2062 2090 LogFlowFunc(("uIntId=%u\n", uIntId)); … … 3462 3490 } 3463 3491 #else 3464 *pu64Value = gicAckHighestPrio PendingIntr(pGicDev, pVCpu, false /*fGroup0*/, true /*fGroup1*/);3492 *pu64Value = gicAckHighestPriorityPendingIntr(pGicDev, pVCpu, false /*fGroup0*/, true /*fGroup1*/); 3465 3493 #endif 3466 3494 break; … … 3493 3521 #else 3494 3522 AssertReleaseFailed(); 3495 *pu64Value = gicGetHighestPrio PendingIntrEx(pGicDev, pGicCpu, false /*fGroup0*/, true /*fGroup1*/, NULL /*pidxIntr*/,3496 NULL /*pbPriority*/);3523 *pu64Value = gicGetHighestPriorityPendingIntrEx(pGicDev, pGicCpu, false /*fGroup0*/, true /*fGroup1*/, 3524 NULL /*pidxIntr*/, NULL /*pbPriority*/); 3497 3525 #endif 3498 3526 break; … … 3837 3865 /* The binary point register are undefined on reset, initialized 3838 3866 with arbitrarily chosen values in our implementation. */ 3839 pGicCpu->bBinaryPtGroup0 = 3;3840 pGicCpu->bBinaryPtGroup1 = 3;3867 pGicCpu->bBinaryPtGroup0 = 0; 3868 pGicCpu->bBinaryPtGroup1 = 0; 3841 3869 } 3842 3870
Note:
See TracChangeset
for help on using the changeset viewer.