VirtualBox

Changeset 68423 in vbox


Ignore:
Timestamp:
Aug 15, 2017 11:28:57 PM (7 years ago)
Author:
vboxsync
Message:

Devices/Bus/PCI,MSI-X: Fix static initialization of the MSI-X memory/PCI region to allow up to 2048 vectors as defined by the specification instead of only allowing up to 128 vectors previously when allocating a static 4KB page for the structures.

Location:
trunk
Files:
3 edited

Legend:

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

    r66645 r68423  
    203203     * @todo fix non-standard naming.  */
    204204    uint8_t                         u8MsixCapSize;
    205 #if HC_ARCH_BITS == 64
    206     /** Explicit alignment padding.   */
    207     uint8_t                         abPadding1[HC_ARCH_BITS == 32 ? 0 : 4];
    208 #endif
     205    /** Size of the MSI-X region. */
     206    uint16_t                        cbMsixRegion;
     207    /** Offset to the PBA for MSI-X.   */
     208    uint16_t                        offMsixPba;
    209209
    210210    /** Pointer to bus specific data. (R3 ptr) */
     
    216216} PDMPCIDEVINT;
    217217AssertCompileMemberAlignment(PDMPCIDEVINT, aIORegions, 8);
    218 AssertCompileSize(PDMPCIDEVINT, HC_ARCH_BITS == 32 ? 264 : 384);
     218AssertCompileSize(PDMPCIDEVINT, HC_ARCH_BITS == 32 ? 268 : 384);
    219219
    220220/** Indicate that PDMPCIDEV::Int.s can be declared. */
  • trunk/src/VBox/Devices/Bus/DevPciIch9.cpp

    r68090 r68423  
    14401440        {
    14411441            Assert(pDev->Int.s.pMsixPageR3 != NULL);
    1442             memcpy(pDev->Int.s.pMsixPageR3, pvMsixPage, 0x1000);
     1442            Assert(pDev->Int.s.cbMsixRegion != 0);
     1443            memcpy(pDev->Int.s.pMsixPageR3, pvMsixPage, pDev->Int.s.cbMsixRegion);
    14431444        }
    14441445    }
  • trunk/src/VBox/Devices/Bus/MsixCommon.cpp

    r64454 r68423  
    55
    66/*
    7  * Copyright (C) 2010-2016 Oracle Corporation
     7 * Copyright (C) 2010-2017 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    8888DECLINLINE(uint8_t*)  msixPendingByte(PPDMPCIDEV pDev, uint32_t iVector)
    8989{
    90     return msixGetPageOffset(pDev, 0x800 + iVector / 8);
     90    return msixGetPageOffset(pDev, pDev->Int.s.offMsixPba + iVector / 8);
    9191}
    9292
     
    116116PDMBOTHCBDECL(int) msixMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    117117{
     118    LogFlowFunc(("\n"));
     119
     120    uint32_t off = (uint32_t)(GCPhysAddr & 0xffff);
     121    PPDMPCIDEV pPciDev = (PPDMPCIDEV)pvUser;
     122
    118123    /// @todo qword accesses?
    119     NOREF(pDevIns);
     124    RT_NOREF(pDevIns);
    120125    AssertMsgReturn(cb == 4,
    121126                    ("MSI-X must be accessed with 4-byte reads"),
    122127                    VERR_INTERNAL_ERROR);
    123 
    124     uint32_t off = (uint32_t)(GCPhysAddr & 0xfff);
     128    AssertMsgReturn(off < pPciDev->Int.s.cbMsixRegion,
     129                    ("Out of bounds access for the MSI-X region\n"),
     130                    VINF_IOM_MMIO_UNUSED_FF);
     131
     132    *(uint32_t*)pv = *(uint32_t*)msixGetPageOffset(pPciDev, off);
     133    return VINF_SUCCESS;
     134}
     135
     136PDMBOTHCBDECL(int) msixMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
     137{
     138    LogFlowFunc(("\n"));
     139
    125140    PPDMPCIDEV pPciDev = (PPDMPCIDEV)pvUser;
    126 
    127     *(uint32_t*)pv = *(uint32_t*)msixGetPageOffset(pPciDev, off);
    128 
    129     return VINF_SUCCESS;
    130 }
    131 
    132 PDMBOTHCBDECL(int) msixMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    133 {
     141    uint32_t off = (uint32_t)(GCPhysAddr & 0xffff);
     142
    134143    /// @todo qword accesses?
    135144    AssertMsgReturn(cb == 4,
    136145                    ("MSI-X must be accessed with 4-byte reads"),
    137146                    VERR_INTERNAL_ERROR);
    138     PPDMPCIDEV pPciDev = (PPDMPCIDEV)pvUser;
    139 
    140     uint32_t off = (uint32_t)(GCPhysAddr & 0xfff);
    141 
    142     AssertMsgReturn(off < 0x800, ("Trying to write to PBA\n"), VINF_SUCCESS);
     147    AssertMsgReturn(off < pPciDev->Int.s.offMsixPba,
     148                    ("Trying to write to PBA\n"),
     149                    VINF_IOM_MMIO_UNUSED_FF);
    143150
    144151    *(uint32_t*)msixGetPageOffset(pPciDev, off) = *(uint32_t*)pv;
    145152
    146153    msixCheckPendingVector(pDevIns, (PCPDMPCIHLP)pPciDev->Int.s.pPciBusPtrR3, pPciDev, off / VBOX_MSIX_ENTRY_SIZE);
    147 
    148154    return VINF_SUCCESS;
    149155}
     
    181187    uint8_t    iBar        = pMsiReg->iMsixBar;
    182188
    183     if (cVectors > VBOX_MSIX_MAX_ENTRIES)
    184     {
    185         AssertMsgFailed(("Too many MSI-X vectors: %d\n", cVectors));
    186         return VERR_TOO_MUCH_DATA;
    187     }
    188 
    189     if (iBar > 5)
    190     {
    191         AssertMsgFailed(("Using wrong BAR for MSI-X: %d\n", iBar));
    192         return VERR_INVALID_PARAMETER;
    193     }
     189    AssertMsgReturn(cVectors <= VBOX_MSIX_MAX_ENTRIES,
     190                    ("Too many MSI-X vectors: %d\n", cVectors),
     191                    VERR_TOO_MUCH_DATA);
     192    AssertMsgReturn(iBar <= 5,
     193                    ("Using wrong BAR for MSI-X: %d\n", iBar),
     194                    VERR_INVALID_PARAMETER);
    194195
    195196    Assert(iCapOffset != 0 && iCapOffset < 0xff && iNextOffset < 0xff);
    196197
    197198    int rc = VINF_SUCCESS;
     199    uint16_t cbPba = cVectors / 8;
     200    if (cVectors % 8)
     201        cbPba++;
     202    uint16_t cbMsixRegion = RT_ALIGN_T(cVectors * sizeof(MsixTableRecord) + cbPba, _4K, uint16_t);
    198203
    199204    /* If device is passthrough, BAR is registered using common mechanism. */
    200205    if (!pciDevIsPassthrough(pDev))
    201206    {
    202         rc = PDMDevHlpPCIIORegionRegister(pDev->Int.s.CTX_SUFF(pDevIns), iBar, 0x1000, PCI_ADDRESS_SPACE_MEM, msixMap);
     207        rc = PDMDevHlpPCIIORegionRegister(pDev->Int.s.CTX_SUFF(pDevIns), iBar, cbMsixRegion, PCI_ADDRESS_SPACE_MEM, msixMap);
    203208        if (RT_FAILURE (rc))
    204209            return rc;
    205210    }
    206211
     212    uint16_t offTable = 0;
     213    uint16_t offPBA   = cVectors * sizeof(MsixTableRecord);
     214
    207215    pDev->Int.s.u8MsixCapOffset = iCapOffset;
    208216    pDev->Int.s.u8MsixCapSize   = VBOX_MSIX_CAP_SIZE;
     217    pDev->Int.s.cbMsixRegion    = cbMsixRegion;
     218    pDev->Int.s.offMsixPba      = offPBA;
    209219    PVM pVM = PDMDevHlpGetVM(pDev->Int.s.CTX_SUFF(pDevIns));
    210220
    211221    pDev->Int.s.pMsixPageR3     = NULL;
    212222
    213     rc = MMHyperAlloc(pVM, 0x1000, 1, MM_TAG_PDM_DEVICE_USER, (void **)&pDev->Int.s.pMsixPageR3);
     223    rc = MMHyperAlloc(pVM, cbMsixRegion, 1, MM_TAG_PDM_DEVICE_USER, (void **)&pDev->Int.s.pMsixPageR3);
    214224    if (RT_FAILURE(rc) || (pDev->Int.s.pMsixPageR3 == NULL))
    215225        return VERR_NO_VM_MEMORY;
    216     RT_BZERO(pDev->Int.s.pMsixPageR3, 0x1000);
     226    RT_BZERO(pDev->Int.s.pMsixPageR3, cbMsixRegion);
    217227    pDev->Int.s.pMsixPageR0     = MMHyperR3ToR0(pVM, pDev->Int.s.pMsixPageR3);
    218228    pDev->Int.s.pMsixPageRC     = MMHyperR3ToRC(pVM, pDev->Int.s.pMsixPageR3);
     
    224234    PCIDevSetByte(pDev,  iCapOffset + 1, iNextOffset); /* next */
    225235    PCIDevSetWord(pDev,  iCapOffset + VBOX_MSIX_CAP_MESSAGE_CONTROL, cVectors - 1);
    226 
    227     uint32_t offTable = 0, offPBA = 0x800;
    228236
    229237    PCIDevSetDWord(pDev,  iCapOffset + VBOX_MSIX_TABLE_BIROFFSET, offTable | iBar);
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