VirtualBox

Changeset 92716 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Dec 2, 2021 9:17:42 PM (3 years ago)
Author:
vboxsync
Message:

VMM/IOM: Made I/O port and MMIO registrations work in driverless mode. bugref:10138

Location:
trunk/src/VBox/VMM/VMMR3
Files:
2 edited

Legend:

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

    r82968 r92716  
    3333#include <VBox/param.h>
    3434#include <iprt/assert.h>
     35#include <iprt/mem.h>
    3536#include <iprt/string.h>
    3637#include <VBox/log.h>
     
    198199
    199200
     201#ifdef VBOX_WITH_STATISTICS
     202/**
     203 * Grows the statistics table.
     204 *
     205 * @returns VBox status code.
     206 * @param   pVM             The cross context VM structure.
     207 * @param   cNewEntries     The minimum number of new entrie.
     208 * @see     IOMR0IoPortGrowStatisticsTable
     209 */
     210static int iomR3IoPortGrowStatisticsTable(PVM pVM, uint32_t cNewEntries)
     211{
     212    AssertReturn(cNewEntries <= _64K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS);
     213
     214    int rc;
     215    if (!SUPR3IsDriverless())
     216    {
     217        rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORT_STATS, cNewEntries, NULL);
     218        AssertLogRelRCReturn(rc, rc);
     219        AssertReturn(cNewEntries <= pVM->iom.s.cIoPortStatsAllocation, VERR_IOM_IOPORT_IPE_2);
     220    }
     221    else
     222    {
     223        /*
     224         * Validate input and state.
     225         */
     226        uint32_t const cOldEntries = pVM->iom.s.cIoPortStatsAllocation;
     227        AssertReturn(cNewEntries > cOldEntries, VERR_IOM_IOPORT_IPE_1);
     228        AssertReturn(pVM->iom.s.cIoPortStats <= cOldEntries, VERR_IOM_IOPORT_IPE_2);
     229
     230        /*
     231         * Calc size and allocate a new table.
     232         */
     233        uint32_t const cbNew = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTSTATSENTRY), PAGE_SIZE);
     234        cNewEntries = cbNew / sizeof(IOMIOPORTSTATSENTRY);
     235
     236        PIOMIOPORTSTATSENTRY const paIoPortStats = (PIOMIOPORTSTATSENTRY)RTMemPageAllocZ(cbNew);
     237        if (paIoPortStats)
     238        {
     239            /*
     240             * Anything to copy over, update and free the old one.
     241             */
     242            PIOMIOPORTSTATSENTRY const pOldIoPortStats = pVM->iom.s.paIoPortStats;
     243            if (pOldIoPortStats)
     244                memcpy(paIoPortStats, pOldIoPortStats, cOldEntries * sizeof(IOMIOPORTSTATSENTRY));
     245
     246            pVM->iom.s.paIoPortStats             = paIoPortStats;
     247            pVM->iom.s.cIoPortStatsAllocation    = cNewEntries;
     248
     249            RTMemPageFree(pOldIoPortStats, RT_ALIGN_32(cOldEntries * sizeof(IOMIOPORTSTATSENTRY), PAGE_SIZE));
     250
     251            rc = VINF_SUCCESS;
     252        }
     253        else
     254            rc = VERR_NO_PAGE_MEMORY;
     255    }
     256
     257    return rc;
     258}
     259#endif
     260
     261
     262/**
     263 * Grows the I/O port registration statistics table.
     264 *
     265 * @returns VBox status code.
     266 * @param   pVM             The cross context VM structure.
     267 * @param   cNewEntries     The minimum number of new entrie.
     268 * @see     IOMR0IoPortGrowRegistrationTables
     269 */
     270static int iomR3IoPortGrowTable(PVM pVM, uint32_t cNewEntries)
     271{
     272    AssertReturn(cNewEntries <= _4K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS);
     273
     274    int rc;
     275    if (!SUPR3IsDriverless())
     276    {
     277        rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORTS, cNewEntries, NULL);
     278        AssertLogRelRCReturn(rc, rc);
     279        AssertReturn(cNewEntries <= pVM->iom.s.cIoPortAlloc, VERR_IOM_IOPORT_IPE_2);
     280    }
     281    else
     282    {
     283        /*
     284         * Validate input and state.
     285         */
     286        uint32_t const cOldEntries = pVM->iom.s.cIoPortAlloc;
     287        AssertReturn(cNewEntries >= cOldEntries, VERR_IOM_IOPORT_IPE_1);
     288
     289        /*
     290         * Allocate the new tables.  We use a single allocation for the three tables (ring-0,
     291         * ring-3, lookup) and does a partial mapping of the result to ring-3.
     292         */
     293        uint32_t const cbRing3  = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTENTRYR3),     PAGE_SIZE);
     294        uint32_t const cbShared = RT_ALIGN_32(cNewEntries * sizeof(IOMIOPORTLOOKUPENTRY), PAGE_SIZE);
     295        uint32_t const cbNew    = cbRing3 + cbShared;
     296
     297        /* Use the rounded up space as best we can. */
     298        cNewEntries = RT_MIN(cbRing3 / sizeof(IOMIOPORTENTRYR3), cbShared / sizeof(IOMIOPORTLOOKUPENTRY));
     299
     300        PIOMIOPORTENTRYR3 const paRing3 = (PIOMIOPORTENTRYR3)RTMemPageAllocZ(cbNew);
     301        if (paRing3)
     302        {
     303            PIOMIOPORTLOOKUPENTRY const paLookup = (PIOMIOPORTLOOKUPENTRY)((uintptr_t)paRing3 + cbRing3);
     304
     305            /*
     306             * Copy over the old info and initialize the idxSelf and idxStats members.
     307             */
     308            if (pVM->iom.s.paIoPortRegs != NULL)
     309            {
     310                memcpy(paRing3,  pVM->iom.s.paIoPortRegs,    sizeof(paRing3[0])  * cOldEntries);
     311                memcpy(paLookup, pVM->iom.s.paIoPortLookup,  sizeof(paLookup[0]) * cOldEntries);
     312            }
     313
     314            size_t i = cbRing3 / sizeof(*paRing3);
     315            while (i-- > cOldEntries)
     316            {
     317                paRing3[i].idxSelf  = (uint16_t)i;
     318                paRing3[i].idxStats = UINT16_MAX;
     319            }
     320
     321            /*
     322             * Update the variables and free the old memory.
     323             */
     324            void * const pvFree =  pVM->iom.s.paIoPortRegs;
     325
     326            pVM->iom.s.paIoPortRegs     = paRing3;
     327            pVM->iom.s.paIoPortLookup   = paLookup;
     328            pVM->iom.s.cIoPortAlloc     = cNewEntries;
     329
     330            RTMemPageFree(pvFree,
     331                            RT_ALIGN_32(cOldEntries * sizeof(IOMIOPORTENTRYR3),     PAGE_SIZE)
     332                          + RT_ALIGN_32(cOldEntries * sizeof(IOMIOPORTLOOKUPENTRY), PAGE_SIZE));
     333
     334            rc = VINF_SUCCESS;
     335        }
     336        else
     337            rc = VERR_NO_PAGE_MEMORY;
     338    }
     339    return rc;
     340}
     341
    200342
    201343/**
     
    254396    if (cNewIoPortStats > pVM->iom.s.cIoPortStatsAllocation)
    255397    {
    256         int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORT_STATS, cNewIoPortStats, NULL);
    257         AssertLogRelRCReturn(rc, rc);
     398        int rc = iomR3IoPortGrowStatisticsTable(pVM, cNewIoPortStats);
     399        AssertRCReturn(rc, rc);
    258400        AssertReturn(idxStats == pVM->iom.s.cIoPortStats, VERR_IOM_IOPORT_IPE_1);
    259         AssertReturn(cNewIoPortStats <= pVM->iom.s.cIoPortStatsAllocation, VERR_IOM_IOPORT_IPE_2);
    260401    }
    261402#endif
     
    264405    if (idx >= pVM->iom.s.cIoPortAlloc)
    265406    {
    266         int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORTS, pVM->iom.s.cIoPortAlloc + 1, NULL);
    267         AssertLogRelRCReturn(rc, rc);
     407        int rc = iomR3IoPortGrowTable(pVM, pVM->iom.s.cIoPortAlloc + 1);
     408        AssertRCReturn(rc, rc);
    268409        AssertReturn(idx == pVM->iom.s.cIoPortRegs, VERR_IOM_IOPORT_IPE_1);
    269410        AssertReturn(idx < pVM->iom.s.cIoPortAlloc, VERR_IOM_IOPORT_IPE_2);
  • trunk/src/VBox/VMM/VMMR3/IOMR3Mmio.cpp

    r82968 r92716  
    3333#include <VBox/param.h>
    3434#include <iprt/assert.h>
     35#include <iprt/mem.h>
    3536#include <iprt/string.h>
    3637#include <VBox/log.h>
     
    110111}
    111112
     113
     114/**
     115 * Grows the statistics table.
     116 *
     117 * @returns VBox status code.
     118 * @param   pVM             The cross context VM structure.
     119 * @param   cNewEntries     The minimum number of new entrie.
     120 * @see     IOMR0IoPortGrowStatisticsTable
     121 */
     122static int iomR3MmioGrowStatisticsTable(PVM pVM, uint32_t cNewEntries)
     123{
     124    AssertReturn(cNewEntries <= _64K, VERR_IOM_TOO_MANY_MMIO_REGISTRATIONS);
     125
     126    int rc;
     127    if (!SUPR3IsDriverless())
     128    {
     129        rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_MMIO_STATS, cNewEntries, NULL);
     130        AssertLogRelRCReturn(rc, rc);
     131        AssertReturn(cNewEntries <= pVM->iom.s.cMmioStatsAllocation, VERR_IOM_MMIO_IPE_2);
     132    }
     133    else
     134    {
     135        /*
     136         * Validate input and state.
     137         */
     138        uint32_t const cOldEntries = pVM->iom.s.cMmioStatsAllocation;
     139        AssertReturn(cNewEntries > cOldEntries, VERR_IOM_MMIO_IPE_1);
     140        AssertReturn(pVM->iom.s.cMmioStats <= cOldEntries, VERR_IOM_MMIO_IPE_2);
     141
     142        /*
     143         * Calc size and allocate a new table.
     144         */
     145        uint32_t const cbNew = RT_ALIGN_32(cNewEntries * sizeof(IOMMMIOSTATSENTRY), PAGE_SIZE);
     146        cNewEntries = cbNew / sizeof(IOMMMIOSTATSENTRY);
     147
     148        PIOMMMIOSTATSENTRY const paMmioStats = (PIOMMMIOSTATSENTRY)RTMemPageAllocZ(cbNew);
     149        if (paMmioStats)
     150        {
     151            /*
     152             * Anything to copy over, update and free the old one.
     153             */
     154            PIOMMMIOSTATSENTRY const pOldMmioStats = pVM->iom.s.paMmioStats;
     155            if (pOldMmioStats)
     156                memcpy(paMmioStats, pOldMmioStats, cOldEntries * sizeof(IOMMMIOSTATSENTRY));
     157
     158            pVM->iom.s.paMmioStats             = paMmioStats;
     159            pVM->iom.s.cMmioStatsAllocation    = cNewEntries;
     160
     161            RTMemPageFree(pOldMmioStats, RT_ALIGN_32(cOldEntries * sizeof(IOMMMIOSTATSENTRY), PAGE_SIZE));
     162
     163            rc = VINF_SUCCESS;
     164        }
     165        else
     166            rc = VERR_NO_PAGE_MEMORY;
     167    }
     168
     169    return rc;
     170}
     171
    112172#endif /* VBOX_WITH_STATISTICS */
     173
     174/**
     175 * Grows the I/O port registration statistics table.
     176 *
     177 * @returns VBox status code.
     178 * @param   pVM             The cross context VM structure.
     179 * @param   cNewEntries     The minimum number of new entrie.
     180 * @see     IOMR0MmioGrowRegistrationTables
     181 */
     182static int iomR3MmioGrowTable(PVM pVM, uint32_t cNewEntries)
     183{
     184    AssertReturn(cNewEntries <= _4K, VERR_IOM_TOO_MANY_MMIO_REGISTRATIONS);
     185
     186    int rc;
     187    if (!SUPR3IsDriverless())
     188    {
     189        rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_MMIO_REGS, cNewEntries, NULL);
     190        AssertLogRelRCReturn(rc, rc);
     191        AssertReturn(cNewEntries <= pVM->iom.s.cMmioAlloc, VERR_IOM_MMIO_IPE_2);
     192    }
     193    else
     194    {
     195        /*
     196         * Validate input and state.
     197         */
     198        uint32_t const cOldEntries = pVM->iom.s.cMmioAlloc;
     199        AssertReturn(cNewEntries >= cOldEntries, VERR_IOM_MMIO_IPE_1);
     200
     201        /*
     202         * Allocate the new tables.  We use a single allocation for the three tables (ring-0,
     203         * ring-3, lookup) and does a partial mapping of the result to ring-3.
     204         */
     205        uint32_t const cbRing3  = RT_ALIGN_32(cNewEntries * sizeof(IOMMMIOENTRYR3),     PAGE_SIZE);
     206        uint32_t const cbShared = RT_ALIGN_32(cNewEntries * sizeof(IOMMMIOLOOKUPENTRY), PAGE_SIZE);
     207        uint32_t const cbNew    = cbRing3 + cbShared;
     208
     209        /* Use the rounded up space as best we can. */
     210        cNewEntries = RT_MIN(cbRing3 / sizeof(IOMMMIOENTRYR3), cbShared / sizeof(IOMMMIOLOOKUPENTRY));
     211
     212        PIOMMMIOENTRYR3 const paRing3 = (PIOMMMIOENTRYR3)RTMemPageAllocZ(cbNew);
     213        if (paRing3)
     214        {
     215            PIOMMMIOLOOKUPENTRY const paLookup = (PIOMMMIOLOOKUPENTRY)((uintptr_t)paRing3 + cbRing3);
     216
     217            /*
     218             * Copy over the old info and initialize the idxSelf and idxStats members.
     219             */
     220            if (pVM->iom.s.paMmioRegs != NULL)
     221            {
     222                memcpy(paRing3,  pVM->iom.s.paMmioRegs,    sizeof(paRing3[0])  * cOldEntries);
     223                memcpy(paLookup, pVM->iom.s.paMmioLookup,  sizeof(paLookup[0]) * cOldEntries);
     224            }
     225
     226            size_t i = cbRing3 / sizeof(*paRing3);
     227            while (i-- > cOldEntries)
     228            {
     229                paRing3[i].idxSelf  = (uint16_t)i;
     230                paRing3[i].idxStats = UINT16_MAX;
     231            }
     232
     233            /*
     234             * Update the variables and free the old memory.
     235             */
     236            void * const pvFree = pVM->iom.s.paMmioRegs;
     237
     238            pVM->iom.s.paMmioRegs     = paRing3;
     239            pVM->iom.s.paMmioLookup   = paLookup;
     240            pVM->iom.s.cMmioAlloc     = cNewEntries;
     241
     242            RTMemPageFree(pvFree,
     243                            RT_ALIGN_32(cOldEntries * sizeof(IOMMMIOENTRYR3),     PAGE_SIZE)
     244                          + RT_ALIGN_32(cOldEntries * sizeof(IOMMMIOLOOKUPENTRY), PAGE_SIZE));
     245
     246            rc = VINF_SUCCESS;
     247        }
     248        else
     249            rc = VERR_NO_PAGE_MEMORY;
     250    }
     251    return rc;
     252}
    113253
    114254
     
    160300    if (cNewMmioStats > pVM->iom.s.cMmioStatsAllocation)
    161301    {
    162         int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_MMIO_STATS, cNewMmioStats, NULL);
    163         AssertLogRelRCReturn(rc, rc);
     302        int rc = iomR3MmioGrowStatisticsTable(pVM, cNewMmioStats);
     303        AssertRCReturn(rc, rc);
    164304        AssertReturn(idxStats == pVM->iom.s.cMmioStats, VERR_IOM_MMIO_IPE_1);
    165         AssertReturn(cNewMmioStats <= pVM->iom.s.cMmioStatsAllocation, VERR_IOM_MMIO_IPE_2);
    166305    }
    167306#endif
     
    170309    if (idx >= pVM->iom.s.cMmioAlloc)
    171310    {
    172         int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_MMIO_REGS, pVM->iom.s.cMmioAlloc + 1, NULL);
    173         AssertLogRelRCReturn(rc, rc);
     311        int rc = iomR3MmioGrowTable(pVM, pVM->iom.s.cMmioAlloc + 1);
     312        AssertRCReturn(rc, rc);
    174313        AssertReturn(idx == pVM->iom.s.cMmioRegs, VERR_IOM_MMIO_IPE_1);
    175         AssertReturn(idx < pVM->iom.s.cMmioAlloc, VERR_IOM_MMIO_IPE_2);
    176314    }
    177315
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