VirtualBox

Ignore:
Timestamp:
Sep 6, 2019 8:09:16 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133172
Message:

IOM: New I/O port registration code. bugref:9218

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/include/IOMInline.h

    r80281 r80641  
    2828 * @{
    2929 */
     30
     31
     32/**
     33 * Gets the I/O port entry for the specified I/O port in the current context.
     34 *
     35 * @returns Pointer to I/O port entry.
     36 * @returns NULL if no port registered.
     37 *
     38 * @param   pVM             The cross context VM structure.
     39 * @param   Port            The I/O port lookup.
     40 * @param   pidxLastHint    Pointer to IOMCPU::idxIoPortLastRead or
     41 *                          IOMCPU::idxIoPortLastWrite.
     42 *
     43 * @note    In ring-0 it is possible to get an uninitialized entry (pDevIns is
     44 *          NULL, cPorts is 0), in which case there should be ring-3 handlers
     45 *          for the entry.  Use IOMIOPORTENTRYR0::idxSelf to get the ring-3
     46 *          entry.
     47 */
     48DECLINLINE(CTX_SUFF(PIOMIOPORTENTRY)) iomIoPortGetEntry(PVMCC pVM, RTIOPORT uPort, uint16_t *pidxLastHint)
     49{
     50    Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
     51
     52#ifdef IN_RING0
     53    uint32_t              iEnd      = RT_MIN(pVM->iom.s.cIoPortLookupEntries, pVM->iomr0.s.cIoPortAlloc);
     54    PIOMIOPORTLOOKUPENTRY paLookup  = pVM->iomr0.s.paIoPortLookup;
     55#else
     56    uint32_t              iEnd      = pVM->iom.s.cIoPortLookupEntries;
     57    PIOMIOPORTLOOKUPENTRY paLookup  = pVM->iom.s.paIoPortLookup;
     58#endif
     59    if (iEnd > 0)
     60    {
     61        uint32_t iFirst = 0;
     62        uint32_t i      = *pidxLastHint;
     63        if (i < iEnd)
     64        { /* likely */ }
     65        else
     66            i = iEnd / 2;
     67        for (;;)
     68        {
     69            PIOMIOPORTLOOKUPENTRY pCur = &paLookup[i];
     70            if (pCur->uFirstPort > uPort)
     71            {
     72                if (i > iFirst)
     73                    iEnd = i;
     74                else
     75                    return NULL;
     76            }
     77            else if (pCur->uLastPort < uPort)
     78            {
     79                i += 1;
     80                if (i < iEnd)
     81                    iFirst = i;
     82                else
     83                    return NULL;
     84            }
     85            else
     86            {
     87                *pidxLastHint = (uint16_t)i;
     88
     89                /*
     90                 * Translate the 'idx' member into a pointer.
     91                 */
     92                size_t const idx = pCur->idx;
     93#ifdef IN_RING0
     94                AssertMsg(idx < pVM->iom.s.cIoPortRegs && idx < pVM->iomr0.s.cIoPortAlloc,
     95                          ("%#zx vs %#x/%x (port %#x)\n", idx, pVM->iom.s.cIoPortRegs, pVM->iomr0.s.cIoPortMax, uPort));
     96                if (idx < pVM->iomr0.s.cIoPortAlloc)
     97                    return &pVM->iomr0.s.paIoPortRegs[idx];
     98#else
     99                if (idx < pVM->iom.s.cIoPortRegs)
     100                    return &pVM->iom.s.paIoPortRegs[idx];
     101                AssertMsgFailed(("%#zx vs %#x (port %#x)\n", idx, pVM->iom.s.cIoPortRegs, uPort));
     102#endif
     103                break;
     104            }
     105
     106            i = iFirst + (iEnd - iFirst) / 2;
     107        }
     108    }
     109    return NULL;
     110}
     111
     112
     113#ifdef VBOX_WITH_STATISTICS
     114/**
     115 * Gets the I/O port statistics entry .
     116 *
     117 * @returns Pointer to stats.  Instead of NULL, a pointer to IoPortDummyStats is
     118 *          returned, so the caller does not need to check for NULL.
     119 *
     120 * @param   pVM         The cross context VM structure.
     121 * @param   pRegEntry   The I/O port entry to get stats for.
     122 */
     123DECLINLINE(PIOMIOPORTSTATSENTRY) iomIoPortGetStats(PVMCC pVM, CTX_SUFF(PIOMIOPORTENTRY) pRegEntry)
     124{
     125    size_t idxStats = pRegEntry->idxStats;
     126# ifdef IN_RING0
     127    if (idxStats < pVM->iomr0.s.cIoPortStatsAllocation)
     128        return &pVM->iomr0.s.paIoPortStats[idxStats];
     129# else
     130    if (idxStats < pVM->iom.s.cIoPortStats)
     131        return &pVM->iom.s.paIoPortStats[idxStats];
     132# endif
     133    return &pVM->iom.s.IoPortDummyStats;
     134}
     135#endif
     136
    30137
    31138/**
Note: See TracChangeset for help on using the changeset viewer.

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