VirtualBox

Ignore:
Timestamp:
May 13, 2020 3:49:35 PM (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

    r84285 r84291  
    497497        else \
    498498            return rcLock; \
     499    } while (0)
     500
     501/**
     502 * Acquires the IOMMU PDM lock (no return, only asserts on failure).
     503 * This will make a long jump to ring-3 to acquire the lock if necessary.
     504 */
     505#define IOMMU_LOCK_NORET(a_pDevIns, a_pThis)  \
     506    do { \
     507        NOREF(pThis); \
     508        int rcLock = PDMDevHlpCritSectEnter((a_pDevIns), (a_pDevIns)->CTX_SUFF(pCritSectRo), VINF_SUCCESS); \
     509        AssertRC(rcLock); \
    499510    } while (0)
    500511
     
    9951006    /** The 32-bit unsigned integer view.  */
    9961007    uint32_t    au32[4];
     1008    /** The 64-bit unsigned integer view. */
     1009    uint64_t    au64[2];
    9971010} EVT_ILLEGAL_DTE_T;
    9981011AssertCompileSize(EVT_ILLEGAL_DTE_T, 16);
     
    10281041    /** The 32-bit unsigned integer view.  */
    10291042    uint32_t    au32[4];
     1043    /** The 64-bit unsigned integer view. */
     1044    uint64_t    au64[2];
    10301045} EVT_IO_PAGE_FAULT_T;
    10311046AssertCompileSize(EVT_IO_PAGE_FAULT_T, 16);
     
    10591074    /** The 32-bit unsigned integer view.  */
    10601075    uint32_t    au32[4];
     1076    /** The 64-bit unsigned integer view. */
     1077    uint64_t    au64[2];
    10611078} EVT_DEV_TAB_HW_ERROR_T;
    10621079AssertCompileSize(EVT_DEV_TAB_HW_ERROR_T, 16);
     
    10941111    /** The 32-bit unsigned integer view. */
    10951112    uint32_t    au32[4];
     1113    /** The 64-bit unsigned integer view. */
     1114    uint64_t    au64[2];
    10961115} EVT_PAGE_TAB_HW_ERR_T;
    10971116AssertCompileSize(EVT_PAGE_TAB_HW_ERR_T, 16);
     
    11001119/** Pointer to a const page table hardware error event. */
    11011120typedef EVT_PAGE_TAB_HW_ERR_T const *PCEVT_PAGE_TAB_HW_ERR_T;
    1102 
    11031121
    11041122/**
     
    11191137    /** The 32-bit unsigned integer view. */
    11201138    uint32_t    au32[4];
     1139    /** The 64-bit unsigned integer view. */
     1140    uint64_t    au64[2];
    11211141} EVT_ILLEGAL_CMD_ERR_T;
    11221142AssertCompileSize(EVT_ILLEGAL_CMD_ERR_T, 16);
     
    11301150    struct
    11311151    {
    1132         uint32_t    u32Rsvd0;           /**< Bits 31:0  - Reserved. */
    1133         uint32_t    u4Rsvd0 : 4;        /**< Bits 35:32 - Reserved. */
    1134         uint32_t    u28AddrLo : 28;     /**< Bits 63:36 - Address: SPA of the attempted access (Lo). */
    1135         uint32_t    u32AddrHi;          /**< Bits 95:64 - Address: SPA of the attempted access (Hi). */
     1152        uint32_t    u32Rsvd0;           /**< Bits 31:0   - Reserved. */
     1153        uint32_t    u25Rsvd1 : 25;      /**< Bits 56:32  - Reserved. */
     1154        uint32_t    u2Type : 2;         /**< Bits 58:57  - Type: The type of hardware error. */
     1155        uint32_t    u1Rsvd1 : 1;        /**< Bit  59     - Reserved. */
     1156        uint32_t    u4EvtCode : 4;      /**< Bits 63:60  - Event code. */
     1157        uint64_t    u64Addr;            /**< Bits 128:64 - Address: SPA of the attempted access. */
    11361158    } n;
    11371159    /** The 32-bit unsigned integer view. */
    1138     uint32_t    au32[3];
    1139 } EVT_CMD_HW_ERROR_T;
    1140 AssertCompileSize(EVT_CMD_HW_ERROR_T, 12);
     1160    uint32_t    au32[4];
     1161    /** The 64-bit unsigned integer view. */
     1162    uint64_t    au64[2];
     1163} EVT_CMD_HW_ERR_T;
     1164AssertCompileSize(EVT_CMD_HW_ERR_T, 16);
     1165/** Pointer to a command hardware error event. */
     1166typedef EVT_CMD_HW_ERR_T *PEVT_CMD_HW_ERR_T;
     1167/** Pointer to a const command hardware error event. */
     1168typedef EVT_CMD_HW_ERR_T const *PCEVT_CMD_HW_ERR_T;
    11411169
    11421170/**
     
    26022630
    26032631/**
     2632 * Halts command processing.
     2633 *
     2634 * @param   pDevIns     The IOMMU device instance.
     2635 */
     2636static void iommuAmdHaltCmdProcessing(PPDMDEVINS pDevIns)
     2637{
     2638    IOMMU_ASSERT_LOCKED(pDevIns);
     2639
     2640    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     2641    ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING);
     2642}
     2643
     2644
     2645/**
    26042646 * Wakes up the command thread if there are commands to be processed or if
    26052647 * processing is requested to be stopped by software.
     
    35663608static void iommuAmdSetHwError(PPDMDEVINS pDevIns, PCEVT_GENERIC_T pEvent)
    35673609{
    3568     /** @todo IOMMU: We should probably lock the device here */
    35693610    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     3611    IOMMU_LOCK_NORET(pDevIns, pThis);
    35703612    if (pThis->ExtFeat.n.u1HwErrorSup)
    35713613    {
     
    35773619        Assert(pThis->HwEvtHi.n.u4EvtCode == IOMMU_EVT_DEV_TAB_HW_ERROR);
    35783620    }
     3621    IOMMU_UNLOCK(pDevIns, pThis);
    35793622}
    35803623
     
    36003643    pEvtPageTabHwErr->n.u1ReadWrite        = RT_BOOL(enmOp == IOMMUOP_MEM_WRITE);
    36013644    pEvtPageTabHwErr->n.u1Translation      = RT_BOOL(enmOp == IOMMUOP_TRANSLATE_REQ);
    3602     pEvtPageTabHwErr->n.u2Type             = enmOp == IOMMUOP_CMD ? HWEVTTYPE_DATA_ERROR : HWEVTTYPE_TARGET_ABORT;;
     3645    pEvtPageTabHwErr->n.u2Type             = enmOp == IOMMUOP_CMD ? HWEVTTYPE_DATA_ERROR : HWEVTTYPE_TARGET_ABORT;
    36033646    pEvtPageTabHwErr->n.u4EvtCode          = IOMMU_EVT_PAGE_TAB_HW_ERROR;
    36043647    pEvtPageTabHwErr->n.u64Addr            = GCPhysPtEntity;
     
    36273670    Log((IOMMU_LOG_PFX ": Raised PAGE_TAB_HARDWARE_ERROR. uDevId=%#x uDomainId=%#x GCPhysPtEntity=%#RGp enmOp=%u enmType=%u\n",
    36283671         pEvtPageTabHwErr->n.u16DevId, pEvtPageTabHwErr->n.u16DomainOrPasidLo, pEvtPageTabHwErr->n.u64Addr, enmOp, enmEvtType));
     3672    NOREF(enmEvtType);
     3673}
     3674
     3675
     3676/**
     3677 * Initializes a COMMAND_HARDWARE_ERROR event.
     3678 *
     3679 * @param   GCPhysCmd       The system physical address of the command that caused
     3680 *                          the error.
     3681 * @param   pEvtCmdHwErr    Where to store the initialized event.
     3682 */
     3683static void iommuAmdInitCmdHwErrorEvent(RTGCPHYS GCPhysCmd, HWEVTTYPE enmHwErrType, PEVT_CMD_HW_ERR_T pEvtCmdHwErr)
     3684{
     3685    memset(pEvtCmdHwErr, 0, sizeof(*pEvtCmdHwErr));
     3686    pEvtCmdHwErr->n.u2Type    = enmHwErrType;
     3687    pEvtCmdHwErr->n.u4EvtCode = IOMMU_EVT_COMMAND_HW_ERROR;
     3688    pEvtCmdHwErr->n.u64Addr   = GCPhysCmd;
     3689}
     3690
     3691
     3692/**
     3693 * Raises a COMMAND_HARDWARE_ERROR event.
     3694 *
     3695 * @param   pDevIns         The IOMMU device instance.
     3696 * @param   pEvtCmdHwErr    The command hardware error event.
     3697 * @param   enmEvtType      The hardware error event type.
     3698 */
     3699static void iommuAmdRaiseCmdHwErrorEvent(PPDMDEVINS pDevIns, PCEVT_CMD_HW_ERR_T pEvtCmdHwErr, EVT_HW_ERR_TYPE_T enmEvtType)
     3700{
     3701    AssertCompile(sizeof(EVT_GENERIC_T) == sizeof(EVT_CMD_HW_ERR_T));
     3702    PCEVT_GENERIC_T pEvent = (PCEVT_GENERIC_T)pEvtCmdHwErr;
     3703
     3704    iommuAmdSetHwError(pDevIns, (PCEVT_GENERIC_T)pEvent);
     3705    iommuAmdWriteEvtLogEntry(pDevIns, (PCEVT_GENERIC_T)pEvent);
     3706    iommuAmdHaltCmdProcessing(pDevIns);
     3707
     3708    Log((IOMMU_LOG_PFX ": Raised COMMAND_HARDWARE_ERROR. GCPhysCmd=%#RGp enmType=%u\n", pEvtCmdHwErr->n.u64Addr, enmEvtType));
    36293709    NOREF(enmEvtType);
    36303710}
     
    45484628         *        mappings and accessing them directly. */
    45494629        IOMMU_STATUS_T Status = iommuAmdGetStatus(pThis);
    4550         if (Status.n.u1CmdBufRunning)
     4630        if (Status.u64 & IOMMU_STATUS_CMD_BUF_RUNNING)
    45514631        {
    45524632            IOMMU_LOCK(pDevIns, pThis);
     
    45834663                else
    45844664                {
    4585                     /** @todo IOMMU: Raise command hardware error. */
    4586                     /* Stop command processing. */
    4587                     ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING);
     4665                    /* Reporting this as a "data error". Maybe target abort is more appropriate? */
     4666                    EVT_CMD_HW_ERR_T EvtCmdHwErr;
     4667                    iommuAmdInitCmdHwErrorEvent(GCPhysCmd, HWEVTTYPE_DATA_ERROR, & EvtCmdHwErr);
     4668                    iommuAmdRaiseCmdHwErrorEvent(pDevIns, &EvtCmdHwErr, kHwErrType_PoisonedData);
    45884669                    break;
    45894670                }
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