VirtualBox

Ignore:
Timestamp:
Feb 26, 2025 4:41:49 PM (2 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167763
Message:

VMM/GICR3Nem-win.cpp: Some preliminary saved state code in an attempt to get saved states working, the format is not final, bugref:10392

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/GICR3Nem-win.cpp

    r107929 r108398  
    3333#include <iprt/nt/nt-and-windows.h>
    3434#include <iprt/nt/hyperv.h>
     35#include <iprt/mem.h>
    3536#include <WinHvPlatform.h>
    3637
     
    5455*   Defined Constants And Macros                                                                                                 *
    5556*********************************************************************************************************************************/
     57/** The current GIC saved state version. */
     58#define GIC_NEM_SAVED_STATE_VERSION               1
    5659
    5760
     
    110113
    111114
     115typedef struct MY_WHV_INTERRUPT_STATE
     116{
     117    uint8_t                         fState;
     118    uint8_t                         bIPriorityCfg;
     119    uint8_t                         bIPriorityActive;
     120    uint8_t                         bRsvd0;
     121} MY_WHV_INTERRUPT_STATE;
     122AssertCompileSize(MY_WHV_INTERRUPT_STATE, sizeof(uint32_t));
     123
     124#define WHV_INTERRUPT_STATE_F_ENABLED           RT_BIT(0)
     125#define WHV_INTERRUPT_STATE_F_EDGE_TRIGGERED    RT_BIT(1)
     126#define WHV_INTERRUPT_STATE_F_ASSERTED          RT_BIT(2)
     127#define WHV_INTERRUPT_STATE_F_SET_PENDING       RT_BIT(3)
     128#define WHV_INTERRUPT_STATE_F_ACTIVE            RT_BIT(4)
     129#define WHV_INTERRUPT_STATE_F_DIRECT            RT_BIT(5)
     130
     131
     132typedef struct MY_WHV_GLOBAL_INTERRUPT_STATE
     133{
     134    uint32_t                        u32IntId;
     135    uint32_t                        idActiveVp;
     136    uint32_t                        u32TargetMpidrOrVpIndex;
     137    MY_WHV_INTERRUPT_STATE          State;
     138} MY_WHV_GLOBAL_INTERRUPT_STATE;
     139AssertCompileSize(MY_WHV_GLOBAL_INTERRUPT_STATE, 4 * sizeof(uint32_t));
     140
     141
     142typedef struct MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE
     143{
     144    uint8_t                         bVersion;
     145    uint8_t                         bGicVersion;
     146    uint8_t                         abPad[2];
     147
     148    uint32_t                        cInterrupts;
     149    uint64_t                        u64RegGicdCtrlEnableGrp1A;
     150
     151    MY_WHV_GLOBAL_INTERRUPT_STATE   aSpis[1]; /* Flexible */
     152} MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE;
     153AssertCompileSize(MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE, 2 * sizeof(uint32_t) + sizeof(uint64_t) + sizeof(MY_WHV_GLOBAL_INTERRUPT_STATE));
     154
     155#define MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE_VERSION 1
     156
     157
     158typedef struct MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE
     159{
     160    uint8_t                         bVersion;
     161    uint8_t                         bGicVersion;
     162    uint8_t                         abPad[6];
     163
     164    uint64_t                        u64RegIccIGrpEn1El1;
     165    uint64_t                        u64RegGicrCtrlEnableLpis;
     166    uint64_t                        u64RegIccBprEl1;
     167    uint64_t                        u64RegIccPmrEl1;
     168    uint64_t                        u64RegGicrPropBase;
     169    uint64_t                        u64RegGicrPendBase;
     170
     171    uint32_t                        au32RegIchAp1REl2[4];
     172
     173    MY_WHV_INTERRUPT_STATE          aPpiStates[32];
     174} MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE;
     175AssertCompileSize(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, 7 * sizeof(uint64_t) + 4 * sizeof(uint32_t) + 32 * sizeof(MY_WHV_INTERRUPT_STATE));
     176
     177#define MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE_VERSION 1
     178
     179#define MY_WHV_VIRTUAL_PROCESSOR_STATE_TYPE_LOCAL_INTERRUPT_CTRL  (WHV_VIRTUAL_PROCESSOR_STATE_TYPE)0x00001000
     180#define MY_WHV_VIRTUAL_PROCESSOR_STATE_TYPE_GLOBAL_INTERRUPT_CTRL (WHV_VIRTUAL_PROCESSOR_STATE_TYPE)0x00001003
     181
     182
    112183/*********************************************************************************************************************************
    113184*   Global Variables                                                                                                             *
    114185*********************************************************************************************************************************/
    115 extern decltype(WHvRequestInterrupt) *  g_pfnWHvRequestInterrupt;
     186extern decltype(WHvGetVirtualProcessorState) * g_pfnWHvGetVirtualProcessorState;
     187extern decltype(WHvSetVirtualProcessorState) * g_pfnWHvSetVirtualProcessorState;
     188extern decltype(WHvRequestInterrupt) *         g_pfnWHvRequestInterrupt;
    116189
    117190/*
     
    119192 */
    120193#ifndef IN_SLICKEDIT
    121 # define WHvRequestInterrupt                        g_pfnWHvRequestInterrupt
     194# define WHvGetVirtualProcessorState           g_pfnWHvGetVirtualProcessorState
     195# define WHvSetVirtualProcessorState           g_pfnWHvSetVirtualProcessorState
     196# define WHvRequestInterrupt                   g_pfnWHvRequestInterrupt
    122197#endif
     198
     199
     200/** Saved state field descriptors for the global interrupt state. */
     201static const SSMFIELD g_aWHvGicGlobalInterruptState[] =
     202{
     203    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_STATE, u32IntId),
     204    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_STATE, idActiveVp),
     205    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_STATE, u32TargetMpidrOrVpIndex),
     206    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_STATE, State.fState),
     207    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_STATE, State.bIPriorityCfg),
     208    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_STATE, State.bIPriorityActive),
     209    SSMFIELD_ENTRY_TERM()
     210};
     211
     212
     213/** Saved state field descriptors for the global GIC state (sans the flexible interrupts array. */
     214static const SSMFIELD g_aWHvGicGlobalState[] =
     215{
     216    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE, bGicVersion),
     217    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE, cInterrupts),
     218    SSMFIELD_ENTRY(MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE, u64RegGicdCtrlEnableGrp1A),
     219    SSMFIELD_ENTRY_TERM()
     220};
     221
     222
     223#define GIC_NEM_HV_PPI_STATE(a_idx) \
     224    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, aPpiStates[a_idx].fState), \
     225    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, aPpiStates[a_idx].bIPriorityCfg), \
     226    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, aPpiStates[a_idx].bIPriorityActive)
     227
     228
     229/** Saved state field descriptors for the local interrupt controller state. */
     230static const SSMFIELD g_aWHvGicLocalInterruptState[] =
     231{
     232    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, bGicVersion),
     233    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, u64RegIccIGrpEn1El1),
     234    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, u64RegGicrCtrlEnableLpis),
     235    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, u64RegIccBprEl1),
     236    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, u64RegIccPmrEl1),
     237    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, u64RegGicrPropBase),
     238    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, u64RegGicrPendBase),
     239    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, au32RegIchAp1REl2[0]),
     240    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, au32RegIchAp1REl2[1]),
     241    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, au32RegIchAp1REl2[2]),
     242    SSMFIELD_ENTRY(MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE, au32RegIchAp1REl2[3]),
     243    GIC_NEM_HV_PPI_STATE(0),
     244    GIC_NEM_HV_PPI_STATE(1),
     245    GIC_NEM_HV_PPI_STATE(2),
     246    GIC_NEM_HV_PPI_STATE(3),
     247    GIC_NEM_HV_PPI_STATE(4),
     248    GIC_NEM_HV_PPI_STATE(5),
     249    GIC_NEM_HV_PPI_STATE(6),
     250    GIC_NEM_HV_PPI_STATE(7),
     251    GIC_NEM_HV_PPI_STATE(8),
     252    GIC_NEM_HV_PPI_STATE(9),
     253    GIC_NEM_HV_PPI_STATE(10),
     254    GIC_NEM_HV_PPI_STATE(11),
     255    GIC_NEM_HV_PPI_STATE(12),
     256    GIC_NEM_HV_PPI_STATE(13),
     257    GIC_NEM_HV_PPI_STATE(14),
     258    GIC_NEM_HV_PPI_STATE(15),
     259    GIC_NEM_HV_PPI_STATE(16),
     260    GIC_NEM_HV_PPI_STATE(17),
     261    GIC_NEM_HV_PPI_STATE(18),
     262    GIC_NEM_HV_PPI_STATE(19),
     263    GIC_NEM_HV_PPI_STATE(20),
     264    GIC_NEM_HV_PPI_STATE(21),
     265    GIC_NEM_HV_PPI_STATE(22),
     266    GIC_NEM_HV_PPI_STATE(23),
     267    GIC_NEM_HV_PPI_STATE(24),
     268    GIC_NEM_HV_PPI_STATE(25),
     269    GIC_NEM_HV_PPI_STATE(26),
     270    GIC_NEM_HV_PPI_STATE(27),
     271    GIC_NEM_HV_PPI_STATE(28),
     272    GIC_NEM_HV_PPI_STATE(29),
     273    GIC_NEM_HV_PPI_STATE(30),
     274    GIC_NEM_HV_PPI_STATE(31),
     275    SSMFIELD_ENTRY_TERM()
     276};
    123277
    124278
     
    199353
    200354/**
     355 * @copydoc FNSSMDEVSAVEEXEC
     356 */
     357static DECLCALLBACK(int) gicR3HvSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     358{
     359    PGICHVDEV       pThis = PDMDEVINS_2_DATA(pDevIns, PGICHVDEV);
     360    PVM             pVM   = PDMDevHlpGetVM(pDevIns);
     361    PCPDMDEVHLPR3   pHlp  = pDevIns->pHlpR3;
     362
     363    AssertReturn(pVM, VERR_INVALID_VM_HANDLE);
     364
     365    LogFlowFunc(("Enter\n"));
     366
     367    /*
     368     * Save the global interrupt state first.
     369     */
     370    /** @todo The saved state is not final because it would be great if we could have
     371     *        a compatible saved state format between all possible GIC variants (no idea whether this is feasible).
     372     */
     373    uint32_t cbWritten = 0;
     374    HRESULT hrc = WHvGetVirtualProcessorState(pThis->hPartition, WHV_ANY_VP, MY_WHV_VIRTUAL_PROCESSOR_STATE_TYPE_GLOBAL_INTERRUPT_CTRL,
     375                                              NULL, 0, &cbWritten);
     376    AssertLogRelMsgReturn(hrc == WHV_E_INSUFFICIENT_BUFFER,
     377                          ("WHvGetVirtualProcessorState(%p, WHV_ANY_VP, WHvVirtualProcessorStateTypeGlobalInterruptState,) -> %Rhrc (Last=%#x/%u)\n",
     378                           pVM->nem.s.hPartition, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
     379                          , VERR_NEM_GET_REGISTERS_FAILED);
     380
     381    /* Allocate a buffer to write the whole state to based on the amount of interrupts indicated. */
     382    uint32_t const cbState = cbWritten;
     383    MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE *pState = (MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE *)RTMemTmpAllocZ(cbState);
     384    AssertLogRelMsgReturn(pState, ("Allocating %u bytes of memory for the global interrupt state buffer failed\n", cbState),
     385                          VERR_NO_MEMORY);
     386
     387    hrc = WHvGetVirtualProcessorState(pThis->hPartition, WHV_ANY_VP, MY_WHV_VIRTUAL_PROCESSOR_STATE_TYPE_GLOBAL_INTERRUPT_CTRL,
     388                                      pState, cbState, &cbWritten);
     389    AssertLogRelMsg(SUCCEEDED(hrc),
     390                    ("WHvGetVirtualProcessorState(%p, WHV_ANY_VP, WHvVirtualProcessorStateTypeGlobalInterruptState, %p, %u) -> %Rhrc (Last=%#x/%u)\n",
     391                    pVM->nem.s.hPartition, pState, cbState, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
     392    AssertLogRelMsgReturn(cbWritten == cbState,
     393                          ("WHvGetVirtualProcessorState(%p, WHV_ANY_VP, WHvVirtualProcessorStateTypeGlobalInterruptState,) -> cbWritten=%u vs expected=%u\n",
     394                           pVM->nem.s.hPartition, cbWritten, cbState);
     395                          , VERR_NEM_GET_REGISTERS_FAILED);
     396    AssertLogRelMsgReturn(pState->bVersion == MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE_VERSION,
     397                          ("WHvGetVirtualProcessorState(%p, WHV_ANY_VP, WHvVirtualProcessorStateTypeGlobalInterruptState,) -> bVersion=%u vs expected=%u\n",
     398                           pVM->nem.s.hPartition, pState->bVersion, MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE_VERSION);
     399                          , VERR_NEM_GET_REGISTERS_FAILED);
     400
     401    if (SUCCEEDED(hrc))
     402    {
     403        pHlp->pfnSSMPutStruct(pSSM, (const void *)pState, &g_aWHvGicGlobalState[0]);
     404        for (uint32_t i = 0; i < pState->cInterrupts; i++)
     405            pHlp->pfnSSMPutStruct(pSSM, (const void *)&pState->aSpis[i], &g_aWHvGicGlobalInterruptState[0]);
     406    }
     407
     408    RTMemTmpFree(pState);
     409    if (FAILED(hrc))
     410        return VERR_NEM_GET_REGISTERS_FAILED;
     411
     412    /*
     413     * Now for the local interrupt state for each vCPU.
     414     */
     415    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     416    {
     417        MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE LocalState;
     418
     419        hrc = WHvGetVirtualProcessorState(pThis->hPartition, idCpu, MY_WHV_VIRTUAL_PROCESSOR_STATE_TYPE_LOCAL_INTERRUPT_CTRL,
     420                                          &LocalState, sizeof(LocalState), &cbWritten);
     421        AssertLogRelMsgReturn(SUCCEEDED(hrc),
     422                              ("WHvGetVirtualProcessorState(%p, WHV_ANY_VP, WHvVirtualProcessorStateTypeInterruptControllerState2,) -> %Rhrc (Last=%#x/%u)\n",
     423                               pVM->nem.s.hPartition, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
     424                              , VERR_NEM_GET_REGISTERS_FAILED);
     425        AssertLogRelMsgReturn(cbWritten == sizeof(LocalState),
     426                              ("WHvGetVirtualProcessorState(%p, WHV_ANY_VP, WHvVirtualProcessorStateTypeInterruptControllerState2,) -> cbWritten=%u vs expected=%u\n",
     427                               pVM->nem.s.hPartition, cbWritten, sizeof(LocalState));
     428                              , VERR_NEM_GET_REGISTERS_FAILED);
     429        AssertLogRelMsgReturn(LocalState.bVersion == MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE_VERSION,
     430                              ("WHvGetVirtualProcessorState(%p, %u, WHvVirtualProcessorStateTypeInterruptControllerState2,) -> bVersion=%u vs expected=%u\n",
     431                               pVM->nem.s.hPartition, idCpu, LocalState.bVersion, MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE_VERSION);
     432                              , VERR_NEM_GET_REGISTERS_FAILED); 
     433
     434        pHlp->pfnSSMPutStruct(pSSM, (const void *)&LocalState, &g_aWHvGicLocalInterruptState[0]);
     435
     436        /*
     437         * Check that we're still good wrt restored data.
     438         */
     439        int rc = pHlp->pfnSSMHandleGetStatus(pSSM);
     440        AssertRCReturn(rc, rc);
     441    }
     442
     443    return VINF_SUCCESS;
     444}
     445
     446
     447/**
     448 * @copydoc FNSSMDEVLOADEXEC
     449 */
     450static DECLCALLBACK(int) gicR3HvLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
     451{
     452    PGICHVDEV       pThis = PDMDEVINS_2_DATA(pDevIns, PGICHVDEV);
     453    PVM             pVM   = PDMDevHlpGetVM(pDevIns);
     454    PCPDMDEVHLPR3   pHlp  = pDevIns->pHlpR3;
     455
     456    AssertReturn(pVM, VERR_INVALID_VM_HANDLE);
     457    AssertReturn(uPass == SSM_PASS_FINAL, VERR_WRONG_ORDER);
     458
     459    LogFlowFunc(("uVersion=%u uPass=%#x\n", uVersion, uPass));
     460
     461    /* Weed out invalid versions. */
     462    if (uVersion != GIC_NEM_SAVED_STATE_VERSION)
     463    {
     464        LogRel(("GIC: gicR3HvLoadExec: Invalid/unrecognized saved-state version %u (%#x)\n", uVersion, uVersion));
     465        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
     466    }
     467
     468    /*
     469     * Restore the global state.
     470     */
     471    MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE GlobalState; RT_ZERO(GlobalState);
     472    int rc = pHlp->pfnSSMGetStruct(pSSM, &GlobalState, &g_aWHvGicGlobalState[0]);
     473    AssertRCReturn(rc, rc);
     474
     475    if (GlobalState.cInterrupts >= _64K) /* Interrupt IDs are 16-bit. */
     476        return VERR_INVALID_PARAMETER;
     477
     478    /* Calculate size of the final buffer and allocate. */
     479    uint32_t const cbState = RT_UOFFSETOF_DYN(MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE, aSpis[GlobalState.cInterrupts]);
     480    MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE *pState = (MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE *)RTMemTmpAllocZ(cbState);
     481    AssertLogRelMsgReturn(pState, ("Allocating %u bytes of memory for the global interrupt state buffer failed\n", cbState),
     482                          VERR_NO_MEMORY);
     483
     484    pState->bVersion                  = MY_WHV_GLOBAL_INTERRUPT_CONTROLLER_STATE_VERSION;
     485    pState->bGicVersion               = GlobalState.bGicVersion;
     486    pState->cInterrupts               = GlobalState.cInterrupts;
     487    pState->u64RegGicdCtrlEnableGrp1A = GlobalState.u64RegGicdCtrlEnableGrp1A;
     488    for (uint32_t i = 0; i < pState->cInterrupts; i++)
     489    {
     490        rc = pHlp->pfnSSMGetStruct(pSSM, &pState->aSpis[i], &g_aWHvGicGlobalInterruptState[0]);
     491        if (RT_FAILURE(rc))
     492            break;
     493    }
     494    AssertRCReturnStmt(rc, RTMemTmpFree(pState), rc);
     495
     496    HRESULT hrc = WHvSetVirtualProcessorState(pThis->hPartition, WHV_ANY_VP, MY_WHV_VIRTUAL_PROCESSOR_STATE_TYPE_GLOBAL_INTERRUPT_CTRL,
     497                                              pState, cbState);
     498    RTMemTmpFree(pState);
     499    pState = NULL;
     500
     501    AssertLogRelMsgReturn(SUCCEEDED(hrc),
     502                          ("WHvSetVirtualProcessorState(%p, WHV_ANY_VP, WHvVirtualProcessorStateTypeGlobalInterruptState,,%u) -> %Rhrc (Last=%#x/%u)\n",
     503                           pVM->nem.s.hPartition, cbState, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
     504                          , VERR_NEM_SET_REGISTERS_FAILED);
     505
     506    /*
     507     * Restore per CPU state.
     508     */
     509    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     510    {
     511        MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE LocalState;
     512        RT_ZERO(LocalState);
     513
     514        rc = pHlp->pfnSSMGetStruct(pSSM, &LocalState, &g_aWHvGicLocalInterruptState[0]);
     515        AssertRCReturn(rc, rc);
     516
     517        LocalState.bVersion = MY_WHV_LOCAL_INTERRUPT_CONTROLLER_STATE_VERSION;
     518
     519        hrc = WHvSetVirtualProcessorState(pThis->hPartition, idCpu, MY_WHV_VIRTUAL_PROCESSOR_STATE_TYPE_LOCAL_INTERRUPT_CTRL,
     520                                          &LocalState, sizeof(LocalState));
     521        AssertLogRelMsgReturn(SUCCEEDED(hrc),
     522                              ("WHvSetVirtualProcessorState(%p, %u, WHvVirtualProcessorStateTypeInterruptControllerState2,) -> %Rhrc (Last=%#x/%u)\n",
     523                               pVM->nem.s.hPartition, idCpu, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
     524                              , VERR_NEM_SET_REGISTERS_FAILED);
     525    }
     526
     527    return VINF_SUCCESS;
     528}
     529
     530
     531/**
    201532 * @interface_method_impl{PDMDEVREG,pfnReset}
    202533 */
     
    278609        return PDMDEV_SET_ERROR(pDevIns, rc,
    279610                                N_("Configuration error: Failed to get the \"RedistributorMmioBase\" value"));
     611
     612    /*
     613     * Register saved state callbacks.
     614     */
     615    rc = PDMDevHlpSSMRegister(pDevIns, GIC_NEM_SAVED_STATE_VERSION, 0 /*cbGuess*/, gicR3HvSaveExec, gicR3HvLoadExec);
     616    AssertRCReturn(rc, rc);
    280617
    281618    gicR3HvReset(pDevIns);
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