VirtualBox

Changeset 100756 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jul 31, 2023 2:14:17 PM (17 months ago)
Author:
vboxsync
Message:

VMM/GICR3: Add some preliminary saved state handling, bugref:10404

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/GICR3.cpp

    r100165 r100756  
    5050*   Defined Constants And Macros                                                                                                 *
    5151*********************************************************************************************************************************/
     52/** Some ancient version... */
     53#define GIC_SAVED_STATE_VERSION                     1
     54
    5255# define GIC_SYSREGRANGE(a_uFirst, a_uLast, a_szName) \
    5356    { (a_uFirst), (a_uLast), kCpumSysRegRdFn_GicV3Icc, kCpumSysRegWrFn_GicV3Icc, 0, 0, 0, 0, 0, 0, a_szName, { 0 }, { 0 }, { 0 }, { 0 } }
     
    153156
    154157/**
     158 * Worker for saving per-VM GIC data.
     159 *
     160 * @returns VBox status code.
     161 * @param   pDevIns     The device instance.
     162 * @param   pVM     The cross context VM structure.
     163 * @param   pSSM    The SSM handle.
     164 */
     165static int gicR3SaveVMData(PPDMDEVINS pDevIns, PVM pVM, PSSMHANDLE pSSM)
     166{
     167    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
     168    PGICDEV         pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
     169
     170    pHlp->pfnSSMPutU32( pSSM, pVM->cCpus);
     171    pHlp->pfnSSMPutU32( pSSM, GIC_SPI_MAX);
     172    pHlp->pfnSSMPutU32( pSSM, pGicDev->u32RegIGrp0);
     173    pHlp->pfnSSMPutU32( pSSM, pGicDev->u32RegICfg0);
     174    pHlp->pfnSSMPutU32( pSSM, pGicDev->u32RegICfg1);
     175    pHlp->pfnSSMPutU32( pSSM, pGicDev->bmIntEnabled);
     176    pHlp->pfnSSMPutU32( pSSM, pGicDev->bmIntPending);
     177    pHlp->pfnSSMPutU32( pSSM, pGicDev->bmIntActive);
     178    pHlp->pfnSSMPutMem( pSSM, (void *)&pGicDev->abIntPriority[0], sizeof(pGicDev->abIntPriority));
     179    pHlp->pfnSSMPutBool(pSSM, pGicDev->fIrqGrp0Enabled);
     180
     181    return pHlp->pfnSSMPutBool(pSSM, pGicDev->fIrqGrp1Enabled);
     182}
     183
     184
     185/**
     186 * Worker for loading per-VM GIC data.
     187 *
     188 * @returns VBox status code.
     189 * @param   pDevIns     The device instance.
     190 * @param   pVM     The cross context VM structure.
     191 * @param   pSSM    The SSM handle.
     192 */
     193static int gicR3LoadVMData(PPDMDEVINS pDevIns, PVM pVM, PSSMHANDLE pSSM)
     194{
     195    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
     196    PGICDEV         pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
     197
     198    /* Load and verify number of CPUs. */
     199    uint32_t cCpus;
     200    int rc = pHlp->pfnSSMGetU32(pSSM, &cCpus);
     201    AssertRCReturn(rc, rc);
     202    if (cCpus != pVM->cCpus)
     203        return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - cCpus: saved=%u config=%u"), cCpus, pVM->cCpus);
     204
     205    /* Load and verify maximum number of SPIs. */
     206    uint32_t cSpisMax;
     207    rc = pHlp->pfnSSMGetU32(pSSM, &cSpisMax);
     208    AssertRCReturn(rc, rc);
     209    if (cSpisMax != GIC_SPI_MAX)
     210        return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - cSpisMax: saved=%u config=%u"),
     211                                       cSpisMax, GIC_SPI_MAX);
     212
     213    /* Load the state. */
     214    pHlp->pfnSSMGetU32V( pSSM, &pGicDev->u32RegIGrp0);
     215    pHlp->pfnSSMGetU32V( pSSM, &pGicDev->u32RegICfg0);
     216    pHlp->pfnSSMGetU32V( pSSM, &pGicDev->u32RegICfg1);
     217    pHlp->pfnSSMGetU32V( pSSM, &pGicDev->bmIntEnabled);
     218    pHlp->pfnSSMGetU32V( pSSM, &pGicDev->bmIntPending);
     219    pHlp->pfnSSMGetU32V( pSSM, &pGicDev->bmIntActive);
     220    pHlp->pfnSSMGetMem(  pSSM, (void *)&pGicDev->abIntPriority[0], sizeof(pGicDev->abIntPriority));
     221    pHlp->pfnSSMGetBoolV(pSSM, &pGicDev->fIrqGrp0Enabled);
     222    pHlp->pfnSSMGetBoolV(pSSM, &pGicDev->fIrqGrp1Enabled);
     223
     224    return VINF_SUCCESS;
     225}
     226
     227
     228/**
     229 * @copydoc FNSSMDEVSAVEEXEC
     230 */
     231static DECLCALLBACK(int) gicR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     232{
     233    PVM             pVM  = PDMDevHlpGetVM(pDevIns);
     234    PCPDMDEVHLPR3   pHlp = pDevIns->pHlpR3;
     235
     236    AssertReturn(pVM, VERR_INVALID_VM_HANDLE);
     237
     238    LogFlow(("GIC: gicR3SaveExec\n"));
     239
     240    /* Save per-VM data. */
     241    int rc = gicR3SaveVMData(pDevIns, pVM, pSSM);
     242    AssertRCReturn(rc, rc);
     243
     244    /* Save per-VCPU data.*/
     245    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     246    {
     247        PVMCPU pVCpu = pVM->apCpusR3[idCpu];
     248        PGICCPU pGicVCpu = VMCPU_TO_GICCPU(pVCpu);
     249
     250        /* Load the redistributor state. */
     251        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->u32RegIGrp0);
     252        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->u32RegICfg0);
     253        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->u32RegICfg1);
     254        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->bmIntEnabled);
     255        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->bmIntPending);
     256        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->bmIntActive);
     257        pHlp->pfnSSMPutMem(pSSM, (void *)&pGicVCpu->abIntPriority[0], sizeof(pGicVCpu->abIntPriority));
     258
     259        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->fIrqGrp0Enabled);
     260        pHlp->pfnSSMPutU32(pSSM, pGicVCpu->fIrqGrp1Enabled);
     261        pHlp->pfnSSMPutU8( pSSM, pGicVCpu->bInterruptPriority);
     262        pHlp->pfnSSMPutU8( pSSM, pGicVCpu->bBinaryPointGrp0);
     263        pHlp->pfnSSMPutU8( pSSM, pGicVCpu->bBinaryPointGrp1);
     264        pHlp->pfnSSMPutMem(pSSM, (void *)&pGicVCpu->abRunningPriorities[0], sizeof(pGicVCpu->abRunningPriorities));
     265        pHlp->pfnSSMPutU8( pSSM, pGicVCpu->idxRunningPriority);
     266    }
     267
     268    return rc;
     269}
     270
     271
     272/**
     273 * @copydoc FNSSMDEVLOADEXEC
     274 */
     275static DECLCALLBACK(int) gicR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
     276{
     277    PVM             pVM  = PDMDevHlpGetVM(pDevIns);
     278    PCPDMDEVHLPR3   pHlp = pDevIns->pHlpR3;
     279
     280    AssertReturn(pVM, VERR_INVALID_VM_HANDLE);
     281    AssertReturn(uPass == SSM_PASS_FINAL, VERR_WRONG_ORDER);
     282
     283    LogFlow(("GIC: gicR3LoadExec: uVersion=%u uPass=%#x\n", uVersion, uPass));
     284
     285    /* Weed out invalid versions. */
     286    if (uVersion != GIC_SAVED_STATE_VERSION)
     287    {
     288        LogRel(("GIC: gicR3LoadExec: Invalid/unrecognized saved-state version %u (%#x)\n", uVersion, uVersion));
     289        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
     290    }
     291
     292    int rc = gicR3LoadVMData(pDevIns, pVM, pSSM);
     293    AssertRCReturn(rc, rc);
     294
     295    /*
     296     * Restore per CPU state.
     297     *
     298     * Note! PDM will restore the VMCPU_FF_INTERRUPT_IRQ and VMCPU_FF_INTERRUPT_FIQ flags for us.
     299     *       This code doesn't touch it.  No devices should make us touch
     300     *       it later during the restore either, only during the 'done' phase.
     301     */
     302    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     303    {
     304        PVMCPU  pVCpu    = pVM->apCpusR3[idCpu];
     305        PGICCPU pGicVCpu = VMCPU_TO_GICCPU(pVCpu);
     306
     307        /* Load the redistributor state. */
     308        pHlp->pfnSSMGetU32V(    pSSM, &pGicVCpu->u32RegIGrp0);
     309        pHlp->pfnSSMGetU32V(    pSSM, &pGicVCpu->u32RegICfg0);
     310        pHlp->pfnSSMGetU32V(    pSSM, &pGicVCpu->u32RegICfg1);
     311        pHlp->pfnSSMGetU32V(    pSSM, &pGicVCpu->bmIntEnabled);
     312        pHlp->pfnSSMGetU32V(    pSSM, &pGicVCpu->bmIntPending);
     313        pHlp->pfnSSMGetU32V(    pSSM, &pGicVCpu->bmIntActive);
     314        pHlp->pfnSSMGetMem(     pSSM, (void *)&pGicVCpu->abIntPriority[0], sizeof(pGicVCpu->abIntPriority));
     315
     316        pHlp->pfnSSMGetBoolV(   pSSM, &pGicVCpu->fIrqGrp0Enabled);
     317        pHlp->pfnSSMGetBoolV(   pSSM, &pGicVCpu->fIrqGrp1Enabled);
     318        pHlp->pfnSSMGetU8V(     pSSM, &pGicVCpu->bInterruptPriority);
     319        pHlp->pfnSSMGetU8(      pSSM, &pGicVCpu->bBinaryPointGrp0);
     320        pHlp->pfnSSMGetU8(      pSSM, &pGicVCpu->bBinaryPointGrp1);
     321        pHlp->pfnSSMGetMem(     pSSM, (void *)&pGicVCpu->abRunningPriorities[0], sizeof(pGicVCpu->abRunningPriorities));
     322        rc = pHlp->pfnSSMGetU8V(pSSM, &pGicVCpu->idxRunningPriority);
     323        if (RT_FAILURE(rc))
     324            return rc;
     325    }
     326
     327    return rc;
     328}
     329
     330
     331/**
    155332 * @interface_method_impl{PDMDEVREG,pfnReset}
    156333 */
     
    283460
    284461    /*
     462     * Register saved state callbacks.
     463     */
     464    rc = PDMDevHlpSSMRegister(pDevIns, GIC_SAVED_STATE_VERSION, 0, gicR3SaveExec, gicR3LoadExec);
     465    AssertRCReturn(rc, rc);
     466
     467    /*
    285468     * Register debugger info callbacks.
    286469     *
Note: See TracChangeset for help on using the changeset viewer.

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