VirtualBox

Changeset 32557 in vbox


Ignore:
Timestamp:
Sep 16, 2010 12:35:25 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
65948
Message:

PCI: saved state code in ICH9

File:
1 edited

Legend:

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

    r32491 r32557  
    733733        if (pDev)
    734734        {
     735            /* Device position */
    735736            SSMR3PutU32(pSSM, i);
     737            /* PCI config registers */
    736738            SSMR3PutMem(pSSM, pDev->config, sizeof(pDev->config));
    737739
     740            /* IRQ pin state */
    738741            int rc = SSMR3PutS32(pSSM, pDev->Int.s.uIrqPinState);
    739742            if (RT_FAILURE(rc))
     
    757760}
    758761
     762
     763/**
     764 * Common routine for restoring the config registers of a PCI device.
     765 *
     766 * @param   pDev                The PCI device.
     767 * @param   pbSrcConfig         The configuration register values to be loaded.
     768 * @param   fIsBridge           Whether this is a bridge device or not.
     769 */
     770static void pciR3CommonRestoreConfig(PPCIDEVICE pDev, uint8_t const *pbSrcConfig, bool fIsBridge)
     771{
     772    /*
     773     * This table defines the fields for normal devices and bridge devices, and
     774     * the order in which they need to be restored.
     775     */
     776    static const struct PciField
     777    {
     778        uint8_t     off;
     779        uint8_t     cb;
     780        uint8_t     fWritable;
     781        uint8_t     fBridge;
     782        const char *pszName;
     783    } s_aFields[] =
     784    {
     785        /* off,cb,fW,fB, pszName */
     786        { VBOX_PCI_VENDOR_ID, 2, 0, 3, "VENDOR_ID" },
     787        { VBOX_PCI_DEVICE_ID, 2, 0, 3, "DEVICE_ID" },
     788        { VBOX_PCI_STATUS, 2, 1, 3, "STATUS" },
     789        { VBOX_PCI_REVISION_ID, 1, 0, 3, "REVISION_ID" },
     790        { VBOX_PCI_CLASS_PROG, 1, 0, 3, "CLASS_PROG" },
     791        { VBOX_PCI_CLASS_SUB, 1, 0, 3, "CLASS_SUB" },
     792        { VBOX_PCI_CLASS_DEVICE, 1, 0, 3, "CLASS_BASE" },
     793        { VBOX_PCI_CACHE_LINE_SIZE, 1, 1, 3, "CACHE_LINE_SIZE" },
     794        { VBOX_PCI_LATENCY_TIMER, 1, 1, 3, "LATENCY_TIMER" },
     795        { VBOX_PCI_HEADER_TYPE, 1, 0, 3, "HEADER_TYPE" },
     796        { VBOX_PCI_BIST, 1, 1, 3, "BIST" },
     797        { VBOX_PCI_BASE_ADDRESS_0, 4, 1, 3, "BASE_ADDRESS_0" },
     798        { VBOX_PCI_BASE_ADDRESS_1, 4, 1, 3, "BASE_ADDRESS_1" },
     799        { VBOX_PCI_BASE_ADDRESS_2, 4, 1, 1, "BASE_ADDRESS_2" },
     800        { VBOX_PCI_PRIMARY_BUS, 1, 1, 2, "PRIMARY_BUS" },       // fWritable = ??
     801        { VBOX_PCI_SECONDARY_BUS, 1, 1, 2, "SECONDARY_BUS" },     // fWritable = ??
     802        { VBOX_PCI_SUBORDINATE_BUS, 1, 1, 2, "SUBORDINATE_BUS" },   // fWritable = ??
     803        { VBOX_PCI_SEC_LATENCY_TIMER, 1, 1, 2, "SEC_LATENCY_TIMER" }, // fWritable = ??
     804        { VBOX_PCI_BASE_ADDRESS_3, 4, 1, 1, "BASE_ADDRESS_3" },
     805        { VBOX_PCI_IO_BASE, 1, 1, 2, "IO_BASE" },           // fWritable = ??
     806        { VBOX_PCI_IO_LIMIT, 1, 1, 2, "IO_LIMIT" },          // fWritable = ??
     807        { VBOX_PCI_SEC_STATUS, 2, 1, 2, "SEC_STATUS" },        // fWritable = ??
     808        { VBOX_PCI_BASE_ADDRESS_4, 4, 1, 1, "BASE_ADDRESS_4" },
     809        { VBOX_PCI_MEMORY_BASE, 2, 1, 2, "MEMORY_BASE" },       // fWritable = ??
     810        { VBOX_PCI_MEMORY_LIMIT, 2, 1, 2, "MEMORY_LIMIT" },      // fWritable = ??
     811        { VBOX_PCI_BASE_ADDRESS_4, 4, 1, 1, "BASE_ADDRESS_4" },
     812        { VBOX_PCI_PREF_MEMORY_BASE, 2, 1, 2, "PREF_MEMORY_BASE" },  // fWritable = ??
     813        { VBOX_PCI_PREF_MEMORY_LIMIT, 2, 1, 2, "PREF_MEMORY_LIMIT" }, // fWritable = ??
     814        { VBOX_PCI_CARDBUS_CIS, 4, 1, 1, "CARDBUS_CIS" },       // fWritable = ??
     815        { VBOX_PCI_PREF_BASE_UPPER32, 4, 1, 2, "PREF_BASE_UPPER32" }, // fWritable = ??
     816        { VBOX_PCI_SUBSYSTEM_VENDOR_ID, 2, 0, 1, "SUBSYSTEM_VENDOR_ID" },// fWritable = !?
     817        { VBOX_PCI_PREF_LIMIT_UPPER32, 4, 1, 2, "PREF_LIMIT_UPPER32" },// fWritable = ??
     818        { VBOX_PCI_SUBSYSTEM_ID, 2, 0, 1, "SUBSYSTEM_ID" },      // fWritable = !?
     819        { VBOX_PCI_ROM_ADDRESS, 4, 1, 1, "ROM_ADDRESS" },       // fWritable = ?!
     820        { VBOX_PCI_IO_BASE_UPPER16, 2, 1, 2, "IO_BASE_UPPER16" },   // fWritable = ?!
     821        { VBOX_PCI_IO_LIMIT_UPPER16, 2, 1, 2, "IO_LIMIT_UPPER16" },  // fWritable = ?!
     822        { VBOX_PCI_CAPABILITY_LIST, 4, 0, 3, "CAPABILITY_LIST" },   // fWritable = !? cb=!?
     823        { VBOX_PCI_RESERVED_38, 4, 1, 1, "RESERVED_38" },               // ???
     824        { VBOX_PCI_ROM_ADDRESS_BR, 4, 1, 2, "ROM_ADDRESS_BR" },    // fWritable = !? cb=!? fBridge=!?
     825        { VBOX_PCI_INTERRUPT_LINE, 1, 1, 3, "INTERRUPT_LINE" },    // fBridge=??
     826        { VBOX_PCI_INTERRUPT_PIN, 1, 0, 3, "INTERRUPT_PIN" },     // fBridge=??
     827        { VBOX_PCI_MIN_GNT, 1, 0, 1, "MIN_GNT" },
     828        { VBOX_PCI_BRIDGE_CONTROL, 2, 1, 2, "BRIDGE_CONTROL" },    // fWritable = !?
     829        { VBOX_PCI_MAX_LAT, 1, 0, 3, "MAX_LAT" },           // fBridge=!?
     830        /* The COMMAND register must come last as it requires the *ADDRESS*
     831           registers to be restored before we pretent to change it from 0 to
     832           whatever value the guest assigned it. */
     833        { VBOX_PCI_COMMAND, 2, 1, 3, "COMMAND" },
     834    };
     835
     836#ifdef RT_STRICT
     837    /* Check that we've got full register coverage. */
     838    uint32_t bmDevice[0x40 / 32];
     839    uint32_t bmBridge[0x40 / 32];
     840    RT_ZERO(bmDevice);
     841    RT_ZERO(bmBridge);
     842    for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
     843    {
     844        uint8_t off = s_aFields[i].off;
     845        uint8_t cb  = s_aFields[i].cb;
     846        uint8_t f   = s_aFields[i].fBridge;
     847        while (cb-- > 0)
     848        {
     849            if (f & 1) AssertMsg(!ASMBitTest(bmDevice, off), ("%#x\n", off));
     850            if (f & 2) AssertMsg(!ASMBitTest(bmBridge, off), ("%#x\n", off));
     851            if (f & 1) ASMBitSet(bmDevice, off);
     852            if (f & 2) ASMBitSet(bmBridge, off);
     853            off++;
     854        }
     855    }
     856    for (uint32_t off = 0; off < 0x40; off++)
     857    {
     858        AssertMsg(ASMBitTest(bmDevice, off), ("%#x\n", off));
     859        AssertMsg(ASMBitTest(bmBridge, off), ("%#x\n", off));
     860    }
     861#endif
     862
     863    /*
     864     * Loop thru the fields covering the 64 bytes of standard registers.
     865     */
     866    uint8_t const fBridge = fIsBridge ? 2 : 1;
     867    uint8_t *pbDstConfig = &pDev->config[0];
     868    for (uint32_t i = 0; i < RT_ELEMENTS(s_aFields); i++)
     869        if (s_aFields[i].fBridge & fBridge)
     870        {
     871            uint8_t const   off = s_aFields[i].off;
     872            uint8_t const   cb  = s_aFields[i].cb;
     873            uint32_t        u32Src;
     874            uint32_t        u32Dst;
     875            switch (cb)
     876            {
     877                case 1:
     878                    u32Src = pbSrcConfig[off];
     879                    u32Dst = pbDstConfig[off];
     880                    break;
     881                case 2:
     882                    u32Src = *(uint16_t const *)&pbSrcConfig[off];
     883                    u32Dst = *(uint16_t const *)&pbDstConfig[off];
     884                    break;
     885                case 4:
     886                    u32Src = *(uint32_t const *)&pbSrcConfig[off];
     887                    u32Dst = *(uint32_t const *)&pbDstConfig[off];
     888                    break;
     889                default:
     890                    AssertFailed();
     891                    continue;
     892            }
     893
     894            if (    u32Src != u32Dst
     895                ||  off == VBOX_PCI_COMMAND)
     896            {
     897                if (u32Src != u32Dst)
     898                {
     899                    if (!s_aFields[i].fWritable)
     900                        LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x - !READ ONLY!\n",
     901                                pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
     902                    else
     903                        LogRel(("PCI: %8s/%u: %2u-bit field %s: %x -> %x\n",
     904                                pDev->name, pDev->pDevIns->iInstance, cb*8, s_aFields[i].pszName, u32Dst, u32Src));
     905                }
     906                if (off == VBOX_PCI_COMMAND)
     907                    PCIDevSetCommand(pDev, 0); /* For remapping, see pciR3CommonLoadExec. */
     908                pDev->Int.s.pfnConfigWrite(pDev, off, u32Src, cb);
     909            }
     910        }
     911
     912    /*
     913     * The device dependent registers.
     914     *
     915     * We will not use ConfigWrite here as we have no clue about the size
     916     * of the registers, so the device is responsible for correctly
     917     * restoring functionality governed by these registers.
     918     */
     919    for (uint32_t off = 0x40; off < sizeof(pDev->config); off++)
     920        if (pbDstConfig[off] != pbSrcConfig[off])
     921        {
     922            LogRel(("PCI: %8s/%u: register %02x: %02x -> %02x\n",
     923                    pDev->name, pDev->pDevIns->iInstance, off, pbDstConfig[off], pbSrcConfig[off])); /** @todo make this Log() later. */
     924            pbDstConfig[off] = pbSrcConfig[off];
     925        }
     926}
     927
     928/**
     929 * Common worker for pciR3LoadExec and pcibridgeR3LoadExec.
     930 *
     931 * @returns VBox status code.
     932 * @param   pBus                The bus which data is being loaded.
     933 * @param   pSSM                The saved state handle.
     934 * @param   uVersion            The data version.
     935 * @param   uPass               The pass.
     936 */
    759937static DECLCALLBACK(int) pciR3CommonLoadExec(PPCIBUS pBus, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    760938{
    761     return 0;
     939    uint32_t    u32;
     940    uint32_t    i;
     941    int         rc;
     942
     943    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
     944
     945    /*
     946     * Iterate thru all the devices and write 0 to the COMMAND register so
     947     * that all the memory is unmapped before we start restoring the saved
     948     * mapping locations.
     949     *
     950     * The register value is restored afterwards so we can do proper
     951     * LogRels in pciR3CommonRestoreConfig.
     952     */
     953    for (i = 0; i < RT_ELEMENTS(pBus->apDevices); i++)
     954    {
     955        PPCIDEVICE pDev = pBus->apDevices[i];
     956        if (pDev)
     957        {
     958            uint16_t u16 = PCIDevGetCommand(pDev);
     959            pDev->Int.s.pfnConfigWrite(pDev, VBOX_PCI_COMMAND, 0, 2);
     960            PCIDevSetCommand(pDev, u16);
     961            Assert(PCIDevGetCommand(pDev) == u16);
     962        }
     963    }
     964
     965    /*
     966     * Iterate all the devices.
     967     */
     968    for (i = 0;; i++)
     969    {
     970        PCIDEVICE   DevTmp;
     971        PPCIDEVICE  pDev;
     972
     973        /* index / terminator */
     974        rc = SSMR3GetU32(pSSM, &u32);
     975        if (RT_FAILURE(rc))
     976            return rc;
     977        if (u32 == (uint32_t)~0)
     978            break;
     979        if (    u32 >= RT_ELEMENTS(pBus->apDevices)
     980            ||  u32 < i)
     981        {
     982            AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
     983            return rc;
     984        }
     985
     986        /* skip forward to the device checking that no new devices are present. */
     987        for (; i < u32; i++)
     988        {
     989            pDev = pBus->apDevices[i];
     990            if (pDev)
     991            {
     992                LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pDev->name,
     993                        PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev)));
     994                if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
     995                    return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("New device in slot %#x, %s (vendor=%#06x device=%#06x)"),
     996                                            i, pDev->name, PCIDevGetVendorId(pDev), PCIDevGetDeviceId(pDev));
     997            }
     998        }
     999
     1000        /* get the data */
     1001        DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */
     1002        SSMR3GetMem(pSSM, DevTmp.config, sizeof(DevTmp.config));
     1003
     1004        rc = SSMR3GetS32(pSSM, &DevTmp.Int.s.uIrqPinState);
     1005        if (RT_FAILURE(rc))
     1006            return rc;
     1007
     1008        /* check that it's still around. */
     1009        pDev = pBus->apDevices[i];
     1010        if (!pDev)
     1011        {
     1012            LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i,
     1013                    PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp)));
     1014            if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
     1015                return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x has been removed! vendor=%#06x device=%#06x"),
     1016                                        i, PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp));
     1017            continue;
     1018        }
     1019
     1020        /* match the vendor id assuming that this will never be changed. */
     1021        if (    DevTmp.config[0] != pDev->config[0]
     1022            ||  DevTmp.config[1] != pDev->config[1])
     1023            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Device in slot %#x (%s) vendor id mismatch! saved=%.4Rhxs current=%.4Rhxs"),
     1024                                     i, pDev->name, DevTmp.config, pDev->config);
     1025
     1026        /* commit the loaded device config. */
     1027        pciR3CommonRestoreConfig(pDev, &DevTmp.config[0], false ); /** @todo fix bridge fun! */
     1028
     1029        pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState;
     1030    }
     1031
     1032    return VINF_SUCCESS;
    7621033}
    7631034
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