Changeset 87415 in vbox
- Timestamp:
- Jan 25, 2021 11:33:58 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 142403
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r87410 r87415 28 28 #include <iprt/x86.h> 29 29 #include <iprt/string.h> 30 #ifdef IN_RING3 31 # include <iprt/mem.h> 32 #endif 30 33 31 34 #include "VBoxDD.h" … … 489 492 { 490 493 Assert(uEncodedLen > 7); 494 Assert(uEncodedLen < 16); 491 495 return 2 << (uEncodedLen - 1); 492 496 } … … 502 506 { 503 507 Assert(uEncodedLen > 7); 508 Assert(uEncodedLen < 16); 504 509 return (2 << (uEncodedLen - 1)) << 4; 505 510 } … … 3733 3738 return VINF_SUCCESS; 3734 3739 3740 /* 3741 * Pre-allocate the maximum command buffer size supported by the IOMMU. 3742 * This avoid trashing the heap as well as not wasting time allocating 3743 * and freeing buffers while processing commands. 3744 */ 3745 size_t cbMaxCmds = sizeof(CMD_GENERIC_T) * iommuAmdGetBufMaxEntries(15); 3746 void *pvCmds = RTMemAllocZ(cbMaxCmds); 3747 AssertReturn(pvCmds, VERR_NO_MEMORY); 3748 3735 3749 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 3736 3750 { … … 3757 3771 * Fetch and process IOMMU commands. 3758 3772 */ 3759 /** @todo r=ramshankar: This employs a simplistic method of fetching commands (one 3760 * at a time) and is expensive due to calls to PGM for fetching guest memory. 3761 * We could optimize by fetching a bunch of commands at a time reducing 3762 * number of calls to PGM. In the longer run we could lock the memory and 3763 * mappings and accessing them directly. */ 3773 /** @todo r=ramshankar: We currently copy all commands from guest memory into a 3774 * temporary host buffer before processing them as a batch. If we want to 3775 * save on host memory a bit we could, once PGM has the necessary APIs, lock 3776 * the page mappings and access them directly. */ 3764 3777 IOMMU_LOCK(pDevIns); 3765 3778 … … 3767 3780 if (Status.n.u1CmdBufRunning) 3768 3781 { 3769 /* Get the offset we need to read the commandfrom memory (circular buffer offset). */3782 /* Get the offsets we need to read commands from memory (circular buffer offset). */ 3770 3783 uint32_t const cbCmdBuf = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len); 3771 uint32_t offHead = pThis->CmdBufHeadPtr.n.off; 3784 uint32_t const offTail = pThis->CmdBufTailPtr.n.off; 3785 uint32_t offHead = pThis->CmdBufHeadPtr.n.off; 3786 3787 /* Validate. */ 3772 3788 Assert(!(offHead & ~IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK)); 3773 3789 Assert(offHead < cbCmdBuf); 3774 while (offHead != pThis->CmdBufTailPtr.n.off) 3790 Assert(cbCmdBuf <= cbMaxCmds); 3791 3792 if (offHead != offTail) 3775 3793 { 3776 /* Read the command from memory. */ 3777 CMD_GENERIC_T Cmd; 3778 RTGCPHYS const GCPhysCmd = (pThis->CmdBufBaseAddr.n.u40Base << X86_PAGE_4K_SHIFT) + offHead; 3779 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCmd, &Cmd, sizeof(Cmd)); 3794 /* Read the entire command buffer from memory (avoids multiple PGM calls). */ 3795 RTGCPHYS const GCPhysCmdBufBase = pThis->CmdBufBaseAddr.n.u40Base << X86_PAGE_4K_SHIFT; 3796 int rc = PDMDevHlpPhysRead(pDevIns, GCPhysCmdBufBase, pvCmds, cbCmdBuf); 3780 3797 if (RT_SUCCESS(rc)) 3781 3798 { 3782 /* Increment the command buffer head pointer. */ 3783 offHead = (offHead + sizeof(CMD_GENERIC_T)) % cbCmdBuf; 3784 pThis->CmdBufHeadPtr.n.off = offHead; 3785 3786 /* Process the fetched command. */ 3799 /* Indicate to software we've fetched all commands from the buffer. */ 3800 pThis->CmdBufHeadPtr.n.off = offTail; 3801 3802 /* Allow IOMMU to do other work while we process commands. */ 3803 IOMMU_UNLOCK(pDevIns); 3804 3805 /* Process the fetched commands. */ 3787 3806 EVT_GENERIC_T EvtError; 3788 IOMMU_UNLOCK(pDevIns); 3789 rc = iommuAmdR3ProcessCmd(pDevIns, &Cmd, GCPhysCmd, &EvtError); 3790 IOMMU_LOCK(pDevIns); 3791 if (RT_FAILURE(rc)) 3807 do 3792 3808 { 3793 if ( rc == VERR_IOMMU_CMD_NOT_SUPPORTED 3794 || rc == VERR_IOMMU_CMD_INVALID_FORMAT) 3809 PCCMD_GENERIC_T pCmd = (PCCMD_GENERIC_T)((uintptr_t)pvCmds + offHead); 3810 rc = iommuAmdR3ProcessCmd(pDevIns, pCmd, GCPhysCmdBufBase + offHead, &EvtError); 3811 if (RT_FAILURE(rc)) 3795 3812 { 3796 Assert(EvtError.n.u4EvtCode == IOMMU_EVT_ILLEGAL_CMD_ERROR); 3797 iommuAmdRaiseIllegalCmdEvent(pDevIns, (PCEVT_ILLEGAL_CMD_ERR_T)&EvtError); 3813 if ( rc == VERR_IOMMU_CMD_NOT_SUPPORTED 3814 || rc == VERR_IOMMU_CMD_INVALID_FORMAT) 3815 { 3816 Assert(EvtError.n.u4EvtCode == IOMMU_EVT_ILLEGAL_CMD_ERROR); 3817 iommuAmdRaiseIllegalCmdEvent(pDevIns, (PCEVT_ILLEGAL_CMD_ERR_T)&EvtError); 3818 } 3819 else if (rc == VERR_IOMMU_CMD_HW_ERROR) 3820 { 3821 Assert(EvtError.n.u4EvtCode == IOMMU_EVT_COMMAND_HW_ERROR); 3822 LogFunc(("Raising command hardware error. Cmd=%#x -> COMMAND_HW_ERROR\n", pCmd->n.u4Opcode)); 3823 iommuAmdRaiseCmdHwErrorEvent(pDevIns, (PCEVT_CMD_HW_ERR_T)&EvtError); 3824 } 3825 break; 3798 3826 } 3799 else if (rc == VERR_IOMMU_CMD_HW_ERROR) 3800 { 3801 Assert(EvtError.n.u4EvtCode == IOMMU_EVT_COMMAND_HW_ERROR); 3802 LogFunc(("Raising command hardware error. Cmd=%#x -> COMMAND_HW_ERROR\n", Cmd.n.u4Opcode)); 3803 iommuAmdRaiseCmdHwErrorEvent(pDevIns, (PCEVT_CMD_HW_ERR_T)&EvtError); 3804 } 3805 break; 3806 } 3827 offHead = (offHead + sizeof(CMD_GENERIC_T)) % cbCmdBuf; 3828 } while (offHead != offTail); 3807 3829 } 3808 3830 else 3809 3831 { 3810 LogFunc(("Failed to read command at %#RGp. rc=%Rrc -> COMMAND_HW_ERROR\n", GCPhysCmd , rc));3832 LogFunc(("Failed to read command at %#RGp. rc=%Rrc -> COMMAND_HW_ERROR\n", GCPhysCmdBufBase, rc)); 3811 3833 EVT_CMD_HW_ERR_T EvtCmdHwErr; 3812 iommuAmdInitCmdHwErrorEvent(GCPhysCmd , &EvtCmdHwErr);3834 iommuAmdInitCmdHwErrorEvent(GCPhysCmdBufBase, &EvtCmdHwErr); 3813 3835 iommuAmdRaiseCmdHwErrorEvent(pDevIns, &EvtCmdHwErr); 3814 break;3836 IOMMU_UNLOCK(pDevIns); 3815 3837 } 3816 3838 } 3817 } 3818 3819 IOMMU_UNLOCK(pDevIns); 3820 } 3821 3839 else 3840 IOMMU_UNLOCK(pDevIns); 3841 } 3842 else 3843 IOMMU_UNLOCK(pDevIns); 3844 } 3845 3846 RTMemFree(pvCmds); 3822 3847 LogFlowFunc(("Command thread terminating\n")); 3823 3848 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.