VirtualBox

Ignore:
Timestamp:
Apr 30, 2020 3:31:01 PM (5 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Grr.. doxygen.

File:
1 edited

Legend:

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

    r84101 r84111  
    327327 */
    328328/** MsiCapId: Capability ID. */
    329 #define IOMMU_BF_MSI_CAPHDR_CAP_ID_SHIFT            0
    330 #define IOMMU_BF_MSI_CAPHDR_CAP_ID_MASK             UINT32_C(0x000000ff)
     329#define IOMMU_BF_MSI_CAP_HDR_CAP_ID_SHIFT           0
     330#define IOMMU_BF_MSI_CAP_HDR_CAP_ID_MASK            UINT32_C(0x000000ff)
    331331/** MsiCapPtr: Pointer (PCI config offset) to the next capability. */
    332 #define IOMMU_BF_MSI_CAPHDR_CAP_PTR_SHIFT           8
    333 #define IOMMU_BF_MSI_CAPHDR_CAP_PTR_MASK            UINT32_C(0x0000ff00)
     332#define IOMMU_BF_MSI_CAP_HDR_CAP_PTR_SHIFT          8
     333#define IOMMU_BF_MSI_CAP_HDR_CAP_PTR_MASK           UINT32_C(0x0000ff00)
    334334/** MsiEn: Message Signal Interrupt enable. */
    335 #define IOMMU_BF_MSI_CAPHDR_EN_SHIFT                16
    336 #define IOMMU_BF_MSI_CAPHDR_EN_MASK                 UINT32_C(0x00010000)
     335#define IOMMU_BF_MSI_CAP_HDR_EN_SHIFT               16
     336#define IOMMU_BF_MSI_CAP_HDR_EN_MASK                UINT32_C(0x00010000)
    337337/** MsiMultMessCap: MSI Multi-Message Capability. */
    338 #define IOMMU_BF_MSI_CAPHDR_MULTMESS_CAP_SHIFT      17
    339 #define IOMMU_BF_MSI_CAPHDR_MULTMESS_CAP_MASK       UINT32_C(0x000e0000)
     338#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_CAP_SHIFT     17
     339#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_CAP_MASK      UINT32_C(0x000e0000)
    340340/** MsiMultMessEn: MSI Mult-Message Enable. */
    341 #define IOMMU_BF_MSI_CAPHDR_MULTMESS_EN_SHIFT       20
    342 #define IOMMU_BF_MSI_CAPHDR_MULTMESS_EN_MASK        UINT32_C(0x00700000)
     341#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_EN_SHIFT      20
     342#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_EN_MASK       UINT32_C(0x00700000)
    343343/** Msi64BitEn: MSI 64-bit Enabled. */
    344 #define IOMMU_BF_MSI_CAPHDR_64BIT_EN_SHIFT          23
    345 #define IOMMU_BF_MSI_CAPHDR_64BIT_EN_MASK           UINT32_C(0x00800000)
     344#define IOMMU_BF_MSI_CAP_HDR_64BIT_EN_SHIFT         23
     345#define IOMMU_BF_MSI_CAP_HDR_64BIT_EN_MASK          UINT32_C(0x00800000)
    346346/** Bits 31:24 reserved. */
    347 #define IOMMU_BF_MSI_CAPHDR_RSVD_24_31_SHIFT        24
    348 #define IOMMU_BF_MSI_CAPHDR_RSVD_24_31_MASK         UINT32_C(0xff000000)
    349 RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_MSI_CAPHDR_, UINT32_C(0), UINT32_MAX,
     347#define IOMMU_BF_MSI_CAP_HDR_RSVD_24_31_SHIFT       24
     348#define IOMMU_BF_MSI_CAP_HDR_RSVD_24_31_MASK        UINT32_C(0xff000000)
     349RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_MSI_CAP_HDR_, UINT32_C(0), UINT32_MAX,
    350350                            (CAP_ID, CAP_PTR, EN, MULTMESS_CAP, MULTMESS_EN, 64BIT_EN, RSVD_24_31));
    351351/** @} */
     
    455455/** Number of device table segments supported (power of 2). */
    456456#define IOMMU_MAX_DEV_TAB_SEGMENTS                  3
     457/** Maximum number of host address translation levels supported. */
     458#define IOMMU_MAX_HOST_PT_LEVEL                     6
    457459/** @} */
    458460
     
    15791581} MSI_CAP_HDR_T;
    15801582AssertCompileSize(MSI_CAP_HDR_T, 4);
     1583#define IOMMU_MSI_CAP_HDR_RW_MASK       RT_BIT(16)
    15811584
    15821585/**
     
    26362639
    26372640
     2641#if 0
     2642static VBOXSTRICTRC iommuAmdMsiCapHdr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     2643{
     2644    RT_NOREF(pThis, iReg);
     2645
     2646    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     2647    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     2648
     2649    MSI_CAP_HDR_T MsiCapHdr;
     2650    MsiCapHdr.u32 = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_CAP_HDR);
     2651
     2652/** @todo   */
     2653    return VINF_SUCCESS;
     2654}
     2655#endif
     2656
    26382657/**
    26392658 * Writes the MSI Address (Lo) Register (32-bit).
     
    32173236 * Constructs a DEV_TAB_HARDWARE_ERROR event.
    32183237 *
    3219  * @param   uDevId          The device ID.
    3220  * @param   GCPhysDevTab    The system physical address of the failed device table
    3221  *                          access.
    3222  * @param   fOperation      The operation being performed.
    3223  * @param   pEvent          Where to store the constructed event.
     3238 * @param   uDevId              The device ID.
     3239 * @param   GCPhysDevTabEntry   The system physical address of the failed device
     3240 *                              table access.
     3241 * @param   enmOp               The operation being performed.
     3242 * @param   pEvent              Where to store the constructed event.
    32243243 *
    32253244 * @thread  Any.
     
    41434162    memset(&pThis->aDevTabBaseAddrs[0], 0, sizeof(pThis->aDevTabBaseAddrs));
    41444163
    4145     pThis->CmdBufBaseAddr.u64     = 0;
    4146     pThis->CmdBufBaseAddr.n.u4Len = 8;
    4147 
    4148     pThis->EvtLogBaseAddr.u64     = 0;
    4149     pThis->EvtLogBaseAddr.n.u4Len = 8;
    4150 
    4151     pThis->Ctrl.u64               = 0;
    4152 
    4153     pThis->ExclRangeBaseAddr.u64  = 0;
    4154     pThis->ExclRangeLimit.u64     = 0;
    4155 
     4164    pThis->CmdBufBaseAddr.u64        = 0;
     4165    pThis->CmdBufBaseAddr.n.u4Len    = 8;
     4166
     4167    pThis->EvtLogBaseAddr.u64        = 0;
     4168    pThis->EvtLogBaseAddr.n.u4Len    = 8;
     4169
     4170    pThis->Ctrl.u64                  = 0;
     4171
     4172    pThis->ExclRangeBaseAddr.u64     = 0;
     4173    pThis->ExclRangeLimit.u64        = 0;
     4174
     4175    pThis->PprLogBaseAddr.u64        = 0;
     4176    pThis->PprLogBaseAddr.n.u4Len    = 8;
     4177
     4178    pThis->HwEvtHi.u64               = 0;
     4179    pThis->HwEvtLo                   = 0;
     4180    pThis->HwEvtStatus.u64           = 0;
     4181
     4182    pThis->GALogBaseAddr.u64         = 0;
     4183    pThis->GALogBaseAddr.n.u4Len     = 8;
     4184    pThis->GALogTailAddr.u64         = 0;
     4185
     4186    pThis->PprLogBBaseAddr.u64       = 0;
     4187    pThis->PprLogBBaseAddr.n.u4Len   = 8;
     4188
     4189    pThis->EvtLogBBaseAddr.u64       = 0;
     4190    pThis->EvtLogBBaseAddr.n.u4Len   = 8;
     4191
     4192    pThis->DevSpecificFeat.u64       = 0;
     4193    pThis->DevSpecificCtrl.u64       = 0;
     4194    pThis->DevSpecificStatus.u64     = 0;
     4195
     4196    pThis->MsiMiscInfo.u64           = 0;
     4197    pThis->PerfOptCtrl.u32           = 0;
     4198
     4199    pThis->XtGenIntrCtrl.u64         = 0;
     4200    pThis->XtPprIntrCtrl.u64         = 0;
     4201    pThis->XtGALogIntrCtrl.u64       = 0;
     4202
     4203    memset(&pThis->aMarcApers[0], 0, sizeof(pThis->aMarcApers));
     4204
     4205    pThis->CmdBufHeadPtr.u64         = 0;
     4206    pThis->CmdBufTailPtr.u64         = 0;
     4207    pThis->EvtLogHeadPtr.u64         = 0;
     4208    pThis->EvtLogTailPtr.u64         = 0;
     4209
     4210    pThis->Status.u64                = 0;
     4211
     4212    pThis->PprLogHeadPtr.u64         = 0;
     4213    pThis->PprLogTailPtr.u64         = 0;
     4214
     4215    pThis->GALogHeadPtr.u64          = 0;
     4216    pThis->GALogTailPtr.u64          = 0;
     4217
     4218    pThis->PprLogBHeadPtr.u64        = 0;
     4219    pThis->PprLogBTailPtr.u64        = 0;
     4220
     4221    pThis->EvtLogBHeadPtr.u64        = 0;
     4222    pThis->EvtLogBTailPtr.u64        = 0;
     4223
     4224    pThis->PprLogAutoResp.u64        = 0;
     4225    pThis->PprLogOverflowEarly.u64   = 0;
     4226    pThis->PprLogBOverflowEarly.u64  = 0;
     4227
     4228    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_LO, 0);
     4229    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_HI, 0);
     4230}
     4231
     4232
     4233/**
     4234 * @interface_method_impl{PDMDEVREG,pfnDestruct}
     4235 */
     4236static DECLCALLBACK(int) iommuAmdR3Destruct(PPDMDEVINS pDevIns)
     4237{
     4238    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
     4239    PIOMMU   pThis   = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     4240    LogFlowFunc(("\n"));
     4241
     4242    /* Close the command thread semaphore. */
     4243    if (pThis->hEvtCmdThread != NIL_SUPSEMEVENT)
     4244    {
     4245        PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtCmdThread);
     4246        pThis->hEvtCmdThread = NIL_SUPSEMEVENT;
     4247    }
     4248    return VINF_SUCCESS;
     4249}
     4250
     4251
     4252/**
     4253 * @interface_method_impl{PDMDEVREG,pfnConstruct}
     4254 */
     4255static DECLCALLBACK(int) iommuAmdR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
     4256{
     4257    NOREF(iInstance);
     4258
     4259    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
     4260    PIOMMU          pThis   = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     4261    PIOMMUCC        pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PIOMMUCC);
     4262    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
     4263    int             rc;
     4264    LogFlowFunc(("\n"));
     4265
     4266    pThisCC->pDevInsR3 = pDevIns;
     4267
     4268    /*
     4269     * Validate and read the configuration.
     4270     */
     4271    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "Device|Function", "");
     4272
     4273    uint8_t uPciDevice;
     4274    rc = pHlp->pfnCFGMQueryU8Def(pCfg, "Device", &uPciDevice, 0);
     4275    if (RT_FAILURE(rc))
     4276        return PDMDEV_SET_ERROR(pDevIns, rc, N_("IOMMU: Failed to query \"Device\""));
     4277
     4278    uint8_t uPciFunction;
     4279    rc = pHlp->pfnCFGMQueryU8Def(pCfg, "Function", &uPciFunction, 2);
     4280    if (RT_FAILURE(rc))
     4281        return PDMDEV_SET_ERROR(pDevIns, rc, N_("IOMMU: Failed to query \"Function\""));
     4282
     4283    /*
     4284     * Register the IOMMU with PDM.
     4285     */
     4286    PDMIOMMUREGR3 IommuReg;
     4287    RT_ZERO(IommuReg);
     4288    IommuReg.u32Version  = PDM_IOMMUREGCC_VERSION;
     4289    IommuReg.pfnMemRead  = iommuAmdDeviceMemRead;
     4290    IommuReg.pfnMemWrite = iommuAmdDeviceMemWrite;
     4291    IommuReg.u32TheEnd   = PDM_IOMMUREGCC_VERSION;
     4292    rc = PDMDevHlpIommuRegister(pDevIns, &IommuReg, &pThisCC->CTX_SUFF(pIommuHlp), &pThis->idxIommu);
     4293    if (RT_FAILURE(rc))
     4294        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to register ourselves as an IOMMU device"));
     4295    if (pThisCC->CTX_SUFF(pIommuHlp)->u32Version != PDM_IOMMUHLPR3_VERSION)
     4296        return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
     4297                                   N_("IOMMU helper version mismatch; got %#x expected %#x"),
     4298                                   pThisCC->CTX_SUFF(pIommuHlp)->u32Version, PDM_IOMMUHLPR3_VERSION);
     4299    if (pThisCC->CTX_SUFF(pIommuHlp)->u32TheEnd != PDM_IOMMUHLPR3_VERSION)
     4300        return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
     4301                                   N_("IOMMU helper end-version mismatch; got %#x expected %#x"),
     4302                                   pThisCC->CTX_SUFF(pIommuHlp)->u32TheEnd, PDM_IOMMUHLPR3_VERSION);
     4303
     4304    /*
     4305     * Initialize read-only PCI configuration space.
     4306     */
     4307    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     4308    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     4309
     4310    /* Header. */
     4311    PDMPciDevSetVendorId(pPciDev,           IOMMU_PCI_VENDOR_ID);      /* AMD */
     4312    PDMPciDevSetDeviceId(pPciDev,           IOMMU_PCI_DEVICE_ID);      /* VirtualBox IOMMU device */
     4313    PDMPciDevSetCommand(pPciDev,            0);                        /* Command */
     4314    PDMPciDevSetStatus(pPciDev,             VBOX_PCI_STATUS_CAP_LIST); /* Status - CapList supported */
     4315    PDMPciDevSetRevisionId(pPciDev,         IOMMU_PCI_REVISION_ID);    /* VirtualBox specific device implementation revision */
     4316    PDMPciDevSetClassBase(pPciDev,          0x08);                     /* System Base Peripheral */
     4317    PDMPciDevSetClassSub(pPciDev,           0x06);                     /* IOMMU */
     4318    PDMPciDevSetClassProg(pPciDev,          0x00);                     /* IOMMU Programming interface */
     4319    PDMPciDevSetHeaderType(pPciDev,         0x00);                     /* Single function, type 0. */
     4320    PDMPciDevSetSubSystemId(pPciDev,        IOMMU_PCI_DEVICE_ID);      /* AMD */
     4321    PDMPciDevSetSubSystemVendorId(pPciDev,  IOMMU_PCI_VENDOR_ID);      /* VirtualBox IOMMU device */
     4322    PDMPciDevSetCapabilityList(pPciDev,     IOMMU_PCI_OFF_CAP_HDR);    /* Offset into capability registers. */
     4323    PDMPciDevSetInterruptPin(pPciDev,       0x01);                     /* INTA#. */
     4324    PDMPciDevSetInterruptLine(pPciDev,      0x00);                     /* For software compatibility; no effect on hardware. */
     4325
     4326    /* Capability Header. */
     4327    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_CAP_HDR,
     4328                        RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_ID,    0xf)     /* RO - Secure Device capability block */
     4329                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_PTR,   IOMMU_PCI_OFF_MSI_CAP_HDR)  /* RO - Offset to next capability */
     4330                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_TYPE,  0x3)     /* RO - IOMMU capability block */
     4331                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_REV,   0x1)     /* RO - IOMMU interface revision */
     4332                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_IOTLB_SUP, 0x0)     /* RO - Remote IOTLB support */
     4333                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_HT_TUNNEL, 0x0)     /* RO - HyperTransport Tunnel support */
     4334                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_NP_CACHE,  0x0)     /* RO - Cache NP page table entries */
     4335                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_EFR_SUP,   0x1)     /* RO - Extended Feature Register support */
     4336                      | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_EXT,   0x1));   /* RO - Misc. Information Register support */
     4337
     4338    /* Base Address Low Register. */
     4339    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_LO, 0x0);   /* RW - Base address (Lo) and enable bit. */
     4340
     4341    /* Base Address High Register. */
     4342    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_HI, 0x0);   /* RW - Base address (Hi) */
     4343
     4344    /* IOMMU Range Register. */
     4345    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_RANGE_REG, 0x0);          /* RW - Range register (implemented as RO by us). */
     4346
     4347    /* Misc. Information Register 0. */
     4348    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MISCINFO_REG_0,
     4349                        RT_BF_MAKE(IOMMU_BF_MISCINFO_0_MSI_NUM,     0x0)    /* RO - MSI number */
     4350                      | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_GVA_SIZE,    0x2)    /* RO - Guest Virt. Addr size (2=48 bits) */
     4351                      | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_PA_SIZE,     0x30)   /* RO - Physical Addr size (48 bits) */
     4352                      | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_VA_SIZE,     0x40)   /* RO - Virt. Addr size (64 bits) */
     4353                      | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_HT_ATS_RESV, 0x0)    /* RW - HT ATS reserved */
     4354                      | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_MSI_NUM_PPR, 0x0));  /* RW - PPR interrupt number */
     4355
     4356    /* Misc. Information Register 1. */
     4357    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MISCINFO_REG_0, 0);
     4358
     4359    /* MSI Capability Header register. */
     4360    PDMMSIREG MsiReg;
     4361    RT_ZERO(MsiReg);
     4362    MsiReg.cMsiVectors    = 1;
     4363    MsiReg.iMsiCapOffset  = IOMMU_PCI_OFF_MSI_CAP_HDR;
     4364    MsiReg.iMsiNextOffset = 0; /* IOMMU_PCI_OFF_MSI_MAP_CAP_HDR */
     4365    MsiReg.fMsi64bit      = 1; /* 64-bit addressing support is mandatory; See AMD spec. 2.8 "IOMMU Interrupt Support". */
     4366    rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
     4367    AssertRCReturn(rc, rc);
     4368
     4369    /* MSI Address (Lo, Hi) and MSI data are read-write PCI config registers handled by our generic PCI config space code. */
     4370#if 0
     4371    /* MSI Address Lo. */
     4372    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_LO, 0);         /* RW - MSI message address (Lo). */
     4373    /* MSI Address Hi. */
     4374    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_HI, 0);         /* RW - MSI message address (Hi). */
     4375    /* MSI Data. */
     4376    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_DATA, 0);            /* RW - MSI data. */
     4377#endif
     4378
     4379#if 0
     4380    /** @todo IOMMU: I don't know if we need to support this, enable later if
     4381     *        required. */
     4382    /* MSI Mapping Capability Header register. */
     4383    PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_MAP_CAP_HDR,
     4384                        RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_CAP_ID,   0x8)       /* RO - Capability ID */
     4385                      | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_CAP_PTR,  0x0)       /* RO - Offset to next capability (NULL) */
     4386                      | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_EN,       0x1)       /* RO - MSI mapping capability enable */
     4387                      | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_FIXED,    0x1)       /* RO - MSI mapping range is fixed */
     4388                      | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_CAP_TYPE, 0x15));    /* RO - MSI mapping capability */
     4389    /* When implementing don't forget to copy this to its MMIO shadow register (MsiMapCapHdr) in iommuAmdR3Init. */
     4390#endif
     4391
     4392    /*
     4393     * Register the PCI function with PDM.
     4394     */
     4395    rc = PDMDevHlpPCIRegisterEx(pDevIns, pPciDev, 0 /* fFlags */, uPciDevice, uPciFunction, "amd-iommu");
     4396    AssertLogRelRCReturn(rc, rc);
     4397
     4398    /*
     4399     * Intercept PCI config. space accesses.
     4400     */
     4401    rc = PDMDevHlpPCIInterceptConfigAccesses(pDevIns, pPciDev, iommuAmdR3PciConfigRead, iommuAmdR3PciConfigWrite);
     4402    AssertLogRelRCReturn(rc, rc);
     4403
     4404    /*
     4405     * Create the MMIO region.
     4406     * Mapping of the region is done when software configures it via PCI config space.
     4407     */
     4408    rc = PDMDevHlpMmioCreate(pDevIns, IOMMU_MMIO_REGION_SIZE, pPciDev, 0 /* iPciRegion */, iommuAmdMmioWrite, iommuAmdMmioRead,
     4409                             NULL /* pvUser */, IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED,
     4410                             "AMD-IOMMU", &pThis->hMmio);
     4411    AssertLogRelRCReturn(rc, rc);
     4412
     4413    /*
     4414     * Register saved state.
     4415     */
     4416    rc = PDMDevHlpSSMRegisterEx(pDevIns, IOMMU_SAVED_STATE_VERSION, sizeof(IOMMU), NULL,
     4417                                NULL, NULL, NULL,
     4418                                NULL, iommuAmdR3SaveExec, NULL,
     4419                                NULL, iommuAmdR3LoadExec, NULL);
     4420    AssertLogRelRCReturn(rc, rc);
     4421
     4422    /*
     4423     * Register debugger info item.
     4424     */
     4425    rc = PDMDevHlpDBGFInfoRegister(pDevIns, "iommu", "Display IOMMU state.", iommuAmdR3DbgInfo);
     4426    AssertLogRelRCReturn(rc, rc);
     4427
     4428    /*
     4429     * Create the command thread and its event semaphore.
     4430     */
     4431    rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->pCmdThread, pThis, iommuAmdR3CmdThread, iommuAmdR3CmdThreadWakeUp,
     4432                               0 /* cbStack */, RTTHREADTYPE_IO, "AMD-IOMMU");
     4433    AssertLogRelRCReturn(rc, rc);
     4434
     4435    rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtCmdThread);
     4436    AssertLogRelRCReturn(rc, rc);
     4437
     4438    /*
     4439     * Initialize read-only registers.
     4440     */
     4441    /** @todo Don't remove the =0 assignment for now. It's just there so it's easier
     4442     *        for me to see existing features that we might want to implement. Do it
     4443     *        later. */
     4444    pThis->ExtFeat.u64 = 0;
    41564445    pThis->ExtFeat.n.u1PrefetchSup           = 0;
    41574446    pThis->ExtFeat.n.u1PprSup                = 0;
     
    41634452    pThis->ExtFeat.n.u1HwErrorSup            = 1;
    41644453    pThis->ExtFeat.n.u1PerfCounterSup        = 0;
    4165     pThis->ExtFeat.n.u2HostAddrTranslateSize = 0;   /* Requires GstTranslateSup. */
     4454    pThis->ExtFeat.n.u2HostAddrTranslateSize = IOMMU_MAX_HOST_PT_LEVEL;
    41664455    pThis->ExtFeat.n.u2GstAddrTranslateSize  = 0;   /* Requires GstTranslateSup. */
    41674456    pThis->ExtFeat.n.u2GstCr3RootTblLevel    = 0;   /* Requires GstTranslateSup. */
     
    41904479    pThis->ExtFeat.n.u1ForcePhysDstSup       = 0;
    41914480
    4192     pThis->PprLogBaseAddr.u64        = 0;
    4193     pThis->PprLogBaseAddr.n.u4Len    = 8;
    4194 
    4195     pThis->HwEvtHi.u64               = 0;
    4196     pThis->HwEvtLo                   = 0;
    4197     pThis->HwEvtStatus.u64           = 0;
    4198 
    4199     pThis->GALogBaseAddr.u64         = 0;
    4200     pThis->GALogBaseAddr.n.u4Len     = 8;
    4201     pThis->GALogTailAddr.u64         = 0;
    4202 
    4203     pThis->PprLogBBaseAddr.u64       = 0;
    4204     pThis->PprLogBBaseAddr.n.u4Len   = 8;
    4205 
    4206     pThis->EvtLogBBaseAddr.u64       = 0;
    4207     pThis->EvtLogBBaseAddr.n.u4Len   = 8;
    4208 
    4209     pThis->DevSpecificFeat.u64       = 0;
    4210     pThis->DevSpecificCtrl.u64       = 0;
    4211     pThis->DevSpecificStatus.u64     = 0;
    4212 
    4213     pThis->MsiMiscInfo.u64           = 0;
    4214     pThis->PerfOptCtrl.u32           = 0;
    4215 
    4216     pThis->XtGenIntrCtrl.u64         = 0;
    4217     pThis->XtPprIntrCtrl.u64         = 0;
    4218     pThis->XtGALogIntrCtrl.u64       = 0;
    4219 
    4220     memset(&pThis->aMarcApers[0], 0, sizeof(pThis->aMarcApers));
    4221 
    4222     pThis->RsvdReg                   = 0;
    4223 
    4224     pThis->CmdBufHeadPtr.u64         = 0;
    4225     pThis->CmdBufTailPtr.u64         = 0;
    4226     pThis->EvtLogHeadPtr.u64         = 0;
    4227     pThis->EvtLogTailPtr.u64         = 0;
    4228 
    4229     pThis->Status.u64                = 0;
    4230 
    4231     pThis->PprLogHeadPtr.u64         = 0;
    4232     pThis->PprLogTailPtr.u64         = 0;
    4233 
    4234     pThis->GALogHeadPtr.u64          = 0;
    4235     pThis->GALogTailPtr.u64          = 0;
    4236 
    4237     pThis->PprLogBHeadPtr.u64        = 0;
    4238     pThis->PprLogBTailPtr.u64        = 0;
    4239 
    4240     pThis->EvtLogBHeadPtr.u64        = 0;
    4241     pThis->EvtLogBTailPtr.u64        = 0;
    4242 
    4243     pThis->PprLogAutoResp.u64        = 0;
    4244     pThis->PprLogOverflowEarly.u64   = 0;
    4245     pThis->PprLogBOverflowEarly.u64  = 0;
    4246 
    4247     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_LO, 0);
    4248     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_HI, 0);
    4249 }
    4250 
    4251 
    4252 /**
    4253  * @interface_method_impl{PDMDEVREG,pfnDestruct}
    4254  */
    4255 static DECLCALLBACK(int) iommuAmdR3Destruct(PPDMDEVINS pDevIns)
    4256 {
    4257     PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
    4258     PIOMMU   pThis   = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
    4259     LogFlowFunc(("\n"));
    4260 
    4261     /* Close the command thread semaphore. */
    4262     if (pThis->hEvtCmdThread != NIL_SUPSEMEVENT)
    4263     {
    4264         PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtCmdThread);
    4265         pThis->hEvtCmdThread = NIL_SUPSEMEVENT;
    4266     }
    4267     return VINF_SUCCESS;
    4268 }
    4269 
    4270 
    4271 /**
    4272  * @interface_method_impl{PDMDEVREG,pfnConstruct}
    4273  */
    4274 static DECLCALLBACK(int) iommuAmdR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
    4275 {
    4276     NOREF(iInstance);
    4277 
    4278     PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    4279     PIOMMU          pThis   = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
    4280     PIOMMUCC        pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PIOMMUCC);
    4281     PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
    4282     int             rc;
    4283     LogFlowFunc(("\n"));
    4284 
    4285     pThisCC->pDevInsR3 = pDevIns;
    4286 
    4287     /*
    4288      * Validate and read the configuration.
    4289      */
    4290     PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "Device|Function", "");
    4291 
    4292     uint8_t uPciDevice;
    4293     rc = pHlp->pfnCFGMQueryU8Def(pCfg, "Device", &uPciDevice, 0);
    4294     if (RT_FAILURE(rc))
    4295         return PDMDEV_SET_ERROR(pDevIns, rc, N_("IOMMU: Failed to query \"Device\""));
    4296 
    4297     uint8_t uPciFunction;
    4298     rc = pHlp->pfnCFGMQueryU8Def(pCfg, "Function", &uPciFunction, 2);
    4299     if (RT_FAILURE(rc))
    4300         return PDMDEV_SET_ERROR(pDevIns, rc, N_("IOMMU: Failed to query \"Function\""));
    4301 
    4302     /*
    4303      * Register the IOMMU with PDM.
    4304      */
    4305     PDMIOMMUREGR3 IommuReg;
    4306     RT_ZERO(IommuReg);
    4307     IommuReg.u32Version  = PDM_IOMMUREGCC_VERSION;
    4308     IommuReg.pfnMemRead  = iommuAmdDeviceMemRead;
    4309     IommuReg.pfnMemWrite = iommuAmdDeviceMemWrite;
    4310     IommuReg.u32TheEnd   = PDM_IOMMUREGCC_VERSION;
    4311     rc = PDMDevHlpIommuRegister(pDevIns, &IommuReg, &pThisCC->CTX_SUFF(pIommuHlp), &pThis->idxIommu);
    4312     if (RT_FAILURE(rc))
    4313         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to register ourselves as an IOMMU device"));
    4314     if (pThisCC->CTX_SUFF(pIommuHlp)->u32Version != PDM_IOMMUHLPR3_VERSION)
    4315         return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
    4316                                    N_("IOMMU helper version mismatch; got %#x expected %#x"),
    4317                                    pThisCC->CTX_SUFF(pIommuHlp)->u32Version, PDM_IOMMUHLPR3_VERSION);
    4318     if (pThisCC->CTX_SUFF(pIommuHlp)->u32TheEnd != PDM_IOMMUHLPR3_VERSION)
    4319         return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS,
    4320                                    N_("IOMMU helper end-version mismatch; got %#x expected %#x"),
    4321                                    pThisCC->CTX_SUFF(pIommuHlp)->u32TheEnd, PDM_IOMMUHLPR3_VERSION);
    4322 
    4323     /*
    4324      * Initialize read-only PCI configuration space.
    4325      */
    4326     PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
    4327     PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
    4328 
    4329     /* Header. */
    4330     PDMPciDevSetVendorId(pPciDev,           IOMMU_PCI_VENDOR_ID);      /* AMD */
    4331     PDMPciDevSetDeviceId(pPciDev,           IOMMU_PCI_DEVICE_ID);      /* VirtualBox IOMMU device */
    4332     PDMPciDevSetCommand(pPciDev,            0);                        /* Command */
    4333     PDMPciDevSetStatus(pPciDev,             VBOX_PCI_STATUS_CAP_LIST); /* Status - CapList supported */
    4334     PDMPciDevSetRevisionId(pPciDev,         IOMMU_PCI_REVISION_ID);    /* VirtualBox specific device implementation revision */
    4335     PDMPciDevSetClassBase(pPciDev,          0x08);                     /* System Base Peripheral */
    4336     PDMPciDevSetClassSub(pPciDev,           0x06);                     /* IOMMU */
    4337     PDMPciDevSetClassProg(pPciDev,          0x00);                     /* IOMMU Programming interface */
    4338     PDMPciDevSetHeaderType(pPciDev,         0x00);                     /* Single function, type 0. */
    4339     PDMPciDevSetSubSystemId(pPciDev,        IOMMU_PCI_DEVICE_ID);      /* AMD */
    4340     PDMPciDevSetSubSystemVendorId(pPciDev,  IOMMU_PCI_VENDOR_ID);      /* VirtualBox IOMMU device */
    4341     PDMPciDevSetCapabilityList(pPciDev,     IOMMU_PCI_OFF_CAP_HDR);    /* Offset into capability registers. */
    4342     PDMPciDevSetInterruptPin(pPciDev,       0x01);                     /* INTA#. */
    4343     PDMPciDevSetInterruptLine(pPciDev,      0x00);                     /* For software compatibility; no effect on hardware. */
    4344 
    4345     /* Capability Header. */
    4346     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_CAP_HDR,
    4347                         RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_ID,    0xf)     /* RO - Secure Device capability block */
    4348                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_PTR,   IOMMU_PCI_OFF_MSI_CAP_HDR)  /* RO - Offset to next capability */
    4349                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_TYPE,  0x3)     /* RO - IOMMU capability block */
    4350                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_REV,   0x1)     /* RO - IOMMU interface revision */
    4351                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_IOTLB_SUP, 0x0)     /* RO - Remote IOTLB support */
    4352                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_HT_TUNNEL, 0x0)     /* RO - HyperTransport Tunnel support */
    4353                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_NP_CACHE,  0x0)     /* RO - Cache NP page table entries */
    4354                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_EFR_SUP,   0x1)     /* RO - Extended Feature Register support */
    4355                       | RT_BF_MAKE(IOMMU_BF_CAPHDR_CAP_EXT,   0x1));   /* RO - Misc. Information Register support */
    4356 
    4357     /* Base Address Low Register. */
    4358     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_LO, 0x0);   /* RW - Base address (Lo) and enable bit. */
    4359 
    4360     /* Base Address High Register. */
    4361     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_BASE_ADDR_REG_HI, 0x0);   /* RW - Base address (Hi) */
    4362 
    4363     /* IOMMU Range Register. */
    4364     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_RANGE_REG, 0x0);          /* RW - Range register (implemented as RO by us). */
    4365 
    4366     /* Misc. Information Register 0. */
    4367     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MISCINFO_REG_0,
    4368                         RT_BF_MAKE(IOMMU_BF_MISCINFO_0_MSI_NUM,     0x0)    /* RO - MSI number */
    4369                       | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_GVA_SIZE,    0x2)    /* RO - Guest Virt. Addr size (2=48 bits) */
    4370                       | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_PA_SIZE,     0x30)   /* RO - Physical Addr size (48 bits) */
    4371                       | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_VA_SIZE,     0x40)   /* RO - Virt. Addr size (64 bits) */
    4372                       | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_HT_ATS_RESV, 0x0)    /* RW - HT ATS reserved */
    4373                       | RT_BF_MAKE(IOMMU_BF_MISCINFO_0_MSI_NUM_PPR, 0x0));  /* RW - PPR interrupt number */
    4374 
    4375     /* Misc. Information Register 1. */
    4376     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MISCINFO_REG_0, 0);
    4377 
    4378     /* MSI Capability Header register. */
    4379     PDMMSIREG MsiReg;
    4380     RT_ZERO(MsiReg);
    4381     MsiReg.cMsiVectors    = 1;
    4382     MsiReg.iMsiCapOffset  = IOMMU_PCI_OFF_MSI_CAP_HDR;
    4383     MsiReg.iMsiNextOffset = 0; /* IOMMU_PCI_OFF_MSI_MAP_CAP_HDR */
    4384     MsiReg.fMsi64bit      = 1; /* 64-bit addressing support is mandatory; See AMD spec. 2.8 "IOMMU Interrupt Support". */
    4385     rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
    4386     AssertRCReturn(rc, rc);
    4387 
    4388     /* MSI Address (Lo, Hi) and MSI data are read-write PCI config registers handled by our generic PCI config space code. */
    4389 #if 0
    4390     /* MSI Address Lo. */
    4391     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_LO, 0);         /* RW - MSI message address (Lo). */
    4392     /* MSI Address Hi. */
    4393     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_HI, 0);         /* RW - MSI message address (Hi). */
    4394     /* MSI Data. */
    4395     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_DATA, 0);            /* RW - MSI data. */
    4396 #endif
    4397 
    4398 #if 0
    4399     /** @todo IOMMU: I don't know if we need to support this, enable later if
    4400      *        required. */
    4401     /* MSI Mapping Capability Header register. */
    4402     PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_MAP_CAP_HDR,
    4403                         RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_CAP_ID,   0x8)       /* RO - Capability ID */
    4404                       | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_CAP_PTR,  0x0)       /* RO - Offset to next capability (NULL) */
    4405                       | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_EN,       0x1)       /* RO - MSI mapping capability enable */
    4406                       | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_FIXED,    0x1)       /* RO - MSI mapping range is fixed */
    4407                       | RT_BF_MAKE(IOMMU_BF_MSI_MAP_CAPHDR_CAP_TYPE, 0x15));    /* RO - MSI mapping capability */
    4408     /* When implementing don't forget to copy this to its MMIO shadow register (MsiMapCapHdr) in iommuAmdR3Init. */
    4409 #endif
    4410 
    4411     /*
    4412      * Register the PCI function with PDM.
    4413      */
    4414     rc = PDMDevHlpPCIRegisterEx(pDevIns, pPciDev, 0 /* fFlags */, uPciDevice, uPciFunction, "amd-iommu");
    4415     AssertLogRelRCReturn(rc, rc);
    4416 
    4417     /*
    4418      * Intercept PCI config. space accesses.
    4419      */
    4420     rc = PDMDevHlpPCIInterceptConfigAccesses(pDevIns, pPciDev, iommuAmdR3PciConfigRead, iommuAmdR3PciConfigWrite);
    4421     AssertLogRelRCReturn(rc, rc);
    4422 
    4423     /*
    4424      * Create the MMIO region.
    4425      * Mapping of the region is done when software configures it via PCI config space.
    4426      */
    4427     rc = PDMDevHlpMmioCreate(pDevIns, IOMMU_MMIO_REGION_SIZE, pPciDev, 0 /* iPciRegion */, iommuAmdMmioWrite, iommuAmdMmioRead,
    4428                              NULL /* pvUser */, IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED,
    4429                              "AMD-IOMMU", &pThis->hMmio);
    4430     AssertLogRelRCReturn(rc, rc);
    4431 
    4432     /*
    4433      * Register saved state.
    4434      */
    4435     rc = PDMDevHlpSSMRegisterEx(pDevIns, IOMMU_SAVED_STATE_VERSION, sizeof(IOMMU), NULL,
    4436                                 NULL, NULL, NULL,
    4437                                 NULL, iommuAmdR3SaveExec, NULL,
    4438                                 NULL, iommuAmdR3LoadExec, NULL);
    4439     AssertLogRelRCReturn(rc, rc);
    4440 
    4441     /*
    4442      * Register debugger info item.
    4443      */
    4444     rc = PDMDevHlpDBGFInfoRegister(pDevIns, "iommu", "Display IOMMU state.", iommuAmdR3DbgInfo);
    4445     AssertLogRelRCReturn(rc, rc);
    4446 
    4447     /*
    4448      * Create the command thread and its event semaphore.
    4449      */
    4450     rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->pCmdThread, pThis, iommuAmdR3CmdThread, iommuAmdR3CmdThreadWakeUp,
    4451                                0 /* cbStack */, RTTHREADTYPE_IO, "AMD-IOMMU");
    4452     AssertLogRelRCReturn(rc, rc);
    4453 
    4454     rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtCmdThread);
    4455     AssertLogRelRCReturn(rc, rc);
     4481    pThis->RsvdReg = 0;
    44564482
    44574483    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette