VirtualBox

Changeset 33236 in vbox for trunk/src/VBox/Devices/Bus


Ignore:
Timestamp:
Oct 19, 2010 3:14:42 PM (14 years ago)
Author:
vboxsync
Message:

PCI: MSI-X work

Location:
trunk/src/VBox/Devices/Bus
Files:
1 added
3 edited

Legend:

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

    r33215 r33236  
    530530            PPDMDEVINS pDevIns = pGlobals->aPciBus.CTX_SUFF(pDevIns);
    531531            MsiNotify(pDevIns, pGlobals->aPciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel);
     532        }
     533
     534        if (MsixIsEnabled(pPciDev))
     535        {
     536            Log2(("MSI-X interrupt: %d level=%d\n", iIrq, iLevel));
     537            PPDMDEVINS pDevIns = pGlobals->aPciBus.CTX_SUFF(pDevIns);
     538            MsixNotify(pDevIns, pGlobals->aPciBus.CTX_SUFF(pPciHlp), pPciDev, iIrq, iLevel);
    532539        }
    533540        return;
     
    774781static DECLCALLBACK(int) ich9pciRegisterMsi(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PPDMMSIREG pMsiReg)
    775782{
    776     return MsiInit(pPciDev, pMsiReg);
     783    int rc;
     784
     785    rc = MsiInit(pPciDev, pMsiReg);
     786    if (rc != VINF_SUCCESS)
     787        return rc;
     788
     789    rc = MsixInit(pPciDev, pMsiReg);
     790    if (rc != VINF_SUCCESS)
     791        return rc;
     792
     793    return rc;
    777794}
    778795
     
    16751692    }
    16761693
     1694    if (   PCIIsMsixCapable(aDev)
     1695        && (u32Address >= aDev->Int.s.u8MsixCapOffset)
     1696        && (u32Address <  aDev->Int.s.u8MsixCapOffset + aDev->Int.s.u8MsixCapSize)
     1697       )
     1698    {
     1699        return MsixPciConfigRead(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns), aDev, u32Address, len);
     1700    }
     1701
    16771702    AssertMsgReturn(u32Address + len <= 256, ("Read after end of PCI config space\n"),
    16781703                    0);
     
    17161741                          aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
    17171742                          aDev, u32Address, val, len);
     1743        return;
     1744    }
     1745
     1746    if (   PCIIsMsixCapable(aDev)
     1747        && (u32Address >= aDev->Int.s.u8MsixCapOffset)
     1748        && (u32Address <  aDev->Int.s.u8MsixCapOffset + aDev->Int.s.u8MsixCapSize)
     1749       )
     1750    {
     1751        MsixPciConfigWrite(aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pDevIns),
     1752                           aDev->Int.s.CTX_SUFF(pBus)->CTX_SUFF(pPciHlp),
     1753                           aDev, u32Address, val, len);
    17181754        return;
    17191755    }
     
    18961932};
    18971933
    1898 static int assignPosition(PPCIBUS pBus, PPCIDEVICE pPciDev, const char *pszName, int iDevFn)
    1899 {
     1934static bool assignPosition(PPCIBUS pBus, PPCIDEVICE pPciDev, const char *pszName, int iDevFn, PciAddress* aPosition)
     1935{
     1936    aPosition->iBus = 0;
     1937    aPosition->iDeviceFunc = iDevFn;
     1938    aPosition->iRegister = 0; /* N/A */
     1939
    19001940    /* Hardcoded slots/functions, per chipset spec */
    19011941    for (size_t i = 0; i < RT_ELEMENTS(PciSlotAssignments); i++)
     
    19041944        {
    19051945            PCISetRequestedDevfunc(pPciDev);
    1906             return (PciSlotAssignments[i].iSlot << 3) + PciSlotAssignments[i].iFunction;
    1907         }
    1908     }
    1909 
     1946            aPosition->iDeviceFunc =
     1947                    (PciSlotAssignments[i].iSlot << 3) + PciSlotAssignments[i].iFunction;
     1948            return true;
     1949        }
     1950    }
     1951
     1952    /* Explicit slot request */
    19101953    if (iDevFn >=0 && iDevFn < (int)RT_ELEMENTS(pBus->apDevices))
    1911         return iDevFn;
     1954        return true;
    19121955
    19131956    /* Otherwise when assigning a slot, we need to make sure all its functions are available */
     
    19241967        {
    19251968            PCIClearRequestedDevfunc(pPciDev);
    1926             return iPos;
    1927         }
    1928     }
    1929 
    1930     return -1;
     1969            aPosition->iDeviceFunc = iPos;
     1970            return true;
     1971        }
     1972    }
     1973
     1974    return false;
    19311975}
    19321976
     
    19481992static int ich9pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
    19491993{
     1994    PciAddress aPosition = {0, 0, 0};
     1995
    19501996    /*
    19511997     * Find device position
    19521998     */
    1953     iDev = assignPosition(pBus, pPciDev, pszName, iDev);
    1954     if (iDev < 0)
    1955     {
    1956         AssertMsgFailed(("Couldn't find free spot!\n"));
     1999    if (!assignPosition(pBus, pPciDev, pszName, iDev, &aPosition))
     2000    {
     2001        AssertMsgFailed(("Couldn't asssign position!\n"));
    19572002        return VERR_PDM_TOO_PCI_MANY_DEVICES;
    19582003    }
    19592004
     2005    AssertMsgReturn(aPosition.iBus == 0,
     2006                    ("Assigning behind the bridge not implemented yet\n"),
     2007                    VERR_PDM_TOO_PCI_MANY_DEVICES);
     2008
     2009
     2010    iDev = aPosition.iDeviceFunc;
    19602011    /*
    19612012     * Check if we can really take this slot, possibly by relocating
     
    19742025    {
    19752026        /* if we got here, we shall (and usually can) relocate the device */
    1976         int iRelDev = assignPosition(pBus, pBus->apDevices[iDev], pBus->apDevices[iDev]->name, -1);
    1977         if (iRelDev < 0 || iRelDev == iDev)
     2027        bool assigned = assignPosition(pBus, pBus->apDevices[iDev], pBus->apDevices[iDev]->name, -1, &aPosition);
     2028        AssertMsgReturn(aPosition.iBus == 0,
     2029                        ("Assigning behind the bridge not implemented yet\n"),
     2030                        VERR_PDM_TOO_PCI_MANY_DEVICES);
     2031        int iRelDev = aPosition.iDeviceFunc;
     2032        if (!assigned || iRelDev == iDev)
    19782033        {
    19792034            AssertMsgFailed(("Couldn't find free spot!\n"));
  • trunk/src/VBox/Devices/Bus/MsiCommon.cpp

    r33215 r33236  
    8484}
    8585
    86 DECLINLINE(bool) msiBitJustCleared(uint32_t u32OldValue,
    87                                    uint32_t u32NewValue,
    88                                    uint32_t u32Mask)
    89 {
    90     return (!!(u32OldValue & u32Mask) && !(u32NewValue & u32Mask));
    91 }
    92 
    93 DECLINLINE(bool) msiBitJustSet(uint32_t u64OldValue,
    94                                uint32_t u64NewValue,
    95                                uint32_t u64Mask)
    96 {
    97     return (!(u64OldValue & u64Mask) && !!(u64NewValue & u64Mask));
     86DECLINLINE(bool) msiBitJustCleared(uint32_t uOldValue,
     87                                   uint32_t uNewValue,
     88                                   uint32_t uMask)
     89{
     90    return (!!(uOldValue & uMask) && !(uNewValue & uMask));
     91}
     92
     93DECLINLINE(bool) msiBitJustSet(uint32_t uOldValue,
     94                               uint32_t uNewValue,
     95                               uint32_t uMask)
     96{
     97    return (!(uOldValue & uMask) && !!(uNewValue & uMask));
    9898}
    9999
     
    104104    Assert(iOff >= 0 && (PCIIsMsiCapable(pDev) && iOff < pDev->Int.s.u8MsiCapSize));
    105105
    106     Log2(("MSIPciConfigWrite: %d <- %x (%d)\n", iOff, val, len));
     106    Log2(("MsiPciConfigWrite: %d <- %x (%d)\n", iOff, val, len));
    107107
    108108    uint32_t uAddr = u32Address;
     
    112112    {
    113113        uint32_t reg = i + iOff;
     114        uint8_t u8Val = (uint8_t)val;
    114115        switch (reg)
    115116        {
     
    119120            case VBOX_MSI_CAP_MESSAGE_CONTROL:
    120121                /* don't change read-only bits: 1-3,7 */
    121                 val &= UINT32_C(~0x8e);
    122                 pDev->config[uAddr] = val;
     122                u8Val &= UINT8_C(~0x8e);
     123                pDev->config[uAddr] = u8Val | (pDev->config[uAddr] & UINT8_C(0x8e));
    123124                break;
    124125            case VBOX_MSI_CAP_MESSAGE_CONTROL + 1:
     
    126127                break;
    127128            default:
    128                 if (pDev->config[uAddr] != val)
     129                if (pDev->config[uAddr] != u8Val)
    129130                {
    130131                    int32_t maskUpdated = -1;
     
    155156                            uint32_t uVector = maskUpdated*8 + iBitNum;
    156157
    157                             if (msiBitJustCleared(pDev->config[uAddr], val, iBit))
     158                            if (msiBitJustCleared(pDev->config[uAddr], u8Val, iBit))
    158159                            {
    159160                                Log(("msi: mask updated bit %d@%x (%d)\n", iBitNum, uAddr, maskUpdated));
     
    167168                                }
    168169                            }
    169                             if (msiBitJustSet(pDev->config[uAddr], val, iBit))
     170                            if (msiBitJustSet(pDev->config[uAddr], u8Val, iBit))
    170171                            {
    171172                                Log(("msi: mask vector: %d\n", uVector));
     
    174175                    }
    175176
    176                     pDev->config[uAddr] = val;
     177                    pDev->config[uAddr] = u8Val;
    177178                }
    178179        }
     
    204205    }
    205206
    206     Log2(("MSIPciConfigRead: %d (%d) -> %x\n", iOff, len, rv));
     207    Log2(("MsiPciConfigRead: %d (%d) -> %x\n", iOff, len, rv));
    207208
    208209    return rv;
     
    212213int MsiInit(PPCIDEVICE pDev, PPDMMSIREG pMsiReg)
    213214{
    214     uint16_t   cVectors    = pMsiReg->cVectors;
    215     uint8_t    iCapOffset  = pMsiReg->iCapOffset;
    216     uint8_t    iNextOffset = pMsiReg->iNextOffset;
    217     uint16_t   iMsiFlags   = pMsiReg->iMsiFlags;
    218 
    219     Assert(cVectors > 0);
     215    if (pMsiReg->cMsiVectors == 0)
     216         return VINF_SUCCESS;
     217
     218    uint16_t   cVectors    = pMsiReg->cMsiVectors;
     219    uint8_t    iCapOffset  = pMsiReg->iMsiCapOffset;
     220    uint8_t    iNextOffset = pMsiReg->iMsiNextOffset;
     221    uint16_t   iFlags   = pMsiReg->iMsiFlags;
    220222
    221223    if (cVectors != 1)
     
    228230    Assert(iCapOffset != 0 && iCapOffset < 0xff && iNextOffset < 0xff);
    229231
    230     bool f64bit = (iMsiFlags & VBOX_PCI_MSI_FLAGS_64BIT) != 0;
     232    bool f64bit = (iFlags & VBOX_PCI_MSI_FLAGS_64BIT) != 0;
    231233    /* We always support per-vector masking */
    232     iMsiFlags |= VBOX_PCI_MSI_FLAGS_MASKBIT;
     234    iFlags |= VBOX_PCI_MSI_FLAGS_MASKBIT;
    233235
    234236    pDev->Int.s.u8MsiCapOffset = iCapOffset;
     
    237239    PCIDevSetByte(pDev,  iCapOffset + 0, VBOX_PCI_CAP_ID_MSI);
    238240    PCIDevSetByte(pDev,  iCapOffset + 1, iNextOffset); /* next */
    239     PCIDevSetWord(pDev,  iCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL, iMsiFlags);
     241    PCIDevSetWord(pDev,  iCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL, iFlags);
    240242
    241243    *msiGetMaskBits(pDev)    = 0;
  • trunk/src/VBox/Devices/Bus/MsiCommon.h

    r33215 r33236  
    11/* $Id$ */
    22/** @file
    3  * Header for MSI support routines.
     3 * Header for MSI/MSI-X support routines.
    44 */
    55/*
     
    4040void     MsiPciConfigWrite(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, uint32_t u32Address, uint32_t val, unsigned len);
    4141uint32_t MsiPciConfigRead (PPDMDEVINS pDevIns, PPCIDEVICE pDev, uint32_t u32Address, unsigned len);
     42
     43
     44/* Init MSI-X support in the device. */
     45int      MsixInit(PPCIDEVICE pDev, PPDMMSIREG pMsiReg);
     46
     47/* If MSI-X is enabled, so that MSIXNotify() shall be used for notifications.  */
     48bool     MsixIsEnabled(PPCIDEVICE pDev);
     49
     50/* Device notification (aka interrupt). */
     51void     MsixNotify(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, int iVector, int iLevel);
     52
     53/* PCI config space accessors for MSI-X */
     54void     MsixPciConfigWrite(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, uint32_t u32Address, uint32_t val, unsigned len);
     55uint32_t MsixPciConfigRead (PPDMDEVINS pDevIns, PPCIDEVICE pDev, uint32_t u32Address, unsigned len);
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