VirtualBox

Changeset 84023 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 27, 2020 7:37:58 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
137593
Message:

AMD IOMMU: bugref:9654 Bits.

File:
1 edited

Legend:

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

    r83999 r84023  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_DEV_IOMMU
     23#include <VBox/msi.h>
    2324#include <VBox/vmm/pdmdev.h>
    2425#include <VBox/AssertGuest.h>
     
    375376RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_MSI_MAP_CAPHDR_, UINT32_C(0), UINT32_MAX,
    376377                            (CAP_ID, CAP_PTR, EN, FIXED, RSVD_18_28, CAP_TYPE));
     378/** @} */
     379
     380/**
     381 * @name IOMMU Status Register Bits.
     382 * In accordance with the AMD spec.
     383 * @{
     384 */
     385/** EventOverflow: Event log overflow. */
     386#define IOMMU_STATUS_EVT_LOG_OVERFLOW               RT_BIT_64(0)
     387/** EventLogInt: Event log interrupt. */
     388#define IOMMU_STATUS_EVT_LOG_INTR                   RT_BIT_64(1)
     389/** ComWaitInt: Completion wait interrupt. */
     390#define IOMMU_STATUS_COMPLETION_WAIT_INTR           RT_BIT_64(2)
     391/** EventLogRun: Event log is running. */
     392#define IOMMU_STATUS_EVT_LOG_RUNNING                RT_BIT_64(3)
     393/** CmdBufRun: Command buffer is running. */
     394#define IOMMU_STATUS_CMD_BUF_RUNNING                RT_BIT_64(4)
     395/** PprOverflow: Peripheral page request log overflow. */
     396#define IOMMU_STATUS_PPR_LOG_OVERFLOW               RT_BIT_64(5)
     397/** PprInt: Peripheral page request log interrupt. */
     398#define IOMMU_STATUS_PPR_LOG_INTR                   RT_BIT_64(6)
     399/** PprLogRun: Peripheral page request log is running. */
     400#define IOMMU_STATUS_PPR_LOG_RUN                    RT_BIT_64(7)
     401/** GALogRun: Guest virtual-APIC log is running. */
     402#define IOMMU_STATUS_GA_LOG_RUN                     RT_BIT_64(8)
     403/** GALOverflow: Guest virtual-APIC log overflow. */
     404#define IOMMU_STATUS_GA_LOG_OVERFLOW                RT_BIT_64(9)
     405/** GAInt: Guest virtual-APIC log interrupt. */
     406#define IOMMU_STATUS_GA_LOG_INTR                    RT_BIT_64(10)
     407/** PprOvrflwB: PPR Log B overflow. */
     408#define IOMMU_STATUS_PPR_LOG_B_OVERFLOW             RT_BIT_64(11)
     409/** PprLogActive: PPR Log B is active. */
     410#define IOMMU_STATUS_PPR_LOG_B_ACTIVE               RT_BIT_64(12)
     411/** EvtOvrflwB: Event log B overflow. */
     412#define IOMMU_STATUS_EVT_LOG_B_OVERFLOW             RT_BIT_64(15)
     413/** EventLogActive: Event log B active. */
     414#define IOMMU_STATUS_EVT_LOG_B_ACTIVE               RT_BIT_64(16)
     415/** PprOvrflwEarlyB: PPR log B overflow early warning. */
     416#define IOMMU_STATUS_PPR_LOG_B_OVERFLOW_EARLY       RT_BIT_64(17)
     417/** PprOverflowEarly: PPR log overflow early warning. */
     418#define IOMMU_STATUS_PPR_LOG_OVERFLOW_EARLY         RT_BIT_64(18)
    377419/** @} */
    378420
     
    767809} EVT_GENERIC_T;
    768810AssertCompileSize(EVT_GENERIC_T, 16);
     811/** Pointer to a generic event log entry. */
     812typedef EVT_GENERIC_T *PEVT_GENERIC_T;
     813/** Pointer to a const generic event log entry. */
     814typedef const EVT_GENERIC_T *PCEVT_GENERIC_T;
    769815
    770816/**
     
    21052151
    21062152#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    2107 
    2108 /**
    2109  * Gets the buffer length length corresponding to a base address.
     2153/**
     2154 * Gets the number of buffer entries given a base register's encoded length.
    21102155 *
    2111  * @param   uEncodedLen     The length to decode (power-of-2 encoded).
    2112  * @param   pcEntries       Where to store the number of entries. Optional, can be
    2113  *                          NULL.
    2114  * @param   pcbBuffer       Where to store the size of the buffer. Optional, can be
    2115  *                          NULL.
     2156 * @returns Number of buffer entries.
     2157 * @param   uEncodedLen     The length (power-of-2 encoded).
     2158 */
     2159DECLINLINE(uint32_t) iommuAmdGetBaseBufEntryCount(uint8_t uEncodedLen)
     2160{
     2161    Assert(uEncodedLen > 7);
     2162    return 2 << (uEncodedLen - 1);
     2163}
     2164
     2165
     2166/**
     2167 * Gets the length of the buffer given a base register's encoded length.
    21162168 *
    2117  * @remarks Both @a pcEntries and @a pcbBuffer cannot both be NULL.
    2118  */
    2119 static void iommuAmdGetBaseBufferLength(uint8_t uEncodedLen, uint32_t *pcEntries, uint32_t *pcbBuffer)
    2120 {
    2121     uint32_t cEntries;
    2122     uint32_t cbBuffer;
    2123     if (uEncodedLen > 7)
    2124     {
    2125         cEntries = 2 << (uEncodedLen - 1);
    2126         cbBuffer = *pcEntries << 4;
    2127     }
    2128     else
    2129         cEntries = cbBuffer = 0;
    2130 
    2131     Assert(pcEntries || pcbBuffer);
    2132     if (pcEntries)
    2133         *pcEntries = cEntries;
    2134     if (pcbBuffer)
    2135         *pcbBuffer = cbBuffer;
     2169 * @returns The length of the buffer in bytes.
     2170 * @param   uEncodedLen     The length (power-of-2 encoded).
     2171 */
     2172DECLINLINE(uint32_t) iommuAmdGetBaseBufLength(uint8_t uEncodedLen)
     2173{
     2174    Assert(uEncodedLen > 7);
     2175    return (2 << (uEncodedLen - 1)) << 4;
    21362176}
    21372177
    21382178
    2139 DECL_FORCE_INLINE(IOMMU_STATUS_T) iommuAmdGetStatus(PCIOMMU pThis)
     2179DECLINLINE(IOMMU_STATUS_T) iommuAmdGetStatus(PCIOMMU pThis)
    21402180{
    21412181    IOMMU_STATUS_T Status;
     
    21452185
    21462186
    2147 DECL_FORCE_INLINE(IOMMU_CTRL_T) iommuAmdGetCtrl(PCIOMMU pThis)
     2187DECLINLINE(IOMMU_CTRL_T) iommuAmdGetCtrl(PCIOMMU pThis)
    21482188{
    21492189    IOMMU_CTRL_T Ctrl;
    21502190    Ctrl.u64 = ASMAtomicReadU64((volatile uint64_t *)&pThis->Ctrl.u64);
    21512191    return Ctrl;
     2192}
     2193
     2194
     2195/**
     2196 * Determines whether MSI is enabled for the IOMMU. This influences interrupt
     2197 * handling in IOMMU.
     2198 *
     2199 * @note There should be a PCIDevXxx function for this.
     2200 */
     2201static bool iommuAmdIsMsiEnabled(PPDMPCIDEV pDevIns)
     2202{
     2203    uint16_t const uMsgCtl = PDMPciDevGetWord(pDevIns, IOMMU_PCI_OFF_MSI_CAP_HDR + VBOX_MSI_CAP_MESSAGE_CONTROL);
     2204    return RT_BOOL(uMsgCtl & VBOX_PCI_MSI_FLAGS_ENABLE);
    21522205}
    21532206
     
    25072560     * In our emulation, we ignore the write entirely.
    25082561     */
    2509     uint32_t const      offBuf     = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
    2510     CMD_BUF_BAR_T const CmdBufBar  = pThis->CmdBufBaseAddr;
    2511     uint32_t            cbBuf;
    2512     iommuAmdGetBaseBufferLength(CmdBufBar.n.u4Len, NULL, &cbBuf);
     2562    uint32_t const      offBuf    = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
     2563    CMD_BUF_BAR_T const CmdBufBar = pThis->CmdBufBaseAddr;
     2564    uint32_t const      cbBuf     = iommuAmdGetBaseBufLength(CmdBufBar.n.u4Len);
    25132565    if (offBuf >= cbBuf)
    25142566    {
     
    27542806 * This is because most registers are 64-bit and aligned on 8-byte boundaries but
    27552807 * some are really 32-bit registers aligned on an 8-byte boundary. We cannot assume
    2756  * guests will only perform 32-bit reads on those 32-bit registers that are aligned
    2757  * on 8-byte boundaries.
     2808 * software will only perform 32-bit reads on those 32-bit registers that are
     2809 * aligned on 8-byte boundaries.
    27582810 *
    27592811 * @returns Strict VBox status code.
     
    29152967    *puResult = uReg;
    29162968    return VINF_SUCCESS;
     2969}
     2970
     2971
     2972static int iommuAmdWriteEventLogEntry(PPDMDEVINS pDevIns, PCEVT_GENERIC_T pEvent)
     2973{
     2974    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     2975    IOMMU_STATUS_T const Status = iommuAmdGetStatus(pThis);
     2976
     2977    /* Check if event logging is active and the log has not overflowed. */
     2978    if (   Status.n.u1EvtLogRunning
     2979        && !Status.n.u1EvtOverflow)
     2980    {
     2981        /* Figure out the event log entry offset. */
     2982        EVT_LOG_TAIL_PTR_T const TailPtr = pThis->EvtLogTailPtr;
     2983        uint32_t const offEvtLogEntry = TailPtr.n.u15Ptr << 4;
     2984
     2985        /* Ensure the event log entry is within limits. */
     2986        uint32_t const uEvtLogLen = iommuAmdGetBaseBufLength(pThis->EvtLogBaseAddr.n.u4Len);
     2987        if (offEvtLogEntry < uEvtLogLen)
     2988        {
     2989            /* Write the event log entry to memory. */
     2990            RTGCPHYS const GCPhysEvtLog      = pThis->EvtLogBaseAddr.n.u40Base;
     2991            RTGCPHYS const GCPhysEvtLogEntry = GCPhysEvtLog + offEvtLogEntry;
     2992            int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysEvtLogEntry, pEvent, sizeof(*pEvent));
     2993            if (RT_FAILURE(rc))
     2994                Log((IOMMU_LOG_PFX ": Failed to write event log entry at %#RGp. rc=%Rrc\n", GCPhysEvtLogEntry, rc));
     2995
     2996            /* Increment the event log tail pointer. */
     2997            pThis->EvtLogTailPtr.n.u15Ptr += sizeof(*pEvent);
     2998
     2999            /* Check if software wants to receive an interrupt when the event log is updated. */
     3000            IOMMU_CTRL_T const Ctrl = iommuAmdGetCtrl(pThis);
     3001            if (Ctrl.n.u1EvtIntrEn)
     3002            {
     3003                /* Signal the event log interrupt. */
     3004                ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_EVT_LOG_INTR);
     3005                /** @todo IOMMU: Generate the interrupt. */
     3006            }
     3007        }
     3008    }
    29173009}
    29183010
     
    31513243    {
    31523244        CMD_BUF_BAR_T const CmdBufBar = pThis->CmdBufBaseAddr;
    3153         uint32_t      cEntries;
    3154         uint32_t      cbBuffer;
    3155         uint8_t const uEncodedLen = CmdBufBar.n.u4Len;
    3156         iommuAmdGetBaseBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     3245        uint8_t const  uEncodedLen = CmdBufBar.n.u4Len;
     3246        uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
     3247        uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
    31573248        pHlp->pfnPrintf(pHlp, "  Command buffer BAR                      = %#RX64\n", CmdBufBar.u64);
    31583249        if (fVerbose)
     
    31663257    {
    31673258        EVT_LOG_BAR_T const EvtLogBar = pThis->EvtLogBaseAddr;
    3168         uint32_t      cEntries;
    3169         uint32_t      cbBuffer;
    3170         uint8_t const uEncodedLen = EvtLogBar.n.u4Len;
    3171         iommuAmdGetBaseBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     3259        uint8_t const  uEncodedLen = EvtLogBar.n.u4Len;
     3260        uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
     3261        uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
    31723262        pHlp->pfnPrintf(pHlp, "  Event log BAR                           = %#RX64\n", EvtLogBar.u64);
    31733263        if (fVerbose)
     
    32883378    {
    32893379        PPR_LOG_BAR_T PprLogBar = pThis->PprLogBaseAddr;
    3290         uint32_t      cEntries;
    3291         uint32_t      cbBuffer;
    3292         uint8_t const uEncodedLen = PprLogBar.n.u4Len;
    3293         iommuAmdGetBaseBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     3380        uint8_t const  uEncodedLen = PprLogBar.n.u4Len;
     3381        uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
     3382        uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
    32943383        pHlp->pfnPrintf(pHlp, "  PPR Log BAR                             = %#RX64\n",   PprLogBar.u64);
    32953384        if (fVerbose)
     
    33253414    {
    33263415        GALOG_BAR_T const GALogBar = pThis->GALogBaseAddr;
    3327         uint32_t      cEntries;
    3328         uint32_t      cbBuffer;
    3329         uint8_t const uEncodedLen = GALogBar.n.u4Len;
    3330         iommuAmdGetBaseBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     3416        uint8_t const  uEncodedLen = GALogBar.n.u4Len;
     3417        uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
     3418        uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
    33313419        pHlp->pfnPrintf(pHlp, "  Guest Log BAR                           = %#RX64\n",    GALogBar.u64);
    33323420        if (fVerbose)
     
    33473435    {
    33483436        PPR_LOG_B_BAR_T PprLogBBar = pThis->PprLogBBaseAddr;
    3349         uint32_t      cEntries;
    3350         uint32_t      cbBuffer;
    3351         uint8_t const uEncodedLen = PprLogBBar.n.u4Len;
    3352         iommuAmdGetBaseBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     3437        uint8_t const uEncodedLen  = PprLogBBar.n.u4Len;
     3438        uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
     3439        uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
    33533440        pHlp->pfnPrintf(pHlp, "  PPR Log B BAR                           = %#RX64\n",   PprLogBBar.u64);
    33543441        if (fVerbose)
     
    33623449    {
    33633450        EVT_LOG_B_BAR_T EvtLogBBar = pThis->EvtLogBBaseAddr;
    3364         uint32_t      cEntries;
    3365         uint32_t      cbBuffer;
    3366         uint8_t const uEncodedLen = EvtLogBBar.n.u4Len;
    3367         iommuAmdGetBaseBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     3451        uint8_t const  uEncodedLen = EvtLogBBar.n.u4Len;
     3452        uint32_t const cEntries    = iommuAmdGetBaseBufEntryCount(uEncodedLen);
     3453        uint32_t const cbBuffer    = iommuAmdGetBaseBufLength(uEncodedLen);
    33683454        pHlp->pfnPrintf(pHlp, "  Event Log B BAR                         = %#RX64\n",   EvtLogBBar.u64);
    33693455        if (fVerbose)
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