VirtualBox

Ignore:
Timestamp:
May 14, 2020 4:36:56 AM (5 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Asynchronous IOMMU command processing.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp

    r84292 r84301  
    11291129        uint32_t    u28Rsvd0 : 28;      /**< Bits 47:32  - Reserved. */
    11301130        uint32_t    u4EvtCode : 4;      /**< Bits 63:60  - Event code. */
    1131         uint32_t    u4Rsvd0 : 4;        /**< Bits 67:64  - Reserved. */
    1132         uint32_t    u28AddrLo : 28;     /**< Bits 95:68  - Address: SPA of the invalid command (Lo). */
    1133         uint32_t    u32AddrHi;          /**< Bits 127:96 - Address: SPA of the invalid command (Hi). */
     1131        uint64_t    u64Addr;            /**< Bits 127:64 - Address: SPA of the invalid command. */
    11341132    } n;
    11351133    /** The 32-bit unsigned integer view. */
     
    11391137} EVT_ILLEGAL_CMD_ERR_T;
    11401138AssertCompileSize(EVT_ILLEGAL_CMD_ERR_T, 16);
     1139/** Pointer to an illegal command error event. */
     1140typedef EVT_ILLEGAL_CMD_ERR_T *PEVT_ILLEGAL_CMD_ERR_T;
     1141/** Pointer to a const illegal command error event. */
     1142typedef EVT_ILLEGAL_CMD_ERR_T const *PCEVT_ILLEGAL_CMD_ERR_T;
    11411143
    11421144/**
     
    21852187    kIllegalCmdErrType_IotlbNotSupported
    21862188} EVT_ILLEGAL_CMD_ERR_TYPE_T;
     2189/** Pointer to an illegal command error event type. */
     2190typedef EVT_ILLEGAL_CMD_ERR_TYPE_T *PEVT_ILLEGAL_CMD_ERR_TYPE_T;
    21872191
    21882192/**
     
    25392543 * @param   uEncodedLen     The length (power-of-2 encoded).
    25402544 */
    2541 DECLINLINE(uint32_t) iommuAmdGetBufLength(uint8_t uEncodedLen)
     2545DECLINLINE(uint32_t) iommuAmdGetTotalBufLength(uint8_t uEncodedLen)
    25422546{
    25432547    Assert(uEncodedLen > 7);
     
    30143018     */
    30153019    uint32_t const offBuf = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
    3016     uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->CmdBufBaseAddr.n.u4Len);
     3020    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len);
    30173021    Assert(cbBuf <= _512K);
    30183022    if (offBuf >= cbBuf)
     
    30463050     */
    30473051    uint32_t const offBuf = u64Value & IOMMU_CMD_BUF_TAIL_PTR_VALID_MASK;
    3048     uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->CmdBufBaseAddr.n.u4Len);
     3052    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len);
    30493053    Assert(cbBuf <= _512K);
    30503054    if (offBuf >= cbBuf)
     
    30883092     */
    30893093    uint32_t const offBuf = u64Value & IOMMU_EVT_LOG_HEAD_PTR_VALID_MASK;
    3090     uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->EvtLogBaseAddr.n.u4Len);
     3094    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->EvtLogBaseAddr.n.u4Len);
    30913095    Assert(cbBuf <= _512K);
    30923096    if (offBuf >= cbBuf)
     
    31303134     */
    31313135    uint32_t const offBuf = u64Value & IOMMU_EVT_LOG_TAIL_PTR_VALID_MASK;
    3132     uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->EvtLogBaseAddr.n.u4Len);
     3136    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->EvtLogBaseAddr.n.u4Len);
    31333137    Assert(cbBuf <= _512K);
    31343138    if (offBuf >= cbBuf)
     
    35693573
    35703574            /* Increment the event log tail pointer. */
    3571             uint32_t const cbEvtLog = iommuAmdGetBufLength(pThis->EvtLogBaseAddr.n.u4Len);
     3575            uint32_t const cbEvtLog = iommuAmdGetTotalBufLength(pThis->EvtLogBaseAddr.n.u4Len);
    35723576            pThis->EvtLogTailPtr.n.off = (offEvt + cbEvt) % cbEvtLog;
    35733577
     
    37703774    Log((IOMMU_LOG_PFX ": Raised DEV_TAB_HARDWARE_ERROR. uDevId=%#x GCPhysDte=%#RGp enmOp=%u enmType=%u\n",
    37713775         pEvtDevTabHwErr->n.u16DevId, pEvtDevTabHwErr->n.u64Addr, enmOp, enmEvtType));
     3776    NOREF(enmEvtType);
     3777}
     3778
     3779
     3780/**
     3781 * Initializes an ILLEGAL_COMMAND_ERROR event.
     3782 *
     3783 * @param   GCPhysCmd       The system physical address of the failed command
     3784 *                          access.
     3785 * @param   pEvtIllegalCmd  Where to store the initialized event.
     3786 */
     3787static void iommuAmdInitIllegalCmdEvent(RTGCPHYS GCPhysCmd, PEVT_ILLEGAL_CMD_ERR_T pEvtIllegalCmd)
     3788{
     3789    Assert(!(GCPhysCmd & UINT64_C(0xf)));
     3790    memset(pEvtIllegalCmd, 0, sizeof(*pEvtIllegalCmd));
     3791    pEvtIllegalCmd->n.u4EvtCode = IOMMU_EVT_ILLEGAL_CMD_ERROR;
     3792    pEvtIllegalCmd->n.u64Addr   = GCPhysCmd;
     3793}
     3794
     3795
     3796/**
     3797 * Raises an ILLEGAL_COMMAND_ERROR event.
     3798 *
     3799 * @param   pDevIns         The IOMMU device instance.
     3800 * @param   pEvtIllegalCmd  The illegal command error event.
     3801 * @param   enmEvtType      The illegal command error event type.
     3802 */
     3803static void iommuAmdRaiseIllegalCmdEvent(PPDMDEVINS pDevIns, PCEVT_ILLEGAL_CMD_ERR_T pEvtIllegalCmd,
     3804                                         EVT_ILLEGAL_CMD_ERR_TYPE_T enmEvtType)
     3805{
     3806    AssertCompile(sizeof(EVT_GENERIC_T) == sizeof(EVT_ILLEGAL_DTE_T));
     3807    PCEVT_GENERIC_T pEvent = (PCEVT_GENERIC_T)pEvtIllegalCmd;
     3808
     3809    IOMMU_LOCK_NORET(pDevIns);
     3810
     3811    iommuAmdWriteEvtLogEntry(pDevIns, pEvent);
     3812    iommuAmdHaltCmdProcessing(pDevIns);
     3813
     3814    IOMMU_UNLOCK(pDevIns);
     3815
     3816    Log((IOMMU_LOG_PFX ": Raised ILLEGAL_COMMAND_ERROR. GCPhysCmd=%#RGp enmType=%u\n", pEvtIllegalCmd->n.u64Addr, enmEvtType));
    37723817    NOREF(enmEvtType);
    37733818}
     
    38083853 * @param   enmOp           The IOMMU operation being performed.
    38093854 * @param   pEvtIllegalDte  The illegal device table entry event.
    3810  * @param   enmEvtType      The illegal DTE event type.
     3855 * @param   enmEvtType      The illegal device table entry event type.
    38113856 *
    38123857 * @thread  Any.
     
    45774622 *
    45784623 * @returns VBox status code.
    4579  * @param   pDevIns     The IOMMU device instance.
    4580  * @param   pCmd        The command to process.
    4581  */
    4582 static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, PCCMD_GENERIC_T pCmd)
     4624 * @param   pDevIns         The IOMMU device instance.
     4625 * @param   pCmd            The command to process.
     4626 * @param   penmEvtType     Where to store the illegal command error event type in
     4627 *                          case of failures.
     4628 */
     4629static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, PCCMD_GENERIC_T pCmd, PEVT_ILLEGAL_CMD_ERR_TYPE_T penmEvtType)
    45834630{
    45844631    IOMMU_ASSERT_NOT_LOCKED(pDevIns);
     
    46064653
    46074654    Log((IOMMU_LOG_PFX ": Invalid/Unrecognized command opcode %u (%#x)\n", bCmd, bCmd));
     4655    *penmEvtType = kIllegalCmdErrType_CmdNotSupported;
    46084656    return VERR_INVALID_FUNCTION;
    46094657}
     
    46584706            IOMMU_LOCK(pDevIns);
    46594707
    4660             uint32_t const cbCmdBuf = iommuAmdGetBufLength(pThis->CmdBufBaseAddr.n.u4Len);
     4708            /* Get the offset we need to read the command from memory (circular buffer offset). */
     4709            uint32_t const cbCmdBuf = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len);
    46614710            uint32_t offHead = pThis->CmdBufHeadPtr.n.off;
    46624711            Assert(!(offHead & ~IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK));
     4712            Assert(offHead < cbCmdBuf);
    46634713            while (offHead != pThis->CmdBufTailPtr.n.off)
    46644714            {
    4665                 /* Fetch the command from guest memory. */
     4715                /* Read the command from memory. */
    46664716                CMD_GENERIC_T Cmd;
    46674717                RTGCPHYS const GCPhysCmd = (pThis->CmdBufBaseAddr.n.u40Base << X86_PAGE_4K_SHIFT) + offHead;
     
    46744724
    46754725                    /* Process the fetched command. */
     4726                    EVT_ILLEGAL_CMD_ERR_TYPE_T enmEvtType;
    46764727                    IOMMU_UNLOCK(pDevIns);
    4677                     rc = iommuAmdR3ProcessCmd(pDevIns, &Cmd);
     4728                    rc = iommuAmdR3ProcessCmd(pDevIns, &Cmd, &enmEvtType);
    46784729                    IOMMU_LOCK(pDevIns);
    46794730                    if (RT_SUCCESS(rc))
     
    46814732                    else
    46824733                    {
    4683                         /** @todo IOMMU: Raise illegal command error. */
    4684                         /* Stop command processing. */
    4685                         ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING);
     4734                        EVT_ILLEGAL_CMD_ERR_T EvtIllegalCmdErr;
     4735                        iommuAmdInitIllegalCmdEvent(GCPhysCmd, &EvtIllegalCmdErr);
     4736                        iommuAmdRaiseIllegalCmdEvent(pDevIns, &EvtIllegalCmdErr, enmEvtType);
    46864737                        break;
    46874738                    }
     
    48464897        uint8_t const  uEncodedLen = CmdBufBar.n.u4Len;
    48474898        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
    4848         uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
     4899        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
    48494900        pHlp->pfnPrintf(pHlp, "  Command buffer BAR                      = %#RX64\n", CmdBufBar.u64);
    48504901        if (fVerbose)
     
    48604911        uint8_t const  uEncodedLen = EvtLogBar.n.u4Len;
    48614912        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
    4862         uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
     4913        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
    48634914        pHlp->pfnPrintf(pHlp, "  Event log BAR                           = %#RX64\n", EvtLogBar.u64);
    48644915        if (fVerbose)
     
    49825033        uint8_t const  uEncodedLen = PprLogBar.n.u4Len;
    49835034        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
    4984         uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
     5035        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
    49855036        pHlp->pfnPrintf(pHlp, "  PPR Log BAR                             = %#RX64\n",   PprLogBar.u64);
    49865037        if (fVerbose)
     
    50185069        uint8_t const  uEncodedLen = GALogBar.n.u4Len;
    50195070        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
    5020         uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
     5071        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
    50215072        pHlp->pfnPrintf(pHlp, "  Guest Log BAR                           = %#RX64\n",    GALogBar.u64);
    50225073        if (fVerbose)
     
    50395090        uint8_t const uEncodedLen  = PprLogBBar.n.u4Len;
    50405091        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
    5041         uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
     5092        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
    50425093        pHlp->pfnPrintf(pHlp, "  PPR Log B BAR                           = %#RX64\n",   PprLogBBar.u64);
    50435094        if (fVerbose)
     
    50535104        uint8_t const  uEncodedLen = EvtLogBBar.n.u4Len;
    50545105        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
    5055         uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
     5106        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
    50565107        pHlp->pfnPrintf(pHlp, "  Event Log B BAR                         = %#RX64\n",   EvtLogBBar.u64);
    50575108        if (fVerbose)
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