Changeset 84302 in vbox for trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
- Timestamp:
- May 14, 2020 10:38:14 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r84301 r84302 803 803 /** The 64-bit unsigned integer view. */ 804 804 uint64_t au64[2]; 805 } CMD_COMPLETION_WAIT_T; 806 AssertCompileSize(CMD_COMPLETION_WAIT_T, 16); 805 } CMD_COMWAIT_T; 806 AssertCompileSize(CMD_COMWAIT_T, 16); 807 /** Pointer to a completion wait command. */ 808 typedef CMD_COMWAIT_T *PCMD_COMWAIT_T; 809 /** Pointer to a const completion wait command. */ 810 typedef CMD_COMWAIT_T const *PCCMD_COMWAIT_T; 811 #define IOMMU_CMD_COM_WAIT_QWORD_0_VALID_MASK UINT64_C(0xf00fffffffffffff) 807 812 808 813 /** … … 2166 2171 2167 2172 /** 2168 * DEV_TAB_HARDWARE_ERROR, PAGE_TAB_HARDWARE_ERROR and COMMAND_HARDWARE_ERROR Event2169 * Types.2170 * In accordance with the AMD spec.2171 */2172 typedef enum EVT_HW_ERR_TYPE_T2173 {2174 kHwErrType_MasterAbort = 0,2175 kHwErrType_TargetAbort,2176 kHwErrType_PoisonedData2177 } EVT_HW_ERR_TYPE_T;2178 2179 /**2180 2173 * ILLEGAL_COMMAND_ERROR Event Types. 2181 2174 * In accordance with the AMD spec. … … 2586 2579 2587 2580 2588 DECL INLINE(IOMMU_STATUS_T) iommuAmdGetStatus(PCIOMMU pThis)2581 DECL_FORCE_INLINE(IOMMU_STATUS_T) iommuAmdGetStatus(PCIOMMU pThis) 2589 2582 { 2590 2583 IOMMU_STATUS_T Status; … … 2594 2587 2595 2588 2596 DECL INLINE(IOMMU_CTRL_T) iommuAmdGetCtrl(PCIOMMU pThis)2589 DECL_FORCE_INLINE(IOMMU_CTRL_T) iommuAmdGetCtrl(PCIOMMU pThis) 2597 2590 { 2598 2591 IOMMU_CTRL_T Ctrl; … … 3655 3648 * @param enmOp The IOMMU operation being performed. 3656 3649 * @param pEvtPageTabHwErr The page table hardware error event. 3657 * @param enmEvtType The hardware error event type.3658 3650 * 3659 3651 * @thread Any. 3660 3652 */ 3661 static void iommuAmdRaisePageTabHwErrorEvent(PPDMDEVINS pDevIns, IOMMUOP enmOp, PEVT_PAGE_TAB_HW_ERR_T pEvtPageTabHwErr, 3662 EVT_HW_ERR_TYPE_T enmEvtType) 3653 static void iommuAmdRaisePageTabHwErrorEvent(PPDMDEVINS pDevIns, IOMMUOP enmOp, PEVT_PAGE_TAB_HW_ERR_T pEvtPageTabHwErr) 3663 3654 { 3664 3655 AssertCompile(sizeof(EVT_GENERIC_T) == sizeof(EVT_PAGE_TAB_HW_ERR_T)); … … 3674 3665 IOMMU_UNLOCK(pDevIns); 3675 3666 3676 Log((IOMMU_LOG_PFX ": Raised PAGE_TAB_HARDWARE_ERROR. uDevId=%#x uDomainId=%#x GCPhysPtEntity=%#RGp enmOp=%u enmType=%u\n",3677 pEvtPageTabHwErr->n.u16DevId, pEvtPageTabHwErr->n.u16DomainOrPasidLo, pEvtPageTabHwErr->n.u64Addr, enmOp, enmEvtType));3678 NOREF(enmEvtType);3667 Log((IOMMU_LOG_PFX ": Raised PAGE_TAB_HARDWARE_ERROR. uDevId=%#x uDomainId=%#x GCPhysPtEntity=%#RGp enmOp=%u u2Type=%u\n", 3668 pEvtPageTabHwErr->n.u16DevId, pEvtPageTabHwErr->n.u16DomainOrPasidLo, pEvtPageTabHwErr->n.u64Addr, enmOp, 3669 pEvtPageTabHwErr->n.u2Type)); 3679 3670 } 3680 3671 … … 3683 3674 * Initializes a COMMAND_HARDWARE_ERROR event. 3684 3675 * 3685 * @param GCPhysCmd The system physical address of the command that caused 3686 * the error. 3676 * @param GCPhysAddr The system physical address the IOMMU attempted to access. 3687 3677 * @param pEvtCmdHwErr Where to store the initialized event. 3688 3678 */ 3689 static void iommuAmdInitCmdHwErrorEvent(RTGCPHYS GCPhys Cmd, HWEVTTYPE enmHwErrType, PEVT_CMD_HW_ERR_T pEvtCmdHwErr)3679 static void iommuAmdInitCmdHwErrorEvent(RTGCPHYS GCPhysAddr, PEVT_CMD_HW_ERR_T pEvtCmdHwErr) 3690 3680 { 3691 3681 memset(pEvtCmdHwErr, 0, sizeof(*pEvtCmdHwErr)); 3692 pEvtCmdHwErr->n.u2Type = enmHwErrType;3682 pEvtCmdHwErr->n.u2Type = HWEVTTYPE_DATA_ERROR; 3693 3683 pEvtCmdHwErr->n.u4EvtCode = IOMMU_EVT_COMMAND_HW_ERROR; 3694 pEvtCmdHwErr->n.u64Addr = GCPhys Cmd;3684 pEvtCmdHwErr->n.u64Addr = GCPhysAddr; 3695 3685 } 3696 3686 … … 3701 3691 * @param pDevIns The IOMMU device instance. 3702 3692 * @param pEvtCmdHwErr The command hardware error event. 3703 * @param enmEvtType The hardware error event type.3704 3693 * 3705 3694 * @thread Any. 3706 3695 */ 3707 static void iommuAmdRaiseCmdHwErrorEvent(PPDMDEVINS pDevIns, PCEVT_CMD_HW_ERR_T pEvtCmdHwErr , EVT_HW_ERR_TYPE_T enmEvtType)3696 static void iommuAmdRaiseCmdHwErrorEvent(PPDMDEVINS pDevIns, PCEVT_CMD_HW_ERR_T pEvtCmdHwErr) 3708 3697 { 3709 3698 AssertCompile(sizeof(EVT_GENERIC_T) == sizeof(EVT_CMD_HW_ERR_T)); … … 3718 3707 IOMMU_UNLOCK(pDevIns); 3719 3708 3720 Log((IOMMU_LOG_PFX ": Raised COMMAND_HARDWARE_ERROR. GCPhysCmd=%#RGp enmType=%u\n", pEvtCmdHwErr->n.u64Addr, enmEvtType));3721 NOREF(enmEvtType);3709 Log((IOMMU_LOG_PFX ": Raised COMMAND_HARDWARE_ERROR. GCPhysCmd=%#RGp u2Type=%u\n", pEvtCmdHwErr->n.u64Addr, 3710 pEvtCmdHwErr->n.u2Type)); 3722 3711 } 3723 3712 … … 3753 3742 * @param enmOp The IOMMU operation being performed. 3754 3743 * @param pEvtDevTabHwErr The device table hardware error event. 3755 * @param enmEvtType The hardware error event type.3756 3744 * 3757 3745 * @thread Any. 3758 3746 */ 3759 static void iommuAmdRaiseDevTabHwErrorEvent(PPDMDEVINS pDevIns, IOMMUOP enmOp, PEVT_DEV_TAB_HW_ERROR_T pEvtDevTabHwErr, 3760 EVT_HW_ERR_TYPE_T enmEvtType) 3747 static void iommuAmdRaiseDevTabHwErrorEvent(PPDMDEVINS pDevIns, IOMMUOP enmOp, PEVT_DEV_TAB_HW_ERROR_T pEvtDevTabHwErr) 3761 3748 { 3762 3749 AssertCompile(sizeof(EVT_GENERIC_T) == sizeof(EVT_DEV_TAB_HW_ERROR_T)); … … 3772 3759 IOMMU_UNLOCK(pDevIns); 3773 3760 3774 Log((IOMMU_LOG_PFX ": Raised DEV_TAB_HARDWARE_ERROR. uDevId=%#x GCPhysDte=%#RGp enmOp=%u enmType=%u\n", 3775 pEvtDevTabHwErr->n.u16DevId, pEvtDevTabHwErr->n.u64Addr, enmOp, enmEvtType)); 3776 NOREF(enmEvtType); 3761 Log((IOMMU_LOG_PFX ": Raised DEV_TAB_HARDWARE_ERROR. uDevId=%#x GCPhysDte=%#RGp enmOp=%u u2Type=%u\n", 3762 pEvtDevTabHwErr->n.u16DevId, pEvtDevTabHwErr->n.u64Addr, enmOp, pEvtDevTabHwErr->n.u2Type)); 3777 3763 } 3778 3764 … … 4142 4128 EVT_DEV_TAB_HW_ERROR_T EvtDevTabHwErr; 4143 4129 iommuAmdInitDevTabHwErrorEvent(uDevId, GCPhysDte, enmOp, &EvtDevTabHwErr); 4144 iommuAmdRaiseDevTabHwErrorEvent(pDevIns, enmOp, &EvtDevTabHwErr , kHwErrType_TargetAbort);4130 iommuAmdRaiseDevTabHwErrorEvent(pDevIns, enmOp, &EvtDevTabHwErr); 4145 4131 return VERR_IOMMU_IPE_1; 4146 4132 } … … 4278 4264 EVT_PAGE_TAB_HW_ERR_T EvtPageTabHwErr; 4279 4265 iommuAmdInitPageTabHwErrorEvent(uDevId, pDte->n.u16DomainId, GCPhysPtEntity, enmOp, &EvtPageTabHwErr); 4280 iommuAmdRaisePageTabHwErrorEvent(pDevIns, enmOp, &EvtPageTabHwErr , kHwErrType_TargetAbort);4266 iommuAmdRaisePageTabHwErrorEvent(pDevIns, enmOp, &EvtPageTabHwErr); 4281 4267 return VERR_IOMMU_IPE_2; 4282 4268 } … … 4623 4609 * @returns VBox status code. 4624 4610 * @param pDevIns The IOMMU device instance. 4611 * @param GCPhysCmd The system physical address of the command. 4625 4612 * @param pCmd The command to process. 4626 * @param penmEvtType Where to store the illegal command error event type in4627 * case of failures.4628 */ 4629 static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, PCCMD_GENERIC_T pCmd, PEVT_ILLEGAL_CMD_ERR_TYPE_T penmEvtType)4613 * 4614 * @thread Command thread. 4615 */ 4616 static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCmd, PCCMD_GENERIC_T pCmd) 4630 4617 { 4631 4618 IOMMU_ASSERT_NOT_LOCKED(pDevIns); 4619 4620 EVT_ILLEGAL_CMD_ERR_T EvtIllegalCmdErr; 4632 4621 4633 4622 PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU); … … 4636 4625 { 4637 4626 case IOMMU_CMD_COMPLETION_WAIT: 4627 { 4628 PCCMD_COMWAIT_T pCmdComWait = (PCCMD_COMWAIT_T)pCmd; 4629 AssertCompile(sizeof(*pCmdComWait) == sizeof(*pCmd)); 4630 4631 /* Validate reserved bits in the command. */ 4632 if (!(pCmdComWait->au64[0] & ~IOMMU_CMD_COM_WAIT_QWORD_0_VALID_MASK)) 4633 { 4634 /* If Completion Store is requested, write the Store Data to the specified Store Address.*/ 4635 if (pCmdComWait->n.u1Store) 4636 { 4637 RTGCPHYS const GCPhysStore = RT_MAKE_U64(pCmdComWait->n.u29StoreAddrLo << 3, pCmdComWait->n.u20StoreAddrHi); 4638 uint64_t const u64Data = pCmdComWait->n.u64StoreData; 4639 4640 int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysStore, &u64Data, sizeof(u64Data)); 4641 if (RT_FAILURE(rc)) 4642 { 4643 EVT_CMD_HW_ERR_T EvtCmdHwErr; 4644 iommuAmdInitCmdHwErrorEvent(GCPhysStore, &EvtCmdHwErr); 4645 iommuAmdRaiseCmdHwErrorEvent(pDevIns, &EvtCmdHwErr); 4646 Log((IOMMU_LOG_PFX ": Failed to write StoreData (%#RX64) to %#RGp. rc=%Rrc\n", u64Data, GCPhysStore, rc)); 4647 return rc; 4648 } 4649 } 4650 4651 /* If command completion interrupt is requested, honor it. */ 4652 if (pCmdComWait->n.u1Interrupt) 4653 { 4654 IOMMU_LOCK(pDevIns); 4655 IOMMU_CTRL_T const Ctrl = iommuAmdGetCtrl(pThis); 4656 if (Ctrl.n.u1CompWaitIntrEn) 4657 { 4658 /* Indicate that this command completed. */ 4659 ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_COMPLETION_WAIT_INTR); 4660 4661 /* Check and signal an interrupt if software wants to receive one when this command completes. */ 4662 IOMMU_CTRL_T const Ctrl = iommuAmdGetCtrl(pThis); 4663 if (Ctrl.n.u1CompWaitIntrEn) 4664 iommuAmdRaiseMsiInterrupt(pDevIns); 4665 } 4666 IOMMU_UNLOCK(pDevIns); 4667 } 4668 return VINF_SUCCESS; 4669 } 4670 4671 iommuAmdInitIllegalCmdEvent(GCPhysCmd, &EvtIllegalCmdErr); 4672 iommuAmdRaiseIllegalCmdEvent(pDevIns, &EvtIllegalCmdErr, kIllegalCmdErrType_RsvdNotZero); 4673 return VERR_INVALID_FUNCTION; 4674 } 4675 4638 4676 case IOMMU_CMD_INV_DEV_TAB_ENTRY: 4639 4677 case IOMMU_CMD_INV_IOMMU_PAGES: … … 4652 4690 } 4653 4691 4654 Log((IOMMU_LOG_PFX ": Invalid/Unrecognized command opcode %u (%#x)\n", bCmd, bCmd)); 4655 *penmEvtType = kIllegalCmdErrType_CmdNotSupported; 4656 return VERR_INVALID_FUNCTION; 4692 Log((IOMMU_LOG_PFX ": Unrecognized or unsupported command opcode %u (%#x)\n", bCmd, bCmd)); 4693 return VERR_NOT_SUPPORTED; 4657 4694 } 4658 4695 … … 4701 4738 * number of calls to PGM. In the longer run we could lock the memory and 4702 4739 * mappings and accessing them directly. */ 4703 IOMMU_STATUS_T Status = iommuAmdGetStatus(pThis); 4740 IOMMU_LOCK(pDevIns); 4741 4742 IOMMU_STATUS_T const Status = iommuAmdGetStatus(pThis); 4704 4743 if (Status.u64 & IOMMU_STATUS_CMD_BUF_RUNNING) 4705 4744 { 4706 IOMMU_LOCK(pDevIns);4707 4708 4745 /* Get the offset we need to read the command from memory (circular buffer offset). */ 4709 4746 uint32_t const cbCmdBuf = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len); … … 4724 4761 4725 4762 /* Process the fetched command. */ 4726 EVT_ILLEGAL_CMD_ERR_TYPE_T enmEvtType;4727 4763 IOMMU_UNLOCK(pDevIns); 4728 rc = iommuAmdR3ProcessCmd(pDevIns, &Cmd, &enmEvtType);4764 rc = iommuAmdR3ProcessCmd(pDevIns, GCPhysCmd, &Cmd); 4729 4765 IOMMU_LOCK(pDevIns); 4730 if (RT_SUCCESS(rc)) 4731 { /* likely */ } 4732 else 4733 { 4734 EVT_ILLEGAL_CMD_ERR_T EvtIllegalCmdErr; 4735 iommuAmdInitIllegalCmdEvent(GCPhysCmd, &EvtIllegalCmdErr); 4736 iommuAmdRaiseIllegalCmdEvent(pDevIns, &EvtIllegalCmdErr, enmEvtType); 4766 if (RT_FAILURE(rc)) 4737 4767 break; 4738 }4739 4768 } 4740 4769 else 4741 4770 { 4742 /* Reporting this as a "data error". Maybe target abort is more appropriate? */4743 4771 EVT_CMD_HW_ERR_T EvtCmdHwErr; 4744 iommuAmdInitCmdHwErrorEvent(GCPhysCmd, HWEVTTYPE_DATA_ERROR,&EvtCmdHwErr);4745 iommuAmdRaiseCmdHwErrorEvent(pDevIns, &EvtCmdHwErr , kHwErrType_PoisonedData);4772 iommuAmdInitCmdHwErrorEvent(GCPhysCmd, &EvtCmdHwErr); 4773 iommuAmdRaiseCmdHwErrorEvent(pDevIns, &EvtCmdHwErr); 4746 4774 break; 4747 4775 } 4748 4776 } 4749 4750 IOMMU_UNLOCK(pDevIns); 4751 } 4752 } 4777 } 4778 4779 IOMMU_UNLOCK(pDevIns); 4780 } 4781 4782 LogFlow((IOMMU_LOG_PFX ": Command thread terminating\n")); 4783 return VINF_SUCCESS; 4753 4784 } 4754 4785
Note:
See TracChangeset
for help on using the changeset viewer.