VirtualBox

Changeset 106370 in vbox


Ignore:
Timestamp:
Oct 16, 2024 1:25:07 PM (3 months ago)
Author:
vboxsync
Message:

VMM/GIC: Some updates to the emulation to make Windows happy enough, bugref:10404 bugref:10732

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/GICAll.cpp

    r106061 r106370  
    211211    bool fIrqGrp1Enabled  = ASMAtomicReadBool(&pThis->fIrqGrp1Enabled);
    212212
     213    /* Only allow interrupts with higher priority than the current configured and running one. */
     214    uint8_t bPriority = RT_MIN(pThis->bInterruptPriority, pThis->abRunningPriorities[pThis->idxRunningPriority]);
     215
    213216    /* Is anything enabled at all? */
    214217    uint32_t bmIntForward = (bmIntPending & bmIntEnabled) & ~bmIntActive; /* Exclude the currently active interrupt. */
    215 
    216     /* Only allow interrupts with higher priority than the current configured and running one. */
    217     uint8_t bPriority = RT_MIN(pThis->bInterruptPriority, pThis->abRunningPriorities[pThis->idxRunningPriority]);
    218 
    219     for (uint32_t i = 0; i < RT_ELEMENTS(pThis->abIntPriority); i++)
    220     {
    221         Log4(("SGI/PPI %u, configured priority %u, running priority %u\n", i, pThis->abIntPriority[i], bPriority));
    222         if (   (bmIntForward & RT_BIT_32(i))
    223             && pThis->abIntPriority[i] < bPriority)
    224             break;
    225         else
    226             bmIntForward &= ~RT_BIT_32(i);
    227 
    228         if (!bmIntForward)
    229             break;
     218    if (bmIntForward)
     219    {
     220        for (uint32_t i = 0; i < RT_ELEMENTS(pThis->abIntPriority); i++)
     221        {
     222            Log4(("SGI/PPI %u, configured priority %u, running priority %u\n", i, pThis->abIntPriority[i], bPriority));
     223            if (   (bmIntForward & RT_BIT_32(i))
     224                && pThis->abIntPriority[i] < bPriority)
     225                break;
     226            else
     227                bmIntForward &= ~RT_BIT_32(i);
     228
     229            if (!bmIntForward)
     230                break;
     231        }
    230232    }
    231233
     
    247249
    248250
    249 DECLINLINE(void) gicDistHasIrqPendingForVCpu(PGICDEV pThis, PGICCPU pGicVCpu, bool *pfIrq, bool *pfFiq)
     251DECLINLINE(void) gicDistHasIrqPendingForVCpu(PGICDEV pThis, PGICCPU pGicVCpu, VMCPUID idCpu, bool *pfIrq, bool *pfFiq)
    250252{
    251253    /* Read the interrupt state. */
     
    257259    bool fIrqGrp1Enabled  = ASMAtomicReadBool(&pThis->fIrqGrp1Enabled);
    258260
     261    /* Only allow interrupts with higher priority than the current configured and running one. */
     262    uint8_t bPriority = RT_MIN(pGicVCpu->bInterruptPriority, pGicVCpu->abRunningPriorities[pGicVCpu->idxRunningPriority]);
     263
    259264    /* Is anything enabled at all? */
    260265    uint32_t bmIntForward = (bmIntPending & bmIntEnabled) & ~bmIntActive; /* Exclude the currently active interrupt. */
    261 
    262     /* Only allow interrupts with higher priority than the current configured and running one. */
    263     uint8_t bPriority = RT_MIN(pGicVCpu->bInterruptPriority, pGicVCpu->abRunningPriorities[pGicVCpu->idxRunningPriority]);
    264     for (uint32_t i = 0; i < RT_ELEMENTS(pThis->abIntPriority); i++)
    265     {
    266         if (   (bmIntForward & RT_BIT_32(i))
    267             && pThis->abIntPriority[i] < bPriority)
    268             break;
    269         else
    270             bmIntForward &= ~RT_BIT_32(i);
     266    if (bmIntForward)
     267    {
     268        for (uint32_t i = 0; i < RT_ELEMENTS(pThis->abIntPriority); i++)
     269        {
     270            Log4(("SPI %u, configured priority %u (routing %#x), running priority %u\n", i + GIC_INTID_RANGE_SPI_START, pThis->abIntPriority[i],
     271                                                                                         pThis->au32IntRouting[i], bPriority));
     272            if (   (bmIntForward & RT_BIT_32(i))
     273                && pThis->abIntPriority[i] < bPriority
     274                && pThis->au32IntRouting[i] == idCpu)
     275                break;
     276            else
     277                bmIntForward &= ~RT_BIT_32(i);
     278
     279            if (!bmIntForward)
     280                break;
     281        }
    271282    }
    272283
     
    303314    PGICDEV pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
    304315    bool fIrqDist, fFiqDist;
    305     gicDistHasIrqPendingForVCpu(pGicDev, pThis, &fIrqDist, &fFiqDist);
     316    gicDistHasIrqPendingForVCpu(pGicDev, pThis, pVCpu->idCpu, &fIrqDist, &fFiqDist);
    306317    fIrq |= fIrqDist;
    307318    fFiq |= fFiqDist;
     
    330341
    331342        bool fIrqDist, fFiqDist;
    332         gicDistHasIrqPendingForVCpu(pThis, pGicVCpu, &fIrqDist, &fFiqDist);
     343        gicDistHasIrqPendingForVCpu(pThis, pGicVCpu, i, &fIrqDist, &fFiqDist);
    333344        fIrq |= fIrqDist;
    334345        fFiq |= fFiqDist;
     
    376387    PGICDEV pThis  = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
    377388
     389    if (offReg >= GIC_DIST_REG_IROUTERn_OFF_START && offReg <= GIC_DIST_REG_IROUTERn_OFF_LAST)
     390    {
     391        *puValue = pThis->au32IntRouting[(offReg - GIC_DIST_REG_IROUTERn_OFF_START) / 4];
     392        return VINF_SUCCESS;
     393    }
     394
    378395    switch (offReg)
    379396    {
     
    381398            *puValue =   (ASMAtomicReadBool(&pThis->fIrqGrp0Enabled) ? GIC_DIST_REG_CTRL_ENABLE_GRP0 : 0)
    382399                       | (ASMAtomicReadBool(&pThis->fIrqGrp1Enabled) ? GIC_DIST_REG_CTRL_ENABLE_GRP1_NS : 0)
    383                        | GIC_DIST_REG_CTRL_DS;
     400                       | GIC_DIST_REG_CTRL_DS
     401                       | GIC_DIST_REG_CTRL_ARE_S;
    384402            break;
    385403        case GIC_DIST_REG_TYPER_OFF:
     
    468486            AssertReleaseFailed();
    469487            break;
    470         case GIC_DIST_REG_IROUTERn_OFF_START: /* Only 32 lines for now. */
    471             *puValue = 0; /** @todo */
    472             break;
    473488        case GIC_DIST_REG_PIDR2_OFF:
    474489            *puValue = GIC_REDIST_REG_PIDR2_ARCH_REV_SET(GIC_REDIST_REG_PIDR2_ARCH_REV_GICV3);
     
    477492        case GIC_DIST_REG_TYPER2_OFF:
    478493            *puValue = 0;
     494            break;
     495        case GIC_DIST_REG_IROUTERn_OFF_START:
     496            AssertFailed();
    479497            break;
    480498        default:
     
    502520    if (offReg >= GIC_DIST_REG_IROUTERn_OFF_START && offReg <= GIC_DIST_REG_IROUTERn_OFF_LAST)
    503521    {
    504         /** @todo Ignored for now, probably make this a MMIO2 region as it begins on 0x6000, see 12.9.22 of the GICv3 architecture
    505          * reference manual. */
     522        uint32_t idxReg = (offReg - GIC_DIST_REG_IROUTERn_OFF_START) / 4;
     523        LogFlowFunc(("GicDist: idxIRouter=%u uValue=%#x\n", idxReg, uValue));
     524        if (idxReg < RT_ELEMENTS(pThis->au32IntRouting))
     525            pThis->au32IntRouting[idxReg] = uValue;
    506526        return VINF_SUCCESS;
    507527    }
     
    513533            ASMAtomicWriteBool(&pThis->fIrqGrp0Enabled, RT_BOOL(uValue & GIC_DIST_REG_CTRL_ENABLE_GRP0));
    514534            ASMAtomicWriteBool(&pThis->fIrqGrp1Enabled, RT_BOOL(uValue & GIC_DIST_REG_CTRL_ENABLE_GRP1_NS));
     535            Assert(!(uValue & GIC_DIST_REG_CTRL_ARE_NS));
    515536            rcStrict = gicDistUpdateIrqState(pVM, pThis);
    516537            break;
     
    542563            break;
    543564        case GIC_DIST_REG_ICENABLERn_OFF_START:
    544             //AssertReleaseFailed();
     565            AssertReleaseFailed();
    545566            break;
    546567        case GIC_DIST_REG_ICENABLERn_OFF_START + 4: /* Only 32 lines for now. */
     
    596617            for (uint32_t i = idxPrio; i < idxPrio + sizeof(uint32_t); i++)
    597618            {
     619#if 1
     620                /** @todo r=aeichner This gross hack prevents Windows from hanging during boot because
     621                 * it tries to set the interrupt priority for PCI interrupt lines to 0 which will cause an interrupt
     622                 * storm later on because the lowest interrupt priority Windows seems to use is 32 for the per vCPU
     623                 * timer.
     624                 */
     625                if ((uValue & 0xff) == 0)
     626                    continue;
     627#endif
    598628                pThis->abIntPriority[i] = (uint8_t)(uValue & 0xff);
    599629                uValue >>= 8;
     
    629659            break;
    630660        default:
    631             AssertReleaseFailed();
     661            //AssertReleaseFailed();
    632662            break;
    633663    }
     
    969999                Assert((uint32_t)idxIntPending < RT_ELEMENTS(pThis->abIntPriority));
    9701000                Assert(pThis->idxRunningPriority < RT_ELEMENTS(pThis->abRunningPriorities) - 1);
     1001
     1002                LogFlowFunc(("Dropping interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n",
     1003                             pThis->abRunningPriorities[pThis->idxRunningPriority],
     1004                             pThis->abIntPriority[idxIntPending],
     1005                             pThis->idxRunningPriority, pThis->idxRunningPriority + 1));
     1006
    9711007                pThis->abRunningPriorities[++pThis->idxRunningPriority] = pThis->abIntPriority[idxIntPending];
    9721008
     
    9841020                bmPending = (ASMAtomicReadU32(&pGicDev->bmIntPending) & bmIntEnabled) & ~bmIntActive;
    9851021                idxIntPending = ASMBitFirstSet(&bmPending, sizeof(bmPending) * 8);
    986                 if (idxIntPending > -1)
     1022                if (   idxIntPending > -1
     1023                    && pGicDev->abIntPriority[idxIntPending] < pThis->bInterruptPriority)
    9871024                {
    9881025                    /* Mark the interrupt as active. */
     
    9901027
    9911028                    /* Drop priority. */
    992                     Assert((uint32_t)idxIntPending < RT_ELEMENTS(pThis->abIntPriority));
     1029                    Assert((uint32_t)idxIntPending < RT_ELEMENTS(pGicDev->abIntPriority));
    9931030                    Assert(pThis->idxRunningPriority < RT_ELEMENTS(pThis->abRunningPriorities) - 1);
    994                     pThis->abRunningPriorities[++pThis->idxRunningPriority] = pThis->abIntPriority[idxIntPending];
     1031
     1032                    LogFlowFunc(("Dropping interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n",
     1033                                 pThis->abRunningPriorities[pThis->idxRunningPriority],
     1034                                 pThis->abIntPriority[idxIntPending],
     1035                                 pThis->idxRunningPriority, pThis->idxRunningPriority + 1));
     1036
     1037                    pThis->abRunningPriorities[++pThis->idxRunningPriority] = pGicDev->abIntPriority[idxIntPending];
    9951038
    9961039                    *pu64Value = idxIntPending + GIC_INTID_RANGE_SPI_START;
     
    10061049            break;
    10071050        case ARMV8_AARCH64_SYSREG_ICC_HPPIR1_EL1:
    1008             AssertReleaseFailed();
    1009             break;
     1051        {
     1052            /** @todo Figure out the highest priority interrupt. */
     1053            uint32_t bmIntActive = ASMAtomicReadU32(&pThis->bmIntActive);
     1054            uint32_t bmIntEnabled = ASMAtomicReadU32(&pThis->bmIntEnabled);
     1055            uint32_t bmPending = (ASMAtomicReadU32(&pThis->bmIntPending) & bmIntEnabled) & ~bmIntActive;
     1056            int32_t idxIntPending = ASMBitFirstSet(&bmPending, sizeof(bmPending) * 8);
     1057            if (idxIntPending > -1)
     1058                *pu64Value = idxIntPending;
     1059            else
     1060            {
     1061                /** @todo This is wrong as the guest might decide to prioritize PPIs and SPIs differently. */
     1062                bmIntActive = ASMAtomicReadU32(&pGicDev->bmIntActive);
     1063                bmIntEnabled = ASMAtomicReadU32(&pGicDev->bmIntEnabled);
     1064                bmPending = (ASMAtomicReadU32(&pGicDev->bmIntPending) & bmIntEnabled) & ~bmIntActive;
     1065                idxIntPending = ASMBitFirstSet(&bmPending, sizeof(bmPending) * 8);
     1066                if (idxIntPending > -1)
     1067                    *pu64Value = idxIntPending + GIC_INTID_RANGE_SPI_START;
     1068                else
     1069                    *pu64Value = GIC_INTID_RANGE_SPECIAL_NO_INTERRUPT;
     1070            }
     1071            break;
     1072        }
    10101073        case ARMV8_AARCH64_SYSREG_ICC_BPR1_EL1:
    10111074            *pu64Value = pThis->bBinaryPointGrp1 & 0x7;
     
    11181181            {
    11191182                /* Route to all but this vCPU. */
    1120                 AssertReleaseFailed();
     1183                for (uint32_t i = 0; i < pVCpu->pVMR3->cCpus; i++)
     1184                {
     1185                    if (i != pVCpu->idCpu)
     1186                    {
     1187                        PVMCPUCC pVCpuDst = VMMGetCpuById(pVCpu->CTX_SUFF(pVM), i);
     1188                        if (pVCpuDst)
     1189                            GICSgiSet(pVCpuDst, uIntId, true /*fAsserted*/);
     1190                        else
     1191                            AssertFailed();
     1192                    }
     1193                }
    11211194            }
    11221195            else
     
    11631236            Assert(pThis->idxRunningPriority > 0);
    11641237            if (RT_LIKELY(pThis->idxRunningPriority))
     1238            {
     1239                LogFlowFunc(("Restoring interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n",
     1240                             pThis->abRunningPriorities[pThis->idxRunningPriority],
     1241                             pThis->abRunningPriorities[pThis->idxRunningPriority - 1],
     1242                             pThis->idxRunningPriority, pThis->idxRunningPriority - 1));
    11651243                pThis->idxRunningPriority--;
     1244            }
    11661245            gicReDistUpdateIrqState(pThis, pVCpu);
    11671246            break;
  • trunk/src/VBox/VMM/VMMR3/GICR3.cpp

    r106061 r106370  
    113113        pHlp->pfnPrintf(pHlp, "     INTID %u    = %u\n", GIC_INTID_RANGE_SPI_START + i, pGicDev->abIntPriority[i]);
    114114
     115    pHlp->pfnPrintf(pHlp, " Interrupt routing:\n");
     116    for (uint32_t i = 0; i < RT_ELEMENTS(pGicDev->au32IntRouting); i++)
     117        pHlp->pfnPrintf(pHlp, "     INTID %u    = %u\n", GIC_INTID_RANGE_SPI_START + i, pGicDev->au32IntRouting[i]);
     118
    115119    pHlp->pfnPrintf(pHlp, "  fIrqGrp0Enabled    = %RTbool\n", pGicDev->fIrqGrp0Enabled);
    116120    pHlp->pfnPrintf(pHlp, "  fIrqGrp1Enabled    = %RTbool\n", pGicDev->fIrqGrp1Enabled);
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