VirtualBox

Changeset 108434 in vbox


Ignore:
Timestamp:
Mar 4, 2025 11:24:21 AM (2 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167808
Message:

VMM/NEM/Hyper-V: Started implementing a NEM/Hyper-V specific APIC emulation utilizing the LocalApicEmulation feature of Hyper-V, bugref:9993

Location:
trunk
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmdev.h

    r107308 r108434  
    755755/** The PDM APIC device registration structure. */
    756756extern const PDMDEVREG g_DeviceAPIC;
     757# if defined(RT_OS_WINDOWS)
     758/** The PDM APIC device registration structure for the Hyper-V NEM. */
     759extern const PDMDEVREG g_DeviceAPICNem;
     760# endif
    757761#elif defined(VBOX_VMM_TARGET_ARMV8)
    758762/** The PDM GIC device registration structure. */
  • trunk/src/VBox/VMM/Makefile.kmk

    r108409 r108434  
    311311 VBoxVMM_SOURCES.linux.amd64 += VMMR3/NEMR3Native-linux.cpp
    312312
    313  VBoxVMM_SOURCES.win.amd64 += VMMR3/NEMR3Native-win.cpp
     313 VBoxVMM_SOURCES.win.amd64 += \
     314        VMMR3/NEMR3Native-win.cpp \
     315        VMMR3/APICR3Nem-win.cpp
     316
    314317 VBoxVMM_DEFS.win.amd64   += VBOX_WITH_NATIVE_NEM
    315318 VBoxVMM_SDKS.win         += VBoxNtDll
  • trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h

    r108076 r108434  
    365365        ADD_REG64(WHvRegisterPendingInterruption, 0);
    366366
    367     /* Interruptibility state.  This can get a little complicated since we get
    368        half of the state via HV_X64_VP_EXECUTION_STATE. */
    369     if (   (fWhat & (CPUMCTX_EXTRN_INHIBIT_INT | CPUMCTX_EXTRN_INHIBIT_NMI))
    370         ==          (CPUMCTX_EXTRN_INHIBIT_INT | CPUMCTX_EXTRN_INHIBIT_NMI) )
    371     {
    372         ADD_REG64(WHvRegisterInterruptState, 0);
    373         if (CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
    374             aValues[iReg - 1].InterruptState.InterruptShadow = 1;
    375         aValues[iReg - 1].InterruptState.NmiMasked = CPUMAreInterruptsInhibitedByNmi(&pVCpu->cpum.GstCtx);
    376     }
    377     else if (fWhat & CPUMCTX_EXTRN_INHIBIT_INT)
    378     {
    379         if (   pVCpu->nem.s.fLastInterruptShadow
    380             || CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
     367    if (!pVM->nem.s.fLocalApicEmulation)
     368    {
     369        /* Interruptibility state.  This can get a little complicated since we get
     370           half of the state via HV_X64_VP_EXECUTION_STATE. */
     371        if (   (fWhat & (CPUMCTX_EXTRN_INHIBIT_INT | CPUMCTX_EXTRN_INHIBIT_NMI))
     372            ==          (CPUMCTX_EXTRN_INHIBIT_INT | CPUMCTX_EXTRN_INHIBIT_NMI) )
    381373        {
    382374            ADD_REG64(WHvRegisterInterruptState, 0);
    383375            if (CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
    384376                aValues[iReg - 1].InterruptState.InterruptShadow = 1;
    385             /** @todo Retrieve NMI state, currently assuming it's zero. (yes this may happen on I/O) */
    386             //if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
    387             //    aValues[iReg - 1].InterruptState.NmiMasked = 1;
    388         }
    389     }
    390     else
    391         Assert(!(fWhat & CPUMCTX_EXTRN_INHIBIT_NMI));
    392 
    393     /* Interrupt windows. Always set if active as Hyper-V seems to be forgetful. */
    394     uint8_t const fDesiredIntWin = pVCpu->nem.s.fDesiredInterruptWindows;
    395     if (   fDesiredIntWin
    396         || pVCpu->nem.s.fCurrentInterruptWindows != fDesiredIntWin)
    397     {
    398         pVCpu->nem.s.fCurrentInterruptWindows = pVCpu->nem.s.fDesiredInterruptWindows;
    399         Log8(("Setting WHvX64RegisterDeliverabilityNotifications, fDesiredIntWin=%X\n", fDesiredIntWin));
    400         ADD_REG64(WHvX64RegisterDeliverabilityNotifications, fDesiredIntWin);
    401         Assert(aValues[iReg - 1].DeliverabilityNotifications.NmiNotification == RT_BOOL(fDesiredIntWin & NEM_WIN_INTW_F_NMI));
    402         Assert(aValues[iReg - 1].DeliverabilityNotifications.InterruptNotification == RT_BOOL(fDesiredIntWin & NEM_WIN_INTW_F_REGULAR));
    403         Assert(aValues[iReg - 1].DeliverabilityNotifications.InterruptPriority == (unsigned)((fDesiredIntWin & NEM_WIN_INTW_F_PRIO_MASK) >> NEM_WIN_INTW_F_PRIO_SHIFT));
    404     }
    405 
    406     /// @todo WHvRegisterPendingEvent
     377            aValues[iReg - 1].InterruptState.NmiMasked = CPUMAreInterruptsInhibitedByNmi(&pVCpu->cpum.GstCtx);
     378        }
     379        else if (fWhat & CPUMCTX_EXTRN_INHIBIT_INT)
     380        {
     381            if (   pVCpu->nem.s.fLastInterruptShadow
     382                || CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
     383            {
     384                ADD_REG64(WHvRegisterInterruptState, 0);
     385                if (CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
     386                    aValues[iReg - 1].InterruptState.InterruptShadow = 1;
     387                /** @todo Retrieve NMI state, currently assuming it's zero. (yes this may happen on I/O) */
     388                //if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
     389                //    aValues[iReg - 1].InterruptState.NmiMasked = 1;
     390            }
     391        }
     392        else
     393            Assert(!(fWhat & CPUMCTX_EXTRN_INHIBIT_NMI));
     394
     395        /* Interrupt windows. Always set if active as Hyper-V seems to be forgetful. */
     396        uint8_t const fDesiredIntWin = pVCpu->nem.s.fDesiredInterruptWindows;
     397        if (   fDesiredIntWin
     398            || pVCpu->nem.s.fCurrentInterruptWindows != fDesiredIntWin)
     399        {
     400            pVCpu->nem.s.fCurrentInterruptWindows = pVCpu->nem.s.fDesiredInterruptWindows;
     401            Log8(("Setting WHvX64RegisterDeliverabilityNotifications, fDesiredIntWin=%X\n", fDesiredIntWin));
     402            ADD_REG64(WHvX64RegisterDeliverabilityNotifications, fDesiredIntWin);
     403            Assert(aValues[iReg - 1].DeliverabilityNotifications.NmiNotification == RT_BOOL(fDesiredIntWin & NEM_WIN_INTW_F_NMI));
     404            Assert(aValues[iReg - 1].DeliverabilityNotifications.InterruptNotification == RT_BOOL(fDesiredIntWin & NEM_WIN_INTW_F_REGULAR));
     405            Assert(aValues[iReg - 1].DeliverabilityNotifications.InterruptPriority == (unsigned)((fDesiredIntWin & NEM_WIN_INTW_F_PRIO_MASK) >> NEM_WIN_INTW_F_PRIO_SHIFT));
     406        }
     407    }
     408    else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC))
     409    {
     410        Log8(("Setting WHvX64RegisterDeliverabilityNotifications, fDesiredIntWin=%X fPicReadyForInterrupt=%RTbool\n",
     411              pVCpu->nem.s.fDesiredInterruptWindows, pVCpu->nem.s.fPicReadyForInterrupt));
     412
     413        if (   pVCpu->nem.s.fDesiredInterruptWindows
     414            && pVCpu->nem.s.fPicReadyForInterrupt)
     415        {
     416            ADD_REG64(WHvRegisterPendingEvent, 0);
     417
     418            uint8_t bInterrupt;
     419            int rc = PDMGetInterrupt(pVCpu, &bInterrupt);
     420            AssertRC(rc);
     421
     422            aValues[iReg - 1].Reg64                    = 0;
     423            aValues[iReg - 1].ExtIntEvent.EventPending = 1;
     424            aValues[iReg - 1].ExtIntEvent.EventType    = WHvX64PendingEventExtInt;
     425            aValues[iReg - 1].ExtIntEvent.Vector       = bInterrupt;
     426        }
     427
     428        if (!pVCpu->nem.s.fIrqWindowRegistered)
     429        {
     430            ADD_REG64(WHvX64RegisterDeliverabilityNotifications, 0);
     431            aValues[iReg - 1].DeliverabilityNotifications.InterruptNotification = 1;
     432            pVCpu->nem.s.fIrqWindowRegistered = true;
     433        }
     434    }
    407435
    408436#undef ADD_REG64
     
    419447           pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues));
    420448#endif
     449
     450    pVCpu->nem.s.fPicReadyForInterrupt = false;
     451
     452    if (!iReg)
     453        return VINF_SUCCESS;
     454
    421455    HRESULT hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues);
    422456    if (SUCCEEDED(hrc))
     
    17611795          pExit->InterruptWindow.DeliverableType, RT_BOOL(pExit->VpContext.Rflags & X86_EFL_IF),
    17621796          pExit->VpContext.ExecutionState.InterruptShadow, pExit->VpContext.Cr8));
     1797
     1798    pVCpu->nem.s.fIrqWindowRegistered  = false;
     1799    pVCpu->nem.s.fPicReadyForInterrupt = true;
    17631800
    17641801    /** @todo call nemHCWinHandleInterruptFF   */
     
    23662403            return nemR3WinHandleExitUnrecoverableException(pVM, pVCpu, pExit);
    23672404
     2405        case WHvRunVpExitReasonX64ApicEoi:
     2406            Assert(pVM->nem.s.fLocalApicEmulation);
     2407            PDMIoApicBroadcastEoi(pVCpu->CTX_SUFF(pVM), pExit->ApicEoi.InterruptVector);
     2408            return VINF_SUCCESS;
     2409
    23682410        case WHvRunVpExitReasonUnsupportedFeature:
    23692411        case WHvRunVpExitReasonInvalidVpRegisterValue:
     
    23912433NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleInterruptFF(PVMCC pVM, PVMCPUCC pVCpu, uint8_t *pfInterruptWindows)
    23922434{
    2393     Assert(!TRPMHasTrap(pVCpu));
     2435    Assert(!TRPMHasTrap(pVCpu) && !pVM->nem.s.fLocalApicEmulation);
    23942436    RT_NOREF_PV(pVM);
    23952437
     
    25482590         */
    25492591        pVCpu->nem.s.fDesiredInterruptWindows = 0;
    2550         if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_PIC
    2551                                      | VMCPU_FF_INTERRUPT_NMI  | VMCPU_FF_INTERRUPT_SMI))
    2552         {
    2553             /* Try inject interrupt. */
    2554             rcStrict = nemHCWinHandleInterruptFF(pVM, pVCpu, &pVCpu->nem.s.fDesiredInterruptWindows);
    2555             if (rcStrict == VINF_SUCCESS)
    2556             { /* likely */ }
    2557             else
     2592        if (!pVM->nem.s.fLocalApicEmulation)
     2593        {
     2594            if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_PIC
     2595                                         | VMCPU_FF_INTERRUPT_NMI  | VMCPU_FF_INTERRUPT_SMI))
    25582596            {
    2559                 LogFlow(("NEM/%u: breaking: nemHCWinHandleInterruptFF -> %Rrc\n", pVCpu->idCpu, VBOXSTRICTRC_VAL(rcStrict) ));
    2560                 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatBreakOnStatus);
    2561                 break;
     2597                /* Try inject interrupt. */
     2598                rcStrict = nemHCWinHandleInterruptFF(pVM, pVCpu, &pVCpu->nem.s.fDesiredInterruptWindows);
     2599                if (rcStrict == VINF_SUCCESS)
     2600                { /* likely */ }
     2601                else
     2602                {
     2603                    LogFlow(("NEM/%u: breaking: nemHCWinHandleInterruptFF -> %Rrc\n", pVCpu->idCpu, VBOXSTRICTRC_VAL(rcStrict) ));
     2604                    STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatBreakOnStatus);
     2605                    break;
     2606                }
    25622607            }
     2608        }
     2609        else
     2610        {
     2611            /* We only need to handle the PIC usign ExtInt here, the APIC is handled through the NEM APIC backend. */
     2612            Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC));
     2613
     2614            if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC))
     2615                pVCpu->nem.s.fDesiredInterruptWindows |= NEM_WIN_INTW_F_REGULAR;
    25632616        }
    25642617
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r107931 r108434  
    163163static decltype(WHvGetVirtualProcessorRegisters) *  g_pfnWHvGetVirtualProcessorRegisters;
    164164static decltype(WHvSetVirtualProcessorRegisters) *  g_pfnWHvSetVirtualProcessorRegisters;
     165static decltype(WHvSuspendPartitionTime) *          g_pfnWHvSuspendPartitionTime;
     166static decltype(WHvResumePartitionTime) *           g_pfnWHvResumePartitionTime;
     167decltype(WHvGetVirtualProcessorState) *             g_pfnWHvGetVirtualProcessorState = NULL;
     168decltype(WHvSetVirtualProcessorState) *             g_pfnWHvSetVirtualProcessorState = NULL;
     169decltype(WHvGetVirtualProcessorInterruptControllerState)  *g_pfnWHvGetVirtualProcessorInterruptControllerState = NULL;
     170decltype(WHvSetVirtualProcessorInterruptControllerState)  *g_pfnWHvSetVirtualProcessorInterruptControllerState = NULL;
     171decltype(WHvGetVirtualProcessorInterruptControllerState2) *g_pfnWHvGetVirtualProcessorInterruptControllerState2 = NULL;
     172decltype(WHvSetVirtualProcessorInterruptControllerState2) *g_pfnWHvSetVirtualProcessorInterruptControllerState2 = NULL;
     173decltype(WHvRequestInterrupt) *                     g_pfnWHvRequestInterrupt;
    165174/** @} */
    166175
     
    213222    NEM_WIN_IMPORT(0, false, WHvGetVirtualProcessorRegisters),
    214223    NEM_WIN_IMPORT(0, false, WHvSetVirtualProcessorRegisters),
     224    NEM_WIN_IMPORT(0, true,  WHvSuspendPartitionTime),
     225    NEM_WIN_IMPORT(0, true,  WHvResumePartitionTime),
     226    NEM_WIN_IMPORT(0, true,  WHvRequestInterrupt),
     227    NEM_WIN_IMPORT(0, true,  WHvGetVirtualProcessorState),
     228    NEM_WIN_IMPORT(0, true,  WHvSetVirtualProcessorState),
     229    NEM_WIN_IMPORT(0, true,  WHvGetVirtualProcessorInterruptControllerState),
     230    NEM_WIN_IMPORT(0, true,  WHvSetVirtualProcessorInterruptControllerState),
     231    NEM_WIN_IMPORT(0, true,  WHvGetVirtualProcessorInterruptControllerState2),
     232    NEM_WIN_IMPORT(0, true,  WHvSetVirtualProcessorInterruptControllerState2),
    215233
    216234    NEM_WIN_IMPORT(1, true,  VidGetHvPartitionId),
     
    285303# define WHvGetVirtualProcessorRegisters            g_pfnWHvGetVirtualProcessorRegisters
    286304# define WHvSetVirtualProcessorRegisters            g_pfnWHvSetVirtualProcessorRegisters
     305# define WHvSuspendPartitionTime                    g_pfnWHvSuspendPartitionTime
     306# define WHvResumePartitionTime                     g_pfnWHvResumePartitionTime
     307# define WHvRequestInterrupt                        g_pfnWHvRequestInterrupt
     308# define WHvGetVirtualProcessorState                g_pfnWHvGetVirtualProcessorState
     309# define WHvSetVirtualProcessorState                g_pfnWHvSetVirtualProcessorState
     310# define WHvGetVirtualProcessorInterruptControllerState     g_pfnWHvGetVirtualProcessorInterruptControllerState
     311# define WHvGetVirtualProcessorInterruptControllerState2    g_pfnWHvGetVirtualProcessorInterruptControllerState2
    287312
    288313# define VidMessageSlotHandleAndGetNext             g_pfnVidMessageSlotHandleAndGetNext
     
    585610                *g_aImports[i].ppfn = NULL;
    586611
    587                 LogRel(("NEM:  %s: Failed to import %s!%s: %Rrc",
     612                LogRel(("NEM:  %s: Failed to import %s!%s: %Rrc\n",
    588613                        g_aImports[i].fOptional ? "info" : fForced ? "fatal" : "error",
    589614                        s_apszDllNames[g_aImports[i].idxDll], g_aImports[i].pszName, rc2));
     
    740765        NEM_LOG_REL_CAP_SUB_EX("Unknown features", "%#RX64", Caps.ExtendedVmExits.AsUINT64 & ~fKnownVmExits);
    741766    pVM->nem.s.fSpeculationControl = RT_BOOL(Caps.Features.SpeculationControl);
     767    pVM->nem.s.fLocalApicEmulation = RT_BOOL(Caps.Features.LocalApicEmulation);
    742768    /** @todo RECHECK: WHV_CAPABILITY_FEATURES typedef. */
    743769
     
    12551281                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    12561282
    1257     int rc;
     1283    int rc = VINF_SUCCESS;
    12581284
    12591285    /*
     
    12811307        if (SUCCEEDED(hrc))
    12821308        {
     1309            RT_ZERO(Property);
    12831310            /*
    1284              * We'll continue setup in nemR3NativeInitAfterCPUM.
     1311             * If the APIC is enabled and LocalApicEmulation is supported we'll use Hyper-V's APIC emulation
     1312             * for best performance.
    12851313             */
    1286             pVM->nem.s.fCreatedEmts     = false;
    1287             pVM->nem.s.hPartition       = hPartition;
    1288             LogRel(("NEM: Created partition %p.\n", hPartition));
    1289             return VINF_SUCCESS;
     1314            PCFGMNODE pCfgmApic = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/Devices/apic");
     1315            if (   pCfgmApic
     1316                && pVM->nem.s.fLocalApicEmulation
     1317                && 0) /** @todo Finish */
     1318            {
     1319                /* If setting this fails log an error but continue. */
     1320                Property.LocalApicEmulationMode = WHvX64LocalApicEmulationModeXApic;
     1321                hrc = WHvSetPartitionProperty(hPartition, WHvPartitionPropertyCodeLocalApicEmulationMode  , &Property, sizeof(Property));
     1322                if (FAILED(hrc))
     1323                {
     1324                    LogRel(("NEM: Failed setting WHvPartitionPropertyCodeLocalApicEmulationMode to WHvX64LocalApicEmulationModeXApic: %Rhrc (Last=%#x/%u)",
     1325                            hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     1326                    pVM->nem.s.fLocalApicEmulation = false;
     1327                }
     1328                else
     1329                {
     1330                    /* Rewrite the configuration tree to point to our APIC emulation. */
     1331                    PCFGMNODE pCfgmDev = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/Devices");
     1332                    Assert(pCfgmDev);
     1333
     1334                    PCFGMNODE pCfgmApicHv = NULL;
     1335                    rc = CFGMR3InsertNode(pCfgmDev, "apic-nem", &pCfgmApicHv);
     1336                    if (RT_SUCCESS(rc))
     1337                    {
     1338                        rc = CFGMR3CopyTree(pCfgmApicHv, pCfgmApic, CFGM_COPY_FLAGS_IGNORE_EXISTING_KEYS | CFGM_COPY_FLAGS_IGNORE_EXISTING_VALUES);
     1339                        if (RT_SUCCESS(rc))
     1340                            CFGMR3RemoveNode(pCfgmApic);
     1341                    }
     1342
     1343                    if (RT_FAILURE(rc))
     1344                        rc = RTErrInfoSetF(pErrInfo, rc, "Failed replace APIC device config with Hyper-V one");
     1345                }
     1346            }
     1347            else
     1348                pVM->nem.s.fLocalApicEmulation = false;
     1349
     1350
     1351            if (RT_SUCCESS(rc))
     1352            {
     1353                /*
     1354                 * We'll continue setup in nemR3NativeInitAfterCPUM.
     1355                 */
     1356                pVM->nem.s.fCreatedEmts     = false;
     1357                pVM->nem.s.hPartition       = hPartition;
     1358                LogRel(("NEM: Created partition %p.\n", hPartition));
     1359                return VINF_SUCCESS;
     1360            }
    12901361        }
    12911362
     
    13211392     */
    13221393    PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/Devices/apic/0/Config");
     1394    if (!pCfg)
     1395        pCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/Devices/apic-nem/0/Config");
    13231396    if (pCfg)
    13241397    {
  • trunk/src/VBox/VMM/VMMR3/PDMDevice.cpp

    r107308 r108434  
    721721    int rc = pdmR3DevReg_Register(&RegCB.Core, &g_DeviceAPIC);
    722722    AssertRCReturn(rc, rc);
     723
     724# if defined(RT_OS_WINDOWS)
     725    /* Register the internal VMM APIC device for NEM mode. */
     726    rc = pdmR3DevReg_Register(&RegCB.Core, &g_DeviceAPICNem);
     727    AssertRCReturn(rc, rc);
     728# endif
    723729#endif
    724730
  • trunk/src/VBox/VMM/include/APICInternal.h

    r107113 r108434  
    4646/** The VirtualBox APIC backend table. */
    4747extern const PDMAPICBACKEND g_ApicBackend;
     48#if defined(RT_OS_WINDOWS)
     49/** The Hyper-V APIC backend. */
     50extern const PDMAPICBACKEND g_ApicNemBackend;
     51# endif
    4852#endif
    4953
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r108413 r108434  
    267267    /** Whether to export/import IA32_SPEC_CTRL. */
    268268    bool                        fDoIa32SpecCtrl : 1;
     269    /** WHvX64LocalApicEmulationModeXApic is used. */
     270    bool                        fLocalApicEmulation : 1;
    269271#  ifdef NEM_WIN_WITH_A20
    270272    /** Set if we've started more than one CPU and cannot mess with A20. */
     
    284286        uint64_t                u64;
    285287# ifdef _WINHVAPIDEFS_H_
    286         /** Interpreed features. */
     288        /** Interpreted features. */
    287289        WHV_PROCESSOR_FEATURES  u;
    288290# endif
     
    513515    /** The desired state of the interrupt windows (NEM_WIN_INTW_F_XXX). */
    514516    uint8_t                     fDesiredInterruptWindows;
     517    /** Cached TPR value. */
     518    uint8_t                     bTpr;
    515519    /** Last copy of HV_X64_VP_EXECUTION_STATE::InterruptShadow. */
    516520    bool                        fLastInterruptShadow : 1;
     521    /** Flag whether the IRQ window notification was registered (for injecting PIC interrupts). */
     522    bool                        fIrqWindowRegistered: 1;
     523    /** Flag whether it is possible inject a PIC interrupt. */
     524    bool                        fPicReadyForInterrupt: 1;
    517525    uint32_t                    uPadding;
    518526    /** The VID_MSHAGN_F_XXX flags.
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