VirtualBox

Changeset 109226 in vbox


Ignore:
Timestamp:
May 12, 2025 12:37:55 PM (12 days ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168810
Message:

VMM/GIC: bugref:10877 GIC ITS, MSI/LPIs work-in-progress.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/gic-its.h

    r109144 r109226  
    4545/** Size of the ITS register frame. */
    4646#define GITS_REG_FRAME_SIZE                                     _64K
     47/** The offset mask for an ITS register within a frame. */
     48#define GITS_REG_OFFSET_MASK                                    (_64K - 1)
    4749
    4850/** The GITS command queue page size. */
  • trunk/src/VBox/VMM/VMMAll/GICAll.cpp

    r109206 r109226  
    720720
    721721
     722DECLHIDDEN(void) gicReDistSetLpi(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t uIntId, bool fAsserted)
     723{
     724    Assert(GIC_CRIT_SECT_IS_OWNER(pDevIns));
     725    PGICDEV pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
     726    NOREF(pGicDev);
     727    AssertMsgFailed(("[%u] uIntId=%RU32 fAsserted=%RTbool\n", pVCpu->idCpu, uIntId, fAsserted));
     728}
     729
     730
     731
    722732/**
    723733 * Updates the internal IRQ state and sets or clears the appropriate force action
     
    18691879            gicReDistUpdateIrqState(pGicDev, pVCpu);
    18701880        }
    1871         else
     1881        else if (uIntId < GIC_INTID_RANGE_LPI_START)
    18721882        {
    18731883            /* Sanity check if the interrupt ID belongs to the distributor. */
     
    19101920            /* Update the distributor IRQ state to reflect change to the active interrupt. */
    19111921            gicDistUpdateIrqState(pVCpu->CTX_SUFF(pVM), pGicDev);
     1922        }
     1923        else
     1924        {
     1925            /** @todo LPIs. */
     1926            /* Sanity check if the interrupt ID is an LPIs. */
    19121927        }
    19131928    }
     
    27332748    GIC_CRIT_SECT_LEAVE(pDevIns);
    27342749    return rc;
     2750}
     2751
     2752
     2753/**
     2754 * @interface_method_impl{PDMGICBACKEND,pfnSendMsi}
     2755 */
     2756DECL_HIDDEN_CALLBACK(int) gicSendMsi(PVMCC pVM, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc)
     2757{
     2758    NOREF(uTagSrc); /** @todo Consider setting (on assert) and clearing (on de-assert) if possible later. */
     2759    AssertPtrReturn(pMsi, VERR_INVALID_PARAMETER);
     2760    Log4Func(("uBusDevFn=%#RX32 Msi.Addr=%#RX64 Msi.Data=%#RX32\n", uBusDevFn, pMsi->Addr.u64, pMsi->Data.u32));
     2761
     2762    PGIC       pGic    = VM_TO_GIC(pVM);
     2763    PPDMDEVINS pDevIns = pGic->CTX_SUFF(pDevIns);
     2764    PGICDEV    pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
     2765    Assert(pGicDev->fEnableLpis);
     2766
     2767    uint32_t const uEventId = pMsi->Data.u32;
     2768    uint32_t const uDevId   = uBusDevFn;
     2769    AssertMsg((pMsi->Addr.u64 & ~(RTGCPHYS)GITS_REG_OFFSET_MASK) == pGicDev->GCPhysGits + GITS_REG_FRAME_SIZE,
     2770              ("Addr=%#RX64 MMIO frame=%#RX64\n", pMsi->Addr.u64, pGicDev->GCPhysGits));
     2771    AssertMsg((pMsi->Addr.u64 & GITS_REG_OFFSET_MASK) == GITS_TRANSLATION_REG_TRANSLATER,
     2772              ("Addr=%#RX64 offset=%#RX32\n", pMsi->Addr.u64, GITS_TRANSLATION_REG_TRANSLATER));
     2773
     2774    gitsSetLpi(pDevIns, &pGicDev->Gits, uDevId, uEventId, true /* fAsserted */);
     2775
     2776    AssertMsgFailed(("uBusDevFn=%#RX32 (%RTbool) Msi.Addr=%#RX64 Msi.Data=%#RX32\n", uBusDevFn, PCIBDF_IS_VALID(uBusDevFn),
     2777                     pMsi->Addr.u64, pMsi->Data.u32));
     2778    return VERR_NOT_IMPLEMENTED;
    27352779}
    27362780
     
    35313575    /* .pfnSetSpi = */      gicSetSpi,
    35323576    /* .pfnSetPpi = */      gicSetPpi,
    3533     /* .pfnSendMsi = */     gitsSendMsi,
     3577    /* .pfnSendMsi = */     gicSendMsi,
    35343578};
    35353579
  • trunk/src/VBox/VMM/VMMAll/GITSAll.cpp

    r109220 r109226  
    441441    Assert(!(offReg & 3));
    442442    Log4Func(("offReg=%u uValue=%#RX64 cb=%u\n", offReg, uValue, cb));
     443    /** @todo Call gitsSetLpi for GITS_TRANSLATER register offset write. */
    443444    AssertReleaseMsgFailed(("offReg=%#x uValue=%#RX64 [%u-bit]\n", offReg, uValue, cb << 3));
    444445}
     
    705706
    706707
     708static int gitsR3IteRead(PPDMDEVINS pDevIns, GITSDTE uDte, uint32_t uEventId, GITSITE *puIte)
     709{
     710    RTGCPHYS const GCPhysIntrTable = uDte & GITS_BF_DTE_ITT_ADDR_MASK;
     711    RTGCPHYS const GCPhysIte       = GCPhysIntrTable + uEventId * sizeof(GITSITE);
     712    return PDMDevHlpPhysReadMeta(pDevIns, GCPhysIte, (void *)puIte, sizeof(*puIte));
     713}
     714
     715
    707716static int gitsR3IteWrite(PPDMDEVINS pDevIns, GITSDTE uDte, uint32_t uEventId, GITSITE uIte)
    708717{
     
    9981007
    9991008
    1000 /**
    1001  * @interface_method_impl{PDMGICBACKEND,pfnSendMsi}
    1002  */
    1003 DECL_HIDDEN_CALLBACK(int) gitsSendMsi(PVMCC pVM, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc)
    1004 {
    1005     AssertPtrReturn(pMsi, VERR_INVALID_PARAMETER);
    1006     Log4Func(("uBusDevFn=%#RX32 Msi.Addr=%#RX64 Msi.Data=%#RX32\n", uBusDevFn, pMsi->Addr.u64, pMsi->Data.u32));
    1007     RT_NOREF(pVM, uBusDevFn, pMsi, uTagSrc);
    1008     AssertMsgFailed(("uBusDevFn=%#RX32 Msi.Addr=%#RX64 Msi.Data=%#RX32\n", uBusDevFn, pMsi->Addr.u64, pMsi->Data.u32));
    1009     return VERR_NOT_IMPLEMENTED;
    1010 }
     1009DECL_HIDDEN_CALLBACK(int) gitsSetLpi(PPDMDEVINS pDevIns, PGITSDEV pGitsDev, uint32_t uDevId, uint32_t uEventId, bool fAsserted)
     1010{
     1011    /* We support 32-bits of device ID and hence it cannot be out of range (asserted below). */
     1012    Assert(sizeof(uDevId) * 8 >= RT_BF_GET(pGitsDev->uTypeReg.u, GITS_BF_CTRL_REG_TYPER_DEV_BITS) + 1);
     1013
     1014    /** @todo Error recording. */
     1015
     1016    GIC_CRIT_SECT_ENTER(pDevIns);
     1017
     1018    bool const fEnabled = RT_BF_GET(pGitsDev->uCtrlReg, GITS_BF_CTRL_REG_CTLR_ENABLED);
     1019    if (fEnabled)
     1020    {
     1021        /* Read the DTE */
     1022        GITSDTE uDte;
     1023        int rc = gitsR3DteRead(pDevIns, pGitsDev, uDevId, &uDte);
     1024        if (RT_SUCCESS(rc))
     1025        {
     1026            /* Check the DTE is mapped (valid). */
     1027            bool const fValid = RT_BF_GET(uDte, GITS_BF_DTE_VALID);
     1028            if (fValid)
     1029            {
     1030                /* Check that the event ID (which is the index) is within range. */
     1031                uint32_t const cEntries = RT_BIT_32(RT_BF_GET(uDte, GITS_BF_DTE_ITT_ADDR) + 1);
     1032                if (uEventId < cEntries)
     1033                {
     1034                    /* Read the interrupt-translation entry. */
     1035                    GITSITE uIte = 0;
     1036                    rc = gitsR3IteRead(pDevIns, uDte, uEventId, &uIte);
     1037                    if (RT_SUCCESS(rc))
     1038                    {
     1039                        /* Check the interrupt ID is within range. */
     1040                        uint16_t const uIntId = RT_BF_GET(uIte, GITS_BF_ITE_INTID);
     1041                        uint16_t const uIcId  = RT_BF_GET(uIte, GITS_BF_ITE_ICID);
     1042                        bool const fIsLpiValid = gicDistIsLpiValid(pDevIns, uIntId);
     1043                        if (fIsLpiValid)
     1044                        {
     1045                            /* Check the interrupt collection ID is valid. */
     1046                            if (uIcId < RT_ELEMENTS(pGitsDev->aCtes))
     1047                            {
     1048                                Assert(!RT_BF_GET(pGitsDev->uTypeReg.u, GITS_BF_CTRL_REG_TYPER_PTA));
     1049                                PCVMCC         pVM  = PDMDevHlpGetVM(pDevIns);
     1050                                VMCPUID const idCpu = pGitsDev->aCtes[uIcId].idTargetCpu;
     1051
     1052                                /* Check that the target CPU is valid. */
     1053                                if (idCpu < pVM->cCpus)
     1054                                {
     1055                                    /* Set or clear the LPI pending state in the redistributor. */
     1056                                    PVMCPUCC pVCpu = pVM->CTX_SUFF(apCpus)[idCpu];
     1057                                    gicReDistSetLpi(pDevIns, pVCpu, uIntId, fAsserted);
     1058                                }
     1059                            }
     1060                        }
     1061                    }
     1062                }
     1063            }
     1064        }
     1065    }
     1066    GIC_CRIT_SECT_LEAVE(pDevIns);
     1067    return VINF_SUCCESS;
     1068}
     1069
    10111070
    10121071#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
  • trunk/src/VBox/VMM/VMMR3/GICR3.cpp

    r109216 r109226  
    991991    /* ITS. */
    992992    {
    993         RTGCPHYS GCPhysMmioBase = 0;
    994         rc = pHlp->pfnCFGMQueryU64(pCfg, "ItsMmioBase", &GCPhysMmioBase);
     993        rc = pHlp->pfnCFGMQueryU64(pCfg, "ItsMmioBase", &pGicDev->GCPhysGits);
    995994        if (RT_SUCCESS(rc))
    996995        {
    997996            Assert(pGicDev->hMmioGits != NIL_IOMMMIOHANDLE);    /* paranoia, as this would be 0 here not NIL_IOMMMIOHANDLE. */
    998997            RTGCPHYS const cbRegion = 2 * GITS_REG_FRAME_SIZE;  /* 2 frames for GICv3. */
    999             rc = PDMDevHlpMmioCreateAndMap(pDevIns, GCPhysMmioBase, cbRegion, gicItsMmioWrite, gicItsMmioRead,
     998            rc = PDMDevHlpMmioCreateAndMap(pDevIns, pGicDev->GCPhysGits, cbRegion, gicItsMmioWrite, gicItsMmioRead,
    1000999                                             IOMMMIO_FLAGS_READ_DWORD_QWORD
    10011000                                           | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED
     
    10051004            AssertLogRelRCReturn(rc, rc);
    10061005            Assert(pGicDev->hMmioGits != NIL_IOMMMIOHANDLE);
     1006            Assert(pGicDev->GCPhysGits != NIL_RTGCPHYS);
    10071007
    10081008            /* When the ITS is enabled we must support LPIs. */
     
    10251025        else
    10261026        {
    1027             pGicDev->hMmioGits = NIL_IOMMMIOHANDLE;
     1027            pGicDev->hMmioGits  = NIL_IOMMMIOHANDLE;
     1028            pGicDev->GCPhysGits = NIL_RTGCPHYS;
    10281029
    10291030            /* When the ITS is disabled we don't support LPIs as we do not support direct LPI injection (guests don't use it). */
  • trunk/src/VBox/VMM/include/GICInternal.h

    r109202 r109226  
    143143        (a_uReg) = ((a_uReg) & ~(a_fRwMask)) | ((uint32_t)(a_uValue) & (uint32_t)(a_fRwMask)); \
    144144    } while (0)
    145 
    146145
    147146/**
     
    232231    /** The interrupt translation service MMIO handle. */
    233232    IOMMMIOHANDLE               hMmioGits;
     233    /** The physical address of the ITS. */
     234    RTGCPHYS                    GCPhysGits;
    234235    /** @} */
    235236} GICDEV;
     
    351352DECL_HIDDEN_CALLBACK(VBOXSTRICTRC) gicItsMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb);
    352353
     354DECLHIDDEN(void)                   gicReDistSetLpi(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t uIntId, bool fAsserted);
    353355DECLHIDDEN(void)                   gicDistReadLpiConfigTableFromMem(PPDMDEVINS pDevIns);
    354356DECLHIDDEN(bool)                   gicDistIsLpiValid(PPDMDEVINS pDevIns, uint16_t uIntId);
  • trunk/src/VBox/VMM/include/GITSInternal.h

    r109212 r109226  
    276276
    277277DECL_HIDDEN_CALLBACK(void)         gitsInit(PGITSDEV pGitsDev);
    278 DECL_HIDDEN_CALLBACK(int)          gitsSendMsi(PVMCC pVM, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc);
     278DECL_HIDDEN_CALLBACK(int)          gitsSetLpi(PPDMDEVINS pDevIns, PGITSDEV pGitsDev, uint32_t uDevId, uint32_t uEventId, bool fAsserted);
    279279DECL_HIDDEN_CALLBACK(uint64_t)     gitsMmioReadCtrl(PCGITSDEV pGitsDev, uint16_t offReg, unsigned cb);
    280280DECL_HIDDEN_CALLBACK(uint64_t)     gitsMmioReadTranslate(PCGITSDEV pGitsDev, uint16_t offReg, unsigned cb);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette