VirtualBox

Changeset 100165 in vbox


Ignore:
Timestamp:
Jun 13, 2023 11:56:42 AM (20 months ago)
Author:
vboxsync
Message:

VMM/GIC: Updates to the emulation, implement interrupt priority support, bugref:10404

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

Legend:

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

    r100108 r100165  
    165165    /* Is anything enabled at all? */
    166166    uint32_t bmIntForward = (bmIntPending & bmIntEnabled) & ~bmIntActive; /* Exclude the currently active interrupt. */
     167
     168    /* Only allow interrupts with higher priority than the current configured and running one. */
     169    uint8_t bPriority = RT_MIN(pThis->bInterruptPriority, pThis->abRunningPriorities[pThis->idxRunningPriority]);
     170
     171    for (uint32_t i = 0; i < RT_ELEMENTS(pThis->abIntPriority); i++)
     172    {
     173        Log4(("SGI/PPI %u, configured priority %u, running priority %u\n", i, pThis->abIntPriority[i], bPriority));
     174        if (   (bmIntForward & RT_BIT_32(i))
     175            && pThis->abIntPriority[i] < bPriority)
     176            break;
     177        else
     178            bmIntForward &= ~RT_BIT_32(i);
     179
     180        if (!bmIntForward)
     181            break;
     182    }
     183
    167184    if (bmIntForward)
    168185    {
     
    177194    }
    178195
    179     LogFlowFunc(("pThis=%p bmIntEnabled=%#x bmIntPending=%#x bmIntActive=%#x fIrq=%RTbool fFiq=%RTbool\n",
    180                  pThis, bmIntEnabled, bmIntPending, bmIntActive, *pfIrq, *pfFiq));
    181 }
    182 
    183 
    184 DECLINLINE(void) gicDistHasIrqPendingForVCpu(PGICDEV pThis, bool *pfIrq, bool *pfFiq)
     196    LogFlowFunc(("pThis=%p bPriority=%u bmIntEnabled=%#x bmIntPending=%#x bmIntActive=%#x fIrq=%RTbool fFiq=%RTbool\n",
     197                 pThis, bPriority, bmIntEnabled, bmIntPending, bmIntActive, *pfIrq, *pfFiq));
     198}
     199
     200
     201DECLINLINE(void) gicDistHasIrqPendingForVCpu(PGICDEV pThis, PGICCPU pGicVCpu, bool *pfIrq, bool *pfFiq)
    185202{
    186203    /* Read the interrupt state. */
     
    194211    /* Is anything enabled at all? */
    195212    uint32_t bmIntForward = (bmIntPending & bmIntEnabled) & ~bmIntActive; /* Exclude the currently active interrupt. */
     213
     214    /* Only allow interrupts with higher priority than the current configured and running one. */
     215    uint8_t bPriority = RT_MIN(pGicVCpu->bInterruptPriority, pGicVCpu->abRunningPriorities[pGicVCpu->idxRunningPriority]);
     216    for (uint32_t i = 0; i < RT_ELEMENTS(pThis->abIntPriority); i++)
     217    {
     218        if (   (bmIntForward & RT_BIT_32(i))
     219            && pThis->abIntPriority[i] < bPriority)
     220            break;
     221        else
     222            bmIntForward &= ~RT_BIT_32(i);
     223    }
     224
    196225    if (bmIntForward)
    197226    {
     
    226255    PGICDEV pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
    227256    bool fIrqDist, fFiqDist;
    228     gicDistHasIrqPendingForVCpu(pGicDev, &fIrqDist, &fFiqDist);
     257    gicDistHasIrqPendingForVCpu(pGicDev, pThis, &fIrqDist, &fFiqDist);
    229258    fIrq |= fIrqDist;
    230259    fFiq |= fFiqDist;
     
    247276    {
    248277        PVMCPUCC pVCpu = pVM->CTX_SUFF(apCpus)[i];
     278        PGICCPU pGicVCpu = VMCPU_TO_GICCPU(pVCpu);
    249279
    250280        bool fIrq, fFiq;
    251         gicReDistHasIrqPending(VMCPU_TO_GICCPU(pVCpu), &fIrq, &fFiq);
     281        gicReDistHasIrqPending(pGicVCpu, &fIrq, &fFiq);
    252282
    253283        bool fIrqDist, fFiqDist;
    254         gicDistHasIrqPendingForVCpu(pThis, &fIrqDist, &fFiqDist);
     284        gicDistHasIrqPendingForVCpu(pThis, pGicVCpu, &fIrqDist, &fFiqDist);
    255285        fIrq |= fIrqDist;
    256286        fFiq |= fFiqDist;
     
    295325DECLINLINE(VBOXSTRICTRC) gicDistRegisterRead(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t offReg, uint32_t *puValue)
    296326{
    297     VMCPU_ASSERT_EMT(pVCpu); RT_NOREF(pVCpu);
     327    VMCPU_ASSERT_EMT(pVCpu);
    298328    PGICDEV pThis  = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
    299329
     
    337367            AssertReleaseFailed();
    338368            break;
     369        case GIC_DIST_REG_IPRIORITYn_OFF_START:
     370        case GIC_DIST_REG_IPRIORITYn_OFF_START + 4: /* These are banked for the PEs and access the redistributor. */
     371        {
     372            PGICCPU pGicVCpu = VMCPU_TO_GICCPU(pVCpu);
     373
     374            /* Figure out the register which is written. */
     375            uint8_t idxPrio = offReg - GIC_DIST_REG_IPRIORITYn_OFF_START;
     376            Assert(idxPrio <= RT_ELEMENTS(pThis->abIntPriority) - sizeof(uint32_t));
     377
     378            uint32_t u32Value = 0;
     379            for (uint32_t i = idxPrio; i < idxPrio + sizeof(uint32_t); i++)
     380                u32Value |= pGicVCpu->abIntPriority[i] << ((i - idxPrio) * 8);
     381
     382            *puValue = u32Value;
     383            break;
     384        }
    339385        case GIC_DIST_REG_IPRIORITYn_OFF_START + 32: /* Only 32 lines for now. */
    340386        {
    341387            /* Figure out the register which is written. */
    342             uint8_t idxPrio = offReg - GIC_REDIST_SGI_PPI_REG_IPRIORITYn_OFF_START - 32;
     388            uint8_t idxPrio = offReg - GIC_DIST_REG_IPRIORITYn_OFF_START - 32;
    343389            Assert(idxPrio <= RT_ELEMENTS(pThis->abIntPriority) - sizeof(uint32_t));
    344390
     
    467513            rcStrict = gicDistUpdateIrqState(pVM, pThis);
    468514            break;
     515        case GIC_DIST_REG_IPRIORITYn_OFF_START: /* These are banked for the PEs and access the redistributor. */
     516        case GIC_DIST_REG_IPRIORITYn_OFF_START + 4:
     517        case GIC_DIST_REG_IPRIORITYn_OFF_START + 8:
     518        case GIC_DIST_REG_IPRIORITYn_OFF_START + 12:
     519        case GIC_DIST_REG_IPRIORITYn_OFF_START + 16:
     520        case GIC_DIST_REG_IPRIORITYn_OFF_START + 20:
     521        case GIC_DIST_REG_IPRIORITYn_OFF_START + 24:
     522        case GIC_DIST_REG_IPRIORITYn_OFF_START + 28:
     523        {
     524            PGICCPU pGicVCpu = VMCPU_TO_GICCPU(pVCpu);
     525
     526            /* Figure out the register which is written. */
     527            uint8_t idxPrio = offReg - GIC_DIST_REG_IPRIORITYn_OFF_START;
     528            Assert(idxPrio <= RT_ELEMENTS(pGicVCpu->abIntPriority) - sizeof(uint32_t));
     529            for (uint32_t i = idxPrio; i < idxPrio + sizeof(uint32_t); i++)
     530            {
     531                pGicVCpu->abIntPriority[i] = (uint8_t)(uValue & 0xff);
     532                uValue >>= 8;
     533            }
     534            break;
     535        }
    469536        case GIC_DIST_REG_IPRIORITYn_OFF_START + 32: /* Only 32 lines for now. */
    470537        case GIC_DIST_REG_IPRIORITYn_OFF_START + 36:
     
    476543        case GIC_DIST_REG_IPRIORITYn_OFF_START + 60:
    477544        {
    478             /* Figure out the register whch is written. */
    479             uint8_t idxPrio = offReg - GIC_REDIST_SGI_PPI_REG_IPRIORITYn_OFF_START - 32;
     545            /* Figure out the register which is written. */
     546            uint8_t idxPrio = offReg - GIC_DIST_REG_IPRIORITYn_OFF_START - 32;
    480547            Assert(idxPrio <= RT_ELEMENTS(pThis->abIntPriority) - sizeof(uint32_t));
    481548            for (uint32_t i = idxPrio; i < idxPrio + sizeof(uint32_t); i++)
     
    514581            break;
    515582        default:
    516             //AssertReleaseFailed();
     583            AssertReleaseFailed();
    517584            break;
    518585    }
     
    636703{
    637704    VMCPU_ASSERT_EMT(pVCpu);
    638     RT_NOREF(pDevIns, pVCpu, offReg, uValue);
     705    RT_NOREF(pDevIns, pVCpu, uValue);
    639706
    640707    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
     708    switch (offReg)
     709    {
     710        case GIC_REDIST_REG_STATUSR_OFF:
     711            AssertReleaseFailed();
     712            break;
     713        case GIC_REDIST_REG_WAKER_OFF:
     714            Assert(uValue == 0);
     715            break;
     716        case GIC_REDIST_REG_PARTIDR_OFF:
     717            AssertReleaseFailed();
     718            break;
     719        case GIC_REDIST_REG_SETLPIR_OFF:
     720            AssertReleaseFailed();
     721            break;
     722        case GIC_REDIST_REG_CLRLPIR_OFF:
     723            AssertReleaseFailed();
     724            break;
     725        case GIC_REDIST_REG_PROPBASER_OFF:
     726            AssertReleaseFailed();
     727            break;
     728        case GIC_REDIST_REG_PENDBASER_OFF:
     729            AssertReleaseFailed();
     730            break;
     731        case GIC_REDIST_REG_INVLPIR_OFF:
     732            AssertReleaseFailed();
     733            break;
     734        case GIC_REDIST_REG_INVALLR_OFF:
     735            AssertReleaseFailed();
     736            break;
     737        default:
     738            AssertReleaseFailed();
     739            break;
     740    }
     741
    641742    return rcStrict;
    642743}
     
    715816            break;
    716817        default:
    717             AssertReleaseFailed();
     818            //AssertReleaseFailed();
     819            break;
    718820    }
    719821
     
    794896            break;
    795897        case ARMV8_AARCH64_SYSREG_ICC_RPR_EL1:
    796             AssertReleaseFailed();
     898            *pu64Value = pThis->abRunningPriorities[pThis->idxRunningPriority];
    797899            break;
    798900        case ARMV8_AARCH64_SYSREG_ICC_SGI1R_EL1:
     
    808910        {
    809911            /** @todo Figure out the highest priority interrupt. */
    810             uint32_t bmPending = ASMAtomicReadU32(&pThis->bmIntPending);
     912            uint32_t bmIntActive = ASMAtomicReadU32(&pThis->bmIntActive);
     913            uint32_t bmIntEnabled = ASMAtomicReadU32(&pThis->bmIntEnabled);
     914            uint32_t bmPending = (ASMAtomicReadU32(&pThis->bmIntPending) & bmIntEnabled) & ~bmIntActive;
    811915            int32_t idxIntPending = ASMBitFirstSet(&bmPending, sizeof(bmPending) * 8);
    812916            if (idxIntPending > -1)
     
    814918                /* Mark the interrupt as active. */
    815919                ASMAtomicOrU32(&pThis->bmIntActive, RT_BIT_32(idxIntPending));
     920                /* Drop priority. */
     921                Assert((uint32_t)idxIntPending < RT_ELEMENTS(pThis->abIntPriority));
     922                Assert(pThis->idxRunningPriority < RT_ELEMENTS(pThis->abRunningPriorities) - 1);
     923                pThis->abRunningPriorities[++pThis->idxRunningPriority] = pThis->abIntPriority[idxIntPending];
     924
    816925                /* Clear edge level interrupts like SGIs as pending. */
    817926                if (idxIntPending <= GIC_INTID_RANGE_SGI_LAST)
    818927                    ASMAtomicBitClear(&pThis->bmIntPending, idxIntPending);
    819928                *pu64Value = idxIntPending;
     929                gicReDistUpdateIrqState(pThis, pVCpu);
    820930            }
    821931            else
    822932            {
    823933                /** @todo This is wrong as the guest might decide to prioritize PPIs and SPIs differently. */
    824                 bmPending = ASMAtomicReadU32(&pGicDev->bmIntPending);
     934                bmIntActive = ASMAtomicReadU32(&pGicDev->bmIntActive);
     935                bmIntEnabled = ASMAtomicReadU32(&pGicDev->bmIntEnabled);
     936                bmPending = (ASMAtomicReadU32(&pGicDev->bmIntPending) & bmIntEnabled) & ~bmIntActive;
    825937                idxIntPending = ASMBitFirstSet(&bmPending, sizeof(bmPending) * 8);
    826938                if (idxIntPending > -1)
     
    828940                    /* Mark the interrupt as active. */
    829941                    ASMAtomicOrU32(&pGicDev->bmIntActive, RT_BIT_32(idxIntPending));
     942
     943                    /* Drop priority. */
     944                    Assert((uint32_t)idxIntPending < RT_ELEMENTS(pThis->abIntPriority));
     945                    Assert(pThis->idxRunningPriority < RT_ELEMENTS(pThis->abRunningPriorities) - 1);
     946                    pThis->abRunningPriorities[++pThis->idxRunningPriority] = pThis->abIntPriority[idxIntPending];
     947
    830948                    *pu64Value = idxIntPending + GIC_INTID_RANGE_SPI_START;
     949                    gicReDistUpdateIrqState(pThis, pVCpu);
    831950                }
    832951                else
     
    8961015    {
    8971016        case ARMV8_AARCH64_SYSREG_ICC_PMR_EL1:
     1017            LogFlowFunc(("ICC_PMR_EL1: Interrupt priority now %u\n", (uint8_t)u64Value));
    8981018            ASMAtomicWriteU8(&pThis->bInterruptPriority, (uint8_t)u64Value);
     1019            gicReDistUpdateIrqState(pThis, pVCpu);
    8991020            break;
    9001021        case ARMV8_AARCH64_SYSREG_ICC_IAR0_EL1:
     
    9861107            else
    9871108                ASMAtomicAndU32(&pGicDev->bmIntActive, ~RT_BIT_32((uint32_t)u64Value));
     1109
     1110            /* Restore previous interrupt priority. */
     1111            Assert(pThis->idxRunningPriority > 0);
     1112            if (RT_LIKELY(pThis->idxRunningPriority))
     1113                pThis->idxRunningPriority--;
    9881114            gicReDistUpdateIrqState(pThis, pVCpu);
    9891115            break;
     
    11141240    LogFlowFunc(("GIC%u\n", pVCpu->idCpu));
    11151241    VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
    1116     RT_NOREF(pVCpu);
     1242
     1243    memset((void *)&pVCpu->gic.s.abRunningPriorities[0], 0xff, sizeof(pVCpu->gic.s.abRunningPriorities));
     1244    pVCpu->gic.s.idxRunningPriority = 0;
     1245    pVCpu->gic.s.bInterruptPriority = 0; /* Means no interrupt gets through to the PE. */
    11171246}
    11181247
  • trunk/src/VBox/VMM/VMMR3/GICR3.cpp

    r100108 r100165  
    7171
    7272/**
     73 * Dumps basic APIC state.
     74 *
     75 * @param   pVM         The cross context VM structure.
     76 * @param   pHlp        The info helpers.
     77 * @param   pszArgs     Arguments, ignored.
     78 */
     79static DECLCALLBACK(void) gicR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     80{
     81    RT_NOREF(pVM, pHlp, pszArgs);
     82}
     83
     84
     85/**
     86 * Dumps GIC Distributor information.
     87 *
     88 * @param   pVM         The cross context VM structure.
     89 * @param   pHlp        The info helpers.
     90 * @param   pszArgs     Arguments, ignored.
     91 */
     92static DECLCALLBACK(void) gicR3InfoDist(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     93{
     94    RT_NOREF(pszArgs);
     95
     96    PGIC pGic = VM_TO_GIC(pVM);
     97    PPDMDEVINS pDevIns = pGic->CTX_SUFF(pDevIns);
     98    PGICDEV    pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
     99
     100    pHlp->pfnPrintf(pHlp, "GICv3 Distributor:\n");
     101    pHlp->pfnPrintf(pHlp, "  IGRP0            = %#RX32\n", pGicDev->u32RegIGrp0);
     102    pHlp->pfnPrintf(pHlp, "  ICFG0            = %#RX32\n", pGicDev->u32RegICfg0);
     103    pHlp->pfnPrintf(pHlp, "  ICFG1            = %#RX32\n", pGicDev->u32RegICfg1);
     104    pHlp->pfnPrintf(pHlp, "  bmIntEnabled     = %#RX32\n", pGicDev->bmIntEnabled);
     105    pHlp->pfnPrintf(pHlp, "  bmIntPending     = %#RX32\n", pGicDev->bmIntPending);
     106    pHlp->pfnPrintf(pHlp, "  bmIntActive      = %#RX32\n", pGicDev->bmIntActive);
     107    pHlp->pfnPrintf(pHlp, " Interrupt priorities:\n");
     108    for (uint32_t i = 0; i < RT_ELEMENTS(pGicDev->abIntPriority); i++)
     109        pHlp->pfnPrintf(pHlp, "     INTID %u    = %u\n", GIC_INTID_RANGE_SPI_START + i, pGicDev->abIntPriority[i]);
     110
     111    pHlp->pfnPrintf(pHlp, "  fIrqGrp0Enabled    = %RTbool\n", pGicDev->fIrqGrp0Enabled);
     112    pHlp->pfnPrintf(pHlp, "  fIrqGrp1Enabled    = %RTbool\n", pGicDev->fIrqGrp1Enabled);
     113}
     114
     115
     116/**
     117 * Dumps the GIC Redistributor information.
     118 *
     119 * @param   pVM         The cross context VM structure.
     120 * @param   pHlp        The info helpers.
     121 * @param   pszArgs     Arguments, ignored.
     122 */
     123static DECLCALLBACK(void) gicR3InfoReDist(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     124{
     125    NOREF(pszArgs);
     126    PVMCPU pVCpu = VMMGetCpu(pVM);
     127    if (!pVCpu)
     128        pVCpu = pVM->apCpusR3[0];
     129
     130    PGICCPU pGicVCpu = VMCPU_TO_GICCPU(pVCpu);
     131
     132    pHlp->pfnPrintf(pHlp, "VCPU[%u] Redistributor:\n", pVCpu->idCpu);
     133    pHlp->pfnPrintf(pHlp, "  IGRP0            = %#RX32\n", pGicVCpu->u32RegIGrp0);
     134    pHlp->pfnPrintf(pHlp, "  ICFG0            = %#RX32\n", pGicVCpu->u32RegICfg0);
     135    pHlp->pfnPrintf(pHlp, "  ICFG1            = %#RX32\n", pGicVCpu->u32RegICfg1);
     136    pHlp->pfnPrintf(pHlp, "  bmIntEnabled     = %#RX32\n", pGicVCpu->bmIntEnabled);
     137    pHlp->pfnPrintf(pHlp, "  bmIntPending     = %#RX32\n", pGicVCpu->bmIntPending);
     138    pHlp->pfnPrintf(pHlp, "  bmIntActive      = %#RX32\n", pGicVCpu->bmIntActive);
     139    pHlp->pfnPrintf(pHlp, " Interrupt priorities:\n");
     140    for (uint32_t i = 0; i < RT_ELEMENTS(pGicVCpu->abIntPriority); i++)
     141        pHlp->pfnPrintf(pHlp, "     INTID %u    = %u\n", i, pGicVCpu->abIntPriority[i]);
     142
     143    pHlp->pfnPrintf(pHlp, "VCPU[%u] ICC state:\n", pVCpu->idCpu);
     144    pHlp->pfnPrintf(pHlp, "  fIrqGrp0Enabled    = %RTbool\n", pGicVCpu->fIrqGrp0Enabled);
     145    pHlp->pfnPrintf(pHlp, "  fIrqGrp1Enabled    = %RTbool\n", pGicVCpu->fIrqGrp1Enabled);
     146    pHlp->pfnPrintf(pHlp, "  bInterruptPriority = %u\n",      pGicVCpu->bInterruptPriority);
     147    pHlp->pfnPrintf(pHlp, "  bBinaryPointGrp0   = %u\n",      pGicVCpu->bBinaryPointGrp0);
     148    pHlp->pfnPrintf(pHlp, "  bBinaryPointGrp1   = %u\n",      pGicVCpu->bBinaryPointGrp1);
     149    pHlp->pfnPrintf(pHlp, "  idxRunningPriority = %u\n",      pGicVCpu->idxRunningPriority);
     150    pHlp->pfnPrintf(pHlp, "  Running priority   = %u\n",      pGicVCpu->abRunningPriorities[pGicVCpu->idxRunningPriority]);
     151}
     152
     153
     154/**
    73155 * @interface_method_impl{PDMDEVREG,pfnReset}
    74156 */
     
    201283
    202284    /*
     285     * Register debugger info callbacks.
     286     *
     287     * We use separate callbacks rather than arguments so they can also be
     288     * dumped in an automated fashion while collecting crash diagnostics and
     289     * not just used during live debugging via the VM debugger.
     290     */
     291    DBGFR3InfoRegisterInternalEx(pVM, "gic",       "Dumps GIC basic information.",          gicR3Info,       DBGFINFO_FLAGS_ALL_EMTS);
     292    DBGFR3InfoRegisterInternalEx(pVM, "gicdist",   "Dumps GIC Distributor information.",    gicR3InfoDist,   DBGFINFO_FLAGS_ALL_EMTS);
     293    DBGFR3InfoRegisterInternalEx(pVM, "gicredist", "Dumps GIC Redistributor information.",  gicR3InfoReDist, DBGFINFO_FLAGS_ALL_EMTS);
     294
     295    /*
    203296     * Statistics.
    204297     */
     
    232325# undef GIC_PROF_COUNTER
    233326
     327    gicR3Reset(pDevIns);
    234328    return VINF_SUCCESS;
    235329}
  • trunk/src/VBox/VMM/include/GICInternal.h

    r99885 r100165  
    6464    IOMMMIOHANDLE               hMmioReDist;
    6565
    66     /** @name SPI disitributor register state.
     66    /** @name SPI distributor register state.
    6767     * @{ */
    6868    /** Interrupt Group 0 Register. */
     
    150150    /** The interrupt controller Binary Point Register for Group 1 interrupts. */
    151151    uint8_t                     bBinaryPointGrp1;
     152    /** The running poriorities caused by preemption. */
     153    volatile uint8_t            abRunningPriorities[256];
     154    /** The index to the current running priority. */
     155    volatile uint8_t            idxRunningPriority;
    152156    /** @} */
    153157
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