VirtualBox

Changeset 83681 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 13, 2020 4:38:52 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
137176
Message:

AMD IOMMU: bugref:9654 Bits.

File:
1 edited

Legend:

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

    r83669 r83681  
    16581658} CMD_BUF_HEAD_PTR_T;
    16591659AssertCompileSize(CMD_BUF_HEAD_PTR_T, 8);
     1660#define IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK       UINT64_C(0x000000000007fff0)
    16601661
    16611662/**
     
    16651666 */
    16661667typedef CMD_BUF_HEAD_PTR_T    CMD_BUF_TAIL_PTR_T;
     1668#define IOMMU_CMD_BUF_TAIL_PTR_VALID_MASK       UINT64_C(0x000000000007fff0)
     1669
    16671670
    16681671/**
     
    18451848    /** The MMIO handle. */
    18461849    IOMMMIOHANDLE               hMmio;
     1850    /** The event semaphore the command thread waits on. */
     1851    SUPSEMEVENT                 hEvtCmdThread;
    18471852
    18481853    /** @name MMIO: Control and status registers.
     
    19811986{
    19821987    /** The IOMMU helpers. */
    1983     PCPDMIOMMUHLPR3     pIommuHlp;
     1988    PCPDMIOMMUHLPR3         pIommuHlp;
     1989    /** The command thread handle. */
     1990    R3PTRTYPE(PPDMTHREAD)   pCmdThread;
    19841991} IOMMUR3;
    19851992/** Pointer to the ring-3 IOMMU device state. */
     
    19921999{
    19932000    /** The IOMMU helpers. */
    1994     PCPDMIOMMUHLPR0     pIommuHlp;
     2001    PCPDMIOMMUHLPR0         pIommuHlp;
    19952002} IOMMUR0;
    19962003/** Pointer to the ring-0 IOMMU device state. */
     
    20032010{
    20042011    /** The IOMMU helpers. */
    2005     PCPDMIOMMUHLPRC     pIommuHlp;
     2012    PCPDMIOMMUHLPRC         pIommuHlp;
    20062013} IOMMURC;
    20072014/** Pointer to the raw-mode IOMMU device state. */
     
    21882195    pThis->MsiData.u32 = u64Value & IOMMU_MSI_DATA_VALID_MASK;
    21892196    return VINF_SUCCESS;
     2197}
     2198
     2199
     2200/**
     2201 * Writes the Command Buffer Head Pointer Register (32-bit).
     2202 */
     2203static VBOXSTRICTRC iommuAmdCmdBufHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     2204{
     2205    RT_NOREF(pDevIns, iReg);
     2206
     2207    /*
     2208     * IOMMU behavior is undefined when software writes this register when the command buffer is running.
     2209     * In our emulation, we ignore the write entirely.
     2210     * See AMD IOMMU spec. 3.3.13 "Command and Event Log Pointer Registers".
     2211     */
     2212    IOMMU_STATUS_T const Status = pThis->Status;
     2213    if (Status.n.u1CmdBufRunning)
     2214    {
     2215        Log((IOMMU_LOG_PFX ": Setting CmdBufHeadPtr (%#RX64) when command buffer is running -> Ignored\n", u64Value));
     2216        return VINF_SUCCESS;
     2217    }
     2218
     2219    /*
     2220     * IOMMU behavior is undefined when software writes a value value outside the buffer length.
     2221     * In our emtulation, we ignore the write entirely.
     2222     */
     2223    uint32_t const      offBuf     = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
     2224    CMD_BUF_BAR_T const CmdBufBar  = pThis->CmdBufBaseAddr;
     2225    uint32_t            cbBuf;
     2226    iommuAmdDecodeBufferLength(CmdBufBar.n.u4CmdLen, NULL, &cbBuf);
     2227    if (offBuf >= cbBuf)
     2228    {
     2229        Log((IOMMU_LOG_PFX ": Setting CmdBufHeadPtr (%#RX32) to a value that exceeds buffer length -> Ignored\n", offBuf, cbBuf));
     2230        return VINF_SUCCESS;
     2231    }
     2232
     2233    pThis->CmdBufHeadPtr.u64 = offBuf;
     2234    LogFlow((IOMMU_LOG_PFX ": Set CmdBufHeadPtr to %#RX32\n", offBuf));
     2235    return VINF_SUCCESS;
     2236}
     2237
     2238
     2239/**
     2240 * Writes the Command Buffer Tail Pointer Register (32-bit).
     2241 */
     2242static VBOXSTRICTRC iommuAmdCmdBufTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     2243{
     2244    RT_NOREF(pDevIns, iReg);
     2245
     2246    /*
     2247     * IOMMU behavior is undefined when software advances this register equal or beyond its head pointer.
     2248     * In our emulation, we ignore the write entirely.
     2249     * See AMD IOMMU spec. 3.3.13 "Command and Event Log Pointer Registers".
     2250     */
     2251    uint32_t const offBufTail = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
     2252    NOREF(offBufTail);
     2253    NOREF(pThis);
     2254    return VINF_SUCCESS;
     2255}
     2256
     2257
     2258/**
     2259 * Writes the Event Log Head Pointer Register (32-bit).
     2260 */
     2261static VBOXSTRICTRC iommuAmdEvtLogHeadPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     2262{
     2263    RT_NOREF(pDevIns, iReg);
     2264    NOREF(pThis);
     2265    NOREF(u64Value);
     2266    return VINF_SUCCESS;
     2267}
     2268
     2269
     2270/**
     2271 * Writes the Event Log Tail Pointer Register (32-bit).
     2272 */
     2273static VBOXSTRICTRC iommuAmdEvtLogTailPtr_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t u64Value)
     2274{
     2275    RT_NOREF(pDevIns, iReg);
     2276    NOREF(pThis);
     2277    NOREF(u64Value);
     2278    return VINF_SUCCESS;
     2279}
     2280
     2281
     2282/**
     2283 * The IOMMU command thread.
     2284 *
     2285 * @returns VBox status code.
     2286 * @param   pDevIns     The device instance.
     2287 * @param   pThread     The command thread.
     2288 */
     2289static DECLCALLBACK(int) iommuAmdR3CmdThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     2290{
     2291    RT_NOREF(pDevIns, pThread);
     2292}
     2293
     2294
     2295/**
     2296 * Unblocks the command thread so it can respond to a state change.
     2297 *
     2298 * @returns VBox status code.
     2299 * @param   pDevIns     The device instance.
     2300 * @param   pThread     The command thread.
     2301 */
     2302static DECLCALLBACK(int) iommuAmdR3CmdThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     2303{
     2304    RT_NOREF(pDevIns, pThread);
    21902305}
    21912306
     
    23022417        case IOMMU_MMIO_OFF_RSVD_REG:            return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
    23032418
    2304         case IOMMU_MMIO_CMD_BUF_HEAD_PTR:
    2305         case IOMMU_MMIO_CMD_BUF_TAIL_PTR:
    2306         case IOMMU_MMIO_EVT_LOG_HEAD_PTR:
    2307         case IOMMU_MMIO_EVT_LOG_TAIL_PTR:
     2419        case IOMMU_MMIO_CMD_BUF_HEAD_PTR:        return iommuAmdCmdBufHeadPtr_w(pDevIns, pThis, off, uValue);
     2420        case IOMMU_MMIO_CMD_BUF_TAIL_PTR:        return iommuAmdCmdBufTailPtr_w(pDevIns, pThis, off, uValue);
     2421        case IOMMU_MMIO_EVT_LOG_HEAD_PTR:        return iommuAmdEvtLogHeadPtr_w(pDevIns, pThis, off, uValue);
     2422        case IOMMU_MMIO_EVT_LOG_TAIL_PTR:        return iommuAmdEvtLogTailPtr_w(pDevIns, pThis, off, uValue);
    23082423
    23092424        case IOMMU_MMIO_OFF_STATUS:
     
    23192434
    23202435        case IOMMU_MMIO_OFF_EVT_LOG_B_HEAD_PTR:
    2321         case IOMMU_MMIO_OFF_EVT_LOG_B_TAIL_PTR:
     2436        case IOMMU_MMIO_OFF_EVT_LOG_B_TAIL_PTR:  return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
    23222437
    23232438        case IOMMU_MMIO_OFF_PPR_LOG_AUTO_RESP:
     
    25132628
    25142629# ifdef IN_RING3
    2515 
    2516 /**
    2517  * Resets read-write portions of the IOMMU state.
    2518  *
    2519  * State data not initialized here is expected to be initialized in the construct
    2520  * callback and remain read-only through the lifetime of the VM.
    2521  *
    2522  * @param   pDevIns   The device instance.
    2523  */
    2524 static void iommuAmdR3Init(PPDMDEVINS pDevIns)
    2525 {
     2630/**
     2631 * @callback_method_impl{FNPCICONFIGREAD}
     2632 */
     2633static DECLCALLBACK(VBOXSTRICTRC) iommuAmdR3PciConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress,
     2634                                                          unsigned cb, uint32_t *pu32Value)
     2635{
     2636    /** @todo IOMMU: PCI config read stat counter. */
     2637    VBOXSTRICTRC rcStrict = PDMDevHlpPCIConfigRead(pDevIns, pPciDev, uAddress, cb, pu32Value);
     2638    Log3((IOMMU_LOG_PFX ": PCI config read: At %#x (%u) -> %#x %Rrc\n", uAddress, cb, *pu32Value, VBOXSTRICTRC_VAL(rcStrict)));
     2639    return rcStrict;
     2640}
     2641
     2642
     2643/**
     2644 * @callback_method_impl{FNPCICONFIGWRITE}
     2645 */
     2646static DECLCALLBACK(VBOXSTRICTRC) iommuAmdR3PciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress,
     2647                                                           unsigned cb, uint32_t u32Value)
     2648{
     2649    /** @todo IOMMU: PCI config write. */
     2650    VBOXSTRICTRC rcStrict = PDMDevHlpPCIConfigWrite(pDevIns, pPciDev, uAddress, cb, u32Value);
     2651    Log3((IOMMU_LOG_PFX ": PCI config write: %#x -> To %#x (%u) %Rrc\n", u32Value, uAddress, cb, VBOXSTRICTRC_VAL(rcStrict)));
     2652    return rcStrict;
     2653}
     2654
     2655
     2656/**
     2657 * @callback_method_impl{FNDBGFHANDLERDEV}
     2658 */
     2659static DECLCALLBACK(void) iommuAmdR3DbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     2660{
     2661    PCIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     2662    Assert(pThis);
     2663
     2664    LogFlow((IOMMU_LOG_PFX ": iommuAmdR3DbgInfo: pThis=%p pszArgs=%s\n", pThis, pszArgs));
     2665    bool const fVerbose = !strncmp(pszArgs, RT_STR_TUPLE("verbose")) ? true : false;
     2666
     2667    pHlp->pfnPrintf(pHlp, "AMD-IOMMU:\n");
     2668    /* Device Table Base Address. */
     2669    {
     2670        DEV_TAB_BAR_T const DevTabBar = pThis->DevTabBaseAddr;
     2671        pHlp->pfnPrintf(pHlp, "  Device Table BAR                        = %#RX64\n", DevTabBar.u64);
     2672        if (fVerbose)
     2673        {
     2674            pHlp->pfnPrintf(pHlp, "    Size                                    = %u (%u bytes)\n", DevTabBar.n.u9Size,
     2675                        (DevTabBar.n.u9Size + 1) * _4K);
     2676            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", DevTabBar.n.u40DevTabBase);
     2677        }
     2678    }
     2679    /* Command Buffer Base Address Register. */
     2680    {
     2681        CMD_BUF_BAR_T const CmdBufBar = pThis->CmdBufBaseAddr;
     2682        uint32_t      cEntries;
     2683        uint32_t      cbBuffer;
     2684        uint8_t const uEncodedLen = CmdBufBar.n.u4CmdLen;
     2685        iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     2686        pHlp->pfnPrintf(pHlp, "  Command buffer BAR                      = %#RX64\n", CmdBufBar.u64);
     2687        if (fVerbose)
     2688        {
     2689            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", CmdBufBar.n.u40CmdBase);
     2690            pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
     2691                            cEntries, cbBuffer);
     2692        }
     2693    }
     2694    /* Event Log Base Address Register. */
     2695    {
     2696        EVT_LOG_BAR_T const EvtLogBar = pThis->EvtLogBaseAddr;
     2697        uint32_t      cEntries;
     2698        uint32_t      cbBuffer;
     2699        uint8_t const uEncodedLen = EvtLogBar.n.u4EvtLen;
     2700        iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     2701        pHlp->pfnPrintf(pHlp, "  Event log BAR                           = %#RX64\n", EvtLogBar.u64);
     2702        if (fVerbose)
     2703        {
     2704            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", EvtLogBar.n.u40EvtBase);
     2705            pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
     2706                            cEntries, cbBuffer);
     2707        }
     2708    }
     2709    /* IOMMU Control Register. */
     2710    {
     2711        IOMMU_CTRL_T const Ctrl = pThis->Ctrl;
     2712        pHlp->pfnPrintf(pHlp, "  Control                                 = %#RX64\n", Ctrl.u64);
     2713        if (fVerbose)
     2714        {
     2715            pHlp->pfnPrintf(pHlp, "    IOMMU enable                            = %RTbool\n", Ctrl.n.u1IommuEn);
     2716            pHlp->pfnPrintf(pHlp, "    HT Tunnel translation enable            = %RTbool\n", Ctrl.n.u1HtTunEn);
     2717            pHlp->pfnPrintf(pHlp, "    Event log enable                        = %RTbool\n", Ctrl.n.u1EvtLogEn);
     2718            pHlp->pfnPrintf(pHlp, "    Event log interrupt enable              = %RTbool\n", Ctrl.n.u1EvtIntrEn);
     2719            pHlp->pfnPrintf(pHlp, "    Completion wait interrupt enable        = %RTbool\n", Ctrl.n.u1EvtIntrEn);
     2720            pHlp->pfnPrintf(pHlp, "    Invalidation timeout                    = %u\n",      Ctrl.n.u3InvTimeOut);
     2721            pHlp->pfnPrintf(pHlp, "    Pass posted write                       = %RTbool\n", Ctrl.n.u1PassPW);
     2722            pHlp->pfnPrintf(pHlp, "    Respose Pass posted write               = %RTbool\n", Ctrl.n.u1ResPassPW);
     2723            pHlp->pfnPrintf(pHlp, "    Coherent                                = %RTbool\n", Ctrl.n.u1Coherent);
     2724            pHlp->pfnPrintf(pHlp, "    Isochronous                             = %RTbool\n", Ctrl.n.u1Isoc);
     2725            pHlp->pfnPrintf(pHlp, "    Command buffer enable                   = %RTbool\n", Ctrl.n.u1CmdBufEn);
     2726            pHlp->pfnPrintf(pHlp, "    PPR log enable                          = %RTbool\n", Ctrl.n.u1PprLogEn);
     2727            pHlp->pfnPrintf(pHlp, "    PPR interrupt enable                    = %RTbool\n", Ctrl.n.u1PprIntrEn);
     2728            pHlp->pfnPrintf(pHlp, "    PPR enable                              = %RTbool\n", Ctrl.n.u1PprEn);
     2729            pHlp->pfnPrintf(pHlp, "    Guest translation eanble                = %RTbool\n", Ctrl.n.u1GstTranslateEn);
     2730            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC enable               = %RTbool\n", Ctrl.n.u1GstVirtApicEn);
     2731            pHlp->pfnPrintf(pHlp, "    CRW                                     = %#x\n",     Ctrl.n.u4Crw);
     2732            pHlp->pfnPrintf(pHlp, "    SMI filter enable                       = %RTbool\n", Ctrl.n.u1SmiFilterEn);
     2733            pHlp->pfnPrintf(pHlp, "    Self-writeback disable                  = %RTbool\n", Ctrl.n.u1SelfWriteBackDis);
     2734            pHlp->pfnPrintf(pHlp, "    SMI filter log enable                   = %RTbool\n", Ctrl.n.u1SmiFilterLogEn);
     2735            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC mode enable          = %#x\n",     Ctrl.n.u3GstVirtApicModeEn);
     2736            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC GA log enable        = %RTbool\n", Ctrl.n.u1GstLogEn);
     2737            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC interrupt enable     = %RTbool\n", Ctrl.n.u1GstIntrEn);
     2738            pHlp->pfnPrintf(pHlp, "    Dual PPR log enable                     = %#x\n",     Ctrl.n.u2DualPprLogEn);
     2739            pHlp->pfnPrintf(pHlp, "    Dual event log enable                   = %#x\n",     Ctrl.n.u2DualEvtLogEn);
     2740            pHlp->pfnPrintf(pHlp, "    Device table segmentation enable        = %#x\n",     Ctrl.n.u3DevTabSegEn);
     2741            pHlp->pfnPrintf(pHlp, "    Privilege abort enable                  = %#x\n",     Ctrl.n.u2PrivAbortEn);
     2742            pHlp->pfnPrintf(pHlp, "    PPR auto response enable                = %RTbool\n", Ctrl.n.u1PprAutoRespEn);
     2743            pHlp->pfnPrintf(pHlp, "    MARC enable                             = %RTbool\n", Ctrl.n.u1MarcEn);
     2744            pHlp->pfnPrintf(pHlp, "    Block StopMark enable                   = %RTbool\n", Ctrl.n.u1BlockStopMarkEn);
     2745            pHlp->pfnPrintf(pHlp, "    PPR auto response always-on enable      = %RTbool\n", Ctrl.n.u1PprAutoRespAlwaysOnEn);
     2746            pHlp->pfnPrintf(pHlp, "    Domain IDPNE                            = %RTbool\n", Ctrl.n.u1DomainIDPNE);
     2747            pHlp->pfnPrintf(pHlp, "    Enhanced PPR handling                   = %RTbool\n", Ctrl.n.u1EnhancedPpr);
     2748            pHlp->pfnPrintf(pHlp, "    Host page table access/dirty bit update = %#x\n",     Ctrl.n.u2HstAccDirtyBitUpdate);
     2749            pHlp->pfnPrintf(pHlp, "    Guest page table dirty bit disable      = %RTbool\n", Ctrl.n.u1GstDirtyUpdateDis);
     2750            pHlp->pfnPrintf(pHlp, "    x2APIC enable                           = %RTbool\n", Ctrl.n.u1X2ApicEn);
     2751            pHlp->pfnPrintf(pHlp, "    x2APIC interrupt enable                 = %RTbool\n", Ctrl.n.u1X2ApicIntrGenEn);
     2752            pHlp->pfnPrintf(pHlp, "    Guest page table access bit update      = %RTbool\n", Ctrl.n.u1GstAccessUpdateDis);
     2753        }
     2754    }
     2755    /* Exclusion Base Address Register. */
     2756    {
     2757        IOMMU_EXCL_RANGE_BAR_T const ExclRangeBar = pThis->ExclRangeBaseAddr;
     2758        pHlp->pfnPrintf(pHlp, "  Exclusion BAR                           = %#RX64\n", ExclRangeBar.u64);
     2759        if (fVerbose)
     2760        {
     2761            pHlp->pfnPrintf(pHlp, "    Exclusion enable                        = %RTbool\n", ExclRangeBar.n.u1ExclEnable);
     2762            pHlp->pfnPrintf(pHlp, "    Allow all devices                       = %RTbool\n", ExclRangeBar.n.u1AllowAll);
     2763            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", ExclRangeBar.n.u40ExclRangeBase);
     2764        }
     2765    }
     2766    /* Exclusion Range Limit Register. */
     2767    {
     2768        IOMMU_EXCL_RANGE_LIMIT_T const ExclRangeLimit = pThis->ExclRangeLimit;
     2769        pHlp->pfnPrintf(pHlp, "  Exclusion Range Limit                   = %#RX64\n", ExclRangeLimit.u64);
     2770        if (fVerbose)
     2771            pHlp->pfnPrintf(pHlp, "    Range limit                             = %#RX64\n", ExclRangeLimit.n.u40ExclLimit);
     2772    }
     2773    /* Extended Feature Register. */
     2774    {
     2775        IOMMU_EXT_FEAT_T ExtFeat = pThis->ExtFeat;
     2776        pHlp->pfnPrintf(pHlp, "  Extended Feature Register               = %#RX64\n", ExtFeat.u64);
     2777        pHlp->pfnPrintf(pHlp, "    Prefetch support                        = %RTbool\n", ExtFeat.n.u1PrefetchSup);
     2778        if (fVerbose)
     2779        {
     2780            pHlp->pfnPrintf(pHlp, "    PPR support                             = %RTbool\n", ExtFeat.n.u1PprSup);
     2781            pHlp->pfnPrintf(pHlp, "    x2APIC support                          = %RTbool\n", ExtFeat.n.u1X2ApicSup);
     2782            pHlp->pfnPrintf(pHlp, "    NX and privilege level support          = %RTbool\n", ExtFeat.n.u1NoExecuteSup);
     2783            pHlp->pfnPrintf(pHlp, "    Guest translation support               = %RTbool\n", ExtFeat.n.u1GstTranslateSup);
     2784            pHlp->pfnPrintf(pHlp, "    Invalidate-All command support          = %RTbool\n", ExtFeat.n.u1InvAllSup);
     2785            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC support              = %RTbool\n", ExtFeat.n.u1GstVirtApicSup);
     2786            pHlp->pfnPrintf(pHlp, "    Hardware error register support         = %RTbool\n", ExtFeat.n.u1HwErrorSup);
     2787            pHlp->pfnPrintf(pHlp, "    Performance counters support            = %RTbool\n", ExtFeat.n.u1PerfCounterSup);
     2788            pHlp->pfnPrintf(pHlp, "    Host address translation size           = %#x\n",     ExtFeat.n.u2HostAddrTranslateSize);
     2789            pHlp->pfnPrintf(pHlp, "    Guest address translation size          = %#x\n",     ExtFeat.n.u2GstAddrTranslateSize);
     2790            pHlp->pfnPrintf(pHlp, "    Guest CR3 root table level support      = %#x\n",     ExtFeat.n.u2GstCr3RootTblLevel);
     2791            pHlp->pfnPrintf(pHlp, "    SMI filter register support             = %#x\n",     ExtFeat.n.u2SmiFilterSup);
     2792            pHlp->pfnPrintf(pHlp, "    SMI filter register count               = %#x\n",     ExtFeat.n.u3SmiFilterCount);
     2793            pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC modes support        = %#x\n",     ExtFeat.n.u3GstVirtApicModeSup);
     2794            pHlp->pfnPrintf(pHlp, "    Dual PPR log support                    = %#x\n",     ExtFeat.n.u2DualPprLogSup);
     2795            pHlp->pfnPrintf(pHlp, "    Dual event log support                  = %#x\n",     ExtFeat.n.u2DualEvtLogSup);
     2796            pHlp->pfnPrintf(pHlp, "    Maximum PASID                           = %#x\n",     ExtFeat.n.u5MaxPasidSup);
     2797            pHlp->pfnPrintf(pHlp, "    User/supervisor page protection support = %RTbool\n", ExtFeat.n.u1UserSupervisorSup);
     2798            pHlp->pfnPrintf(pHlp, "    Device table segments supported         = %u\n",      (ExtFeat.n.u2DevTabSegSup << 1));
     2799            pHlp->pfnPrintf(pHlp, "    PPR log overflow early warning support  = %RTbool\n", ExtFeat.n.u1PprLogOverflowWarn);
     2800            pHlp->pfnPrintf(pHlp, "    PPR auto response support               = %RTbool\n", ExtFeat.n.u1PprAutoRespSup);
     2801            pHlp->pfnPrintf(pHlp, "    MARC support                            = %#x\n",     ExtFeat.n.u2MarcSup);
     2802            pHlp->pfnPrintf(pHlp, "    Block StopMark message support          = %RTbool\n", ExtFeat.n.u1BlockStopMarkSup);
     2803            pHlp->pfnPrintf(pHlp, "    Performance optimization support        = %RTbool\n", ExtFeat.n.u1PerfOptSup);
     2804            pHlp->pfnPrintf(pHlp, "    MSI capability MMIO access support      = %RTbool\n", ExtFeat.n.u1MsiCapMmioSup);
     2805            pHlp->pfnPrintf(pHlp, "    Guest I/O protection support            = %RTbool\n", ExtFeat.n.u1GstIoSup);
     2806            pHlp->pfnPrintf(pHlp, "    Host access support                     = %RTbool\n", ExtFeat.n.u1HostAccessSup);
     2807            pHlp->pfnPrintf(pHlp, "    Enhanced PPR handling support           = %RTbool\n", ExtFeat.n.u1EnhancedPprSup);
     2808            pHlp->pfnPrintf(pHlp, "    Attribute forward supported             = %RTbool\n", ExtFeat.n.u1AttrForwardSup);
     2809            pHlp->pfnPrintf(pHlp, "    Host dirty support                      = %RTbool\n", ExtFeat.n.u1HostDirtySup);
     2810            pHlp->pfnPrintf(pHlp, "    Invalidate IOTLB type support           = %RTbool\n", ExtFeat.n.u1InvIoTlbTypeSup);
     2811            pHlp->pfnPrintf(pHlp, "    Guest page table access bit hw disable  = %RTbool\n", ExtFeat.n.u1GstUpdateDisSup);
     2812            pHlp->pfnPrintf(pHlp, "    Force physical dest for remapped intr.  = %RTbool\n", ExtFeat.n.u1ForcePhysDstSup);
     2813        }
     2814    }
     2815    /* PPR Log Base Address Register. */
     2816    {
     2817        PPR_LOG_BAR_T PprLogBar = pThis->PprLogBaseAddr;
     2818        uint32_t      cEntries;
     2819        uint32_t      cbBuffer;
     2820        uint8_t const uEncodedLen = PprLogBar.n.u4PprLogLen;
     2821        iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     2822        pHlp->pfnPrintf(pHlp, "  PPR Log BAR                             = %#RX64\n",   PprLogBar.u64);
     2823        if (fVerbose)
     2824        {
     2825            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", PprLogBar.n.u40PprLogBase);
     2826            pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
     2827                            cEntries, cbBuffer);
     2828        }
     2829    }
     2830    /* Hardware Event (Hi) Register. */
     2831    {
     2832        IOMMU_HW_EVT_HI_T HwEvtHi = pThis->HwEvtHi;
     2833        pHlp->pfnPrintf(pHlp, "  Hardware Event (Hi)                     = %#RX64\n",   HwEvtHi.u64);
     2834        if (fVerbose)
     2835        {
     2836            pHlp->pfnPrintf(pHlp, "    First operand                           = %#RX64\n", HwEvtHi.n.u60FirstOperand);
     2837            pHlp->pfnPrintf(pHlp, "    Event code                              = %#RX8\n",  HwEvtHi.n.u4EvtCode);
     2838        }
     2839    }
     2840    /* Hardware Event (Lo) Register. */
     2841    pHlp->pfnPrintf(pHlp, "  Hardware Event (Lo)                         = %#RX64\n", pThis->HwEvtLo);
     2842    /* Hardware Event Status. */
     2843    {
     2844        IOMMU_HW_EVT_STATUS_T HwEvtStatus = pThis->HwEvtStatus;
     2845        pHlp->pfnPrintf(pHlp, "  Hardware Event Status                   = %#RX64\n",    HwEvtStatus.u64);
     2846        if (fVerbose)
     2847        {
     2848            pHlp->pfnPrintf(pHlp, "    Valid                                   = %RTbool\n", HwEvtStatus.n.u1Valid);
     2849            pHlp->pfnPrintf(pHlp, "    Overflow                                = %RTbool\n", HwEvtStatus.n.u1Overflow);
     2850        }
     2851    }
     2852    /* Guest Virtual-APIC Log Base Address Register. */
     2853    {
     2854        GALOG_BAR_T const GALogBar = pThis->GALogBaseAddr;
     2855        uint32_t      cEntries;
     2856        uint32_t      cbBuffer;
     2857        uint8_t const uEncodedLen = GALogBar.n.u4GALogLen;
     2858        iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     2859        pHlp->pfnPrintf(pHlp, "  Guest Log BAR                           = %#RX64\n",    GALogBar.u64);
     2860        if (fVerbose)
     2861        {
     2862            pHlp->pfnPrintf(pHlp, "    Base address                            = %RTbool\n", GALogBar.n.u40GALogBase);
     2863            pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
     2864                            cEntries, cbBuffer);
     2865        }
     2866    }
     2867    /* Guest Virtual-APIC Log Tail Address Register. */
     2868    {
     2869        GALOG_TAIL_ADDR_T GALogTail = pThis->GALogTailAddr;
     2870        pHlp->pfnPrintf(pHlp, "  Guest Log Tail Address                  = %#RX64\n",   GALogTail.u64);
     2871        if (fVerbose)
     2872            pHlp->pfnPrintf(pHlp, "    Tail address                            = %#RX64\n", GALogTail.n.u40GALogTailAddr);
     2873    }
     2874    /* PPR Log B Base Address Register. */
     2875    {
     2876        PPR_LOG_B_BAR_T PprLogBBar = pThis->PprLogBBaseAddr;
     2877        uint32_t      cEntries;
     2878        uint32_t      cbBuffer;
     2879        uint8_t const uEncodedLen = PprLogBBar.n.u4PprLogLen;
     2880        iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     2881        pHlp->pfnPrintf(pHlp, "  PPR Log B BAR                           = %#RX64\n",   PprLogBBar.u64);
     2882        if (fVerbose)
     2883        {
     2884            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", PprLogBBar.n.u40PprLogBase);
     2885            pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
     2886                            cEntries, cbBuffer);
     2887        }
     2888    }
     2889    /* Event Log B Base Address Register. */
     2890    {
     2891        EVT_LOG_B_BAR_T EvtLogBBar = pThis->EvtLogBBaseAddr;
     2892        uint32_t      cEntries;
     2893        uint32_t      cbBuffer;
     2894        uint8_t const uEncodedLen = EvtLogBBar.n.u4EvtLen;
     2895        iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
     2896        pHlp->pfnPrintf(pHlp, "  Event Log B BAR                         = %#RX64\n",   EvtLogBBar.u64);
     2897        if (fVerbose)
     2898        {
     2899            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", EvtLogBBar.n.u40EvtBase);
     2900            pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
     2901                            cEntries, cbBuffer);
     2902        }
     2903    }
     2904    /* Device Table Segment Registers. */
     2905    for (unsigned i = 0; i < RT_ELEMENTS(pThis->DevTabSeg); i++)
     2906    {
     2907        DEV_TAB_SEG_BAR_T const DevTabSeg = pThis->DevTabSeg[i];
     2908        pHlp->pfnPrintf(pHlp, "  Device Table Segment BAR [%u]            = %#RX64\n",  DevTabSeg.u64);
     2909        if (fVerbose)
     2910        {
     2911            pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", DevTabSeg.n.u40DevTabBase);
     2912            pHlp->pfnPrintf(pHlp, "    Size                                    = %#x (%u bytes)\n", DevTabSeg.n.u8Size,
     2913                            (DevTabSeg.n.u8Size + 1) << X86_PAGE_4K_SHIFT);
     2914        }
     2915    }
     2916    /* Device-Specific Feature Extension Register. */
     2917    {
     2918        DEV_SPECIFIC_FEAT_T const DevSpecificFeat = pThis->DevSpecificFeat;
     2919        pHlp->pfnPrintf(pHlp, "  Device-specific Feature                 = %#RX64\n",   DevSpecificFeat.u64);
     2920        if (fVerbose)
     2921        {
     2922            pHlp->pfnPrintf(pHlp, "    Feature                                 = %#RX32\n", DevSpecificFeat.n.u24DevSpecFeat);
     2923            pHlp->pfnPrintf(pHlp, "    Minor revision ID                       = %#x\n",    DevSpecificFeat.n.u4RevMinor);
     2924            pHlp->pfnPrintf(pHlp, "    Major revision ID                       = %#x\n",    DevSpecificFeat.n.u4RevMajor);
     2925        }
     2926    }
     2927    /* Device-Specific Control Extension Register. */
     2928    {
     2929        DEV_SPECIFIC_CTRL_T const DevSpecificCtrl = pThis->DevSpecificCtrl;
     2930        pHlp->pfnPrintf(pHlp, "  Device-specific Control                 = %#RX64\n",   DevSpecificCtrl.u64);
     2931        if (fVerbose)
     2932        {
     2933            pHlp->pfnPrintf(pHlp, "    Control                                 = %#RX32\n", DevSpecificCtrl.n.u24DevSpecCtrl);
     2934            pHlp->pfnPrintf(pHlp, "    Minor revision ID                       = %#x\n",    DevSpecificCtrl.n.u4RevMinor);
     2935            pHlp->pfnPrintf(pHlp, "    Major revision ID                       = %#x\n",    DevSpecificCtrl.n.u4RevMajor);
     2936        }
     2937    }
     2938    /* Device-Specific Status Extension Register. */
     2939    {
     2940        DEV_SPECIFIC_STATUS_T const DevSpecificStatus = pThis->DevSpecificStatus;
     2941        pHlp->pfnPrintf(pHlp, "  Device-specific Control                 = %#RX64\n",   DevSpecificStatus.u64);
     2942        if (fVerbose)
     2943        {
     2944            pHlp->pfnPrintf(pHlp, "    Status                                  = %#RX32\n", DevSpecificStatus.n.u24DevSpecStatus);
     2945            pHlp->pfnPrintf(pHlp, "    Minor revision ID                       = %#x\n",    DevSpecificStatus.n.u4RevMinor);
     2946            pHlp->pfnPrintf(pHlp, "    Major revision ID                       = %#x\n",    DevSpecificStatus.n.u4RevMajor);
     2947        }
     2948    }
     2949    /* MSI Miscellaneous Information Register (Lo and Hi). */
     2950    {
     2951        MSI_MISC_INFO_T const MsiMiscInfo = pThis->MsiMiscInfo;
     2952        pHlp->pfnPrintf(pHlp, "  MSI Misc. Info. Register                = %#RX64\n",    MsiMiscInfo.u64);
     2953        if (fVerbose)
     2954        {
     2955            pHlp->pfnPrintf(pHlp, "    Event Log MSI number                    = %#x\n",     MsiMiscInfo.n.u5MsiNumEvtLog);
     2956            pHlp->pfnPrintf(pHlp, "    Guest Virtual-Address Size              = %#x\n",     MsiMiscInfo.n.u3GstVirtAddrSize);
     2957            pHlp->pfnPrintf(pHlp, "    Physical Address Size                   = %#x\n",     MsiMiscInfo.n.u7PhysAddrSize);
     2958            pHlp->pfnPrintf(pHlp, "    Virtual-Address Size                    = %#x\n",     MsiMiscInfo.n.u7VirtAddrSize);
     2959            pHlp->pfnPrintf(pHlp, "    HT Transport ATS Range Reserved         = %RTbool\n", MsiMiscInfo.n.u1HtAtsResv);
     2960            pHlp->pfnPrintf(pHlp, "    PPR MSI number                          = %#x\n",     MsiMiscInfo.n.u5MsiNumPpr);
     2961            pHlp->pfnPrintf(pHlp, "    GA Log MSI number                       = %#x\n",     MsiMiscInfo.n.u5MsiNumGa);
     2962        }
     2963    }
     2964    /* MSI Capability Header. */
     2965    {
     2966        MSI_CAP_HDR_T const MsiCapHdr = pThis->MsiCapHdr;
     2967        pHlp->pfnPrintf(pHlp, "  MSI Capability Header                   = %#RX32\n",    MsiCapHdr.u32);
     2968        if (fVerbose)
     2969        {
     2970            pHlp->pfnPrintf(pHlp, "    Capability ID                           = %#x\n",     MsiCapHdr.n.u8MsiCapId);
     2971            pHlp->pfnPrintf(pHlp, "    Capability Ptr (PCI config offset)      = %#x\n",     MsiCapHdr.n.u8MsiCapPtr);
     2972            pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", MsiCapHdr.n.u1MsiEnable);
     2973            pHlp->pfnPrintf(pHlp, "    Multi-message capability                = %#x\n",     MsiCapHdr.n.u3MsiMultiMessCap);
     2974            pHlp->pfnPrintf(pHlp, "    Multi-message enable                    = %#x\n",     MsiCapHdr.n.u3MsiMultiMessEn);
     2975        }
     2976    }
     2977    /* MSI Address Register (Lo and Hi). */
     2978    {
     2979        MSI_ADDR_T const MsiAddr = pThis->MsiAddr;
     2980        pHlp->pfnPrintf(pHlp, "  MSI Address                             = %#RX64\n",   MsiAddr.u64);
     2981        if (fVerbose)
     2982            pHlp->pfnPrintf(pHlp, "    Address                                 = %#RX64\n", MsiAddr.n.u62MsiAddr);
     2983    }
     2984    /* MSI Data. */
     2985    {
     2986        MSI_DATA_T const MsiData = pThis->MsiData;
     2987        pHlp->pfnPrintf(pHlp, "  MSI Data                                = %#RX32\n", MsiData.u32);
     2988        if (fVerbose)
     2989            pHlp->pfnPrintf(pHlp, "    Data                                    = %#x\n",  MsiData.n.u16MsiData);
     2990    }
     2991    /* MSI Mapping Capability Header. */
     2992    {
     2993        MSI_MAP_CAP_HDR_T const MsiMapCapHdr = pThis->MsiMapCapHdr;
     2994        pHlp->pfnPrintf(pHlp, "  MSI Mapping Capability Header           = %#RX32\n",    MsiMapCapHdr.u32);
     2995        if (fVerbose)
     2996        {
     2997            pHlp->pfnPrintf(pHlp, "    Capability ID                           = %#x\n",     MsiMapCapHdr.n.u8MsiMapCapId);
     2998            pHlp->pfnPrintf(pHlp, "    Map enable                              = %RTbool\n", MsiMapCapHdr.n.u1MsiMapEn);
     2999            pHlp->pfnPrintf(pHlp, "    Map fixed                               = %RTbool\n", MsiMapCapHdr.n.u1MsiMapFixed);
     3000            pHlp->pfnPrintf(pHlp, "    Map capability type                     = %#x\n",     MsiMapCapHdr.n.u5MapCapType);
     3001        }
     3002    }
     3003    /* Performance Optimization Control Register. */
     3004    {
     3005        IOMMU_PERF_OPT_CTRL_T const PerfOptCtrl = pThis->PerfOptCtrl;
     3006        pHlp->pfnPrintf(pHlp, "  Performance Optimization Control        = %#RX32\n",    PerfOptCtrl.u32);
     3007        if (fVerbose)
     3008            pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", PerfOptCtrl.n.u1PerfOptEn);
     3009    }
     3010    /* XT (x2APIC) General Interrupt Control Register. */
     3011    {
     3012        IOMMU_XT_GEN_INTR_CTRL_T const XtGenIntrCtrl = pThis->XtGenIntrCtrl;
     3013        pHlp->pfnPrintf(pHlp, "  XT General Interrupt Control            = %#RX64\n", XtGenIntrCtrl.u64);
     3014        if (fVerbose)
     3015        {
     3016            pHlp->pfnPrintf(pHlp, "    Interrupt destination mode              = %s\n",
     3017                            !XtGenIntrCtrl.n.u1X2ApicIntrDstMode ? "physical" : "logical");
     3018            pHlp->pfnPrintf(pHlp, "    Interrupt destination                   = %#RX64\n",
     3019                            RT_MAKE_U64(XtGenIntrCtrl.n.u24X2ApicIntrDstLo, XtGenIntrCtrl.n.u7X2ApicIntrDstHi));
     3020            pHlp->pfnPrintf(pHlp, "    Interrupt vector                        = %#x\n", XtGenIntrCtrl.n.u8X2ApicIntrVector);
     3021            pHlp->pfnPrintf(pHlp, "    Interrupt delivery mode                 = %#x\n",
     3022                            !XtGenIntrCtrl.n.u8X2ApicIntrVector ? "fixed" : "arbitrated");
     3023        }
     3024    }
     3025    /* XT (x2APIC) PPR Interrupt Control Register. */
     3026    {
     3027        IOMMU_XT_PPR_INTR_CTRL_T const XtPprIntrCtrl = pThis->XtPprIntrCtrl;
     3028        pHlp->pfnPrintf(pHlp, "  XT PPR Interrupt Control                = %#RX64\n", XtPprIntrCtrl.u64);
     3029        if (fVerbose)
     3030        {
     3031            pHlp->pfnPrintf(pHlp, "   Interrupt destination mode               = %s\n",
     3032                            !XtPprIntrCtrl.n.u1X2ApicIntrDstMode ? "physical" : "logical");
     3033            pHlp->pfnPrintf(pHlp, "   Interrupt destination                    = %#RX64\n",
     3034                            RT_MAKE_U64(XtPprIntrCtrl.n.u24X2ApicIntrDstLo, XtPprIntrCtrl.n.u7X2ApicIntrDstHi));
     3035            pHlp->pfnPrintf(pHlp, "   Interrupt vector                         = %#x\n", XtPprIntrCtrl.n.u8X2ApicIntrVector);
     3036            pHlp->pfnPrintf(pHlp, "   Interrupt delivery mode                  = %#x\n",
     3037                            !XtPprIntrCtrl.n.u8X2ApicIntrVector ? "fixed" : "arbitrated");
     3038        }
     3039    }
     3040    /* XT (X2APIC) GA Log Interrupt Control Register. */
     3041    {
     3042        IOMMU_XT_GALOG_INTR_CTRL_T const XtGALogIntrCtrl = pThis->XtGALogIntrCtrl;
     3043        pHlp->pfnPrintf(pHlp, "  XT PPR Interrupt Control                = %#RX64\n", XtGALogIntrCtrl.u64);
     3044        if (fVerbose)
     3045        {
     3046            pHlp->pfnPrintf(pHlp, "    Interrupt destination mode              = %s\n",
     3047                            !XtGALogIntrCtrl.n.u1X2ApicIntrDstMode ? "physical" : "logical");
     3048            pHlp->pfnPrintf(pHlp, "    Interrupt destination                   = %#RX64\n",
     3049                            RT_MAKE_U64(XtGALogIntrCtrl.n.u24X2ApicIntrDstLo, XtGALogIntrCtrl.n.u7X2ApicIntrDstHi));
     3050            pHlp->pfnPrintf(pHlp, "    Interrupt vector                        = %#x\n", XtGALogIntrCtrl.n.u8X2ApicIntrVector);
     3051            pHlp->pfnPrintf(pHlp, "    Interrupt delivery mode                 = %#x\n",
     3052                            !XtGALogIntrCtrl.n.u8X2ApicIntrVector ? "fixed" : "arbitrated");
     3053        }
     3054    }
     3055    /* MARC Registers. */
     3056    {
     3057        for (unsigned i = 0; i < RT_ELEMENTS(pThis->aMarcApers); i++)
     3058        {
     3059            pHlp->pfnPrintf(pHlp, " MARC Aperature %u:\n", i);
     3060            MARC_APER_BAR_T const MarcAperBar = pThis->aMarcApers[i].Base;
     3061            pHlp->pfnPrintf(pHlp, "   Base    = %#RX64 (addr: %#RX64)\n", MarcAperBar.u64, MarcAperBar.n.u40MarcBaseAddr);
     3062
     3063            MARC_APER_RELOC_T const MarcAperReloc = pThis->aMarcApers[i].Reloc;
     3064            pHlp->pfnPrintf(pHlp, "   Reloc   = %#RX64 (addr: %#RX64, read-only: %RTbool, enable: %RTbool)\n",
     3065                            MarcAperReloc.u64, MarcAperReloc.n.u40MarcRelocAddr, MarcAperReloc.n.u1ReadOnly,
     3066                            MarcAperReloc.n.u1RelocEn);
     3067
     3068            MARC_APER_LEN_T const MarcAperLen = pThis->aMarcApers[i].Length;
     3069            pHlp->pfnPrintf(pHlp, "   Length  = %u pages\n", MarcAperLen.n.u40MarcLength);
     3070        }
     3071    }
     3072    /* Reserved Register. */
     3073    pHlp->pfnPrintf(pHlp, "  Reserved Register                           = %#RX64\n", pThis->RsvdReg);
     3074    /* Command Buffer Head Pointer Register. */
     3075    {
     3076        CMD_BUF_HEAD_PTR_T const CmdBufHeadPtr = pThis->CmdBufHeadPtr;
     3077        pHlp->pfnPrintf(pHlp, "  Command Buffer Head Pointer             = %#RX64\n", CmdBufHeadPtr.u64);
     3078        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufHeadPtr.n.u15Ptr);
     3079    }
     3080    /* Command Buffer Tail Pointer Register. */
     3081    {
     3082        CMD_BUF_HEAD_PTR_T const CmdBufTailPtr = pThis->CmdBufTailPtr;
     3083        pHlp->pfnPrintf(pHlp, "  Command Buffer Tail Pointer             = %#RX64\n", CmdBufTailPtr.u64);
     3084        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufTailPtr.n.u15Ptr);
     3085    }
     3086    /* Event Log Head Pointer Register. */
     3087    {
     3088        EVT_LOG_HEAD_PTR_T const EvtLogHeadPtr = pThis->EvtLogHeadPtr;
     3089        pHlp->pfnPrintf(pHlp, "  Event Log Head Pointer                  = %#RX64\n", EvtLogHeadPtr.u64);
     3090        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogHeadPtr.n.u15Ptr);
     3091    }
     3092    /* Event Log Tail Pointer Register. */
     3093    {
     3094        EVT_LOG_TAIL_PTR_T const EvtLogTailPtr = pThis->EvtLogTailPtr;
     3095        pHlp->pfnPrintf(pHlp, "  Event Log Head Pointer                  = %#RX64\n", EvtLogTailPtr.u64);
     3096        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogTailPtr.n.u15Ptr);
     3097    }
     3098    /* Status Register. */
     3099    {
     3100        IOMMU_STATUS_T const Status = pThis->Status;
     3101        pHlp->pfnPrintf(pHlp, "  Status Register                         = %#RX64\n", Status.u64);
     3102        if (fVerbose)
     3103        {
     3104            pHlp->pfnPrintf(pHlp, "    Event log overflow                      = %RTbool\n", Status.n.u1EvtOverflow);
     3105            pHlp->pfnPrintf(pHlp, "    Event log interrupt                     = %RTbool\n", Status.n.u1EvtLogIntr);
     3106            pHlp->pfnPrintf(pHlp, "    Completion wait interrupt               = %RTbool\n", Status.n.u1CompWaitIntr);
     3107            pHlp->pfnPrintf(pHlp, "    Event log running                       = %RTbool\n", Status.n.u1EvtLogRunning);
     3108            pHlp->pfnPrintf(pHlp, "    Command buffer running                  = %RTbool\n", Status.n.u1CmdBufRunning);
     3109            pHlp->pfnPrintf(pHlp, "    PPR overflow                            = %RTbool\n", Status.n.u1PprOverflow);
     3110            pHlp->pfnPrintf(pHlp, "    PPR interrupt                           = %RTbool\n", Status.n.u1PprIntr);
     3111            pHlp->pfnPrintf(pHlp, "    PPR log running                         = %RTbool\n", Status.n.u1PprLogRunning);
     3112            pHlp->pfnPrintf(pHlp, "    Guest log running                       = %RTbool\n", Status.n.u1GstLogRunning);
     3113            pHlp->pfnPrintf(pHlp, "    Guest log interrupt                     = %RTbool\n", Status.n.u1GstLogIntr);
     3114            pHlp->pfnPrintf(pHlp, "    PPR log B overflow                      = %RTbool\n", Status.n.u1PprOverflowB);
     3115            pHlp->pfnPrintf(pHlp, "    PPR log active                          = %RTbool\n", Status.n.u1PprLogActive);
     3116            pHlp->pfnPrintf(pHlp, "    Event log B overflow                    = %RTbool\n", Status.n.u1EvtOverflowB);
     3117            pHlp->pfnPrintf(pHlp, "    Event log active                        = %RTbool\n", Status.n.u1EvtLogActive);
     3118            pHlp->pfnPrintf(pHlp, "    PPR log B overflow early warning        = %RTbool\n", Status.n.u1PprOverflowEarlyB);
     3119            pHlp->pfnPrintf(pHlp, "    PPR log overflow early warning          = %RTbool\n", Status.n.u1PprOverflowEarly);
     3120        }
     3121    }
     3122    /* PPR Log Head Pointer. */
     3123    {
     3124        PPR_LOG_HEAD_PTR_T const PprLogHeadPtr = pThis->PprLogHeadPtr;
     3125        pHlp->pfnPrintf(pHlp, "  PPR Log Head Pointer                    = %#RX64\n", PprLogHeadPtr.u64);
     3126        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogHeadPtr.n.u15Ptr);
     3127    }
     3128    /* PPR Log Tail Pointer. */
     3129    {
     3130        PPR_LOG_TAIL_PTR_T const PprLogTailPtr = pThis->PprLogTailPtr;
     3131        pHlp->pfnPrintf(pHlp, "  PPR Log Tail Pointer                    = %#RX64\n", PprLogTailPtr.u64);
     3132        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogTailPtr.n.u15Ptr);
     3133    }
     3134    /* Guest Virtual-APIC Log Head Pointer. */
     3135    {
     3136        GALOG_HEAD_PTR_T const GALogHeadPtr = pThis->GALogHeadPtr;
     3137        pHlp->pfnPrintf(pHlp, "  Guest Virtual-APIC Log Head Pointer     = %#RX64\n", GALogHeadPtr.u64);
     3138        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  GALogHeadPtr.n.u12GALogPtr);
     3139    }
     3140    /* Guest Virtual-APIC Log Tail Pointer. */
     3141    {
     3142        GALOG_HEAD_PTR_T const GALogTailPtr = pThis->GALogTailPtr;
     3143        pHlp->pfnPrintf(pHlp, "  Guest Virtual-APIC Log Tail Pointer     = %#RX64\n", GALogTailPtr.u64);
     3144        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  GALogTailPtr.n.u12GALogPtr);
     3145    }
     3146    /* PPR Log B Head Pointer. */
     3147    {
     3148        PPR_LOG_B_HEAD_PTR_T const PprLogBHeadPtr = pThis->PprLogBHeadPtr;
     3149        pHlp->pfnPrintf(pHlp, "  PPR Log B Head Pointer                  = %#RX64\n", PprLogBHeadPtr.u64);
     3150        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBHeadPtr.n.u15Ptr);
     3151    }
     3152    /* PPR Log B Tail Pointer. */
     3153    {
     3154        PPR_LOG_B_TAIL_PTR_T const PprLogBTailPtr = pThis->PprLogBTailPtr;
     3155        pHlp->pfnPrintf(pHlp, "  PPR Log B Tail Pointer                  = %#RX64\n", PprLogBTailPtr.u64);
     3156        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBTailPtr.n.u15Ptr);
     3157    }
     3158    /* Event Log B Head Pointer. */
     3159    {
     3160        EVT_LOG_B_HEAD_PTR_T const EvtLogBHeadPtr = pThis->EvtLogBHeadPtr;
     3161        pHlp->pfnPrintf(pHlp, "  Event Log B Head Pointer                = %#RX64\n", EvtLogBHeadPtr.u64);
     3162        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBHeadPtr.n.u15Ptr);
     3163    }
     3164    /* Event Log B Tail Pointer. */
     3165    {
     3166        EVT_LOG_B_TAIL_PTR_T const EvtLogBTailPtr = pThis->EvtLogBTailPtr;
     3167        pHlp->pfnPrintf(pHlp, "  Event Log B Tail Pointer                = %#RX64\n", EvtLogBTailPtr.u64);
     3168        pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBTailPtr.n.u15Ptr);
     3169    }
     3170    /* PPR Log Auto Response Register. */
     3171    {
     3172        PPR_LOG_AUTO_RESP_T const PprLogAutoResp = pThis->PprLogAutoResp;
     3173        pHlp->pfnPrintf(pHlp, "  PPR Log Auto Response Register          = %#RX64\n",     PprLogAutoResp.u64);
     3174        if (fVerbose)
     3175        {
     3176            pHlp->pfnPrintf(pHlp, "    Code                                    = %#x\n",      PprLogAutoResp.n.u4AutoRespCode);
     3177            pHlp->pfnPrintf(pHlp, "    Mask Gen.                               = %RTbool\n",  PprLogAutoResp.n.u1AutoRespMaskGen);
     3178        }
     3179    }
     3180    /* PPR Log Overflow Early Warning Indicator Register. */
     3181    {
     3182        PPR_LOG_OVERFLOW_EARLY_T const PprLogOverflowEarly = pThis->PprLogOverflowEarly;
     3183        pHlp->pfnPrintf(pHlp, "  PPR Log overflow early warning          = %#RX64\n",    PprLogOverflowEarly.u64);
     3184        if (fVerbose)
     3185        {
     3186            pHlp->pfnPrintf(pHlp, "    Threshold                               = %#x\n",     PprLogOverflowEarly.n.u15Threshold);
     3187            pHlp->pfnPrintf(pHlp, "    Interrupt enable                        = %RTbool\n", PprLogOverflowEarly.n.u1IntrEn);
     3188            pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", PprLogOverflowEarly.n.u1Enable);
     3189        }
     3190    }
     3191    /* PPR Log Overflow Early Warning Indicator Register. */
     3192    {
     3193        PPR_LOG_OVERFLOW_EARLY_T const PprLogBOverflowEarly = pThis->PprLogBOverflowEarly;
     3194        pHlp->pfnPrintf(pHlp, "  PPR Log B overflow early warning        = %#RX64\n",    PprLogBOverflowEarly.u64);
     3195        if (fVerbose)
     3196        {
     3197            pHlp->pfnPrintf(pHlp, "    Threshold                               = %#x\n",     PprLogBOverflowEarly.n.u15Threshold);
     3198            pHlp->pfnPrintf(pHlp, "    Interrupt enable                        = %RTbool\n", PprLogBOverflowEarly.n.u1IntrEn);
     3199            pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", PprLogBOverflowEarly.n.u1Enable);
     3200        }
     3201    }
     3202}
     3203
     3204
     3205/**
     3206 * @callback_method_impl{FNSSMDEVSAVEEXEC}
     3207 */
     3208static DECLCALLBACK(int) iommuAmdR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     3209{
     3210    /** @todo IOMMU: Save state. */
     3211    RT_NOREF2(pDevIns, pSSM);
     3212    return VERR_NOT_IMPLEMENTED;
     3213}
     3214
     3215
     3216/**
     3217 * @callback_method_impl{FNSSMDEVLOADEXEC}
     3218 */
     3219static DECLCALLBACK(int) iommuAmdR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
     3220{
     3221    /** @todo IOMMU: Load state. */
     3222    RT_NOREF4(pDevIns, pSSM, uVersion, uPass);
     3223    return VERR_NOT_IMPLEMENTED;
     3224}
     3225
     3226
     3227/**
     3228 * @interface_method_impl{PDMDEVREG,pfnReset}
     3229 */
     3230static DECLCALLBACK(void) iommuAmdR3Reset(PPDMDEVINS pDevIns)
     3231{
     3232    /*
     3233     * Resets read-write portion of the IOMMU state.
     3234     *
     3235     * State data not initialized here is expected to be initialized during
     3236     * device construction and remain read-only through the lifetime of the VM.
     3237     */
    25263238    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
    25273239    Assert(pThis);
     
    26203332
    26213333/**
    2622  * @callback_method_impl{FNPCICONFIGREAD}
    2623  */
    2624 static DECLCALLBACK(VBOXSTRICTRC) iommuAmdR3PciConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress,
    2625                                                           unsigned cb, uint32_t *pu32Value)
    2626 {
    2627     /** @todo IOMMU: PCI config read stat counter. */
    2628     VBOXSTRICTRC rcStrict = PDMDevHlpPCIConfigRead(pDevIns, pPciDev, uAddress, cb, pu32Value);
    2629     Log3((IOMMU_LOG_PFX ": PCI config read: At %#x (%u) -> %#x %Rrc\n", uAddress, cb, *pu32Value, VBOXSTRICTRC_VAL(rcStrict)));
    2630     return rcStrict;
    2631 }
    2632 
    2633 
    2634 /**
    2635  * @callback_method_impl{FNPCICONFIGWRITE}
    2636  */
    2637 static DECLCALLBACK(VBOXSTRICTRC) iommuAmdR3PciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress,
    2638                                                            unsigned cb, uint32_t u32Value)
    2639 {
    2640     /** @todo IOMMU: PCI config write. */
    2641     VBOXSTRICTRC rcStrict = PDMDevHlpPCIConfigWrite(pDevIns, pPciDev, uAddress, cb, u32Value);
    2642     Log3((IOMMU_LOG_PFX ": PCI config write: %#x -> To %#x (%u) %Rrc\n", u32Value, uAddress, cb, VBOXSTRICTRC_VAL(rcStrict)));
    2643     return rcStrict;
    2644 }
    2645 
    2646 
    2647 /**
    2648  * @callback_method_impl{FNDBGFHANDLERDEV}
    2649  */
    2650 static DECLCALLBACK(void) iommuAmdR3DbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    2651 {
    2652     PCIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
    2653     Assert(pThis);
    2654 
    2655     LogFlow((IOMMU_LOG_PFX ": iommuAmdR3DbgInfo: pThis=%p pszArgs=%s\n", pThis, pszArgs));
    2656     bool const fVerbose = !strncmp(pszArgs, RT_STR_TUPLE("verbose")) ? true : false;
    2657 
    2658     pHlp->pfnPrintf(pHlp, "AMD-IOMMU:\n");
    2659     /* Device Table Base Address. */
    2660     {
    2661         DEV_TAB_BAR_T const DevTabBar = pThis->DevTabBaseAddr;
    2662         pHlp->pfnPrintf(pHlp, "  Device Table BAR                        = %#RX64\n", DevTabBar.u64);
    2663         if (fVerbose)
    2664         {
    2665             pHlp->pfnPrintf(pHlp, "    Size                                    = %u (%u bytes)\n", DevTabBar.n.u9Size,
    2666                         (DevTabBar.n.u9Size + 1) * _4K);
    2667             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", DevTabBar.n.u40DevTabBase);
    2668         }
    2669     }
    2670     /* Command Buffer Base Address Register. */
    2671     {
    2672         CMD_BUF_BAR_T const CmdBufBar = pThis->CmdBufBaseAddr;
    2673         uint32_t      cEntries;
    2674         uint32_t      cbBuffer;
    2675         uint8_t const uEncodedLen = CmdBufBar.n.u4CmdLen;
    2676         iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
    2677         pHlp->pfnPrintf(pHlp, "  Command buffer BAR                      = %#RX64\n", CmdBufBar.u64);
    2678         if (fVerbose)
    2679         {
    2680             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", CmdBufBar.n.u40CmdBase);
    2681             pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
    2682                             cEntries, cbBuffer);
    2683         }
    2684     }
    2685     /* Event Log Base Address Register. */
    2686     {
    2687         EVT_LOG_BAR_T const EvtLogBar = pThis->EvtLogBaseAddr;
    2688         uint32_t      cEntries;
    2689         uint32_t      cbBuffer;
    2690         uint8_t const uEncodedLen = EvtLogBar.n.u4EvtLen;
    2691         iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
    2692         pHlp->pfnPrintf(pHlp, "  Event log BAR                           = %#RX64\n", EvtLogBar.u64);
    2693         if (fVerbose)
    2694         {
    2695             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", EvtLogBar.n.u40EvtBase);
    2696             pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
    2697                             cEntries, cbBuffer);
    2698         }
    2699     }
    2700     /* IOMMU Control Register. */
    2701     {
    2702         IOMMU_CTRL_T const Ctrl = pThis->Ctrl;
    2703         pHlp->pfnPrintf(pHlp, "  Control                                 = %#RX64\n", Ctrl.u64);
    2704         if (fVerbose)
    2705         {
    2706             pHlp->pfnPrintf(pHlp, "    IOMMU enable                            = %RTbool\n", Ctrl.n.u1IommuEn);
    2707             pHlp->pfnPrintf(pHlp, "    HT Tunnel translation enable            = %RTbool\n", Ctrl.n.u1HtTunEn);
    2708             pHlp->pfnPrintf(pHlp, "    Event log enable                        = %RTbool\n", Ctrl.n.u1EvtLogEn);
    2709             pHlp->pfnPrintf(pHlp, "    Event log interrupt enable              = %RTbool\n", Ctrl.n.u1EvtIntrEn);
    2710             pHlp->pfnPrintf(pHlp, "    Completion wait interrupt enable        = %RTbool\n", Ctrl.n.u1EvtIntrEn);
    2711             pHlp->pfnPrintf(pHlp, "    Invalidation timeout                    = %u\n",      Ctrl.n.u3InvTimeOut);
    2712             pHlp->pfnPrintf(pHlp, "    Pass posted write                       = %RTbool\n", Ctrl.n.u1PassPW);
    2713             pHlp->pfnPrintf(pHlp, "    Respose Pass posted write               = %RTbool\n", Ctrl.n.u1ResPassPW);
    2714             pHlp->pfnPrintf(pHlp, "    Coherent                                = %RTbool\n", Ctrl.n.u1Coherent);
    2715             pHlp->pfnPrintf(pHlp, "    Isochronous                             = %RTbool\n", Ctrl.n.u1Isoc);
    2716             pHlp->pfnPrintf(pHlp, "    Command buffer enable                   = %RTbool\n", Ctrl.n.u1CmdBufEn);
    2717             pHlp->pfnPrintf(pHlp, "    PPR log enable                          = %RTbool\n", Ctrl.n.u1PprLogEn);
    2718             pHlp->pfnPrintf(pHlp, "    PPR interrupt enable                    = %RTbool\n", Ctrl.n.u1PprIntrEn);
    2719             pHlp->pfnPrintf(pHlp, "    PPR enable                              = %RTbool\n", Ctrl.n.u1PprEn);
    2720             pHlp->pfnPrintf(pHlp, "    Guest translation eanble                = %RTbool\n", Ctrl.n.u1GstTranslateEn);
    2721             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC enable               = %RTbool\n", Ctrl.n.u1GstVirtApicEn);
    2722             pHlp->pfnPrintf(pHlp, "    CRW                                     = %#x\n",     Ctrl.n.u4Crw);
    2723             pHlp->pfnPrintf(pHlp, "    SMI filter enable                       = %RTbool\n", Ctrl.n.u1SmiFilterEn);
    2724             pHlp->pfnPrintf(pHlp, "    Self-writeback disable                  = %RTbool\n", Ctrl.n.u1SelfWriteBackDis);
    2725             pHlp->pfnPrintf(pHlp, "    SMI filter log enable                   = %RTbool\n", Ctrl.n.u1SmiFilterLogEn);
    2726             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC mode enable          = %#x\n",     Ctrl.n.u3GstVirtApicModeEn);
    2727             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC GA log enable        = %RTbool\n", Ctrl.n.u1GstLogEn);
    2728             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC interrupt enable     = %RTbool\n", Ctrl.n.u1GstIntrEn);
    2729             pHlp->pfnPrintf(pHlp, "    Dual PPR log enable                     = %#x\n",     Ctrl.n.u2DualPprLogEn);
    2730             pHlp->pfnPrintf(pHlp, "    Dual event log enable                   = %#x\n",     Ctrl.n.u2DualEvtLogEn);
    2731             pHlp->pfnPrintf(pHlp, "    Device table segmentation enable        = %#x\n",     Ctrl.n.u3DevTabSegEn);
    2732             pHlp->pfnPrintf(pHlp, "    Privilege abort enable                  = %#x\n",     Ctrl.n.u2PrivAbortEn);
    2733             pHlp->pfnPrintf(pHlp, "    PPR auto response enable                = %RTbool\n", Ctrl.n.u1PprAutoRespEn);
    2734             pHlp->pfnPrintf(pHlp, "    MARC enable                             = %RTbool\n", Ctrl.n.u1MarcEn);
    2735             pHlp->pfnPrintf(pHlp, "    Block StopMark enable                   = %RTbool\n", Ctrl.n.u1BlockStopMarkEn);
    2736             pHlp->pfnPrintf(pHlp, "    PPR auto response always-on enable      = %RTbool\n", Ctrl.n.u1PprAutoRespAlwaysOnEn);
    2737             pHlp->pfnPrintf(pHlp, "    Domain IDPNE                            = %RTbool\n", Ctrl.n.u1DomainIDPNE);
    2738             pHlp->pfnPrintf(pHlp, "    Enhanced PPR handling                   = %RTbool\n", Ctrl.n.u1EnhancedPpr);
    2739             pHlp->pfnPrintf(pHlp, "    Host page table access/dirty bit update = %#x\n",     Ctrl.n.u2HstAccDirtyBitUpdate);
    2740             pHlp->pfnPrintf(pHlp, "    Guest page table dirty bit disable      = %RTbool\n", Ctrl.n.u1GstDirtyUpdateDis);
    2741             pHlp->pfnPrintf(pHlp, "    x2APIC enable                           = %RTbool\n", Ctrl.n.u1X2ApicEn);
    2742             pHlp->pfnPrintf(pHlp, "    x2APIC interrupt enable                 = %RTbool\n", Ctrl.n.u1X2ApicIntrGenEn);
    2743             pHlp->pfnPrintf(pHlp, "    Guest page table access bit update      = %RTbool\n", Ctrl.n.u1GstAccessUpdateDis);
    2744         }
    2745     }
    2746     /* Exclusion Base Address Register. */
    2747     {
    2748         IOMMU_EXCL_RANGE_BAR_T const ExclRangeBar = pThis->ExclRangeBaseAddr;
    2749         pHlp->pfnPrintf(pHlp, "  Exclusion BAR                           = %#RX64\n", ExclRangeBar.u64);
    2750         if (fVerbose)
    2751         {
    2752             pHlp->pfnPrintf(pHlp, "    Exclusion enable                        = %RTbool\n", ExclRangeBar.n.u1ExclEnable);
    2753             pHlp->pfnPrintf(pHlp, "    Allow all devices                       = %RTbool\n", ExclRangeBar.n.u1AllowAll);
    2754             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", ExclRangeBar.n.u40ExclRangeBase);
    2755         }
    2756     }
    2757     /* Exclusion Range Limit Register. */
    2758     {
    2759         IOMMU_EXCL_RANGE_LIMIT_T const ExclRangeLimit = pThis->ExclRangeLimit;
    2760         pHlp->pfnPrintf(pHlp, "  Exclusion Range Limit                   = %#RX64\n", ExclRangeLimit.u64);
    2761         if (fVerbose)
    2762             pHlp->pfnPrintf(pHlp, "    Range limit                             = %#RX64\n", ExclRangeLimit.n.u40ExclLimit);
    2763     }
    2764     /* Extended Feature Register. */
    2765     {
    2766         IOMMU_EXT_FEAT_T ExtFeat = pThis->ExtFeat;
    2767         pHlp->pfnPrintf(pHlp, "  Extended Feature Register               = %#RX64\n", ExtFeat.u64);
    2768         pHlp->pfnPrintf(pHlp, "    Prefetch support                        = %RTbool\n", ExtFeat.n.u1PrefetchSup);
    2769         if (fVerbose)
    2770         {
    2771             pHlp->pfnPrintf(pHlp, "    PPR support                             = %RTbool\n", ExtFeat.n.u1PprSup);
    2772             pHlp->pfnPrintf(pHlp, "    x2APIC support                          = %RTbool\n", ExtFeat.n.u1X2ApicSup);
    2773             pHlp->pfnPrintf(pHlp, "    NX and privilege level support          = %RTbool\n", ExtFeat.n.u1NoExecuteSup);
    2774             pHlp->pfnPrintf(pHlp, "    Guest translation support               = %RTbool\n", ExtFeat.n.u1GstTranslateSup);
    2775             pHlp->pfnPrintf(pHlp, "    Invalidate-All command support          = %RTbool\n", ExtFeat.n.u1InvAllSup);
    2776             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC support              = %RTbool\n", ExtFeat.n.u1GstVirtApicSup);
    2777             pHlp->pfnPrintf(pHlp, "    Hardware error register support         = %RTbool\n", ExtFeat.n.u1HwErrorSup);
    2778             pHlp->pfnPrintf(pHlp, "    Performance counters support            = %RTbool\n", ExtFeat.n.u1PerfCounterSup);
    2779             pHlp->pfnPrintf(pHlp, "    Host address translation size           = %#x\n",     ExtFeat.n.u2HostAddrTranslateSize);
    2780             pHlp->pfnPrintf(pHlp, "    Guest address translation size          = %#x\n",     ExtFeat.n.u2GstAddrTranslateSize);
    2781             pHlp->pfnPrintf(pHlp, "    Guest CR3 root table level support      = %#x\n",     ExtFeat.n.u2GstCr3RootTblLevel);
    2782             pHlp->pfnPrintf(pHlp, "    SMI filter register support             = %#x\n",     ExtFeat.n.u2SmiFilterSup);
    2783             pHlp->pfnPrintf(pHlp, "    SMI filter register count               = %#x\n",     ExtFeat.n.u3SmiFilterCount);
    2784             pHlp->pfnPrintf(pHlp, "    Guest virtual-APIC modes support        = %#x\n",     ExtFeat.n.u3GstVirtApicModeSup);
    2785             pHlp->pfnPrintf(pHlp, "    Dual PPR log support                    = %#x\n",     ExtFeat.n.u2DualPprLogSup);
    2786             pHlp->pfnPrintf(pHlp, "    Dual event log support                  = %#x\n",     ExtFeat.n.u2DualEvtLogSup);
    2787             pHlp->pfnPrintf(pHlp, "    Maximum PASID                           = %#x\n",     ExtFeat.n.u5MaxPasidSup);
    2788             pHlp->pfnPrintf(pHlp, "    User/supervisor page protection support = %RTbool\n", ExtFeat.n.u1UserSupervisorSup);
    2789             pHlp->pfnPrintf(pHlp, "    Device table segments supported         = %u\n",      (ExtFeat.n.u2DevTabSegSup << 1));
    2790             pHlp->pfnPrintf(pHlp, "    PPR log overflow early warning support  = %RTbool\n", ExtFeat.n.u1PprLogOverflowWarn);
    2791             pHlp->pfnPrintf(pHlp, "    PPR auto response support               = %RTbool\n", ExtFeat.n.u1PprAutoRespSup);
    2792             pHlp->pfnPrintf(pHlp, "    MARC support                            = %#x\n",     ExtFeat.n.u2MarcSup);
    2793             pHlp->pfnPrintf(pHlp, "    Block StopMark message support          = %RTbool\n", ExtFeat.n.u1BlockStopMarkSup);
    2794             pHlp->pfnPrintf(pHlp, "    Performance optimization support        = %RTbool\n", ExtFeat.n.u1PerfOptSup);
    2795             pHlp->pfnPrintf(pHlp, "    MSI capability MMIO access support      = %RTbool\n", ExtFeat.n.u1MsiCapMmioSup);
    2796             pHlp->pfnPrintf(pHlp, "    Guest I/O protection support            = %RTbool\n", ExtFeat.n.u1GstIoSup);
    2797             pHlp->pfnPrintf(pHlp, "    Host access support                     = %RTbool\n", ExtFeat.n.u1HostAccessSup);
    2798             pHlp->pfnPrintf(pHlp, "    Enhanced PPR handling support           = %RTbool\n", ExtFeat.n.u1EnhancedPprSup);
    2799             pHlp->pfnPrintf(pHlp, "    Attribute forward supported             = %RTbool\n", ExtFeat.n.u1AttrForwardSup);
    2800             pHlp->pfnPrintf(pHlp, "    Host dirty support                      = %RTbool\n", ExtFeat.n.u1HostDirtySup);
    2801             pHlp->pfnPrintf(pHlp, "    Invalidate IOTLB type support           = %RTbool\n", ExtFeat.n.u1InvIoTlbTypeSup);
    2802             pHlp->pfnPrintf(pHlp, "    Guest page table access bit hw disable  = %RTbool\n", ExtFeat.n.u1GstUpdateDisSup);
    2803             pHlp->pfnPrintf(pHlp, "    Force physical dest for remapped intr.  = %RTbool\n", ExtFeat.n.u1ForcePhysDstSup);
    2804         }
    2805     }
    2806     /* PPR Log Base Address Register. */
    2807     {
    2808         PPR_LOG_BAR_T PprLogBar = pThis->PprLogBaseAddr;
    2809         uint32_t      cEntries;
    2810         uint32_t      cbBuffer;
    2811         uint8_t const uEncodedLen = PprLogBar.n.u4PprLogLen;
    2812         iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
    2813         pHlp->pfnPrintf(pHlp, "  PPR Log BAR                             = %#RX64\n",   PprLogBar.u64);
    2814         if (fVerbose)
    2815         {
    2816             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", PprLogBar.n.u40PprLogBase);
    2817             pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
    2818                             cEntries, cbBuffer);
    2819         }
    2820     }
    2821     /* Hardware Event (Hi) Register. */
    2822     {
    2823         IOMMU_HW_EVT_HI_T HwEvtHi = pThis->HwEvtHi;
    2824         pHlp->pfnPrintf(pHlp, "  Hardware Event (Hi)                     = %#RX64\n",   HwEvtHi.u64);
    2825         if (fVerbose)
    2826         {
    2827             pHlp->pfnPrintf(pHlp, "    First operand                           = %#RX64\n", HwEvtHi.n.u60FirstOperand);
    2828             pHlp->pfnPrintf(pHlp, "    Event code                              = %#RX8\n",  HwEvtHi.n.u4EvtCode);
    2829         }
    2830     }
    2831     /* Hardware Event (Lo) Register. */
    2832     pHlp->pfnPrintf(pHlp, "  Hardware Event (Lo)                         = %#RX64\n", pThis->HwEvtLo);
    2833     /* Hardware Event Status. */
    2834     {
    2835         IOMMU_HW_EVT_STATUS_T HwEvtStatus = pThis->HwEvtStatus;
    2836         pHlp->pfnPrintf(pHlp, "  Hardware Event Status                   = %#RX64\n",    HwEvtStatus.u64);
    2837         if (fVerbose)
    2838         {
    2839             pHlp->pfnPrintf(pHlp, "    Valid                                   = %RTbool\n", HwEvtStatus.n.u1Valid);
    2840             pHlp->pfnPrintf(pHlp, "    Overflow                                = %RTbool\n", HwEvtStatus.n.u1Overflow);
    2841         }
    2842     }
    2843     /* Guest Virtual-APIC Log Base Address Register. */
    2844     {
    2845         GALOG_BAR_T const GALogBar = pThis->GALogBaseAddr;
    2846         uint32_t      cEntries;
    2847         uint32_t      cbBuffer;
    2848         uint8_t const uEncodedLen = GALogBar.n.u4GALogLen;
    2849         iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
    2850         pHlp->pfnPrintf(pHlp, "  Guest Log BAR                           = %#RX64\n",    GALogBar.u64);
    2851         if (fVerbose)
    2852         {
    2853             pHlp->pfnPrintf(pHlp, "    Base address                            = %RTbool\n", GALogBar.n.u40GALogBase);
    2854             pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
    2855                             cEntries, cbBuffer);
    2856         }
    2857     }
    2858     /* Guest Virtual-APIC Log Tail Address Register. */
    2859     {
    2860         GALOG_TAIL_ADDR_T GALogTail = pThis->GALogTailAddr;
    2861         pHlp->pfnPrintf(pHlp, "  Guest Log Tail Address                  = %#RX64\n",   GALogTail.u64);
    2862         if (fVerbose)
    2863             pHlp->pfnPrintf(pHlp, "    Tail address                            = %#RX64\n", GALogTail.n.u40GALogTailAddr);
    2864     }
    2865     /* PPR Log B Base Address Register. */
    2866     {
    2867         PPR_LOG_B_BAR_T PprLogBBar = pThis->PprLogBBaseAddr;
    2868         uint32_t      cEntries;
    2869         uint32_t      cbBuffer;
    2870         uint8_t const uEncodedLen = PprLogBBar.n.u4PprLogLen;
    2871         iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
    2872         pHlp->pfnPrintf(pHlp, "  PPR Log B BAR                           = %#RX64\n",   PprLogBBar.u64);
    2873         if (fVerbose)
    2874         {
    2875             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", PprLogBBar.n.u40PprLogBase);
    2876             pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
    2877                             cEntries, cbBuffer);
    2878         }
    2879     }
    2880     /* Event Log B Base Address Register. */
    2881     {
    2882         EVT_LOG_B_BAR_T EvtLogBBar = pThis->EvtLogBBaseAddr;
    2883         uint32_t      cEntries;
    2884         uint32_t      cbBuffer;
    2885         uint8_t const uEncodedLen = EvtLogBBar.n.u4EvtLen;
    2886         iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, &cbBuffer);
    2887         pHlp->pfnPrintf(pHlp, "  Event Log B BAR                         = %#RX64\n",   EvtLogBBar.u64);
    2888         if (fVerbose)
    2889         {
    2890             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", EvtLogBBar.n.u40EvtBase);
    2891             pHlp->pfnPrintf(pHlp, "    Length                                  = %u (%u entries, %u bytes)\n", uEncodedLen,
    2892                             cEntries, cbBuffer);
    2893         }
    2894     }
    2895     /* Device Table Segment Registers. */
    2896     for (unsigned i = 0; i < RT_ELEMENTS(pThis->DevTabSeg); i++)
    2897     {
    2898         DEV_TAB_SEG_BAR_T const DevTabSeg = pThis->DevTabSeg[i];
    2899         pHlp->pfnPrintf(pHlp, "  Device Table Segment BAR [%u]            = %#RX64\n",  DevTabSeg.u64);
    2900         if (fVerbose)
    2901         {
    2902             pHlp->pfnPrintf(pHlp, "    Base address                            = %#RX64\n", DevTabSeg.n.u40DevTabBase);
    2903             pHlp->pfnPrintf(pHlp, "    Size                                    = %#x (%u bytes)\n", DevTabSeg.n.u8Size,
    2904                             (DevTabSeg.n.u8Size + 1) << X86_PAGE_4K_SHIFT);
    2905         }
    2906     }
    2907     /* Device-Specific Feature Extension Register. */
    2908     {
    2909         DEV_SPECIFIC_FEAT_T const DevSpecificFeat = pThis->DevSpecificFeat;
    2910         pHlp->pfnPrintf(pHlp, "  Device-specific Feature                 = %#RX64\n",   DevSpecificFeat.u64);
    2911         if (fVerbose)
    2912         {
    2913             pHlp->pfnPrintf(pHlp, "    Feature                                 = %#RX32\n", DevSpecificFeat.n.u24DevSpecFeat);
    2914             pHlp->pfnPrintf(pHlp, "    Minor revision ID                       = %#x\n",    DevSpecificFeat.n.u4RevMinor);
    2915             pHlp->pfnPrintf(pHlp, "    Major revision ID                       = %#x\n",    DevSpecificFeat.n.u4RevMajor);
    2916         }
    2917     }
    2918     /* Device-Specific Control Extension Register. */
    2919     {
    2920         DEV_SPECIFIC_CTRL_T const DevSpecificCtrl = pThis->DevSpecificCtrl;
    2921         pHlp->pfnPrintf(pHlp, "  Device-specific Control                 = %#RX64\n",   DevSpecificCtrl.u64);
    2922         if (fVerbose)
    2923         {
    2924             pHlp->pfnPrintf(pHlp, "    Control                                 = %#RX32\n", DevSpecificCtrl.n.u24DevSpecCtrl);
    2925             pHlp->pfnPrintf(pHlp, "    Minor revision ID                       = %#x\n",    DevSpecificCtrl.n.u4RevMinor);
    2926             pHlp->pfnPrintf(pHlp, "    Major revision ID                       = %#x\n",    DevSpecificCtrl.n.u4RevMajor);
    2927         }
    2928     }
    2929     /* Device-Specific Status Extension Register. */
    2930     {
    2931         DEV_SPECIFIC_STATUS_T const DevSpecificStatus = pThis->DevSpecificStatus;
    2932         pHlp->pfnPrintf(pHlp, "  Device-specific Control                 = %#RX64\n",   DevSpecificStatus.u64);
    2933         if (fVerbose)
    2934         {
    2935             pHlp->pfnPrintf(pHlp, "    Status                                  = %#RX32\n", DevSpecificStatus.n.u24DevSpecStatus);
    2936             pHlp->pfnPrintf(pHlp, "    Minor revision ID                       = %#x\n",    DevSpecificStatus.n.u4RevMinor);
    2937             pHlp->pfnPrintf(pHlp, "    Major revision ID                       = %#x\n",    DevSpecificStatus.n.u4RevMajor);
    2938         }
    2939     }
    2940     /* MSI Miscellaneous Information Register (Lo and Hi). */
    2941     {
    2942         MSI_MISC_INFO_T const MsiMiscInfo = pThis->MsiMiscInfo;
    2943         pHlp->pfnPrintf(pHlp, "  MSI Misc. Info. Register                = %#RX64\n",    MsiMiscInfo.u64);
    2944         if (fVerbose)
    2945         {
    2946             pHlp->pfnPrintf(pHlp, "    Event Log MSI number                    = %#x\n",     MsiMiscInfo.n.u5MsiNumEvtLog);
    2947             pHlp->pfnPrintf(pHlp, "    Guest Virtual-Address Size              = %#x\n",     MsiMiscInfo.n.u3GstVirtAddrSize);
    2948             pHlp->pfnPrintf(pHlp, "    Physical Address Size                   = %#x\n",     MsiMiscInfo.n.u7PhysAddrSize);
    2949             pHlp->pfnPrintf(pHlp, "    Virtual-Address Size                    = %#x\n",     MsiMiscInfo.n.u7VirtAddrSize);
    2950             pHlp->pfnPrintf(pHlp, "    HT Transport ATS Range Reserved         = %RTbool\n", MsiMiscInfo.n.u1HtAtsResv);
    2951             pHlp->pfnPrintf(pHlp, "    PPR MSI number                          = %#x\n",     MsiMiscInfo.n.u5MsiNumPpr);
    2952             pHlp->pfnPrintf(pHlp, "    GA Log MSI number                       = %#x\n",     MsiMiscInfo.n.u5MsiNumGa);
    2953         }
    2954     }
    2955     /* MSI Capability Header. */
    2956     {
    2957         MSI_CAP_HDR_T const MsiCapHdr = pThis->MsiCapHdr;
    2958         pHlp->pfnPrintf(pHlp, "  MSI Capability Header                   = %#RX32\n",    MsiCapHdr.u32);
    2959         if (fVerbose)
    2960         {
    2961             pHlp->pfnPrintf(pHlp, "    Capability ID                           = %#x\n",     MsiCapHdr.n.u8MsiCapId);
    2962             pHlp->pfnPrintf(pHlp, "    Capability Ptr (PCI config offset)      = %#x\n",     MsiCapHdr.n.u8MsiCapPtr);
    2963             pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", MsiCapHdr.n.u1MsiEnable);
    2964             pHlp->pfnPrintf(pHlp, "    Multi-message capability                = %#x\n",     MsiCapHdr.n.u3MsiMultiMessCap);
    2965             pHlp->pfnPrintf(pHlp, "    Multi-message enable                    = %#x\n",     MsiCapHdr.n.u3MsiMultiMessEn);
    2966         }
    2967     }
    2968     /* MSI Address Register (Lo and Hi). */
    2969     {
    2970         MSI_ADDR_T const MsiAddr = pThis->MsiAddr;
    2971         pHlp->pfnPrintf(pHlp, "  MSI Address                             = %#RX64\n",   MsiAddr.u64);
    2972         if (fVerbose)
    2973             pHlp->pfnPrintf(pHlp, "    Address                                 = %#RX64\n", MsiAddr.n.u62MsiAddr);
    2974     }
    2975     /* MSI Data. */
    2976     {
    2977         MSI_DATA_T const MsiData = pThis->MsiData;
    2978         pHlp->pfnPrintf(pHlp, "  MSI Data                                = %#RX32\n", MsiData.u32);
    2979         if (fVerbose)
    2980             pHlp->pfnPrintf(pHlp, "    Data                                    = %#x\n",  MsiData.n.u16MsiData);
    2981     }
    2982     /* MSI Mapping Capability Header. */
    2983     {
    2984         MSI_MAP_CAP_HDR_T const MsiMapCapHdr = pThis->MsiMapCapHdr;
    2985         pHlp->pfnPrintf(pHlp, "  MSI Mapping Capability Header           = %#RX32\n",    MsiMapCapHdr.u32);
    2986         if (fVerbose)
    2987         {
    2988             pHlp->pfnPrintf(pHlp, "    Capability ID                           = %#x\n",     MsiMapCapHdr.n.u8MsiMapCapId);
    2989             pHlp->pfnPrintf(pHlp, "    Map enable                              = %RTbool\n", MsiMapCapHdr.n.u1MsiMapEn);
    2990             pHlp->pfnPrintf(pHlp, "    Map fixed                               = %RTbool\n", MsiMapCapHdr.n.u1MsiMapFixed);
    2991             pHlp->pfnPrintf(pHlp, "    Map capability type                     = %#x\n",     MsiMapCapHdr.n.u5MapCapType);
    2992         }
    2993     }
    2994     /* Performance Optimization Control Register. */
    2995     {
    2996         IOMMU_PERF_OPT_CTRL_T const PerfOptCtrl = pThis->PerfOptCtrl;
    2997         pHlp->pfnPrintf(pHlp, "  Performance Optimization Control        = %#RX32\n",    PerfOptCtrl.u32);
    2998         if (fVerbose)
    2999             pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", PerfOptCtrl.n.u1PerfOptEn);
    3000     }
    3001     /* XT (x2APIC) General Interrupt Control Register. */
    3002     {
    3003         IOMMU_XT_GEN_INTR_CTRL_T const XtGenIntrCtrl = pThis->XtGenIntrCtrl;
    3004         pHlp->pfnPrintf(pHlp, "  XT General Interrupt Control            = %#RX64\n", XtGenIntrCtrl.u64);
    3005         if (fVerbose)
    3006         {
    3007             pHlp->pfnPrintf(pHlp, "    Interrupt destination mode              = %s\n",
    3008                             !XtGenIntrCtrl.n.u1X2ApicIntrDstMode ? "physical" : "logical");
    3009             pHlp->pfnPrintf(pHlp, "    Interrupt destination                   = %#RX64\n",
    3010                             RT_MAKE_U64(XtGenIntrCtrl.n.u24X2ApicIntrDstLo, XtGenIntrCtrl.n.u7X2ApicIntrDstHi));
    3011             pHlp->pfnPrintf(pHlp, "    Interrupt vector                        = %#x\n", XtGenIntrCtrl.n.u8X2ApicIntrVector);
    3012             pHlp->pfnPrintf(pHlp, "    Interrupt delivery mode                 = %#x\n",
    3013                             !XtGenIntrCtrl.n.u8X2ApicIntrVector ? "fixed" : "arbitrated");
    3014         }
    3015     }
    3016     /* XT (x2APIC) PPR Interrupt Control Register. */
    3017     {
    3018         IOMMU_XT_PPR_INTR_CTRL_T const XtPprIntrCtrl = pThis->XtPprIntrCtrl;
    3019         pHlp->pfnPrintf(pHlp, "  XT PPR Interrupt Control                = %#RX64\n", XtPprIntrCtrl.u64);
    3020         if (fVerbose)
    3021         {
    3022             pHlp->pfnPrintf(pHlp, "   Interrupt destination mode               = %s\n",
    3023                             !XtPprIntrCtrl.n.u1X2ApicIntrDstMode ? "physical" : "logical");
    3024             pHlp->pfnPrintf(pHlp, "   Interrupt destination                    = %#RX64\n",
    3025                             RT_MAKE_U64(XtPprIntrCtrl.n.u24X2ApicIntrDstLo, XtPprIntrCtrl.n.u7X2ApicIntrDstHi));
    3026             pHlp->pfnPrintf(pHlp, "   Interrupt vector                         = %#x\n", XtPprIntrCtrl.n.u8X2ApicIntrVector);
    3027             pHlp->pfnPrintf(pHlp, "   Interrupt delivery mode                  = %#x\n",
    3028                             !XtPprIntrCtrl.n.u8X2ApicIntrVector ? "fixed" : "arbitrated");
    3029         }
    3030     }
    3031     /* XT (X2APIC) GA Log Interrupt Control Register. */
    3032     {
    3033         IOMMU_XT_GALOG_INTR_CTRL_T const XtGALogIntrCtrl = pThis->XtGALogIntrCtrl;
    3034         pHlp->pfnPrintf(pHlp, "  XT PPR Interrupt Control                = %#RX64\n", XtGALogIntrCtrl.u64);
    3035         if (fVerbose)
    3036         {
    3037             pHlp->pfnPrintf(pHlp, "    Interrupt destination mode              = %s\n",
    3038                             !XtGALogIntrCtrl.n.u1X2ApicIntrDstMode ? "physical" : "logical");
    3039             pHlp->pfnPrintf(pHlp, "    Interrupt destination                   = %#RX64\n",
    3040                             RT_MAKE_U64(XtGALogIntrCtrl.n.u24X2ApicIntrDstLo, XtGALogIntrCtrl.n.u7X2ApicIntrDstHi));
    3041             pHlp->pfnPrintf(pHlp, "    Interrupt vector                        = %#x\n", XtGALogIntrCtrl.n.u8X2ApicIntrVector);
    3042             pHlp->pfnPrintf(pHlp, "    Interrupt delivery mode                 = %#x\n",
    3043                             !XtGALogIntrCtrl.n.u8X2ApicIntrVector ? "fixed" : "arbitrated");
    3044         }
    3045     }
    3046     /* MARC Registers. */
    3047     {
    3048         for (unsigned i = 0; i < RT_ELEMENTS(pThis->aMarcApers); i++)
    3049         {
    3050             pHlp->pfnPrintf(pHlp, " MARC Aperature %u:\n", i);
    3051             MARC_APER_BAR_T const MarcAperBar = pThis->aMarcApers[i].Base;
    3052             pHlp->pfnPrintf(pHlp, "   Base    = %#RX64 (addr: %#RX64)\n", MarcAperBar.u64, MarcAperBar.n.u40MarcBaseAddr);
    3053 
    3054             MARC_APER_RELOC_T const MarcAperReloc = pThis->aMarcApers[i].Reloc;
    3055             pHlp->pfnPrintf(pHlp, "   Reloc   = %#RX64 (addr: %#RX64, read-only: %RTbool, enable: %RTbool)\n",
    3056                             MarcAperReloc.u64, MarcAperReloc.n.u40MarcRelocAddr, MarcAperReloc.n.u1ReadOnly,
    3057                             MarcAperReloc.n.u1RelocEn);
    3058 
    3059             MARC_APER_LEN_T const MarcAperLen = pThis->aMarcApers[i].Length;
    3060             pHlp->pfnPrintf(pHlp, "   Length  = %u pages\n", MarcAperLen.n.u40MarcLength);
    3061         }
    3062     }
    3063     /* Reserved Register. */
    3064     pHlp->pfnPrintf(pHlp, "  Reserved Register                           = %#RX64\n", pThis->RsvdReg);
    3065     /* Command Buffer Head Pointer Register. */
    3066     {
    3067         CMD_BUF_HEAD_PTR_T const CmdBufHeadPtr = pThis->CmdBufHeadPtr;
    3068         pHlp->pfnPrintf(pHlp, "  Command Buffer Head Pointer             = %#RX64\n", CmdBufHeadPtr.u64);
    3069         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufHeadPtr.n.u15Ptr);
    3070     }
    3071     /* Command Buffer Tail Pointer Register. */
    3072     {
    3073         CMD_BUF_HEAD_PTR_T const CmdBufTailPtr = pThis->CmdBufTailPtr;
    3074         pHlp->pfnPrintf(pHlp, "  Command Buffer Tail Pointer             = %#RX64\n", CmdBufTailPtr.u64);
    3075         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  CmdBufTailPtr.n.u15Ptr);
    3076     }
    3077     /* Event Log Head Pointer Register. */
    3078     {
    3079         EVT_LOG_HEAD_PTR_T const EvtLogHeadPtr = pThis->EvtLogHeadPtr;
    3080         pHlp->pfnPrintf(pHlp, "  Event Log Head Pointer                  = %#RX64\n", EvtLogHeadPtr.u64);
    3081         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogHeadPtr.n.u15Ptr);
    3082     }
    3083     /* Event Log Tail Pointer Register. */
    3084     {
    3085         EVT_LOG_TAIL_PTR_T const EvtLogTailPtr = pThis->EvtLogTailPtr;
    3086         pHlp->pfnPrintf(pHlp, "  Event Log Head Pointer                  = %#RX64\n", EvtLogTailPtr.u64);
    3087         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogTailPtr.n.u15Ptr);
    3088     }
    3089     /* Status Register. */
    3090     {
    3091         IOMMU_STATUS_T const Status = pThis->Status;
    3092         pHlp->pfnPrintf(pHlp, "  Status Register                         = %#RX64\n", Status.u64);
    3093         if (fVerbose)
    3094         {
    3095             pHlp->pfnPrintf(pHlp, "    Event log overflow                      = %RTbool\n", Status.n.u1EvtOverflow);
    3096             pHlp->pfnPrintf(pHlp, "    Event log interrupt                     = %RTbool\n", Status.n.u1EvtLogIntr);
    3097             pHlp->pfnPrintf(pHlp, "    Completion wait interrupt               = %RTbool\n", Status.n.u1CompWaitIntr);
    3098             pHlp->pfnPrintf(pHlp, "    Event log running                       = %RTbool\n", Status.n.u1EvtLogRunning);
    3099             pHlp->pfnPrintf(pHlp, "    Command buffer running                  = %RTbool\n", Status.n.u1CmdBufRunning);
    3100             pHlp->pfnPrintf(pHlp, "    PPR overflow                            = %RTbool\n", Status.n.u1PprOverflow);
    3101             pHlp->pfnPrintf(pHlp, "    PPR interrupt                           = %RTbool\n", Status.n.u1PprIntr);
    3102             pHlp->pfnPrintf(pHlp, "    PPR log running                         = %RTbool\n", Status.n.u1PprLogRunning);
    3103             pHlp->pfnPrintf(pHlp, "    Guest log running                       = %RTbool\n", Status.n.u1GstLogRunning);
    3104             pHlp->pfnPrintf(pHlp, "    Guest log interrupt                     = %RTbool\n", Status.n.u1GstLogIntr);
    3105             pHlp->pfnPrintf(pHlp, "    PPR log B overflow                      = %RTbool\n", Status.n.u1PprOverflowB);
    3106             pHlp->pfnPrintf(pHlp, "    PPR log active                          = %RTbool\n", Status.n.u1PprLogActive);
    3107             pHlp->pfnPrintf(pHlp, "    Event log B overflow                    = %RTbool\n", Status.n.u1EvtOverflowB);
    3108             pHlp->pfnPrintf(pHlp, "    Event log active                        = %RTbool\n", Status.n.u1EvtLogActive);
    3109             pHlp->pfnPrintf(pHlp, "    PPR log B overflow early warning        = %RTbool\n", Status.n.u1PprOverflowEarlyB);
    3110             pHlp->pfnPrintf(pHlp, "    PPR log overflow early warning          = %RTbool\n", Status.n.u1PprOverflowEarly);
    3111         }
    3112     }
    3113     /* PPR Log Head Pointer. */
    3114     {
    3115         PPR_LOG_HEAD_PTR_T const PprLogHeadPtr = pThis->PprLogHeadPtr;
    3116         pHlp->pfnPrintf(pHlp, "  PPR Log Head Pointer                    = %#RX64\n", PprLogHeadPtr.u64);
    3117         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogHeadPtr.n.u15Ptr);
    3118     }
    3119     /* PPR Log Tail Pointer. */
    3120     {
    3121         PPR_LOG_TAIL_PTR_T const PprLogTailPtr = pThis->PprLogTailPtr;
    3122         pHlp->pfnPrintf(pHlp, "  PPR Log Tail Pointer                    = %#RX64\n", PprLogTailPtr.u64);
    3123         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogTailPtr.n.u15Ptr);
    3124     }
    3125     /* Guest Virtual-APIC Log Head Pointer. */
    3126     {
    3127         GALOG_HEAD_PTR_T const GALogHeadPtr = pThis->GALogHeadPtr;
    3128         pHlp->pfnPrintf(pHlp, "  Guest Virtual-APIC Log Head Pointer     = %#RX64\n", GALogHeadPtr.u64);
    3129         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  GALogHeadPtr.n.u12GALogPtr);
    3130     }
    3131     /* Guest Virtual-APIC Log Tail Pointer. */
    3132     {
    3133         GALOG_HEAD_PTR_T const GALogTailPtr = pThis->GALogTailPtr;
    3134         pHlp->pfnPrintf(pHlp, "  Guest Virtual-APIC Log Tail Pointer     = %#RX64\n", GALogTailPtr.u64);
    3135         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  GALogTailPtr.n.u12GALogPtr);
    3136     }
    3137     /* PPR Log B Head Pointer. */
    3138     {
    3139         PPR_LOG_B_HEAD_PTR_T const PprLogBHeadPtr = pThis->PprLogBHeadPtr;
    3140         pHlp->pfnPrintf(pHlp, "  PPR Log B Head Pointer                  = %#RX64\n", PprLogBHeadPtr.u64);
    3141         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBHeadPtr.n.u15Ptr);
    3142     }
    3143     /* PPR Log B Tail Pointer. */
    3144     {
    3145         PPR_LOG_B_TAIL_PTR_T const PprLogBTailPtr = pThis->PprLogBTailPtr;
    3146         pHlp->pfnPrintf(pHlp, "  PPR Log B Tail Pointer                  = %#RX64\n", PprLogBTailPtr.u64);
    3147         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  PprLogBTailPtr.n.u15Ptr);
    3148     }
    3149     /* Event Log B Head Pointer. */
    3150     {
    3151         EVT_LOG_B_HEAD_PTR_T const EvtLogBHeadPtr = pThis->EvtLogBHeadPtr;
    3152         pHlp->pfnPrintf(pHlp, "  Event Log B Head Pointer                = %#RX64\n", EvtLogBHeadPtr.u64);
    3153         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBHeadPtr.n.u15Ptr);
    3154     }
    3155     /* Event Log B Tail Pointer. */
    3156     {
    3157         EVT_LOG_B_TAIL_PTR_T const EvtLogBTailPtr = pThis->EvtLogBTailPtr;
    3158         pHlp->pfnPrintf(pHlp, "  Event Log B Tail Pointer                = %#RX64\n", EvtLogBTailPtr.u64);
    3159         pHlp->pfnPrintf(pHlp, "    Pointer                                 = %#x\n",  EvtLogBTailPtr.n.u15Ptr);
    3160     }
    3161     /* PPR Log Auto Response Register. */
    3162     {
    3163         PPR_LOG_AUTO_RESP_T const PprLogAutoResp = pThis->PprLogAutoResp;
    3164         pHlp->pfnPrintf(pHlp, "  PPR Log Auto Response Register          = %#RX64\n",     PprLogAutoResp.u64);
    3165         if (fVerbose)
    3166         {
    3167             pHlp->pfnPrintf(pHlp, "    Code                                    = %#x\n",      PprLogAutoResp.n.u4AutoRespCode);
    3168             pHlp->pfnPrintf(pHlp, "    Mask Gen.                               = %RTbool\n",  PprLogAutoResp.n.u1AutoRespMaskGen);
    3169         }
    3170     }
    3171     /* PPR Log Overflow Early Warning Indicator Register. */
    3172     {
    3173         PPR_LOG_OVERFLOW_EARLY_T const PprLogOverflowEarly = pThis->PprLogOverflowEarly;
    3174         pHlp->pfnPrintf(pHlp, "  PPR Log overflow early warning          = %#RX64\n",    PprLogOverflowEarly.u64);
    3175         if (fVerbose)
    3176         {
    3177             pHlp->pfnPrintf(pHlp, "    Threshold                               = %#x\n",     PprLogOverflowEarly.n.u15Threshold);
    3178             pHlp->pfnPrintf(pHlp, "    Interrupt enable                        = %RTbool\n", PprLogOverflowEarly.n.u1IntrEn);
    3179             pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", PprLogOverflowEarly.n.u1Enable);
    3180         }
    3181     }
    3182     /* PPR Log Overflow Early Warning Indicator Register. */
    3183     {
    3184         PPR_LOG_OVERFLOW_EARLY_T const PprLogBOverflowEarly = pThis->PprLogBOverflowEarly;
    3185         pHlp->pfnPrintf(pHlp, "  PPR Log B overflow early warning        = %#RX64\n",    PprLogBOverflowEarly.u64);
    3186         if (fVerbose)
    3187         {
    3188             pHlp->pfnPrintf(pHlp, "    Threshold                               = %#x\n",     PprLogBOverflowEarly.n.u15Threshold);
    3189             pHlp->pfnPrintf(pHlp, "    Interrupt enable                        = %RTbool\n", PprLogBOverflowEarly.n.u1IntrEn);
    3190             pHlp->pfnPrintf(pHlp, "    Enable                                  = %RTbool\n", PprLogBOverflowEarly.n.u1Enable);
    3191         }
    3192     }
    3193 }
    3194 
    3195 
    3196 /**
    3197  * @callback_method_impl{FNSSMDEVSAVEEXEC}
    3198  */
    3199 static DECLCALLBACK(int) iommuAmdR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    3200 {
    3201     /** @todo IOMMU: Save state. */
    3202     RT_NOREF2(pDevIns, pSSM);
    3203     return VERR_NOT_IMPLEMENTED;
    3204 }
    3205 
    3206 
    3207 /**
    3208  * @callback_method_impl{FNSSMDEVLOADEXEC}
    3209  */
    3210 static DECLCALLBACK(int) iommuAmdR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    3211 {
    3212     /** @todo IOMMU: Load state. */
    3213     RT_NOREF4(pDevIns, pSSM, uVersion, uPass);
    3214     return VERR_NOT_IMPLEMENTED;
    3215 }
    3216 
    3217 
    3218 /**
    3219  * @interface_method_impl{PDMDEVREG,pfnReset}
    3220  */
    3221 static DECLCALLBACK(void) iommuAmdR3Reset(PPDMDEVINS pDevIns)
    3222 {
    3223     iommuAmdR3Init(pDevIns);
    3224 }
    3225 
    3226 
    3227 /**
    32283334 * @interface_method_impl{PDMDEVREG,pfnDestruct}
    32293335 */
     
    33583464
    33593465    /*
    3360      * Initialize parts of the IOMMU state as it would during reset.
    3361      * Must be called -after- initializing PCI config. space registers.
    3362      */
    3363     iommuAmdR3Init(pDevIns);
    3364 
    3365     /*
    33663466     * Register the PCI function with PDM.
    33673467     */
     
    33733473     */
    33743474    rc = PDMDevHlpPCIInterceptConfigAccesses(pDevIns, pPciDev, iommuAmdR3PciConfigRead, iommuAmdR3PciConfigWrite);
    3375     AssertRCReturn(rc, rc);
     3475    AssertLogRelRCReturn(rc, rc);
    33763476
    33773477    /*
     
    33813481                             NULL /* pvUser */, IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED,
    33823482                             "AMD-IOMMU", &pThis->hMmio);
    3383     AssertRCReturn(rc, rc);
     3483    AssertLogRelRCReturn(rc, rc);
    33843484
    33853485    /*
     
    33903490                                NULL, iommuAmdR3SaveExec, NULL,
    33913491                                NULL, iommuAmdR3LoadExec, NULL);
    3392     AssertRCReturn(rc, rc);
     3492    AssertLogRelRCReturn(rc, rc);
    33933493
    33943494    /*
     
    33963496     */
    33973497    rc = PDMDevHlpDBGFInfoRegister(pDevIns, "iommu", "Display IOMMU state.", iommuAmdR3DbgInfo);
    3398     AssertRCReturn(rc, rc);
     3498    AssertLogRelRCReturn(rc, rc);
     3499
     3500    /*
     3501     * Create the command thread and its event semaphore.
     3502     */
     3503    rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->pCmdThread, pThis, iommuAmdR3CmdThread, iommuAmdR3CmdThreadWakeUp,
     3504                               0 /* cbStack */, RTTHREADTYPE_IO, "AMD-IOMMU");
     3505    AssertLogRelRCReturn(rc, rc);
     3506
     3507    rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtCmdThread);
     3508    AssertLogRelRCReturn(rc, rc);
     3509
     3510    /*
     3511     * Initialize parts of the IOMMU state as it would during reset.
     3512     * Must be called -after- initializing PCI config. space registers.
     3513     */
     3514    iommuAmdR3Reset(pDevIns);
    33993515
    34003516    return VINF_SUCCESS;
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