VirtualBox

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


Ignore:
Timestamp:
Apr 24, 2020 8:49:48 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
137523
Message:

AMD IOMMU: bugref:9654 Bits.

File:
1 edited

Legend:

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

    r83945 r83959  
    7878
    7979#define IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST            0x100
     80#define IOMMU_MMIO_OFF_DEV_TAB_SEG_1                0x100
     81#define IOMMU_MMIO_OFF_DEV_TAB_SEG_2                0x108
     82#define IOMMU_MMIO_OFF_DEV_TAB_SEG_3                0x110
     83#define IOMMU_MMIO_OFF_DEV_TAB_SEG_4                0x118
     84#define IOMMU_MMIO_OFF_DEV_TAB_SEG_5                0x120
     85#define IOMMU_MMIO_OFF_DEV_TAB_SEG_6                0x128
     86#define IOMMU_MMIO_OFF_DEV_TAB_SEG_7                0x130
    8087#define IOMMU_MMIO_OFF_DEV_TAB_SEG_LAST             0x130
    8188
     
    372379/** @name Miscellaneous IOMMU defines.
    373380 * @{ */
    374 #define IOMMU_LOG_PFX                               "AMD_IOMMU"     /**< Log prefix string. */
    375 #define IOMMU_SAVED_STATE_VERSION                   1               /**< The current saved state version. */
    376 #define IOMMU_PCI_VENDOR_ID                         0x1022          /**< AMD's vendor ID. */
    377 #define IOMMU_PCI_DEVICE_ID                         0xc0de          /**< VirtualBox IOMMU device ID. */
    378 #define IOMMU_PCI_REVISION_ID                       0x01            /**< VirtualBox IOMMU device revision ID. */
    379 #define IOMMU_MMIO_REGION_SIZE                      _16K            /**< Size of the MMIO region in bytes. */
     381/** Log prefix string. */
     382#define IOMMU_LOG_PFX                               "AMD_IOMMU"
     383/** The current saved state version. */
     384#define IOMMU_SAVED_STATE_VERSION                   1
     385/** AMD's vendor ID. */
     386#define IOMMU_PCI_VENDOR_ID                         0x1022
     387/** VirtualBox IOMMU device ID. */
     388#define IOMMU_PCI_DEVICE_ID                         0xc0de
     389/** VirtualBox IOMMU device revision ID. */
     390#define IOMMU_PCI_REVISION_ID                       0x01
     391/** Size of the MMIO region in bytes. */
     392#define IOMMU_MMIO_REGION_SIZE                      _16K
     393/** Number of device table segments supported (power of 2). */
     394#define IOMMU_MAX_DEV_TAB_SEGMENTS                  3
    380395/** @} */
    381396
     
    10571072} DEV_TAB_BAR_T;
    10581073AssertCompileSize(DEV_TAB_BAR_T, 8);
    1059 #define IOMMU_DEV_TAB_BAR_VALID_MASK      UINT64_C(0x000ffffffffff3ff)
     1074#define IOMMU_DEV_TAB_BAR_VALID_MASK      UINT64_C(0x000ffffffffff1ff)
    10601075
    10611076/**
     
    13761391} DEV_TAB_SEG_BAR_T;
    13771392AssertCompileSize(DEV_TAB_SEG_BAR_T, 8);
     1393#define IOMMU_DEV_TAB_SEG_BAR_VALID_MASK      UINT64_C(0x000ffffffffff0ff)
    13781394
    13791395/**
     
    20852101
    20862102
     2103/*********************************************************************************************************************************
     2104*   Global Variables                                                                                                             *
     2105*********************************************************************************************************************************/
     2106/**
     2107 * An array of the number of device table segments supported.
     2108 * Indexed by u2DevTabSegSup.
     2109 */
     2110static uint8_t const g_aDevTabSegments[] = { 0, 2, 4, 8 };
     2111
     2112/**
     2113 * The maximum size (inclusive) of each device table segment (0 to 7).
     2114 * Indexed by the device table segment index.
     2115 */
     2116static uint16_t const g_aDevTabSegmentSizes[] = { 0x1ff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x3f };
     2117
     2118
    20872119#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    20882120
     
    22992331    RT_NOREF(pDevIns, iReg);
    23002332
    2301     /* Ignore all unrecognized bits. */
     2333    /* Mask out all unrecognized bits. */
    23022334    u64Value &= IOMMU_HW_EVT_STATUS_VALID_MASK;
    23032335
     
    23202352
    23212353/**
     2354 * Writes the Device Table Segment Base Address Register.
     2355 */
     2356static VBOXSTRICTRC iommuAmdDevTabSegBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     2357{
     2358    RT_NOREF(pDevIns);
     2359
     2360    /* Figure out which segment is being written. */
     2361    uint8_t const idxDevTabSeg = (iReg - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3;
     2362    Assert(idxDevTabSeg < RT_ELEMENTS(pThis->DevTabSeg));
     2363
     2364    /* Mask out all unrecognized bits. */
     2365    u64Value &= IOMMU_DEV_TAB_SEG_BAR_VALID_MASK;
     2366    uint8_t const cbSegSize = u64Value & UINT64_C(0xff);
     2367
     2368    /* Validate the size and write the register. */
     2369    uint8_t const  idxSegment   = idxDevTabSeg + 1;
     2370    uint16_t const cbMaxSegSize = g_aDevTabSegmentSizes[idxSegment];
     2371    if (cbSegSize <= cbMaxSegSize)
     2372        pThis->DevTabSeg[idxDevTabSeg].u64 = u64Value;
     2373    else
     2374        Log((IOMMU_LOG_PFX ": Setting device table segment %u with invalid size (%#RX32) -> Ignored\n", idxSegment, cbSegSize));
     2375
     2376    return VINF_SUCCESS;
     2377}
     2378
     2379
     2380/**
    23222381 * Writes the MSI Address (Lo) Register (32-bit).
    23232382 */
     
    25272586        case IOMMU_MMIO_OFF_PPR_EVT_B_BAR:       return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
    25282587
    2529         case IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST:
    2530         case IOMMU_MMIO_OFF_DEV_TAB_SEG_LAST:
    2531         {
    2532             uint8_t const idxDevTabSeg = (off - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3;
    2533             Assert(idxDevTabSeg < RT_ELEMENTS(pThis->DevTabSeg));
    2534             return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
    2535         }
     2588        case IOMMU_MMIO_OFF_DEV_TAB_SEG_1:
     2589        case IOMMU_MMIO_OFF_DEV_TAB_SEG_2:
     2590        case IOMMU_MMIO_OFF_DEV_TAB_SEG_3:
     2591        case IOMMU_MMIO_OFF_DEV_TAB_SEG_4:
     2592        case IOMMU_MMIO_OFF_DEV_TAB_SEG_5:
     2593        case IOMMU_MMIO_OFF_DEV_TAB_SEG_6:
     2594        case IOMMU_MMIO_OFF_DEV_TAB_SEG_7:       return iommuAmdDevTabSegBar_w(pDevIns, pThis, off, uValue);
    25362595
    25372596        case IOMMU_MMIO_OFF_DEV_SPECIFIC_FEAT:
     
    27892848    *puResult = uReg;
    27902849    return VINF_SUCCESS;
     2850}
     2851
     2852
     2853/**
     2854 * Reads a device table segment (0-7) from guest memory.
     2855 *
     2856 * @returns VBox status code.
     2857 * @param   pDevIns     The IOMMU device instance.
     2858 * @param   idxSeg      The device table segment index.
     2859 * @param   pvBuf       Where to store the device table segment.
     2860 * @param   cbBuf       The size of the buffer in bytes.
     2861 */
     2862static int iommuAmdReadDeviceTableSegment(PPDMDEVINS pDevIns, uint8_t idxSeg, void *pvBuf, uint32_t cbBuf)
     2863{
     2864    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     2865    Assert(pThis);
     2866
     2867    /* Validate. */
     2868    Assert(pvBuf);
     2869    Assert(cbBuf <= _2M);
     2870    Assert(!idxSeg || pThis->ExtFeat.n.u2DevTabSegSup);
     2871    Assert(!idxSeg || idxSeg < g_aDevTabSegments[pThis->ExtFeat.n.u2DevTabSegSup]);
     2872
     2873    /* Get the base address and size of the segment. */
     2874    RTGCPHYS GCPhysDevTab;
     2875    uint32_t cbDevTab;
     2876    if (!idxSeg)
     2877    {
     2878        GCPhysDevTab = pThis->DevTabBaseAddr.n.u40DevTabBase;
     2879        cbDevTab     = pThis->DevTabBaseAddr.n.u9Size;
     2880    }
     2881    else
     2882    {
     2883        GCPhysDevTab = pThis->DevTabSeg[idxSeg].n.u40DevTabBase;
     2884        cbDevTab     = pThis->DevTabSeg[idxSeg].n.u8Size;
     2885    }
     2886
     2887    /* Validate that the destination buffer is large enough to hold the segment. */
     2888    Assert(cbBuf >= cbDevTab);
     2889
     2890    /* Copy the device table to the buffer. */
     2891    int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysDevTab, pvBuf, cbDevTab);
     2892    if (RT_FAILURE(rc))
     2893    {
     2894        Log((IOMMU_LOG_PFX ": iommuAmdFetchDeviceTable: Failed to read device table segment. idxSeg=%u GCPhys=%#RGp rc=%Rrc",
     2895             idxSeg, GCPhysDevTab, rc));
     2896    }
     2897
     2898    return rc;
    27912899}
    27922900
     
    30903198        if (fVerbose)
    30913199        {
    3092             pHlp->pfnPrintf(pHlp, "    PPR support                             = %RTbool\n", ExtFeat.n.u1PprSup);
    3093             pHlp->pfnPrintf(pHlp, "    x2APIC support                          = %RTbool\n", ExtFeat.n.u1X2ApicSup);
    3094             pHlp->pfnPrintf(pHlp, "    NX and privilege level support          = %RTbool\n", ExtFeat.n.u1NoExecuteSup);
    3095             pHlp->pfnPrintf(pHlp, "    Guest translation support               = %RTbool\n", ExtFeat.n.u1GstTranslateSup);
    3096             pHlp->pfnPrintf(pHlp, "    Invalidate-All command support          = %RTbool\n", ExtFeat.n.u1InvAllSup);
    3097             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC support              = %RTbool\n", ExtFeat.n.u1GstVirtApicSup);
    3098             pHlp->pfnPrintf(pHlp, "    Hardware error register support         = %RTbool\n", ExtFeat.n.u1HwErrorSup);
    3099             pHlp->pfnPrintf(pHlp, "    Performance counters support            = %RTbool\n", ExtFeat.n.u1PerfCounterSup);
    3100             pHlp->pfnPrintf(pHlp, "    Host address translation size           = %#x\n",     ExtFeat.n.u2HostAddrTranslateSize);
    3101             pHlp->pfnPrintf(pHlp, "    Guest address translation size          = %#x\n",     ExtFeat.n.u2GstAddrTranslateSize);
    3102             pHlp->pfnPrintf(pHlp, "    Guest CR3 root table level support      = %#x\n",     ExtFeat.n.u2GstCr3RootTblLevel);
    3103             pHlp->pfnPrintf(pHlp, "    SMI filter register support             = %#x\n",     ExtFeat.n.u2SmiFilterSup);
    3104             pHlp->pfnPrintf(pHlp, "    SMI filter register count               = %#x\n",     ExtFeat.n.u3SmiFilterCount);
    3105             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC modes support        = %#x\n",     ExtFeat.n.u3GstVirtApicModeSup);
    3106             pHlp->pfnPrintf(pHlp, "    Dual PPR log support                    = %#x\n",     ExtFeat.n.u2DualPprLogSup);
    3107             pHlp->pfnPrintf(pHlp, "    Dual event log support                  = %#x\n",     ExtFeat.n.u2DualEvtLogSup);
    3108             pHlp->pfnPrintf(pHlp, "    Maximum PASID                           = %#x\n",     ExtFeat.n.u5MaxPasidSup);
    3109             pHlp->pfnPrintf(pHlp, "    User/supervisor page protection support = %RTbool\n", ExtFeat.n.u1UserSupervisorSup);
    3110             pHlp->pfnPrintf(pHlp, "    Device table segments supported         = %u\n",      (ExtFeat.n.u2DevTabSegSup << 1));
    3111             pHlp->pfnPrintf(pHlp, "    PPR log overflow early warning support  = %RTbool\n", ExtFeat.n.u1PprLogOverflowWarn);
    3112             pHlp->pfnPrintf(pHlp, "    PPR auto response support               = %RTbool\n", ExtFeat.n.u1PprAutoRespSup);
    3113             pHlp->pfnPrintf(pHlp, "    MARC support                            = %#x\n",     ExtFeat.n.u2MarcSup);
    3114             pHlp->pfnPrintf(pHlp, "    Block StopMark message support          = %RTbool\n", ExtFeat.n.u1BlockStopMarkSup);
    3115             pHlp->pfnPrintf(pHlp, "    Performance optimization support        = %RTbool\n", ExtFeat.n.u1PerfOptSup);
    3116             pHlp->pfnPrintf(pHlp, "    MSI capability MMIO access support      = %RTbool\n", ExtFeat.n.u1MsiCapMmioSup);
    3117             pHlp->pfnPrintf(pHlp, "    Guest I/O protection support            = %RTbool\n", ExtFeat.n.u1GstIoSup);
    3118             pHlp->pfnPrintf(pHlp, "    Host access support                     = %RTbool\n", ExtFeat.n.u1HostAccessSup);
    3119             pHlp->pfnPrintf(pHlp, "    Enhanced PPR handling support           = %RTbool\n", ExtFeat.n.u1EnhancedPprSup);
    3120             pHlp->pfnPrintf(pHlp, "    Attribute forward supported             = %RTbool\n", ExtFeat.n.u1AttrForwardSup);
    3121             pHlp->pfnPrintf(pHlp, "    Host dirty support                      = %RTbool\n", ExtFeat.n.u1HostDirtySup);
    3122             pHlp->pfnPrintf(pHlp, "    Invalidate IOTLB type support           = %RTbool\n", ExtFeat.n.u1InvIoTlbTypeSup);
    3123             pHlp->pfnPrintf(pHlp, "    Guest page table access bit hw disable  = %RTbool\n", ExtFeat.n.u1GstUpdateDisSup);
    3124             pHlp->pfnPrintf(pHlp, "    Force physical dest for remapped intr.  = %RTbool\n", ExtFeat.n.u1ForcePhysDstSup);
     3200            pHlp->pfnPrintf(pHlp, "    PPR support                             = %RTbool\n",  ExtFeat.n.u1PprSup);
     3201            pHlp->pfnPrintf(pHlp, "    x2APIC support                          = %RTbool\n",  ExtFeat.n.u1X2ApicSup);
     3202            pHlp->pfnPrintf(pHlp, "    NX and privilege level support          = %RTbool\n",  ExtFeat.n.u1NoExecuteSup);
     3203            pHlp->pfnPrintf(pHlp, "    Guest translation support               = %RTbool\n",  ExtFeat.n.u1GstTranslateSup);
     3204            pHlp->pfnPrintf(pHlp, "    Invalidate-All command support          = %RTbool\n",  ExtFeat.n.u1InvAllSup);
     3205            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC support              = %RTbool\n",  ExtFeat.n.u1GstVirtApicSup);
     3206            pHlp->pfnPrintf(pHlp, "    Hardware error register support         = %RTbool\n",  ExtFeat.n.u1HwErrorSup);
     3207            pHlp->pfnPrintf(pHlp, "    Performance counters support            = %RTbool\n",  ExtFeat.n.u1PerfCounterSup);
     3208            pHlp->pfnPrintf(pHlp, "    Host address translation size           = %#x\n",      ExtFeat.n.u2HostAddrTranslateSize);
     3209            pHlp->pfnPrintf(pHlp, "    Guest address translation size          = %#x\n",      ExtFeat.n.u2GstAddrTranslateSize);
     3210            pHlp->pfnPrintf(pHlp, "    Guest CR3 root table level support      = %#x\n",      ExtFeat.n.u2GstCr3RootTblLevel);
     3211            pHlp->pfnPrintf(pHlp, "    SMI filter register support             = %#x\n",      ExtFeat.n.u2SmiFilterSup);
     3212            pHlp->pfnPrintf(pHlp, "    SMI filter register count               = %#x\n",      ExtFeat.n.u3SmiFilterCount);
     3213            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC modes support        = %#x\n",      ExtFeat.n.u3GstVirtApicModeSup);
     3214            pHlp->pfnPrintf(pHlp, "    Dual PPR log support                    = %#x\n",      ExtFeat.n.u2DualPprLogSup);
     3215            pHlp->pfnPrintf(pHlp, "    Dual event log support                  = %#x\n",      ExtFeat.n.u2DualEvtLogSup);
     3216            pHlp->pfnPrintf(pHlp, "    Maximum PASID                           = %#x\n",      ExtFeat.n.u5MaxPasidSup);
     3217            pHlp->pfnPrintf(pHlp, "    User/supervisor page protection support = %RTbool\n",  ExtFeat.n.u1UserSupervisorSup);
     3218            pHlp->pfnPrintf(pHlp, "    Device table segments supported         = %#x (%u)\n", ExtFeat.n.u2DevTabSegSup,
     3219                            g_aDevTabSegments[ExtFeat.n.u2DevTabSegSup]);
     3220            pHlp->pfnPrintf(pHlp, "    PPR log overflow early warning support  = %RTbool\n",  ExtFeat.n.u1PprLogOverflowWarn);
     3221            pHlp->pfnPrintf(pHlp, "    PPR auto response support               = %RTbool\n",  ExtFeat.n.u1PprAutoRespSup);
     3222            pHlp->pfnPrintf(pHlp, "    MARC support                            = %#x\n",      ExtFeat.n.u2MarcSup);
     3223            pHlp->pfnPrintf(pHlp, "    Block StopMark message support          = %RTbool\n",  ExtFeat.n.u1BlockStopMarkSup);
     3224            pHlp->pfnPrintf(pHlp, "    Performance optimization support        = %RTbool\n",  ExtFeat.n.u1PerfOptSup);
     3225            pHlp->pfnPrintf(pHlp, "    MSI capability MMIO access support      = %RTbool\n",  ExtFeat.n.u1MsiCapMmioSup);
     3226            pHlp->pfnPrintf(pHlp, "    Guest I/O protection support            = %RTbool\n",  ExtFeat.n.u1GstIoSup);
     3227            pHlp->pfnPrintf(pHlp, "    Host access support                     = %RTbool\n",  ExtFeat.n.u1HostAccessSup);
     3228            pHlp->pfnPrintf(pHlp, "    Enhanced PPR handling support           = %RTbool\n",  ExtFeat.n.u1EnhancedPprSup);
     3229            pHlp->pfnPrintf(pHlp, "    Attribute forward supported             = %RTbool\n",  ExtFeat.n.u1AttrForwardSup);
     3230            pHlp->pfnPrintf(pHlp, "    Host dirty support                      = %RTbool\n",  ExtFeat.n.u1HostDirtySup);
     3231            pHlp->pfnPrintf(pHlp, "    Invalidate IOTLB type support           = %RTbool\n",  ExtFeat.n.u1InvIoTlbTypeSup);
     3232            pHlp->pfnPrintf(pHlp, "    Guest page table access bit hw disable  = %RTbool\n",  ExtFeat.n.u1GstUpdateDisSup);
     3233            pHlp->pfnPrintf(pHlp, "    Force physical dest for remapped intr.  = %RTbool\n",  ExtFeat.n.u1ForcePhysDstSup);
    31253234        }
    31263235    }
     
    35853694    pThis->ExtFeat.n.u5MaxPasidSup           = 0;   /* Requires GstTranslateSup. */
    35863695    pThis->ExtFeat.n.u1UserSupervisorSup     = 0;
    3587     pThis->ExtFeat.n.u2DevTabSegSup          = 0;
     3696    AssertCompile(IOMMU_MAX_DEV_TAB_SEGMENTS < RT_ELEMENTS(g_aDevTabSegments));
     3697    pThis->ExtFeat.n.u2DevTabSegSup          = IOMMU_MAX_DEV_TAB_SEGMENTS;
    35883698    pThis->ExtFeat.n.u1PprLogOverflowWarn    = 0;
    35893699    pThis->ExtFeat.n.u1PprAutoRespSup        = 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