VirtualBox

Changeset 80641 in vbox for trunk/src/VBox/VMM


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

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

Location:
trunk/src/VBox/VMM
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/Makefile.kmk

    r80335 r80641  
    484484        VMMR0/HMVMXR0.cpp \
    485485        VMMR0/HMSVMR0.cpp \
     486        VMMR0/IOMR0.cpp \
    486487        VMMR0/PDMR0Device.cpp \
    487488        VMMR0/PDMR0Driver.cpp \
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h

    r80089 r80641  
    11581158IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_ins_op,OP_SIZE,_addr,ADDR_SIZE), bool, fIoChecked)
    11591159{
    1160     PVM             pVM  = pVCpu->CTX_SUFF(pVM);
     1160    PVMCC           pVM  = pVCpu->CTX_SUFF(pVM);
    11611161    VBOXSTRICTRC    rcStrict;
    11621162
     
    12501250IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_rep_ins_op,OP_SIZE,_addr,ADDR_SIZE), bool, fIoChecked)
    12511251{
    1252     PVM pVM = pVCpu->CTX_SUFF(pVM);
     1252    PVMCC pVM = pVCpu->CTX_SUFF(pVM);
    12531253
    12541254    IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_ES | CPUMCTX_EXTRN_TR);
     
    14671467IEM_CIMPL_DEF_2(RT_CONCAT4(iemCImpl_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg, bool, fIoChecked)
    14681468{
    1469     PVM             pVM  = pVCpu->CTX_SUFF(pVM);
     1469    PVMCC           pVM  = pVCpu->CTX_SUFF(pVM);
    14701470    VBOXSTRICTRC    rcStrict;
    14711471
     
    15401540IEM_CIMPL_DEF_2(RT_CONCAT4(iemCImpl_rep_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg, bool, fIoChecked)
    15411541{
    1542     PVM pVM = pVCpu->CTX_SUFF(pVM);
     1542    PVMCC pVM = pVCpu->CTX_SUFF(pVM);
    15431543
    15441544    /*
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r80333 r80641  
    7575 * @param   cbValue     The size of the register to read in bytes. 1, 2 or 4 bytes.
    7676 */
    77 VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue)
     77VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVMCC pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue)
    7878{
    7979    Assert(pVCpu->iom.s.PendingIOPortWrite.cbValue == 0);
     
    8181/** @todo should initialize *pu32Value here because it can happen that some
    8282 *        handle is buggy and doesn't handle all cases. */
    83     /* Take the IOM lock before performing any device I/O. */
     83
     84    /* For lookups we need to share lock IOM. */
    8485    int rc2 = IOM_LOCK_SHARED(pVM);
    8586#ifndef IN_RING3
     
    8889#endif
    8990    AssertRC(rc2);
     91
     92    /*
     93     * Get the entry for the current context.
     94     */
     95    CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, Port, &pVCpu->iom.s.idxIoPortLastRead);
     96    if (pRegEntry)
     97    {
     98#ifdef VBOX_WITH_STATISTICS
     99        PIOMIOPORTSTATSENTRY  pStats    = iomIoPortGetStats(pVM, pRegEntry);
     100#endif
     101
     102        /*
     103         * Found an entry, get the data so we can leave the IOM lock.
     104         */
     105        PFNIOMIOPORTIN pfnInCallback = pRegEntry->pfnInCallback;
     106        PPDMDEVINS     pDevIns       = pRegEntry->pDevIns;
     107#ifndef IN_RING3
     108        if (   pfnInCallback
     109            && pDevIns
     110            && pRegEntry->cPorts > 0)
     111        { /* likely */ }
     112        else
     113        {
     114            STAM_COUNTER_INC(&pStats->InRZToR3);
     115            IOM_UNLOCK_SHARED(pVM);
     116            return VINF_IOM_R3_IOPORT_READ;
     117        }
     118#endif
     119        void           *pvUser       = pRegEntry->pvUser;
     120        IOM_UNLOCK_SHARED(pVM);
     121        AssertPtr(pDevIns);
     122        AssertPtr(pfnInCallback);
     123
     124        /*
     125         * Call the device.
     126         */
     127        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);
     128        if (rcStrict == VINF_SUCCESS)
     129        {
     130            STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     131            rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);
     132            STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     133            PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
     134
     135            if (rcStrict == VINF_SUCCESS)
     136                STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
     137#ifndef IN_RING3
     138            else if (rcStrict == VINF_IOM_R3_IOPORT_READ)
     139                STAM_COUNTER_INC(&pStats->InRZToR3);
     140#endif
     141            else if (rcStrict == VERR_IOM_IOPORT_UNUSED)
     142            {
     143                /* make return value */
     144                rcStrict = VINF_SUCCESS;
     145                switch (cbValue)
     146                {
     147                    case 1: *(uint8_t  *)pu32Value = 0xff; break;
     148                    case 2: *(uint16_t *)pu32Value = 0xffff; break;
     149                    case 4: *(uint32_t *)pu32Value = UINT32_C(0xffffffff); break;
     150                    default:
     151                        AssertMsgFailedReturn(("Invalid I/O port size %d. Port=%d\n", cbValue, Port), VERR_IOM_INVALID_IOPORT_SIZE);
     152                }
     153            }
     154            Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=%Rrc\n", Port, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));
     155        }
     156        else
     157            STAM_COUNTER_INC(&pStats->InRZToR3);
     158        return rcStrict;
     159    }
     160
     161    /*
     162     * Old code
     163     * Old code
     164     * Old code
     165     */
    90166
    91167#ifdef VBOX_WITH_STATISTICS
     
    242318 * @param   cb          Size of the transfer unit (1, 2 or 4 bytes).
    243319 */
    244 VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort,
     320VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortReadString(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uPort,
    245321                                               void *pvDst, uint32_t *pcTransfers, unsigned cb)
    246322{
    247323    Assert(pVCpu->iom.s.PendingIOPortWrite.cbValue == 0);
    248324
    249     /* Take the IOM lock before performing any device I/O. */
     325    /* For lookups we need to share lock IOM. */
    250326    int rc2 = IOM_LOCK_SHARED(pVM);
    251327#ifndef IN_RING3
     
    257333    const uint32_t cRequestedTransfers = *pcTransfers;
    258334    Assert(cRequestedTransfers > 0);
     335
     336    /*
     337     * Get the entry for the current context.
     338     */
     339    CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, uPort, &pVCpu->iom.s.idxIoPortLastReadStr);
     340    if (pRegEntry)
     341    {
     342#ifdef VBOX_WITH_STATISTICS
     343        PIOMIOPORTSTATSENTRY  pStats    = iomIoPortGetStats(pVM, pRegEntry);
     344#endif
     345
     346        /*
     347         * Found an entry, get the data so we can leave the IOM lock.
     348         */
     349        PFNIOMIOPORTINSTRING pfnInStrCallback = pRegEntry->pfnInStrCallback;
     350        PFNIOMIOPORTIN       pfnInCallback    = pRegEntry->pfnInCallback;
     351        PPDMDEVINS           pDevIns          = pRegEntry->pDevIns;
     352#ifndef IN_RING3
     353        if (   pfnInCallback
     354            && pDevIns
     355            && pRegEntry->cPorts > 0)
     356        { /* likely */ }
     357        else
     358        {
     359            STAM_COUNTER_INC(&pStats->InRZToR3);
     360            IOM_UNLOCK_SHARED(pVM);
     361            return VINF_IOM_R3_IOPORT_READ;
     362        }
     363#endif
     364        void           *pvUser       = pRegEntry->pvUser;
     365        IOM_UNLOCK_SHARED(pVM);
     366        AssertPtr(pDevIns);
     367        AssertPtr(pfnInCallback);
     368
     369        /*
     370         * Call the device.
     371         */
     372        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);
     373        if (rcStrict == VINF_SUCCESS)
     374        {
     375            /*
     376             * First using the string I/O callback.
     377             */
     378            if (pfnInStrCallback)
     379            {
     380                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     381                rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);
     382                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     383            }
     384
     385            /*
     386             * Then doing the single I/O fallback.
     387             */
     388            if (   *pcTransfers > 0
     389                && rcStrict == VINF_SUCCESS)
     390            {
     391                pvDst = (uint8_t *)pvDst + (cRequestedTransfers - *pcTransfers) * cb;
     392                do
     393                {
     394                    uint32_t u32Value = 0;
     395                    STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);
     396                    rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb);
     397                    STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);
     398                    if (rcStrict == VERR_IOM_IOPORT_UNUSED)
     399                    {
     400                        u32Value = UINT32_MAX;
     401                        rcStrict = VINF_SUCCESS;
     402                    }
     403                    if (IOM_SUCCESS(rcStrict))
     404                    {
     405                        switch (cb)
     406                        {
     407                            case 4: *(uint32_t *)pvDst =           u32Value; pvDst = (uint8_t *)pvDst + 4; break;
     408                            case 2: *(uint16_t *)pvDst = (uint16_t)u32Value; pvDst = (uint8_t *)pvDst + 2; break;
     409                            case 1: *(uint8_t  *)pvDst = (uint8_t )u32Value; pvDst = (uint8_t *)pvDst + 1; break;
     410                            default: AssertFailed();
     411                        }
     412                        *pcTransfers -= 1;
     413                    }
     414                } while (   *pcTransfers > 0
     415                         && rcStrict == VINF_SUCCESS);
     416            }
     417            PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
     418
     419#ifdef VBOX_WITH_STATISTICS
     420            if (rcStrict == VINF_SUCCESS && pStats)
     421                STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));
     422# ifndef IN_RING3
     423            else if (rcStrict == VINF_IOM_R3_IOPORT_READ && pStats)
     424                STAM_COUNTER_INC(&pStats->InRZToR3);
     425# endif
     426#endif
     427            Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",
     428                  uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
     429        }
     430#ifndef IN_RING3
     431        else
     432            STAM_COUNTER_INC(&pStats->InRZToR3);
     433#endif
     434        return rcStrict;
     435    }
     436
     437    /*
     438     * Old code
     439     * Old code
     440     * Old code
     441     */
    259442
    260443#ifdef VBOX_WITH_STATISTICS
     
    458641 * @param   cbValue     The size of the register to read in bytes. 1, 2 or 4 bytes.
    459642 */
    460 VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
     643VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVMCC pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
    461644{
    462645#ifndef IN_RING3
     
    464647#endif
    465648
    466     /* Take the IOM lock before performing any device I/O. */
     649    /* For lookups we need to share lock IOM. */
    467650    int rc2 = IOM_LOCK_SHARED(pVM);
    468651#ifndef IN_RING3
     
    472655    AssertRC(rc2);
    473656
    474 /** @todo bird: When I get time, I'll remove the RC/R0 trees and link the RC/R0
    475  *        entries to the ring-3 node. */
     657    /*
     658     * Get the entry for the current context.
     659     */
     660    CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, Port, &pVCpu->iom.s.idxIoPortLastWrite);
     661    if (pRegEntry)
     662    {
     663#ifdef VBOX_WITH_STATISTICS
     664        PIOMIOPORTSTATSENTRY  pStats    = iomIoPortGetStats(pVM, pRegEntry);
     665#endif
     666
     667        /*
     668         * Found an entry, get the data so we can leave the IOM lock.
     669         */
     670        PFNIOMIOPORTOUT pfnOutCallback   = pRegEntry->pfnOutCallback;
     671        PPDMDEVINS      pDevIns          = pRegEntry->pDevIns;
     672#ifndef IN_RING3
     673        if (   pfnOutCallback
     674            && pDevIns
     675            && pRegEntry->cPorts > 0)
     676        { /* likely */ }
     677        else
     678        {
     679            IOM_UNLOCK_SHARED(pVM);
     680            STAM_COUNTER_INC(&pStats->OutRZToR3);
     681            return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);
     682        }
     683#endif
     684        void           *pvUser       = pRegEntry->pvUser;
     685        IOM_UNLOCK_SHARED(pVM);
     686        AssertPtr(pDevIns);
     687        AssertPtr(pfnOutCallback);
     688
     689        /*
     690         * Call the device.
     691         */
     692        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);
     693        if (rcStrict == VINF_SUCCESS)
     694        {
     695            STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     696            rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);
     697            STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     698
     699            PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
     700
     701#ifdef VBOX_WITH_STATISTICS
     702            if (rcStrict == VINF_SUCCESS)
     703                STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
     704#endif
     705            Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d rc=%Rrc\n", Port, u32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));
     706        }
     707#ifndef IN_RING3
     708        if (rcStrict == VINF_IOM_R3_IOPORT_WRITE)
     709        {
     710            STAM_COUNTER_INC(&pStats->OutRZToR3);
     711            return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);
     712        }
     713#endif
     714        return rcStrict;
     715    }
     716
     717    /*
     718     * Old code
     719     * Old code
     720     * Old code
     721     */
     722
    476723#ifdef VBOX_WITH_STATISTICS
    477724    /*
     
    611858 * @param   cb          Size of the transfer unit (1, 2 or 4 bytes).
    612859 */
    613 VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,
     860VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortWriteString(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,
    614861                                                uint32_t *pcTransfers, unsigned cb)
    615862{
     
    627874    const uint32_t cRequestedTransfers = *pcTransfers;
    628875    Assert(cRequestedTransfers > 0);
     876
     877    /*
     878     * Get the entry for the current context.
     879     */
     880    CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, uPort, &pVCpu->iom.s.idxIoPortLastWriteStr);
     881    if (pRegEntry)
     882    {
     883#ifdef VBOX_WITH_STATISTICS
     884        PIOMIOPORTSTATSENTRY  pStats    = iomIoPortGetStats(pVM, pRegEntry);
     885#endif
     886
     887        /*
     888         * Found an entry, get the data so we can leave the IOM lock.
     889         */
     890        PFNIOMIOPORTOUTSTRING   pfnOutStrCallback = pRegEntry->pfnOutStrCallback;
     891        PFNIOMIOPORTOUT         pfnOutCallback    = pRegEntry->pfnOutCallback;
     892        PPDMDEVINS              pDevIns           = pRegEntry->pDevIns;
     893#ifndef IN_RING3
     894        if (   pfnOutCallback
     895            && pDevIns
     896            && pRegEntry->cPorts > 0)
     897        { /* likely */ }
     898        else
     899        {
     900            IOM_UNLOCK_SHARED(pVM);
     901            STAM_COUNTER_INC(&pStats->OutRZToR3);
     902            return VINF_IOM_R3_IOPORT_WRITE;
     903        }
     904#endif
     905        void           *pvUser       = pRegEntry->pvUser;
     906        IOM_UNLOCK_SHARED(pVM);
     907        AssertPtr(pDevIns);
     908        AssertPtr(pfnOutCallback);
     909
     910        /*
     911         * Call the device.
     912         */
     913        VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);
     914        if (rcStrict == VINF_SUCCESS)
     915        {
     916            /*
     917             * First using string I/O if possible.
     918             */
     919            if (pfnOutStrCallback)
     920            {
     921                STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     922                rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);
     923                STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     924            }
     925
     926            /*
     927             * Then doing the single I/O fallback.
     928             */
     929            if (   *pcTransfers > 0
     930                && rcStrict == VINF_SUCCESS)
     931            {
     932                pvSrc = (uint8_t *)pvSrc + (cRequestedTransfers - *pcTransfers) * cb;
     933                do
     934                {
     935                    uint32_t u32Value;
     936                    switch (cb)
     937                    {
     938                        case 4: u32Value = *(uint32_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 4; break;
     939                        case 2: u32Value = *(uint16_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 2; break;
     940                        case 1: u32Value = *(uint8_t  *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 1; break;
     941                        default: AssertFailed(); u32Value = UINT32_MAX;
     942                    }
     943                    STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);
     944                    rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb);
     945                    STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);
     946                    if (IOM_SUCCESS(rcStrict))
     947                        *pcTransfers -= 1;
     948                } while (   *pcTransfers > 0
     949                         && rcStrict == VINF_SUCCESS);
     950            }
     951
     952            PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));
     953
     954#ifdef VBOX_WITH_STATISTICS
     955            if (rcStrict == VINF_SUCCESS)
     956                STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));
     957# ifndef IN_RING3
     958            else if (rcStrict == VINF_IOM_R3_IOPORT_WRITE)
     959                STAM_COUNTER_INC(&pStats->OutRZToR3);
     960# endif
     961#endif
     962            Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n",
     963                  uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));
     964        }
     965#ifndef IN_RING3
     966        else
     967            STAM_COUNTER_INC(&pStats->OutRZToR3);
     968#endif
     969        return rcStrict;
     970    }
     971
     972    /*
     973     * Old code.
     974     * Old code.
     975     * Old code.
     976     */
    629977
    630978#ifdef VBOX_WITH_STATISTICS
  • trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp

    r80531 r80641  
    5454#include <VBox/vmm/gmm.h>
    5555#include "GVMMR0Internal.h"
     56#include <VBox/vmm/iom.h>
    5657#include <VBox/vmm/pdm.h>
    57 #include <VBox/vmm/vmcc.h>
    58 #include <VBox/vmm/vmcpuset.h>
    5958#include <VBox/vmm/vmm.h>
    6059#ifdef VBOX_WITH_NEM_R0
    6160# include <VBox/vmm/nem.h>
    6261#endif
     62#include <VBox/vmm/vmcpuset.h>
     63#include <VBox/vmm/vmcc.h>
    6364#include <VBox/param.h>
    6465#include <VBox/err.h>
     
    903904                        GMMR0InitPerVMData(pGVM);
    904905                        PDMR0InitPerVMData(pGVM);
     906                        IOMR0InitPerVMData(pGVM);
    905907                        pGVM->gvmm.s.VMMemObj  = hVMMemObj;
    906908
     
    12941296#endif
    12951297    PDMR0CleanupVM(pGVM);
     1298    IOMR0CleanupVM(pGVM);
    12961299
    12971300    AssertCompile(NIL_RTTHREADCTXHOOK == (RTTHREADCTXHOOK)0); /* Depends on zero initialized memory working for NIL at the moment. */
  • trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp

    r80548 r80641  
    195195                                                          void *pvUser)
    196196{
    197     RT_NOREF(pDevIns, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser);
    198     return VERR_NOT_IMPLEMENTED;
     197    PDMDEV_ASSERT_DEVINS(pDevIns);
     198    LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: hIoPorts=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p\n",
     199             pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser));
     200    PGVM pGVM = pDevIns->Internal.s.pGVM;
     201    VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
     202    VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
     203
     204    int rc = IOMR0IoPortSetUpContext(pGVM, pDevIns, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser);
     205
     206    LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
     207    return rc;
    199208}
    200209
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r80587 r80641  
    2323#include <VBox/vmm/vmm.h>
    2424#include <VBox/sup.h>
     25#include <VBox/vmm/iom.h>
    2526#include <VBox/vmm/trpm.h>
    2627#include <VBox/vmm/cpum.h>
     
    21982199
    21992200        /*
     2201         * IOM requests.
     2202         */
     2203        case VMMR0_DO_IOM_GROW_IO_PORTS:
     2204        {
     2205            if (pReqHdr || idCpu != 0)
     2206                return VERR_INVALID_PARAMETER;
     2207            rc = IOMR0IoPortGrowRegistrationTables(pGVM, u64Arg);
     2208            VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING);
     2209            break;
     2210        }
     2211
     2212        case VMMR0_DO_IOM_GROW_IO_PORT_STATS:
     2213        {
     2214            if (pReqHdr || idCpu != 0)
     2215                return VERR_INVALID_PARAMETER;
     2216            rc = IOMR0IoPortGrowStatisticsTable(pGVM, u64Arg);
     2217            VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING);
     2218            break;
     2219        }
     2220
     2221        /*
    22002222         * For profiling.
    22012223         */
     
    22962318
    22972319            case VMMR0_DO_PDM_DEVICE_CREATE:
     2320            case VMMR0_DO_IOM_GROW_IO_PORTS:
     2321            case VMMR0_DO_IOM_GROW_IO_PORT_STATS:
    22982322            {
    22992323                PGVMCPU        pGVCpu        = &pGVM->aCpus[idCpu];
  • trunk/src/VBox/VMM/VMMR3/IOM.cpp

    r80531 r80641  
    230230            STAM_REG(pVM, &pVM->iom.s.StatRZInstOther,        STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Inst/Other",           STAMUNIT_OCCURENCES,     "Other instructions counter.");
    231231            STAM_REG(pVM, &pVM->iom.s.StatR3MMIOHandler,      STAMTYPE_COUNTER, "/IOM/R3-MMIOHandler",                      STAMUNIT_OCCURENCES,     "Number of calls to iomR3MmioHandler.");
     232#if 0 /* unused */
    232233            STAM_REG(pVM, &pVM->iom.s.StatInstIn,             STAMTYPE_COUNTER, "/IOM/IOWork/In",                           STAMUNIT_OCCURENCES,     "Counter of any IN instructions.");
    233234            STAM_REG(pVM, &pVM->iom.s.StatInstOut,            STAMTYPE_COUNTER, "/IOM/IOWork/Out",                          STAMUNIT_OCCURENCES,     "Counter of any OUT instructions.");
    234235            STAM_REG(pVM, &pVM->iom.s.StatInstIns,            STAMTYPE_COUNTER, "/IOM/IOWork/Ins",                          STAMUNIT_OCCURENCES,     "Counter of any INS instructions.");
    235236            STAM_REG(pVM, &pVM->iom.s.StatInstOuts,           STAMTYPE_COUNTER, "/IOM/IOWork/Outs",                         STAMUNIT_OCCURENCES,     "Counter of any OUTS instructions.");
     237#endif
    236238        }
    237239    }
     
    413415    return VINF_SUCCESS;
    414416}
     417
     418
     419/**
     420 * Worker for PDMDEVHLPR3::pfnIoPortCreateEx.
     421 */
     422VMMR3_INT_DECL(int)  IOMR3IoPortCreate(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
     423                                       uint32_t iPciRegion, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
     424                                       PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, RTR3PTR pvUser,
     425                                       const char *pszDesc, PIOMIOPORTHANDLE phIoPorts)
     426{
     427    /*
     428     * Validate input.
     429     */
     430    AssertPtrReturn(phIoPorts, VERR_INVALID_POINTER);
     431    *phIoPorts = UINT32_MAX;
     432    VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
     433    VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
     434
     435    AssertPtrReturn(pDevIns, VERR_INVALID_POINTER);
     436
     437    AssertMsgReturn(cPorts > 0 && cPorts <= _8K, ("cPorts=%s\n", cPorts), VERR_OUT_OF_RANGE);
     438    AssertReturn(!fFlags, VERR_INVALID_FLAGS);
     439
     440    AssertReturn(pfnOut || pfnIn || pfnOutStr || pfnInStr, VERR_INVALID_PARAMETER);
     441    AssertPtrNullReturn(pfnOut, VERR_INVALID_POINTER);
     442    AssertPtrNullReturn(pfnIn, VERR_INVALID_POINTER);
     443    AssertPtrNullReturn(pfnOutStr, VERR_INVALID_POINTER);
     444    AssertPtrNullReturn(pfnInStr, VERR_INVALID_POINTER);
     445    AssertPtrReturn(pszDesc, VERR_INVALID_POINTER);
     446    AssertReturn(*pszDesc != '\0', VERR_INVALID_POINTER);
     447    AssertReturn(strlen(pszDesc) < 128, VERR_INVALID_POINTER);
     448
     449    /*
     450     * Ensure that we've got table space for it.
     451     */
     452#ifndef VBOX_WITH_STATISTICS
     453    uint16_t const idxStats        = UINT16_MAX;
     454#else
     455    uint32_t const idxStats        = pVM->iom.s.cIoPortStats;
     456    uint32_t const cNewIoPortStats = idxStats + cPorts;
     457    AssertReturn(cNewIoPortStats <= _64K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS);
     458    if (cNewIoPortStats > pVM->iom.s.cIoPortStatsAllocation)
     459    {
     460        int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORT_STATS, cNewIoPortStats, NULL);
     461        AssertLogRelRCReturn(rc, rc);
     462        AssertReturn(idxStats == pVM->iom.s.cIoPortStats, VERR_IOM_IOPORT_IPE_1);
     463        AssertReturn(cNewIoPortStats <= pVM->iom.s.cIoPortStatsAllocation, VERR_IOM_IOPORT_IPE_2);
     464    }
     465#endif
     466
     467    uint32_t idx = pVM->iom.s.cIoPortRegs;
     468    if (idx >= pVM->iom.s.cIoPortAlloc)
     469    {
     470        int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORTS, pVM->iom.s.cIoPortAlloc + 1, NULL);
     471        AssertLogRelRCReturn(rc, rc);
     472        AssertReturn(idx == pVM->iom.s.cIoPortRegs, VERR_IOM_IOPORT_IPE_1);
     473        AssertReturn(idx < pVM->iom.s.cIoPortAlloc, VERR_IOM_IOPORT_IPE_2);
     474    }
     475
     476    /*
     477     * Enter it.
     478     */
     479    pVM->iom.s.paIoPortRegs[idx].pvUser             = pvUser;
     480    pVM->iom.s.paIoPortRegs[idx].pDevIns            = pDevIns;
     481    pVM->iom.s.paIoPortRegs[idx].pfnOutCallback     = pfnOut    ? pfnOut    : iomR3IOPortDummyOut;
     482    pVM->iom.s.paIoPortRegs[idx].pfnInCallback      = pfnIn     ? pfnIn     : iomR3IOPortDummyIn;
     483    pVM->iom.s.paIoPortRegs[idx].pfnOutStrCallback  = pfnOutStr ? pfnOutStr : iomR3IOPortDummyOutStr;
     484    pVM->iom.s.paIoPortRegs[idx].pfnInStrCallback   = pfnInStr  ? pfnInStr  : iomR3IOPortDummyInStr;
     485    pVM->iom.s.paIoPortRegs[idx].pszDesc            = pszDesc;
     486    pVM->iom.s.paIoPortRegs[idx].pPciDev            = pPciDev;
     487    pVM->iom.s.paIoPortRegs[idx].iPciRegion         = iPciRegion;
     488    pVM->iom.s.paIoPortRegs[idx].cPorts             = cPorts;
     489    pVM->iom.s.paIoPortRegs[idx].uPort              = UINT16_MAX;
     490    pVM->iom.s.paIoPortRegs[idx].idxStats           = (uint16_t)idxStats;
     491    pVM->iom.s.paIoPortRegs[idx].fMapped            = false;
     492    pVM->iom.s.paIoPortRegs[idx].idxSelf            = idx;
     493
     494    pVM->iom.s.cIoPortRegs = idx + 1;
     495    *phIoPorts = idx;
     496    return VINF_SUCCESS;
     497}
     498
     499
     500/**
     501 * Worker for PDMDEVHLPR3::pfnIoPortMap.
     502 */
     503VMMR3_INT_DECL(int)  IOMR3IoPortMap(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT uPort)
     504{
     505    /*
     506     * Validate input and state.
     507     */
     508    AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE);
     509    AssertReturn(hIoPorts < pVM->iom.s.cIoPortRegs, VERR_IOM_INVALID_IOPORT_HANDLE);
     510    PIOMIOPORTENTRYR3 const pRegEntry = &pVM->iom.s.paIoPortRegs[hIoPorts];
     511    AssertReturn(pRegEntry->pDevIns == pDevIns, VERR_IOM_INVALID_IOPORT_HANDLE);
     512
     513    RTIOPORT const cPorts = pRegEntry->cPorts;
     514    AssertMsgReturn(cPorts > 0 && cPorts <= _8K, ("cPorts=%s\n", cPorts), VERR_IOM_IOPORT_IPE_1);
     515    AssertReturn((uint32_t)uPort + cPorts <= _64K, VERR_OUT_OF_RANGE);
     516    RTIOPORT const uLastPort = uPort + cPorts - 1;
     517
     518    /*
     519     * Do the mapping.
     520     */
     521    int rc = VINF_SUCCESS;
     522    IOM_LOCK_EXCL(pVM);
     523
     524    if (!pRegEntry->fMapped)
     525    {
     526        uint32_t const cEntries = RT_MIN(pVM->iom.s.cIoPortLookupEntries, pVM->iom.s.cIoPortRegs);
     527        Assert(pVM->iom.s.cIoPortLookupEntries == cEntries);
     528
     529        PIOMIOPORTLOOKUPENTRY paEntries = pVM->iom.s.paIoPortLookup;
     530        PIOMIOPORTLOOKUPENTRY pEntry;
     531        if (cEntries > 0)
     532        {
     533            uint32_t iFirst = 0;
     534            uint32_t iEnd   = cEntries;
     535            uint32_t i      = cEntries / 2;
     536            for (;;)
     537            {
     538                pEntry = &paEntries[i];
     539                if (pEntry->uLastPort < uPort)
     540                {
     541                    i += 1;
     542                    if (i < iEnd)
     543                        iFirst = i;
     544                    else
     545                    {
     546                        /* Insert after the entry we just considered: */
     547                        pEntry += 1;
     548                        if (iEnd < cEntries)
     549                            memmove(pEntry + 1, pEntry, sizeof(*pEntry) * (cEntries - iEnd));
     550                        break;
     551                    }
     552                }
     553                else if (pEntry->uFirstPort > uLastPort)
     554                {
     555                    if (i > iFirst)
     556                        iEnd = i;
     557                    else
     558                    {
     559                        /* Insert at the entry we just considered: */
     560                        if (iEnd < cEntries)
     561                            memmove(pEntry + 1, pEntry, sizeof(*pEntry) * (cEntries - iEnd));
     562                        break;
     563                    }
     564                }
     565                else
     566                {
     567                    /* Oops! We've got a conflict. */
     568                    AssertLogRelMsgFailed(("%u..%u (%s) conflicts with existing mapping %u..%u (%s)\n",
     569                                           uPort, uLastPort, pRegEntry->pszDesc,
     570                                           pEntry->uFirstPort, pEntry->uLastPort, pVM->iom.s.paIoPortRegs[pEntry->idx].pszDesc));
     571                    IOM_UNLOCK_EXCL(pVM);
     572                    return VERR_IOM_IOPORT_RANGE_CONFLICT;
     573                }
     574
     575                i = iFirst + (iEnd - iFirst) / 2;
     576            }
     577        }
     578        else
     579            pEntry = paEntries;
     580
     581        /*
     582         * Fill in the entry and bump the table size.
     583         */
     584        pEntry->idx        = hIoPorts;
     585        pEntry->uFirstPort = uPort;
     586        pEntry->uLastPort  = uLastPort;
     587        pVM->iom.s.cIoPortLookupEntries = cEntries + 1;
     588
     589        pRegEntry->uPort   = uPort;
     590        pRegEntry->fMapped = true;
     591
     592#ifdef VBOX_STRICT
     593        /*
     594         * Assert table sanity.
     595         */
     596        AssertMsg(paEntries[0].uLastPort >= paEntries[0].uFirstPort, ("%#x %#x\n", paEntries[0].uLastPort, paEntries[0].uFirstPort));
     597        AssertMsg(paEntries[0].idx < pVM->iom.s.cIoPortRegs, ("%#x %#x\n", paEntries[0].idx, pVM->iom.s.cIoPortRegs));
     598
     599        RTIOPORT uPortPrev = paEntries[0].uLastPort;
     600        for (size_t i = 1; i <= cEntries; i++)
     601        {
     602            AssertMsg(paEntries[i].uLastPort >= paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, paEntries[i].uLastPort, paEntries[i].uFirstPort));
     603            AssertMsg(paEntries[i].idx < pVM->iom.s.cIoPortRegs, ("%u: %#x %#x\n", i, paEntries[i].idx, pVM->iom.s.cIoPortRegs));
     604            AssertMsg(uPortPrev < paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, uPortPrev, paEntries[i].uFirstPort));
     605            uPortPrev = paEntries[i].uLastPort;
     606        }
     607#endif
     608    }
     609    else
     610    {
     611        AssertFailed();
     612        rc = VERR_IOM_IOPORTS_ALREADY_MAPPED;
     613    }
     614
     615    IOM_UNLOCK_EXCL(pVM);
     616    return rc;
     617}
     618
     619
     620/**
     621 * Worker for PDMDEVHLPR3::pfnIoPortUnmap.
     622 */
     623VMMR3_INT_DECL(int)  IOMR3IoPortUnmap(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
     624{
     625    /*
     626     * Validate input and state.
     627     */
     628    AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE);
     629    AssertReturn(hIoPorts < pVM->iom.s.cIoPortRegs, VERR_IOM_INVALID_IOPORT_HANDLE);
     630    PIOMIOPORTENTRYR3 const pRegEntry = &pVM->iom.s.paIoPortRegs[hIoPorts];
     631    AssertReturn(pRegEntry->pDevIns == pDevIns, VERR_IOM_INVALID_IOPORT_HANDLE);
     632
     633    /*
     634     * Do the mapping.
     635     */
     636    int rc;
     637    IOM_LOCK_EXCL(pVM);
     638
     639    if (pRegEntry->fMapped)
     640    {
     641        RTIOPORT const uPort     = pRegEntry->uPort;
     642        RTIOPORT const uLastPort = uPort + pRegEntry->cPorts - 1;
     643        uint32_t const cEntries  = RT_MIN(pVM->iom.s.cIoPortLookupEntries, pVM->iom.s.cIoPortRegs);
     644        Assert(pVM->iom.s.cIoPortLookupEntries == cEntries);
     645        Assert(cEntries > 0);
     646
     647        PIOMIOPORTLOOKUPENTRY paEntries = pVM->iom.s.paIoPortLookup;
     648        uint32_t iFirst = 0;
     649        uint32_t iEnd   = cEntries;
     650        uint32_t i      = cEntries / 2;
     651        for (;;)
     652        {
     653            PIOMIOPORTLOOKUPENTRY pEntry = &paEntries[i];
     654            if (pEntry->uLastPort < uPort)
     655            {
     656                i += 1;
     657                if (i < iEnd)
     658                    iFirst = i;
     659                else
     660                {
     661                    rc = VERR_IOM_IOPORT_IPE_1;
     662                    AssertLogRelMsgFailedBreak(("%u..%u (%s) not found!\n", uPort, uLastPort, pRegEntry->pszDesc));
     663                }
     664            }
     665            else if (pEntry->uFirstPort > uLastPort)
     666            {
     667                if (i > iFirst)
     668                    iEnd = i;
     669                else
     670                {
     671                    rc = VERR_IOM_IOPORT_IPE_1;
     672                    AssertLogRelMsgFailedBreak(("%u..%u (%s) not found!\n", uPort, uLastPort, pRegEntry->pszDesc));
     673                }
     674            }
     675            else if (pEntry->idx == hIoPorts)
     676            {
     677                Assert(pEntry->uFirstPort == uPort);
     678                Assert(pEntry->uLastPort == uLastPort);
     679                if (i + 1 < cEntries)
     680                    memmove(pEntry, pEntry + 1, sizeof(*pEntry) * (cEntries - i - 1));
     681                pVM->iom.s.cIoPortLookupEntries = cEntries - 1;
     682                pRegEntry->uPort   = UINT16_MAX;
     683                pRegEntry->fMapped = false;
     684                rc = VINF_SUCCESS;
     685                break;
     686            }
     687            else
     688            {
     689                AssertLogRelMsgFailed(("Lookig for %u..%u (%s), found %u..%u (%s) instead!\n",
     690                                       uPort, uLastPort, pRegEntry->pszDesc,
     691                                       pEntry->uFirstPort, pEntry->uLastPort, pVM->iom.s.paIoPortRegs[pEntry->idx].pszDesc));
     692                rc = VERR_IOM_IOPORT_IPE_1;
     693                break;
     694            }
     695
     696            i = iFirst + (iEnd - iFirst) / 2;
     697        }
     698
     699#ifdef VBOX_STRICT
     700        /*
     701         * Assert table sanity.
     702         */
     703        AssertMsg(paEntries[0].uLastPort >= paEntries[0].uFirstPort, ("%#x %#x\n", paEntries[0].uLastPort, paEntries[0].uFirstPort));
     704        AssertMsg(paEntries[0].idx < pVM->iom.s.cIoPortRegs, ("%#x %#x\n", paEntries[0].idx, pVM->iom.s.cIoPortRegs));
     705
     706        RTIOPORT uPortPrev = paEntries[0].uLastPort;
     707        for (i = 1; i <= cEntries; i++)
     708        {
     709            AssertMsg(paEntries[i].uLastPort >= paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, paEntries[i].uLastPort, paEntries[i].uFirstPort));
     710            AssertMsg(paEntries[i].idx < pVM->iom.s.cIoPortRegs, ("%u: %#x %#x\n", i, paEntries[i].idx, pVM->iom.s.cIoPortRegs));
     711            AssertMsg(uPortPrev < paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, uPortPrev, paEntries[i].uFirstPort));
     712            uPortPrev = paEntries[i].uLastPort;
     713        }
     714#endif
     715    }
     716    else
     717    {
     718        AssertFailed();
     719        rc = VERR_IOM_IOPORTS_NOT_MAPPED;
     720    }
     721
     722    IOM_UNLOCK_EXCL(pVM);
     723    return rc;
     724}
     725
    415726
    416727#ifdef VBOX_WITH_STATISTICS
  • trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp

    r80531 r80641  
    104104                                                    RTR3PTR pvUser, const char *pszDesc, PIOMIOPORTHANDLE phIoPorts)
    105105{
    106     RT_NOREF(pDevIns, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, phIoPorts);
    107     return VERR_NOT_IMPLEMENTED;
     106    PDMDEV_ASSERT_DEVINS(pDevIns);
     107    LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: cPorts=%#x fFlags=%#x pPciDev=%p iPciRegion=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p pszDesc=%p:{%s} phIoPorts=%p\n",
     108             pDevIns->pReg->szName, pDevIns->iInstance, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr,
     109             pvUser, pszDesc, pszDesc, phIoPorts));
     110    PVM pVM = pDevIns->Internal.s.pVMR3;
     111    VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
     112    VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
     113
     114    int rc = IOMR3IoPortCreate(pVM, pDevIns, cPorts, fFlags, pPciDev, iPciRegion,
     115                               pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, phIoPorts);
     116
     117    LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: returns %Rrc (*phIoPorts=%#x)\n",
     118             pDevIns->pReg->szName, pDevIns->iInstance, rc, *phIoPorts));
     119    return rc;
    108120}
    109121
     
    112124static DECLCALLBACK(int) pdmR3DevHlp_IoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port)
    113125{
    114     RT_NOREF(pDevIns, hIoPorts, Port);
    115     return VERR_NOT_IMPLEMENTED;
     126    PDMDEV_ASSERT_DEVINS(pDevIns);
     127    LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x Port=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, Port));
     128    PVM pVM = pDevIns->Internal.s.pVMR3;
     129    VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
     130
     131    int rc = IOMR3IoPortMap(pVM, pDevIns, hIoPorts, Port);
     132
     133    LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
     134    return rc;
    116135}
    117136
     
    120139static DECLCALLBACK(int) pdmR3DevHlp_IoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
    121140{
    122     RT_NOREF(pDevIns, hIoPorts);
    123     return VERR_NOT_IMPLEMENTED;
     141    PDMDEV_ASSERT_DEVINS(pDevIns);
     142    LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
     143    PVM pVM = pDevIns->Internal.s.pVMR3;
     144    VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
     145
     146    int rc = IOMR3IoPortUnmap(pVM, pDevIns, hIoPorts);
     147
     148    LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
     149    return rc;
    124150}
    125151
     
    129155{
    130156    PDMDEV_ASSERT_DEVINS(pDevIns);
    131     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p p32_tszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,
     157    LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,
    132158             Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
    133159    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
  • 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/**
  • trunk/src/VBox/VMM/include/IOMInternal.h

    r80281 r80641  
    139139/** Pointer to I/O port statistics. */
    140140typedef IOMMMIOSTATS *PIOMMMIOSTATS;
     141
     142/**
     143 * I/O port lookup table entry.
     144 */
     145typedef struct IOMIOPORTLOOKUPENTRY
     146{
     147    /** The first port in the range. */
     148    RTIOPORT                    uFirstPort;
     149    /** The last port in the range (inclusive). */
     150    RTIOPORT                    uLastPort;
     151    /** The registration handle/index. */
     152    uint16_t                    idx;
     153} IOMIOPORTLOOKUPENTRY;
     154/** Pointer to an I/O port lookup table entry. */
     155typedef IOMIOPORTLOOKUPENTRY *PIOMIOPORTLOOKUPENTRY;
     156/** Pointer to a const I/O port lookup table entry. */
     157typedef IOMIOPORTLOOKUPENTRY const *PCIOMIOPORTLOOKUPENTRY;
     158
     159/**
     160 * Ring-0 I/O port handle table entry.
     161 */
     162typedef struct IOMIOPORTENTRYR0
     163{
     164    /** Pointer to user argument. */
     165    RTR0PTR                             pvUser;
     166    /** Pointer to the associated device instance, NULL if entry not used. */
     167    R0PTRTYPE(PPDMDEVINS)               pDevIns;
     168    /** Pointer to OUT callback function. */
     169    R0PTRTYPE(PFNIOMIOPORTOUT)          pfnOutCallback;
     170    /** Pointer to IN callback function. */
     171    R0PTRTYPE(PFNIOMIOPORTIN)           pfnInCallback;
     172    /** Pointer to string OUT callback function. */
     173    R0PTRTYPE(PFNIOMIOPORTOUTSTRING)    pfnOutStrCallback;
     174    /** Pointer to string IN callback function. */
     175    R0PTRTYPE(PFNIOMIOPORTINSTRING)     pfnInStrCallback;
     176    /** The entry of the first statistics entry, UINT16_MAX if no stats. */
     177    uint16_t                            idxStats;
     178    /** The number of ports covered by this entry, 0 if entry not used. */
     179    RTIOPORT                            cPorts;
     180    /** Same as the handle index. */
     181    uint16_t                            idxSelf;
     182} IOMIOPORTENTRYR0;
     183/** Pointer to a ring-0 I/O port handle table entry. */
     184typedef IOMIOPORTENTRYR0 *PIOMIOPORTENTRYR0;
     185/** Pointer to a const ring-0 I/O port handle table entry. */
     186typedef IOMIOPORTENTRYR0 const *PCIOMIOPORTENTRYR0;
     187
     188/**
     189 * Ring-3 I/O port handle table entry.
     190 */
     191typedef struct IOMIOPORTENTRYR3
     192{
     193    /** Pointer to user argument. */
     194    RTR3PTR                             pvUser;
     195    /** Pointer to the associated device instance. */
     196    R3PTRTYPE(PPDMDEVINS)               pDevIns;
     197    /** Pointer to OUT callback function. */
     198    R3PTRTYPE(PFNIOMIOPORTOUT)          pfnOutCallback;
     199    /** Pointer to IN callback function. */
     200    R3PTRTYPE(PFNIOMIOPORTIN)           pfnInCallback;
     201    /** Pointer to string OUT callback function. */
     202    R3PTRTYPE(PFNIOMIOPORTOUTSTRING)    pfnOutStrCallback;
     203    /** Pointer to string IN callback function. */
     204    R3PTRTYPE(PFNIOMIOPORTINSTRING)     pfnInStrCallback;
     205    /** Description / Name. For easing debugging. */
     206    R3PTRTYPE(const char *)             pszDesc;
     207    /** PCI device the registration is associated with. */
     208    R3PTRTYPE(PPDMPCIDEV)               pPciDev;
     209    /** The PCI device region (high 16-bit word) and subregion (low word),
     210     *  UINT32_MAX if not applicable. */
     211    uint32_t                            iPciRegion;
     212    /** The number of ports covered by this entry. */
     213    RTIOPORT                            cPorts;
     214    /** The current port mapping (duplicates lookup table). */
     215    RTIOPORT                            uPort;
     216    /** The entry of the first statistics entry, UINT16_MAX if no stats. */
     217    uint16_t                            idxStats;
     218    /** Set if mapped, clear if not.
     219     * Only updated when critsect is held exclusively.   */
     220    bool                                fMapped;
     221    /** Same as the handle index. */
     222    uint16_t                            idxSelf;
     223} IOMIOPORTENTRYR3;
     224/** Pointer to a ring-3 I/O port handle table entry. */
     225typedef IOMIOPORTENTRYR3 *PIOMIOPORTENTRYR3;
     226/** Pointer to a const ring-3 I/O port handle table entry. */
     227typedef IOMIOPORTENTRYR3 const *PCIOMIOPORTENTRYR3;
     228
     229/**
     230 * I/O port statistics entry (one I/O port).
     231 */
     232typedef struct IOMIOPORTSTATSENTRY
     233{
     234    /** Number of INs to this port from R3. */
     235    STAMCOUNTER                 InR3;
     236    /** Profiling IN handler overhead in R3. */
     237    STAMPROFILE                 ProfInR3;
     238    /** Number of OUTs to this port from R3. */
     239    STAMCOUNTER                 OutR3;
     240    /** Profiling OUT handler overhead in R3. */
     241    STAMPROFILE                 ProfOutR3;
     242
     243    /** Number of INs to this port from R0/RC. */
     244    STAMCOUNTER                 InRZ;
     245    /** Profiling IN handler overhead in R0/RC. */
     246    STAMPROFILE                 ProfInRZ;
     247    /** Number of INs to this port from R0/RC which was serviced in R3. */
     248    STAMCOUNTER                 InRZToR3;
     249
     250    /** Number of OUTs to this port from R0/RC. */
     251    STAMCOUNTER                 OutRZ;
     252    /** Profiling OUT handler overhead in R0/RC. */
     253    STAMPROFILE                 ProfOutRZ;
     254    /** Number of OUTs to this port from R0/RC which was serviced in R3. */
     255    STAMCOUNTER                 OutRZToR3;
     256} IOMIOPORTSTATSENTRY;
     257/** Pointer to I/O port statistics entry. */
     258typedef IOMIOPORTSTATSENTRY *PIOMIOPORTSTATSENTRY;
    141259
    142260
     
    281399/**
    282400 * The IOM trees.
     401 *
    283402 * These are offset based the nodes and root must be in the same
    284403 * memory block in HC. The locations of IOM structure and the hypervisor heap
     
    306425/** Pointer to the IOM trees. */
    307426typedef IOMTREES *PIOMTREES;
    308 
    309 
    310 /**
    311  * Converts an IOM pointer into a VM pointer.
    312  * @returns Pointer to the VM structure the PGM is part of.
    313  * @param   pIOM   Pointer to IOM instance data.
    314  */
    315 #define IOM2VM(pIOM)  ( (PVM)((char*)pIOM - pIOM->offVM) )
    316 
    317 /**
    318  * IOM Data (part of VM)
    319  */
    320 typedef struct IOM
    321 {
    322     /** Pointer to the trees - R3 ptr. */
    323     R3PTRTYPE(PIOMTREES)            pTreesR3;
    324     /** Pointer to the trees - R0 ptr. */
    325     R0PTRTYPE(PIOMTREES)            pTreesR0;
    326 
    327     /** MMIO physical access handler type.   */
    328     PGMPHYSHANDLERTYPE              hMmioHandlerType;
    329     uint32_t                        u32Padding;
    330 
    331     /** Lock serializing EMT access to IOM. */
    332 #ifdef IOM_WITH_CRIT_SECT_RW
    333     PDMCRITSECTRW                   CritSect;
    334 #else
    335     PDMCRITSECT                     CritSect;
    336 #endif
    337 
    338     /** @name I/O Port statistics.
    339      * @{ */
    340     STAMCOUNTER                     StatInstIn;
    341     STAMCOUNTER                     StatInstOut;
    342     STAMCOUNTER                     StatInstIns;
    343     STAMCOUNTER                     StatInstOuts;
    344     /** @} */
    345 
    346     /** @name MMIO statistics.
    347      * @{ */
    348     STAMPROFILE                     StatRZMMIOHandler;
    349     STAMCOUNTER                     StatRZMMIOFailures;
    350 
    351     STAMPROFILE                     StatRZInstMov;
    352     STAMPROFILE                     StatRZInstCmp;
    353     STAMPROFILE                     StatRZInstAnd;
    354     STAMPROFILE                     StatRZInstOr;
    355     STAMPROFILE                     StatRZInstXor;
    356     STAMPROFILE                     StatRZInstBt;
    357     STAMPROFILE                     StatRZInstTest;
    358     STAMPROFILE                     StatRZInstXchg;
    359     STAMPROFILE                     StatRZInstStos;
    360     STAMPROFILE                     StatRZInstLods;
    361 #ifdef IOM_WITH_MOVS_SUPPORT
    362     STAMPROFILEADV                  StatRZInstMovs;
    363     STAMPROFILE                     StatRZInstMovsToMMIO;
    364     STAMPROFILE                     StatRZInstMovsFromMMIO;
    365     STAMPROFILE                     StatRZInstMovsMMIO;
    366 #endif
    367     STAMCOUNTER                     StatRZInstOther;
    368 
    369     STAMCOUNTER                     StatRZMMIO1Byte;
    370     STAMCOUNTER                     StatRZMMIO2Bytes;
    371     STAMCOUNTER                     StatRZMMIO4Bytes;
    372     STAMCOUNTER                     StatRZMMIO8Bytes;
    373 
    374     STAMCOUNTER                     StatR3MMIOHandler;
    375 
    376     RTUINT                          cMovsMaxBytes;
    377     RTUINT                          cStosMaxBytes;
    378     /** @} */
    379 } IOM;
    380 /** Pointer to IOM instance data. */
    381 typedef IOM *PIOM;
    382427
    383428
     
    433478     * (Saves quite some time in rep outs/ins instruction emulation.)
    434479     * @{ */
     480    /** I/O port registration index for the last read operation. */
     481    uint16_t                            idxIoPortLastRead;
     482    /** I/O port registration index for the last write operation. */
     483    uint16_t                            idxIoPortLastWrite;
     484    /** I/O port registration index for the last read string operation. */
     485    uint16_t                            idxIoPortLastReadStr;
     486    /** I/O port registration index for the last write string operation. */
     487    uint16_t                            idxIoPortLastWriteStr;
     488    uint32_t                            u32Padding;
     489
    435490    R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastReadR3;
    436491    R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastWriteR3;
     
    450505/** Pointer to IOM per virtual CPU instance data. */
    451506typedef IOMCPU *PIOMCPU;
     507
     508
     509/**
     510 * IOM Data (part of VM)
     511 */
     512typedef struct IOM
     513{
     514    /** Pointer to the trees - R3 ptr. */
     515    R3PTRTYPE(PIOMTREES)            pTreesR3;
     516    /** Pointer to the trees - R0 ptr. */
     517    R0PTRTYPE(PIOMTREES)            pTreesR0;
     518
     519    /** MMIO physical access handler type.   */
     520    PGMPHYSHANDLERTYPE              hMmioHandlerType;
     521    uint32_t                        u32Padding;
     522
     523    /** @name I/O ports
     524     * @note The updating of these variables is done exclusively from EMT(0).
     525     * @{ */
     526    /** Number of I/O port registrations. */
     527    uint32_t                        cIoPortRegs;
     528    /** The size of the paIoPortsRegs allocation (in entries). */
     529    uint32_t                        cIoPortAlloc;
     530    /** I/O port registration table for ring-3.
     531     * There is a parallel table in ring-0, IOMR0PERVM::paIoPortRegs. */
     532    R3PTRTYPE(PIOMIOPORTENTRYR3)    paIoPortRegs;
     533    /** Number of entries in the lookup table. */
     534    uint32_t                        cIoPortLookupEntries;
     535    uint32_t                        u32Padding1;
     536    /** I/O port lookup table. */
     537    R3PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;
     538
     539    /** The number of valid entries in paioPortStats. */
     540    uint32_t                        cIoPortStats;
     541    /** The size of the paIoPortStats allocation (in entries). */
     542    uint32_t                        cIoPortStatsAllocation;
     543    /** I/O port lookup table.   */
     544    R3PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
     545    /** Dummy stats entry so we don't need to check for NULL pointers so much. */
     546    IOMIOPORTSTATSENTRY             IoPortDummyStats;
     547    /** @} */
     548
     549
     550    /** Lock serializing EMT access to IOM. */
     551#ifdef IOM_WITH_CRIT_SECT_RW
     552    PDMCRITSECTRW                   CritSect;
     553#else
     554    PDMCRITSECT                     CritSect;
     555#endif
     556
     557#if 0 /* unused */
     558    /** @name I/O Port statistics.
     559     * @{ */
     560    STAMCOUNTER                     StatInstIn;
     561    STAMCOUNTER                     StatInstOut;
     562    STAMCOUNTER                     StatInstIns;
     563    STAMCOUNTER                     StatInstOuts;
     564    /** @} */
     565#endif
     566
     567    /** @name MMIO statistics.
     568     * @{ */
     569    STAMPROFILE                     StatRZMMIOHandler;
     570    STAMCOUNTER                     StatRZMMIOFailures;
     571
     572    STAMPROFILE                     StatRZInstMov;
     573    STAMPROFILE                     StatRZInstCmp;
     574    STAMPROFILE                     StatRZInstAnd;
     575    STAMPROFILE                     StatRZInstOr;
     576    STAMPROFILE                     StatRZInstXor;
     577    STAMPROFILE                     StatRZInstBt;
     578    STAMPROFILE                     StatRZInstTest;
     579    STAMPROFILE                     StatRZInstXchg;
     580    STAMPROFILE                     StatRZInstStos;
     581    STAMPROFILE                     StatRZInstLods;
     582#ifdef IOM_WITH_MOVS_SUPPORT
     583    STAMPROFILEADV                  StatRZInstMovs;
     584    STAMPROFILE                     StatRZInstMovsToMMIO;
     585    STAMPROFILE                     StatRZInstMovsFromMMIO;
     586    STAMPROFILE                     StatRZInstMovsMMIO;
     587#endif
     588    STAMCOUNTER                     StatRZInstOther;
     589
     590    STAMCOUNTER                     StatRZMMIO1Byte;
     591    STAMCOUNTER                     StatRZMMIO2Bytes;
     592    STAMCOUNTER                     StatRZMMIO4Bytes;
     593    STAMCOUNTER                     StatRZMMIO8Bytes;
     594
     595    STAMCOUNTER                     StatR3MMIOHandler;
     596
     597    RTUINT                          cMovsMaxBytes;
     598    RTUINT                          cStosMaxBytes;
     599    /** @} */
     600} IOM;
     601/** Pointer to IOM instance data. */
     602typedef IOM *PIOM;
     603
     604
     605/**
     606 * IOM data kept in the ring-0 GVM.
     607 */
     608typedef struct IOMR0PERVM
     609{
     610    /** @name I/O ports
     611     * @{ */
     612    /** The higest ring-0 I/O port registration plus one. */
     613    uint32_t                        cIoPortMax;
     614    /** The size of the paIoPortsRegs allocation (in entries). */
     615    uint32_t                        cIoPortAlloc;
     616    /** I/O port registration table for ring-0.
     617     * There is a parallel table for ring-3, paIoPortRing3Regs. */
     618    R0PTRTYPE(PIOMIOPORTENTRYR0)    paIoPortRegs;
     619    /** I/O port lookup table. */
     620    R0PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup;
     621    /** I/O port registration table for ring-3.
     622     * Also mapped to ring-3 as IOM::paIoPortRegs. */
     623    R0PTRTYPE(PIOMIOPORTENTRYR3)    paIoPortRing3Regs;
     624    /** Handle to the allocation backing both the ring-0 and ring-3 registration
     625     * tables as well as the lookup table. */
     626    RTR0MEMOBJ                      hIoPortMemObj;
     627    /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */
     628    RTR0MEMOBJ                      hIoPortMapObj;
     629#ifdef VBOX_WITH_STATISTICS
     630    /** The size of the paIoPortStats allocation (in entries). */
     631    uint32_t                        cIoPortStatsAllocation;
     632    /** I/O port lookup table.   */
     633    R0PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats;
     634    /** Handle to the allocation backing the I/O port statistics. */
     635    RTR0MEMOBJ                      hIoPortStatsMemObj;
     636    /** Handle to the ring-3 mapping of the I/O port statistics. */
     637    RTR0MEMOBJ                      hIoPortStatsMapObj;
     638#endif
     639    /** @} */
     640} IOMR0PERVM;
    452641
    453642
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r80334 r80641  
    5151//# define NEM_WIN_USE_OUR_OWN_RUN_API          /**< Applies to ring-3 code only. Useful for testing VID API. */
    5252# define NEM_WIN_WITH_RING0_RUNLOOP             /**< Enables the ring-0 runloop. */
    53 # define NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT   /**< For quickly testing ring-3 API without messing with CFGM. */
     53//# define NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT   /**< For quickly testing ring-3 API without messing with CFGM. */
    5454# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    5555#  error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS"
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