VirtualBox

Changeset 84123 in vbox


Ignore:
Timestamp:
May 1, 2020 8:43:46 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
137713
Message:

AMD IOMMU: bugref:9654 Bits.

File:
1 edited

Legend:

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

    r84117 r84123  
    17931793    struct
    17941794    {
    1795         uint32_t    u4Rsvd0 : 4;    /**< Bits 3:0   - Reserved. */
    1796         uint32_t    u15Ptr : 15;    /**< Bits 18:4  - Buffer pointer. */
    1797         uint32_t    u13Rsvd0 : 13;  /**< Bits 31:19 - Reserved. */
     1795        uint32_t    off;            /**< Bits 31:0  - Buffer pointer (offset; 16 byte aligned, 512 KB max). */
    17981796        uint32_t    u32Rsvd0;       /**< Bits 63:32 - Reserved. */
    17991797    } n;
     
    20972095    /** @} */
    20982096
     2097    /** @name Internal Book keeping.
     2098     *  @{ */
     2099    uint32_t                    cbCmdBufUsed;       /**< Size of commands pending in the command buffer. */
     2100    uint32_t                    cbEvtLogUsed;       /**< Size of entries pending in the event log buffer. */
     2101    /** @} */
     2102
    20992103    /** @name MMIO: Command and Event Status register.
    21002104     * @{ */
     
    22272231#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    22282232/**
    2229  * Gets the number of buffer entries given a base register's encoded length.
     2233 * Gets the maximum number of buffer entries for the given buffer length.
    22302234 *
    22312235 * @returns Number of buffer entries.
    22322236 * @param   uEncodedLen     The length (power-of-2 encoded).
    22332237 */
    2234 DECLINLINE(uint32_t) iommuAmdGetBaseBufEntryCount(uint8_t uEncodedLen)
     2238DECLINLINE(uint32_t) iommuAmdGetBufMaxEntries(uint8_t uEncodedLen)
    22352239{
    22362240    Assert(uEncodedLen > 7);
     
    22402244
    22412245/**
    2242  * Gets the length of the buffer given a base register's encoded length.
     2246 * Gets the total length of the buffer given a base register's encoded length.
    22432247 *
    22442248 * @returns The length of the buffer in bytes.
    22452249 * @param   uEncodedLen     The length (power-of-2 encoded).
    22462250 */
    2247 DECLINLINE(uint32_t) iommuAmdGetBaseBufLength(uint8_t uEncodedLen)
     2251DECLINLINE(uint32_t) iommuAmdGetBufLength(uint8_t uEncodedLen)
    22482252{
    22492253    Assert(uEncodedLen > 7);
     
    24742478        {
    24752479            ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_CMD_BUF_RUNNING);
     2480
    24762481            /* If the command buffer isn't empty, kick the command thread to start processing commands. */
    2477             if (pThis->CmdBufHeadPtr.n.u15Ptr != pThis->CmdBufTailPtr.n.u15Ptr)
     2482            if (pThis->CmdBufTailPtr.n.off != pThis->CmdBufHeadPtr.n.off)
    24782483                PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtCmdThread);
    24792484        }
     
    27212726    uint32_t const      offBuf    = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
    27222727    CMD_BUF_BAR_T const CmdBufBar = pThis->CmdBufBaseAddr;
    2723     uint32_t const      cbBuf     = iommuAmdGetBaseBufLength(CmdBufBar.n.u4Len);
     2728    uint32_t const      cbBuf     = iommuAmdGetBufLength(CmdBufBar.n.u4Len);
     2729    Assert(cbBuf <= _512K);
    27242730    if (offBuf >= cbBuf)
    27252731    {
     
    27292735    }
    27302736
    2731     pThis->CmdBufHeadPtr.u64 = offBuf;
     2737    pThis->CmdBufHeadPtr.au32[0] = offBuf;
    27322738    LogFlow((IOMMU_LOG_PFX ": Set CmdBufHeadPtr to %#RX32\n", offBuf));
    27332739    return VINF_SUCCESS;
     
    27432749
    27442750    /*
    2745      * IOMMU behavior is undefined when software advances this register equal or beyond its head pointer.
     2751     * IOMMU behavior is undefined when software writes a value outside the buffer length.
    27462752     * In our emulation, we ignore the write entirely.
    27472753     * See AMD IOMMU spec. 3.3.13 "Command and Event Log Pointer Registers".
    27482754     */
    27492755    uint32_t const offBufTail = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
    2750     NOREF(offBufTail);
    2751     NOREF(pThis);
     2756    CMD_BUF_BAR_T const CmdBufBar = pThis->CmdBufBaseAddr;
     2757    uint32_t const      cbBuf     = iommuAmdGetBufLength(CmdBufBar.n.u4Len);
     2758    if (offBufTail >= cbBuf)
     2759    {
     2760        Log((IOMMU_LOG_PFX ": Setting CmdBufTailPtr (%#RX32) to a value that exceeds buffer length (%#RX32) -> Ignored\n",
     2761             offBufTail, cbBuf));
     2762        return VINF_SUCCESS;
     2763    }
     2764
     2765    pThis->CmdBufTailPtr.au32[0] = offBufTail;
     2766    LogFlow((IOMMU_LOG_PFX ": Set CmdBufTailPtr to %#RX32\n", offBufTail));
    27522767    return VINF_SUCCESS;
    27532768}
     
    31703185        && !Status.n.u1EvtOverflow)
    31713186    {
    3172         /* Figure out the event log entry offset. */
    3173         EVT_LOG_TAIL_PTR_T const TailPtr = pThis->EvtLogTailPtr;
    3174         uint32_t const offEvtLogEntry = TailPtr.n.u15Ptr << 4;
    3175 
    3176         /* Ensure the event log entry is within limits. */
    3177         uint32_t const uEvtLogLen = iommuAmdGetBaseBufLength(pThis->EvtLogBaseAddr.n.u4Len);
    3178         if (offEvtLogEntry < uEvtLogLen)
     3187        uint32_t const cbEvt = sizeof(*pEvent);
     3188
     3189        /* Get the offset we need to write the event to in memory (circular buffer offset). */
     3190        uint32_t const offEvt = pThis->EvtLogTailPtr.n.off;
     3191        Assert(!(offEvt & ~IOMMU_CMD_BUF_TAIL_PTR_VALID_MASK));
     3192
     3193        /* Ensure we have space in the event log. */
     3194        uint32_t const cbEvtLog = iommuAmdGetBufLength(pThis->EvtLogBaseAddr.n.u4Len);
     3195        uint32_t const cbUsed   = pThis->cbEvtLogUsed;
     3196        if (cbUsed + cbEvt < cbEvtLog)
    31793197        {
    31803198            /* Write the event log entry to memory. */
    31813199            RTGCPHYS const GCPhysEvtLog      = pThis->EvtLogBaseAddr.n.u40Base << X86_PAGE_4K_SHIFT;
    3182             RTGCPHYS const GCPhysEvtLogEntry = GCPhysEvtLog + offEvtLogEntry;
    3183             int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysEvtLogEntry, pEvent, sizeof(*pEvent));
     3200            RTGCPHYS const GCPhysEvtLogEntry = GCPhysEvtLog + offEvt;
     3201            int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysEvtLogEntry, pEvent, cbEvt);
    31843202            if (RT_FAILURE(rc))
    31853203                Log((IOMMU_LOG_PFX ": Failed to write event log entry at %#RGp. rc=%Rrc\n", GCPhysEvtLogEntry, rc));
    31863204
    31873205            /* Increment the event log tail pointer. */
    3188             pThis->EvtLogTailPtr.n.u15Ptr += sizeof(*pEvent);
     3206            pThis->EvtLogTailPtr.n.off = (offEvt + cbEvt) % cbEvtLog;
     3207
     3208            /* Increment the size of entries pending in the event log. */
     3209            pThis->cbEvtLogUsed += cbEvt;
    31893210
    31903211            /* Indicate that an event log entry was written. */
     
    36113632        CMD_BUF_BAR_T const CmdBufBar = pThis->CmdBufBaseAddr;
    36123633        uint8_t const  uEncodedLen = CmdBufBar.n.u4Len;
    3613         uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
    3614         uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
     3634        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
     3635        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
    36153636        pHlp->pfnPrintf(pHlp, "  Command buffer BAR                      = %#RX64\n", CmdBufBar.u64);
    36163637        if (fVerbose)
     
    36253646        EVT_LOG_BAR_T const EvtLogBar = pThis->EvtLogBaseAddr;
    36263647        uint8_t const  uEncodedLen = EvtLogBar.n.u4Len;
    3627         uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
    3628         uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
     3648        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
     3649        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
    36293650        pHlp->pfnPrintf(pHlp, "  Event log BAR                           = %#RX64\n", EvtLogBar.u64);
    36303651        if (fVerbose)
     
    37473768        PPR_LOG_BAR_T PprLogBar = pThis->PprLogBaseAddr;
    37483769        uint8_t const  uEncodedLen = PprLogBar.n.u4Len;
    3749         uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
    3750         uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
     3770        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
     3771        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
    37513772        pHlp->pfnPrintf(pHlp, "  PPR Log BAR                             = %#RX64\n",   PprLogBar.u64);
    37523773        if (fVerbose)
     
    37833804        GALOG_BAR_T const GALogBar = pThis->GALogBaseAddr;
    37843805        uint8_t const  uEncodedLen = GALogBar.n.u4Len;
    3785         uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
    3786         uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
     3806        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
     3807        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
    37873808        pHlp->pfnPrintf(pHlp, "  Guest Log BAR                           = %#RX64\n",    GALogBar.u64);
    37883809        if (fVerbose)
     
    38043825        PPR_LOG_B_BAR_T PprLogBBar = pThis->PprLogBBaseAddr;
    38053826        uint8_t const uEncodedLen  = PprLogBBar.n.u4Len;
    3806         uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
    3807         uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
     3827        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
     3828        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
    38083829        pHlp->pfnPrintf(pHlp, "  PPR Log B BAR                           = %#RX64\n",   PprLogBBar.u64);
    38093830        if (fVerbose)
     
    38183839        EVT_LOG_B_BAR_T EvtLogBBar = pThis->EvtLogBBaseAddr;
    38193840        uint8_t const  uEncodedLen = EvtLogBBar.n.u4Len;
    3820         uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
    3821         uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
     3841        uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
     3842        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
    38223843        pHlp->pfnPrintf(pHlp, "  Event Log B BAR                         = %#RX64\n",   EvtLogBBar.u64);
    38233844        if (fVerbose)
     
    39964017        CMD_BUF_HEAD_PTR_T const CmdBufHeadPtr = pThis->CmdBufHeadPtr;
    39974018        pHlp->pfnPrintf(pHlp, "  Command Buffer Head Pointer             = %#RX64\n", CmdBufHeadPtr.u64);
    3998         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufHeadPtr.n.u15Ptr);
     4019        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufHeadPtr.n.off);
    39994020    }
    40004021    /* Command Buffer Tail Pointer Register. */
     
    40024023        CMD_BUF_HEAD_PTR_T const CmdBufTailPtr = pThis->CmdBufTailPtr;
    40034024        pHlp->pfnPrintf(pHlp, "  Command Buffer Tail Pointer             = %#RX64\n", CmdBufTailPtr.u64);
    4004         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufTailPtr.n.u15Ptr);
     4025        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufTailPtr.n.off);
    40054026    }
    40064027    /* Event Log Head Pointer Register. */
     
    40084029        EVT_LOG_HEAD_PTR_T const EvtLogHeadPtr = pThis->EvtLogHeadPtr;
    40094030        pHlp->pfnPrintf(pHlp, "  Event Log Head Pointer                  = %#RX64\n", EvtLogHeadPtr.u64);
    4010         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogHeadPtr.n.u15Ptr);
     4031        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogHeadPtr.n.off);
    40114032    }
    40124033    /* Event Log Tail Pointer Register. */
     
    40144035        EVT_LOG_TAIL_PTR_T const EvtLogTailPtr = pThis->EvtLogTailPtr;
    40154036        pHlp->pfnPrintf(pHlp, "  Event Log Head Pointer                  = %#RX64\n", EvtLogTailPtr.u64);
    4016         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogTailPtr.n.u15Ptr);
     4037        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogTailPtr.n.off);
    40174038    }
    40184039    /* Status Register. */
     
    40444065        PPR_LOG_HEAD_PTR_T const PprLogHeadPtr = pThis->PprLogHeadPtr;
    40454066        pHlp->pfnPrintf(pHlp, "  PPR Log Head Pointer                    = %#RX64\n", PprLogHeadPtr.u64);
    4046         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogHeadPtr.n.u15Ptr);
     4067        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogHeadPtr.n.off);
    40474068    }
    40484069    /* PPR Log Tail Pointer. */
     
    40504071        PPR_LOG_TAIL_PTR_T const PprLogTailPtr = pThis->PprLogTailPtr;
    40514072        pHlp->pfnPrintf(pHlp, "  PPR Log Tail Pointer                    = %#RX64\n", PprLogTailPtr.u64);
    4052         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogTailPtr.n.u15Ptr);
     4073        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogTailPtr.n.off);
    40534074    }
    40544075    /* Guest Virtual-APIC Log Head Pointer. */
     
    40684089        PPR_LOG_B_HEAD_PTR_T const PprLogBHeadPtr = pThis->PprLogBHeadPtr;
    40694090        pHlp->pfnPrintf(pHlp, "  PPR Log B Head Pointer                  = %#RX64\n", PprLogBHeadPtr.u64);
    4070         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBHeadPtr.n.u15Ptr);
     4091        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBHeadPtr.n.off);
    40714092    }
    40724093    /* PPR Log B Tail Pointer. */
     
    40744095        PPR_LOG_B_TAIL_PTR_T const PprLogBTailPtr = pThis->PprLogBTailPtr;
    40754096        pHlp->pfnPrintf(pHlp, "  PPR Log B Tail Pointer                  = %#RX64\n", PprLogBTailPtr.u64);
    4076         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBTailPtr.n.u15Ptr);
     4097        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBTailPtr.n.off);
    40774098    }
    40784099    /* Event Log B Head Pointer. */
     
    40804101        EVT_LOG_B_HEAD_PTR_T const EvtLogBHeadPtr = pThis->EvtLogBHeadPtr;
    40814102        pHlp->pfnPrintf(pHlp, "  Event Log B Head Pointer                = %#RX64\n", EvtLogBHeadPtr.u64);
    4082         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBHeadPtr.n.u15Ptr);
     4103        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBHeadPtr.n.off);
    40834104    }
    40844105    /* Event Log B Tail Pointer. */
     
    40864107        EVT_LOG_B_TAIL_PTR_T const EvtLogBTailPtr = pThis->EvtLogBTailPtr;
    40874108        pHlp->pfnPrintf(pHlp, "  Event Log B Tail Pointer                = %#RX64\n", EvtLogBTailPtr.u64);
    4088         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBTailPtr.n.u15Ptr);
     4109        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBTailPtr.n.off);
    40894110    }
    40904111    /* PPR Log Auto Response Register. */
     
    42074228    pThis->EvtLogHeadPtr.u64         = 0;
    42084229    pThis->EvtLogTailPtr.u64         = 0;
     4230
     4231    pThis->cbCmdBufUsed              = 0;
     4232    pThis->cbEvtLogUsed              = 0;
    42094233
    42104234    pThis->Status.u64                = 0;
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