VirtualBox

Changeset 86204 in vbox for trunk/src/VBox/Devices/Bus


Ignore:
Timestamp:
Sep 21, 2020 5:31:18 PM (4 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Reworked register accesses (write done) to support sub-qword accesses for qword registers.
In theory, we should also support 1 and 2 byte transfers. Currently using IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING.

File:
1 edited

Legend:

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

    r86145 r86204  
    4343/** The IOTLB entry magic. */
    4444#define IOMMU_IOTLBE_MAGIC                          0x10acce55
     45
     46#ifndef DEBUG_ramshankar
     47/** Temporary, make permanent later (get rid of define entirely and remove old
     48 *  code). This allow ssub-qword accesses to qword registers. Write accesses
     49 *  seems to work (needs testing one sub-path of the code), Read accesses not yet
     50 *  converted. */
     51# define IOMMU_NEW_REGISTER_ACCESS
     52#endif
    4553
    4654
     
    195203    /** @} */
    196204
    197     /** @name MMIO: PPR Log registers.
     205    /** @name MMIO: Peripheral Page Request (PPR) Log registers.
    198206     * @{ */
    199207    PPR_LOG_BAR_T               PprLogBaseAddr;         /**< PPR Log base address register. */
     
    241249    /** @} */
    242250
    243     /** @name MMIO: MARC registers.
     251    /** @name MMIO: Memory Address Routing & Control (MARC) registers.
    244252     * @{ */
    245253    MARC_APER_T                 aMarcApers[4];          /**< MARC Aperture Registers. */
     
    378386
    379387/**
    380  * IOMMU register access routines.
    381  */
    382 typedef struct
     388 * IOMMU register access.
     389 */
     390typedef struct IOMMUREGACC
    383391{
    384392    const char   *pszName;
    385     VBOXSTRICTRC (*pfnRead )(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t *pu64Value);
    386     VBOXSTRICTRC (*pfnWrite)(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t  u64Value);
    387     bool         f64BitReg;
     393    VBOXSTRICTRC (*pfnRead)(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value);
     394    VBOXSTRICTRC (*pfnWrite)(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t  u64Value);
     395    uint8_t      cb;
    388396} IOMMUREGACC;
     397/** Pointer to an IOMMU register access. */
     398typedef IOMMUREGACC *PIOMMUREGACC;
     399/** Pointer to a const IOMMU register access. */
     400typedef IOMMUREGACC const *PCIOMMUREGACC;
    389401
    390402
     
    546558
    547559/**
    548  * Writes to a read-only register.
    549  */
    550 static VBOXSTRICTRC iommuAmdIgnore_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    551 {
    552     RT_NOREF(pDevIns, pThis, iReg, u64Value);
    553     LogFunc(("Write to read-only register (%#x) with value %#RX64 ignored\n", iReg, u64Value));
    554     return VINF_SUCCESS;
    555 }
     560 * Reads the Device Table Base Address Register.
     561 */
     562static VBOXSTRICTRC iommuAmdDevTabBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     563{
     564    RT_NOREF(pDevIns, offReg);
     565    *pu64Value = pThis->aDevTabBaseAddrs[0].u64;
     566    return VINF_SUCCESS;
     567}
     568
     569
     570/**
     571 * Reads the Command Buffer Base Address Register.
     572 */
     573static VBOXSTRICTRC iommuAmdCmdBufBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     574{
     575    RT_NOREF(pDevIns, offReg);
     576    *pu64Value = pThis->CmdBufBaseAddr.u64;
     577    return VINF_SUCCESS;
     578}
     579
     580
     581/**
     582 * Reads the Event Log Base Address Register.
     583 */
     584static VBOXSTRICTRC iommuAmdEvtLogBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     585{
     586    RT_NOREF(pDevIns, offReg);
     587    *pu64Value = pThis->EvtLogBaseAddr.u64;
     588    return VINF_SUCCESS;
     589}
     590
     591
     592/**
     593 * Reads the Control Register.
     594 */
     595static VBOXSTRICTRC iommuAmdCtrl_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     596{
     597    RT_NOREF(pDevIns, offReg);
     598    *pu64Value = pThis->Ctrl.u64;
     599    return VINF_SUCCESS;
     600}
     601
     602
     603/**
     604 * Reads the Exclusion Range Base Address Register.
     605 */
     606static VBOXSTRICTRC iommuAmdExclRangeBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     607{
     608    RT_NOREF(pDevIns, offReg);
     609    *pu64Value = pThis->ExclRangeBaseAddr.u64;
     610    return VINF_SUCCESS;
     611}
     612
     613
     614/**
     615 * Reads to the Exclusion Range Limit Register.
     616 */
     617static VBOXSTRICTRC iommuAmdExclRangeLimit_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     618{
     619    RT_NOREF(pDevIns, offReg);
     620    *pu64Value = pThis->ExclRangeLimit.u64;
     621    return VINF_SUCCESS;
     622}
     623
     624
     625/**
     626 * Reads to the Extended Feature Register.
     627 */
     628static VBOXSTRICTRC iommuAmdExtFeat_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     629{
     630    RT_NOREF(pDevIns, offReg);
     631    *pu64Value = pThis->ExtFeat.u64;
     632    return VINF_SUCCESS;
     633}
     634
     635
     636/**
     637 * Reads to the PPR Log Base Address Register.
     638 */
     639static VBOXSTRICTRC iommuAmdPprLogBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     640{
     641    RT_NOREF(pDevIns, offReg);
     642    *pu64Value = pThis->PprLogBaseAddr.u64;
     643    return VINF_SUCCESS;
     644}
     645
     646
     647/**
     648 * Writes the Hardware Event Register (Hi).
     649 */
     650static VBOXSTRICTRC iommuAmdHwEvtHi_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     651{
     652    RT_NOREF(pDevIns, offReg);
     653    *pu64Value = pThis->HwEvtHi.u64;
     654    return VINF_SUCCESS;
     655}
     656
     657
     658/**
     659 * Reads the Hardware Event Register (Lo).
     660 */
     661static VBOXSTRICTRC iommuAmdHwEvtLo_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     662{
     663    RT_NOREF(pDevIns, offReg);
     664    *pu64Value = pThis->HwEvtLo;
     665    return VINF_SUCCESS;
     666}
     667
     668
     669/**
     670 * Reads the Hardware Event Status Register.
     671 */
     672static VBOXSTRICTRC iommuAmdHwEvtStatus_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     673{
     674    RT_NOREF(pDevIns, offReg);
     675    *pu64Value = pThis->HwEvtStatus.u64;
     676    return VINF_SUCCESS;
     677}
     678
     679
     680/**
     681 * Reads to the GA Log Base Address Register.
     682 */
     683static VBOXSTRICTRC iommuAmdGALogBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     684{
     685    RT_NOREF(pDevIns, offReg);
     686    *pu64Value = pThis->GALogBaseAddr.u64;
     687    return VINF_SUCCESS;
     688}
     689
     690
     691/**
     692 * Reads to the PPR Log B Base Address Register.
     693 */
     694static VBOXSTRICTRC iommuAmdPprLogBBaseAddr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     695{
     696    RT_NOREF(pDevIns, offReg);
     697    *pu64Value = pThis->PprLogBBaseAddr.u64;
     698    return VINF_SUCCESS;
     699}
     700
     701
     702/**
     703 * Reads to the Event Log B Base Address Register.
     704 */
     705static VBOXSTRICTRC iommuAmdEvtLogBBaseAddr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     706{
     707    RT_NOREF(pDevIns, offReg);
     708    *pu64Value = pThis->EvtLogBBaseAddr.u64;
     709    return VINF_SUCCESS;
     710}
     711
     712
     713/**
     714 * Reads the Device Table Segment Base Address Register.
     715 */
     716static VBOXSTRICTRC iommuAmdDevTabSegBar_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     717{
     718    RT_NOREF(pDevIns);
     719
     720    /* Figure out which segment is being written. */
     721    uint8_t const offSegment = (offReg - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3;
     722    uint8_t const idxSegment = offSegment + 1;
     723    Assert(idxSegment < RT_ELEMENTS(pThis->aDevTabBaseAddrs));
     724
     725    *pu64Value = pThis->aDevTabBaseAddrs[idxSegment].u64;
     726    return VINF_SUCCESS;
     727}
     728
     729
     730/**
     731 * Reads the Device Specific Feature Extension (DSFX) Register.
     732 */
     733static VBOXSTRICTRC iommuAmdDevSpecificFeat_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     734{
     735    RT_NOREF(pDevIns, offReg);
     736    *pu64Value = pThis->DevSpecificFeat.u64;
     737    return VINF_SUCCESS;
     738}
     739
     740/**
     741 * Reads the Device Specific Control Extension (DSCX) Register.
     742 */
     743static VBOXSTRICTRC iommuAmdDevSpecificCtrl_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     744{
     745    RT_NOREF(pDevIns, offReg);
     746    *pu64Value = pThis->DevSpecificCtrl.u64;
     747    return VINF_SUCCESS;
     748}
     749
     750
     751/**
     752 * Reads the Device Specific Status Extension (DSSX) Register.
     753 */
     754static VBOXSTRICTRC iommuAmdDevSpecificStatus_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     755{
     756    RT_NOREF(pDevIns, offReg);
     757    *pu64Value = pThis->DevSpecificStatus.u64;
     758    return VINF_SUCCESS;
     759}
     760
     761
     762/**
     763 * Reads the MSI Vector Register 0 (32-bit) or the MSI Vector Register 1 (32-bit).
     764 */
     765static VBOXSTRICTRC iommuAmdDevMsiVector_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     766{
     767    RT_NOREF(pDevIns, offReg);
     768    if (offReg == IOMMU_MMIO_OFF_MSI_VECTOR_0)
     769        *pu64Value = pThis->MiscInfo.au32[0];
     770    else
     771    {
     772        AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_VECTOR_1, ("%#x\n", offReg));
     773        *pu64Value = pThis->MiscInfo.au32[1];
     774    }
     775    return VINF_SUCCESS;
     776}
     777
     778
     779#ifdef IOMMU_NEW_REGISTER_ACCESS
     780/**
     781 * Reads the MSI Capability Header Register (32-bit) or the MSI Address (Lo)
     782 * Register (32-bit).
     783 */
     784static VBOXSTRICTRC iommuAmdMsiCapHdrOrAddrLo_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     785{
     786    RT_NOREF(pThis);
     787    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     788    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     789    if (offReg == IOMMU_MMIO_OFF_MSI_CAP_HDR)
     790        *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_CAP_HDR);
     791    else
     792    {
     793        AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_ADDR_LO, ("%#x\n", offReg));
     794        *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_LO);
     795    }
     796    return VINF_SUCCESS;
     797}
     798
     799
     800/**
     801 * Reads the MSI Address (Hi) Register (32-bit) or the MSI data register (32-bit).
     802 */
     803static VBOXSTRICTRC iommuAmdMsiAddrHiOrData_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     804{
     805    RT_NOREF(pThis);
     806    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     807    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     808
     809    if (offReg == IOMMU_MMIO_OFF_MSI_ADDR_HI)
     810        *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_HI);
     811    else
     812    {
     813        AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_DATA, ("%#x\n", offReg));
     814        *pu64Value = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_DATA);
     815    }
     816    return VINF_SUCCESS;
     817}
     818#endif
     819
     820/**
     821 * Reads the Command Buffer Head Pointer Register.
     822 */
     823static VBOXSTRICTRC iommuAmdCmdBufHeadPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     824{
     825    RT_NOREF(pDevIns, offReg);
     826    *pu64Value = pThis->CmdBufHeadPtr.u64;
     827    return VINF_SUCCESS;
     828}
     829
     830
     831/**
     832 * Reads the Command Buffer Tail Pointer Register.
     833 */
     834static VBOXSTRICTRC iommuAmdCmdBufTailPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     835{
     836    RT_NOREF(pDevIns, offReg);
     837    *pu64Value = pThis->CmdBufTailPtr.u64;
     838    return VINF_SUCCESS;
     839}
     840
     841
     842/**
     843 * Reads the Event Log Head Pointer Register.
     844 */
     845static VBOXSTRICTRC iommuAmdEvtLogHeadPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     846{
     847    RT_NOREF(pDevIns, offReg);
     848    *pu64Value = pThis->EvtLogHeadPtr.u64;
     849    return VINF_SUCCESS;
     850}
     851
     852
     853/**
     854 * Reads the Event Log Tail Pointer Register.
     855 */
     856static VBOXSTRICTRC iommuAmdEvtLogTailPtr_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     857{
     858    RT_NOREF(pDevIns, offReg);
     859    *pu64Value = pThis->EvtLogTailPtr.u64;
     860    return VINF_SUCCESS;
     861}
     862
     863
     864/**
     865 * Reads the Status Register.
     866 */
     867static VBOXSTRICTRC iommuAmdStatus_r(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t *pu64Value)
     868{
     869    RT_NOREF(pDevIns, offReg);
     870    *pu64Value = pThis->Status.u64;
     871    return VINF_SUCCESS;
     872}
     873
     874#ifndef IOMMU_NEW_REGISTER_ACCESS
     875static VBOXSTRICTRC iommuAmdIgnore_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     876{
     877    RT_NOREF(pDevIns, pThis, offReg, u64Value);
     878    return VINF_SUCCESS;
     879}
     880#endif
    556881
    557882
     
    559884 * Writes the Device Table Base Address Register.
    560885 */
    561 static VBOXSTRICTRC iommuAmdDevTabBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    562 {
    563     RT_NOREF(pDevIns, iReg);
     886static VBOXSTRICTRC iommuAmdDevTabBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     887{
     888    RT_NOREF(pDevIns, offReg);
    564889
    565890    /* Mask out all unrecognized bits. */
     
    575900 * Writes the Command Buffer Base Address Register.
    576901 */
    577 static VBOXSTRICTRC iommuAmdCmdBufBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    578 {
    579     RT_NOREF(pDevIns, iReg);
     902static VBOXSTRICTRC iommuAmdCmdBufBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     903{
     904    RT_NOREF(pDevIns, offReg);
    580905
    581906    /*
     
    618943 * Writes the Event Log Base Address Register.
    619944 */
    620 static VBOXSTRICTRC iommuAmdEvtLogBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    621 {
    622     RT_NOREF(pDevIns, iReg);
     945static VBOXSTRICTRC iommuAmdEvtLogBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     946{
     947    RT_NOREF(pDevIns, offReg);
    623948
    624949    /*
     
    662987 * Writes the Control Register.
    663988 */
    664 static VBOXSTRICTRC iommuAmdCtrl_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    665 {
    666     RT_NOREF(pDevIns, iReg);
     989static VBOXSTRICTRC iommuAmdCtrl_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     990{
     991    RT_NOREF(pDevIns, offReg);
    667992
    668993    /* Mask out all unrecognized bits. */
    669994    u64Value &= IOMMU_CTRL_VALID_MASK;
    670 
    671     IOMMU_CTRL_T const OldCtrl = iommuAmdGetCtrl(pThis);
    672995    IOMMU_CTRL_T NewCtrl;
    673996    NewCtrl.u64 = u64Value;
    674997
    675     /* Update the register. */
    676     ASMAtomicWriteU64(&pThis->Ctrl.u64, NewCtrl.u64);
    677 
    678     bool const fNewIommuEn = NewCtrl.n.u1IommuEn;
    679     bool const fOldIommuEn = OldCtrl.n.u1IommuEn;
    680 
    681     /* Enable or disable event logging when the bit transitions. */
    682     bool const fOldEvtLogEn = OldCtrl.n.u1EvtLogEn;
    683     bool const fNewEvtLogEn = NewCtrl.n.u1EvtLogEn;
    684     if (   fOldEvtLogEn != fNewEvtLogEn
    685         || fOldIommuEn != fNewIommuEn)
    686     {
    687         if (   fNewIommuEn
    688             && fNewEvtLogEn)
    689         {
    690             ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_OVERFLOW);
    691             ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_EVT_LOG_RUNNING);
    692         }
    693         else
    694             ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_RUNNING);
    695     }
    696 
    697     /* Enable or disable command buffer processing when the bit transitions. */
    698     bool const fOldCmdBufEn = OldCtrl.n.u1CmdBufEn;
    699     bool const fNewCmdBufEn = NewCtrl.n.u1CmdBufEn;
    700     if (   fOldCmdBufEn != fNewCmdBufEn
    701         || fOldIommuEn != fNewIommuEn)
    702     {
    703         if (   fNewCmdBufEn
    704             && fNewIommuEn)
    705         {
    706             ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_CMD_BUF_RUNNING);
    707             LogFunc(("Command buffer enabled\n"));
    708 
    709             /* Wake up the command thread to start processing commands. */
    710             iommuAmdCmdThreadWakeUpIfNeeded(pDevIns);
    711         }
    712         else
    713         {
    714             ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING);
    715             LogFunc(("Command buffer disabled\n"));
    716         }
    717     }
    718 
    719     return VINF_SUCCESS;
    720 }
    721 
    722 
    723 /**
    724  * Writes to the Excluse Range Base Address Register.
    725  */
    726 static VBOXSTRICTRC iommuAmdExclRangeBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    727 {
    728     RT_NOREF(pDevIns, iReg);
     998    /* Ensure the device table segments are within limits. */
     999    if (NewCtrl.n.u3DevTabSegEn <= pThis->ExtFeat.n.u2DevTabSegSup)
     1000    {
     1001        IOMMU_CTRL_T const OldCtrl = iommuAmdGetCtrl(pThis);
     1002
     1003        /* Update the register. */
     1004        ASMAtomicWriteU64(&pThis->Ctrl.u64, NewCtrl.u64);
     1005
     1006        bool const fNewIommuEn = NewCtrl.n.u1IommuEn;
     1007        bool const fOldIommuEn = OldCtrl.n.u1IommuEn;
     1008
     1009        /* Enable or disable event logging when the bit transitions. */
     1010        bool const fOldEvtLogEn = OldCtrl.n.u1EvtLogEn;
     1011        bool const fNewEvtLogEn = NewCtrl.n.u1EvtLogEn;
     1012        if (   fOldEvtLogEn != fNewEvtLogEn
     1013            || fOldIommuEn != fNewIommuEn)
     1014        {
     1015            if (   fNewIommuEn
     1016                && fNewEvtLogEn)
     1017            {
     1018                ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_OVERFLOW);
     1019                ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_EVT_LOG_RUNNING);
     1020            }
     1021            else
     1022                ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_EVT_LOG_RUNNING);
     1023        }
     1024
     1025        /* Enable or disable command buffer processing when the bit transitions. */
     1026        bool const fOldCmdBufEn = OldCtrl.n.u1CmdBufEn;
     1027        bool const fNewCmdBufEn = NewCtrl.n.u1CmdBufEn;
     1028        if (   fOldCmdBufEn != fNewCmdBufEn
     1029            || fOldIommuEn != fNewIommuEn)
     1030        {
     1031            if (   fNewCmdBufEn
     1032                && fNewIommuEn)
     1033            {
     1034                ASMAtomicOrU64(&pThis->Status.u64, IOMMU_STATUS_CMD_BUF_RUNNING);
     1035                LogFunc(("Command buffer enabled\n"));
     1036
     1037                /* Wake up the command thread to start processing commands. */
     1038                iommuAmdCmdThreadWakeUpIfNeeded(pDevIns);
     1039            }
     1040            else
     1041            {
     1042                ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING);
     1043                LogFunc(("Command buffer disabled\n"));
     1044            }
     1045        }
     1046    }
     1047    else
     1048    {
     1049        LogFunc(("Invalid number of device table segments enabled, exceeds %#x (%#RX64) -> Ignored!\n",
     1050                 pThis->ExtFeat.n.u2DevTabSegSup, NewCtrl.u64));
     1051    }
     1052
     1053    return VINF_SUCCESS;
     1054}
     1055
     1056
     1057/**
     1058 * Writes to the Exclusion Range Base Address Register.
     1059 */
     1060static VBOXSTRICTRC iommuAmdExclRangeBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1061{
     1062    RT_NOREF(pDevIns, offReg);
    7291063    pThis->ExclRangeBaseAddr.u64 = u64Value & IOMMU_EXCL_RANGE_BAR_VALID_MASK;
    7301064    return VINF_SUCCESS;
     
    7331067
    7341068/**
    735  * Writes to the Excluse Range Limit Register.
    736  */
    737 static VBOXSTRICTRC iommuAmdExclRangeLimit_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    738 {
    739     RT_NOREF(pDevIns, iReg);
     1069 * Writes to the Exclusion Range Limit Register.
     1070 */
     1071static VBOXSTRICTRC iommuAmdExclRangeLimit_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1072{
     1073    RT_NOREF(pDevIns, offReg);
    7401074    u64Value &= IOMMU_EXCL_RANGE_LIMIT_VALID_MASK;
    7411075    u64Value |= UINT64_C(0xfff);
     
    7481082 * Writes the Hardware Event Register (Hi).
    7491083 */
    750 static VBOXSTRICTRC iommuAmdHwEvtHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     1084static VBOXSTRICTRC iommuAmdHwEvtHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
    7511085{
    7521086    /** @todo IOMMU: Why the heck is this marked read/write by the AMD IOMMU spec? */
    753     RT_NOREF(pDevIns, iReg);
     1087    RT_NOREF(pDevIns, offReg);
    7541088    LogFlowFunc(("Writing %#RX64 to hardware event (Hi) register!\n", u64Value));
    7551089    pThis->HwEvtHi.u64 = u64Value;
     
    7611095 * Writes the Hardware Event Register (Lo).
    7621096 */
    763 static VBOXSTRICTRC iommuAmdHwEvtLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     1097static VBOXSTRICTRC iommuAmdHwEvtLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
    7641098{
    7651099    /** @todo IOMMU: Why the heck is this marked read/write by the AMD IOMMU spec? */
    766     RT_NOREF(pDevIns, iReg);
     1100    RT_NOREF(pDevIns, offReg);
    7671101    LogFlowFunc(("Writing %#RX64 to hardware event (Lo) register!\n", u64Value));
    7681102    pThis->HwEvtLo = u64Value;
     
    7741108 * Writes the Hardware Event Status Register.
    7751109 */
    776 static VBOXSTRICTRC iommuAmdHwEvtStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    777 {
    778     RT_NOREF(pDevIns, iReg);
     1110static VBOXSTRICTRC iommuAmdHwEvtStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1111{
     1112    RT_NOREF(pDevIns, offReg);
    7791113
    7801114    /* Mask out all unrecognized bits. */
     
    8031137 * Writes the Device Table Segment Base Address Register.
    8041138 */
    805 static VBOXSTRICTRC iommuAmdDevTabSegBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     1139static VBOXSTRICTRC iommuAmdDevTabSegBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
    8061140{
    8071141    RT_NOREF(pDevIns);
    8081142
    8091143    /* Figure out which segment is being written. */
    810     uint8_t const offSegment = (iReg - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3;
     1144    uint8_t const offSegment = (offReg - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3;
    8111145    uint8_t const idxSegment = offSegment + 1;
    8121146    Assert(idxSegment < RT_ELEMENTS(pThis->aDevTabBaseAddrs));
     
    8321166
    8331167
     1168#ifndef IOMMU_NEW_REGISTER_ACCESS
    8341169/**
    8351170 * Writes the MSI Capability Header Register.
    8361171 */
    837 static VBOXSTRICTRC iommuAmdMsiCapHdr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    838 {
    839     RT_NOREF(pThis, iReg);
     1172static VBOXSTRICTRC iommuAmdMsiCapHdr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1173{
     1174    RT_NOREF(pThis, offReg);
    8401175    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
    8411176    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     
    8511186 * Writes the MSI Address (Lo) Register (32-bit).
    8521187 */
    853 static VBOXSTRICTRC iommuAmdMsiAddrLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    854 {
    855     RT_NOREF(pThis, iReg);
     1188static VBOXSTRICTRC iommuAmdMsiAddrLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1189{
     1190    RT_NOREF(pThis, offReg);
    8561191    Assert(!RT_HI_U32(u64Value));
    8571192    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     
    8651200 * Writes the MSI Address (Hi) Register (32-bit).
    8661201 */
    867 static VBOXSTRICTRC iommuAmdMsiAddrHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    868 {
    869     RT_NOREF(pThis, iReg);
     1202static VBOXSTRICTRC iommuAmdMsiAddrHi_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1203{
     1204    RT_NOREF(pThis, offReg);
    8701205    Assert(!RT_HI_U32(u64Value));
    8711206    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     
    8791214 * Writes the MSI Data Register (32-bit).
    8801215 */
    881 static VBOXSTRICTRC iommuAmdMsiData_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    882 {
    883     RT_NOREF(pThis, iReg);
     1216static VBOXSTRICTRC iommuAmdMsiData_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1217{
     1218    RT_NOREF(pThis, offReg);
    8841219    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
    8851220    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     
    8871222    return VINF_SUCCESS;
    8881223}
    889 
    890 
    891 /**
    892  * Writes the Command Buffer Head Pointer Register (32-bit).
    893  */
    894 static VBOXSTRICTRC iommuAmdCmdBufHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    895 {
    896     RT_NOREF(pDevIns, iReg);
     1224#else
     1225/**
     1226 * Writes the MSI Capability Header Register (32-bit) or the MSI Address (Lo)
     1227 * Register (32-bit).
     1228 */
     1229static VBOXSTRICTRC iommuAmdMsiCapHdrOrAddrLo_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1230{
     1231    RT_NOREF(pThis);
     1232    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     1233    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     1234    if (offReg == IOMMU_MMIO_OFF_MSI_CAP_HDR)
     1235    {
     1236        /* MsiMultMessEn not supported, so only MsiEn is the writable bit. */
     1237        MSI_CAP_HDR_T MsiCapHdr;
     1238        MsiCapHdr.u32           = PDMPciDevGetDWord(pPciDev, IOMMU_PCI_OFF_MSI_CAP_HDR);
     1239        MsiCapHdr.n.u1MsiEnable = RT_BOOL(u64Value & IOMMU_MSI_CAP_HDR_MSI_EN_MASK);
     1240        PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_CAP_HDR, MsiCapHdr.u32);
     1241    }
     1242    else
     1243    {
     1244        AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_ADDR_LO, ("%#x\n", offReg));
     1245        uint32_t const uMsiAddrLo = u64Value & VBOX_MSI_ADDR_VALID_MASK;
     1246        PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_LO, uMsiAddrLo);
     1247    }
     1248    return VINF_SUCCESS;
     1249}
     1250
     1251
     1252/**
     1253 * Writes the MSI Address (Hi) Register (32-bit) or the MSI data register (32-bit).
     1254 */
     1255static VBOXSTRICTRC iommuAmdMsiAddrHiOrData_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1256{
     1257    RT_NOREF(pThis);
     1258    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     1259    PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
     1260    if (offReg == IOMMU_MMIO_OFF_MSI_ADDR_HI)
     1261        PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_ADDR_HI, u64Value);
     1262    else
     1263    {
     1264        AssertMsg(offReg == IOMMU_MMIO_OFF_MSI_DATA, ("%#x\n", offReg));
     1265        uint32_t const uMsiData = u64Value & VBOX_MSI_DATA_VALID_MASK;
     1266        PDMPciDevSetDWord(pPciDev, IOMMU_PCI_OFF_MSI_DATA, uMsiData);
     1267    }
     1268    return VINF_SUCCESS;
     1269}
     1270#endif
     1271
     1272
     1273/**
     1274 * Writes the Command Buffer Head Pointer Register.
     1275 */
     1276static VBOXSTRICTRC iommuAmdCmdBufHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1277{
     1278    RT_NOREF(pDevIns, offReg);
    8971279
    8981280    /*
     
    9321314
    9331315/**
    934  * Writes the Command Buffer Tail Pointer Register (32-bit).
    935  */
    936 static VBOXSTRICTRC iommuAmdCmdBufTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    937 {
    938     RT_NOREF(pDevIns, iReg);
     1316 * Writes the Command Buffer Tail Pointer Register.
     1317 */
     1318static VBOXSTRICTRC iommuAmdCmdBufTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1319{
     1320    RT_NOREF(pDevIns, offReg);
    9391321
    9401322    /*
     
    9731355
    9741356/**
    975  * Writes the Event Log Head Pointer Register (32-bit).
    976  */
    977 static VBOXSTRICTRC iommuAmdEvtLogHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    978 {
    979     RT_NOREF(pDevIns, iReg);
     1357 * Writes the Event Log Head Pointer Register.
     1358 */
     1359static VBOXSTRICTRC iommuAmdEvtLogHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1360{
     1361    RT_NOREF(pDevIns, offReg);
    9801362
    9811363    /*
     
    10021384
    10031385/**
    1004  * Writes the Event Log Tail Pointer Register (32-bit).
    1005  */
    1006 static VBOXSTRICTRC iommuAmdEvtLogTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    1007 {
    1008     RT_NOREF(pDevIns, iReg);
     1386 * Writes the Event Log Tail Pointer Register.
     1387 */
     1388static VBOXSTRICTRC iommuAmdEvtLogTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1389{
     1390    RT_NOREF(pDevIns, offReg);
    10091391    NOREF(pThis);
    10101392
     
    10431425
    10441426/**
    1045  * Writes the Status Register (64-bit).
    1046  */
    1047 static VBOXSTRICTRC iommuAmdStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
    1048 {
    1049     RT_NOREF(pDevIns, iReg);
     1427 * Writes the Status Register.
     1428 */
     1429static VBOXSTRICTRC iommuAmdStatus_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t offReg, uint64_t u64Value)
     1430{
     1431    RT_NOREF(pDevIns, offReg);
    10501432
    10511433    /* Mask out all unrecognized bits. */
     
    10681450}
    10691451
    1070 
    1071 #if 0
    1072 /**
    1073  * Table 0: Registers-access table.
    1074  */
    1075 static const IOMMUREGACC g_aTable0Regs[] =
    1076 {
    1077 
     1452#ifdef IOMMU_NEW_REGISTER_ACCESS
     1453/**
     1454 * Register access table 0.
     1455 * The MMIO offset of each entry must be a multiple of 8!
     1456 */
     1457static const IOMMUREGACC g_aRegAccess0[] =
     1458{
     1459    /* MMIO off.   Register name                           Read function                Write function               Reg. size */
     1460    { /* 0x00  */  "DEV_TAB_BAR",                          iommuAmdDevTabBar_r,         iommuAmdDevTabBar_w,         8 },
     1461    { /* 0x08  */  "CMD_BUF_BAR",                          iommuAmdCmdBufBar_r,         iommuAmdCmdBufBar_w,         8 },
     1462    { /* 0x10  */  "EVT_LOG_BAR",                          iommuAmdEvtLogBar_r,         iommuAmdEvtLogBar_w,         8 },
     1463    { /* 0x18  */  "CTRL",                                 iommuAmdCtrl_r,              iommuAmdCtrl_w,              8 },
     1464    { /* 0x20  */  "EXCL_BAR",                             iommuAmdExclRangeBar_r,      iommuAmdExclRangeBar_w,      8 },
     1465    { /* 0x28  */  "EXCL_RANGE_LIMIT",                     iommuAmdExclRangeLimit_r,    iommuAmdExclRangeLimit_w,    8 },
     1466    { /* 0x30  */  "EXT_FEAT",                             iommuAmdExtFeat_r,           NULL,                        8 },
     1467    { /* 0x38  */  "PPR_LOG_BAR",                          iommuAmdPprLogBar_r,         NULL,                        8 },
     1468    { /* 0x40  */  "HW_EVT_HI",                            iommuAmdHwEvtHi_r,           iommuAmdHwEvtHi_w,           8 },
     1469    { /* 0x48  */  "HW_EVT_LO",                            iommuAmdHwEvtLo_r,           iommuAmdHwEvtLo_w,           8 },
     1470    { /* 0x50  */  "HW_EVT_STATUS",                        iommuAmdHwEvtStatus_r,       iommuAmdHwEvtStatus_w,       8 },
     1471    { /* 0x58  */  NULL,                                   NULL,                        NULL,                        0 },
     1472
     1473    { /* 0x60  */  "SMI_FLT_0",                            NULL,                        NULL,                        8 },
     1474    { /* 0x68  */  "SMI_FLT_1",                            NULL,                        NULL,                        8 },
     1475    { /* 0x70  */  "SMI_FLT_2",                            NULL,                        NULL,                        8 },
     1476    { /* 0x78  */  "SMI_FLT_3",                            NULL,                        NULL,                        8 },
     1477    { /* 0x80  */  "SMI_FLT_4",                            NULL,                        NULL,                        8 },
     1478    { /* 0x88  */  "SMI_FLT_5",                            NULL,                        NULL,                        8 },
     1479    { /* 0x90  */  "SMI_FLT_6",                            NULL,                        NULL,                        8 },
     1480    { /* 0x98  */  "SMI_FLT_7",                            NULL,                        NULL,                        8 },
     1481    { /* 0xa0  */  "SMI_FLT_8",                            NULL,                        NULL,                        8 },
     1482    { /* 0xa8  */  "SMI_FLT_9",                            NULL,                        NULL,                        8 },
     1483    { /* 0xb0  */  "SMI_FLT_10",                           NULL,                        NULL,                        8 },
     1484    { /* 0xb8  */  "SMI_FLT_11",                           NULL,                        NULL,                        8 },
     1485    { /* 0xc0  */  "SMI_FLT_12",                           NULL,                        NULL,                        8 },
     1486    { /* 0xc8  */  "SMI_FLT_13",                           NULL,                        NULL,                        8 },
     1487    { /* 0xd0  */  "SMI_FLT_14",                           NULL,                        NULL,                        8 },
     1488    { /* 0xd8  */  "SMI_FLT_15",                           NULL,                        NULL,                        8 },
     1489
     1490    { /* 0xe0  */  "GALOG_BAR",                            iommuAmdGALogBar_r,          NULL,                        8 },
     1491    { /* 0xe8  */  "GALOG_TAIL_ADDR",                      NULL,                        NULL,                        8 },
     1492    { /* 0xf0  */  "PPR_LOG_B_BAR",                        iommuAmdPprLogBBaseAddr_r,   NULL,                        8 },
     1493    { /* 0xf8  */  "PPR_EVT_B_BAR",                        iommuAmdEvtLogBBaseAddr_r,   NULL,                        8 },
     1494
     1495    { /* 0x100 */  "DEV_TAB_SEG_1",                        iommuAmdDevTabSegBar_r,      iommuAmdDevTabSegBar_w,      8 },
     1496    { /* 0x108 */  "DEV_TAB_SEG_2",                        iommuAmdDevTabSegBar_r,      iommuAmdDevTabSegBar_w,      8 },
     1497    { /* 0x110 */  "DEV_TAB_SEG_3",                        iommuAmdDevTabSegBar_r,      iommuAmdDevTabSegBar_w,      8 },
     1498    { /* 0x118 */  "DEV_TAB_SEG_4",                        iommuAmdDevTabSegBar_r,      iommuAmdDevTabSegBar_w,      8 },
     1499    { /* 0x120 */  "DEV_TAB_SEG_5",                        iommuAmdDevTabSegBar_r,      iommuAmdDevTabSegBar_w,      8 },
     1500    { /* 0x128 */  "DEV_TAB_SEG_6",                        iommuAmdDevTabSegBar_r,      iommuAmdDevTabSegBar_w,      8 },
     1501    { /* 0x130 */  "DEV_TAB_SEG_7",                        iommuAmdDevTabSegBar_r,      iommuAmdDevTabSegBar_w,      8 },
     1502
     1503    { /* 0x138 */  "DEV_SPECIFIC_FEAT",                    iommuAmdDevSpecificFeat_r,   NULL,                        8 },
     1504    { /* 0x140 */  "DEV_SPECIFIC_CTRL",                    iommuAmdDevSpecificCtrl_r,   NULL,                        8 },
     1505    { /* 0x148 */  "DEV_SPECIFIC_STATUS",                  iommuAmdDevSpecificStatus_r, NULL,                        8 },
     1506
     1507    { /* 0x150 */  "MSI_VECTOR_0 or MSI_VECTOR_1",         iommuAmdDevMsiVector_r,      NULL,                        4 },
     1508    { /* 0x158 */  "MSI_CAP_HDR or MSI_ADDR_LO",           iommuAmdMsiCapHdrOrAddrLo_r, iommuAmdMsiCapHdrOrAddrLo_w, 4 },
     1509    { /* 0x160 */  "MSI_ADDR_HI or MSI_DATA",              iommuAmdMsiAddrHiOrData_r,   iommuAmdMsiAddrHiOrData_w,   4 },
     1510    { /* 0x168 */  "MSI_MAPPING_CAP_HDR or PERF_OPT_CTRL", NULL,                        NULL,                        4 },
     1511
     1512    { /* 0x170 */  "XT_GEN_INTR_CTRL",                     NULL,                        NULL,                        8 },
     1513    { /* 0x178 */  "XT_PPR_INTR_CTRL",                     NULL,                        NULL,                        8 },
     1514    { /* 0x180 */  "XT_GALOG_INT_CTRL",                    NULL,                        NULL,                        8 },
    10781515};
    1079 
    1080 /**
    1081  * Table 1: Registers-access table.
    1082  */
    1083 static const IOMMUREGACC g_aTable1Regs[] =
    1084 {
     1516AssertCompile(RT_ELEMENTS(g_aRegAccess0) == (IOMMU_MMIO_OFF_QWORD_TABLE_0_END - IOMMU_MMIO_OFF_QWORD_TABLE_0_START) / 8);
     1517
     1518/**
     1519 * Register access table 1.
     1520 * The MMIO offset of each entry must be a multiple of 8!
     1521 */
     1522static const IOMMUREGACC g_aRegAccess1[] =
     1523{
     1524    /* MMIO offset    Register name      Read function    Write function    Register size. */
     1525    { /* 0x200 */  "MARC_APER_BAR_0",    NULL,            NULL,             8 },
     1526    { /* 0x208 */  "MARC_APER_RELOC_0",  NULL,            NULL,             8 },
     1527    { /* 0x210 */  "MARC_APER_LEN_0",    NULL,            NULL,             8 },
     1528    { /* 0x218 */  "MARC_APER_BAR_1",    NULL,            NULL,             8 },
     1529    { /* 0x220 */  "MARC_APER_RELOC_1",  NULL,            NULL,             8 },
     1530    { /* 0x228 */  "MARC_APER_LEN_1",    NULL,            NULL,             8 },
     1531    { /* 0x230 */  "MARC_APER_BAR_2",    NULL,            NULL,             8 },
     1532    { /* 0x238 */  "MARC_APER_RELOC_2",  NULL,            NULL,             8 },
     1533    { /* 0x240 */  "MARC_APER_LEN_2",    NULL,            NULL,             8 },
     1534    { /* 0x248 */  "MARC_APER_BAR_3",    NULL,            NULL,             8 },
     1535    { /* 0x250 */  "MARC_APER_RELOC_3",  NULL,            NULL,             8 },
     1536    { /* 0x258 */  "MARC_APER_LEN_3",    NULL,            NULL,             8 }
    10851537};
     1538AssertCompile(RT_ELEMENTS(g_aRegAccess1) == (IOMMU_MMIO_OFF_QWORD_TABLE_1_END - IOMMU_MMIO_OFF_QWORD_TABLE_1_START) / 8);
     1539
     1540/**
     1541 * Register access table 2.
     1542 * The MMIO offset of each entry must be a multiple of 8!
     1543 */
     1544static const IOMMUREGACC g_aRegAccess2[] =
     1545{
     1546    /* MMIO offset    Register name               Read Function             Write function           Register size (bytes) */
     1547    { /* 0x1ff8 */    "RSVD_REG",                 NULL,                     NULL,                    8 },
     1548
     1549    { /* 0x2000 */    "CMD_BUF_HEAD_PTR",         iommuAmdCmdBufHeadPtr_r,  iommuAmdCmdBufHeadPtr_w, 8 },
     1550    { /* 0x2008 */    "CMD_BUF_TAIL_PTR",         iommuAmdCmdBufTailPtr_r , iommuAmdCmdBufTailPtr_w, 8 },
     1551    { /* 0x2010 */    "EVT_LOG_HEAD_PTR",         iommuAmdEvtLogHeadPtr_r,  iommuAmdEvtLogHeadPtr_w, 8 },
     1552    { /* 0x2018 */    "EVT_LOG_TAIL_PTR",         iommuAmdEvtLogTailPtr_r,  iommuAmdEvtLogTailPtr_w, 8 },
     1553
     1554    { /* 0x2020 */    "STATUS",                   iommuAmdStatus_r,         iommuAmdStatus_w,        8 },
     1555    { /* 0x2028 */    NULL,                       NULL,                     NULL,                    0 },
     1556
     1557    { /* 0x2030 */    "PPR_LOG_HEAD_PTR",         NULL,                     NULL,                    8 },
     1558    { /* 0x2038 */    "PPR_LOG_TAIL_PTR",         NULL,                     NULL,                    8 },
     1559
     1560    { /* 0x2040 */    "GALOG_HEAD_PTR",           NULL,                     NULL,                    8 },
     1561    { /* 0x2048 */    "GALOG_TAIL_PTR",           NULL,                     NULL,                    8 },
     1562
     1563    { /* 0x2050 */    "PPR_LOG_B_HEAD_PTR",       NULL,                     NULL,                    8 },
     1564    { /* 0x2058 */    "PPR_LOG_B_TAIL_PTR",       NULL,                     NULL,                    8 },
     1565
     1566    { /* 0x2060 */    NULL,                       NULL,                     NULL,                    0 },
     1567    { /* 0x2068 */    NULL,                       NULL,                     NULL,                    0 },
     1568
     1569    { /* 0x2070 */    "EVT_LOG_B_HEAD_PTR",       NULL,                     NULL,                    8 },
     1570    { /* 0x2078 */    "EVT_LOG_B_TAIL_PTR",       NULL,                     NULL,                    8 },
     1571
     1572    { /* 0x2080 */    "PPR_LOG_AUTO_RESP",        NULL,                     NULL,                    8 },
     1573    { /* 0x2088 */    "PPR_LOG_OVERFLOW_EARLY",   NULL,                     NULL,                    8 },
     1574    { /* 0x2090 */    "PPR_LOG_B_OVERFLOW_EARLY", NULL,                     NULL,                    8 }
     1575};
     1576AssertCompile(RT_ELEMENTS(g_aRegAccess2) == (IOMMU_MMIO_OFF_QWORD_TABLE_2_END - IOMMU_MMIO_OFF_QWORD_TABLE_2_START) / 8);
    10861577#endif
    10871578
     
    11001591static VBOXSTRICTRC iommuAmdWriteRegister(PPDMDEVINS pDevIns, uint32_t off, uint8_t cb, uint64_t uValue)
    11011592{
     1593    /*
     1594     * Validate the access in case of IOM bug or incorrect assumption.
     1595     */
    11021596    Assert(off < IOMMU_MMIO_REGION_SIZE);
    1103     Assert(cb == 4 || cb == 8);
    1104     Assert(!(off & (cb - 1)));
     1597    AssertMsgReturn(cb == 4 || cb == 8, ("Invalid access size %u\n", cb), VINF_SUCCESS);
     1598    AssertMsgReturn(!(off & 3), ("Invalid offset %#x\n", off), VINF_SUCCESS);
    11051599
    11061600    Log5Func(("off=%#x cb=%u uValue=%#RX64\n", off, cb, uValue));
    11071601
    11081602    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     1603#ifndef IOMMU_NEW_REGISTER_ACCESS
    11091604    switch (off)
    11101605    {
     
    11831678        case IOMMU_MMIO_OFF_RSVD_REG:            return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
    11841679
    1185         case IOMMU_MMIO_CMD_BUF_HEAD_PTR:        return iommuAmdCmdBufHeadPtr_w(pDevIns, pThis, off, uValue);
    1186         case IOMMU_MMIO_CMD_BUF_TAIL_PTR:        return iommuAmdCmdBufTailPtr_w(pDevIns, pThis, off, uValue);
    1187         case IOMMU_MMIO_EVT_LOG_HEAD_PTR:        return iommuAmdEvtLogHeadPtr_w(pDevIns, pThis, off, uValue);
    1188         case IOMMU_MMIO_EVT_LOG_TAIL_PTR:        return iommuAmdEvtLogTailPtr_w(pDevIns, pThis, off, uValue);
     1680        case IOMMU_MMIO_OFF_CMD_BUF_HEAD_PTR:    return iommuAmdCmdBufHeadPtr_w(pDevIns, pThis, off, uValue);
     1681        case IOMMU_MMIO_OFF_CMD_BUF_TAIL_PTR:    return iommuAmdCmdBufTailPtr_w(pDevIns, pThis, off, uValue);
     1682        case IOMMU_MMIO_OFF_EVT_LOG_HEAD_PTR:    return iommuAmdEvtLogHeadPtr_w(pDevIns, pThis, off, uValue);
     1683        case IOMMU_MMIO_OFF_EVT_LOG_TAIL_PTR:    return iommuAmdEvtLogTailPtr_w(pDevIns, pThis, off, uValue);
    11891684
    11901685        case IOMMU_MMIO_OFF_STATUS:              return iommuAmdStatus_w(pDevIns, pThis, off, uValue);
     
    12211716        }
    12221717    }
     1718#else
     1719    /*
     1720     * Figure out which table the register belongs to and validate its index.
     1721     */
     1722    PCIOMMUREGACC pReg;
     1723    if (off < IOMMU_MMIO_OFF_QWORD_TABLE_0_END)
     1724    {
     1725        uint32_t const idxReg = off >> 3;
     1726        Assert(idxReg < RT_ELEMENTS(g_aRegAccess0));
     1727        pReg = &g_aRegAccess0[idxReg];
     1728    }
     1729    else if (   off <  IOMMU_MMIO_OFF_QWORD_TABLE_1_END
     1730             && off >= IOMMU_MMIO_OFF_QWORD_TABLE_1_START)
     1731    {
     1732        uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_1_START) >> 3;
     1733        Assert(idxReg < RT_ELEMENTS(g_aRegAccess1));
     1734        pReg = &g_aRegAccess1[idxReg];
     1735    }
     1736    else if (   off <  IOMMU_MMIO_OFF_QWORD_TABLE_2_END
     1737             && off >= IOMMU_MMIO_OFF_QWORD_TABLE_2_START)
     1738    {
     1739        uint32_t const idxReg = (off - IOMMU_MMIO_OFF_QWORD_TABLE_2_START) >> 3;
     1740        Assert(idxReg < RT_ELEMENTS(g_aRegAccess2));
     1741        pReg = &g_aRegAccess2[idxReg];
     1742    }
     1743    else
     1744    {
     1745        LogFunc(("Writing unknown register %u (%#x) with %#RX64 -> Ignored\n", off, off, uValue));
     1746        return VINF_SUCCESS;
     1747    }
     1748
     1749    if (pReg->pfnWrite)
     1750    {
     1751        /*
     1752         * If the write access is aligned and matches the register size, dispatch right away.
     1753         * This handles all aligned, 32-bit writes as well.
     1754         */
     1755        if (   cb == pReg->cb
     1756            && !(off & (cb - 1)))
     1757            return pReg->pfnWrite(pDevIns, pThis, off, uValue);
     1758
     1759        /*
     1760         * A 32-bit access for a 64-bit register.
     1761         * This is writing a 64-bit register since we took care of 32-bit writes above.
     1762         * We shouldn't get smaller sizes because we've specified so with IOM.
     1763         */
     1764        Assert(cb == 4);
     1765        if (!(off & 7))
     1766        {
     1767            /* Lower 32-bits are being written. Merge with higher bits of the register. */
     1768            uint64_t uHi;
     1769            if (pReg->pfnRead)
     1770            {
     1771                VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off, &uHi);
     1772                if (RT_FAILURE(rcStrict))
     1773                {
     1774                    LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict)));
     1775                    return rcStrict;
     1776                }
     1777            }
     1778            else
     1779                uHi = 0;
     1780            uHi &= UINT64_C(0xffffffff00000000);
     1781            uValue |= uHi;
     1782
     1783            /* Perform the full, 64-bit write. */
     1784            return pReg->pfnWrite(pDevIns, pThis, off, uValue);
     1785        }
     1786
     1787        /* Higher 32-bits are being written. Merge with lower bits of the register. */
     1788        Assert(!(off & 3));
     1789        Assert(off > 4);
     1790        uint64_t uLo;
     1791        if (pReg->pfnRead)
     1792        {
     1793            VBOXSTRICTRC rcStrict = pReg->pfnRead(pDevIns, pThis, off - 4, &uLo);
     1794            if (RT_FAILURE(rcStrict))
     1795            {
     1796                LogFunc(("Reading off %#x during split write failed! rc=%Rrc\n -> Ignored", off, VBOXSTRICTRC_VAL(rcStrict)));
     1797                return rcStrict;
     1798            }
     1799        }
     1800        else
     1801            uLo = 0;
     1802
     1803        uLo &= UINT64_C(0x00000000ffffffff);
     1804        uValue <<= 32;
     1805        uValue |= uLo;
     1806
     1807        /* Perform the full, 64-bit write. */
     1808        return pReg->pfnWrite(pDevIns, pThis, off - 4, uValue);
     1809    }
     1810    else
     1811        LogFunc(("Writing unknown register %u (%#x) with %#RX64 (cb=%u) -> Ignored\n", off,  off, uValue, cb));
     1812
     1813    return VINF_SUCCESS;
     1814#endif
    12231815}
    12241816
     
    13541946        case IOMMU_MMIO_OFF_RSVD_REG:                 uReg = pThis->RsvdReg;                    break;
    13551947
    1356         case IOMMU_MMIO_CMD_BUF_HEAD_PTR:             uReg = pThis->CmdBufHeadPtr.u64;          break;
    1357         case IOMMU_MMIO_CMD_BUF_TAIL_PTR:             uReg = pThis->CmdBufTailPtr.u64;          break;
    1358         case IOMMU_MMIO_EVT_LOG_HEAD_PTR:             uReg = pThis->EvtLogHeadPtr.u64;          break;
    1359         case IOMMU_MMIO_EVT_LOG_TAIL_PTR:             uReg = pThis->EvtLogTailPtr.u64;          break;
     1948        case IOMMU_MMIO_OFF_CMD_BUF_HEAD_PTR:         uReg = pThis->CmdBufHeadPtr.u64;          break;
     1949        case IOMMU_MMIO_OFF_CMD_BUF_TAIL_PTR:         uReg = pThis->CmdBufTailPtr.u64;          break;
     1950        case IOMMU_MMIO_OFF_EVT_LOG_HEAD_PTR:         uReg = pThis->EvtLogHeadPtr.u64;          break;
     1951        case IOMMU_MMIO_OFF_EVT_LOG_TAIL_PTR:         uReg = pThis->EvtLogTailPtr.u64;          break;
    13601952
    13611953        case IOMMU_MMIO_OFF_STATUS:                   uReg = pThis->Status.u64;                 break;
     
    34224014        if (fVerbose)
    34234015        {
    3424             pHlp->pfnPrintf(pHlp, "    Base address                            = %RTbool\n", GALogBar.n.u40Base << X86_PAGE_4K_SHIFT);
     4016            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", GALogBar.n.u40Base << X86_PAGE_4K_SHIFT);
    34254017            pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
    34264018                            cEntries, cbBuffer);
     
    42244816     */
    42254817    rc = PDMDevHlpMmioCreate(pDevIns, IOMMU_MMIO_REGION_SIZE, pPciDev, 0 /* iPciRegion */, iommuAmdMmioWrite, iommuAmdMmioRead,
    4226                              NULL /* pvUser */, IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED,
     4818                             NULL /* pvUser */, IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING,
    42274819                             "AMD-IOMMU", &pThis->hMmio);
    42284820    AssertLogRelRCReturn(rc, rc);
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