VirtualBox

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


Ignore:
Timestamp:
Oct 4, 2008 9:20:46 PM (16 years ago)
Author:
vboxsync
Message:

Split up PDMDevice.cpp, moving all the devhlps into two new files named PDMDevHlp.cpp and PDMDevMiscHlp.cpp.

Location:
trunk/src/VBox/VMM
Files:
3 edited
2 copied

Legend:

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

    r12964 r12980  
    6969        PDM.cpp \
    7070        PDMDevice.cpp \
     71        PDMDevHlp.cpp \
     72        PDMDevMiscHlp.cpp \
    7173        PDMDriver.cpp \
    7274        PDMLdr.cpp \
  • trunk/src/VBox/VMM/PDMDevHlp.cpp

    r12979 r12980  
    11/* $Id$ */
    22/** @file
    3  * PDM - Pluggable Device and Driver Manager, Device parts.
     3 * PDM - Pluggable Device and Driver Manager, Device Helpers.
    44 */
    55
     
    3030#include <VBox/pgm.h>
    3131#include <VBox/iom.h>
    32 #include <VBox/cfgm.h>
    3332#include <VBox/rem.h>
    3433#include <VBox/dbgf.h>
     
    3938#include <VBox/log.h>
    4039#include <VBox/err.h>
    41 #include <iprt/alloc.h>
    42 #include <iprt/alloca.h>
    4340#include <iprt/asm.h>
    4441#include <iprt/assert.h>
    45 #include <iprt/path.h>
    46 #include <iprt/semaphore.h>
    4742#include <iprt/string.h>
    4843#include <iprt/thread.h>
     
    5045
    5146/*******************************************************************************
    52 *   Structures and Typedefs                                                    *
     47*   Defined Constants And Macros                                               *
    5348*******************************************************************************/
    54 /**
    55  * Internal callback structure pointer.
    56  * The main purpose is to define the extra data we associate
    57  * with PDMDEVREGCB so we can find the VM instance and so on.
    58  */
    59 typedef struct PDMDEVREGCBINT
    60 {
    61     /** The callback structure. */
    62     PDMDEVREGCB     Core;
    63     /** A bit of padding. */
    64     uint32_t        u32[4];
    65     /** VM Handle. */
    66     PVM             pVM;
    67 } PDMDEVREGCBINT, *PPDMDEVREGCBINT;
    68 typedef const PDMDEVREGCBINT *PCPDMDEVREGCBINT;
    69 
    70 
    71 /*******************************************************************************
    72 *   Internal Functions                                                         *
    73 *******************************************************************************/
    74 __BEGIN_DECLS
    75 static DECLCALLBACK(int)    pdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pDevReg);
    76 static DECLCALLBACK(void *) pdmR3DevReg_MMHeapAlloc(PPDMDEVREGCB pCallbacks, size_t cb);
    77 static DECLCALLBACK(bool)   pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem);
    78 
    79 /* VSlick regex:
    80 search : \om/\*\*.+?\*\/\nDECLCALLBACKMEMBER\(([^,]*), *pfn([^)]*)\)\(
    81 replace: \/\*\* @copydoc PDMDEVHLPR3::pfn\2 \*\/\nstatic DECLCALLBACK\(\1\) pdmR3DevHlp_\2\(
    82  */
    83 
    84 /** @name R3 DevHlp
    85  * @{
    86  */
    87 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn, PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc);
    88 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTRCPTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
    89 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
    90 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts);
    91 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
    92                                                      PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
    93                                                      const char *pszDesc);
    94 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
    95                                                        const char *pszWrite, const char *pszRead, const char *pszFill,
    96                                                        const char *pszDesc);
    97 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
    98                                                        const char *pszWrite, const char *pszRead, const char *pszFill,
    99                                                        const char *pszDesc);
    100 static DECLCALLBACK(int)    pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    101 static DECLCALLBACK(int)    pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc);
    102 static DECLCALLBACK(int)    pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
    103                                                     PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
    104                                                     PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone);
    105 static DECLCALLBACK(int)    pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer);
    106 static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc);
    107 static DECLCALLBACK(int)    pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev);
    108 static DECLCALLBACK(int)    pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback);
    109 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
    110                                                               PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld);
    111 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    112 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    113 static DECLCALLBACK(void)   pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    114 static DECLCALLBACK(void)   pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    115 static DECLCALLBACK(int)    pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc);
    116 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb);
    117 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb);
    118 static DECLCALLBACK(void)   pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv);
    119 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
    120 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va);
    121 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...);
    122 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va);
    123 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    124 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    125 static DECLCALLBACK(int)    pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args);
    126 static DECLCALLBACK(int)    pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler);
    127 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
    128 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...);
    129 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args);
    130 static DECLCALLBACK(int)    pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName);
    131 static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime);
    132 static DECLCALLBACK(int)    pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
    133                                                         PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
    134 
    135 static DECLCALLBACK(PVM)    pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns);
    136 static DECLCALLBACK(int)    pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
    137 static DECLCALLBACK(int)    pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
    138 static DECLCALLBACK(int)    pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
    139 static DECLCALLBACK(int)    pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
    140 static DECLCALLBACK(int)    pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
    141 static DECLCALLBACK(int)    pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp);
    142 static DECLCALLBACK(int)    pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue);
    143 static DECLCALLBACK(void)   pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
    144 static DECLCALLBACK(void)   pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
    145 static DECLCALLBACK(int)    pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
    146 static DECLCALLBACK(int)    pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
    147 static DECLCALLBACK(int)    pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
    148 static DECLCALLBACK(int)    pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys);
    149 static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns);
    150 static DECLCALLBACK(bool)   pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns);
    151 static DECLCALLBACK(void)   pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable);
    152 static DECLCALLBACK(int)    pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns);
    153 static DECLCALLBACK(int)    pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns);
    154 static DECLCALLBACK(int)    pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns);
    155 static DECLCALLBACK(int)    pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns);
    156 static DECLCALLBACK(int)    pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns);
    157 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    158 static DECLCALLBACK(int)    pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
    159 static DECLCALLBACK(int)    pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
    160 static DECLCALLBACK(int)    pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
    161 static DECLCALLBACK(int)    pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
    162 static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
    163 static DECLCALLBACK(void)   pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns);
    164 static DECLCALLBACK(int)    pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
    165 static DECLCALLBACK(int)    pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
    166 static DECLCALLBACK(void)   pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    167                                                uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
    168 static DECLCALLBACK(int)    pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    169 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc);
    170 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion);
    171 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    172 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    173 static DECLCALLBACK(int)    pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr);
    174 static DECLCALLBACK(int)    pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize);
    175 static DECLCALLBACK(int)    pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys);
    176 
    177 static DECLCALLBACK(PVM)    pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns);
    178 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
    179 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
    180 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
    181 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
    182 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
    183 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
    184 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
    185 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
    186 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
    187 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
    188 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC);
    189 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr);
    190 
    191 static DECLCALLBACK(bool)   pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns);
    192 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable);
    193 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns);
    194 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns);
    195 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns);
    196 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns);
    197 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns);
    198 static DECLCALLBACK(bool)   pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    199 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
    200 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
    201 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
    202 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
    203 static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
    204 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns);
    205 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
    206 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
    207 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    208                                                            uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
    209 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    210 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc);
    211 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion);
    212 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    213 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    214 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr);
    215 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize);
    216 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys);
    217 /** @} */
    218 
    219 
    220 /** @name HC PIC Helpers
    221  * @{
    222  */
    223 static DECLCALLBACK(void)   pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns);
    224 static DECLCALLBACK(void)   pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns);
    225 static DECLCALLBACK(int)    pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    226 static DECLCALLBACK(void)   pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns);
    227 static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    228 static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    229 /** @} */
    230 
    231 
    232 /** @name HC APIC Helpers
    233  * @{
    234  */
    235 static DECLCALLBACK(void)   pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu);
    236 static DECLCALLBACK(void)   pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu);
    237 static DECLCALLBACK(void)   pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion);
    238 static DECLCALLBACK(int)    pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    239 static DECLCALLBACK(void)   pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns);
    240 static DECLCALLBACK(VMCPUID) pdmR3ApicHlp_GetCpuId(PPDMDEVINS pDevIns);
    241 static DECLCALLBACK(PCPDMAPICHLPRC) pdmR3ApicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    242 static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    243 /** @} */
    244 
    245 
    246 /** @name HC I/O APIC Helpers
    247  * @{
    248  */
    249 static DECLCALLBACK(void)   pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
    250                                                           uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode);
    251 static DECLCALLBACK(int)    pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    252 static DECLCALLBACK(void)   pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns);
    253 static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    254 static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    255 /** @} */
    256 
    257 
    258 /** @name HC PCI Bus Helpers
    259  * @{
    260  */
    261 static DECLCALLBACK(void)   pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    262 static DECLCALLBACK(void)   pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    263 static DECLCALLBACK(bool)   pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys);
    264 static DECLCALLBACK(int)    pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc);
    265 static DECLCALLBACK(void)   pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns);
    266 static DECLCALLBACK(PCPDMPCIHLPRC) pdmR3PciHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    267 static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    268 /** @} */
    269 
    270 /** @def PDMDEV_ASSERT_DEVINS
    271  * Asserts the validity of the device instance.
    272  */
    273 #ifdef VBOX_STRICT
    274 # define PDMDEV_ASSERT_DEVINS(pDevIns)   \
    275     do { \
    276         AssertPtr(pDevIns); \
    277         Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); \
    278         Assert(pDevIns->pvInstanceDataR3 == (void *)&pDevIns->achInstanceData[0]); \
    279     } while (0)
    280 #else
    281 # define PDMDEV_ASSERT_DEVINS(pDevIns)   do { } while (0)
    282 #endif
    283 
    284 static int pdmR3DevLoadModules(PVM pVM);
    285 static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
    286 
    287 
    28849/*
    28950 * Allow physical read and writes from any thread
     
    29152#define PDM_PHYS_READWRITE_FROM_ANY_THREAD
    29253
    293 __END_DECLS
    294 
    295 /*******************************************************************************
    296 *   Global Variables                                                           *
    297 *******************************************************************************/
     54
     55/** @name R3 DevHlp
     56 * @{
     57 */
     58
     59
     60/** @copydoc PDMDEVHLPR3::pfnIOPortRegister */
     61static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
     62                                                    PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
     63{
     64    PDMDEV_ASSERT_DEVINS(pDevIns);
     65    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->pDevReg->szDeviceName, pDevIns->iInstance,
     66             Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
     67    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     68
     69    int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
     70
     71    LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     72    return rc;
     73}
     74
     75
     76/** @copydoc PDMDEVHLPR3::pfnIOPortRegisterGC */
     77static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTRCPTR pvUser,
     78                                                      const char *pszOut, const char *pszIn,
     79                                                      const char *pszOutStr, const char *pszInStr, const char *pszDesc)
     80{
     81    PDMDEV_ASSERT_DEVINS(pDevIns);
     82    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     83    LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
     84             Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
     85
     86    /*
     87     * Resolve the functions (one of the can be NULL).
     88     */
     89    int rc = VINF_SUCCESS;
     90    if (    pDevIns->pDevReg->szRCMod[0]
     91        &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
     92    {
     93        RTGCPTR32 GCPtrIn = 0;
     94        if (pszIn)
     95        {
     96            rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszIn, &GCPtrIn);
     97            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szRCMod, pszIn));
     98        }
     99        RTGCPTR32 GCPtrOut = 0;
     100        if (pszOut && VBOX_SUCCESS(rc))
     101        {
     102            rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOut, &GCPtrOut);
     103            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szRCMod, pszOut));
     104        }
     105        RTGCPTR32 GCPtrInStr = 0;
     106        if (pszInStr && VBOX_SUCCESS(rc))
     107        {
     108            rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszInStr, &GCPtrInStr);
     109            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szRCMod, pszInStr));
     110        }
     111        RTGCPTR32 GCPtrOutStr = 0;
     112        if (pszOutStr && VBOX_SUCCESS(rc))
     113        {
     114            rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOutStr, &GCPtrOutStr);
     115            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szRCMod, pszOutStr));
     116        }
     117
     118        if (VBOX_SUCCESS(rc))
     119            rc = IOMR3IOPortRegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc);
     120    }
     121    else
     122    {
     123        AssertMsgFailed(("No GC module for this driver!\n"));
     124        rc = VERR_INVALID_PARAMETER;
     125    }
     126
     127    LogFlow(("pdmR3DevHlp_IOPortRegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     128    return rc;
     129}
     130
     131
     132/** @copydoc PDMDEVHLPR3::pfnIOPortRegisterR0 */
     133static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser,
     134                                                      const char *pszOut, const char *pszIn,
     135                                                      const char *pszOutStr, const char *pszInStr, const char *pszDesc)
     136{
     137    PDMDEV_ASSERT_DEVINS(pDevIns);
     138    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     139    LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
     140             Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
     141
     142    /*
     143     * Resolve the functions (one of the can be NULL).
     144     */
     145    int rc = VINF_SUCCESS;
     146    if (    pDevIns->pDevReg->szR0Mod[0]
     147        &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
     148    {
     149        R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;
     150        if (pszIn)
     151        {
     152            rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszIn, &pfnR0PtrIn);
     153            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szR0Mod, pszIn));
     154        }
     155        R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;
     156        if (pszOut && VBOX_SUCCESS(rc))
     157        {
     158            rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOut, &pfnR0PtrOut);
     159            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szR0Mod, pszOut));
     160        }
     161        R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;
     162        if (pszInStr && VBOX_SUCCESS(rc))
     163        {
     164            rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszInStr, &pfnR0PtrInStr);
     165            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szR0Mod, pszInStr));
     166        }
     167        R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;
     168        if (pszOutStr && VBOX_SUCCESS(rc))
     169        {
     170            rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOutStr, &pfnR0PtrOutStr);
     171            AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szR0Mod, pszOutStr));
     172        }
     173
     174        if (VBOX_SUCCESS(rc))
     175            rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
     176    }
     177    else
     178    {
     179        AssertMsgFailed(("No R0 module for this driver!\n"));
     180        rc = VERR_INVALID_PARAMETER;
     181    }
     182
     183    LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     184    return rc;
     185}
     186
     187
     188/** @copydoc PDMDEVHLPR3::pfnIOPortDeregister */
     189static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts)
     190{
     191    PDMDEV_ASSERT_DEVINS(pDevIns);
     192    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     193    LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
     194             Port, cPorts));
     195
     196    int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts);
     197
     198    LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     199    return rc;
     200}
     201
     202
     203/** @copydoc PDMDEVHLPR3::pfnMMIORegister */
     204static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
     205                                                  PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
     206                                                  const char *pszDesc)
     207{
     208    PDMDEV_ASSERT_DEVINS(pDevIns);
     209    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     210    LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p pszDesc=%p:{%s}\n",
     211             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc, pszDesc));
     212
     213    int rc = IOMR3MMIORegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc);
     214
     215    LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     216    return rc;
     217}
     218
     219
     220/** @copydoc PDMDEVHLPR3::pfnMMIORegisterGC */
     221static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
     222                                                    const char *pszWrite, const char *pszRead, const char *pszFill,
     223                                                    const char *pszDesc)
     224{
     225    PDMDEV_ASSERT_DEVINS(pDevIns);
     226    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     227    LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
     228             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
     229
     230    /*
     231     * Resolve the functions.
     232     * Not all function have to present, leave it to IOM to enforce this.
     233     */
     234    int rc = VINF_SUCCESS;
     235    if (    pDevIns->pDevReg->szRCMod[0]
     236        &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
     237    {
     238        RTGCPTR32 GCPtrWrite = 0;
     239        if (pszWrite)
     240            rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszWrite, &GCPtrWrite);
     241        RTGCPTR32 GCPtrRead = 0;
     242        int rc2 = VINF_SUCCESS;
     243        if (pszRead)
     244            rc2 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszRead, &GCPtrRead);
     245        RTGCPTR32 GCPtrFill = 0;
     246        int rc3 = VINF_SUCCESS;
     247        if (pszFill)
     248            rc3 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszFill, &GCPtrFill);
     249        if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
     250            rc = IOMR3MMIORegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill);
     251        else
     252        {
     253            AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szRCMod, pszWrite));
     254            AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szRCMod, pszRead));
     255            AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szRCMod, pszFill));
     256            if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
     257                rc = rc2;
     258            if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
     259                rc = rc3;
     260        }
     261    }
     262    else
     263    {
     264        AssertMsgFailed(("No GC module for this driver!\n"));
     265        rc = VERR_INVALID_PARAMETER;
     266    }
     267
     268    LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     269    return rc;
     270}
     271
     272/** @copydoc PDMDEVHLPR3::pfnMMIORegisterR0 */
     273static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
     274                                                    const char *pszWrite, const char *pszRead, const char *pszFill,
     275                                                    const char *pszDesc)
     276{
     277    PDMDEV_ASSERT_DEVINS(pDevIns);
     278    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     279    LogFlow(("pdmR3DevHlp_MMIORegisterHC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
     280             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
     281
     282    /*
     283     * Resolve the functions.
     284     * Not all function have to present, leave it to IOM to enforce this.
     285     */
     286    int rc = VINF_SUCCESS;
     287    if (    pDevIns->pDevReg->szR0Mod[0]
     288        &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
     289    {
     290        R0PTRTYPE(PFNIOMMMIOWRITE) pfnR0PtrWrite = 0;
     291        if (pszWrite)
     292            rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszWrite, &pfnR0PtrWrite);
     293        R0PTRTYPE(PFNIOMMMIOREAD) pfnR0PtrRead = 0;
     294        int rc2 = VINF_SUCCESS;
     295        if (pszRead)
     296            rc2 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszRead, &pfnR0PtrRead);
     297        R0PTRTYPE(PFNIOMMMIOFILL) pfnR0PtrFill = 0;
     298        int rc3 = VINF_SUCCESS;
     299        if (pszFill)
     300            rc3 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill);
     301        if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
     302            rc = IOMR3MMIORegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill);
     303        else
     304        {
     305            AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szR0Mod, pszWrite));
     306            AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szR0Mod, pszRead));
     307            AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szR0Mod, pszFill));
     308            if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
     309                rc = rc2;
     310            if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
     311                rc = rc3;
     312        }
     313    }
     314    else
     315    {
     316        AssertMsgFailed(("No R0 module for this driver!\n"));
     317        rc = VERR_INVALID_PARAMETER;
     318    }
     319
     320    LogFlow(("pdmR3DevHlp_MMIORegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     321    return rc;
     322}
     323
     324
     325/** @copydoc PDMDEVHLPR3::pfnMMIODeregister */
     326static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
     327{
     328    PDMDEV_ASSERT_DEVINS(pDevIns);
     329    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     330    LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
     331             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
     332
     333    int rc = IOMR3MMIODeregister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange);
     334
     335    LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     336    return rc;
     337}
     338
     339
     340/** @copydoc PDMDEVHLPR3::pfnROMRegister */
     341static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc)
     342{
     343    PDMDEV_ASSERT_DEVINS(pDevIns);
     344    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     345    LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvBinary=%p fShadow=%RTbool pszDesc=%p:{%s}\n",
     346             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc, pszDesc));
     347
     348    int rc = MMR3PhysRomRegister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc);
     349
     350    LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     351    return rc;
     352}
     353
     354
     355/** @copydoc PDMDEVHLPR3::pfnSSMRegister */
     356static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
     357                                                 PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
     358                                                 PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
     359{
     360    PDMDEV_ASSERT_DEVINS(pDevIns);
     361    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     362    LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: pszName=%p:{%s} u32Instance=%#x u32Version=#x cbGuess=%#x pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoaddone=%p\n",
     363             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
     364
     365    int rc = SSMR3Register(pDevIns->Internal.s.pVMR3, pDevIns, pszName, u32Instance, u32Version, cbGuess,
     366                           pfnSavePrep, pfnSaveExec, pfnSaveDone,
     367                           pfnLoadPrep, pfnLoadExec, pfnLoadDone);
     368
     369    LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     370    return rc;
     371}
     372
     373
     374/** @copydoc PDMDEVHLPR3::pfnTMTimerCreate */
     375static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
     376{
     377    PDMDEV_ASSERT_DEVINS(pDevIns);
     378    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     379    LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
     380             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
     381
     382    int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
     383
     384    LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     385    return rc;
     386}
     387
     388
     389/** @copydoc PDMDEVHLPR3::pfnTMTimerCreateExternal */
     390static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc)
     391{
     392    PDMDEV_ASSERT_DEVINS(pDevIns);
     393    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     394
     395    return TMR3TimerCreateExternal(pDevIns->Internal.s.pVMR3, enmClock, pfnCallback, pvUser, pszDesc);
     396}
     397
     398/** @copydoc PDMDEVHLPR3::pfnPCIRegister */
     399static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev)
     400{
     401    PDMDEV_ASSERT_DEVINS(pDevIns);
     402    PVM pVM = pDevIns->Internal.s.pVMR3;
     403    VM_ASSERT_EMT(pVM);
     404    LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Vhxs}\n",
     405             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pPciDev->config));
     406
     407    /*
     408     * Validate input.
     409     */
     410    if (!pPciDev)
     411    {
     412        Assert(pPciDev);
     413        LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (pPciDev)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     414        return VERR_INVALID_PARAMETER;
     415    }
     416    if (!pPciDev->config[0] && !pPciDev->config[1])
     417    {
     418        Assert(pPciDev->config[0] || pPciDev->config[1]);
     419        LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (vendor)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     420        return VERR_INVALID_PARAMETER;
     421    }
     422    if (pDevIns->Internal.s.pPciDeviceR3)
     423    {
     424        /** @todo the PCI device vs. PDM device designed is a bit flawed if we have to
     425         * support a PDM device with multiple PCI devices. This might become a problem
     426         * when upgrading the chipset for instance...
     427         */
     428        AssertMsgFailed(("Only one PCI device per device is currently implemented!\n"));
     429        return VERR_INTERNAL_ERROR;
     430    }
     431
     432    /*
     433     * Choose the PCI bus for the device.
     434     * This is simple. If the device was configured for a particular bus, it'll
     435     * already have one. If not, we'll just take the first one.
     436     */
     437    PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
     438    if (!pBus)
     439        pBus = pDevIns->Internal.s.pPciBusR3 = &pVM->pdm.s.aPciBuses[0];
     440    int rc;
     441    if (pBus)
     442    {
     443        if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
     444            pDevIns->Internal.s.pPciBusR0 = MMHyperR3ToR0(pVM, pDevIns->Internal.s.pPciBusR3);
     445        else
     446            pDevIns->Internal.s.pPciBusR0 = NIL_RTR0PTR;
     447
     448        if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
     449            pDevIns->Internal.s.pPciBusRC = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciBusR3);
     450        else
     451            pDevIns->Internal.s.pPciBusRC = NIL_RTRCPTR;
     452
     453        /*
     454         * Check the configuration for PCI device and function assignment.
     455         */
     456        int iDev = -1;
     457        uint8_t     u8Device;
     458        rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIDeviceNo", &u8Device);
     459        if (VBOX_SUCCESS(rc))
     460        {
     461            if (u8Device > 31)
     462            {
     463                AssertMsgFailed(("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d)\n",
     464                                 u8Device, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     465                return VERR_INTERNAL_ERROR;
     466            }
     467
     468            uint8_t     u8Function;
     469            rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIFunctionNo", &u8Function);
     470            if (VBOX_FAILURE(rc))
     471            {
     472                AssertMsgFailed(("Configuration error: PCIDeviceNo, but PCIFunctionNo query failed with rc=%Vrc (%s/%d)\n",
     473                                 rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     474                return rc;
     475            }
     476            if (u8Function > 7)
     477            {
     478                AssertMsgFailed(("Configuration error: PCIFunctionNo=%d, max is 7. (%s/%d)\n",
     479                                 u8Function, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     480                return VERR_INTERNAL_ERROR;
     481            }
     482            iDev = (u8Device << 3) | u8Function;
     483        }
     484        else if (rc != VERR_CFGM_VALUE_NOT_FOUND)
     485        {
     486            AssertMsgFailed(("Configuration error: PCIDeviceNo query failed with rc=%Vrc (%s/%d)\n",
     487                             rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     488            return rc;
     489        }
     490
     491        /*
     492         * Call the pci bus device to do the actual registration.
     493         */
     494        pdmLock(pVM);
     495        rc = pBus->pfnRegisterR3(pBus->pDevInsR3, pPciDev, pDevIns->pDevReg->szDeviceName, iDev);
     496        pdmUnlock(pVM);
     497        if (VBOX_SUCCESS(rc))
     498        {
     499            pPciDev->pDevIns = pDevIns;
     500
     501            pDevIns->Internal.s.pPciDeviceR3 = pPciDev;
     502            if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0)
     503                pDevIns->Internal.s.pPciDeviceR0 = MMHyperR3ToR0(pVM, pPciDev);
     504            else
     505                pDevIns->Internal.s.pPciDeviceR0 = NIL_RTR0PTR;
     506
     507            if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
     508                pDevIns->Internal.s.pPciDeviceRC = MMHyperR3ToRC(pVM, pPciDev);
     509            else
     510                pDevIns->Internal.s.pPciDeviceRC = NIL_RTRCPTR;
     511
     512            Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
     513                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev->devfn, pDevIns->Internal.s.pPciBusR3->iBus));
     514        }
     515    }
     516    else
     517    {
     518        AssertMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
     519        rc = VERR_PDM_NO_PCI_BUS;
     520    }
     521
     522    LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     523    return rc;
     524}
     525
     526
     527/** @copydoc PDMDEVHLPR3::pfnPCIIORegionRegister */
     528static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
     529{
     530    PDMDEV_ASSERT_DEVINS(pDevIns);
     531    PVM pVM = pDevIns->Internal.s.pVMR3;
     532    VM_ASSERT_EMT(pVM);
     533    LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: iRegion=%d cbRegion=%#x enmType=%d pfnCallback=%p\n",
     534             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cbRegion, enmType, pfnCallback));
     535
     536    /*
     537     * Validate input.
     538     */
     539    if (iRegion < 0 || iRegion >= PCI_NUM_REGIONS)
     540    {
     541        Assert(iRegion >= 0 && iRegion < PCI_NUM_REGIONS);
     542        LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (iRegion)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     543        return VERR_INVALID_PARAMETER;
     544    }
     545    switch (enmType)
     546    {
     547        case PCI_ADDRESS_SPACE_MEM:
     548        case PCI_ADDRESS_SPACE_IO:
     549        case PCI_ADDRESS_SPACE_MEM_PREFETCH:
     550            break;
     551        default:
     552            AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
     553            LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (enmType)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     554            return VERR_INVALID_PARAMETER;
     555    }
     556    if (!pfnCallback)
     557    {
     558        Assert(pfnCallback);
     559        LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (callback)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     560        return VERR_INVALID_PARAMETER;
     561    }
     562    AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
     563
     564    /*
     565     * Must have a PCI device registered!
     566     */
     567    int rc;
     568    PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
     569    if (pPciDev)
     570    {
     571        /*
     572         * We're currently restricted to page aligned MMIO regions.
     573         */
     574        if (    (enmType == PCI_ADDRESS_SPACE_MEM || enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH)
     575            &&  cbRegion != RT_ALIGN_32(cbRegion, PAGE_SIZE))
     576        {
     577            Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %#x -> %#x\n",
     578                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbRegion, RT_ALIGN_32(cbRegion, PAGE_SIZE)));
     579            cbRegion = RT_ALIGN_32(cbRegion, PAGE_SIZE);
     580        }
     581
     582        PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
     583        Assert(pBus);
     584        pdmLock(pVM);
     585        rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
     586        pdmUnlock(pVM);
     587    }
     588    else
     589    {
     590        AssertMsgFailed(("No PCI device registered!\n"));
     591        rc = VERR_PDM_NOT_PCI_DEVICE;
     592    }
     593
     594    LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     595    return rc;
     596}
     597
     598
     599/** @copydoc PDMDEVHLPR3::pfnPCISetConfigCallbacks */
     600static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
     601                                                            PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
     602{
     603    PDMDEV_ASSERT_DEVINS(pDevIns);
     604    PVM pVM = pDevIns->Internal.s.pVMR3;
     605    VM_ASSERT_EMT(pVM);
     606    LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
     607             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
     608
     609    /*
     610     * Validate input and resolve defaults.
     611     */
     612    AssertPtr(pfnRead);
     613    AssertPtr(pfnWrite);
     614    AssertPtrNull(ppfnReadOld);
     615    AssertPtrNull(ppfnWriteOld);
     616    AssertPtrNull(pPciDev);
     617
     618    if (!pPciDev)
     619        pPciDev = pDevIns->Internal.s.pPciDeviceR3;
     620    AssertReleaseMsg(pPciDev, ("You must register your device first!\n"));
     621    PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
     622    AssertRelease(pBus);
     623    AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
     624
     625    /*
     626     * Do the job.
     627     */
     628    pdmLock(pVM);
     629    pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
     630    pdmUnlock(pVM);
     631
     632    LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     633}
     634
     635
     636/** @copydoc PDMDEVHLPR3::pfnPCISetIrq */
     637static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
     638{
     639    PDMDEV_ASSERT_DEVINS(pDevIns);
     640    LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
     641
     642    /*
     643     * Validate input.
     644     */
     645    /** @todo iIrq and iLevel checks. */
     646
     647    /*
     648     * Must have a PCI device registered!
     649     */
     650    PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
     651    if (pPciDev)
     652    {
     653        PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3; /** @todo the bus should be associated with the PCI device not the PDM device. */
     654        Assert(pBus);
     655        PVM pVM = pDevIns->Internal.s.pVMR3;
     656        pdmLock(pVM);
     657        pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
     658        pdmUnlock(pVM);
     659    }
     660    else
     661        AssertReleaseMsgFailed(("No PCI device registered!\n"));
     662
     663    LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     664}
     665
     666
     667/** @copydoc PDMDEVHLPR3::pfnPCISetIrqNoWait */
     668static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
     669{
     670    pdmR3DevHlp_PCISetIrq(pDevIns, iIrq, iLevel);
     671}
     672
     673
     674/** @copydoc PDMDEVHLPR3::pfnISASetIrq */
     675static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
     676{
     677    PDMDEV_ASSERT_DEVINS(pDevIns);
     678    LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
     679
     680    /*
     681     * Validate input.
     682     */
     683    /** @todo iIrq and iLevel checks. */
     684
     685    PVM pVM = pDevIns->Internal.s.pVMR3;
     686    PDMIsaSetIrq(pVM, iIrq, iLevel);    /* (The API takes the lock.) */
     687
     688    LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     689}
     690
     691
     692/** @copydoc PDMDEVHLPR3::pfnISASetIrqNoWait */
     693static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
     694{
     695    pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
     696}
     697
     698
     699/** @copydoc PDMDEVHLPR3::pfnDriverAttach */
     700static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
     701{
     702    PDMDEV_ASSERT_DEVINS(pDevIns);
     703    PVM pVM = pDevIns->Internal.s.pVMR3;
     704    VM_ASSERT_EMT(pVM);
     705    LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
     706             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
     707
     708    /*
     709     * Lookup the LUN, it might already be registered.
     710     */
     711    PPDMLUN pLunPrev = NULL;
     712    PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
     713    for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
     714        if (pLun->iLun == iLun)
     715            break;
     716
     717    /*
     718     * Create the LUN if if wasn't found, else check if driver is already attached to it.
     719     */
     720    if (!pLun)
     721    {
     722        if (    !pBaseInterface
     723            ||  !pszDesc
     724            ||  !*pszDesc)
     725        {
     726            Assert(pBaseInterface);
     727            Assert(pszDesc || *pszDesc);
     728            return VERR_INVALID_PARAMETER;
     729        }
     730
     731        pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
     732        if (!pLun)
     733            return VERR_NO_MEMORY;
     734
     735        pLun->iLun      = iLun;
     736        pLun->pNext     = pLunPrev ? pLunPrev->pNext : NULL;
     737        pLun->pTop      = NULL;
     738        pLun->pBottom   = NULL;
     739        pLun->pDevIns   = pDevIns;
     740        pLun->pszDesc   = pszDesc;
     741        pLun->pBase     = pBaseInterface;
     742        if (!pLunPrev)
     743            pDevIns->Internal.s.pLunsR3 = pLun;
     744        else
     745            pLunPrev->pNext = pLun;
     746        Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
     747             iLun, pszDesc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     748    }
     749    else if (pLun->pTop)
     750    {
     751        AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
     752        LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
     753        return VERR_PDM_DRIVER_ALREADY_ATTACHED;
     754    }
     755    Assert(pLun->pBase == pBaseInterface);
     756
     757
     758    /*
     759     * Get the attached driver configuration.
     760     */
     761    int rc;
     762    char szNode[48];
     763    RTStrPrintf(szNode, sizeof(szNode), "LUN#%d", iLun);
     764    PCFGMNODE   pNode = CFGMR3GetChild(pDevIns->Internal.s.pCfgHandle, szNode);
     765    if (pNode)
     766    {
     767        char *pszName;
     768        rc = CFGMR3QueryStringAlloc(pNode, "Driver", &pszName);
     769        if (VBOX_SUCCESS(rc))
     770        {
     771            /*
     772             * Find the driver.
     773             */
     774            PPDMDRV pDrv = pdmR3DrvLookup(pVM, pszName);
     775            if (pDrv)
     776            {
     777                /* config node */
     778                PCFGMNODE pConfigNode = CFGMR3GetChild(pNode, "Config");
     779                if (!pConfigNode)
     780                    rc = CFGMR3InsertNode(pNode, "Config", &pConfigNode);
     781                if (VBOX_SUCCESS(rc))
     782                {
     783                    CFGMR3SetRestrictedRoot(pConfigNode);
     784
     785                    /*
     786                     * Allocate the driver instance.
     787                     */
     788                    size_t cb = RT_OFFSETOF(PDMDRVINS, achInstanceData[pDrv->pDrvReg->cbInstance]);
     789                    cb = RT_ALIGN_Z(cb, 16);
     790                    PPDMDRVINS pNew = (PPDMDRVINS)MMR3HeapAllocZ(pVM, MM_TAG_PDM_DRIVER, cb);
     791                    if (pNew)
     792                    {
     793                        /*
     794                         * Initialize the instance structure (declaration order).
     795                         */
     796                        pNew->u32Version                = PDM_DRVINS_VERSION;
     797                        //pNew->Internal.s.pUp            = NULL;
     798                        //pNew->Internal.s.pDown          = NULL;
     799                        pNew->Internal.s.pLun           = pLun;
     800                        pNew->Internal.s.pDrv           = pDrv;
     801                        pNew->Internal.s.pVM            = pVM;
     802                        //pNew->Internal.s.fDetaching     = false;
     803                        pNew->Internal.s.pCfgHandle     = pNode;
     804                        pNew->pDrvHlp                   = &g_pdmR3DrvHlp;
     805                        pNew->pDrvReg                   = pDrv->pDrvReg;
     806                        pNew->pCfgHandle                = pConfigNode;
     807                        pNew->iInstance                 = pDrv->cInstances++;
     808                        pNew->pUpBase                   = pBaseInterface;
     809                        //pNew->pDownBase                 = NULL;
     810                        //pNew->IBase.pfnQueryInterface   = NULL;
     811                        pNew->pvInstanceData            = &pNew->achInstanceData[0];
     812
     813                        /*
     814                         * Link with LUN and call the constructor.
     815                         */
     816                        pLun->pTop = pLun->pBottom = pNew;
     817                        rc = pDrv->pDrvReg->pfnConstruct(pNew, pNew->pCfgHandle);
     818                        if (VBOX_SUCCESS(rc))
     819                        {
     820                            MMR3HeapFree(pszName);
     821                            *ppBaseInterface = &pNew->IBase;
     822                            Log(("PDM: Attached driver '%s'/%d to LUN#%d on device '%s'/%d.\n",
     823                                 pDrv->pDrvReg->szDriverName, pNew->iInstance, iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     824                            LogFlow(("pdmR3DevHlp_DriverAttach: caller '%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
     825                            /*
     826                             * Might return != VINF_SUCCESS (e.g. VINF_NAT_DNS) */
     827                            return rc;
     828                        }
     829
     830                        /*
     831                         * Free the driver.
     832                         */
     833                        pLun->pTop = pLun->pBottom = NULL;
     834                        ASMMemFill32(pNew, cb, 0xdeadd0d0);
     835                        MMR3HeapFree(pNew);
     836                        pDrv->cInstances--;
     837                    }
     838                    else
     839                    {
     840                        AssertMsgFailed(("Failed to allocate %d bytes for instantiating driver '%s'\n", cb, pszName));
     841                        rc = VERR_NO_MEMORY;
     842                    }
     843                }
     844                else
     845                    AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
     846            }
     847            else
     848            {
     849                AssertMsgFailed(("Driver '%s' wasn't found!\n", pszName));
     850                rc = VERR_PDM_DRIVER_NOT_FOUND;
     851            }
     852            MMR3HeapFree(pszName);
     853        }
     854        else
     855        {
     856            AssertMsgFailed(("Query for string value of \"Driver\" -> %Vrc\n", rc));
     857            if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     858                rc = VERR_PDM_CFG_MISSING_DRIVER_NAME;
     859        }
     860    }
     861    else
     862        rc = VERR_PDM_NO_ATTACHED_DRIVER;
     863
     864
     865    LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     866    return rc;
     867}
     868
     869
     870/** @copydoc PDMDEVHLPR3::pfnMMHeapAlloc */
     871static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
     872{
     873    PDMDEV_ASSERT_DEVINS(pDevIns);
     874    LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
     875
     876    void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
     877
     878    LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
     879    return pv;
     880}
     881
     882
     883/** @copydoc PDMDEVHLPR3::pfnMMHeapAllocZ */
     884static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
     885{
     886    PDMDEV_ASSERT_DEVINS(pDevIns);
     887    LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
     888
     889    void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
     890
     891    LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
     892    return pv;
     893}
     894
     895
     896/** @copydoc PDMDEVHLPR3::pfnMMHeapFree */
     897static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
     898{
     899    PDMDEV_ASSERT_DEVINS(pDevIns);
     900    LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
     901
     902    MMR3HeapFree(pv);
     903
     904    LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     905}
     906
     907
     908/** @copydoc PDMDEVHLPR3::pfnVMSetError */
     909static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
     910{
     911    PDMDEV_ASSERT_DEVINS(pDevIns);
     912    va_list args;
     913    va_start(args, pszFormat);
     914    int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
     915    va_end(args);
     916    return rc;
     917}
     918
     919
     920/** @copydoc PDMDEVHLPR3::pfnVMSetErrorV */
     921static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
     922{
     923    PDMDEV_ASSERT_DEVINS(pDevIns);
     924    int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
     925    return rc;
     926}
     927
     928
     929/** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeError */
     930static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...)
     931{
     932    PDMDEV_ASSERT_DEVINS(pDevIns);
     933    va_list args;
     934    va_start(args, pszFormat);
     935    int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, args);
     936    va_end(args);
     937    return rc;
     938}
     939
     940
     941/** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeErrorV */
     942static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va)
     943{
     944    PDMDEV_ASSERT_DEVINS(pDevIns);
     945    int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, va);
     946    return rc;
     947}
     948
     949
     950/** @copydoc PDMDEVHLPR3::pfnAssertEMT */
     951static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
     952{
     953    PDMDEV_ASSERT_DEVINS(pDevIns);
     954    if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
     955        return true;
     956
     957    char szMsg[100];
     958    RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
     959    AssertMsg1(szMsg, iLine, pszFile, pszFunction);
     960    AssertBreakpoint();
     961    return false;
     962}
     963
     964
     965/** @copydoc PDMDEVHLPR3::pfnAssertOther */
     966static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
     967{
     968    PDMDEV_ASSERT_DEVINS(pDevIns);
     969    if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
     970        return true;
     971
     972    char szMsg[100];
     973    RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
     974    AssertMsg1(szMsg, iLine, pszFile, pszFunction);
     975    AssertBreakpoint();
     976    return false;
     977}
     978
     979
     980/** @copydoc PDMDEVHLPR3::pfnDBGFStopV */
     981static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
     982{
     983    PDMDEV_ASSERT_DEVINS(pDevIns);
     984#ifdef LOG_ENABLED
     985    va_list va2;
     986    va_copy(va2, args);
     987    LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
     988             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
     989    va_end(va2);
     990#endif
     991
     992    PVM pVM = pDevIns->Internal.s.pVMR3;
     993    VM_ASSERT_EMT(pVM);
     994    int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
     995
     996    LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     997    return rc;
     998}
     999
     1000
     1001/** @copydoc PDMDEVHLPR3::pfnDBGFInfoRegister */
     1002static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
     1003{
     1004    PDMDEV_ASSERT_DEVINS(pDevIns);
     1005    LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
     1006             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
     1007
     1008    PVM pVM = pDevIns->Internal.s.pVMR3;
     1009    VM_ASSERT_EMT(pVM);
     1010    int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
     1011
     1012    LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1013    return rc;
     1014}
     1015
     1016
     1017/** @copydoc PDMDEVHLPR3::pfnSTAMRegister */
     1018static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
     1019{
     1020    PDMDEV_ASSERT_DEVINS(pDevIns);
     1021    PVM pVM = pDevIns->Internal.s.pVMR3;
     1022    VM_ASSERT_EMT(pVM);
     1023
     1024    STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
     1025    NOREF(pVM);
     1026}
     1027
     1028
     1029
     1030/** @copydoc PDMDEVHLPR3::pfnSTAMRegisterF */
     1031static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
     1032                                                    STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
     1033{
     1034    PDMDEV_ASSERT_DEVINS(pDevIns);
     1035    PVM pVM = pDevIns->Internal.s.pVMR3;
     1036    VM_ASSERT_EMT(pVM);
     1037
     1038    va_list args;
     1039    va_start(args, pszName);
     1040    int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
     1041    va_end(args);
     1042    AssertRC(rc);
     1043
     1044    NOREF(pVM);
     1045}
     1046
     1047
     1048/** @copydoc PDMDEVHLPR3::pfnSTAMRegisterV */
     1049static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
     1050                                                    STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
     1051{
     1052    PDMDEV_ASSERT_DEVINS(pDevIns);
     1053    PVM pVM = pDevIns->Internal.s.pVMR3;
     1054    VM_ASSERT_EMT(pVM);
     1055
     1056    int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
     1057    AssertRC(rc);
     1058
     1059    NOREF(pVM);
     1060}
     1061
     1062
     1063/** @copydoc PDMDEVHLPR3::pfnRTCRegister */
     1064static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
     1065{
     1066    PDMDEV_ASSERT_DEVINS(pDevIns);
     1067    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     1068    LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
     1069             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
     1070             pRtcReg->pfnWrite, ppRtcHlp));
     1071
     1072    /*
     1073     * Validate input.
     1074     */
     1075    if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
     1076    {
     1077        AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
     1078                         PDM_RTCREG_VERSION));
     1079        LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (version)\n",
     1080                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1081        return VERR_INVALID_PARAMETER;
     1082    }
     1083    if (    !pRtcReg->pfnWrite
     1084        ||  !pRtcReg->pfnRead)
     1085    {
     1086        Assert(pRtcReg->pfnWrite);
     1087        Assert(pRtcReg->pfnRead);
     1088        LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
     1089                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1090        return VERR_INVALID_PARAMETER;
     1091    }
     1092
     1093    if (!ppRtcHlp)
     1094    {
     1095        Assert(ppRtcHlp);
     1096        LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (ppRtcHlp)\n",
     1097                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1098        return VERR_INVALID_PARAMETER;
     1099    }
     1100
     1101    /*
     1102     * Only one DMA device.
     1103     */
     1104    PVM pVM = pDevIns->Internal.s.pVMR3;
     1105    if (pVM->pdm.s.pRtc)
     1106    {
     1107        AssertMsgFailed(("Only one RTC device is supported!\n"));
     1108        LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
     1109                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1110        return VERR_INVALID_PARAMETER;
     1111    }
     1112
     1113    /*
     1114     * Allocate and initialize pci bus structure.
     1115     */
     1116    int rc = VINF_SUCCESS;
     1117    PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
     1118    if (pRtc)
     1119    {
     1120        pRtc->pDevIns   = pDevIns;
     1121        pRtc->Reg       = *pRtcReg;
     1122        pVM->pdm.s.pRtc = pRtc;
     1123
     1124        /* set the helper pointer. */
     1125        *ppRtcHlp = &g_pdmR3DevRtcHlp;
     1126        Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
     1127             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
     1128    }
     1129    else
     1130        rc = VERR_NO_MEMORY;
     1131
     1132    LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
     1133             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1134    return rc;
     1135}
     1136
     1137
     1138/** @copydoc PDMDEVHLPR3::pfnPDMQueueCreate */
     1139static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
     1140                                                    PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue)
     1141{
     1142    PDMDEV_ASSERT_DEVINS(pDevIns);
     1143    LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool ppQueue=%p\n",
     1144             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue));
     1145
     1146    PVM pVM = pDevIns->Internal.s.pVMR3;
     1147    VM_ASSERT_EMT(pVM);
     1148    int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue);
     1149
     1150    LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppQueue));
     1151    return rc;
     1152}
     1153
     1154
     1155/** @copydoc PDMDEVHLPR3::pfnCritSectInit */
     1156static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName)
     1157{
     1158    PDMDEV_ASSERT_DEVINS(pDevIns);
     1159    LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%p:{%s}\n",
     1160             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pCritSect, pszName, pszName));
     1161
     1162    PVM pVM = pDevIns->Internal.s.pVMR3;
     1163    VM_ASSERT_EMT(pVM);
     1164    int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, pszName);
     1165
     1166    LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1167    return rc;
     1168}
     1169
     1170
     1171/** @copydoc PDMDEVHLPR3::pfnUTCNow */
     1172static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
     1173{
     1174    PDMDEV_ASSERT_DEVINS(pDevIns);
     1175    LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: pTime=%p\n",
     1176             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pTime));
     1177
     1178    pTime = TMR3UTCNow(pDevIns->Internal.s.pVMR3, pTime);
     1179
     1180    LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: returns %RU64\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
     1181    return pTime;
     1182}
     1183
     1184
     1185/** @copydoc PDMDEVHLPR3::pfnPDMThreadCreate */
     1186static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
     1187                                                     PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
     1188{
     1189    PDMDEV_ASSERT_DEVINS(pDevIns);
     1190    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     1191    LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
     1192             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
     1193
     1194    int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
     1195
     1196    LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
     1197            rc, *ppThread));
     1198    return rc;
     1199}
     1200
     1201
     1202/** @copydoc PDMDEVHLPR3::pfnGetVM */
     1203static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
     1204{
     1205    PDMDEV_ASSERT_DEVINS(pDevIns);
     1206    LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
     1207    return pDevIns->Internal.s.pVMR3;
     1208}
     1209
     1210
     1211/** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
     1212static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
     1213{
     1214    PDMDEV_ASSERT_DEVINS(pDevIns);
     1215    PVM pVM = pDevIns->Internal.s.pVMR3;
     1216    VM_ASSERT_EMT(pVM);
     1217    LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, .pfnSetIrqR3=%p, "
     1218             ".pfnSaveExecR3=%p, .pfnLoadExecR3=%p, .pfnFakePCIBIOSR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppPciHlpR3=%p\n",
     1219             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
     1220             pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnSetIrqR3, pPciBusReg->pfnSaveExecR3, pPciBusReg->pfnLoadExecR3,
     1221             pPciBusReg->pfnFakePCIBIOSR3, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqR0, pPciBusReg->pszSetIrqR0, ppPciHlpR3));
     1222
     1223    /*
     1224     * Validate the structure.
     1225     */
     1226    if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
     1227    {
     1228        AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
     1229        LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1230        return VERR_INVALID_PARAMETER;
     1231    }
     1232    if (    !pPciBusReg->pfnRegisterR3
     1233        ||  !pPciBusReg->pfnIORegionRegisterR3
     1234        ||  !pPciBusReg->pfnSetIrqR3
     1235        ||  !pPciBusReg->pfnSaveExecR3
     1236        ||  !pPciBusReg->pfnLoadExecR3
     1237        ||  !pPciBusReg->pfnFakePCIBIOSR3)
     1238    {
     1239        Assert(pPciBusReg->pfnRegisterR3);
     1240        Assert(pPciBusReg->pfnIORegionRegisterR3);
     1241        Assert(pPciBusReg->pfnSetIrqR3);
     1242        Assert(pPciBusReg->pfnSaveExecR3);
     1243        Assert(pPciBusReg->pfnLoadExecR3);
     1244        Assert(pPciBusReg->pfnFakePCIBIOSR3);
     1245        LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1246        return VERR_INVALID_PARAMETER;
     1247    }
     1248    if (    pPciBusReg->pszSetIrqRC
     1249        &&  !VALID_PTR(pPciBusReg->pszSetIrqRC))
     1250    {
     1251        Assert(VALID_PTR(pPciBusReg->pszSetIrqRC));
     1252        LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1253        return VERR_INVALID_PARAMETER;
     1254    }
     1255    if (    pPciBusReg->pszSetIrqR0
     1256        &&  !VALID_PTR(pPciBusReg->pszSetIrqR0))
     1257    {
     1258        Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
     1259        LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1260        return VERR_INVALID_PARAMETER;
     1261    }
     1262     if (!ppPciHlpR3)
     1263    {
     1264        Assert(ppPciHlpR3);
     1265        LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (ppPciHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1266        return VERR_INVALID_PARAMETER;
     1267    }
     1268
     1269    /*
     1270     * Find free PCI bus entry.
     1271     */
     1272    unsigned iBus = 0;
     1273    for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
     1274        if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
     1275            break;
     1276    if (iBus >= RT_ELEMENTS(pVM->pdm.s.aPciBuses))
     1277    {
     1278        AssertMsgFailed(("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)));
     1279        LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (pci bus)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1280        return VERR_INVALID_PARAMETER;
     1281    }
     1282    PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
     1283
     1284    /*
     1285     * Resolve and init the RC bits.
     1286     */
     1287    if (pPciBusReg->pszSetIrqRC)
     1288    {
     1289        int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, &pPciBus->pfnSetIrqRC);
     1290        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, rc));
     1291        if (VBOX_FAILURE(rc))
     1292        {
     1293            LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1294            return rc;
     1295        }
     1296        pPciBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1297    }
     1298    else
     1299    {
     1300        pPciBus->pfnSetIrqRC = 0;
     1301        pPciBus->pDevInsRC   = 0;
     1302    }
     1303
     1304    /*
     1305     * Resolve and init the R0 bits.
     1306     */
     1307    if (pPciBusReg->pszSetIrqR0)
     1308    {
     1309        int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
     1310        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, rc));
     1311        if (VBOX_FAILURE(rc))
     1312        {
     1313            LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1314            return rc;
     1315        }
     1316        pPciBus->pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
     1317    }
     1318    else
     1319    {
     1320        pPciBus->pfnSetIrqR0 = 0;
     1321        pPciBus->pDevInsR0   = 0;
     1322    }
     1323
     1324    /*
     1325     * Init the R3 bits.
     1326     */
     1327    pPciBus->iBus                    = iBus;
     1328    pPciBus->pDevInsR3               = pDevIns;
     1329    pPciBus->pfnRegisterR3           = pPciBusReg->pfnRegisterR3;
     1330    pPciBus->pfnIORegionRegisterR3   = pPciBusReg->pfnIORegionRegisterR3;
     1331    pPciBus->pfnSetConfigCallbacksR3 = pPciBusReg->pfnSetConfigCallbacksR3;
     1332    pPciBus->pfnSetIrqR3             = pPciBusReg->pfnSetIrqR3;
     1333    pPciBus->pfnSaveExecR3           = pPciBusReg->pfnSaveExecR3;
     1334    pPciBus->pfnLoadExecR3           = pPciBusReg->pfnLoadExecR3;
     1335    pPciBus->pfnFakePCIBIOSR3        = pPciBusReg->pfnFakePCIBIOSR3;
     1336
     1337    Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
     1338
     1339    /* set the helper pointer and return. */
     1340    *ppPciHlpR3 = &g_pdmR3DevPciHlp;
     1341    LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
     1342    return VINF_SUCCESS;
     1343}
     1344
     1345
     1346/** @copydoc PDMDEVHLPR3::pfnPICRegister */
     1347static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
     1348{
     1349    PDMDEV_ASSERT_DEVINS(pDevIns);
     1350    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     1351    LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pfnGetInterruptR3=%p, .pszGetIrqRC=%p:{%s}, .pszGetInterruptRC=%p:{%s}, .pszGetIrqR0=%p:{%s}, .pszGetInterruptR0=%p:{%s} } ppPicHlpR3=%p\n",
     1352             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
     1353             pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
     1354             pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
     1355             ppPicHlpR3));
     1356
     1357    /*
     1358     * Validate input.
     1359     */
     1360    if (pPicReg->u32Version != PDM_PICREG_VERSION)
     1361    {
     1362        AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
     1363        LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1364        return VERR_INVALID_PARAMETER;
     1365    }
     1366    if (    !pPicReg->pfnSetIrqR3
     1367        ||  !pPicReg->pfnGetInterruptR3)
     1368    {
     1369        Assert(pPicReg->pfnSetIrqR3);
     1370        Assert(pPicReg->pfnGetInterruptR3);
     1371        LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1372        return VERR_INVALID_PARAMETER;
     1373    }
     1374    if (    (   pPicReg->pszSetIrqRC
     1375             || pPicReg->pszGetInterruptRC)
     1376        &&  (   !VALID_PTR(pPicReg->pszSetIrqRC)
     1377             || !VALID_PTR(pPicReg->pszGetInterruptRC))
     1378       )
     1379    {
     1380        Assert(VALID_PTR(pPicReg->pszSetIrqRC));
     1381        Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
     1382        LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1383        return VERR_INVALID_PARAMETER;
     1384    }
     1385    if (    pPicReg->pszSetIrqRC
     1386        &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
     1387    {
     1388        Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC);
     1389        LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1390        return VERR_INVALID_PARAMETER;
     1391    }
     1392    if (    pPicReg->pszSetIrqR0
     1393        &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
     1394    {
     1395        Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0);
     1396        LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R0 flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1397        return VERR_INVALID_PARAMETER;
     1398    }
     1399    if (!ppPicHlpR3)
     1400    {
     1401        Assert(ppPicHlpR3);
     1402        LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (ppPicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1403        return VERR_INVALID_PARAMETER;
     1404    }
     1405
     1406    /*
     1407     * Only one PIC device.
     1408     */
     1409    PVM pVM = pDevIns->Internal.s.pVMR3;
     1410    if (pVM->pdm.s.Pic.pDevInsR3)
     1411    {
     1412        AssertMsgFailed(("Only one pic device is supported!\n"));
     1413        LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1414        return VERR_INVALID_PARAMETER;
     1415    }
     1416
     1417    /*
     1418     * RC stuff.
     1419     */
     1420    if (pPicReg->pszSetIrqRC)
     1421    {
     1422        int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
     1423        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, rc));
     1424        if (VBOX_SUCCESS(rc))
     1425        {
     1426            rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
     1427            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, rc));
     1428        }
     1429        if (VBOX_FAILURE(rc))
     1430        {
     1431            LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1432            return rc;
     1433        }
     1434        pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1435    }
     1436    else
     1437    {
     1438        pVM->pdm.s.Pic.pDevInsRC = 0;
     1439        pVM->pdm.s.Pic.pfnSetIrqRC = 0;
     1440        pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
     1441    }
     1442
     1443    /*
     1444     * R0 stuff.
     1445     */
     1446    if (pPicReg->pszSetIrqR0)
     1447    {
     1448        int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
     1449        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, rc));
     1450        if (VBOX_SUCCESS(rc))
     1451        {
     1452            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
     1453            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, rc));
     1454        }
     1455        if (VBOX_FAILURE(rc))
     1456        {
     1457            LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1458            return rc;
     1459        }
     1460        pVM->pdm.s.Pic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
     1461        Assert(pVM->pdm.s.Pic.pDevInsR0);
     1462    }
     1463    else
     1464    {
     1465        pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
     1466        pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
     1467        pVM->pdm.s.Pic.pDevInsR0 = 0;
     1468    }
     1469
     1470    /*
     1471     * R3 stuff.
     1472     */
     1473    pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
     1474    pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
     1475    pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
     1476    Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
     1477
     1478    /* set the helper pointer and return. */
     1479    *ppPicHlpR3 = &g_pdmR3DevPicHlp;
     1480    LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
     1481    return VINF_SUCCESS;
     1482}
     1483
     1484
     1485/** @copydoc PDMDEVHLPR3::pfnAPICRegister */
     1486static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
     1487{
     1488    PDMDEV_ASSERT_DEVINS(pDevIns);
     1489    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     1490    LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptR3=%p, .pfnSetBaseR3=%p, .pfnGetBaseR3=%p, "
     1491             ".pfnSetTPRR3=%p, .pfnGetTPRR3=%p, .pfnBusDeliverR3=%p, pszGetInterruptRC=%p:{%s}, pszSetBaseRC=%p:{%s}, pszGetBaseRC=%p:{%s}, "
     1492             ".pszSetTPRRC=%p:{%s}, .pszGetTPRRC=%p:{%s}, .pszBusDeliverRC=%p:{%s}} ppApicHlpR3=%p\n",
     1493             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptR3, pApicReg->pfnSetBaseR3,
     1494             pApicReg->pfnGetBaseR3, pApicReg->pfnSetTPRR3, pApicReg->pfnGetTPRR3, pApicReg->pfnBusDeliverR3, pApicReg->pszGetInterruptRC,
     1495             pApicReg->pszGetInterruptRC, pApicReg->pszSetBaseRC, pApicReg->pszSetBaseRC, pApicReg->pszGetBaseRC, pApicReg->pszGetBaseRC,
     1496             pApicReg->pszSetTPRRC, pApicReg->pszSetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszBusDeliverRC,
     1497             pApicReg->pszBusDeliverRC, ppApicHlpR3));
     1498
     1499    /*
     1500     * Validate input.
     1501     */
     1502    if (pApicReg->u32Version != PDM_APICREG_VERSION)
     1503    {
     1504        AssertMsgFailed(("u32Version=%#x expected %#x\n", pApicReg->u32Version, PDM_APICREG_VERSION));
     1505        LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1506        return VERR_INVALID_PARAMETER;
     1507    }
     1508    if (    !pApicReg->pfnGetInterruptR3
     1509        ||  !pApicReg->pfnHasPendingIrqR3
     1510        ||  !pApicReg->pfnSetBaseR3
     1511        ||  !pApicReg->pfnGetBaseR3
     1512        ||  !pApicReg->pfnSetTPRR3
     1513        ||  !pApicReg->pfnGetTPRR3
     1514        ||  !pApicReg->pfnBusDeliverR3)
     1515    {
     1516        Assert(pApicReg->pfnGetInterruptR3);
     1517        Assert(pApicReg->pfnHasPendingIrqR3);
     1518        Assert(pApicReg->pfnSetBaseR3);
     1519        Assert(pApicReg->pfnGetBaseR3);
     1520        Assert(pApicReg->pfnSetTPRR3);
     1521        Assert(pApicReg->pfnGetTPRR3);
     1522        Assert(pApicReg->pfnBusDeliverR3);
     1523        LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1524        return VERR_INVALID_PARAMETER;
     1525    }
     1526    if (   (    pApicReg->pszGetInterruptRC
     1527            ||  pApicReg->pszHasPendingIrqRC
     1528            ||  pApicReg->pszSetBaseRC
     1529            ||  pApicReg->pszGetBaseRC
     1530            ||  pApicReg->pszSetTPRRC
     1531            ||  pApicReg->pszGetTPRRC
     1532            ||  pApicReg->pszBusDeliverRC)
     1533        &&  (   !VALID_PTR(pApicReg->pszGetInterruptRC)
     1534            ||  !VALID_PTR(pApicReg->pszHasPendingIrqRC)
     1535            ||  !VALID_PTR(pApicReg->pszSetBaseRC)
     1536            ||  !VALID_PTR(pApicReg->pszGetBaseRC)
     1537            ||  !VALID_PTR(pApicReg->pszSetTPRRC)
     1538            ||  !VALID_PTR(pApicReg->pszGetTPRRC)
     1539            ||  !VALID_PTR(pApicReg->pszBusDeliverRC))
     1540       )
     1541    {
     1542        Assert(VALID_PTR(pApicReg->pszGetInterruptRC));
     1543        Assert(VALID_PTR(pApicReg->pszHasPendingIrqRC));
     1544        Assert(VALID_PTR(pApicReg->pszSetBaseRC));
     1545        Assert(VALID_PTR(pApicReg->pszGetBaseRC));
     1546        Assert(VALID_PTR(pApicReg->pszSetTPRRC));
     1547        Assert(VALID_PTR(pApicReg->pszGetTPRRC));
     1548        Assert(VALID_PTR(pApicReg->pszBusDeliverRC));
     1549        LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1550        return VERR_INVALID_PARAMETER;
     1551    }
     1552    if (   (    pApicReg->pszGetInterruptR0
     1553            ||  pApicReg->pszHasPendingIrqR0
     1554            ||  pApicReg->pszSetBaseR0
     1555            ||  pApicReg->pszGetBaseR0
     1556            ||  pApicReg->pszSetTPRR0
     1557            ||  pApicReg->pszGetTPRR0
     1558            ||  pApicReg->pszBusDeliverR0)
     1559        &&  (   !VALID_PTR(pApicReg->pszGetInterruptR0)
     1560            ||  !VALID_PTR(pApicReg->pszHasPendingIrqR0)
     1561            ||  !VALID_PTR(pApicReg->pszSetBaseR0)
     1562            ||  !VALID_PTR(pApicReg->pszGetBaseR0)
     1563            ||  !VALID_PTR(pApicReg->pszSetTPRR0)
     1564            ||  !VALID_PTR(pApicReg->pszGetTPRR0)
     1565            ||  !VALID_PTR(pApicReg->pszBusDeliverR0))
     1566       )
     1567    {
     1568        Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
     1569        Assert(VALID_PTR(pApicReg->pszHasPendingIrqR0));
     1570        Assert(VALID_PTR(pApicReg->pszSetBaseR0));
     1571        Assert(VALID_PTR(pApicReg->pszGetBaseR0));
     1572        Assert(VALID_PTR(pApicReg->pszSetTPRR0));
     1573        Assert(VALID_PTR(pApicReg->pszGetTPRR0));
     1574        Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
     1575        LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1576        return VERR_INVALID_PARAMETER;
     1577    }
     1578    if (!ppApicHlpR3)
     1579    {
     1580        Assert(ppApicHlpR3);
     1581        LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1582        return VERR_INVALID_PARAMETER;
     1583    }
     1584
     1585    /*
     1586     * Only one APIC device. (malc: only in UP case actually)
     1587     */
     1588    PVM pVM = pDevIns->Internal.s.pVMR3;
     1589    if (pVM->pdm.s.Apic.pDevInsR3)
     1590    {
     1591        AssertMsgFailed(("Only one apic device is supported!\n"));
     1592        LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1593        return VERR_INVALID_PARAMETER;
     1594    }
     1595
     1596    /*
     1597     * Resolve & initialize the RC bits.
     1598     */
     1599    if (pApicReg->pszGetInterruptRC)
     1600    {
     1601        int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, &pVM->pdm.s.Apic.pfnGetInterruptRC);
     1602        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, rc));
     1603        if (RT_SUCCESS(rc))
     1604        {
     1605            rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, &pVM->pdm.s.Apic.pfnHasPendingIrqRC);
     1606            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, rc));
     1607        }
     1608        if (RT_SUCCESS(rc))
     1609        {
     1610            rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, &pVM->pdm.s.Apic.pfnSetBaseRC);
     1611            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, rc));
     1612        }
     1613        if (RT_SUCCESS(rc))
     1614        {
     1615            rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, &pVM->pdm.s.Apic.pfnGetBaseRC);
     1616            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, rc));
     1617        }
     1618        if (RT_SUCCESS(rc))
     1619        {
     1620            rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, &pVM->pdm.s.Apic.pfnSetTPRRC);
     1621            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, rc));
     1622        }
     1623        if (RT_SUCCESS(rc))
     1624        {
     1625            rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, &pVM->pdm.s.Apic.pfnGetTPRRC);
     1626            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, rc));
     1627        }
     1628        if (RT_SUCCESS(rc))
     1629        {
     1630            rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, &pVM->pdm.s.Apic.pfnBusDeliverRC);
     1631            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, rc));
     1632        }
     1633        if (VBOX_FAILURE(rc))
     1634        {
     1635            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1636            return rc;
     1637        }
     1638        pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1639    }
     1640    else
     1641    {
     1642        pVM->pdm.s.Apic.pDevInsRC           = 0;
     1643        pVM->pdm.s.Apic.pfnGetInterruptRC   = 0;
     1644        pVM->pdm.s.Apic.pfnHasPendingIrqRC  = 0;
     1645        pVM->pdm.s.Apic.pfnSetBaseRC        = 0;
     1646        pVM->pdm.s.Apic.pfnGetBaseRC        = 0;
     1647        pVM->pdm.s.Apic.pfnSetTPRRC         = 0;
     1648        pVM->pdm.s.Apic.pfnGetTPRRC         = 0;
     1649        pVM->pdm.s.Apic.pfnBusDeliverRC     = 0;
     1650    }
     1651
     1652    /*
     1653     * Resolve & initialize the R0 bits.
     1654     */
     1655    if (pApicReg->pszGetInterruptR0)
     1656    {
     1657        int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
     1658        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
     1659        if (RT_SUCCESS(rc))
     1660        {
     1661            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, &pVM->pdm.s.Apic.pfnHasPendingIrqR0);
     1662            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, rc));
     1663        }
     1664        if (RT_SUCCESS(rc))
     1665        {
     1666            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
     1667            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
     1668        }
     1669        if (RT_SUCCESS(rc))
     1670        {
     1671            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
     1672            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
     1673        }
     1674        if (RT_SUCCESS(rc))
     1675        {
     1676            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
     1677            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
     1678        }
     1679        if (RT_SUCCESS(rc))
     1680        {
     1681            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
     1682            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
     1683        }
     1684        if (RT_SUCCESS(rc))
     1685        {
     1686            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
     1687            AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
     1688        }
     1689        if (VBOX_FAILURE(rc))
     1690        {
     1691            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1692            return rc;
     1693        }
     1694        pVM->pdm.s.Apic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
     1695        Assert(pVM->pdm.s.Apic.pDevInsR0);
     1696    }
     1697    else
     1698    {
     1699        pVM->pdm.s.Apic.pfnGetInterruptR0   = 0;
     1700        pVM->pdm.s.Apic.pfnHasPendingIrqR0  = 0;
     1701        pVM->pdm.s.Apic.pfnSetBaseR0        = 0;
     1702        pVM->pdm.s.Apic.pfnGetBaseR0        = 0;
     1703        pVM->pdm.s.Apic.pfnSetTPRR0         = 0;
     1704        pVM->pdm.s.Apic.pfnGetTPRR0         = 0;
     1705        pVM->pdm.s.Apic.pfnBusDeliverR0     = 0;
     1706        pVM->pdm.s.Apic.pDevInsR0           = 0;
     1707    }
     1708
     1709    /*
     1710     * Initialize the HC bits.
     1711     */
     1712    pVM->pdm.s.Apic.pDevInsR3           = pDevIns;
     1713    pVM->pdm.s.Apic.pfnGetInterruptR3   = pApicReg->pfnGetInterruptR3;
     1714    pVM->pdm.s.Apic.pfnHasPendingIrqR3  = pApicReg->pfnHasPendingIrqR3;
     1715    pVM->pdm.s.Apic.pfnSetBaseR3        = pApicReg->pfnSetBaseR3;
     1716    pVM->pdm.s.Apic.pfnGetBaseR3        = pApicReg->pfnGetBaseR3;
     1717    pVM->pdm.s.Apic.pfnSetTPRR3         = pApicReg->pfnSetTPRR3;
     1718    pVM->pdm.s.Apic.pfnGetTPRR3         = pApicReg->pfnGetTPRR3;
     1719    pVM->pdm.s.Apic.pfnBusDeliverR3     = pApicReg->pfnBusDeliverR3;
     1720    Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
     1721
     1722    /* set the helper pointer and return. */
     1723    *ppApicHlpR3 = &g_pdmR3DevApicHlp;
     1724    LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
     1725    return VINF_SUCCESS;
     1726}
     1727
     1728
     1729/** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
     1730static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
     1731{
     1732    PDMDEV_ASSERT_DEVINS(pDevIns);
     1733    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     1734    LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
     1735             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
     1736             pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
     1737
     1738    /*
     1739     * Validate input.
     1740     */
     1741    if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
     1742    {
     1743        AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
     1744        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1745        return VERR_INVALID_PARAMETER;
     1746    }
     1747    if (!pIoApicReg->pfnSetIrqR3)
     1748    {
     1749        Assert(pIoApicReg->pfnSetIrqR3);
     1750        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1751        return VERR_INVALID_PARAMETER;
     1752    }
     1753    if (    pIoApicReg->pszSetIrqRC
     1754        &&  !VALID_PTR(pIoApicReg->pszSetIrqRC))
     1755    {
     1756        Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
     1757        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1758        return VERR_INVALID_PARAMETER;
     1759    }
     1760    if (    pIoApicReg->pszSetIrqR0
     1761        &&  !VALID_PTR(pIoApicReg->pszSetIrqR0))
     1762    {
     1763        Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
     1764        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1765        return VERR_INVALID_PARAMETER;
     1766    }
     1767    if (!ppIoApicHlpR3)
     1768    {
     1769        Assert(ppIoApicHlpR3);
     1770        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1771        return VERR_INVALID_PARAMETER;
     1772    }
     1773
     1774    /*
     1775     * The I/O APIC requires the APIC to be present (hacks++).
     1776     * If the I/O APIC does GC stuff so must the APIC.
     1777     */
     1778    PVM pVM = pDevIns->Internal.s.pVMR3;
     1779    if (!pVM->pdm.s.Apic.pDevInsR3)
     1780    {
     1781        AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
     1782        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1783        return VERR_INVALID_PARAMETER;
     1784    }
     1785    if (    pIoApicReg->pszSetIrqRC
     1786        &&  !pVM->pdm.s.Apic.pDevInsRC)
     1787    {
     1788        AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
     1789        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1790        return VERR_INVALID_PARAMETER;
     1791    }
     1792
     1793    /*
     1794     * Only one I/O APIC device.
     1795     */
     1796    if (pVM->pdm.s.IoApic.pDevInsR3)
     1797    {
     1798        AssertMsgFailed(("Only one ioapic device is supported!\n"));
     1799        LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1800        return VERR_INVALID_PARAMETER;
     1801    }
     1802
     1803    /*
     1804     * Resolve & initialize the GC bits.
     1805     */
     1806    if (pIoApicReg->pszSetIrqRC)
     1807    {
     1808        int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
     1809        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, rc));
     1810        if (VBOX_FAILURE(rc))
     1811        {
     1812            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1813            return rc;
     1814        }
     1815        pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1816    }
     1817    else
     1818    {
     1819        pVM->pdm.s.IoApic.pDevInsRC   = 0;
     1820        pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
     1821    }
     1822
     1823    /*
     1824     * Resolve & initialize the R0 bits.
     1825     */
     1826    if (pIoApicReg->pszSetIrqR0)
     1827    {
     1828        int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
     1829        AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
     1830        if (VBOX_FAILURE(rc))
     1831        {
     1832            LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1833            return rc;
     1834        }
     1835        pVM->pdm.s.IoApic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
     1836        Assert(pVM->pdm.s.IoApic.pDevInsR0);
     1837    }
     1838    else
     1839    {
     1840        pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
     1841        pVM->pdm.s.IoApic.pDevInsR0   = 0;
     1842    }
     1843
     1844    /*
     1845     * Initialize the R3 bits.
     1846     */
     1847    pVM->pdm.s.IoApic.pDevInsR3   = pDevIns;
     1848    pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
     1849    Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
     1850
     1851    /* set the helper pointer and return. */
     1852    *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
     1853    LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
     1854    return VINF_SUCCESS;
     1855}
     1856
     1857
     1858/** @copydoc PDMDEVHLPR3::pfnDMACRegister */
     1859static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
     1860{
     1861    PDMDEV_ASSERT_DEVINS(pDevIns);
     1862    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     1863    LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: pDmacReg=%p:{.u32Version=%#x, .pfnRun=%p, .pfnRegister=%p, .pfnReadMemory=%p, .pfnWriteMemory=%p, .pfnSetDREQ=%p, .pfnGetChannelMode=%p} ppDmacHlp=%p\n",
     1864             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
     1865             pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
     1866
     1867    /*
     1868     * Validate input.
     1869     */
     1870    if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
     1871    {
     1872        AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
     1873                         PDM_DMACREG_VERSION));
     1874        LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
     1875                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1876        return VERR_INVALID_PARAMETER;
     1877    }
     1878    if (    !pDmacReg->pfnRun
     1879        ||  !pDmacReg->pfnRegister
     1880        ||  !pDmacReg->pfnReadMemory
     1881        ||  !pDmacReg->pfnWriteMemory
     1882        ||  !pDmacReg->pfnSetDREQ
     1883        ||  !pDmacReg->pfnGetChannelMode)
     1884    {
     1885        Assert(pDmacReg->pfnRun);
     1886        Assert(pDmacReg->pfnRegister);
     1887        Assert(pDmacReg->pfnReadMemory);
     1888        Assert(pDmacReg->pfnWriteMemory);
     1889        Assert(pDmacReg->pfnSetDREQ);
     1890        Assert(pDmacReg->pfnGetChannelMode);
     1891        LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
     1892                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1893        return VERR_INVALID_PARAMETER;
     1894    }
     1895
     1896    if (!ppDmacHlp)
     1897    {
     1898        Assert(ppDmacHlp);
     1899        LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
     1900                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1901        return VERR_INVALID_PARAMETER;
     1902    }
     1903
     1904    /*
     1905     * Only one DMA device.
     1906     */
     1907    PVM pVM = pDevIns->Internal.s.pVMR3;
     1908    if (pVM->pdm.s.pDmac)
     1909    {
     1910        AssertMsgFailed(("Only one DMA device is supported!\n"));
     1911        LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
     1912                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
     1913        return VERR_INVALID_PARAMETER;
     1914    }
     1915
     1916    /*
     1917     * Allocate and initialize pci bus structure.
     1918     */
     1919    int rc = VINF_SUCCESS;
     1920    PPDMDMAC  pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
     1921    if (pDmac)
     1922    {
     1923        pDmac->pDevIns   = pDevIns;
     1924        pDmac->Reg       = *pDmacReg;
     1925        pVM->pdm.s.pDmac = pDmac;
     1926
     1927        /* set the helper pointer. */
     1928        *ppDmacHlp = &g_pdmR3DevDmacHlp;
     1929        Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
     1930             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
     1931    }
     1932    else
     1933        rc = VERR_NO_MEMORY;
     1934
     1935    LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
     1936             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1937    return rc;
     1938}
     1939
     1940
     1941/** @copydoc PDMDEVHLPR3::pfnPhysRead */
     1942static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
     1943{
     1944    PDMDEV_ASSERT_DEVINS(pDevIns);
     1945    LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
     1946             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
     1947
     1948    /*
     1949     * For the convenience of the device we put no thread restriction on this interface.
     1950     * That means we'll have to check which thread we're in and choose our path.
     1951     */
     1952#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
     1953    PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
     1954#else
     1955    if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
     1956        PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
     1957    else
     1958    {
     1959        Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1960        PVMREQ pReq;
     1961        AssertCompileSize(RTGCPHYS, 4);
     1962        int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
     1963                                 (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
     1964        while (rc == VERR_TIMEOUT)
     1965            rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
     1966        AssertReleaseRC(rc);
     1967        VMR3ReqFree(pReq);
     1968    }
     1969#endif
     1970    Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1971}
     1972
     1973
     1974/** @copydoc PDMDEVHLPR3::pfnPhysWrite */
     1975static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
     1976{
     1977    PDMDEV_ASSERT_DEVINS(pDevIns);
     1978    LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
     1979             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
     1980
     1981    /*
     1982     * For the convenience of the device we put no thread restriction on this interface.
     1983     * That means we'll have to check which thread we're in and choose our path.
     1984     */
     1985#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
     1986    PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
     1987#else
     1988    if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
     1989        PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
     1990    else
     1991    {
     1992        Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1993        PVMREQ pReq;
     1994        AssertCompileSize(RTGCPHYS, 4);
     1995        int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
     1996                                 (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
     1997        while (rc == VERR_TIMEOUT)
     1998            rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
     1999        AssertReleaseRC(rc);
     2000        VMR3ReqFree(pReq);
     2001    }
     2002#endif
     2003    Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2004}
     2005
     2006
     2007/** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
     2008static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
     2009{
     2010    PDMDEV_ASSERT_DEVINS(pDevIns);
     2011    PVM pVM = pDevIns->Internal.s.pVMR3;
     2012    VM_ASSERT_EMT(pVM);
     2013    LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
     2014             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
     2015
     2016    if (!VM_IS_EMT(pVM))
     2017        return VERR_ACCESS_DENIED;
     2018
     2019    int rc = PGMPhysReadGCPtr(pVM, pvDst, GCVirtSrc, cb);
     2020
     2021    LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2022
     2023    return rc;
     2024}
     2025
     2026
     2027/** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
     2028static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
     2029{
     2030    PDMDEV_ASSERT_DEVINS(pDevIns);
     2031    PVM pVM = pDevIns->Internal.s.pVMR3;
     2032    VM_ASSERT_EMT(pVM);
     2033    LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
     2034             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
     2035
     2036    if (!VM_IS_EMT(pVM))
     2037        return VERR_ACCESS_DENIED;
     2038
     2039    int rc = PGMPhysWriteGCPtr(pVM, GCVirtDst, pvSrc, cb);
     2040
     2041    LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2042
     2043    return rc;
     2044}
     2045
     2046
     2047/** @copydoc PDMDEVHLPR3::pfnPhysReserve */
     2048static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
     2049{
     2050    PDMDEV_ASSERT_DEVINS(pDevIns);
     2051    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2052    LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
     2053             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, pszDesc, pszDesc));
     2054
     2055    int rc = MMR3PhysReserve(pDevIns->Internal.s.pVMR3, GCPhys, cbRange, pszDesc);
     2056
     2057    LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2058
     2059    return rc;
     2060}
     2061
     2062
     2063/** @copydoc PDMDEVHLPR3::pfnObsoletePhys2HCVirt */
     2064static DECLCALLBACK(int) pdmR3DevHlp_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
     2065{
     2066    PDMDEV_ASSERT_DEVINS(pDevIns);
     2067    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2068    NOREF(GCPhys);
     2069    NOREF(cbRange);
     2070    NOREF(ppvHC);
     2071    return VERR_ACCESS_DENIED;
     2072}
     2073
     2074
     2075/** @copydoc PDMDEVHLPR3::pfnObsoletePhysGCPtr2HCPtr */
     2076static DECLCALLBACK(int) pdmR3DevHlp_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
     2077{
     2078    PDMDEV_ASSERT_DEVINS(pDevIns);
     2079    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2080    NOREF(GCPtr);
     2081    NOREF(pHCPtr);
     2082    return VERR_ACCESS_DENIED;
     2083}
     2084
     2085
     2086/** @copydoc PDMDEVHLPR3::pfnPhysGCPtr2GCPhys */
     2087static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
     2088{
     2089    PDMDEV_ASSERT_DEVINS(pDevIns);
     2090    PVM pVM = pDevIns->Internal.s.pVMR3;
     2091    VM_ASSERT_EMT(pVM);
     2092    LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%VGv pGCPhys=%p\n",
     2093             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPtr, pGCPhys));
     2094
     2095    if (!VM_IS_EMT(pVM))
     2096        return VERR_ACCESS_DENIED;
     2097
     2098    int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, pGCPhys);
     2099
     2100    LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Vrc *pGCPhys=%VGp\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pGCPhys));
     2101
     2102    return rc;
     2103}
     2104
     2105
     2106/** @copydoc PDMDEVHLPR3::pfnVMState */
     2107static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
     2108{
     2109    PDMDEV_ASSERT_DEVINS(pDevIns);
     2110
     2111    VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
     2112
     2113    LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
     2114             enmVMState, VMR3GetStateName(enmVMState)));
     2115    return enmVMState;
     2116}
     2117
     2118
     2119/** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
     2120static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
     2121{
     2122    PDMDEV_ASSERT_DEVINS(pDevIns);
     2123    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2124
     2125    bool fRc = PGMPhysIsA20Enabled(pDevIns->Internal.s.pVMR3);
     2126
     2127    LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
     2128    return fRc;
     2129}
     2130
     2131
     2132/** @copydoc PDMDEVHLPR3::pfnA20Set */
     2133static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
     2134{
     2135    PDMDEV_ASSERT_DEVINS(pDevIns);
     2136    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2137    LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
     2138    //Assert(*(unsigned *)&fEnable <= 1);
     2139    PGMR3PhysSetA20(pDevIns->Internal.s.pVMR3, fEnable);
     2140}
     2141
     2142
     2143/** @copydoc PDMDEVHLPR3::pfnVMReset */
     2144static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
     2145{
     2146    PDMDEV_ASSERT_DEVINS(pDevIns);
     2147    PVM pVM = pDevIns->Internal.s.pVMR3;
     2148    VM_ASSERT_EMT(pVM);
     2149    LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
     2150             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
     2151
     2152    /*
     2153     * We postpone this operation because we're likely to be inside a I/O instruction
     2154     * and the EIP will be updated when we return.
     2155     * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
     2156     */
     2157    bool fHaltOnReset;
     2158    int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
     2159    if (VBOX_SUCCESS(rc) && fHaltOnReset)
     2160    {
     2161        Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
     2162        rc = VINF_EM_HALT;
     2163    }
     2164    else
     2165    {
     2166        VM_FF_SET(pVM, VM_FF_RESET);
     2167        rc = VINF_EM_RESET;
     2168    }
     2169
     2170    LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2171    return rc;
     2172}
     2173
     2174
     2175/** @copydoc PDMDEVHLPR3::pfnVMSuspend */
     2176static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
     2177{
     2178    PDMDEV_ASSERT_DEVINS(pDevIns);
     2179    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2180    LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
     2181             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2182
     2183    int rc = VMR3Suspend(pDevIns->Internal.s.pVMR3);
     2184
     2185    LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2186    return rc;
     2187}
     2188
     2189
     2190/** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
     2191static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
     2192{
     2193    PDMDEV_ASSERT_DEVINS(pDevIns);
     2194    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2195    LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
     2196             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2197
     2198    int rc = VMR3PowerOff(pDevIns->Internal.s.pVMR3);
     2199
     2200    LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2201    return rc;
     2202}
     2203
     2204
     2205/** @copydoc PDMDEVHLPR3::pfnLockVM */
     2206static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns)
     2207{
     2208    return VMMR3Lock(pDevIns->Internal.s.pVMR3);
     2209}
     2210
     2211
     2212/** @copydoc PDMDEVHLPR3::pfnUnlockVM */
     2213static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns)
     2214{
     2215    return VMMR3Unlock(pDevIns->Internal.s.pVMR3);
     2216}
     2217
     2218
     2219/** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
     2220static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
     2221{
     2222    PVM pVM = pDevIns->Internal.s.pVMR3;
     2223    if (VMMR3LockIsOwner(pVM))
     2224        return true;
     2225
     2226    RTNATIVETHREAD NativeThreadOwner = VMMR3LockGetOwner(pVM);
     2227    RTTHREAD ThreadOwner = RTThreadFromNative(NativeThreadOwner);
     2228    char szMsg[100];
     2229    RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
     2230                pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
     2231                NativeThreadOwner, ThreadOwner, RTThreadGetName(ThreadOwner), RTThreadSelfName());
     2232    AssertMsg1(szMsg, iLine, pszFile, pszFunction);
     2233    AssertBreakpoint();
     2234    return false;
     2235}
     2236
     2237/** @copydoc PDMDEVHLPR3::pfnDMARegister */
     2238static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
     2239{
     2240    PDMDEV_ASSERT_DEVINS(pDevIns);
     2241    PVM pVM = pDevIns->Internal.s.pVMR3;
     2242    VM_ASSERT_EMT(pVM);
     2243    LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
     2244             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
     2245    int rc = VINF_SUCCESS;
     2246    if (pVM->pdm.s.pDmac)
     2247        pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
     2248    else
     2249    {
     2250        AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
     2251        rc = VERR_PDM_NO_DMAC_INSTANCE;
     2252    }
     2253    LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
     2254             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2255    return rc;
     2256}
     2257
     2258/** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
     2259static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
     2260{
     2261    PDMDEV_ASSERT_DEVINS(pDevIns);
     2262    PVM pVM = pDevIns->Internal.s.pVMR3;
     2263    VM_ASSERT_EMT(pVM);
     2264    LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
     2265             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
     2266    int rc = VINF_SUCCESS;
     2267    if (pVM->pdm.s.pDmac)
     2268    {
     2269        uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
     2270        if (pcbRead)
     2271            *pcbRead = cb;
     2272    }
     2273    else
     2274    {
     2275        AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
     2276        rc = VERR_PDM_NO_DMAC_INSTANCE;
     2277    }
     2278    LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
     2279             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2280    return rc;
     2281}
     2282
     2283/** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
     2284static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
     2285{
     2286    PDMDEV_ASSERT_DEVINS(pDevIns);
     2287    PVM pVM = pDevIns->Internal.s.pVMR3;
     2288    VM_ASSERT_EMT(pVM);
     2289    LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
     2290             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
     2291    int rc = VINF_SUCCESS;
     2292    if (pVM->pdm.s.pDmac)
     2293    {
     2294        uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
     2295        if (pcbWritten)
     2296            *pcbWritten = cb;
     2297    }
     2298    else
     2299    {
     2300        AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
     2301        rc = VERR_PDM_NO_DMAC_INSTANCE;
     2302    }
     2303    LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
     2304             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2305    return rc;
     2306}
     2307
     2308/** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
     2309static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
     2310{
     2311    PDMDEV_ASSERT_DEVINS(pDevIns);
     2312    PVM pVM = pDevIns->Internal.s.pVMR3;
     2313    VM_ASSERT_EMT(pVM);
     2314    LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
     2315             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, uLevel));
     2316    int rc = VINF_SUCCESS;
     2317    if (pVM->pdm.s.pDmac)
     2318        pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
     2319    else
     2320    {
     2321        AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
     2322        rc = VERR_PDM_NO_DMAC_INSTANCE;
     2323    }
     2324    LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
     2325             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2326    return rc;
     2327}
     2328
     2329/** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
     2330static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
     2331{
     2332    PDMDEV_ASSERT_DEVINS(pDevIns);
     2333    PVM pVM = pDevIns->Internal.s.pVMR3;
     2334    VM_ASSERT_EMT(pVM);
     2335    LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
     2336             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel));
     2337    uint8_t u8Mode;
     2338    if (pVM->pdm.s.pDmac)
     2339        u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
     2340    else
     2341    {
     2342        AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
     2343        u8Mode = 3 << 2 /* illegal mode type */;
     2344    }
     2345    LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
     2346             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Mode));
     2347    return u8Mode;
     2348}
     2349
     2350/** @copydoc PDMDEVHLPR3::pfnDMASchedule */
     2351static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
     2352{
     2353    PDMDEV_ASSERT_DEVINS(pDevIns);
     2354    PVM pVM = pDevIns->Internal.s.pVMR3;
     2355    VM_ASSERT_EMT(pVM);
     2356    LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
     2357             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
     2358
     2359    AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
     2360    VM_FF_SET(pVM, VM_FF_PDM_DMA);
     2361    REMR3NotifyDmaPending(pVM);
     2362    VMR3NotifyFF(pVM, true);
     2363}
     2364
     2365
     2366/** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
     2367static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
     2368{
     2369    PDMDEV_ASSERT_DEVINS(pDevIns);
     2370    PVM pVM = pDevIns->Internal.s.pVMR3;
     2371    VM_ASSERT_EMT(pVM);
     2372
     2373    LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
     2374             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, u8Value));
     2375    int rc;
     2376    if (pVM->pdm.s.pRtc)
     2377        rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
     2378    else
     2379        rc = VERR_PDM_NO_RTC_INSTANCE;
     2380
     2381    LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
     2382             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2383    return rc;
     2384}
     2385
     2386
     2387/** @copydoc PDMDEVHLPR3::pfnCMOSRead */
     2388static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
     2389{
     2390    PDMDEV_ASSERT_DEVINS(pDevIns);
     2391    PVM pVM = pDevIns->Internal.s.pVMR3;
     2392    VM_ASSERT_EMT(pVM);
     2393
     2394    LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
     2395             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, pu8Value));
     2396    int rc;
     2397    if (pVM->pdm.s.pRtc)
     2398        rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
     2399    else
     2400        rc = VERR_PDM_NO_RTC_INSTANCE;
     2401
     2402    LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
     2403             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2404    return rc;
     2405}
     2406
     2407
     2408/** @copydoc PDMDEVHLPR3::pfnGetCpuId */
     2409static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
     2410                                               uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
     2411{
     2412    PDMDEV_ASSERT_DEVINS(pDevIns);
     2413    LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
     2414             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
     2415    AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
     2416
     2417    CPUMGetGuestCpuId(pDevIns->Internal.s.pVMR3, iLeaf, pEax, pEbx, pEcx, pEdx);
     2418
     2419    LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
     2420             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
     2421}
     2422
     2423
     2424/** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
     2425static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
     2426{
     2427    PDMDEV_ASSERT_DEVINS(pDevIns);
     2428    LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
     2429             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
     2430
     2431    int rc = MMR3PhysRomProtect(pDevIns->Internal.s.pVMR3, GCPhysStart, cbRange);
     2432
     2433    LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2434    return rc;
     2435}
     2436
     2437
     2438/**
     2439 * @copydoc PDMDEVHLPR3::pfnMMIO2Register
     2440 */
     2441static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
     2442{
     2443    PDMDEV_ASSERT_DEVINS(pDevIns);
     2444    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2445    LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: iRegion=#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",
     2446             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cb, fFlags, ppv, pszDesc, pszDesc));
     2447
     2448    int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, cb, fFlags, ppv, pszDesc);
     2449
     2450    LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2451    return rc;
     2452}
     2453
     2454
     2455/**
     2456 * @copydoc PDMDEVHLPR3::pfnMMIO2Deregister
     2457 */
     2458static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
     2459{
     2460    PDMDEV_ASSERT_DEVINS(pDevIns);
     2461    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2462    LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: iRegion=#x\n",
     2463             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion));
     2464
     2465    AssertReturn(iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);
     2466
     2467    int rc = PGMR3PhysMMIO2Deregister(pDevIns->Internal.s.pVMR3, pDevIns, iRegion);
     2468
     2469    LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2470    return rc;
     2471}
     2472
     2473
     2474/**
     2475 * @copydoc PDMDEVHLPR3::pfnMMIO2Map
     2476 */
     2477static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
     2478{
     2479    PDMDEV_ASSERT_DEVINS(pDevIns);
     2480    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2481    LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
     2482             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
     2483
     2484    int rc = PGMR3PhysMMIO2Map(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
     2485
     2486    LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2487    return rc;
     2488}
     2489
     2490
     2491/**
     2492 * @copydoc PDMDEVHLPR3::pfnMMIO2Unmap
     2493 */
     2494static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
     2495{
     2496    PDMDEV_ASSERT_DEVINS(pDevIns);
     2497    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2498    LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
     2499             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
     2500
     2501    int rc = PGMR3PhysMMIO2Unmap(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
     2502
     2503    LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     2504    return rc;
     2505}
     2506
     2507
     2508/**
     2509 * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2
     2510 */
     2511static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
     2512                                                     const char *pszDesc, PRTRCPTR pRCPtr)
     2513{
     2514    PDMDEV_ASSERT_DEVINS(pDevIns);
     2515    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2516    LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: iRegion=#x off=%RGp cb=%RGp pszDesc=%p:{%s} pRCPtr=%p\n",
     2517             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, off, cb, pszDesc, pszDesc, pRCPtr));
     2518
     2519    int rc = MMR3HyperMapMMIO2(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, off, cb, pszDesc, pRCPtr);
     2520
     2521    LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc *pRCPtr=%RRv\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pRCPtr));
     2522    return rc;
     2523}
     2524
     2525
     2526/**
     2527 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
     2528 */
     2529static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
     2530{
     2531    PDMDEV_ASSERT_DEVINS(pDevIns);
     2532    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2533
     2534    int rc = PDMR3RegisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys, pvHeap, cbSize);
     2535    return rc;
     2536}
     2537
     2538
     2539/**
     2540 * @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap
     2541 */
     2542static DECLCALLBACK(int) pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
     2543{
     2544    PDMDEV_ASSERT_DEVINS(pDevIns);
     2545    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     2546
     2547    int rc = PDMR3UnregisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys);
     2548    return rc;
     2549}
     2550
     2551
    2982552/**
    2992553 * The device helper structure for trusted devices.
     
    3612615    pdmR3DevHlp_PhysWriteGCVirt,
    3622616    pdmR3DevHlp_PhysReserve,
    363     pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt,
    364     pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr,
     2617    pdmR3DevHlp_Obsolete_Phys2HCVirt,
     2618    pdmR3DevHlp_Obsolete_PhysGCPtr2HCPtr,
    3652619    pdmR3DevHlp_A20IsEnabled,
    3662620    pdmR3DevHlp_A20Set,
     
    3902644    PDM_DEVHLP_VERSION /* the end */
    3912645};
     2646
     2647
     2648
     2649
     2650/** @copydoc PDMDEVHLPR3::pfnGetVM */
     2651static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
     2652{
     2653    PDMDEV_ASSERT_DEVINS(pDevIns);
     2654    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2655    return NULL;
     2656}
     2657
     2658
     2659/** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
     2660static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
     2661{
     2662    PDMDEV_ASSERT_DEVINS(pDevIns);
     2663    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2664    NOREF(pPciBusReg);
     2665    NOREF(ppPciHlpR3);
     2666    return VERR_ACCESS_DENIED;
     2667}
     2668
     2669
     2670/** @copydoc PDMDEVHLPR3::pfnPICRegister */
     2671static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
     2672{
     2673    PDMDEV_ASSERT_DEVINS(pDevIns);
     2674    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2675    NOREF(pPicReg);
     2676    NOREF(ppPicHlpR3);
     2677    return VERR_ACCESS_DENIED;
     2678}
     2679
     2680
     2681/** @copydoc PDMDEVHLPR3::pfnAPICRegister */
     2682static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
     2683{
     2684    PDMDEV_ASSERT_DEVINS(pDevIns);
     2685    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2686    NOREF(pApicReg);
     2687    NOREF(ppApicHlpR3);
     2688    return VERR_ACCESS_DENIED;
     2689}
     2690
     2691
     2692/** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
     2693static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
     2694{
     2695    PDMDEV_ASSERT_DEVINS(pDevIns);
     2696    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2697    NOREF(pIoApicReg);
     2698    NOREF(ppIoApicHlpR3);
     2699    return VERR_ACCESS_DENIED;
     2700}
     2701
     2702
     2703/** @copydoc PDMDEVHLPR3::pfnDMACRegister */
     2704static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
     2705{
     2706    PDMDEV_ASSERT_DEVINS(pDevIns);
     2707    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2708    NOREF(pDmacReg);
     2709    NOREF(ppDmacHlp);
     2710    return VERR_ACCESS_DENIED;
     2711}
     2712
     2713
     2714/** @copydoc PDMDEVHLPR3::pfnPhysRead */
     2715static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
     2716{
     2717    PDMDEV_ASSERT_DEVINS(pDevIns);
     2718    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2719    NOREF(GCPhys);
     2720    NOREF(pvBuf);
     2721    NOREF(cbRead);
     2722}
     2723
     2724
     2725/** @copydoc PDMDEVHLPR3::pfnPhysWrite */
     2726static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
     2727{
     2728    PDMDEV_ASSERT_DEVINS(pDevIns);
     2729    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2730    NOREF(GCPhys);
     2731    NOREF(pvBuf);
     2732    NOREF(cbWrite);
     2733}
     2734
     2735
     2736/** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
     2737static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
     2738{
     2739    PDMDEV_ASSERT_DEVINS(pDevIns);
     2740    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2741    NOREF(pvDst);
     2742    NOREF(GCVirtSrc);
     2743    NOREF(cb);
     2744    return VERR_ACCESS_DENIED;
     2745}
     2746
     2747
     2748/** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
     2749static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
     2750{
     2751    PDMDEV_ASSERT_DEVINS(pDevIns);
     2752    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2753    NOREF(GCVirtDst);
     2754    NOREF(pvSrc);
     2755    NOREF(cb);
     2756    return VERR_ACCESS_DENIED;
     2757}
     2758
     2759
     2760/** @copydoc PDMDEVHLPR3::pfnPhysReserve */
     2761static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
     2762{
     2763    PDMDEV_ASSERT_DEVINS(pDevIns);
     2764    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2765    NOREF(GCPhys);
     2766    NOREF(cbRange);
     2767    return VERR_ACCESS_DENIED;
     2768}
     2769
     2770
     2771/** @copydoc PDMDEVHLPR3::pfnObsoletePhys2HCVirt */
     2772static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
     2773{
     2774    PDMDEV_ASSERT_DEVINS(pDevIns);
     2775    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2776    NOREF(GCPhys);
     2777    NOREF(cbRange);
     2778    NOREF(ppvHC);
     2779    return VERR_ACCESS_DENIED;
     2780}
     2781
     2782
     2783/** @copydoc PDMDEVHLPR3::pfnObsoletePhysGCPtr2HCPtr */
     2784static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
     2785{
     2786    PDMDEV_ASSERT_DEVINS(pDevIns);
     2787    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2788    NOREF(GCPtr);
     2789    NOREF(pHCPtr);
     2790    return VERR_ACCESS_DENIED;
     2791}
     2792
     2793
     2794/** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
     2795static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
     2796{
     2797    PDMDEV_ASSERT_DEVINS(pDevIns);
     2798    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2799    return false;
     2800}
     2801
     2802
     2803/** @copydoc PDMDEVHLPR3::pfnA20Set */
     2804static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
     2805{
     2806    PDMDEV_ASSERT_DEVINS(pDevIns);
     2807    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2808    NOREF(fEnable);
     2809}
     2810
     2811
     2812/** @copydoc PDMDEVHLPR3::pfnVMReset */
     2813static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
     2814{
     2815    PDMDEV_ASSERT_DEVINS(pDevIns);
     2816    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2817    return VERR_ACCESS_DENIED;
     2818}
     2819
     2820
     2821/** @copydoc PDMDEVHLPR3::pfnVMSuspend */
     2822static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
     2823{
     2824    PDMDEV_ASSERT_DEVINS(pDevIns);
     2825    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2826    return VERR_ACCESS_DENIED;
     2827}
     2828
     2829
     2830/** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
     2831static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
     2832{
     2833    PDMDEV_ASSERT_DEVINS(pDevIns);
     2834    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2835    return VERR_ACCESS_DENIED;
     2836}
     2837
     2838
     2839/** @copydoc PDMDEVHLPR3::pfnLockVM */
     2840static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns)
     2841{
     2842    PDMDEV_ASSERT_DEVINS(pDevIns);
     2843    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2844    return VERR_ACCESS_DENIED;
     2845}
     2846
     2847
     2848/** @copydoc PDMDEVHLPR3::pfnUnlockVM */
     2849static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns)
     2850{
     2851    PDMDEV_ASSERT_DEVINS(pDevIns);
     2852    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2853    return VERR_ACCESS_DENIED;
     2854}
     2855
     2856
     2857/** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
     2858static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
     2859{
     2860    PDMDEV_ASSERT_DEVINS(pDevIns);
     2861    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2862    return false;
     2863}
     2864
     2865
     2866/** @copydoc PDMDEVHLPR3::pfnDMARegister */
     2867static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
     2868{
     2869    PDMDEV_ASSERT_DEVINS(pDevIns);
     2870    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2871    return VERR_ACCESS_DENIED;
     2872}
     2873
     2874
     2875/** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
     2876static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
     2877{
     2878    PDMDEV_ASSERT_DEVINS(pDevIns);
     2879    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2880    if (pcbRead)
     2881        *pcbRead = 0;
     2882    return VERR_ACCESS_DENIED;
     2883}
     2884
     2885
     2886/** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
     2887static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
     2888{
     2889    PDMDEV_ASSERT_DEVINS(pDevIns);
     2890    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2891    if (pcbWritten)
     2892        *pcbWritten = 0;
     2893    return VERR_ACCESS_DENIED;
     2894}
     2895
     2896
     2897/** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
     2898static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
     2899{
     2900    PDMDEV_ASSERT_DEVINS(pDevIns);
     2901    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2902    return VERR_ACCESS_DENIED;
     2903}
     2904
     2905
     2906/** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
     2907static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
     2908{
     2909    PDMDEV_ASSERT_DEVINS(pDevIns);
     2910    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2911    return 3 << 2 /* illegal mode type */;
     2912}
     2913
     2914
     2915/** @copydoc PDMDEVHLPR3::pfnDMASchedule */
     2916static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns)
     2917{
     2918    PDMDEV_ASSERT_DEVINS(pDevIns);
     2919    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2920}
     2921
     2922
     2923/** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
     2924static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
     2925{
     2926    PDMDEV_ASSERT_DEVINS(pDevIns);
     2927    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2928    return VERR_ACCESS_DENIED;
     2929}
     2930
     2931
     2932/** @copydoc PDMDEVHLPR3::pfnCMOSRead */
     2933static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
     2934{
     2935    PDMDEV_ASSERT_DEVINS(pDevIns);
     2936    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2937    return VERR_ACCESS_DENIED;
     2938}
     2939
     2940
     2941/** @copydoc PDMDEVHLPR3::pfnGetCpuId */
     2942static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
     2943                                                         uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
     2944{
     2945    PDMDEV_ASSERT_DEVINS(pDevIns);
     2946    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2947}
     2948
     2949
     2950/** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
     2951static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
     2952{
     2953    PDMDEV_ASSERT_DEVINS(pDevIns);
     2954    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2955    return VERR_ACCESS_DENIED;
     2956}
     2957
     2958
     2959/** @copydoc PDMDEVHLPR3::pfnMMIO2Register */
     2960static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
     2961{
     2962    PDMDEV_ASSERT_DEVINS(pDevIns);
     2963    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2964    return VERR_ACCESS_DENIED;
     2965}
     2966
     2967
     2968/** @copydoc PDMDEVHLPR3::pfnMMIO2Deregister */
     2969static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
     2970{
     2971    PDMDEV_ASSERT_DEVINS(pDevIns);
     2972    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2973    return VERR_ACCESS_DENIED;
     2974}
     2975
     2976
     2977/** @copydoc PDMDEVHLPR3::pfnMMIO2Map */
     2978static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
     2979{
     2980    PDMDEV_ASSERT_DEVINS(pDevIns);
     2981    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2982    return VERR_ACCESS_DENIED;
     2983}
     2984
     2985
     2986/** @copydoc PDMDEVHLPR3::pfnMMIO2Unmap */
     2987static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
     2988{
     2989    PDMDEV_ASSERT_DEVINS(pDevIns);
     2990    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     2991    return VERR_ACCESS_DENIED;
     2992}
     2993
     2994
     2995/** @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2 */
     2996static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr)
     2997{
     2998    PDMDEV_ASSERT_DEVINS(pDevIns);
     2999    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     3000    return VERR_ACCESS_DENIED;
     3001}
     3002
     3003
     3004/** @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap */
     3005static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
     3006{
     3007    PDMDEV_ASSERT_DEVINS(pDevIns);
     3008    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     3009    return VERR_ACCESS_DENIED;
     3010}
     3011
     3012
     3013/** @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap */
     3014static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
     3015{
     3016    PDMDEV_ASSERT_DEVINS(pDevIns);
     3017    AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     3018    return VERR_ACCESS_DENIED;
     3019}
    3923020
    3933021
     
    4883116
    4893117
    490 /**
    491  * PIC Device Helpers.
    492  */
    493 const PDMPICHLPR3 g_pdmR3DevPicHlp =
    494 {
    495     PDM_PICHLPR3_VERSION,
    496     pdmR3PicHlp_SetInterruptFF,
    497     pdmR3PicHlp_ClearInterruptFF,
    498     pdmR3PicHlp_Lock,
    499     pdmR3PicHlp_Unlock,
    500     pdmR3PicHlp_GetRCHelpers,
    501     pdmR3PicHlp_GetR0Helpers,
    502     PDM_PICHLPR3_VERSION /* the end */
    503 };
    504 
    505 
    506 /**
    507  * APIC Device Helpers.
    508  */
    509 const PDMAPICHLPR3 g_pdmR3DevApicHlp =
    510 {
    511     PDM_APICHLPR3_VERSION,
    512     pdmR3ApicHlp_SetInterruptFF,
    513     pdmR3ApicHlp_ClearInterruptFF,
    514     pdmR3ApicHlp_ChangeFeature,
    515     pdmR3ApicHlp_Lock,
    516     pdmR3ApicHlp_Unlock,
    517     pdmR3ApicHlp_GetCpuId,
    518     pdmR3ApicHlp_GetRCHelpers,
    519     pdmR3ApicHlp_GetR0Helpers,
    520     PDM_APICHLPR3_VERSION /* the end */
    521 };
    522 
    523 
    524 /**
    525  * I/O APIC Device Helpers.
    526  */
    527 const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
    528 {
    529     PDM_IOAPICHLPR3_VERSION,
    530     pdmR3IoApicHlp_ApicBusDeliver,
    531     pdmR3IoApicHlp_Lock,
    532     pdmR3IoApicHlp_Unlock,
    533     pdmR3IoApicHlp_GetRCHelpers,
    534     pdmR3IoApicHlp_GetR0Helpers,
    535     PDM_IOAPICHLPR3_VERSION /* the end */
    536 };
    537 
    538 
    539 /**
    540  * PCI Bus Device Helpers.
    541  */
    542 const PDMPCIHLPR3 g_pdmR3DevPciHlp =
    543 {
    544     PDM_PCIHLPR3_VERSION,
    545     pdmR3PciHlp_IsaSetIrq,
    546     pdmR3PciHlp_IoApicSetIrq,
    547     pdmR3PciHlp_IsMMIO2Base,
    548     pdmR3PciHlp_GetRCHelpers,
    549     pdmR3PciHlp_GetR0Helpers,
    550     pdmR3PciHlp_Lock,
    551     pdmR3PciHlp_Unlock,
    552     PDM_PCIHLPR3_VERSION, /* the end */
    553 };
    554 
    555 
    556 /**
    557  * DMAC Device Helpers.
    558  */
    559 const PDMDMACHLP g_pdmR3DevDmacHlp =
    560 {
    561     PDM_DMACHLP_VERSION
    562 };
    563 
    564 
    565 /**
    566  * RTC Device Helpers.
    567  */
    568 const PDMRTCHLP g_pdmR3DevRtcHlp =
    569 {
    570     PDM_RTCHLP_VERSION
    571 };
    572 
    573 
    574 
    575 /**
    576  * This function will initialize the devices for this VM instance.
    577  *
    578  *
    579  * First of all this mean loading the builtin device and letting them
    580  * register themselves. Beyond that any additional device modules are
    581  * loaded and called for registration.
    582  *
    583  * Then the device configuration is enumerated, the instantiation order
    584  * is determined, and finally they are instantiated.
    585  *
    586  * After all device have been successfully instantiated the the primary
    587  * PCI Bus device is called to emulate the PCI BIOS, i.e. making the
    588  * resource assignments. If there is no PCI device, this step is of course
    589  * skipped.
    590  *
    591  * Finally the init completion routines of the instantiated devices
    592  * are called.
    593  *
    594  * @returns VBox status code.
    595  * @param   pVM     VM Handle.
    596  */
    597 int pdmR3DevInit(PVM pVM)
    598 {
    599     LogFlow(("pdmR3DevInit:\n"));
    600 
    601     AssertRelease(!(RT_OFFSETOF(PDMDEVINS, achInstanceData) & 15));
    602     AssertRelease(sizeof(pVM->pdm.s.pDevInstances->Internal.s) <= sizeof(pVM->pdm.s.pDevInstances->Internal.padding));
    603 
    604     /*
    605      * Load device modules.
    606      */
    607     int rc = pdmR3DevLoadModules(pVM);
    608     if (RT_FAILURE(rc))
    609         return rc;
    610 
    611 #ifdef VBOX_WITH_USB
    612     /* ditto for USB Devices. */
    613     rc = pdmR3UsbLoadModules(pVM);
    614     if (RT_FAILURE(rc))
    615         return rc;
    616 #endif
    617 
    618     /*
    619      * Get the RC & R0 devhlps and create the devhlp R3 task queue.
    620      */
    621     PCPDMDEVHLPRC pDevHlpRC;
    622     rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCDevHlp", &pDevHlpRC);
    623     AssertReleaseRCReturn(rc, rc);
    624 
    625     PCPDMDEVHLPR0 pDevHlpR0;
    626     rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0DevHlp", &pDevHlpR0);
    627     AssertReleaseRCReturn(rc, rc);
    628 
    629     rc = PDMR3QueueCreateInternal(pVM, sizeof(PDMDEVHLPTASK), 8, 0, pdmR3DevHlpQueueConsumer, true, &pVM->pdm.s.pDevHlpQueueHC);
    630     AssertRCReturn(rc, rc);
    631     pVM->pdm.s.pDevHlpQueueGC = PDMQueueGCPtr(pVM->pdm.s.pDevHlpQueueHC);
    632 
    633 
    634     /*
    635      *
    636      * Enumerate the device instance configurations
    637      * and come up with a instantiation order.
    638      *
    639      */
    640     /* Switch to /Devices, which contains the device instantiations. */
    641     PCFGMNODE pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "Devices");
    642 
    643     /*
    644      * Count the device instances.
    645      */
    646     PCFGMNODE pCur;
    647     PCFGMNODE pInstanceNode;
    648     unsigned cDevs = 0;
    649     for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
    650         for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
    651             cDevs++;
    652     if (!cDevs)
    653     {
    654         Log(("PDM: No devices were configured!\n"));
    655         return VINF_SUCCESS;
    656     }
    657     Log2(("PDM: cDevs=%d!\n", cDevs));
    658 
    659     /*
    660      * Collect info on each device instance.
    661      */
    662     struct DEVORDER
    663     {
    664         /** Configuration node. */
    665         PCFGMNODE   pNode;
    666         /** Pointer to device. */
    667         PPDMDEV     pDev;
    668         /** Init order. */
    669         uint32_t    u32Order;
    670         /** VBox instance number. */
    671         uint32_t    iInstance;
    672     } *paDevs = (struct DEVORDER *)alloca(sizeof(paDevs[0]) * (cDevs + 1)); /* (One extra for swapping) */
    673     Assert(paDevs);
    674     unsigned i = 0;
    675     for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
    676     {
    677         /* Get the device name. */
    678         char szName[sizeof(paDevs[0].pDev->pDevReg->szDeviceName)];
    679         rc = CFGMR3GetName(pCur, szName, sizeof(szName));
    680         AssertMsgRCReturn(rc, ("Configuration error: device name is too long (or something)! rc=%Vrc\n", rc), rc);
    681 
    682         /* Find the device. */
    683         PPDMDEV pDev = pdmR3DevLookup(pVM, szName);
    684         AssertMsgReturn(pDev, ("Configuration error: device '%s' not found!\n", szName), VERR_PDM_DEVICE_NOT_FOUND);
    685 
    686         /* Configured priority or use default based on device class? */
    687         uint32_t u32Order;
    688         rc = CFGMR3QueryU32(pCur, "Priority", &u32Order);
    689         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    690         {
    691             uint32_t u32 = pDev->pDevReg->fClass;
    692             for (u32Order = 1; !(u32 & u32Order); u32Order <<= 1)
    693                 /* nop */;
    694         }
    695         else
    696             AssertMsgRCReturn(rc, ("Configuration error: reading \"Priority\" for the '%s' device failed rc=%Vrc!\n", szName, rc), rc);
    697 
    698         /* Enumerate the device instances. */
    699         for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
    700         {
    701             paDevs[i].pNode = pInstanceNode;
    702             paDevs[i].pDev = pDev;
    703             paDevs[i].u32Order = u32Order;
    704 
    705             /* Get the instance number. */
    706             char szInstance[32];
    707             rc = CFGMR3GetName(pInstanceNode, szInstance, sizeof(szInstance));
    708             AssertMsgRCReturn(rc, ("Configuration error: instance name is too long (or something)! rc=%Vrc\n", rc), rc);
    709             char *pszNext = NULL;
    710             rc = RTStrToUInt32Ex(szInstance, &pszNext, 0, &paDevs[i].iInstance);
    711             AssertMsgRCReturn(rc, ("Configuration error: RTStrToInt32Ex failed on the instance name '%s'! rc=%Vrc\n", szInstance, rc), rc);
    712             AssertMsgReturn(!*pszNext, ("Configuration error: the instance name '%s' isn't all digits. (%s)\n", szInstance, pszNext), VERR_INVALID_PARAMETER);
    713 
    714             /* next instance */
    715             i++;
    716         }
    717     } /* devices */
    718     Assert(i == cDevs);
    719 
    720     /*
    721      * Sort the device array ascending on u32Order. (bubble)
    722      */
    723     unsigned c = cDevs - 1;
    724     while (c)
    725     {
    726         unsigned j = 0;
    727         for (i = 0; i < c; i++)
    728             if (paDevs[i].u32Order > paDevs[i + 1].u32Order)
    729             {
    730                 paDevs[cDevs] = paDevs[i + 1];
    731                 paDevs[i + 1] = paDevs[i];
    732                 paDevs[i] = paDevs[cDevs];
    733                 j = i;
    734             }
    735         c = j;
    736     }
    737 
    738 
    739     /*
    740      *
    741      * Instantiate the devices.
    742      *
    743      */
    744     for (i = 0; i < cDevs; i++)
    745     {
    746         /*
    747          * Gather a bit of config.
    748          */
    749         /* trusted */
    750         bool fTrusted;
    751         rc = CFGMR3QueryBool(paDevs[i].pNode, "Trusted", &fTrusted);
    752         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    753             fTrusted = false;
    754         else if (VBOX_FAILURE(rc))
    755         {
    756             AssertMsgFailed(("configuration error: failed to query boolean \"Trusted\", rc=%Vrc\n", rc));
    757             return rc;
    758         }
    759         /* config node */
    760         PCFGMNODE pConfigNode = CFGMR3GetChild(paDevs[i].pNode, "Config");
    761         if (!pConfigNode)
    762         {
    763             rc = CFGMR3InsertNode(paDevs[i].pNode, "Config", &pConfigNode);
    764             if (VBOX_FAILURE(rc))
    765             {
    766                 AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
    767                 return rc;
    768             }
    769         }
    770         CFGMR3SetRestrictedRoot(pConfigNode);
    771 
    772         /*
    773          * Allocate the device instance.
    774          */
    775         size_t cb = RT_OFFSETOF(PDMDEVINS, achInstanceData[paDevs[i].pDev->pDevReg->cbInstance]);
    776         cb = RT_ALIGN_Z(cb, 16);
    777         PPDMDEVINS pDevIns;
    778         if (paDevs[i].pDev->pDevReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0))
    779             rc = MMR3HyperAllocOnceNoRel(pVM, cb, 0, MM_TAG_PDM_DEVICE, (void **)&pDevIns);
    780         else
    781             rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_DEVICE, cb, (void **)&pDevIns);
    782         if (VBOX_FAILURE(rc))
    783         {
    784             AssertMsgFailed(("Failed to allocate %d bytes of instance data for device '%s'. rc=%Vrc\n",
    785                              cb, paDevs[i].pDev->pDevReg->szDeviceName, rc));
    786             return rc;
    787         }
    788 
    789         /*
    790          * Initialize it.
    791          */
    792         pDevIns->u32Version                     = PDM_DEVINS_VERSION;
    793         //pDevIns->Internal.s.pNextR3             = NULL;
    794         //pDevIns->Internal.s.pPerDeviceNextR3    = NULL;
    795         pDevIns->Internal.s.pDevR3              = paDevs[i].pDev;
    796         pDevIns->Internal.s.pVMR3               = pVM;
    797         pDevIns->Internal.s.pVMR0               = pVM->pVMR0;
    798         pDevIns->Internal.s.pVMRC               = pVM->pVMRC;
    799         //pDevIns->Internal.s.pLunsR3             = NULL;
    800         pDevIns->Internal.s.pCfgHandle          = paDevs[i].pNode;
    801         //pDevIns->Internal.s.pPciDeviceR3        = NULL;
    802         //pDevIns->Internal.s.pPciBusR3           = NULL; /** @todo pci bus selection. (in 2008 perhaps) */
    803         //pDevIns->Internal.s.pPciDeviceR0        = 0;
    804         //pDevIns->Internal.s.pPciBusR0           = 0;
    805         //pDevIns->Internal.s.pPciDeviceRC        = 0;
    806         //pDevIns->Internal.s.pPciBusRC           = 0;
    807         pDevIns->pDevHlpR3                      = fTrusted ? &g_pdmR3DevHlpTrusted : &g_pdmR3DevHlpUnTrusted;
    808         pDevIns->pDevHlpRC                      = pDevHlpRC;
    809         pDevIns->pDevHlpR0                      = pDevHlpR0;
    810         pDevIns->pDevReg                        = paDevs[i].pDev->pDevReg;
    811         pDevIns->pCfgHandle                     = pConfigNode;
    812         pDevIns->iInstance                      = paDevs[i].iInstance;
    813         pDevIns->pvInstanceDataR3               = &pDevIns->achInstanceData[0];
    814         pDevIns->pvInstanceDataRC               = pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC
    815                                                 ? MMHyperR3ToRC(pVM, pDevIns->pvInstanceDataR3) : NIL_RTRCPTR;
    816         pDevIns->pvInstanceDataR0               = pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0
    817                                                 ? MMHyperR3ToR0(pVM, pDevIns->pvInstanceDataR3) : NIL_RTR0PTR;
    818 
    819         /*
    820          * Link it into all the lists.
    821          */
    822         /* The global instance FIFO. */
    823         PPDMDEVINS pPrev1 = pVM->pdm.s.pDevInstances;
    824         if (!pPrev1)
    825             pVM->pdm.s.pDevInstances = pDevIns;
    826         else
    827         {
    828             while (pPrev1->Internal.s.pNextR3)
    829                 pPrev1 = pPrev1->Internal.s.pNextR3;
    830             pPrev1->Internal.s.pNextR3 = pDevIns;
    831         }
    832 
    833         /* The per device instance FIFO. */
    834         PPDMDEVINS pPrev2 = paDevs[i].pDev->pInstances;
    835         if (!pPrev2)
    836             paDevs[i].pDev->pInstances = pDevIns;
    837         else
    838         {
    839             while (pPrev2->Internal.s.pPerDeviceNextR3)
    840                 pPrev2 = pPrev2->Internal.s.pPerDeviceNextR3;
    841             pPrev2->Internal.s.pPerDeviceNextR3 = pDevIns;
    842         }
    843 
    844         /*
    845          * Call the constructor.
    846          */
    847         Log(("PDM: Constructing device '%s' instance %d...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    848         rc = pDevIns->pDevReg->pfnConstruct(pDevIns, pDevIns->iInstance, pDevIns->pCfgHandle);
    849         if (VBOX_FAILURE(rc))
    850         {
    851             LogRel(("PDM: Failed to construct '%s'/%d! %Vra\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    852             /* because we're damn lazy right now, we'll say that the destructor will be called even if the constructor fails. */
    853             return rc;
    854         }
    855     } /* for device instances */
    856 
    857 #ifdef VBOX_WITH_USB
    858     /* ditto for USB Devices. */
    859     rc = pdmR3UsbInstantiateDevices(pVM);
    860     if (RT_FAILURE(rc))
    861         return rc;
    862 #endif
    863 
    864 
    865     /*
    866      *
    867      * PCI BIOS Fake and Init Complete.
    868      *
    869      */
    870     if (pVM->pdm.s.aPciBuses[0].pDevInsR3)
    871     {
    872         pdmLock(pVM);
    873         rc = pVM->pdm.s.aPciBuses[0].pfnFakePCIBIOSR3(pVM->pdm.s.aPciBuses[0].pDevInsR3);
    874         pdmUnlock(pVM);
    875         if (VBOX_FAILURE(rc))
    876         {
    877             AssertMsgFailed(("PCI BIOS fake failed rc=%Vrc\n", rc));
    878             return rc;
    879         }
    880     }
    881 
    882     for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
    883     {
    884         if (pDevIns->pDevReg->pfnInitComplete)
    885         {
    886             rc = pDevIns->pDevReg->pfnInitComplete(pDevIns);
    887             if (VBOX_FAILURE(rc))
    888             {
    889                 AssertMsgFailed(("InitComplete on device '%s'/%d failed with rc=%Vrc\n",
    890                                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    891                 return rc;
    892             }
    893         }
    894     }
    895 
    896 #ifdef VBOX_WITH_USB
    897     /* ditto for USB Devices. */
    898     rc = pdmR3UsbVMInitComplete(pVM);
    899     if (RT_FAILURE(rc))
    900         return rc;
    901 #endif
    902 
    903     LogFlow(("pdmR3DevInit: returns %Vrc\n", VINF_SUCCESS));
    904     return VINF_SUCCESS;
    905 }
    906 
    907 
    908 /**
    909  * Lookups a device structure by name.
    910  * @internal
    911  */
    912 PPDMDEV pdmR3DevLookup(PVM pVM, const char *pszName)
    913 {
    914     RTUINT cchName = strlen(pszName);
    915     for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
    916         if (    pDev->cchName == cchName
    917             &&  !strcmp(pDev->pDevReg->szDeviceName, pszName))
    918             return pDev;
    919     return NULL;
    920 }
    921 
    922 
    923 /**
    924  * Loads the device modules.
    925  *
    926  * @returns VBox status code.
    927  * @param   pVM     Pointer to the shared VM structure.
    928  */
    929 static int pdmR3DevLoadModules(PVM pVM)
    930 {
    931     /*
    932      * Initialize the callback structure.
    933      */
    934     PDMDEVREGCBINT RegCB;
    935     RegCB.Core.u32Version = PDM_DEVREG_CB_VERSION;
    936     RegCB.Core.pfnRegister = pdmR3DevReg_Register;
    937     RegCB.Core.pfnMMHeapAlloc = pdmR3DevReg_MMHeapAlloc;
    938     RegCB.pVM = pVM;
    939 
    940     /*
    941      * Load the builtin module
    942      */
    943     PCFGMNODE pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Devices");
    944     bool fLoadBuiltin;
    945     int rc = CFGMR3QueryBool(pDevicesNode, "LoadBuiltin", &fLoadBuiltin);
    946     if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    947         fLoadBuiltin = true;
    948     else if (VBOX_FAILURE(rc))
    949     {
    950         AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Vrc\n", rc));
    951         return rc;
    952     }
    953     if (fLoadBuiltin)
    954     {
    955         /* make filename */
    956         char *pszFilename = pdmR3FileR3("VBoxDD", /* fShared = */ true);
    957         if (!pszFilename)
    958             return VERR_NO_TMP_MEMORY;
    959         rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD");
    960         RTMemTmpFree(pszFilename);
    961         if (VBOX_FAILURE(rc))
    962             return rc;
    963 
    964         /* make filename */
    965         pszFilename = pdmR3FileR3("VBoxDD2", /* fShared = */ true);
    966         if (!pszFilename)
    967             return VERR_NO_TMP_MEMORY;
    968         rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD2");
    969         RTMemTmpFree(pszFilename);
    970         if (VBOX_FAILURE(rc))
    971             return rc;
    972     }
    973 
    974     /*
    975      * Load additional device modules.
    976      */
    977     PCFGMNODE pCur;
    978     for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
    979     {
    980         /*
    981          * Get the name and path.
    982          */
    983         char szName[PDMMOD_NAME_LEN];
    984         rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
    985         if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
    986         {
    987             AssertMsgFailed(("configuration error: The module name is too long, cchName=%d.\n", CFGMR3GetNameLen(pCur)));
    988             return VERR_PDM_MODULE_NAME_TOO_LONG;
    989         }
    990         else if (VBOX_FAILURE(rc))
    991         {
    992             AssertMsgFailed(("CFGMR3GetName -> %Vrc.\n", rc));
    993             return rc;
    994         }
    995 
    996         /* the path is optional, if no path the module name + path is used. */
    997         char szFilename[RTPATH_MAX];
    998         rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
    999         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    1000             strcpy(szFilename, szName);
    1001         else if (VBOX_FAILURE(rc))
    1002         {
    1003             AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Vrc.\n", rc));
    1004             return rc;
    1005         }
    1006 
    1007         /* prepend path? */
    1008         if (!RTPathHavePath(szFilename))
    1009         {
    1010             char *psz = pdmR3FileR3(szFilename);
    1011             if (!psz)
    1012                 return VERR_NO_TMP_MEMORY;
    1013             size_t cch = strlen(psz) + 1;
    1014             if (cch > sizeof(szFilename))
    1015             {
    1016                 RTMemTmpFree(psz);
    1017                 AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
    1018                 return VERR_FILENAME_TOO_LONG;
    1019             }
    1020             memcpy(szFilename, psz, cch);
    1021             RTMemTmpFree(psz);
    1022         }
    1023 
    1024         /*
    1025          * Load the module and register it's devices.
    1026          */
    1027         rc = pdmR3DevLoad(pVM, &RegCB, szFilename, szName);
    1028         if (VBOX_FAILURE(rc))
    1029             return rc;
    1030     }
    1031 
    1032     return VINF_SUCCESS;
    1033 }
    1034 
    1035 
    1036 /**
    1037  * Loads one device module and call the registration entry point.
    1038  *
    1039  * @returns VBox status code.
    1040  * @param   pVM             VM handle.
    1041  * @param   pRegCB          The registration callback stuff.
    1042  * @param   pszFilename     Module filename.
    1043  * @param   pszName         Module name.
    1044  */
    1045 static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
    1046 {
    1047     /*
    1048      * Load it.
    1049      */
    1050     int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
    1051     if (VBOX_SUCCESS(rc))
    1052     {
    1053         /*
    1054          * Get the registration export and call it.
    1055          */
    1056         FNPDMVBOXDEVICESREGISTER *pfnVBoxDevicesRegister;
    1057         rc = PDMR3LdrGetSymbolR3(pVM, pszName, "VBoxDevicesRegister", (void **)&pfnVBoxDevicesRegister);
    1058         if (VBOX_SUCCESS(rc))
    1059         {
    1060             Log(("PDM: Calling VBoxDevicesRegister (%p) of %s (%s)\n", pfnVBoxDevicesRegister, pszName, pszFilename));
    1061             rc = pfnVBoxDevicesRegister(&pRegCB->Core, VBOX_VERSION);
    1062             if (VBOX_SUCCESS(rc))
    1063                 Log(("PDM: Successfully loaded device module %s (%s).\n", pszName, pszFilename));
    1064             else
    1065                 AssertMsgFailed(("VBoxDevicesRegister failed with rc=%Vrc for module %s (%s)\n", rc, pszName, pszFilename));
    1066         }
    1067         else
    1068         {
    1069             AssertMsgFailed(("Failed to locate 'VBoxDevicesRegister' in %s (%s) rc=%Vrc\n", pszName, pszFilename, rc));
    1070             if (rc == VERR_SYMBOL_NOT_FOUND)
    1071                 rc = VERR_PDM_NO_REGISTRATION_EXPORT;
    1072         }
    1073     }
    1074     else
    1075         AssertMsgFailed(("Failed to load %s %s!\n", pszFilename, pszName));
    1076     return rc;
    1077 }
    1078 
    1079 
    1080 
    1081 /**
    1082  * Registers a device with the current VM instance.
    1083  *
    1084  * @returns VBox status code.
    1085  * @param   pCallbacks      Pointer to the callback table.
    1086  * @param   pDevReg         Pointer to the device registration record.
    1087  *                          This data must be permanent and readonly.
    1088  */
    1089 static DECLCALLBACK(int) pdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pDevReg)
    1090 {
    1091     /*
    1092      * Validate the registration structure.
    1093      */
    1094     Assert(pDevReg);
    1095     if (pDevReg->u32Version != PDM_DEVREG_VERSION)
    1096     {
    1097         AssertMsgFailed(("Unknown struct version %#x!\n", pDevReg->u32Version));
    1098         return VERR_PDM_UNKNOWN_DEVREG_VERSION;
    1099     }
    1100     if (    !pDevReg->szDeviceName[0]
    1101         ||  strlen(pDevReg->szDeviceName) >= sizeof(pDevReg->szDeviceName))
    1102     {
    1103         AssertMsgFailed(("Invalid name '%s'\n", pDevReg->szDeviceName));
    1104         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1105     }
    1106     if (    (pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1107         &&  (   !pDevReg->szRCMod[0]
    1108              || strlen(pDevReg->szRCMod) >= sizeof(pDevReg->szRCMod)))
    1109     {
    1110         AssertMsgFailed(("Invalid GC module name '%s' - (Device %s)\n", pDevReg->szRCMod, pDevReg->szDeviceName));
    1111         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1112     }
    1113     if (    (pDevReg->fFlags & PDM_DEVREG_FLAGS_R0)
    1114         &&  (   !pDevReg->szR0Mod[0]
    1115              || strlen(pDevReg->szR0Mod) >= sizeof(pDevReg->szR0Mod)))
    1116     {
    1117         AssertMsgFailed(("Invalid R0 module name '%s' - (Device %s)\n", pDevReg->szR0Mod, pDevReg->szDeviceName));
    1118         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1119     }
    1120     if ((pDevReg->fFlags & PDM_DEVREG_FLAGS_HOST_BITS_MASK) != PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT)
    1121     {
    1122         AssertMsgFailed(("Invalid host bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
    1123         return VERR_PDM_INVALID_DEVICE_HOST_BITS;
    1124     }
    1125     if (!(pDevReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_MASK))
    1126     {
    1127         AssertMsgFailed(("Invalid guest bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
    1128         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1129     }
    1130     if (!pDevReg->fClass)
    1131     {
    1132         AssertMsgFailed(("No class! (Device %s)\n", pDevReg->szDeviceName));
    1133         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1134     }
    1135     if (pDevReg->cMaxInstances <= 0)
    1136     {
    1137         AssertMsgFailed(("Max instances %u! (Device %s)\n", pDevReg->cMaxInstances, pDevReg->szDeviceName));
    1138         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1139     }
    1140     if (pDevReg->cbInstance > (RTUINT)(pDevReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0)  ? 96 * _1K : _1M))
    1141     {
    1142         AssertMsgFailed(("Instance size %d bytes! (Device %s)\n", pDevReg->cbInstance, pDevReg->szDeviceName));
    1143         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1144     }
    1145     if (!pDevReg->pfnConstruct)
    1146     {
    1147         AssertMsgFailed(("No constructore! (Device %s)\n", pDevReg->szDeviceName));
    1148         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1149     }
    1150     /* Check matching guest bits last without any asserting. Enables trial and error registration. */
    1151     if (!(pDevReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT))
    1152     {
    1153         Log(("PDM: Rejected device '%s' because it didn't match the guest bits.\n", pDevReg->szDeviceName));
    1154         return VERR_PDM_INVALID_DEVICE_GUEST_BITS;
    1155     }
    1156     AssertLogRelMsg(pDevReg->u32VersionEnd == PDM_DEVREG_VERSION,
    1157                     ("u32VersionEnd=%#x, expected %#x. (szDeviceName=%s)\n",
    1158                      pDevReg->u32VersionEnd, PDM_DEVREG_VERSION, pDevReg->szDeviceName));
    1159 
    1160     /*
    1161      * Check for duplicate and find FIFO entry at the same time.
    1162      */
    1163     PCPDMDEVREGCBINT pRegCB = (PCPDMDEVREGCBINT)pCallbacks;
    1164     PPDMDEV pDevPrev = NULL;
    1165     PPDMDEV pDev = pRegCB->pVM->pdm.s.pDevs;
    1166     for (; pDev; pDevPrev = pDev, pDev = pDev->pNext)
    1167     {
    1168         if (!strcmp(pDev->pDevReg->szDeviceName, pDevReg->szDeviceName))
    1169         {
    1170             AssertMsgFailed(("Device '%s' already exists\n", pDevReg->szDeviceName));
    1171             return VERR_PDM_DEVICE_NAME_CLASH;
    1172         }
    1173     }
    1174 
    1175     /*
    1176      * Allocate new device structure and insert it into the list.
    1177      */
    1178     pDev = (PPDMDEV)MMR3HeapAlloc(pRegCB->pVM, MM_TAG_PDM_DEVICE, sizeof(*pDev));
    1179     if (pDev)
    1180     {
    1181         pDev->pNext = NULL;
    1182         pDev->cInstances = 0;
    1183         pDev->pInstances = NULL;
    1184         pDev->pDevReg = pDevReg;
    1185         pDev->cchName = strlen(pDevReg->szDeviceName);
    1186 
    1187         if (pDevPrev)
    1188             pDevPrev->pNext = pDev;
    1189         else
    1190             pRegCB->pVM->pdm.s.pDevs = pDev;
    1191         Log(("PDM: Registered device '%s'\n", pDevReg->szDeviceName));
    1192         return VINF_SUCCESS;
    1193     }
    1194     return VERR_NO_MEMORY;
    1195 }
    1196 
    1197 
    1198 /**
    1199  * Allocate memory which is associated with current VM instance
    1200  * and automatically freed on it's destruction.
    1201  *
    1202  * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
    1203  * @param   pCallbacks      Pointer to the callback table.
    1204  * @param   cb              Number of bytes to allocate.
    1205  */
    1206 static DECLCALLBACK(void *) pdmR3DevReg_MMHeapAlloc(PPDMDEVREGCB pCallbacks, size_t cb)
    1207 {
    1208     Assert(pCallbacks);
    1209     Assert(pCallbacks->u32Version == PDM_DEVREG_CB_VERSION);
    1210 
    1211     void *pv = MMR3HeapAlloc(((PPDMDEVREGCBINT)pCallbacks)->pVM, MM_TAG_PDM_DEVICE_USER, cb);
    1212     LogFlow(("pdmR3DevReg_MMHeapAlloc(,%#zx): returns %p\n", cb, pv));
    1213     return pv;
    1214 }
    1215 
    1216 
    1217 
    1218 
    1219 
    1220 /*
    1221  *
    1222  *
    1223  *
    1224  *
    1225  *   p d m R 3 D e v H l p
    1226  *   p d m R 3 D e v H l p
    1227  *   p d m R 3 D e v H l p
    1228  *
    1229  *
    1230  *
    1231  *
    1232  */
    1233 
    12343118
    12353119/**
     
    12413125 * @param   pItem       The item to consume. Upon return this item will be freed.
    12423126 */
    1243 static DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
     3127DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
    12443128{
    12453129    PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
     
    12663150}
    12673151
    1268 
    1269 /** @copydoc PDMDEVHLPR3::pfnIOPortRegister */
    1270 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
    1271                                                     PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
    1272 {
    1273     PDMDEV_ASSERT_DEVINS(pDevIns);
    1274     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->pDevReg->szDeviceName, pDevIns->iInstance,
    1275              Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
    1276     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1277 
    1278     int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
    1279 
    1280     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1281     return rc;
    1282 }
    1283 
    1284 
    1285 /** @copydoc PDMDEVHLPR3::pfnIOPortRegisterGC */
    1286 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTRCPTR pvUser,
    1287                                                       const char *pszOut, const char *pszIn,
    1288                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    1289 {
    1290     PDMDEV_ASSERT_DEVINS(pDevIns);
    1291     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1292     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1293              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    1294 
    1295     /*
    1296      * Resolve the functions (one of the can be NULL).
    1297      */
    1298     int rc = VINF_SUCCESS;
    1299     if (    pDevIns->pDevReg->szRCMod[0]
    1300         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    1301     {
    1302         RTGCPTR32 GCPtrIn = 0;
    1303         if (pszIn)
    1304         {
    1305             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszIn, &GCPtrIn);
    1306             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szRCMod, pszIn));
    1307         }
    1308         RTGCPTR32 GCPtrOut = 0;
    1309         if (pszOut && VBOX_SUCCESS(rc))
    1310         {
    1311             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOut, &GCPtrOut);
    1312             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szRCMod, pszOut));
    1313         }
    1314         RTGCPTR32 GCPtrInStr = 0;
    1315         if (pszInStr && VBOX_SUCCESS(rc))
    1316         {
    1317             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszInStr, &GCPtrInStr);
    1318             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szRCMod, pszInStr));
    1319         }
    1320         RTGCPTR32 GCPtrOutStr = 0;
    1321         if (pszOutStr && VBOX_SUCCESS(rc))
    1322         {
    1323             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOutStr, &GCPtrOutStr);
    1324             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szRCMod, pszOutStr));
    1325         }
    1326 
    1327         if (VBOX_SUCCESS(rc))
    1328             rc = IOMR3IOPortRegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc);
    1329     }
    1330     else
    1331     {
    1332         AssertMsgFailed(("No GC module for this driver!\n"));
    1333         rc = VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     LogFlow(("pdmR3DevHlp_IOPortRegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1337     return rc;
    1338 }
    1339 
    1340 
    1341 /** @copydoc PDMDEVHLPR3::pfnIOPortRegisterR0 */
    1342 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser,
    1343                                                       const char *pszOut, const char *pszIn,
    1344                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    1345 {
    1346     PDMDEV_ASSERT_DEVINS(pDevIns);
    1347     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1348     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1349              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    1350 
    1351     /*
    1352      * Resolve the functions (one of the can be NULL).
    1353      */
    1354     int rc = VINF_SUCCESS;
    1355     if (    pDevIns->pDevReg->szR0Mod[0]
    1356         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    1357     {
    1358         R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;
    1359         if (pszIn)
    1360         {
    1361             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszIn, &pfnR0PtrIn);
    1362             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szR0Mod, pszIn));
    1363         }
    1364         R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;
    1365         if (pszOut && VBOX_SUCCESS(rc))
    1366         {
    1367             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOut, &pfnR0PtrOut);
    1368             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szR0Mod, pszOut));
    1369         }
    1370         R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;
    1371         if (pszInStr && VBOX_SUCCESS(rc))
    1372         {
    1373             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszInStr, &pfnR0PtrInStr);
    1374             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szR0Mod, pszInStr));
    1375         }
    1376         R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;
    1377         if (pszOutStr && VBOX_SUCCESS(rc))
    1378         {
    1379             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOutStr, &pfnR0PtrOutStr);
    1380             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szR0Mod, pszOutStr));
    1381         }
    1382 
    1383         if (VBOX_SUCCESS(rc))
    1384             rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
    1385     }
    1386     else
    1387     {
    1388         AssertMsgFailed(("No R0 module for this driver!\n"));
    1389         rc = VERR_INVALID_PARAMETER;
    1390     }
    1391 
    1392     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1393     return rc;
    1394 }
    1395 
    1396 
    1397 /** @copydoc PDMDEVHLPR3::pfnIOPortDeregister */
    1398 static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts)
    1399 {
    1400     PDMDEV_ASSERT_DEVINS(pDevIns);
    1401     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1402     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1403              Port, cPorts));
    1404 
    1405     int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts);
    1406 
    1407     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1408     return rc;
    1409 }
    1410 
    1411 
    1412 /** @copydoc PDMDEVHLPR3::pfnMMIORegister */
    1413 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
    1414                                                   PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
    1415                                                   const char *pszDesc)
    1416 {
    1417     PDMDEV_ASSERT_DEVINS(pDevIns);
    1418     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1419     LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p pszDesc=%p:{%s}\n",
    1420              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc, pszDesc));
    1421 
    1422     int rc = IOMR3MMIORegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc);
    1423 
    1424     LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1425     return rc;
    1426 }
    1427 
    1428 
    1429 /** @copydoc PDMDEVHLPR3::pfnMMIORegisterGC */
    1430 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
    1431                                                     const char *pszWrite, const char *pszRead, const char *pszFill,
    1432                                                     const char *pszDesc)
    1433 {
    1434     PDMDEV_ASSERT_DEVINS(pDevIns);
    1435     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1436     LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
    1437              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
    1438 
    1439     /*
    1440      * Resolve the functions.
    1441      * Not all function have to present, leave it to IOM to enforce this.
    1442      */
    1443     int rc = VINF_SUCCESS;
    1444     if (    pDevIns->pDevReg->szRCMod[0]
    1445         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    1446     {
    1447         RTGCPTR32 GCPtrWrite = 0;
    1448         if (pszWrite)
    1449             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszWrite, &GCPtrWrite);
    1450         RTGCPTR32 GCPtrRead = 0;
    1451         int rc2 = VINF_SUCCESS;
    1452         if (pszRead)
    1453             rc2 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszRead, &GCPtrRead);
    1454         RTGCPTR32 GCPtrFill = 0;
    1455         int rc3 = VINF_SUCCESS;
    1456         if (pszFill)
    1457             rc3 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszFill, &GCPtrFill);
    1458         if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1459             rc = IOMR3MMIORegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill);
    1460         else
    1461         {
    1462             AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szRCMod, pszWrite));
    1463             AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szRCMod, pszRead));
    1464             AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szRCMod, pszFill));
    1465             if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
    1466                 rc = rc2;
    1467             if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
    1468                 rc = rc3;
    1469         }
    1470     }
    1471     else
    1472     {
    1473         AssertMsgFailed(("No GC module for this driver!\n"));
    1474         rc = VERR_INVALID_PARAMETER;
    1475     }
    1476 
    1477     LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1478     return rc;
    1479 }
    1480 
    1481 /** @copydoc PDMDEVHLPR3::pfnMMIORegisterR0 */
    1482 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
    1483                                                     const char *pszWrite, const char *pszRead, const char *pszFill,
    1484                                                     const char *pszDesc)
    1485 {
    1486     PDMDEV_ASSERT_DEVINS(pDevIns);
    1487     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1488     LogFlow(("pdmR3DevHlp_MMIORegisterHC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
    1489              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
    1490 
    1491     /*
    1492      * Resolve the functions.
    1493      * Not all function have to present, leave it to IOM to enforce this.
    1494      */
    1495     int rc = VINF_SUCCESS;
    1496     if (    pDevIns->pDevReg->szR0Mod[0]
    1497         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    1498     {
    1499         R0PTRTYPE(PFNIOMMMIOWRITE) pfnR0PtrWrite = 0;
    1500         if (pszWrite)
    1501             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszWrite, &pfnR0PtrWrite);
    1502         R0PTRTYPE(PFNIOMMMIOREAD) pfnR0PtrRead = 0;
    1503         int rc2 = VINF_SUCCESS;
    1504         if (pszRead)
    1505             rc2 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszRead, &pfnR0PtrRead);
    1506         R0PTRTYPE(PFNIOMMMIOFILL) pfnR0PtrFill = 0;
    1507         int rc3 = VINF_SUCCESS;
    1508         if (pszFill)
    1509             rc3 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill);
    1510         if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1511             rc = IOMR3MMIORegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill);
    1512         else
    1513         {
    1514             AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szR0Mod, pszWrite));
    1515             AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szR0Mod, pszRead));
    1516             AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szR0Mod, pszFill));
    1517             if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
    1518                 rc = rc2;
    1519             if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
    1520                 rc = rc3;
    1521         }
    1522     }
    1523     else
    1524     {
    1525         AssertMsgFailed(("No R0 module for this driver!\n"));
    1526         rc = VERR_INVALID_PARAMETER;
    1527     }
    1528 
    1529     LogFlow(("pdmR3DevHlp_MMIORegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1530     return rc;
    1531 }
    1532 
    1533 
    1534 /** @copydoc PDMDEVHLPR3::pfnMMIODeregister */
    1535 static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    1536 {
    1537     PDMDEV_ASSERT_DEVINS(pDevIns);
    1538     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1539     LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
    1540              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
    1541 
    1542     int rc = IOMR3MMIODeregister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange);
    1543 
    1544     LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1545     return rc;
    1546 }
    1547 
    1548 
    1549 /** @copydoc PDMDEVHLPR3::pfnROMRegister */
    1550 static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc)
    1551 {
    1552     PDMDEV_ASSERT_DEVINS(pDevIns);
    1553     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1554     LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvBinary=%p fShadow=%RTbool pszDesc=%p:{%s}\n",
    1555              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc, pszDesc));
    1556 
    1557     int rc = MMR3PhysRomRegister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc);
    1558 
    1559     LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1560     return rc;
    1561 }
    1562 
    1563 
    1564 /** @copydoc PDMDEVHLPR3::pfnSSMRegister */
    1565 static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
    1566                                                  PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
    1567                                                  PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
    1568 {
    1569     PDMDEV_ASSERT_DEVINS(pDevIns);
    1570     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1571     LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: pszName=%p:{%s} u32Instance=%#x u32Version=#x cbGuess=%#x pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoaddone=%p\n",
    1572              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
    1573 
    1574     int rc = SSMR3Register(pDevIns->Internal.s.pVMR3, pDevIns, pszName, u32Instance, u32Version, cbGuess,
    1575                            pfnSavePrep, pfnSaveExec, pfnSaveDone,
    1576                            pfnLoadPrep, pfnLoadExec, pfnLoadDone);
    1577 
    1578     LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1579     return rc;
    1580 }
    1581 
    1582 
    1583 /** @copydoc PDMDEVHLPR3::pfnTMTimerCreate */
    1584 static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
    1585 {
    1586     PDMDEV_ASSERT_DEVINS(pDevIns);
    1587     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1588     LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
    1589              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
    1590 
    1591     int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
    1592 
    1593     LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1594     return rc;
    1595 }
    1596 
    1597 
    1598 /** @copydoc PDMDEVHLPR3::pfnTMTimerCreateExternal */
    1599 static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc)
    1600 {
    1601     PDMDEV_ASSERT_DEVINS(pDevIns);
    1602     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1603 
    1604     return TMR3TimerCreateExternal(pDevIns->Internal.s.pVMR3, enmClock, pfnCallback, pvUser, pszDesc);
    1605 }
    1606 
    1607 /** @copydoc PDMDEVHLPR3::pfnPCIRegister */
    1608 static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev)
    1609 {
    1610     PDMDEV_ASSERT_DEVINS(pDevIns);
    1611     PVM pVM = pDevIns->Internal.s.pVMR3;
    1612     VM_ASSERT_EMT(pVM);
    1613     LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Vhxs}\n",
    1614              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pPciDev->config));
    1615 
    1616     /*
    1617      * Validate input.
    1618      */
    1619     if (!pPciDev)
    1620     {
    1621         Assert(pPciDev);
    1622         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (pPciDev)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1623         return VERR_INVALID_PARAMETER;
    1624     }
    1625     if (!pPciDev->config[0] && !pPciDev->config[1])
    1626     {
    1627         Assert(pPciDev->config[0] || pPciDev->config[1]);
    1628         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (vendor)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1629         return VERR_INVALID_PARAMETER;
    1630     }
    1631     if (pDevIns->Internal.s.pPciDeviceR3)
    1632     {
    1633         /** @todo the PCI device vs. PDM device designed is a bit flawed if we have to
    1634          * support a PDM device with multiple PCI devices. This might become a problem
    1635          * when upgrading the chipset for instance...
    1636          */
    1637         AssertMsgFailed(("Only one PCI device per device is currently implemented!\n"));
    1638         return VERR_INTERNAL_ERROR;
    1639     }
    1640 
    1641     /*
    1642      * Choose the PCI bus for the device.
    1643      * This is simple. If the device was configured for a particular bus, it'll
    1644      * already have one. If not, we'll just take the first one.
    1645      */
    1646     PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1647     if (!pBus)
    1648         pBus = pDevIns->Internal.s.pPciBusR3 = &pVM->pdm.s.aPciBuses[0];
    1649     int rc;
    1650     if (pBus)
    1651     {
    1652         if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1653             pDevIns->Internal.s.pPciBusR0 = MMHyperR3ToR0(pVM, pDevIns->Internal.s.pPciBusR3);
    1654         else
    1655             pDevIns->Internal.s.pPciBusR0 = NIL_RTR0PTR;
    1656 
    1657         if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1658             pDevIns->Internal.s.pPciBusRC = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciBusR3);
    1659         else
    1660             pDevIns->Internal.s.pPciBusRC = NIL_RTRCPTR;
    1661 
    1662         /*
    1663          * Check the configuration for PCI device and function assignment.
    1664          */
    1665         int iDev = -1;
    1666         uint8_t     u8Device;
    1667         rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIDeviceNo", &u8Device);
    1668         if (VBOX_SUCCESS(rc))
    1669         {
    1670             if (u8Device > 31)
    1671             {
    1672                 AssertMsgFailed(("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d)\n",
    1673                                  u8Device, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1674                 return VERR_INTERNAL_ERROR;
    1675             }
    1676 
    1677             uint8_t     u8Function;
    1678             rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIFunctionNo", &u8Function);
    1679             if (VBOX_FAILURE(rc))
    1680             {
    1681                 AssertMsgFailed(("Configuration error: PCIDeviceNo, but PCIFunctionNo query failed with rc=%Vrc (%s/%d)\n",
    1682                                  rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1683                 return rc;
    1684             }
    1685             if (u8Function > 7)
    1686             {
    1687                 AssertMsgFailed(("Configuration error: PCIFunctionNo=%d, max is 7. (%s/%d)\n",
    1688                                  u8Function, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1689                 return VERR_INTERNAL_ERROR;
    1690             }
    1691             iDev = (u8Device << 3) | u8Function;
    1692         }
    1693         else if (rc != VERR_CFGM_VALUE_NOT_FOUND)
    1694         {
    1695             AssertMsgFailed(("Configuration error: PCIDeviceNo query failed with rc=%Vrc (%s/%d)\n",
    1696                              rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1697             return rc;
    1698         }
    1699 
    1700         /*
    1701          * Call the pci bus device to do the actual registration.
    1702          */
    1703         pdmLock(pVM);
    1704         rc = pBus->pfnRegisterR3(pBus->pDevInsR3, pPciDev, pDevIns->pDevReg->szDeviceName, iDev);
    1705         pdmUnlock(pVM);
    1706         if (VBOX_SUCCESS(rc))
    1707         {
    1708             pPciDev->pDevIns = pDevIns;
    1709 
    1710             pDevIns->Internal.s.pPciDeviceR3 = pPciDev;
    1711             if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0)
    1712                 pDevIns->Internal.s.pPciDeviceR0 = MMHyperR3ToR0(pVM, pPciDev);
    1713             else
    1714                 pDevIns->Internal.s.pPciDeviceR0 = NIL_RTR0PTR;
    1715 
    1716             if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1717                 pDevIns->Internal.s.pPciDeviceRC = MMHyperR3ToRC(pVM, pPciDev);
    1718             else
    1719                 pDevIns->Internal.s.pPciDeviceRC = NIL_RTRCPTR;
    1720 
    1721             Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
    1722                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev->devfn, pDevIns->Internal.s.pPciBusR3->iBus));
    1723         }
    1724     }
    1725     else
    1726     {
    1727         AssertMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
    1728         rc = VERR_PDM_NO_PCI_BUS;
    1729     }
    1730 
    1731     LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1732     return rc;
    1733 }
    1734 
    1735 
    1736 /** @copydoc PDMDEVHLPR3::pfnPCIIORegionRegister */
    1737 static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
    1738 {
    1739     PDMDEV_ASSERT_DEVINS(pDevIns);
    1740     PVM pVM = pDevIns->Internal.s.pVMR3;
    1741     VM_ASSERT_EMT(pVM);
    1742     LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: iRegion=%d cbRegion=%#x enmType=%d pfnCallback=%p\n",
    1743              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cbRegion, enmType, pfnCallback));
    1744 
    1745     /*
    1746      * Validate input.
    1747      */
    1748     if (iRegion < 0 || iRegion >= PCI_NUM_REGIONS)
    1749     {
    1750         Assert(iRegion >= 0 && iRegion < PCI_NUM_REGIONS);
    1751         LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (iRegion)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1752         return VERR_INVALID_PARAMETER;
    1753     }
    1754     switch (enmType)
    1755     {
    1756         case PCI_ADDRESS_SPACE_MEM:
    1757         case PCI_ADDRESS_SPACE_IO:
    1758         case PCI_ADDRESS_SPACE_MEM_PREFETCH:
    1759             break;
    1760         default:
    1761             AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
    1762             LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (enmType)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1763             return VERR_INVALID_PARAMETER;
    1764     }
    1765     if (!pfnCallback)
    1766     {
    1767         Assert(pfnCallback);
    1768         LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (callback)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1769         return VERR_INVALID_PARAMETER;
    1770     }
    1771     AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
    1772 
    1773     /*
    1774      * Must have a PCI device registered!
    1775      */
    1776     int rc;
    1777     PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1778     if (pPciDev)
    1779     {
    1780         /*
    1781          * We're currently restricted to page aligned MMIO regions.
    1782          */
    1783         if (    (enmType == PCI_ADDRESS_SPACE_MEM || enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH)
    1784             &&  cbRegion != RT_ALIGN_32(cbRegion, PAGE_SIZE))
    1785         {
    1786             Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %#x -> %#x\n",
    1787                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbRegion, RT_ALIGN_32(cbRegion, PAGE_SIZE)));
    1788             cbRegion = RT_ALIGN_32(cbRegion, PAGE_SIZE);
    1789         }
    1790 
    1791         PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1792         Assert(pBus);
    1793         pdmLock(pVM);
    1794         rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
    1795         pdmUnlock(pVM);
    1796     }
    1797     else
    1798     {
    1799         AssertMsgFailed(("No PCI device registered!\n"));
    1800         rc = VERR_PDM_NOT_PCI_DEVICE;
    1801     }
    1802 
    1803     LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1804     return rc;
    1805 }
    1806 
    1807 
    1808 /** @copydoc PDMDEVHLPR3::pfnPCISetConfigCallbacks */
    1809 static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
    1810                                                             PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
    1811 {
    1812     PDMDEV_ASSERT_DEVINS(pDevIns);
    1813     PVM pVM = pDevIns->Internal.s.pVMR3;
    1814     VM_ASSERT_EMT(pVM);
    1815     LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
    1816              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
    1817 
    1818     /*
    1819      * Validate input and resolve defaults.
    1820      */
    1821     AssertPtr(pfnRead);
    1822     AssertPtr(pfnWrite);
    1823     AssertPtrNull(ppfnReadOld);
    1824     AssertPtrNull(ppfnWriteOld);
    1825     AssertPtrNull(pPciDev);
    1826 
    1827     if (!pPciDev)
    1828         pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1829     AssertReleaseMsg(pPciDev, ("You must register your device first!\n"));
    1830     PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1831     AssertRelease(pBus);
    1832     AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
    1833 
    1834     /*
    1835      * Do the job.
    1836      */
    1837     pdmLock(pVM);
    1838     pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
    1839     pdmUnlock(pVM);
    1840 
    1841     LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1842 }
    1843 
    1844 
    1845 /** @copydoc PDMDEVHLPR3::pfnPCISetIrq */
    1846 static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1847 {
    1848     PDMDEV_ASSERT_DEVINS(pDevIns);
    1849     LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
    1850 
    1851     /*
    1852      * Validate input.
    1853      */
    1854     /** @todo iIrq and iLevel checks. */
    1855 
    1856     /*
    1857      * Must have a PCI device registered!
    1858      */
    1859     PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1860     if (pPciDev)
    1861     {
    1862         PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3; /** @todo the bus should be associated with the PCI device not the PDM device. */
    1863         Assert(pBus);
    1864         PVM pVM = pDevIns->Internal.s.pVMR3;
    1865         pdmLock(pVM);
    1866         pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
    1867         pdmUnlock(pVM);
    1868     }
    1869     else
    1870         AssertReleaseMsgFailed(("No PCI device registered!\n"));
    1871 
    1872     LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1873 }
    1874 
    1875 
    1876 /** @copydoc PDMDEVHLPR3::pfnPCISetIrqNoWait */
    1877 static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1878 {
    1879     pdmR3DevHlp_PCISetIrq(pDevIns, iIrq, iLevel);
    1880 }
    1881 
    1882 
    1883 /** @copydoc PDMDEVHLPR3::pfnISASetIrq */
    1884 static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1885 {
    1886     PDMDEV_ASSERT_DEVINS(pDevIns);
    1887     LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
    1888 
    1889     /*
    1890      * Validate input.
    1891      */
    1892     /** @todo iIrq and iLevel checks. */
    1893 
    1894     PVM pVM = pDevIns->Internal.s.pVMR3;
    1895     PDMIsaSetIrq(pVM, iIrq, iLevel);    /* (The API takes the lock.) */
    1896 
    1897     LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1898 }
    1899 
    1900 
    1901 /** @copydoc PDMDEVHLPR3::pfnISASetIrqNoWait */
    1902 static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1903 {
    1904     pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
    1905 }
    1906 
    1907 
    1908 /** @copydoc PDMDEVHLPR3::pfnDriverAttach */
    1909 static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
    1910 {
    1911     PDMDEV_ASSERT_DEVINS(pDevIns);
    1912     PVM pVM = pDevIns->Internal.s.pVMR3;
    1913     VM_ASSERT_EMT(pVM);
    1914     LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
    1915              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
    1916 
    1917     /*
    1918      * Lookup the LUN, it might already be registered.
    1919      */
    1920     PPDMLUN pLunPrev = NULL;
    1921     PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
    1922     for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
    1923         if (pLun->iLun == iLun)
    1924             break;
    1925 
    1926     /*
    1927      * Create the LUN if if wasn't found, else check if driver is already attached to it.
    1928      */
    1929     if (!pLun)
    1930     {
    1931         if (    !pBaseInterface
    1932             ||  !pszDesc
    1933             ||  !*pszDesc)
    1934         {
    1935             Assert(pBaseInterface);
    1936             Assert(pszDesc || *pszDesc);
    1937             return VERR_INVALID_PARAMETER;
    1938         }
    1939 
    1940         pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
    1941         if (!pLun)
    1942             return VERR_NO_MEMORY;
    1943 
    1944         pLun->iLun      = iLun;
    1945         pLun->pNext     = pLunPrev ? pLunPrev->pNext : NULL;
    1946         pLun->pTop      = NULL;
    1947         pLun->pBottom   = NULL;
    1948         pLun->pDevIns   = pDevIns;
    1949         pLun->pszDesc   = pszDesc;
    1950         pLun->pBase     = pBaseInterface;
    1951         if (!pLunPrev)
    1952             pDevIns->Internal.s.pLunsR3 = pLun;
    1953         else
    1954             pLunPrev->pNext = pLun;
    1955         Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
    1956              iLun, pszDesc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1957     }
    1958     else if (pLun->pTop)
    1959     {
    1960         AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
    1961         LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
    1962         return VERR_PDM_DRIVER_ALREADY_ATTACHED;
    1963     }
    1964     Assert(pLun->pBase == pBaseInterface);
    1965 
    1966 
    1967     /*
    1968      * Get the attached driver configuration.
    1969      */
    1970     int rc;
    1971     char szNode[48];
    1972     RTStrPrintf(szNode, sizeof(szNode), "LUN#%d", iLun);
    1973     PCFGMNODE   pNode = CFGMR3GetChild(pDevIns->Internal.s.pCfgHandle, szNode);
    1974     if (pNode)
    1975     {
    1976         char *pszName;
    1977         rc = CFGMR3QueryStringAlloc(pNode, "Driver", &pszName);
    1978         if (VBOX_SUCCESS(rc))
    1979         {
    1980             /*
    1981              * Find the driver.
    1982              */
    1983             PPDMDRV pDrv = pdmR3DrvLookup(pVM, pszName);
    1984             if (pDrv)
    1985             {
    1986                 /* config node */
    1987                 PCFGMNODE pConfigNode = CFGMR3GetChild(pNode, "Config");
    1988                 if (!pConfigNode)
    1989                     rc = CFGMR3InsertNode(pNode, "Config", &pConfigNode);
    1990                 if (VBOX_SUCCESS(rc))
    1991                 {
    1992                     CFGMR3SetRestrictedRoot(pConfigNode);
    1993 
    1994                     /*
    1995                      * Allocate the driver instance.
    1996                      */
    1997                     size_t cb = RT_OFFSETOF(PDMDRVINS, achInstanceData[pDrv->pDrvReg->cbInstance]);
    1998                     cb = RT_ALIGN_Z(cb, 16);
    1999                     PPDMDRVINS pNew = (PPDMDRVINS)MMR3HeapAllocZ(pVM, MM_TAG_PDM_DRIVER, cb);
    2000                     if (pNew)
    2001                     {
    2002                         /*
    2003                          * Initialize the instance structure (declaration order).
    2004                          */
    2005                         pNew->u32Version                = PDM_DRVINS_VERSION;
    2006                         //pNew->Internal.s.pUp            = NULL;
    2007                         //pNew->Internal.s.pDown          = NULL;
    2008                         pNew->Internal.s.pLun           = pLun;
    2009                         pNew->Internal.s.pDrv           = pDrv;
    2010                         pNew->Internal.s.pVM            = pVM;
    2011                         //pNew->Internal.s.fDetaching     = false;
    2012                         pNew->Internal.s.pCfgHandle     = pNode;
    2013                         pNew->pDrvHlp                   = &g_pdmR3DrvHlp;
    2014                         pNew->pDrvReg                   = pDrv->pDrvReg;
    2015                         pNew->pCfgHandle                = pConfigNode;
    2016                         pNew->iInstance                 = pDrv->cInstances++;
    2017                         pNew->pUpBase                   = pBaseInterface;
    2018                         //pNew->pDownBase                 = NULL;
    2019                         //pNew->IBase.pfnQueryInterface   = NULL;
    2020                         pNew->pvInstanceData            = &pNew->achInstanceData[0];
    2021 
    2022                         /*
    2023                          * Link with LUN and call the constructor.
    2024                          */
    2025                         pLun->pTop = pLun->pBottom = pNew;
    2026                         rc = pDrv->pDrvReg->pfnConstruct(pNew, pNew->pCfgHandle);
    2027                         if (VBOX_SUCCESS(rc))
    2028                         {
    2029                             MMR3HeapFree(pszName);
    2030                             *ppBaseInterface = &pNew->IBase;
    2031                             Log(("PDM: Attached driver '%s'/%d to LUN#%d on device '%s'/%d.\n",
    2032                                  pDrv->pDrvReg->szDriverName, pNew->iInstance, iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2033                             LogFlow(("pdmR3DevHlp_DriverAttach: caller '%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2034                             /*
    2035                              * Might return != VINF_SUCCESS (e.g. VINF_NAT_DNS) */
    2036                             return rc;
    2037                         }
    2038 
    2039                         /*
    2040                          * Free the driver.
    2041                          */
    2042                         pLun->pTop = pLun->pBottom = NULL;
    2043                         ASMMemFill32(pNew, cb, 0xdeadd0d0);
    2044                         MMR3HeapFree(pNew);
    2045                         pDrv->cInstances--;
    2046                     }
    2047                     else
    2048                     {
    2049                         AssertMsgFailed(("Failed to allocate %d bytes for instantiating driver '%s'\n", cb, pszName));
    2050                         rc = VERR_NO_MEMORY;
    2051                     }
    2052                 }
    2053                 else
    2054                     AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
    2055             }
    2056             else
    2057             {
    2058                 AssertMsgFailed(("Driver '%s' wasn't found!\n", pszName));
    2059                 rc = VERR_PDM_DRIVER_NOT_FOUND;
    2060             }
    2061             MMR3HeapFree(pszName);
    2062         }
    2063         else
    2064         {
    2065             AssertMsgFailed(("Query for string value of \"Driver\" -> %Vrc\n", rc));
    2066             if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    2067                 rc = VERR_PDM_CFG_MISSING_DRIVER_NAME;
    2068         }
    2069     }
    2070     else
    2071         rc = VERR_PDM_NO_ATTACHED_DRIVER;
    2072 
    2073 
    2074     LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2075     return rc;
    2076 }
    2077 
    2078 
    2079 /** @copydoc PDMDEVHLPR3::pfnMMHeapAlloc */
    2080 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
    2081 {
    2082     PDMDEV_ASSERT_DEVINS(pDevIns);
    2083     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
    2084 
    2085     void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
    2086 
    2087     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2088     return pv;
    2089 }
    2090 
    2091 
    2092 /** @copydoc PDMDEVHLPR3::pfnMMHeapAllocZ */
    2093 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
    2094 {
    2095     PDMDEV_ASSERT_DEVINS(pDevIns);
    2096     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
    2097 
    2098     void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
    2099 
    2100     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2101     return pv;
    2102 }
    2103 
    2104 
    2105 /** @copydoc PDMDEVHLPR3::pfnMMHeapFree */
    2106 static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
    2107 {
    2108     PDMDEV_ASSERT_DEVINS(pDevIns);
    2109     LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2110 
    2111     MMR3HeapFree(pv);
    2112 
    2113     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2114 }
    2115 
    2116 
    2117 /** @copydoc PDMDEVHLPR3::pfnVMSetError */
    2118 static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
    2119 {
    2120     PDMDEV_ASSERT_DEVINS(pDevIns);
    2121     va_list args;
    2122     va_start(args, pszFormat);
    2123     int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
    2124     va_end(args);
    2125     return rc;
    2126 }
    2127 
    2128 
    2129 /** @copydoc PDMDEVHLPR3::pfnVMSetErrorV */
    2130 static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
    2131 {
    2132     PDMDEV_ASSERT_DEVINS(pDevIns);
    2133     int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
    2134     return rc;
    2135 }
    2136 
    2137 
    2138 /** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeError */
    2139 static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...)
    2140 {
    2141     PDMDEV_ASSERT_DEVINS(pDevIns);
    2142     va_list args;
    2143     va_start(args, pszFormat);
    2144     int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, args);
    2145     va_end(args);
    2146     return rc;
    2147 }
    2148 
    2149 
    2150 /** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeErrorV */
    2151 static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va)
    2152 {
    2153     PDMDEV_ASSERT_DEVINS(pDevIns);
    2154     int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, va);
    2155     return rc;
    2156 }
    2157 
    2158 
    2159 /** @copydoc PDMDEVHLPR3::pfnAssertEMT */
    2160 static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    2161 {
    2162     PDMDEV_ASSERT_DEVINS(pDevIns);
    2163     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
    2164         return true;
    2165 
    2166     char szMsg[100];
    2167     RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
    2168     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    2169     AssertBreakpoint();
    2170     return false;
    2171 }
    2172 
    2173 
    2174 /** @copydoc PDMDEVHLPR3::pfnAssertOther */
    2175 static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    2176 {
    2177     PDMDEV_ASSERT_DEVINS(pDevIns);
    2178     if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
    2179         return true;
    2180 
    2181     char szMsg[100];
    2182     RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
    2183     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    2184     AssertBreakpoint();
    2185     return false;
    2186 }
    2187 
    2188 
    2189 /** @copydoc PDMDEVHLPR3::pfnDBGFStopV */
    2190 static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
    2191 {
    2192     PDMDEV_ASSERT_DEVINS(pDevIns);
    2193 #ifdef LOG_ENABLED
    2194     va_list va2;
    2195     va_copy(va2, args);
    2196     LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
    2197              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
    2198     va_end(va2);
    2199 #endif
    2200 
    2201     PVM pVM = pDevIns->Internal.s.pVMR3;
    2202     VM_ASSERT_EMT(pVM);
    2203     int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
    2204 
    2205     LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2206     return rc;
    2207 }
    2208 
    2209 
    2210 /** @copydoc PDMDEVHLPR3::pfnDBGFInfoRegister */
    2211 static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
    2212 {
    2213     PDMDEV_ASSERT_DEVINS(pDevIns);
    2214     LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
    2215              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
    2216 
    2217     PVM pVM = pDevIns->Internal.s.pVMR3;
    2218     VM_ASSERT_EMT(pVM);
    2219     int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
    2220 
    2221     LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2222     return rc;
    2223 }
    2224 
    2225 
    2226 /** @copydoc PDMDEVHLPR3::pfnSTAMRegister */
    2227 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
    2228 {
    2229     PDMDEV_ASSERT_DEVINS(pDevIns);
    2230     PVM pVM = pDevIns->Internal.s.pVMR3;
    2231     VM_ASSERT_EMT(pVM);
    2232 
    2233     STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
    2234     NOREF(pVM);
    2235 }
    2236 
    2237 
    2238 
    2239 /** @copydoc PDMDEVHLPR3::pfnSTAMRegisterF */
    2240 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    2241                                                     STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
    2242 {
    2243     PDMDEV_ASSERT_DEVINS(pDevIns);
    2244     PVM pVM = pDevIns->Internal.s.pVMR3;
    2245     VM_ASSERT_EMT(pVM);
    2246 
    2247     va_list args;
    2248     va_start(args, pszName);
    2249     int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    2250     va_end(args);
    2251     AssertRC(rc);
    2252 
    2253     NOREF(pVM);
    2254 }
    2255 
    2256 
    2257 /** @copydoc PDMDEVHLPR3::pfnSTAMRegisterV */
    2258 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    2259                                                     STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
    2260 {
    2261     PDMDEV_ASSERT_DEVINS(pDevIns);
    2262     PVM pVM = pDevIns->Internal.s.pVMR3;
    2263     VM_ASSERT_EMT(pVM);
    2264 
    2265     int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    2266     AssertRC(rc);
    2267 
    2268     NOREF(pVM);
    2269 }
    2270 
    2271 
    2272 /** @copydoc PDMDEVHLPR3::pfnRTCRegister */
    2273 static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
    2274 {
    2275     PDMDEV_ASSERT_DEVINS(pDevIns);
    2276     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2277     LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
    2278              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
    2279              pRtcReg->pfnWrite, ppRtcHlp));
    2280 
    2281     /*
    2282      * Validate input.
    2283      */
    2284     if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
    2285     {
    2286         AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
    2287                          PDM_RTCREG_VERSION));
    2288         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (version)\n",
    2289                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2290         return VERR_INVALID_PARAMETER;
    2291     }
    2292     if (    !pRtcReg->pfnWrite
    2293         ||  !pRtcReg->pfnRead)
    2294     {
    2295         Assert(pRtcReg->pfnWrite);
    2296         Assert(pRtcReg->pfnRead);
    2297         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
    2298                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2299         return VERR_INVALID_PARAMETER;
    2300     }
    2301 
    2302     if (!ppRtcHlp)
    2303     {
    2304         Assert(ppRtcHlp);
    2305         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (ppRtcHlp)\n",
    2306                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2307         return VERR_INVALID_PARAMETER;
    2308     }
    2309 
    2310     /*
    2311      * Only one DMA device.
    2312      */
    2313     PVM pVM = pDevIns->Internal.s.pVMR3;
    2314     if (pVM->pdm.s.pRtc)
    2315     {
    2316         AssertMsgFailed(("Only one RTC device is supported!\n"));
    2317         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
    2318                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2319         return VERR_INVALID_PARAMETER;
    2320     }
    2321 
    2322     /*
    2323      * Allocate and initialize pci bus structure.
    2324      */
    2325     int rc = VINF_SUCCESS;
    2326     PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
    2327     if (pRtc)
    2328     {
    2329         pRtc->pDevIns   = pDevIns;
    2330         pRtc->Reg       = *pRtcReg;
    2331         pVM->pdm.s.pRtc = pRtc;
    2332 
    2333         /* set the helper pointer. */
    2334         *ppRtcHlp = &g_pdmR3DevRtcHlp;
    2335         Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
    2336              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2337     }
    2338     else
    2339         rc = VERR_NO_MEMORY;
    2340 
    2341     LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
    2342              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2343     return rc;
    2344 }
    2345 
    2346 
    2347 /** @copydoc PDMDEVHLPR3::pfnPDMQueueCreate */
    2348 static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
    2349                                                     PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue)
    2350 {
    2351     PDMDEV_ASSERT_DEVINS(pDevIns);
    2352     LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool ppQueue=%p\n",
    2353              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue));
    2354 
    2355     PVM pVM = pDevIns->Internal.s.pVMR3;
    2356     VM_ASSERT_EMT(pVM);
    2357     int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue);
    2358 
    2359     LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppQueue));
    2360     return rc;
    2361 }
    2362 
    2363 
    2364 /** @copydoc PDMDEVHLPR3::pfnCritSectInit */
    2365 static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName)
    2366 {
    2367     PDMDEV_ASSERT_DEVINS(pDevIns);
    2368     LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%p:{%s}\n",
    2369              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pCritSect, pszName, pszName));
    2370 
    2371     PVM pVM = pDevIns->Internal.s.pVMR3;
    2372     VM_ASSERT_EMT(pVM);
    2373     int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, pszName);
    2374 
    2375     LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2376     return rc;
    2377 }
    2378 
    2379 
    2380 /** @copydoc PDMDEVHLPR3::pfnUTCNow */
    2381 static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
    2382 {
    2383     PDMDEV_ASSERT_DEVINS(pDevIns);
    2384     LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: pTime=%p\n",
    2385              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pTime));
    2386 
    2387     pTime = TMR3UTCNow(pDevIns->Internal.s.pVMR3, pTime);
    2388 
    2389     LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: returns %RU64\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
    2390     return pTime;
    2391 }
    2392 
    2393 
    2394 /** @copydoc PDMDEVHLPR3::pfnPDMThreadCreate */
    2395 static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
    2396                                                      PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
    2397 {
    2398     PDMDEV_ASSERT_DEVINS(pDevIns);
    2399     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2400     LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
    2401              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
    2402 
    2403     int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
    2404 
    2405     LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    2406             rc, *ppThread));
    2407     return rc;
    2408 }
    2409 
    2410 
    2411 /** @copydoc PDMDEVHLPR3::pfnGetVM */
    2412 static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
    2413 {
    2414     PDMDEV_ASSERT_DEVINS(pDevIns);
    2415     LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
    2416     return pDevIns->Internal.s.pVMR3;
    2417 }
    2418 
    2419 
    2420 /** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
    2421 static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
    2422 {
    2423     PDMDEV_ASSERT_DEVINS(pDevIns);
    2424     PVM pVM = pDevIns->Internal.s.pVMR3;
    2425     VM_ASSERT_EMT(pVM);
    2426     LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, .pfnSetIrqR3=%p, "
    2427              ".pfnSaveExecR3=%p, .pfnLoadExecR3=%p, .pfnFakePCIBIOSR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppPciHlpR3=%p\n",
    2428              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
    2429              pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnSetIrqR3, pPciBusReg->pfnSaveExecR3, pPciBusReg->pfnLoadExecR3,
    2430              pPciBusReg->pfnFakePCIBIOSR3, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqR0, pPciBusReg->pszSetIrqR0, ppPciHlpR3));
    2431 
    2432     /*
    2433      * Validate the structure.
    2434      */
    2435     if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
    2436     {
    2437         AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
    2438         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2439         return VERR_INVALID_PARAMETER;
    2440     }
    2441     if (    !pPciBusReg->pfnRegisterR3
    2442         ||  !pPciBusReg->pfnIORegionRegisterR3
    2443         ||  !pPciBusReg->pfnSetIrqR3
    2444         ||  !pPciBusReg->pfnSaveExecR3
    2445         ||  !pPciBusReg->pfnLoadExecR3
    2446         ||  !pPciBusReg->pfnFakePCIBIOSR3)
    2447     {
    2448         Assert(pPciBusReg->pfnRegisterR3);
    2449         Assert(pPciBusReg->pfnIORegionRegisterR3);
    2450         Assert(pPciBusReg->pfnSetIrqR3);
    2451         Assert(pPciBusReg->pfnSaveExecR3);
    2452         Assert(pPciBusReg->pfnLoadExecR3);
    2453         Assert(pPciBusReg->pfnFakePCIBIOSR3);
    2454         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2455         return VERR_INVALID_PARAMETER;
    2456     }
    2457     if (    pPciBusReg->pszSetIrqRC
    2458         &&  !VALID_PTR(pPciBusReg->pszSetIrqRC))
    2459     {
    2460         Assert(VALID_PTR(pPciBusReg->pszSetIrqRC));
    2461         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2462         return VERR_INVALID_PARAMETER;
    2463     }
    2464     if (    pPciBusReg->pszSetIrqR0
    2465         &&  !VALID_PTR(pPciBusReg->pszSetIrqR0))
    2466     {
    2467         Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
    2468         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2469         return VERR_INVALID_PARAMETER;
    2470     }
    2471      if (!ppPciHlpR3)
    2472     {
    2473         Assert(ppPciHlpR3);
    2474         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (ppPciHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2475         return VERR_INVALID_PARAMETER;
    2476     }
    2477 
    2478     /*
    2479      * Find free PCI bus entry.
    2480      */
    2481     unsigned iBus = 0;
    2482     for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
    2483         if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
    2484             break;
    2485     if (iBus >= RT_ELEMENTS(pVM->pdm.s.aPciBuses))
    2486     {
    2487         AssertMsgFailed(("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)));
    2488         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (pci bus)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2489         return VERR_INVALID_PARAMETER;
    2490     }
    2491     PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
    2492 
    2493     /*
    2494      * Resolve and init the RC bits.
    2495      */
    2496     if (pPciBusReg->pszSetIrqRC)
    2497     {
    2498         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, &pPciBus->pfnSetIrqRC);
    2499         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, rc));
    2500         if (VBOX_FAILURE(rc))
    2501         {
    2502             LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2503             return rc;
    2504         }
    2505         pPciBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2506     }
    2507     else
    2508     {
    2509         pPciBus->pfnSetIrqRC = 0;
    2510         pPciBus->pDevInsRC   = 0;
    2511     }
    2512 
    2513     /*
    2514      * Resolve and init the R0 bits.
    2515      */
    2516     if (pPciBusReg->pszSetIrqR0)
    2517     {
    2518         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
    2519         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, rc));
    2520         if (VBOX_FAILURE(rc))
    2521         {
    2522             LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2523             return rc;
    2524         }
    2525         pPciBus->pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2526     }
    2527     else
    2528     {
    2529         pPciBus->pfnSetIrqR0 = 0;
    2530         pPciBus->pDevInsR0   = 0;
    2531     }
    2532 
    2533     /*
    2534      * Init the R3 bits.
    2535      */
    2536     pPciBus->iBus                    = iBus;
    2537     pPciBus->pDevInsR3               = pDevIns;
    2538     pPciBus->pfnRegisterR3           = pPciBusReg->pfnRegisterR3;
    2539     pPciBus->pfnIORegionRegisterR3   = pPciBusReg->pfnIORegionRegisterR3;
    2540     pPciBus->pfnSetConfigCallbacksR3 = pPciBusReg->pfnSetConfigCallbacksR3;
    2541     pPciBus->pfnSetIrqR3             = pPciBusReg->pfnSetIrqR3;
    2542     pPciBus->pfnSaveExecR3           = pPciBusReg->pfnSaveExecR3;
    2543     pPciBus->pfnLoadExecR3           = pPciBusReg->pfnLoadExecR3;
    2544     pPciBus->pfnFakePCIBIOSR3        = pPciBusReg->pfnFakePCIBIOSR3;
    2545 
    2546     Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2547 
    2548     /* set the helper pointer and return. */
    2549     *ppPciHlpR3 = &g_pdmR3DevPciHlp;
    2550     LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2551     return VINF_SUCCESS;
    2552 }
    2553 
    2554 
    2555 /** @copydoc PDMDEVHLPR3::pfnPICRegister */
    2556 static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
    2557 {
    2558     PDMDEV_ASSERT_DEVINS(pDevIns);
    2559     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2560     LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pfnGetInterruptR3=%p, .pszGetIrqRC=%p:{%s}, .pszGetInterruptRC=%p:{%s}, .pszGetIrqR0=%p:{%s}, .pszGetInterruptR0=%p:{%s} } ppPicHlpR3=%p\n",
    2561              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
    2562              pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
    2563              pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
    2564              ppPicHlpR3));
    2565 
    2566     /*
    2567      * Validate input.
    2568      */
    2569     if (pPicReg->u32Version != PDM_PICREG_VERSION)
    2570     {
    2571         AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
    2572         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2573         return VERR_INVALID_PARAMETER;
    2574     }
    2575     if (    !pPicReg->pfnSetIrqR3
    2576         ||  !pPicReg->pfnGetInterruptR3)
    2577     {
    2578         Assert(pPicReg->pfnSetIrqR3);
    2579         Assert(pPicReg->pfnGetInterruptR3);
    2580         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2581         return VERR_INVALID_PARAMETER;
    2582     }
    2583     if (    (   pPicReg->pszSetIrqRC
    2584              || pPicReg->pszGetInterruptRC)
    2585         &&  (   !VALID_PTR(pPicReg->pszSetIrqRC)
    2586              || !VALID_PTR(pPicReg->pszGetInterruptRC))
    2587        )
    2588     {
    2589         Assert(VALID_PTR(pPicReg->pszSetIrqRC));
    2590         Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
    2591         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2592         return VERR_INVALID_PARAMETER;
    2593     }
    2594     if (    pPicReg->pszSetIrqRC
    2595         &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    2596     {
    2597         Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC);
    2598         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2599         return VERR_INVALID_PARAMETER;
    2600     }
    2601     if (    pPicReg->pszSetIrqR0
    2602         &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    2603     {
    2604         Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0);
    2605         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R0 flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2606         return VERR_INVALID_PARAMETER;
    2607     }
    2608     if (!ppPicHlpR3)
    2609     {
    2610         Assert(ppPicHlpR3);
    2611         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (ppPicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2612         return VERR_INVALID_PARAMETER;
    2613     }
    2614 
    2615     /*
    2616      * Only one PIC device.
    2617      */
    2618     PVM pVM = pDevIns->Internal.s.pVMR3;
    2619     if (pVM->pdm.s.Pic.pDevInsR3)
    2620     {
    2621         AssertMsgFailed(("Only one pic device is supported!\n"));
    2622         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2623         return VERR_INVALID_PARAMETER;
    2624     }
    2625 
    2626     /*
    2627      * RC stuff.
    2628      */
    2629     if (pPicReg->pszSetIrqRC)
    2630     {
    2631         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
    2632         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, rc));
    2633         if (VBOX_SUCCESS(rc))
    2634         {
    2635             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
    2636             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, rc));
    2637         }
    2638         if (VBOX_FAILURE(rc))
    2639         {
    2640             LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2641             return rc;
    2642         }
    2643         pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2644     }
    2645     else
    2646     {
    2647         pVM->pdm.s.Pic.pDevInsRC = 0;
    2648         pVM->pdm.s.Pic.pfnSetIrqRC = 0;
    2649         pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
    2650     }
    2651 
    2652     /*
    2653      * R0 stuff.
    2654      */
    2655     if (pPicReg->pszSetIrqR0)
    2656     {
    2657         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
    2658         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, rc));
    2659         if (VBOX_SUCCESS(rc))
    2660         {
    2661             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
    2662             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, rc));
    2663         }
    2664         if (VBOX_FAILURE(rc))
    2665         {
    2666             LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2667             return rc;
    2668         }
    2669         pVM->pdm.s.Pic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2670         Assert(pVM->pdm.s.Pic.pDevInsR0);
    2671     }
    2672     else
    2673     {
    2674         pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
    2675         pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
    2676         pVM->pdm.s.Pic.pDevInsR0 = 0;
    2677     }
    2678 
    2679     /*
    2680      * R3 stuff.
    2681      */
    2682     pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
    2683     pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
    2684     pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
    2685     Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2686 
    2687     /* set the helper pointer and return. */
    2688     *ppPicHlpR3 = &g_pdmR3DevPicHlp;
    2689     LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2690     return VINF_SUCCESS;
    2691 }
    2692 
    2693 
    2694 /** @copydoc PDMDEVHLPR3::pfnAPICRegister */
    2695 static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
    2696 {
    2697     PDMDEV_ASSERT_DEVINS(pDevIns);
    2698     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2699     LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptR3=%p, .pfnSetBaseR3=%p, .pfnGetBaseR3=%p, "
    2700              ".pfnSetTPRR3=%p, .pfnGetTPRR3=%p, .pfnBusDeliverR3=%p, pszGetInterruptRC=%p:{%s}, pszSetBaseRC=%p:{%s}, pszGetBaseRC=%p:{%s}, "
    2701              ".pszSetTPRRC=%p:{%s}, .pszGetTPRRC=%p:{%s}, .pszBusDeliverRC=%p:{%s}} ppApicHlpR3=%p\n",
    2702              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptR3, pApicReg->pfnSetBaseR3,
    2703              pApicReg->pfnGetBaseR3, pApicReg->pfnSetTPRR3, pApicReg->pfnGetTPRR3, pApicReg->pfnBusDeliverR3, pApicReg->pszGetInterruptRC,
    2704              pApicReg->pszGetInterruptRC, pApicReg->pszSetBaseRC, pApicReg->pszSetBaseRC, pApicReg->pszGetBaseRC, pApicReg->pszGetBaseRC,
    2705              pApicReg->pszSetTPRRC, pApicReg->pszSetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszBusDeliverRC,
    2706              pApicReg->pszBusDeliverRC, ppApicHlpR3));
    2707 
    2708     /*
    2709      * Validate input.
    2710      */
    2711     if (pApicReg->u32Version != PDM_APICREG_VERSION)
    2712     {
    2713         AssertMsgFailed(("u32Version=%#x expected %#x\n", pApicReg->u32Version, PDM_APICREG_VERSION));
    2714         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2715         return VERR_INVALID_PARAMETER;
    2716     }
    2717     if (    !pApicReg->pfnGetInterruptR3
    2718         ||  !pApicReg->pfnHasPendingIrqR3
    2719         ||  !pApicReg->pfnSetBaseR3
    2720         ||  !pApicReg->pfnGetBaseR3
    2721         ||  !pApicReg->pfnSetTPRR3
    2722         ||  !pApicReg->pfnGetTPRR3
    2723         ||  !pApicReg->pfnBusDeliverR3)
    2724     {
    2725         Assert(pApicReg->pfnGetInterruptR3);
    2726         Assert(pApicReg->pfnHasPendingIrqR3);
    2727         Assert(pApicReg->pfnSetBaseR3);
    2728         Assert(pApicReg->pfnGetBaseR3);
    2729         Assert(pApicReg->pfnSetTPRR3);
    2730         Assert(pApicReg->pfnGetTPRR3);
    2731         Assert(pApicReg->pfnBusDeliverR3);
    2732         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2733         return VERR_INVALID_PARAMETER;
    2734     }
    2735     if (   (    pApicReg->pszGetInterruptRC
    2736             ||  pApicReg->pszHasPendingIrqRC
    2737             ||  pApicReg->pszSetBaseRC
    2738             ||  pApicReg->pszGetBaseRC
    2739             ||  pApicReg->pszSetTPRRC
    2740             ||  pApicReg->pszGetTPRRC
    2741             ||  pApicReg->pszBusDeliverRC)
    2742         &&  (   !VALID_PTR(pApicReg->pszGetInterruptRC)
    2743             ||  !VALID_PTR(pApicReg->pszHasPendingIrqRC)
    2744             ||  !VALID_PTR(pApicReg->pszSetBaseRC)
    2745             ||  !VALID_PTR(pApicReg->pszGetBaseRC)
    2746             ||  !VALID_PTR(pApicReg->pszSetTPRRC)
    2747             ||  !VALID_PTR(pApicReg->pszGetTPRRC)
    2748             ||  !VALID_PTR(pApicReg->pszBusDeliverRC))
    2749        )
    2750     {
    2751         Assert(VALID_PTR(pApicReg->pszGetInterruptRC));
    2752         Assert(VALID_PTR(pApicReg->pszHasPendingIrqRC));
    2753         Assert(VALID_PTR(pApicReg->pszSetBaseRC));
    2754         Assert(VALID_PTR(pApicReg->pszGetBaseRC));
    2755         Assert(VALID_PTR(pApicReg->pszSetTPRRC));
    2756         Assert(VALID_PTR(pApicReg->pszGetTPRRC));
    2757         Assert(VALID_PTR(pApicReg->pszBusDeliverRC));
    2758         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2759         return VERR_INVALID_PARAMETER;
    2760     }
    2761     if (   (    pApicReg->pszGetInterruptR0
    2762             ||  pApicReg->pszHasPendingIrqR0
    2763             ||  pApicReg->pszSetBaseR0
    2764             ||  pApicReg->pszGetBaseR0
    2765             ||  pApicReg->pszSetTPRR0
    2766             ||  pApicReg->pszGetTPRR0
    2767             ||  pApicReg->pszBusDeliverR0)
    2768         &&  (   !VALID_PTR(pApicReg->pszGetInterruptR0)
    2769             ||  !VALID_PTR(pApicReg->pszHasPendingIrqR0)
    2770             ||  !VALID_PTR(pApicReg->pszSetBaseR0)
    2771             ||  !VALID_PTR(pApicReg->pszGetBaseR0)
    2772             ||  !VALID_PTR(pApicReg->pszSetTPRR0)
    2773             ||  !VALID_PTR(pApicReg->pszGetTPRR0)
    2774             ||  !VALID_PTR(pApicReg->pszBusDeliverR0))
    2775        )
    2776     {
    2777         Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
    2778         Assert(VALID_PTR(pApicReg->pszHasPendingIrqR0));
    2779         Assert(VALID_PTR(pApicReg->pszSetBaseR0));
    2780         Assert(VALID_PTR(pApicReg->pszGetBaseR0));
    2781         Assert(VALID_PTR(pApicReg->pszSetTPRR0));
    2782         Assert(VALID_PTR(pApicReg->pszGetTPRR0));
    2783         Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
    2784         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2785         return VERR_INVALID_PARAMETER;
    2786     }
    2787     if (!ppApicHlpR3)
    2788     {
    2789         Assert(ppApicHlpR3);
    2790         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2791         return VERR_INVALID_PARAMETER;
    2792     }
    2793 
    2794     /*
    2795      * Only one APIC device. (malc: only in UP case actually)
    2796      */
    2797     PVM pVM = pDevIns->Internal.s.pVMR3;
    2798     if (pVM->pdm.s.Apic.pDevInsR3)
    2799     {
    2800         AssertMsgFailed(("Only one apic device is supported!\n"));
    2801         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2802         return VERR_INVALID_PARAMETER;
    2803     }
    2804 
    2805     /*
    2806      * Resolve & initialize the RC bits.
    2807      */
    2808     if (pApicReg->pszGetInterruptRC)
    2809     {
    2810         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, &pVM->pdm.s.Apic.pfnGetInterruptRC);
    2811         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, rc));
    2812         if (RT_SUCCESS(rc))
    2813         {
    2814             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, &pVM->pdm.s.Apic.pfnHasPendingIrqRC);
    2815             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, rc));
    2816         }
    2817         if (RT_SUCCESS(rc))
    2818         {
    2819             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, &pVM->pdm.s.Apic.pfnSetBaseRC);
    2820             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, rc));
    2821         }
    2822         if (RT_SUCCESS(rc))
    2823         {
    2824             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, &pVM->pdm.s.Apic.pfnGetBaseRC);
    2825             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, rc));
    2826         }
    2827         if (RT_SUCCESS(rc))
    2828         {
    2829             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, &pVM->pdm.s.Apic.pfnSetTPRRC);
    2830             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, rc));
    2831         }
    2832         if (RT_SUCCESS(rc))
    2833         {
    2834             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, &pVM->pdm.s.Apic.pfnGetTPRRC);
    2835             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, rc));
    2836         }
    2837         if (RT_SUCCESS(rc))
    2838         {
    2839             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, &pVM->pdm.s.Apic.pfnBusDeliverRC);
    2840             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, rc));
    2841         }
    2842         if (VBOX_FAILURE(rc))
    2843         {
    2844             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2845             return rc;
    2846         }
    2847         pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2848     }
    2849     else
    2850     {
    2851         pVM->pdm.s.Apic.pDevInsRC           = 0;
    2852         pVM->pdm.s.Apic.pfnGetInterruptRC   = 0;
    2853         pVM->pdm.s.Apic.pfnHasPendingIrqRC  = 0;
    2854         pVM->pdm.s.Apic.pfnSetBaseRC        = 0;
    2855         pVM->pdm.s.Apic.pfnGetBaseRC        = 0;
    2856         pVM->pdm.s.Apic.pfnSetTPRRC         = 0;
    2857         pVM->pdm.s.Apic.pfnGetTPRRC         = 0;
    2858         pVM->pdm.s.Apic.pfnBusDeliverRC     = 0;
    2859     }
    2860 
    2861     /*
    2862      * Resolve & initialize the R0 bits.
    2863      */
    2864     if (pApicReg->pszGetInterruptR0)
    2865     {
    2866         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
    2867         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
    2868         if (RT_SUCCESS(rc))
    2869         {
    2870             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, &pVM->pdm.s.Apic.pfnHasPendingIrqR0);
    2871             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, rc));
    2872         }
    2873         if (RT_SUCCESS(rc))
    2874         {
    2875             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
    2876             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
    2877         }
    2878         if (RT_SUCCESS(rc))
    2879         {
    2880             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
    2881             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
    2882         }
    2883         if (RT_SUCCESS(rc))
    2884         {
    2885             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
    2886             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
    2887         }
    2888         if (RT_SUCCESS(rc))
    2889         {
    2890             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
    2891             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
    2892         }
    2893         if (RT_SUCCESS(rc))
    2894         {
    2895             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
    2896             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
    2897         }
    2898         if (VBOX_FAILURE(rc))
    2899         {
    2900             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2901             return rc;
    2902         }
    2903         pVM->pdm.s.Apic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2904         Assert(pVM->pdm.s.Apic.pDevInsR0);
    2905     }
    2906     else
    2907     {
    2908         pVM->pdm.s.Apic.pfnGetInterruptR0   = 0;
    2909         pVM->pdm.s.Apic.pfnHasPendingIrqR0  = 0;
    2910         pVM->pdm.s.Apic.pfnSetBaseR0        = 0;
    2911         pVM->pdm.s.Apic.pfnGetBaseR0        = 0;
    2912         pVM->pdm.s.Apic.pfnSetTPRR0         = 0;
    2913         pVM->pdm.s.Apic.pfnGetTPRR0         = 0;
    2914         pVM->pdm.s.Apic.pfnBusDeliverR0     = 0;
    2915         pVM->pdm.s.Apic.pDevInsR0           = 0;
    2916     }
    2917 
    2918     /*
    2919      * Initialize the HC bits.
    2920      */
    2921     pVM->pdm.s.Apic.pDevInsR3           = pDevIns;
    2922     pVM->pdm.s.Apic.pfnGetInterruptR3   = pApicReg->pfnGetInterruptR3;
    2923     pVM->pdm.s.Apic.pfnHasPendingIrqR3  = pApicReg->pfnHasPendingIrqR3;
    2924     pVM->pdm.s.Apic.pfnSetBaseR3        = pApicReg->pfnSetBaseR3;
    2925     pVM->pdm.s.Apic.pfnGetBaseR3        = pApicReg->pfnGetBaseR3;
    2926     pVM->pdm.s.Apic.pfnSetTPRR3         = pApicReg->pfnSetTPRR3;
    2927     pVM->pdm.s.Apic.pfnGetTPRR3         = pApicReg->pfnGetTPRR3;
    2928     pVM->pdm.s.Apic.pfnBusDeliverR3     = pApicReg->pfnBusDeliverR3;
    2929     Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2930 
    2931     /* set the helper pointer and return. */
    2932     *ppApicHlpR3 = &g_pdmR3DevApicHlp;
    2933     LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2934     return VINF_SUCCESS;
    2935 }
    2936 
    2937 
    2938 /** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
    2939 static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
    2940 {
    2941     PDMDEV_ASSERT_DEVINS(pDevIns);
    2942     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2943     LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
    2944              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
    2945              pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
    2946 
    2947     /*
    2948      * Validate input.
    2949      */
    2950     if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
    2951     {
    2952         AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
    2953         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2954         return VERR_INVALID_PARAMETER;
    2955     }
    2956     if (!pIoApicReg->pfnSetIrqR3)
    2957     {
    2958         Assert(pIoApicReg->pfnSetIrqR3);
    2959         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2960         return VERR_INVALID_PARAMETER;
    2961     }
    2962     if (    pIoApicReg->pszSetIrqRC
    2963         &&  !VALID_PTR(pIoApicReg->pszSetIrqRC))
    2964     {
    2965         Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
    2966         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2967         return VERR_INVALID_PARAMETER;
    2968     }
    2969     if (    pIoApicReg->pszSetIrqR0
    2970         &&  !VALID_PTR(pIoApicReg->pszSetIrqR0))
    2971     {
    2972         Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
    2973         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2974         return VERR_INVALID_PARAMETER;
    2975     }
    2976     if (!ppIoApicHlpR3)
    2977     {
    2978         Assert(ppIoApicHlpR3);
    2979         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2980         return VERR_INVALID_PARAMETER;
    2981     }
    2982 
    2983     /*
    2984      * The I/O APIC requires the APIC to be present (hacks++).
    2985      * If the I/O APIC does GC stuff so must the APIC.
    2986      */
    2987     PVM pVM = pDevIns->Internal.s.pVMR3;
    2988     if (!pVM->pdm.s.Apic.pDevInsR3)
    2989     {
    2990         AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
    2991         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2992         return VERR_INVALID_PARAMETER;
    2993     }
    2994     if (    pIoApicReg->pszSetIrqRC
    2995         &&  !pVM->pdm.s.Apic.pDevInsRC)
    2996     {
    2997         AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
    2998         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2999         return VERR_INVALID_PARAMETER;
    3000     }
    3001 
    3002     /*
    3003      * Only one I/O APIC device.
    3004      */
    3005     if (pVM->pdm.s.IoApic.pDevInsR3)
    3006     {
    3007         AssertMsgFailed(("Only one ioapic device is supported!\n"));
    3008         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3009         return VERR_INVALID_PARAMETER;
    3010     }
    3011 
    3012     /*
    3013      * Resolve & initialize the GC bits.
    3014      */
    3015     if (pIoApicReg->pszSetIrqRC)
    3016     {
    3017         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
    3018         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, rc));
    3019         if (VBOX_FAILURE(rc))
    3020         {
    3021             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3022             return rc;
    3023         }
    3024         pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    3025     }
    3026     else
    3027     {
    3028         pVM->pdm.s.IoApic.pDevInsRC   = 0;
    3029         pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
    3030     }
    3031 
    3032     /*
    3033      * Resolve & initialize the R0 bits.
    3034      */
    3035     if (pIoApicReg->pszSetIrqR0)
    3036     {
    3037         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
    3038         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
    3039         if (VBOX_FAILURE(rc))
    3040         {
    3041             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3042             return rc;
    3043         }
    3044         pVM->pdm.s.IoApic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    3045         Assert(pVM->pdm.s.IoApic.pDevInsR0);
    3046     }
    3047     else
    3048     {
    3049         pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
    3050         pVM->pdm.s.IoApic.pDevInsR0   = 0;
    3051     }
    3052 
    3053     /*
    3054      * Initialize the R3 bits.
    3055      */
    3056     pVM->pdm.s.IoApic.pDevInsR3   = pDevIns;
    3057     pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
    3058     Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    3059 
    3060     /* set the helper pointer and return. */
    3061     *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
    3062     LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    3063     return VINF_SUCCESS;
    3064 }
    3065 
    3066 
    3067 /** @copydoc PDMDEVHLPR3::pfnDMACRegister */
    3068 static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
    3069 {
    3070     PDMDEV_ASSERT_DEVINS(pDevIns);
    3071     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3072     LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: pDmacReg=%p:{.u32Version=%#x, .pfnRun=%p, .pfnRegister=%p, .pfnReadMemory=%p, .pfnWriteMemory=%p, .pfnSetDREQ=%p, .pfnGetChannelMode=%p} ppDmacHlp=%p\n",
    3073              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
    3074              pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
    3075 
    3076     /*
    3077      * Validate input.
    3078      */
    3079     if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
    3080     {
    3081         AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
    3082                          PDM_DMACREG_VERSION));
    3083         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
    3084                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3085         return VERR_INVALID_PARAMETER;
    3086     }
    3087     if (    !pDmacReg->pfnRun
    3088         ||  !pDmacReg->pfnRegister
    3089         ||  !pDmacReg->pfnReadMemory
    3090         ||  !pDmacReg->pfnWriteMemory
    3091         ||  !pDmacReg->pfnSetDREQ
    3092         ||  !pDmacReg->pfnGetChannelMode)
    3093     {
    3094         Assert(pDmacReg->pfnRun);
    3095         Assert(pDmacReg->pfnRegister);
    3096         Assert(pDmacReg->pfnReadMemory);
    3097         Assert(pDmacReg->pfnWriteMemory);
    3098         Assert(pDmacReg->pfnSetDREQ);
    3099         Assert(pDmacReg->pfnGetChannelMode);
    3100         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
    3101                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3102         return VERR_INVALID_PARAMETER;
    3103     }
    3104 
    3105     if (!ppDmacHlp)
    3106     {
    3107         Assert(ppDmacHlp);
    3108         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
    3109                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3110         return VERR_INVALID_PARAMETER;
    3111     }
    3112 
    3113     /*
    3114      * Only one DMA device.
    3115      */
    3116     PVM pVM = pDevIns->Internal.s.pVMR3;
    3117     if (pVM->pdm.s.pDmac)
    3118     {
    3119         AssertMsgFailed(("Only one DMA device is supported!\n"));
    3120         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
    3121                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3122         return VERR_INVALID_PARAMETER;
    3123     }
    3124 
    3125     /*
    3126      * Allocate and initialize pci bus structure.
    3127      */
    3128     int rc = VINF_SUCCESS;
    3129     PPDMDMAC  pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
    3130     if (pDmac)
    3131     {
    3132         pDmac->pDevIns   = pDevIns;
    3133         pDmac->Reg       = *pDmacReg;
    3134         pVM->pdm.s.pDmac = pDmac;
    3135 
    3136         /* set the helper pointer. */
    3137         *ppDmacHlp = &g_pdmR3DevDmacHlp;
    3138         Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
    3139              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    3140     }
    3141     else
    3142         rc = VERR_NO_MEMORY;
    3143 
    3144     LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
    3145              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3146     return rc;
    3147 }
    3148 
    3149 
    3150 /** @copydoc PDMDEVHLPR3::pfnPhysRead */
    3151 static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
    3152 {
    3153     PDMDEV_ASSERT_DEVINS(pDevIns);
    3154     LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
    3155              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
    3156 
    3157     /*
    3158      * For the convenience of the device we put no thread restriction on this interface.
    3159      * That means we'll have to check which thread we're in and choose our path.
    3160      */
    3161 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    3162     PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3163 #else
    3164     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    3165         PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3166     else
    3167     {
    3168         Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3169         PVMREQ pReq;
    3170         AssertCompileSize(RTGCPHYS, 4);
    3171         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    3172                                  (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3173         while (rc == VERR_TIMEOUT)
    3174             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    3175         AssertReleaseRC(rc);
    3176         VMR3ReqFree(pReq);
    3177     }
    3178 #endif
    3179     Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3180 }
    3181 
    3182 
    3183 /** @copydoc PDMDEVHLPR3::pfnPhysWrite */
    3184 static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
    3185 {
    3186     PDMDEV_ASSERT_DEVINS(pDevIns);
    3187     LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
    3188              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
    3189 
    3190     /*
    3191      * For the convenience of the device we put no thread restriction on this interface.
    3192      * That means we'll have to check which thread we're in and choose our path.
    3193      */
    3194 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    3195     PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3196 #else
    3197     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    3198         PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3199     else
    3200     {
    3201         Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3202         PVMREQ pReq;
    3203         AssertCompileSize(RTGCPHYS, 4);
    3204         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    3205                                  (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3206         while (rc == VERR_TIMEOUT)
    3207             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    3208         AssertReleaseRC(rc);
    3209         VMR3ReqFree(pReq);
    3210     }
    3211 #endif
    3212     Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3213 }
    3214 
    3215 
    3216 /** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
    3217 static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
    3218 {
    3219     PDMDEV_ASSERT_DEVINS(pDevIns);
    3220     PVM pVM = pDevIns->Internal.s.pVMR3;
    3221     VM_ASSERT_EMT(pVM);
    3222     LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
    3223              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
    3224 
    3225     if (!VM_IS_EMT(pVM))
    3226         return VERR_ACCESS_DENIED;
    3227 
    3228     int rc = PGMPhysReadGCPtr(pVM, pvDst, GCVirtSrc, cb);
    3229 
    3230     LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3231 
    3232     return rc;
    3233 }
    3234 
    3235 
    3236 /** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
    3237 static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
    3238 {
    3239     PDMDEV_ASSERT_DEVINS(pDevIns);
    3240     PVM pVM = pDevIns->Internal.s.pVMR3;
    3241     VM_ASSERT_EMT(pVM);
    3242     LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
    3243              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
    3244 
    3245     if (!VM_IS_EMT(pVM))
    3246         return VERR_ACCESS_DENIED;
    3247 
    3248     int rc = PGMPhysWriteGCPtr(pVM, GCVirtDst, pvSrc, cb);
    3249 
    3250     LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3251 
    3252     return rc;
    3253 }
    3254 
    3255 
    3256 /** @copydoc PDMDEVHLPR3::pfnPhysReserve */
    3257 static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
    3258 {
    3259     PDMDEV_ASSERT_DEVINS(pDevIns);
    3260     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3261     LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
    3262              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, pszDesc, pszDesc));
    3263 
    3264     int rc = MMR3PhysReserve(pDevIns->Internal.s.pVMR3, GCPhys, cbRange, pszDesc);
    3265 
    3266     LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3267 
    3268     return rc;
    3269 }
    3270 
    3271 
    3272 /** @copydoc PDMDEVHLPR3::pfnPhysGCPtr2GCPhys */
    3273 static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
    3274 {
    3275     PDMDEV_ASSERT_DEVINS(pDevIns);
    3276     PVM pVM = pDevIns->Internal.s.pVMR3;
    3277     VM_ASSERT_EMT(pVM);
    3278     LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%VGv pGCPhys=%p\n",
    3279              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPtr, pGCPhys));
    3280 
    3281     if (!VM_IS_EMT(pVM))
    3282         return VERR_ACCESS_DENIED;
    3283 
    3284     int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, pGCPhys);
    3285 
    3286     LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Vrc *pGCPhys=%VGp\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pGCPhys));
    3287 
    3288     return rc;
    3289 }
    3290 
    3291 
    3292 /** @copydoc PDMDEVHLPR3::pfnVMState */
    3293 static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
    3294 {
    3295     PDMDEV_ASSERT_DEVINS(pDevIns);
    3296 
    3297     VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
    3298 
    3299     LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    3300              enmVMState, VMR3GetStateName(enmVMState)));
    3301     return enmVMState;
    3302 }
    3303 
    3304 
    3305 /** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
    3306 static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
    3307 {
    3308     PDMDEV_ASSERT_DEVINS(pDevIns);
    3309     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3310 
    3311     bool fRc = PGMPhysIsA20Enabled(pDevIns->Internal.s.pVMR3);
    3312 
    3313     LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
    3314     return fRc;
    3315 }
    3316 
    3317 
    3318 /** @copydoc PDMDEVHLPR3::pfnA20Set */
    3319 static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
    3320 {
    3321     PDMDEV_ASSERT_DEVINS(pDevIns);
    3322     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3323     LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
    3324     //Assert(*(unsigned *)&fEnable <= 1);
    3325     PGMR3PhysSetA20(pDevIns->Internal.s.pVMR3, fEnable);
    3326 }
    3327 
    3328 
    3329 /** @copydoc PDMDEVHLPR3::pfnVMReset */
    3330 static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
    3331 {
    3332     PDMDEV_ASSERT_DEVINS(pDevIns);
    3333     PVM pVM = pDevIns->Internal.s.pVMR3;
    3334     VM_ASSERT_EMT(pVM);
    3335     LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
    3336              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
    3337 
    3338     /*
    3339      * We postpone this operation because we're likely to be inside a I/O instruction
    3340      * and the EIP will be updated when we return.
    3341      * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
    3342      */
    3343     bool fHaltOnReset;
    3344     int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
    3345     if (VBOX_SUCCESS(rc) && fHaltOnReset)
    3346     {
    3347         Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
    3348         rc = VINF_EM_HALT;
    3349     }
    3350     else
    3351     {
    3352         VM_FF_SET(pVM, VM_FF_RESET);
    3353         rc = VINF_EM_RESET;
    3354     }
    3355 
    3356     LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3357     return rc;
    3358 }
    3359 
    3360 
    3361 /** @copydoc PDMDEVHLPR3::pfnVMSuspend */
    3362 static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
    3363 {
    3364     PDMDEV_ASSERT_DEVINS(pDevIns);
    3365     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3366     LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
    3367              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3368 
    3369     int rc = VMR3Suspend(pDevIns->Internal.s.pVMR3);
    3370 
    3371     LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3372     return rc;
    3373 }
    3374 
    3375 
    3376 /** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
    3377 static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
    3378 {
    3379     PDMDEV_ASSERT_DEVINS(pDevIns);
    3380     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3381     LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
    3382              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3383 
    3384     int rc = VMR3PowerOff(pDevIns->Internal.s.pVMR3);
    3385 
    3386     LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3387     return rc;
    3388 }
    3389 
    3390 
    3391 /** @copydoc PDMDEVHLPR3::pfnLockVM */
    3392 static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns)
    3393 {
    3394     return VMMR3Lock(pDevIns->Internal.s.pVMR3);
    3395 }
    3396 
    3397 
    3398 /** @copydoc PDMDEVHLPR3::pfnUnlockVM */
    3399 static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns)
    3400 {
    3401     return VMMR3Unlock(pDevIns->Internal.s.pVMR3);
    3402 }
    3403 
    3404 
    3405 /** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
    3406 static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    3407 {
    3408     PVM pVM = pDevIns->Internal.s.pVMR3;
    3409     if (VMMR3LockIsOwner(pVM))
    3410         return true;
    3411 
    3412     RTNATIVETHREAD NativeThreadOwner = VMMR3LockGetOwner(pVM);
    3413     RTTHREAD ThreadOwner = RTThreadFromNative(NativeThreadOwner);
    3414     char szMsg[100];
    3415     RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
    3416                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    3417                 NativeThreadOwner, ThreadOwner, RTThreadGetName(ThreadOwner), RTThreadSelfName());
    3418     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    3419     AssertBreakpoint();
    3420     return false;
    3421 }
    3422 
    3423 /** @copydoc PDMDEVHLPR3::pfnDMARegister */
    3424 static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
    3425 {
    3426     PDMDEV_ASSERT_DEVINS(pDevIns);
    3427     PVM pVM = pDevIns->Internal.s.pVMR3;
    3428     VM_ASSERT_EMT(pVM);
    3429     LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
    3430              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
    3431     int rc = VINF_SUCCESS;
    3432     if (pVM->pdm.s.pDmac)
    3433         pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
    3434     else
    3435     {
    3436         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3437         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3438     }
    3439     LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
    3440              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3441     return rc;
    3442 }
    3443 
    3444 /** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
    3445 static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
    3446 {
    3447     PDMDEV_ASSERT_DEVINS(pDevIns);
    3448     PVM pVM = pDevIns->Internal.s.pVMR3;
    3449     VM_ASSERT_EMT(pVM);
    3450     LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
    3451              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
    3452     int rc = VINF_SUCCESS;
    3453     if (pVM->pdm.s.pDmac)
    3454     {
    3455         uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
    3456         if (pcbRead)
    3457             *pcbRead = cb;
    3458     }
    3459     else
    3460     {
    3461         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3462         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3463     }
    3464     LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
    3465              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3466     return rc;
    3467 }
    3468 
    3469 /** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
    3470 static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
    3471 {
    3472     PDMDEV_ASSERT_DEVINS(pDevIns);
    3473     PVM pVM = pDevIns->Internal.s.pVMR3;
    3474     VM_ASSERT_EMT(pVM);
    3475     LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
    3476              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
    3477     int rc = VINF_SUCCESS;
    3478     if (pVM->pdm.s.pDmac)
    3479     {
    3480         uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
    3481         if (pcbWritten)
    3482             *pcbWritten = cb;
    3483     }
    3484     else
    3485     {
    3486         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3487         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3488     }
    3489     LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
    3490              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3491     return rc;
    3492 }
    3493 
    3494 /** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
    3495 static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
    3496 {
    3497     PDMDEV_ASSERT_DEVINS(pDevIns);
    3498     PVM pVM = pDevIns->Internal.s.pVMR3;
    3499     VM_ASSERT_EMT(pVM);
    3500     LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
    3501              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, uLevel));
    3502     int rc = VINF_SUCCESS;
    3503     if (pVM->pdm.s.pDmac)
    3504         pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
    3505     else
    3506     {
    3507         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3508         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3509     }
    3510     LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
    3511              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3512     return rc;
    3513 }
    3514 
    3515 /** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
    3516 static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
    3517 {
    3518     PDMDEV_ASSERT_DEVINS(pDevIns);
    3519     PVM pVM = pDevIns->Internal.s.pVMR3;
    3520     VM_ASSERT_EMT(pVM);
    3521     LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
    3522              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel));
    3523     uint8_t u8Mode;
    3524     if (pVM->pdm.s.pDmac)
    3525         u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
    3526     else
    3527     {
    3528         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3529         u8Mode = 3 << 2 /* illegal mode type */;
    3530     }
    3531     LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
    3532              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Mode));
    3533     return u8Mode;
    3534 }
    3535 
    3536 /** @copydoc PDMDEVHLPR3::pfnDMASchedule */
    3537 static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
    3538 {
    3539     PDMDEV_ASSERT_DEVINS(pDevIns);
    3540     PVM pVM = pDevIns->Internal.s.pVMR3;
    3541     VM_ASSERT_EMT(pVM);
    3542     LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
    3543              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
    3544 
    3545     AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3546     VM_FF_SET(pVM, VM_FF_PDM_DMA);
    3547     REMR3NotifyDmaPending(pVM);
    3548     VMR3NotifyFF(pVM, true);
    3549 }
    3550 
    3551 
    3552 /** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
    3553 static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
    3554 {
    3555     PDMDEV_ASSERT_DEVINS(pDevIns);
    3556     PVM pVM = pDevIns->Internal.s.pVMR3;
    3557     VM_ASSERT_EMT(pVM);
    3558 
    3559     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
    3560              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, u8Value));
    3561     int rc;
    3562     if (pVM->pdm.s.pRtc)
    3563         rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
    3564     else
    3565         rc = VERR_PDM_NO_RTC_INSTANCE;
    3566 
    3567     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
    3568              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3569     return rc;
    3570 }
    3571 
    3572 
    3573 /** @copydoc PDMDEVHLPR3::pfnCMOSRead */
    3574 static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
    3575 {
    3576     PDMDEV_ASSERT_DEVINS(pDevIns);
    3577     PVM pVM = pDevIns->Internal.s.pVMR3;
    3578     VM_ASSERT_EMT(pVM);
    3579 
    3580     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
    3581              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, pu8Value));
    3582     int rc;
    3583     if (pVM->pdm.s.pRtc)
    3584         rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
    3585     else
    3586         rc = VERR_PDM_NO_RTC_INSTANCE;
    3587 
    3588     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
    3589              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3590     return rc;
    3591 }
    3592 
    3593 
    3594 /** @copydoc PDMDEVHLPR3::pfnGetCpuId */
    3595 static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    3596                                                uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
    3597 {
    3598     PDMDEV_ASSERT_DEVINS(pDevIns);
    3599     LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
    3600              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
    3601     AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
    3602 
    3603     CPUMGetGuestCpuId(pDevIns->Internal.s.pVMR3, iLeaf, pEax, pEbx, pEcx, pEdx);
    3604 
    3605     LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
    3606              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
    3607 }
    3608 
    3609 
    3610 /** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
    3611 static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    3612 {
    3613     PDMDEV_ASSERT_DEVINS(pDevIns);
    3614     LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
    3615              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
    3616 
    3617     int rc = MMR3PhysRomProtect(pDevIns->Internal.s.pVMR3, GCPhysStart, cbRange);
    3618 
    3619     LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3620     return rc;
    3621 }
    3622 
    3623 
    3624 /**
    3625  * @copydoc PDMDEVHLPR3::pfnMMIO2Register
    3626  */
    3627 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
    3628 {
    3629     PDMDEV_ASSERT_DEVINS(pDevIns);
    3630     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3631     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: iRegion=#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",
    3632              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cb, fFlags, ppv, pszDesc, pszDesc));
    3633 
    3634     int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, cb, fFlags, ppv, pszDesc);
    3635 
    3636     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3637     return rc;
    3638 }
    3639 
    3640 
    3641 /**
    3642  * @copydoc PDMDEVHLPR3::pfnMMIO2Deregister
    3643  */
    3644 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
    3645 {
    3646     PDMDEV_ASSERT_DEVINS(pDevIns);
    3647     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3648     LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: iRegion=#x\n",
    3649              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion));
    3650 
    3651     AssertReturn(iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);
    3652 
    3653     int rc = PGMR3PhysMMIO2Deregister(pDevIns->Internal.s.pVMR3, pDevIns, iRegion);
    3654 
    3655     LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3656     return rc;
    3657 }
    3658 
    3659 
    3660 /**
    3661  * @copydoc PDMDEVHLPR3::pfnMMIO2Map
    3662  */
    3663 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    3664 {
    3665     PDMDEV_ASSERT_DEVINS(pDevIns);
    3666     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3667     LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
    3668              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
    3669 
    3670     int rc = PGMR3PhysMMIO2Map(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
    3671 
    3672     LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3673     return rc;
    3674 }
    3675 
    3676 
    3677 /**
    3678  * @copydoc PDMDEVHLPR3::pfnMMIO2Unmap
    3679  */
    3680 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    3681 {
    3682     PDMDEV_ASSERT_DEVINS(pDevIns);
    3683     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3684     LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
    3685              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
    3686 
    3687     int rc = PGMR3PhysMMIO2Unmap(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
    3688 
    3689     LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3690     return rc;
    3691 }
    3692 
    3693 
    3694 /**
    3695  * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2
    3696  */
    3697 static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
    3698                                                      const char *pszDesc, PRTRCPTR pRCPtr)
    3699 {
    3700     PDMDEV_ASSERT_DEVINS(pDevIns);
    3701     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3702     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: iRegion=#x off=%RGp cb=%RGp pszDesc=%p:{%s} pRCPtr=%p\n",
    3703              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, off, cb, pszDesc, pszDesc, pRCPtr));
    3704 
    3705     int rc = MMR3HyperMapMMIO2(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, off, cb, pszDesc, pRCPtr);
    3706 
    3707     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc *pRCPtr=%RRv\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pRCPtr));
    3708     return rc;
    3709 }
    3710 
    3711 
    3712 /**
    3713  * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
    3714  */
    3715 static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
    3716 {
    3717     PDMDEV_ASSERT_DEVINS(pDevIns);
    3718     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3719 
    3720     int rc = PDMR3RegisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys, pvHeap, cbSize);
    3721     return rc;
    3722 }
    3723 
    3724 
    3725 /**
    3726  * @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap
    3727  */
    3728 static DECLCALLBACK(int) pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
    3729 {
    3730     PDMDEV_ASSERT_DEVINS(pDevIns);
    3731     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3732 
    3733     int rc = PDMR3UnregisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys);
    3734     return rc;
    3735 }
    3736 
    3737 
    3738 
    3739 
    3740 
    3741 /** @copydoc PDMDEVHLPR3::pfnGetVM */
    3742 static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
    3743 {
    3744     PDMDEV_ASSERT_DEVINS(pDevIns);
    3745     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3746     return NULL;
    3747 }
    3748 
    3749 
    3750 /** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
    3751 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
    3752 {
    3753     PDMDEV_ASSERT_DEVINS(pDevIns);
    3754     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3755     NOREF(pPciBusReg);
    3756     NOREF(ppPciHlpR3);
    3757     return VERR_ACCESS_DENIED;
    3758 }
    3759 
    3760 
    3761 /** @copydoc PDMDEVHLPR3::pfnPICRegister */
    3762 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
    3763 {
    3764     PDMDEV_ASSERT_DEVINS(pDevIns);
    3765     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3766     NOREF(pPicReg);
    3767     NOREF(ppPicHlpR3);
    3768     return VERR_ACCESS_DENIED;
    3769 }
    3770 
    3771 
    3772 /** @copydoc PDMDEVHLPR3::pfnAPICRegister */
    3773 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
    3774 {
    3775     PDMDEV_ASSERT_DEVINS(pDevIns);
    3776     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3777     NOREF(pApicReg);
    3778     NOREF(ppApicHlpR3);
    3779     return VERR_ACCESS_DENIED;
    3780 }
    3781 
    3782 
    3783 /** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
    3784 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
    3785 {
    3786     PDMDEV_ASSERT_DEVINS(pDevIns);
    3787     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3788     NOREF(pIoApicReg);
    3789     NOREF(ppIoApicHlpR3);
    3790     return VERR_ACCESS_DENIED;
    3791 }
    3792 
    3793 
    3794 /** @copydoc PDMDEVHLPR3::pfnDMACRegister */
    3795 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
    3796 {
    3797     PDMDEV_ASSERT_DEVINS(pDevIns);
    3798     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3799     NOREF(pDmacReg);
    3800     NOREF(ppDmacHlp);
    3801     return VERR_ACCESS_DENIED;
    3802 }
    3803 
    3804 
    3805 /** @copydoc PDMDEVHLPR3::pfnPhysRead */
    3806 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
    3807 {
    3808     PDMDEV_ASSERT_DEVINS(pDevIns);
    3809     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3810     NOREF(GCPhys);
    3811     NOREF(pvBuf);
    3812     NOREF(cbRead);
    3813 }
    3814 
    3815 
    3816 /** @copydoc PDMDEVHLPR3::pfnPhysWrite */
    3817 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
    3818 {
    3819     PDMDEV_ASSERT_DEVINS(pDevIns);
    3820     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3821     NOREF(GCPhys);
    3822     NOREF(pvBuf);
    3823     NOREF(cbWrite);
    3824 }
    3825 
    3826 
    3827 /** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
    3828 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
    3829 {
    3830     PDMDEV_ASSERT_DEVINS(pDevIns);
    3831     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3832     NOREF(pvDst);
    3833     NOREF(GCVirtSrc);
    3834     NOREF(cb);
    3835     return VERR_ACCESS_DENIED;
    3836 }
    3837 
    3838 
    3839 /** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
    3840 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
    3841 {
    3842     PDMDEV_ASSERT_DEVINS(pDevIns);
    3843     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3844     NOREF(GCVirtDst);
    3845     NOREF(pvSrc);
    3846     NOREF(cb);
    3847     return VERR_ACCESS_DENIED;
    3848 }
    3849 
    3850 
    3851 /** @copydoc PDMDEVHLPR3::pfnPhysReserve */
    3852 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
    3853 {
    3854     PDMDEV_ASSERT_DEVINS(pDevIns);
    3855     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3856     NOREF(GCPhys);
    3857     NOREF(cbRange);
    3858     return VERR_ACCESS_DENIED;
    3859 }
    3860 
    3861 
    3862 /** @copydoc PDMDEVHLPR3::pfnObsoletePhys2HCVirt */
    3863 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
    3864 {
    3865     PDMDEV_ASSERT_DEVINS(pDevIns);
    3866     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3867     NOREF(GCPhys);
    3868     NOREF(cbRange);
    3869     NOREF(ppvHC);
    3870     return VERR_ACCESS_DENIED;
    3871 }
    3872 
    3873 
    3874 /** @copydoc PDMDEVHLPR3::pfnObsoletePhysGCPtr2HCPtr */
    3875 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
    3876 {
    3877     PDMDEV_ASSERT_DEVINS(pDevIns);
    3878     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3879     NOREF(GCPtr);
    3880     NOREF(pHCPtr);
    3881     return VERR_ACCESS_DENIED;
    3882 }
    3883 
    3884 
    3885 /** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
    3886 static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
    3887 {
    3888     PDMDEV_ASSERT_DEVINS(pDevIns);
    3889     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3890     return false;
    3891 }
    3892 
    3893 
    3894 /** @copydoc PDMDEVHLPR3::pfnA20Set */
    3895 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
    3896 {
    3897     PDMDEV_ASSERT_DEVINS(pDevIns);
    3898     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3899     NOREF(fEnable);
    3900 }
    3901 
    3902 
    3903 /** @copydoc PDMDEVHLPR3::pfnVMReset */
    3904 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
    3905 {
    3906     PDMDEV_ASSERT_DEVINS(pDevIns);
    3907     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3908     return VERR_ACCESS_DENIED;
    3909 }
    3910 
    3911 
    3912 /** @copydoc PDMDEVHLPR3::pfnVMSuspend */
    3913 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
    3914 {
    3915     PDMDEV_ASSERT_DEVINS(pDevIns);
    3916     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3917     return VERR_ACCESS_DENIED;
    3918 }
    3919 
    3920 
    3921 /** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
    3922 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
    3923 {
    3924     PDMDEV_ASSERT_DEVINS(pDevIns);
    3925     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3926     return VERR_ACCESS_DENIED;
    3927 }
    3928 
    3929 
    3930 /** @copydoc PDMDEVHLPR3::pfnLockVM */
    3931 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns)
    3932 {
    3933     PDMDEV_ASSERT_DEVINS(pDevIns);
    3934     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3935     return VERR_ACCESS_DENIED;
    3936 }
    3937 
    3938 
    3939 /** @copydoc PDMDEVHLPR3::pfnUnlockVM */
    3940 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns)
    3941 {
    3942     PDMDEV_ASSERT_DEVINS(pDevIns);
    3943     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3944     return VERR_ACCESS_DENIED;
    3945 }
    3946 
    3947 
    3948 /** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
    3949 static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    3950 {
    3951     PDMDEV_ASSERT_DEVINS(pDevIns);
    3952     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3953     return false;
    3954 }
    3955 
    3956 
    3957 /** @copydoc PDMDEVHLPR3::pfnDMARegister */
    3958 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
    3959 {
    3960     PDMDEV_ASSERT_DEVINS(pDevIns);
    3961     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3962     return VERR_ACCESS_DENIED;
    3963 }
    3964 
    3965 
    3966 /** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
    3967 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
    3968 {
    3969     PDMDEV_ASSERT_DEVINS(pDevIns);
    3970     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3971     if (pcbRead)
    3972         *pcbRead = 0;
    3973     return VERR_ACCESS_DENIED;
    3974 }
    3975 
    3976 
    3977 /** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
    3978 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
    3979 {
    3980     PDMDEV_ASSERT_DEVINS(pDevIns);
    3981     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3982     if (pcbWritten)
    3983         *pcbWritten = 0;
    3984     return VERR_ACCESS_DENIED;
    3985 }
    3986 
    3987 
    3988 /** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
    3989 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
    3990 {
    3991     PDMDEV_ASSERT_DEVINS(pDevIns);
    3992     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3993     return VERR_ACCESS_DENIED;
    3994 }
    3995 
    3996 
    3997 /** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
    3998 static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
    3999 {
    4000     PDMDEV_ASSERT_DEVINS(pDevIns);
    4001     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4002     return 3 << 2 /* illegal mode type */;
    4003 }
    4004 
    4005 
    4006 /** @copydoc PDMDEVHLPR3::pfnDMASchedule */
    4007 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns)
    4008 {
    4009     PDMDEV_ASSERT_DEVINS(pDevIns);
    4010     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4011 }
    4012 
    4013 
    4014 /** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
    4015 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
    4016 {
    4017     PDMDEV_ASSERT_DEVINS(pDevIns);
    4018     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4019     return VERR_ACCESS_DENIED;
    4020 }
    4021 
    4022 
    4023 /** @copydoc PDMDEVHLPR3::pfnCMOSRead */
    4024 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
    4025 {
    4026     PDMDEV_ASSERT_DEVINS(pDevIns);
    4027     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4028     return VERR_ACCESS_DENIED;
    4029 }
    4030 
    4031 
    4032 /** @copydoc PDMDEVHLPR3::pfnGetCpuId */
    4033 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    4034                                                          uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
    4035 {
    4036     PDMDEV_ASSERT_DEVINS(pDevIns);
    4037     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4038 }
    4039 
    4040 
    4041 /** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
    4042 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    4043 {
    4044     PDMDEV_ASSERT_DEVINS(pDevIns);
    4045     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4046     return VERR_ACCESS_DENIED;
    4047 }
    4048 
    4049 
    4050 /** @copydoc PDMDEVHLPR3::pfnMMIO2Register */
    4051 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
    4052 {
    4053     PDMDEV_ASSERT_DEVINS(pDevIns);
    4054     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4055     return VERR_ACCESS_DENIED;
    4056 }
    4057 
    4058 
    4059 /** @copydoc PDMDEVHLPR3::pfnMMIO2Deregister */
    4060 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
    4061 {
    4062     PDMDEV_ASSERT_DEVINS(pDevIns);
    4063     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4064     return VERR_ACCESS_DENIED;
    4065 }
    4066 
    4067 
    4068 /** @copydoc PDMDEVHLPR3::pfnMMIO2Map */
    4069 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    4070 {
    4071     PDMDEV_ASSERT_DEVINS(pDevIns);
    4072     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4073     return VERR_ACCESS_DENIED;
    4074 }
    4075 
    4076 
    4077 /** @copydoc PDMDEVHLPR3::pfnMMIO2Unmap */
    4078 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    4079 {
    4080     PDMDEV_ASSERT_DEVINS(pDevIns);
    4081     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4082     return VERR_ACCESS_DENIED;
    4083 }
    4084 
    4085 
    4086 /** @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2 */
    4087 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr)
    4088 {
    4089     PDMDEV_ASSERT_DEVINS(pDevIns);
    4090     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4091     return VERR_ACCESS_DENIED;
    4092 }
    4093 
    4094 
    4095 /** @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap */
    4096 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
    4097 {
    4098     PDMDEV_ASSERT_DEVINS(pDevIns);
    4099     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4100     return VERR_ACCESS_DENIED;
    4101 }
    4102 
    4103 
    4104 /** @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap */
    4105 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
    4106 {
    4107     PDMDEV_ASSERT_DEVINS(pDevIns);
    4108     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4109     return VERR_ACCESS_DENIED;
    4110 }
    4111 
    4112 
    4113 
    4114 
    4115 
    4116 /** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
    4117 static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
    4118 {
    4119     PDMDEV_ASSERT_DEVINS(pDevIns);
    4120     PVM pVM = pDevIns->Internal.s.pVMR3;
    4121     LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
    4122              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pVM, 0, VM_FF_INTERRUPT_PIC)));
    4123     /* for PIC we always deliver to CPU 0, MP use APIC */
    4124     VMCPU_FF_SET(pVM, 0, VM_FF_INTERRUPT_PIC);
    4125     REMR3NotifyInterruptSet(pVM);
    4126     VMR3NotifyFF(pVM, true);
    4127 }
    4128 
    4129 
    4130 /** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
    4131 static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
    4132 {
    4133     PDMDEV_ASSERT_DEVINS(pDevIns);
    4134     LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
    4135              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC)));
    4136     /* for PIC we always deliver to CPU 0, MP use APIC */
    4137     VMCPU_FF_CLEAR(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC);
    4138     REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMR3);
    4139 }
    4140 
    4141 
    4142 /** @copydoc PDMPICHLPR3::pfnLock */
    4143 static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4144 {
    4145     PDMDEV_ASSERT_DEVINS(pDevIns);
    4146     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4147 }
    4148 
    4149 
    4150 /** @copydoc PDMPICHLPR3::pfnUnlock */
    4151 static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
    4152 {
    4153     PDMDEV_ASSERT_DEVINS(pDevIns);
    4154     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4155 }
    4156 
    4157 
    4158 /** @copydoc PDMPICHLPR3::pfnGetRCHelpers */
    4159 static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4160 {
    4161     PDMDEV_ASSERT_DEVINS(pDevIns);
    4162     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4163     RTRCPTR pRCHelpers = 0;
    4164     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPicHlp", &pRCHelpers);
    4165     AssertReleaseRC(rc);
    4166     AssertRelease(pRCHelpers);
    4167     LogFlow(("pdmR3PicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
    4168              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4169     return pRCHelpers;
    4170 }
    4171 
    4172 
    4173 /** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
    4174 static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4175 {
    4176     PDMDEV_ASSERT_DEVINS(pDevIns);
    4177     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4178     PCPDMPICHLPR0 pR0Helpers = 0;
    4179     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PicHlp", &pR0Helpers);
    4180     AssertReleaseRC(rc);
    4181     AssertRelease(pR0Helpers);
    4182     LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4183              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4184     return pR0Helpers;
    4185 }
    4186 
    4187 
    4188 /** @copydoc PDMAPICHLPR3::pfnSetInterruptFF */
    4189 static DECLCALLBACK(void) pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu)
    4190 {
    4191     PDMDEV_ASSERT_DEVINS(pDevIns);
    4192     PVM pVM = pDevIns->Internal.s.pVMR3;
    4193     LogFlow(("pdmR3ApicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 1\n",
    4194              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pVM, idCpu, VM_FF_INTERRUPT_APIC)));
    4195     VMCPU_FF_SET(pVM, idCpu, VM_FF_INTERRUPT_APIC);
    4196     REMR3NotifyInterruptSet(pVM);
    4197     VMR3NotifyFF(pVM, true);
    4198 }
    4199 
    4200 
    4201 /** @copydoc PDMAPICHLPR3::pfnClearInterruptFF */
    4202 static DECLCALLBACK(void) pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu)
    4203 {
    4204     PDMDEV_ASSERT_DEVINS(pDevIns);
    4205     LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 0\n",
    4206              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pDevIns->Internal.s.pVMR3, idCpu, VM_FF_INTERRUPT_APIC)));
    4207     VMCPU_FF_CLEAR(pDevIns->Internal.s.pVMR3, idCpu, VM_FF_INTERRUPT_APIC);
    4208     REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMR3);
    4209 }
    4210 
    4211 
    4212 /** @copydoc PDMAPICHLPR3::pfnChangeFeature */
    4213 static DECLCALLBACK(void) pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
    4214 {
    4215     PDMDEV_ASSERT_DEVINS(pDevIns);
    4216     LogFlow(("pdmR3ApicHlp_ChangeFeature: caller='%s'/%d: version=%d\n",
    4217              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, (int)enmVersion));
    4218     switch (enmVersion)
    4219     {
    4220         case PDMAPICVERSION_NONE:
    4221             CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
    4222             CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
    4223             break;
    4224         case PDMAPICVERSION_APIC:
    4225             CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
    4226             CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
    4227             break;
    4228         case PDMAPICVERSION_X2APIC:
    4229             CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
    4230             CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
    4231             break;
    4232         default:
    4233             AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
    4234     }
    4235 }
    4236 
    4237 /** @copydoc PDMAPICHLPR3::pfnLock */
    4238 static DECLCALLBACK(int) pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4239 {
    4240     PDMDEV_ASSERT_DEVINS(pDevIns);
    4241     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4242 }
    4243 
    4244 
    4245 /** @copydoc PDMAPICHLPR3::pfnUnlock */
    4246 static DECLCALLBACK(void) pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns)
    4247 {
    4248     PDMDEV_ASSERT_DEVINS(pDevIns);
    4249     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4250 }
    4251 
    4252 
    4253 /** @copydoc PDMAPICHLPR3::pfnGetCpuId */
    4254 static DECLCALLBACK(VMCPUID) pdmR3ApicHlp_GetCpuId(PPDMDEVINS pDevIns)
    4255 {
    4256     PDMDEV_ASSERT_DEVINS(pDevIns);
    4257     return VMMGetCpuId(pDevIns->Internal.s.pVMR3);
    4258 }
    4259 
    4260 
    4261 /** @copydoc PDMAPICHLPR3::pfnGetRCHelpers */
    4262 static DECLCALLBACK(PCPDMAPICHLPRC) pdmR3ApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4263 {
    4264     PDMDEV_ASSERT_DEVINS(pDevIns);
    4265     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4266     RTRCPTR pRCHelpers = 0;
    4267     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCApicHlp", &pRCHelpers);
    4268     AssertReleaseRC(rc);
    4269     AssertRelease(pRCHelpers);
    4270     LogFlow(("pdmR3ApicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
    4271              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4272     return pRCHelpers;
    4273 }
    4274 
    4275 
    4276 /** @copydoc PDMAPICHLPR3::pfnGetR0Helpers */
    4277 static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4278 {
    4279     PDMDEV_ASSERT_DEVINS(pDevIns);
    4280     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4281     PCPDMAPICHLPR0 pR0Helpers = 0;
    4282     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0ApicHlp", &pR0Helpers);
    4283     AssertReleaseRC(rc);
    4284     AssertRelease(pR0Helpers);
    4285     LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4286              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4287     return pR0Helpers;
    4288 }
    4289 
    4290 
    4291 /** @copydoc PDMIOAPICHLPR3::pfnApicBusDeliver */
    4292 static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
    4293                                                         uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
    4294 {
    4295     PDMDEV_ASSERT_DEVINS(pDevIns);
    4296     PVM pVM = pDevIns->Internal.s.pVMR3;
    4297     LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
    4298              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
    4299     if (pVM->pdm.s.Apic.pfnBusDeliverR3)
    4300         pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
    4301 }
    4302 
    4303 
    4304 /** @copydoc PDMIOAPICHLPR3::pfnLock */
    4305 static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4306 {
    4307     PDMDEV_ASSERT_DEVINS(pDevIns);
    4308     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4309 }
    4310 
    4311 
    4312 /** @copydoc PDMIOAPICHLPR3::pfnUnlock */
    4313 static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
    4314 {
    4315     PDMDEV_ASSERT_DEVINS(pDevIns);
    4316     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4317 }
    4318 
    4319 
    4320 /** @copydoc PDMIOAPICHLPR3::pfnGetRCHelpers */
    4321 static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4322 {
    4323     PDMDEV_ASSERT_DEVINS(pDevIns);
    4324     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4325     RTRCPTR pRCHelpers = 0;
    4326     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCIoApicHlp", &pRCHelpers);
    4327     AssertReleaseRC(rc);
    4328     AssertRelease(pRCHelpers);
    4329     LogFlow(("pdmR3IoApicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
    4330              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4331     return pRCHelpers;
    4332 }
    4333 
    4334 
    4335 /** @copydoc PDMIOAPICHLPR3::pfnGetR0Helpers */
    4336 static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4337 {
    4338     PDMDEV_ASSERT_DEVINS(pDevIns);
    4339     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4340     PCPDMIOAPICHLPR0 pR0Helpers = 0;
    4341     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0IoApicHlp", &pR0Helpers);
    4342     AssertReleaseRC(rc);
    4343     AssertRelease(pR0Helpers);
    4344     LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4345              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4346     return pR0Helpers;
    4347 }
    4348 
    4349 
    4350 /** @copydoc PDMPCIHLPR3::pfnIsaSetIrq */
    4351 static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    4352 {
    4353     PDMDEV_ASSERT_DEVINS(pDevIns);
    4354     Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
    4355     PDMIsaSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel);
    4356 }
    4357 
    4358 
    4359 /** @copydoc PDMPCIHLPR3::pfnIoApicSetIrq */
    4360 static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    4361 {
    4362     PDMDEV_ASSERT_DEVINS(pDevIns);
    4363     Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
    4364     PDMIoApicSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel);
    4365 }
    4366 
    4367 
    4368 /** @copydoc PDMPCIHLPR3::pfnIsMMIO2Base */
    4369 static DECLCALLBACK(bool) pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys)
    4370 {
    4371     PDMDEV_ASSERT_DEVINS(pDevIns);
    4372     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4373     bool fRc = PGMR3PhysMMIO2IsBase(pDevIns->Internal.s.pVMR3, pOwner, GCPhys);
    4374     Log4(("pdmR3PciHlp_IsMMIO2Base: pOwner=%p GCPhys=%RGp -> %RTbool\n", pOwner, GCPhys, fRc));
    4375     return fRc;
    4376 }
    4377 
    4378 
    4379 /** @copydoc PDMPCIHLPR3::pfnLock */
    4380 static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4381 {
    4382     PDMDEV_ASSERT_DEVINS(pDevIns);
    4383     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4384 }
    4385 
    4386 
    4387 /** @copydoc PDMPCIHLPR3::pfnUnlock */
    4388 static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
    4389 {
    4390     PDMDEV_ASSERT_DEVINS(pDevIns);
    4391     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4392 }
    4393 
    4394 
    4395 /** @copydoc PDMPCIHLPR3::pfnGetRCHelpers */
    4396 static DECLCALLBACK(PCPDMPCIHLPRC) pdmR3PciHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4397 {
    4398     PDMDEV_ASSERT_DEVINS(pDevIns);
    4399     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4400     RTRCPTR pRCHelpers = 0;
    4401     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPciHlp", &pRCHelpers);
    4402     AssertReleaseRC(rc);
    4403     AssertRelease(pRCHelpers);
    4404     LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
    4405              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4406     return pRCHelpers;
    4407 }
    4408 
    4409 
    4410 /** @copydoc PDMPCIHLPR3::pfnGetR0Helpers */
    4411 static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4412 {
    4413     PDMDEV_ASSERT_DEVINS(pDevIns);
    4414     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4415     PCPDMPCIHLPR0 pR0Helpers = 0;
    4416     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PciHlp", &pR0Helpers);
    4417     AssertReleaseRC(rc);
    4418     AssertRelease(pR0Helpers);
    4419     LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4420              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4421     return pR0Helpers;
    4422 }
    4423 
    4424 
    4425 /**
    4426  * Locates a LUN.
    4427  *
    4428  * @returns VBox status code.
    4429  * @param   pVM             VM Handle.
    4430  * @param   pszDevice       Device name.
    4431  * @param   iInstance       Device instance.
    4432  * @param   iLun            The Logical Unit to obtain the interface of.
    4433  * @param   ppLun           Where to store the pointer to the LUN if found.
    4434  * @thread  Try only do this in EMT...
    4435  */
    4436 int pdmR3DevFindLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMLUN *ppLun)
    4437 {
    4438     /*
    4439      * Iterate registered devices looking for the device.
    4440      */
    4441     RTUINT cchDevice = strlen(pszDevice);
    4442     for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
    4443     {
    4444         if (    pDev->cchName == cchDevice
    4445             &&  !memcmp(pDev->pDevReg->szDeviceName, pszDevice, cchDevice))
    4446         {
    4447             /*
    4448              * Iterate device instances.
    4449              */
    4450             for (PPDMDEVINS pDevIns = pDev->pInstances; pDevIns; pDevIns = pDevIns->Internal.s.pPerDeviceNextR3)
    4451             {
    4452                 if (pDevIns->iInstance == iInstance)
    4453                 {
    4454                     /*
    4455                      * Iterate luns.
    4456                      */
    4457                     for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
    4458                     {
    4459                         if (pLun->iLun == iLun)
    4460                         {
    4461                             *ppLun = pLun;
    4462                             return VINF_SUCCESS;
    4463                         }
    4464                     }
    4465                     return VERR_PDM_LUN_NOT_FOUND;
    4466                 }
    4467             }
    4468             return VERR_PDM_DEVICE_INSTANCE_NOT_FOUND;
    4469         }
    4470     }
    4471     return VERR_PDM_DEVICE_NOT_FOUND;
    4472 }
    4473 
    4474 
    4475 /**
    4476  * Attaches a preconfigured driver to an existing device instance.
    4477  *
    4478  * This is used to change drivers and suchlike at runtime.
    4479  *
    4480  * @returns VBox status code.
    4481  * @param   pVM             VM Handle.
    4482  * @param   pszDevice       Device name.
    4483  * @param   iInstance       Device instance.
    4484  * @param   iLun            The Logical Unit to obtain the interface of.
    4485  * @param   ppBase          Where to store the base interface pointer. Optional.
    4486  * @thread  EMT
    4487  */
    4488 PDMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
    4489 {
    4490     VM_ASSERT_EMT(pVM);
    4491     LogFlow(("PDMR3DeviceAttach: pszDevice=%p:{%s} iInstance=%d iLun=%d ppBase=%p\n",
    4492              pszDevice, pszDevice, iInstance, iLun, ppBase));
    4493 
    4494     /*
    4495      * Find the LUN in question.
    4496      */
    4497     PPDMLUN pLun;
    4498     int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
    4499     if (VBOX_SUCCESS(rc))
    4500     {
    4501         /*
    4502          * Can we attach anything at runtime?
    4503          */
    4504         PPDMDEVINS pDevIns = pLun->pDevIns;
    4505         if (pDevIns->pDevReg->pfnAttach)
    4506         {
    4507             if (!pLun->pTop)
    4508             {
    4509                 rc = pDevIns->pDevReg->pfnAttach(pDevIns, iLun);
    4510 
    4511             }
    4512             else
    4513                 rc = VERR_PDM_DRIVER_ALREADY_ATTACHED;
    4514         }
    4515         else
    4516             rc = VERR_PDM_DEVICE_NO_RT_ATTACH;
    4517 
    4518         if (ppBase)
    4519             *ppBase = pLun->pTop ? &pLun->pTop->IBase : NULL;
    4520     }
    4521     else if (ppBase)
    4522         *ppBase = NULL;
    4523 
    4524     if (ppBase)
    4525         LogFlow(("PDMR3DeviceAttach: returns %Vrc *ppBase=%p\n", rc, *ppBase));
    4526     else
    4527         LogFlow(("PDMR3DeviceAttach: returns %Vrc\n", rc));
    4528     return rc;
    4529 }
    4530 
    4531 
    4532 /**
    4533  * Detaches a driver chain from an existing device instance.
    4534  *
    4535  * This is used to change drivers and suchlike at runtime.
    4536  *
    4537  * @returns VBox status code.
    4538  * @param   pVM             VM Handle.
    4539  * @param   pszDevice       Device name.
    4540  * @param   iInstance       Device instance.
    4541  * @param   iLun            The Logical Unit to obtain the interface of.
    4542  * @thread  EMT
    4543  */
    4544 PDMR3DECL(int) PDMR3DeviceDetach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun)
    4545 {
    4546     VM_ASSERT_EMT(pVM);
    4547     LogFlow(("PDMR3DeviceDetach: pszDevice=%p:{%s} iInstance=%d iLun=%d\n",
    4548              pszDevice, pszDevice, iInstance, iLun));
    4549 
    4550     /*
    4551      * Find the LUN in question.
    4552      */
    4553     PPDMLUN pLun;
    4554     int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
    4555     if (VBOX_SUCCESS(rc))
    4556     {
    4557         /*
    4558          * Can we detach anything at runtime?
    4559          */
    4560         PPDMDEVINS pDevIns = pLun->pDevIns;
    4561         if (pDevIns->pDevReg->pfnDetach)
    4562         {
    4563             if (pLun->pTop)
    4564                 rc = pdmR3DrvDetach(pLun->pTop);
    4565             else
    4566                 rc = VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN;
    4567         }
    4568         else
    4569             rc = VERR_PDM_DEVICE_NO_RT_DETACH;
    4570     }
    4571 
    4572     LogFlow(("PDMR3DeviceDetach: returns %Vrc\n", rc));
    4573     return rc;
    4574 }
    4575 
     3152/** @} */
     3153
  • trunk/src/VBox/VMM/PDMDevMiscHlp.cpp

    r12979 r12980  
    11/* $Id$ */
    22/** @file
    3  * PDM - Pluggable Device and Driver Manager, Device parts.
     3 * PDM - Pluggable Device and Driver Manager, Misc. Device Helpers.
    44 */
    55
     
    2727#include "PDMInternal.h"
    2828#include <VBox/pdm.h>
    29 #include <VBox/mm.h>
    30 #include <VBox/pgm.h>
    31 #include <VBox/iom.h>
    32 #include <VBox/cfgm.h>
    3329#include <VBox/rem.h>
    34 #include <VBox/dbgf.h>
    3530#include <VBox/vm.h>
    3631#include <VBox/vmm.h>
    3732
    38 #include <VBox/version.h>
    3933#include <VBox/log.h>
    4034#include <VBox/err.h>
    41 #include <iprt/alloc.h>
    42 #include <iprt/alloca.h>
    4335#include <iprt/asm.h>
    4436#include <iprt/assert.h>
    45 #include <iprt/path.h>
    46 #include <iprt/semaphore.h>
    47 #include <iprt/string.h>
    4837#include <iprt/thread.h>
    4938
    50 
    51 /*******************************************************************************
    52 *   Structures and Typedefs                                                    *
    53 *******************************************************************************/
    54 /**
    55  * Internal callback structure pointer.
    56  * The main purpose is to define the extra data we associate
    57  * with PDMDEVREGCB so we can find the VM instance and so on.
    58  */
    59 typedef struct PDMDEVREGCBINT
    60 {
    61     /** The callback structure. */
    62     PDMDEVREGCB     Core;
    63     /** A bit of padding. */
    64     uint32_t        u32[4];
    65     /** VM Handle. */
    66     PVM             pVM;
    67 } PDMDEVREGCBINT, *PPDMDEVREGCBINT;
    68 typedef const PDMDEVREGCBINT *PCPDMDEVREGCBINT;
    69 
    70 
    71 /*******************************************************************************
    72 *   Internal Functions                                                         *
    73 *******************************************************************************/
    74 __BEGIN_DECLS
    75 static DECLCALLBACK(int)    pdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pDevReg);
    76 static DECLCALLBACK(void *) pdmR3DevReg_MMHeapAlloc(PPDMDEVREGCB pCallbacks, size_t cb);
    77 static DECLCALLBACK(bool)   pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem);
    78 
    79 /* VSlick regex:
    80 search : \om/\*\*.+?\*\/\nDECLCALLBACKMEMBER\(([^,]*), *pfn([^)]*)\)\(
    81 replace: \/\*\* @copydoc PDMDEVHLPR3::pfn\2 \*\/\nstatic DECLCALLBACK\(\1\) pdmR3DevHlp_\2\(
    82  */
    83 
    84 /** @name R3 DevHlp
    85  * @{
    86  */
    87 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn, PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc);
    88 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTRCPTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
    89 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
    90 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts);
    91 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
    92                                                      PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
    93                                                      const char *pszDesc);
    94 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
    95                                                        const char *pszWrite, const char *pszRead, const char *pszFill,
    96                                                        const char *pszDesc);
    97 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
    98                                                        const char *pszWrite, const char *pszRead, const char *pszFill,
    99                                                        const char *pszDesc);
    100 static DECLCALLBACK(int)    pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    101 static DECLCALLBACK(int)    pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc);
    102 static DECLCALLBACK(int)    pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
    103                                                     PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
    104                                                     PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone);
    105 static DECLCALLBACK(int)    pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer);
    106 static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc);
    107 static DECLCALLBACK(int)    pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev);
    108 static DECLCALLBACK(int)    pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback);
    109 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
    110                                                               PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld);
    111 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    112 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    113 static DECLCALLBACK(void)   pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    114 static DECLCALLBACK(void)   pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    115 static DECLCALLBACK(int)    pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc);
    116 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb);
    117 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb);
    118 static DECLCALLBACK(void)   pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv);
    119 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
    120 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va);
    121 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...);
    122 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va);
    123 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    124 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    125 static DECLCALLBACK(int)    pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args);
    126 static DECLCALLBACK(int)    pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler);
    127 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
    128 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...);
    129 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args);
    130 static DECLCALLBACK(int)    pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName);
    131 static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime);
    132 static DECLCALLBACK(int)    pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
    133                                                         PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
    134 
    135 static DECLCALLBACK(PVM)    pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns);
    136 static DECLCALLBACK(int)    pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
    137 static DECLCALLBACK(int)    pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
    138 static DECLCALLBACK(int)    pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
    139 static DECLCALLBACK(int)    pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
    140 static DECLCALLBACK(int)    pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
    141 static DECLCALLBACK(int)    pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp);
    142 static DECLCALLBACK(int)    pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue);
    143 static DECLCALLBACK(void)   pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
    144 static DECLCALLBACK(void)   pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
    145 static DECLCALLBACK(int)    pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
    146 static DECLCALLBACK(int)    pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
    147 static DECLCALLBACK(int)    pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
    148 static DECLCALLBACK(int)    pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys);
    149 static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns);
    150 static DECLCALLBACK(bool)   pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns);
    151 static DECLCALLBACK(void)   pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable);
    152 static DECLCALLBACK(int)    pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns);
    153 static DECLCALLBACK(int)    pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns);
    154 static DECLCALLBACK(int)    pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns);
    155 static DECLCALLBACK(int)    pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns);
    156 static DECLCALLBACK(int)    pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns);
    157 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    158 static DECLCALLBACK(int)    pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
    159 static DECLCALLBACK(int)    pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
    160 static DECLCALLBACK(int)    pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
    161 static DECLCALLBACK(int)    pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
    162 static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
    163 static DECLCALLBACK(void)   pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns);
    164 static DECLCALLBACK(int)    pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
    165 static DECLCALLBACK(int)    pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
    166 static DECLCALLBACK(void)   pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    167                                                uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
    168 static DECLCALLBACK(int)    pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    169 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc);
    170 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion);
    171 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    172 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    173 static DECLCALLBACK(int)    pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr);
    174 static DECLCALLBACK(int)    pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize);
    175 static DECLCALLBACK(int)    pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys);
    176 
    177 static DECLCALLBACK(PVM)    pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns);
    178 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
    179 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
    180 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
    181 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
    182 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
    183 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
    184 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
    185 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
    186 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
    187 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
    188 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC);
    189 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr);
    190 
    191 static DECLCALLBACK(bool)   pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns);
    192 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable);
    193 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns);
    194 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns);
    195 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns);
    196 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns);
    197 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns);
    198 static DECLCALLBACK(bool)   pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    199 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
    200 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
    201 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
    202 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
    203 static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
    204 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns);
    205 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
    206 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
    207 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    208                                                            uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
    209 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    210 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc);
    211 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion);
    212 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    213 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    214 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr);
    215 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize);
    216 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys);
    217 /** @} */
    21839
    21940
     
    22142 * @{
    22243 */
    223 static DECLCALLBACK(void)   pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns);
    224 static DECLCALLBACK(void)   pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns);
    225 static DECLCALLBACK(int)    pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    226 static DECLCALLBACK(void)   pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns);
    227 static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    228 static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    229 /** @} */
    230 
    231 
    232 /** @name HC APIC Helpers
    233  * @{
    234  */
    235 static DECLCALLBACK(void)   pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu);
    236 static DECLCALLBACK(void)   pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu);
    237 static DECLCALLBACK(void)   pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion);
    238 static DECLCALLBACK(int)    pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    239 static DECLCALLBACK(void)   pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns);
    240 static DECLCALLBACK(VMCPUID) pdmR3ApicHlp_GetCpuId(PPDMDEVINS pDevIns);
    241 static DECLCALLBACK(PCPDMAPICHLPRC) pdmR3ApicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    242 static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    243 /** @} */
    244 
    245 
    246 /** @name HC I/O APIC Helpers
    247  * @{
    248  */
    249 static DECLCALLBACK(void)   pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
    250                                                           uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode);
    251 static DECLCALLBACK(int)    pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    252 static DECLCALLBACK(void)   pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns);
    253 static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    254 static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    255 /** @} */
    256 
    257 
    258 /** @name HC PCI Bus Helpers
    259  * @{
    260  */
    261 static DECLCALLBACK(void)   pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    262 static DECLCALLBACK(void)   pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    263 static DECLCALLBACK(bool)   pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys);
    264 static DECLCALLBACK(int)    pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc);
    265 static DECLCALLBACK(void)   pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns);
    266 static DECLCALLBACK(PCPDMPCIHLPRC) pdmR3PciHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    267 static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    268 /** @} */
    269 
    270 /** @def PDMDEV_ASSERT_DEVINS
    271  * Asserts the validity of the device instance.
    272  */
    273 #ifdef VBOX_STRICT
    274 # define PDMDEV_ASSERT_DEVINS(pDevIns)   \
    275     do { \
    276         AssertPtr(pDevIns); \
    277         Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); \
    278         Assert(pDevIns->pvInstanceDataR3 == (void *)&pDevIns->achInstanceData[0]); \
    279     } while (0)
    280 #else
    281 # define PDMDEV_ASSERT_DEVINS(pDevIns)   do { } while (0)
    282 #endif
    283 
    284 static int pdmR3DevLoadModules(PVM pVM);
    285 static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName);
    286 
    287 
    288 /*
    289  * Allow physical read and writes from any thread
    290  */
    291 #define PDM_PHYS_READWRITE_FROM_ANY_THREAD
    292 
    293 __END_DECLS
    294 
    295 /*******************************************************************************
    296 *   Global Variables                                                           *
    297 *******************************************************************************/
    298 /**
    299  * The device helper structure for trusted devices.
    300  */
    301 const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
    302 {
    303     PDM_DEVHLP_VERSION,
    304     pdmR3DevHlp_IOPortRegister,
    305     pdmR3DevHlp_IOPortRegisterGC,
    306     pdmR3DevHlp_IOPortRegisterR0,
    307     pdmR3DevHlp_IOPortDeregister,
    308     pdmR3DevHlp_MMIORegister,
    309     pdmR3DevHlp_MMIORegisterGC,
    310     pdmR3DevHlp_MMIORegisterR0,
    311     pdmR3DevHlp_MMIODeregister,
    312     pdmR3DevHlp_ROMRegister,
    313     pdmR3DevHlp_SSMRegister,
    314     pdmR3DevHlp_TMTimerCreate,
    315     pdmR3DevHlp_TMTimerCreateExternal,
    316     pdmR3DevHlp_PCIRegister,
    317     pdmR3DevHlp_PCIIORegionRegister,
    318     pdmR3DevHlp_PCISetConfigCallbacks,
    319     pdmR3DevHlp_PCISetIrq,
    320     pdmR3DevHlp_PCISetIrqNoWait,
    321     pdmR3DevHlp_ISASetIrq,
    322     pdmR3DevHlp_ISASetIrqNoWait,
    323     pdmR3DevHlp_DriverAttach,
    324     pdmR3DevHlp_MMHeapAlloc,
    325     pdmR3DevHlp_MMHeapAllocZ,
    326     pdmR3DevHlp_MMHeapFree,
    327     pdmR3DevHlp_VMSetError,
    328     pdmR3DevHlp_VMSetErrorV,
    329     pdmR3DevHlp_VMSetRuntimeError,
    330     pdmR3DevHlp_VMSetRuntimeErrorV,
    331     pdmR3DevHlp_AssertEMT,
    332     pdmR3DevHlp_AssertOther,
    333     pdmR3DevHlp_DBGFStopV,
    334     pdmR3DevHlp_DBGFInfoRegister,
    335     pdmR3DevHlp_STAMRegister,
    336     pdmR3DevHlp_STAMRegisterF,
    337     pdmR3DevHlp_STAMRegisterV,
    338     pdmR3DevHlp_RTCRegister,
    339     pdmR3DevHlp_PDMQueueCreate,
    340     pdmR3DevHlp_CritSectInit,
    341     pdmR3DevHlp_UTCNow,
    342     pdmR3DevHlp_PDMThreadCreate,
    343     pdmR3DevHlp_PhysGCPtr2GCPhys,
    344     pdmR3DevHlp_VMState,
    345     0,
    346     0,
    347     0,
    348     0,
    349     0,
    350     0,
    351     0,
    352     pdmR3DevHlp_GetVM,
    353     pdmR3DevHlp_PCIBusRegister,
    354     pdmR3DevHlp_PICRegister,
    355     pdmR3DevHlp_APICRegister,
    356     pdmR3DevHlp_IOAPICRegister,
    357     pdmR3DevHlp_DMACRegister,
    358     pdmR3DevHlp_PhysRead,
    359     pdmR3DevHlp_PhysWrite,
    360     pdmR3DevHlp_PhysReadGCVirt,
    361     pdmR3DevHlp_PhysWriteGCVirt,
    362     pdmR3DevHlp_PhysReserve,
    363     pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt,
    364     pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr,
    365     pdmR3DevHlp_A20IsEnabled,
    366     pdmR3DevHlp_A20Set,
    367     pdmR3DevHlp_VMReset,
    368     pdmR3DevHlp_VMSuspend,
    369     pdmR3DevHlp_VMPowerOff,
    370     pdmR3DevHlp_LockVM,
    371     pdmR3DevHlp_UnlockVM,
    372     pdmR3DevHlp_AssertVMLock,
    373     pdmR3DevHlp_DMARegister,
    374     pdmR3DevHlp_DMAReadMemory,
    375     pdmR3DevHlp_DMAWriteMemory,
    376     pdmR3DevHlp_DMASetDREQ,
    377     pdmR3DevHlp_DMAGetChannelMode,
    378     pdmR3DevHlp_DMASchedule,
    379     pdmR3DevHlp_CMOSWrite,
    380     pdmR3DevHlp_CMOSRead,
    381     pdmR3DevHlp_GetCpuId,
    382     pdmR3DevHlp_ROMProtectShadow,
    383     pdmR3DevHlp_MMIO2Register,
    384     pdmR3DevHlp_MMIO2Deregister,
    385     pdmR3DevHlp_MMIO2Map,
    386     pdmR3DevHlp_MMIO2Unmap,
    387     pdmR3DevHlp_MMHyperMapMMIO2,
    388     pdmR3DevHlp_RegisterVMMDevHeap,
    389     pdmR3DevHlp_UnregisterVMMDevHeap,
    390     PDM_DEVHLP_VERSION /* the end */
    391 };
    392 
    393 
    394 /**
    395  * The device helper structure for non-trusted devices.
    396  */
    397 const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
    398 {
    399     PDM_DEVHLP_VERSION,
    400     pdmR3DevHlp_IOPortRegister,
    401     pdmR3DevHlp_IOPortRegisterGC,
    402     pdmR3DevHlp_IOPortRegisterR0,
    403     pdmR3DevHlp_IOPortDeregister,
    404     pdmR3DevHlp_MMIORegister,
    405     pdmR3DevHlp_MMIORegisterGC,
    406     pdmR3DevHlp_MMIORegisterR0,
    407     pdmR3DevHlp_MMIODeregister,
    408     pdmR3DevHlp_ROMRegister,
    409     pdmR3DevHlp_SSMRegister,
    410     pdmR3DevHlp_TMTimerCreate,
    411     pdmR3DevHlp_TMTimerCreateExternal,
    412     pdmR3DevHlp_PCIRegister,
    413     pdmR3DevHlp_PCIIORegionRegister,
    414     pdmR3DevHlp_PCISetConfigCallbacks,
    415     pdmR3DevHlp_PCISetIrq,
    416     pdmR3DevHlp_PCISetIrqNoWait,
    417     pdmR3DevHlp_ISASetIrq,
    418     pdmR3DevHlp_ISASetIrqNoWait,
    419     pdmR3DevHlp_DriverAttach,
    420     pdmR3DevHlp_MMHeapAlloc,
    421     pdmR3DevHlp_MMHeapAllocZ,
    422     pdmR3DevHlp_MMHeapFree,
    423     pdmR3DevHlp_VMSetError,
    424     pdmR3DevHlp_VMSetErrorV,
    425     pdmR3DevHlp_VMSetRuntimeError,
    426     pdmR3DevHlp_VMSetRuntimeErrorV,
    427     pdmR3DevHlp_AssertEMT,
    428     pdmR3DevHlp_AssertOther,
    429     pdmR3DevHlp_DBGFStopV,
    430     pdmR3DevHlp_DBGFInfoRegister,
    431     pdmR3DevHlp_STAMRegister,
    432     pdmR3DevHlp_STAMRegisterF,
    433     pdmR3DevHlp_STAMRegisterV,
    434     pdmR3DevHlp_RTCRegister,
    435     pdmR3DevHlp_PDMQueueCreate,
    436     pdmR3DevHlp_CritSectInit,
    437     pdmR3DevHlp_UTCNow,
    438     pdmR3DevHlp_PDMThreadCreate,
    439     pdmR3DevHlp_PhysGCPtr2GCPhys,
    440     pdmR3DevHlp_VMState,
    441     0,
    442     0,
    443     0,
    444     0,
    445     0,
    446     0,
    447     0,
    448     pdmR3DevHlp_Untrusted_GetVM,
    449     pdmR3DevHlp_Untrusted_PCIBusRegister,
    450     pdmR3DevHlp_Untrusted_PICRegister,
    451     pdmR3DevHlp_Untrusted_APICRegister,
    452     pdmR3DevHlp_Untrusted_IOAPICRegister,
    453     pdmR3DevHlp_Untrusted_DMACRegister,
    454     pdmR3DevHlp_Untrusted_PhysRead,
    455     pdmR3DevHlp_Untrusted_PhysWrite,
    456     pdmR3DevHlp_Untrusted_PhysReadGCVirt,
    457     pdmR3DevHlp_Untrusted_PhysWriteGCVirt,
    458     pdmR3DevHlp_Untrusted_PhysReserve,
    459     pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt,
    460     pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr,
    461     pdmR3DevHlp_Untrusted_A20IsEnabled,
    462     pdmR3DevHlp_Untrusted_A20Set,
    463     pdmR3DevHlp_Untrusted_VMReset,
    464     pdmR3DevHlp_Untrusted_VMSuspend,
    465     pdmR3DevHlp_Untrusted_VMPowerOff,
    466     pdmR3DevHlp_Untrusted_LockVM,
    467     pdmR3DevHlp_Untrusted_UnlockVM,
    468     pdmR3DevHlp_Untrusted_AssertVMLock,
    469     pdmR3DevHlp_Untrusted_DMARegister,
    470     pdmR3DevHlp_Untrusted_DMAReadMemory,
    471     pdmR3DevHlp_Untrusted_DMAWriteMemory,
    472     pdmR3DevHlp_Untrusted_DMASetDREQ,
    473     pdmR3DevHlp_Untrusted_DMAGetChannelMode,
    474     pdmR3DevHlp_Untrusted_DMASchedule,
    475     pdmR3DevHlp_Untrusted_CMOSWrite,
    476     pdmR3DevHlp_Untrusted_CMOSRead,
    477     pdmR3DevHlp_Untrusted_GetCpuId,
    478     pdmR3DevHlp_Untrusted_ROMProtectShadow,
    479     pdmR3DevHlp_Untrusted_MMIO2Register,
    480     pdmR3DevHlp_Untrusted_MMIO2Deregister,
    481     pdmR3DevHlp_Untrusted_MMIO2Map,
    482     pdmR3DevHlp_Untrusted_MMIO2Unmap,
    483     pdmR3DevHlp_Untrusted_MMHyperMapMMIO2,
    484     pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
    485     pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap,
    486     PDM_DEVHLP_VERSION /* the end */
    487 };
     44
     45/** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
     46static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
     47{
     48    PDMDEV_ASSERT_DEVINS(pDevIns);
     49    PVM pVM = pDevIns->Internal.s.pVMR3;
     50    LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
     51             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pVM, 0, VM_FF_INTERRUPT_PIC)));
     52    /* for PIC we always deliver to CPU 0, MP use APIC */
     53    VMCPU_FF_SET(pVM, 0, VM_FF_INTERRUPT_PIC);
     54    REMR3NotifyInterruptSet(pVM);
     55    VMR3NotifyFF(pVM, true);
     56}
     57
     58
     59/** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
     60static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
     61{
     62    PDMDEV_ASSERT_DEVINS(pDevIns);
     63    LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
     64             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC)));
     65    /* for PIC we always deliver to CPU 0, MP use APIC */
     66    VMCPU_FF_CLEAR(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC);
     67    REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMR3);
     68}
     69
     70
     71/** @copydoc PDMPICHLPR3::pfnLock */
     72static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
     73{
     74    PDMDEV_ASSERT_DEVINS(pDevIns);
     75    return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
     76}
     77
     78
     79/** @copydoc PDMPICHLPR3::pfnUnlock */
     80static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
     81{
     82    PDMDEV_ASSERT_DEVINS(pDevIns);
     83    pdmUnlock(pDevIns->Internal.s.pVMR3);
     84}
     85
     86
     87/** @copydoc PDMPICHLPR3::pfnGetRCHelpers */
     88static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
     89{
     90    PDMDEV_ASSERT_DEVINS(pDevIns);
     91    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     92    RTRCPTR pRCHelpers = 0;
     93    int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPicHlp", &pRCHelpers);
     94    AssertReleaseRC(rc);
     95    AssertRelease(pRCHelpers);
     96    LogFlow(("pdmR3PicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
     97             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
     98    return pRCHelpers;
     99}
     100
     101
     102/** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
     103static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
     104{
     105    PDMDEV_ASSERT_DEVINS(pDevIns);
     106    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
     107    PCPDMPICHLPR0 pR0Helpers = 0;
     108    int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PicHlp", &pR0Helpers);
     109    AssertReleaseRC(rc);
     110    AssertRelease(pR0Helpers);
     111    LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
     112             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
     113    return pR0Helpers;
     114}
    488115
    489116
     
    503130};
    504131
    505 
    506 /**
    507  * APIC Device Helpers.
    508  */
    509 const PDMAPICHLPR3 g_pdmR3DevApicHlp =
    510 {
    511     PDM_APICHLPR3_VERSION,
    512     pdmR3ApicHlp_SetInterruptFF,
    513     pdmR3ApicHlp_ClearInterruptFF,
    514     pdmR3ApicHlp_ChangeFeature,
    515     pdmR3ApicHlp_Lock,
    516     pdmR3ApicHlp_Unlock,
    517     pdmR3ApicHlp_GetCpuId,
    518     pdmR3ApicHlp_GetRCHelpers,
    519     pdmR3ApicHlp_GetR0Helpers,
    520     PDM_APICHLPR3_VERSION /* the end */
    521 };
    522 
    523 
    524 /**
    525  * I/O APIC Device Helpers.
    526  */
    527 const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
    528 {
    529     PDM_IOAPICHLPR3_VERSION,
    530     pdmR3IoApicHlp_ApicBusDeliver,
    531     pdmR3IoApicHlp_Lock,
    532     pdmR3IoApicHlp_Unlock,
    533     pdmR3IoApicHlp_GetRCHelpers,
    534     pdmR3IoApicHlp_GetR0Helpers,
    535     PDM_IOAPICHLPR3_VERSION /* the end */
    536 };
    537 
    538 
    539 /**
    540  * PCI Bus Device Helpers.
    541  */
    542 const PDMPCIHLPR3 g_pdmR3DevPciHlp =
    543 {
    544     PDM_PCIHLPR3_VERSION,
    545     pdmR3PciHlp_IsaSetIrq,
    546     pdmR3PciHlp_IoApicSetIrq,
    547     pdmR3PciHlp_IsMMIO2Base,
    548     pdmR3PciHlp_GetRCHelpers,
    549     pdmR3PciHlp_GetR0Helpers,
    550     pdmR3PciHlp_Lock,
    551     pdmR3PciHlp_Unlock,
    552     PDM_PCIHLPR3_VERSION, /* the end */
    553 };
    554 
    555 
    556 /**
    557  * DMAC Device Helpers.
    558  */
    559 const PDMDMACHLP g_pdmR3DevDmacHlp =
    560 {
    561     PDM_DMACHLP_VERSION
    562 };
    563 
    564 
    565 /**
    566  * RTC Device Helpers.
    567  */
    568 const PDMRTCHLP g_pdmR3DevRtcHlp =
    569 {
    570     PDM_RTCHLP_VERSION
    571 };
    572 
    573 
    574 
    575 /**
    576  * This function will initialize the devices for this VM instance.
    577  *
    578  *
    579  * First of all this mean loading the builtin device and letting them
    580  * register themselves. Beyond that any additional device modules are
    581  * loaded and called for registration.
    582  *
    583  * Then the device configuration is enumerated, the instantiation order
    584  * is determined, and finally they are instantiated.
    585  *
    586  * After all device have been successfully instantiated the the primary
    587  * PCI Bus device is called to emulate the PCI BIOS, i.e. making the
    588  * resource assignments. If there is no PCI device, this step is of course
    589  * skipped.
    590  *
    591  * Finally the init completion routines of the instantiated devices
    592  * are called.
    593  *
    594  * @returns VBox status code.
    595  * @param   pVM     VM Handle.
    596  */
    597 int pdmR3DevInit(PVM pVM)
    598 {
    599     LogFlow(("pdmR3DevInit:\n"));
    600 
    601     AssertRelease(!(RT_OFFSETOF(PDMDEVINS, achInstanceData) & 15));
    602     AssertRelease(sizeof(pVM->pdm.s.pDevInstances->Internal.s) <= sizeof(pVM->pdm.s.pDevInstances->Internal.padding));
    603 
    604     /*
    605      * Load device modules.
    606      */
    607     int rc = pdmR3DevLoadModules(pVM);
    608     if (RT_FAILURE(rc))
    609         return rc;
    610 
    611 #ifdef VBOX_WITH_USB
    612     /* ditto for USB Devices. */
    613     rc = pdmR3UsbLoadModules(pVM);
    614     if (RT_FAILURE(rc))
    615         return rc;
    616 #endif
    617 
    618     /*
    619      * Get the RC & R0 devhlps and create the devhlp R3 task queue.
    620      */
    621     PCPDMDEVHLPRC pDevHlpRC;
    622     rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCDevHlp", &pDevHlpRC);
    623     AssertReleaseRCReturn(rc, rc);
    624 
    625     PCPDMDEVHLPR0 pDevHlpR0;
    626     rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0DevHlp", &pDevHlpR0);
    627     AssertReleaseRCReturn(rc, rc);
    628 
    629     rc = PDMR3QueueCreateInternal(pVM, sizeof(PDMDEVHLPTASK), 8, 0, pdmR3DevHlpQueueConsumer, true, &pVM->pdm.s.pDevHlpQueueHC);
    630     AssertRCReturn(rc, rc);
    631     pVM->pdm.s.pDevHlpQueueGC = PDMQueueGCPtr(pVM->pdm.s.pDevHlpQueueHC);
    632 
    633 
    634     /*
    635      *
    636      * Enumerate the device instance configurations
    637      * and come up with a instantiation order.
    638      *
    639      */
    640     /* Switch to /Devices, which contains the device instantiations. */
    641     PCFGMNODE pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "Devices");
    642 
    643     /*
    644      * Count the device instances.
    645      */
    646     PCFGMNODE pCur;
    647     PCFGMNODE pInstanceNode;
    648     unsigned cDevs = 0;
    649     for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
    650         for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
    651             cDevs++;
    652     if (!cDevs)
    653     {
    654         Log(("PDM: No devices were configured!\n"));
    655         return VINF_SUCCESS;
    656     }
    657     Log2(("PDM: cDevs=%d!\n", cDevs));
    658 
    659     /*
    660      * Collect info on each device instance.
    661      */
    662     struct DEVORDER
    663     {
    664         /** Configuration node. */
    665         PCFGMNODE   pNode;
    666         /** Pointer to device. */
    667         PPDMDEV     pDev;
    668         /** Init order. */
    669         uint32_t    u32Order;
    670         /** VBox instance number. */
    671         uint32_t    iInstance;
    672     } *paDevs = (struct DEVORDER *)alloca(sizeof(paDevs[0]) * (cDevs + 1)); /* (One extra for swapping) */
    673     Assert(paDevs);
    674     unsigned i = 0;
    675     for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
    676     {
    677         /* Get the device name. */
    678         char szName[sizeof(paDevs[0].pDev->pDevReg->szDeviceName)];
    679         rc = CFGMR3GetName(pCur, szName, sizeof(szName));
    680         AssertMsgRCReturn(rc, ("Configuration error: device name is too long (or something)! rc=%Vrc\n", rc), rc);
    681 
    682         /* Find the device. */
    683         PPDMDEV pDev = pdmR3DevLookup(pVM, szName);
    684         AssertMsgReturn(pDev, ("Configuration error: device '%s' not found!\n", szName), VERR_PDM_DEVICE_NOT_FOUND);
    685 
    686         /* Configured priority or use default based on device class? */
    687         uint32_t u32Order;
    688         rc = CFGMR3QueryU32(pCur, "Priority", &u32Order);
    689         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    690         {
    691             uint32_t u32 = pDev->pDevReg->fClass;
    692             for (u32Order = 1; !(u32 & u32Order); u32Order <<= 1)
    693                 /* nop */;
    694         }
    695         else
    696             AssertMsgRCReturn(rc, ("Configuration error: reading \"Priority\" for the '%s' device failed rc=%Vrc!\n", szName, rc), rc);
    697 
    698         /* Enumerate the device instances. */
    699         for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
    700         {
    701             paDevs[i].pNode = pInstanceNode;
    702             paDevs[i].pDev = pDev;
    703             paDevs[i].u32Order = u32Order;
    704 
    705             /* Get the instance number. */
    706             char szInstance[32];
    707             rc = CFGMR3GetName(pInstanceNode, szInstance, sizeof(szInstance));
    708             AssertMsgRCReturn(rc, ("Configuration error: instance name is too long (or something)! rc=%Vrc\n", rc), rc);
    709             char *pszNext = NULL;
    710             rc = RTStrToUInt32Ex(szInstance, &pszNext, 0, &paDevs[i].iInstance);
    711             AssertMsgRCReturn(rc, ("Configuration error: RTStrToInt32Ex failed on the instance name '%s'! rc=%Vrc\n", szInstance, rc), rc);
    712             AssertMsgReturn(!*pszNext, ("Configuration error: the instance name '%s' isn't all digits. (%s)\n", szInstance, pszNext), VERR_INVALID_PARAMETER);
    713 
    714             /* next instance */
    715             i++;
    716         }
    717     } /* devices */
    718     Assert(i == cDevs);
    719 
    720     /*
    721      * Sort the device array ascending on u32Order. (bubble)
    722      */
    723     unsigned c = cDevs - 1;
    724     while (c)
    725     {
    726         unsigned j = 0;
    727         for (i = 0; i < c; i++)
    728             if (paDevs[i].u32Order > paDevs[i + 1].u32Order)
    729             {
    730                 paDevs[cDevs] = paDevs[i + 1];
    731                 paDevs[i + 1] = paDevs[i];
    732                 paDevs[i] = paDevs[cDevs];
    733                 j = i;
    734             }
    735         c = j;
    736     }
    737 
    738 
    739     /*
    740      *
    741      * Instantiate the devices.
    742      *
    743      */
    744     for (i = 0; i < cDevs; i++)
    745     {
    746         /*
    747          * Gather a bit of config.
    748          */
    749         /* trusted */
    750         bool fTrusted;
    751         rc = CFGMR3QueryBool(paDevs[i].pNode, "Trusted", &fTrusted);
    752         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    753             fTrusted = false;
    754         else if (VBOX_FAILURE(rc))
    755         {
    756             AssertMsgFailed(("configuration error: failed to query boolean \"Trusted\", rc=%Vrc\n", rc));
    757             return rc;
    758         }
    759         /* config node */
    760         PCFGMNODE pConfigNode = CFGMR3GetChild(paDevs[i].pNode, "Config");
    761         if (!pConfigNode)
    762         {
    763             rc = CFGMR3InsertNode(paDevs[i].pNode, "Config", &pConfigNode);
    764             if (VBOX_FAILURE(rc))
    765             {
    766                 AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
    767                 return rc;
    768             }
    769         }
    770         CFGMR3SetRestrictedRoot(pConfigNode);
    771 
    772         /*
    773          * Allocate the device instance.
    774          */
    775         size_t cb = RT_OFFSETOF(PDMDEVINS, achInstanceData[paDevs[i].pDev->pDevReg->cbInstance]);
    776         cb = RT_ALIGN_Z(cb, 16);
    777         PPDMDEVINS pDevIns;
    778         if (paDevs[i].pDev->pDevReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0))
    779             rc = MMR3HyperAllocOnceNoRel(pVM, cb, 0, MM_TAG_PDM_DEVICE, (void **)&pDevIns);
    780         else
    781             rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_DEVICE, cb, (void **)&pDevIns);
    782         if (VBOX_FAILURE(rc))
    783         {
    784             AssertMsgFailed(("Failed to allocate %d bytes of instance data for device '%s'. rc=%Vrc\n",
    785                              cb, paDevs[i].pDev->pDevReg->szDeviceName, rc));
    786             return rc;
    787         }
    788 
    789         /*
    790          * Initialize it.
    791          */
    792         pDevIns->u32Version                     = PDM_DEVINS_VERSION;
    793         //pDevIns->Internal.s.pNextR3             = NULL;
    794         //pDevIns->Internal.s.pPerDeviceNextR3    = NULL;
    795         pDevIns->Internal.s.pDevR3              = paDevs[i].pDev;
    796         pDevIns->Internal.s.pVMR3               = pVM;
    797         pDevIns->Internal.s.pVMR0               = pVM->pVMR0;
    798         pDevIns->Internal.s.pVMRC               = pVM->pVMRC;
    799         //pDevIns->Internal.s.pLunsR3             = NULL;
    800         pDevIns->Internal.s.pCfgHandle          = paDevs[i].pNode;
    801         //pDevIns->Internal.s.pPciDeviceR3        = NULL;
    802         //pDevIns->Internal.s.pPciBusR3           = NULL; /** @todo pci bus selection. (in 2008 perhaps) */
    803         //pDevIns->Internal.s.pPciDeviceR0        = 0;
    804         //pDevIns->Internal.s.pPciBusR0           = 0;
    805         //pDevIns->Internal.s.pPciDeviceRC        = 0;
    806         //pDevIns->Internal.s.pPciBusRC           = 0;
    807         pDevIns->pDevHlpR3                      = fTrusted ? &g_pdmR3DevHlpTrusted : &g_pdmR3DevHlpUnTrusted;
    808         pDevIns->pDevHlpRC                      = pDevHlpRC;
    809         pDevIns->pDevHlpR0                      = pDevHlpR0;
    810         pDevIns->pDevReg                        = paDevs[i].pDev->pDevReg;
    811         pDevIns->pCfgHandle                     = pConfigNode;
    812         pDevIns->iInstance                      = paDevs[i].iInstance;
    813         pDevIns->pvInstanceDataR3               = &pDevIns->achInstanceData[0];
    814         pDevIns->pvInstanceDataRC               = pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC
    815                                                 ? MMHyperR3ToRC(pVM, pDevIns->pvInstanceDataR3) : NIL_RTRCPTR;
    816         pDevIns->pvInstanceDataR0               = pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0
    817                                                 ? MMHyperR3ToR0(pVM, pDevIns->pvInstanceDataR3) : NIL_RTR0PTR;
    818 
    819         /*
    820          * Link it into all the lists.
    821          */
    822         /* The global instance FIFO. */
    823         PPDMDEVINS pPrev1 = pVM->pdm.s.pDevInstances;
    824         if (!pPrev1)
    825             pVM->pdm.s.pDevInstances = pDevIns;
    826         else
    827         {
    828             while (pPrev1->Internal.s.pNextR3)
    829                 pPrev1 = pPrev1->Internal.s.pNextR3;
    830             pPrev1->Internal.s.pNextR3 = pDevIns;
    831         }
    832 
    833         /* The per device instance FIFO. */
    834         PPDMDEVINS pPrev2 = paDevs[i].pDev->pInstances;
    835         if (!pPrev2)
    836             paDevs[i].pDev->pInstances = pDevIns;
    837         else
    838         {
    839             while (pPrev2->Internal.s.pPerDeviceNextR3)
    840                 pPrev2 = pPrev2->Internal.s.pPerDeviceNextR3;
    841             pPrev2->Internal.s.pPerDeviceNextR3 = pDevIns;
    842         }
    843 
    844         /*
    845          * Call the constructor.
    846          */
    847         Log(("PDM: Constructing device '%s' instance %d...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    848         rc = pDevIns->pDevReg->pfnConstruct(pDevIns, pDevIns->iInstance, pDevIns->pCfgHandle);
    849         if (VBOX_FAILURE(rc))
    850         {
    851             LogRel(("PDM: Failed to construct '%s'/%d! %Vra\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    852             /* because we're damn lazy right now, we'll say that the destructor will be called even if the constructor fails. */
    853             return rc;
    854         }
    855     } /* for device instances */
    856 
    857 #ifdef VBOX_WITH_USB
    858     /* ditto for USB Devices. */
    859     rc = pdmR3UsbInstantiateDevices(pVM);
    860     if (RT_FAILURE(rc))
    861         return rc;
    862 #endif
    863 
    864 
    865     /*
    866      *
    867      * PCI BIOS Fake and Init Complete.
    868      *
    869      */
    870     if (pVM->pdm.s.aPciBuses[0].pDevInsR3)
    871     {
    872         pdmLock(pVM);
    873         rc = pVM->pdm.s.aPciBuses[0].pfnFakePCIBIOSR3(pVM->pdm.s.aPciBuses[0].pDevInsR3);
    874         pdmUnlock(pVM);
    875         if (VBOX_FAILURE(rc))
    876         {
    877             AssertMsgFailed(("PCI BIOS fake failed rc=%Vrc\n", rc));
    878             return rc;
    879         }
    880     }
    881 
    882     for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
    883     {
    884         if (pDevIns->pDevReg->pfnInitComplete)
    885         {
    886             rc = pDevIns->pDevReg->pfnInitComplete(pDevIns);
    887             if (VBOX_FAILURE(rc))
    888             {
    889                 AssertMsgFailed(("InitComplete on device '%s'/%d failed with rc=%Vrc\n",
    890                                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    891                 return rc;
    892             }
    893         }
    894     }
    895 
    896 #ifdef VBOX_WITH_USB
    897     /* ditto for USB Devices. */
    898     rc = pdmR3UsbVMInitComplete(pVM);
    899     if (RT_FAILURE(rc))
    900         return rc;
    901 #endif
    902 
    903     LogFlow(("pdmR3DevInit: returns %Vrc\n", VINF_SUCCESS));
    904     return VINF_SUCCESS;
    905 }
    906 
    907 
    908 /**
    909  * Lookups a device structure by name.
    910  * @internal
    911  */
    912 PPDMDEV pdmR3DevLookup(PVM pVM, const char *pszName)
    913 {
    914     RTUINT cchName = strlen(pszName);
    915     for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
    916         if (    pDev->cchName == cchName
    917             &&  !strcmp(pDev->pDevReg->szDeviceName, pszName))
    918             return pDev;
    919     return NULL;
    920 }
    921 
    922 
    923 /**
    924  * Loads the device modules.
    925  *
    926  * @returns VBox status code.
    927  * @param   pVM     Pointer to the shared VM structure.
    928  */
    929 static int pdmR3DevLoadModules(PVM pVM)
    930 {
    931     /*
    932      * Initialize the callback structure.
    933      */
    934     PDMDEVREGCBINT RegCB;
    935     RegCB.Core.u32Version = PDM_DEVREG_CB_VERSION;
    936     RegCB.Core.pfnRegister = pdmR3DevReg_Register;
    937     RegCB.Core.pfnMMHeapAlloc = pdmR3DevReg_MMHeapAlloc;
    938     RegCB.pVM = pVM;
    939 
    940     /*
    941      * Load the builtin module
    942      */
    943     PCFGMNODE pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Devices");
    944     bool fLoadBuiltin;
    945     int rc = CFGMR3QueryBool(pDevicesNode, "LoadBuiltin", &fLoadBuiltin);
    946     if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    947         fLoadBuiltin = true;
    948     else if (VBOX_FAILURE(rc))
    949     {
    950         AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Vrc\n", rc));
    951         return rc;
    952     }
    953     if (fLoadBuiltin)
    954     {
    955         /* make filename */
    956         char *pszFilename = pdmR3FileR3("VBoxDD", /* fShared = */ true);
    957         if (!pszFilename)
    958             return VERR_NO_TMP_MEMORY;
    959         rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD");
    960         RTMemTmpFree(pszFilename);
    961         if (VBOX_FAILURE(rc))
    962             return rc;
    963 
    964         /* make filename */
    965         pszFilename = pdmR3FileR3("VBoxDD2", /* fShared = */ true);
    966         if (!pszFilename)
    967             return VERR_NO_TMP_MEMORY;
    968         rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD2");
    969         RTMemTmpFree(pszFilename);
    970         if (VBOX_FAILURE(rc))
    971             return rc;
    972     }
    973 
    974     /*
    975      * Load additional device modules.
    976      */
    977     PCFGMNODE pCur;
    978     for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
    979     {
    980         /*
    981          * Get the name and path.
    982          */
    983         char szName[PDMMOD_NAME_LEN];
    984         rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
    985         if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
    986         {
    987             AssertMsgFailed(("configuration error: The module name is too long, cchName=%d.\n", CFGMR3GetNameLen(pCur)));
    988             return VERR_PDM_MODULE_NAME_TOO_LONG;
    989         }
    990         else if (VBOX_FAILURE(rc))
    991         {
    992             AssertMsgFailed(("CFGMR3GetName -> %Vrc.\n", rc));
    993             return rc;
    994         }
    995 
    996         /* the path is optional, if no path the module name + path is used. */
    997         char szFilename[RTPATH_MAX];
    998         rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
    999         if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    1000             strcpy(szFilename, szName);
    1001         else if (VBOX_FAILURE(rc))
    1002         {
    1003             AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Vrc.\n", rc));
    1004             return rc;
    1005         }
    1006 
    1007         /* prepend path? */
    1008         if (!RTPathHavePath(szFilename))
    1009         {
    1010             char *psz = pdmR3FileR3(szFilename);
    1011             if (!psz)
    1012                 return VERR_NO_TMP_MEMORY;
    1013             size_t cch = strlen(psz) + 1;
    1014             if (cch > sizeof(szFilename))
    1015             {
    1016                 RTMemTmpFree(psz);
    1017                 AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
    1018                 return VERR_FILENAME_TOO_LONG;
    1019             }
    1020             memcpy(szFilename, psz, cch);
    1021             RTMemTmpFree(psz);
    1022         }
    1023 
    1024         /*
    1025          * Load the module and register it's devices.
    1026          */
    1027         rc = pdmR3DevLoad(pVM, &RegCB, szFilename, szName);
    1028         if (VBOX_FAILURE(rc))
    1029             return rc;
    1030     }
    1031 
    1032     return VINF_SUCCESS;
    1033 }
    1034 
    1035 
    1036 /**
    1037  * Loads one device module and call the registration entry point.
    1038  *
    1039  * @returns VBox status code.
    1040  * @param   pVM             VM handle.
    1041  * @param   pRegCB          The registration callback stuff.
    1042  * @param   pszFilename     Module filename.
    1043  * @param   pszName         Module name.
    1044  */
    1045 static int pdmR3DevLoad(PVM pVM, PPDMDEVREGCBINT pRegCB, const char *pszFilename, const char *pszName)
    1046 {
    1047     /*
    1048      * Load it.
    1049      */
    1050     int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
    1051     if (VBOX_SUCCESS(rc))
    1052     {
    1053         /*
    1054          * Get the registration export and call it.
    1055          */
    1056         FNPDMVBOXDEVICESREGISTER *pfnVBoxDevicesRegister;
    1057         rc = PDMR3LdrGetSymbolR3(pVM, pszName, "VBoxDevicesRegister", (void **)&pfnVBoxDevicesRegister);
    1058         if (VBOX_SUCCESS(rc))
    1059         {
    1060             Log(("PDM: Calling VBoxDevicesRegister (%p) of %s (%s)\n", pfnVBoxDevicesRegister, pszName, pszFilename));
    1061             rc = pfnVBoxDevicesRegister(&pRegCB->Core, VBOX_VERSION);
    1062             if (VBOX_SUCCESS(rc))
    1063                 Log(("PDM: Successfully loaded device module %s (%s).\n", pszName, pszFilename));
    1064             else
    1065                 AssertMsgFailed(("VBoxDevicesRegister failed with rc=%Vrc for module %s (%s)\n", rc, pszName, pszFilename));
    1066         }
    1067         else
    1068         {
    1069             AssertMsgFailed(("Failed to locate 'VBoxDevicesRegister' in %s (%s) rc=%Vrc\n", pszName, pszFilename, rc));
    1070             if (rc == VERR_SYMBOL_NOT_FOUND)
    1071                 rc = VERR_PDM_NO_REGISTRATION_EXPORT;
    1072         }
    1073     }
    1074     else
    1075         AssertMsgFailed(("Failed to load %s %s!\n", pszFilename, pszName));
    1076     return rc;
    1077 }
    1078 
    1079 
    1080 
    1081 /**
    1082  * Registers a device with the current VM instance.
    1083  *
    1084  * @returns VBox status code.
    1085  * @param   pCallbacks      Pointer to the callback table.
    1086  * @param   pDevReg         Pointer to the device registration record.
    1087  *                          This data must be permanent and readonly.
    1088  */
    1089 static DECLCALLBACK(int) pdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pDevReg)
    1090 {
    1091     /*
    1092      * Validate the registration structure.
    1093      */
    1094     Assert(pDevReg);
    1095     if (pDevReg->u32Version != PDM_DEVREG_VERSION)
    1096     {
    1097         AssertMsgFailed(("Unknown struct version %#x!\n", pDevReg->u32Version));
    1098         return VERR_PDM_UNKNOWN_DEVREG_VERSION;
    1099     }
    1100     if (    !pDevReg->szDeviceName[0]
    1101         ||  strlen(pDevReg->szDeviceName) >= sizeof(pDevReg->szDeviceName))
    1102     {
    1103         AssertMsgFailed(("Invalid name '%s'\n", pDevReg->szDeviceName));
    1104         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1105     }
    1106     if (    (pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1107         &&  (   !pDevReg->szRCMod[0]
    1108              || strlen(pDevReg->szRCMod) >= sizeof(pDevReg->szRCMod)))
    1109     {
    1110         AssertMsgFailed(("Invalid GC module name '%s' - (Device %s)\n", pDevReg->szRCMod, pDevReg->szDeviceName));
    1111         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1112     }
    1113     if (    (pDevReg->fFlags & PDM_DEVREG_FLAGS_R0)
    1114         &&  (   !pDevReg->szR0Mod[0]
    1115              || strlen(pDevReg->szR0Mod) >= sizeof(pDevReg->szR0Mod)))
    1116     {
    1117         AssertMsgFailed(("Invalid R0 module name '%s' - (Device %s)\n", pDevReg->szR0Mod, pDevReg->szDeviceName));
    1118         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1119     }
    1120     if ((pDevReg->fFlags & PDM_DEVREG_FLAGS_HOST_BITS_MASK) != PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT)
    1121     {
    1122         AssertMsgFailed(("Invalid host bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
    1123         return VERR_PDM_INVALID_DEVICE_HOST_BITS;
    1124     }
    1125     if (!(pDevReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_MASK))
    1126     {
    1127         AssertMsgFailed(("Invalid guest bits flags! fFlags=%#x (Device %s)\n", pDevReg->fFlags, pDevReg->szDeviceName));
    1128         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1129     }
    1130     if (!pDevReg->fClass)
    1131     {
    1132         AssertMsgFailed(("No class! (Device %s)\n", pDevReg->szDeviceName));
    1133         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1134     }
    1135     if (pDevReg->cMaxInstances <= 0)
    1136     {
    1137         AssertMsgFailed(("Max instances %u! (Device %s)\n", pDevReg->cMaxInstances, pDevReg->szDeviceName));
    1138         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1139     }
    1140     if (pDevReg->cbInstance > (RTUINT)(pDevReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0)  ? 96 * _1K : _1M))
    1141     {
    1142         AssertMsgFailed(("Instance size %d bytes! (Device %s)\n", pDevReg->cbInstance, pDevReg->szDeviceName));
    1143         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1144     }
    1145     if (!pDevReg->pfnConstruct)
    1146     {
    1147         AssertMsgFailed(("No constructore! (Device %s)\n", pDevReg->szDeviceName));
    1148         return VERR_PDM_INVALID_DEVICE_REGISTRATION;
    1149     }
    1150     /* Check matching guest bits last without any asserting. Enables trial and error registration. */
    1151     if (!(pDevReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT))
    1152     {
    1153         Log(("PDM: Rejected device '%s' because it didn't match the guest bits.\n", pDevReg->szDeviceName));
    1154         return VERR_PDM_INVALID_DEVICE_GUEST_BITS;
    1155     }
    1156     AssertLogRelMsg(pDevReg->u32VersionEnd == PDM_DEVREG_VERSION,
    1157                     ("u32VersionEnd=%#x, expected %#x. (szDeviceName=%s)\n",
    1158                      pDevReg->u32VersionEnd, PDM_DEVREG_VERSION, pDevReg->szDeviceName));
    1159 
    1160     /*
    1161      * Check for duplicate and find FIFO entry at the same time.
    1162      */
    1163     PCPDMDEVREGCBINT pRegCB = (PCPDMDEVREGCBINT)pCallbacks;
    1164     PPDMDEV pDevPrev = NULL;
    1165     PPDMDEV pDev = pRegCB->pVM->pdm.s.pDevs;
    1166     for (; pDev; pDevPrev = pDev, pDev = pDev->pNext)
    1167     {
    1168         if (!strcmp(pDev->pDevReg->szDeviceName, pDevReg->szDeviceName))
    1169         {
    1170             AssertMsgFailed(("Device '%s' already exists\n", pDevReg->szDeviceName));
    1171             return VERR_PDM_DEVICE_NAME_CLASH;
    1172         }
    1173     }
    1174 
    1175     /*
    1176      * Allocate new device structure and insert it into the list.
    1177      */
    1178     pDev = (PPDMDEV)MMR3HeapAlloc(pRegCB->pVM, MM_TAG_PDM_DEVICE, sizeof(*pDev));
    1179     if (pDev)
    1180     {
    1181         pDev->pNext = NULL;
    1182         pDev->cInstances = 0;
    1183         pDev->pInstances = NULL;
    1184         pDev->pDevReg = pDevReg;
    1185         pDev->cchName = strlen(pDevReg->szDeviceName);
    1186 
    1187         if (pDevPrev)
    1188             pDevPrev->pNext = pDev;
    1189         else
    1190             pRegCB->pVM->pdm.s.pDevs = pDev;
    1191         Log(("PDM: Registered device '%s'\n", pDevReg->szDeviceName));
    1192         return VINF_SUCCESS;
    1193     }
    1194     return VERR_NO_MEMORY;
    1195 }
    1196 
    1197 
    1198 /**
    1199  * Allocate memory which is associated with current VM instance
    1200  * and automatically freed on it's destruction.
    1201  *
    1202  * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
    1203  * @param   pCallbacks      Pointer to the callback table.
    1204  * @param   cb              Number of bytes to allocate.
    1205  */
    1206 static DECLCALLBACK(void *) pdmR3DevReg_MMHeapAlloc(PPDMDEVREGCB pCallbacks, size_t cb)
    1207 {
    1208     Assert(pCallbacks);
    1209     Assert(pCallbacks->u32Version == PDM_DEVREG_CB_VERSION);
    1210 
    1211     void *pv = MMR3HeapAlloc(((PPDMDEVREGCBINT)pCallbacks)->pVM, MM_TAG_PDM_DEVICE_USER, cb);
    1212     LogFlow(("pdmR3DevReg_MMHeapAlloc(,%#zx): returns %p\n", cb, pv));
    1213     return pv;
    1214 }
    1215 
    1216 
    1217 
    1218 
    1219 
    1220 /*
    1221  *
    1222  *
    1223  *
    1224  *
    1225  *   p d m R 3 D e v H l p
    1226  *   p d m R 3 D e v H l p
    1227  *   p d m R 3 D e v H l p
    1228  *
    1229  *
    1230  *
    1231  *
    1232  */
    1233 
    1234 
    1235 /**
    1236  * Queue consumer callback for internal component.
    1237  *
    1238  * @returns Success indicator.
    1239  *          If false the item will not be removed and the flushing will stop.
    1240  * @param   pVM         The VM handle.
    1241  * @param   pItem       The item to consume. Upon return this item will be freed.
    1242  */
    1243 static DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
    1244 {
    1245     PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
    1246     LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsHC));
    1247     switch (pTask->enmOp)
    1248     {
    1249         case PDMDEVHLPTASKOP_ISA_SET_IRQ:
    1250             PDMIsaSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
    1251             break;
    1252 
    1253         case PDMDEVHLPTASKOP_PCI_SET_IRQ:
    1254             pdmR3DevHlp_PCISetIrq(pTask->pDevInsHC, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
    1255             break;
    1256 
    1257         case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
    1258             PDMIoApicSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
    1259             break;
    1260 
    1261         default:
    1262             AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
    1263             break;
    1264     }
    1265     return true;
    1266 }
    1267 
    1268 
    1269 /** @copydoc PDMDEVHLPR3::pfnIOPortRegister */
    1270 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
    1271                                                     PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
    1272 {
    1273     PDMDEV_ASSERT_DEVINS(pDevIns);
    1274     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->pDevReg->szDeviceName, pDevIns->iInstance,
    1275              Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
    1276     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1277 
    1278     int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
    1279 
    1280     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1281     return rc;
    1282 }
    1283 
    1284 
    1285 /** @copydoc PDMDEVHLPR3::pfnIOPortRegisterGC */
    1286 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTRCPTR pvUser,
    1287                                                       const char *pszOut, const char *pszIn,
    1288                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    1289 {
    1290     PDMDEV_ASSERT_DEVINS(pDevIns);
    1291     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1292     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1293              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    1294 
    1295     /*
    1296      * Resolve the functions (one of the can be NULL).
    1297      */
    1298     int rc = VINF_SUCCESS;
    1299     if (    pDevIns->pDevReg->szRCMod[0]
    1300         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    1301     {
    1302         RTGCPTR32 GCPtrIn = 0;
    1303         if (pszIn)
    1304         {
    1305             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszIn, &GCPtrIn);
    1306             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szRCMod, pszIn));
    1307         }
    1308         RTGCPTR32 GCPtrOut = 0;
    1309         if (pszOut && VBOX_SUCCESS(rc))
    1310         {
    1311             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOut, &GCPtrOut);
    1312             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szRCMod, pszOut));
    1313         }
    1314         RTGCPTR32 GCPtrInStr = 0;
    1315         if (pszInStr && VBOX_SUCCESS(rc))
    1316         {
    1317             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszInStr, &GCPtrInStr);
    1318             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szRCMod, pszInStr));
    1319         }
    1320         RTGCPTR32 GCPtrOutStr = 0;
    1321         if (pszOutStr && VBOX_SUCCESS(rc))
    1322         {
    1323             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOutStr, &GCPtrOutStr);
    1324             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szRCMod, pszOutStr));
    1325         }
    1326 
    1327         if (VBOX_SUCCESS(rc))
    1328             rc = IOMR3IOPortRegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc);
    1329     }
    1330     else
    1331     {
    1332         AssertMsgFailed(("No GC module for this driver!\n"));
    1333         rc = VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     LogFlow(("pdmR3DevHlp_IOPortRegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1337     return rc;
    1338 }
    1339 
    1340 
    1341 /** @copydoc PDMDEVHLPR3::pfnIOPortRegisterR0 */
    1342 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser,
    1343                                                       const char *pszOut, const char *pszIn,
    1344                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    1345 {
    1346     PDMDEV_ASSERT_DEVINS(pDevIns);
    1347     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1348     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1349              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    1350 
    1351     /*
    1352      * Resolve the functions (one of the can be NULL).
    1353      */
    1354     int rc = VINF_SUCCESS;
    1355     if (    pDevIns->pDevReg->szR0Mod[0]
    1356         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    1357     {
    1358         R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;
    1359         if (pszIn)
    1360         {
    1361             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszIn, &pfnR0PtrIn);
    1362             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szR0Mod, pszIn));
    1363         }
    1364         R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;
    1365         if (pszOut && VBOX_SUCCESS(rc))
    1366         {
    1367             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOut, &pfnR0PtrOut);
    1368             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szR0Mod, pszOut));
    1369         }
    1370         R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;
    1371         if (pszInStr && VBOX_SUCCESS(rc))
    1372         {
    1373             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszInStr, &pfnR0PtrInStr);
    1374             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szR0Mod, pszInStr));
    1375         }
    1376         R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;
    1377         if (pszOutStr && VBOX_SUCCESS(rc))
    1378         {
    1379             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOutStr, &pfnR0PtrOutStr);
    1380             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szR0Mod, pszOutStr));
    1381         }
    1382 
    1383         if (VBOX_SUCCESS(rc))
    1384             rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
    1385     }
    1386     else
    1387     {
    1388         AssertMsgFailed(("No R0 module for this driver!\n"));
    1389         rc = VERR_INVALID_PARAMETER;
    1390     }
    1391 
    1392     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1393     return rc;
    1394 }
    1395 
    1396 
    1397 /** @copydoc PDMDEVHLPR3::pfnIOPortDeregister */
    1398 static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts)
    1399 {
    1400     PDMDEV_ASSERT_DEVINS(pDevIns);
    1401     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1402     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1403              Port, cPorts));
    1404 
    1405     int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts);
    1406 
    1407     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1408     return rc;
    1409 }
    1410 
    1411 
    1412 /** @copydoc PDMDEVHLPR3::pfnMMIORegister */
    1413 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
    1414                                                   PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
    1415                                                   const char *pszDesc)
    1416 {
    1417     PDMDEV_ASSERT_DEVINS(pDevIns);
    1418     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1419     LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p pszDesc=%p:{%s}\n",
    1420              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc, pszDesc));
    1421 
    1422     int rc = IOMR3MMIORegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc);
    1423 
    1424     LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1425     return rc;
    1426 }
    1427 
    1428 
    1429 /** @copydoc PDMDEVHLPR3::pfnMMIORegisterGC */
    1430 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
    1431                                                     const char *pszWrite, const char *pszRead, const char *pszFill,
    1432                                                     const char *pszDesc)
    1433 {
    1434     PDMDEV_ASSERT_DEVINS(pDevIns);
    1435     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1436     LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
    1437              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
    1438 
    1439     /*
    1440      * Resolve the functions.
    1441      * Not all function have to present, leave it to IOM to enforce this.
    1442      */
    1443     int rc = VINF_SUCCESS;
    1444     if (    pDevIns->pDevReg->szRCMod[0]
    1445         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    1446     {
    1447         RTGCPTR32 GCPtrWrite = 0;
    1448         if (pszWrite)
    1449             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszWrite, &GCPtrWrite);
    1450         RTGCPTR32 GCPtrRead = 0;
    1451         int rc2 = VINF_SUCCESS;
    1452         if (pszRead)
    1453             rc2 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszRead, &GCPtrRead);
    1454         RTGCPTR32 GCPtrFill = 0;
    1455         int rc3 = VINF_SUCCESS;
    1456         if (pszFill)
    1457             rc3 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszFill, &GCPtrFill);
    1458         if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1459             rc = IOMR3MMIORegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill);
    1460         else
    1461         {
    1462             AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szRCMod, pszWrite));
    1463             AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szRCMod, pszRead));
    1464             AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szRCMod, pszFill));
    1465             if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
    1466                 rc = rc2;
    1467             if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
    1468                 rc = rc3;
    1469         }
    1470     }
    1471     else
    1472     {
    1473         AssertMsgFailed(("No GC module for this driver!\n"));
    1474         rc = VERR_INVALID_PARAMETER;
    1475     }
    1476 
    1477     LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1478     return rc;
    1479 }
    1480 
    1481 /** @copydoc PDMDEVHLPR3::pfnMMIORegisterR0 */
    1482 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
    1483                                                     const char *pszWrite, const char *pszRead, const char *pszFill,
    1484                                                     const char *pszDesc)
    1485 {
    1486     PDMDEV_ASSERT_DEVINS(pDevIns);
    1487     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1488     LogFlow(("pdmR3DevHlp_MMIORegisterHC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
    1489              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
    1490 
    1491     /*
    1492      * Resolve the functions.
    1493      * Not all function have to present, leave it to IOM to enforce this.
    1494      */
    1495     int rc = VINF_SUCCESS;
    1496     if (    pDevIns->pDevReg->szR0Mod[0]
    1497         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    1498     {
    1499         R0PTRTYPE(PFNIOMMMIOWRITE) pfnR0PtrWrite = 0;
    1500         if (pszWrite)
    1501             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszWrite, &pfnR0PtrWrite);
    1502         R0PTRTYPE(PFNIOMMMIOREAD) pfnR0PtrRead = 0;
    1503         int rc2 = VINF_SUCCESS;
    1504         if (pszRead)
    1505             rc2 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszRead, &pfnR0PtrRead);
    1506         R0PTRTYPE(PFNIOMMMIOFILL) pfnR0PtrFill = 0;
    1507         int rc3 = VINF_SUCCESS;
    1508         if (pszFill)
    1509             rc3 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill);
    1510         if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1511             rc = IOMR3MMIORegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill);
    1512         else
    1513         {
    1514             AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szR0Mod, pszWrite));
    1515             AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szR0Mod, pszRead));
    1516             AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szR0Mod, pszFill));
    1517             if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
    1518                 rc = rc2;
    1519             if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
    1520                 rc = rc3;
    1521         }
    1522     }
    1523     else
    1524     {
    1525         AssertMsgFailed(("No R0 module for this driver!\n"));
    1526         rc = VERR_INVALID_PARAMETER;
    1527     }
    1528 
    1529     LogFlow(("pdmR3DevHlp_MMIORegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1530     return rc;
    1531 }
    1532 
    1533 
    1534 /** @copydoc PDMDEVHLPR3::pfnMMIODeregister */
    1535 static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    1536 {
    1537     PDMDEV_ASSERT_DEVINS(pDevIns);
    1538     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1539     LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
    1540              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
    1541 
    1542     int rc = IOMR3MMIODeregister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange);
    1543 
    1544     LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1545     return rc;
    1546 }
    1547 
    1548 
    1549 /** @copydoc PDMDEVHLPR3::pfnROMRegister */
    1550 static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc)
    1551 {
    1552     PDMDEV_ASSERT_DEVINS(pDevIns);
    1553     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1554     LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvBinary=%p fShadow=%RTbool pszDesc=%p:{%s}\n",
    1555              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc, pszDesc));
    1556 
    1557     int rc = MMR3PhysRomRegister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc);
    1558 
    1559     LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1560     return rc;
    1561 }
    1562 
    1563 
    1564 /** @copydoc PDMDEVHLPR3::pfnSSMRegister */
    1565 static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
    1566                                                  PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
    1567                                                  PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
    1568 {
    1569     PDMDEV_ASSERT_DEVINS(pDevIns);
    1570     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1571     LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: pszName=%p:{%s} u32Instance=%#x u32Version=#x cbGuess=%#x pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoaddone=%p\n",
    1572              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
    1573 
    1574     int rc = SSMR3Register(pDevIns->Internal.s.pVMR3, pDevIns, pszName, u32Instance, u32Version, cbGuess,
    1575                            pfnSavePrep, pfnSaveExec, pfnSaveDone,
    1576                            pfnLoadPrep, pfnLoadExec, pfnLoadDone);
    1577 
    1578     LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1579     return rc;
    1580 }
    1581 
    1582 
    1583 /** @copydoc PDMDEVHLPR3::pfnTMTimerCreate */
    1584 static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
    1585 {
    1586     PDMDEV_ASSERT_DEVINS(pDevIns);
    1587     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1588     LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
    1589              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
    1590 
    1591     int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
    1592 
    1593     LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1594     return rc;
    1595 }
    1596 
    1597 
    1598 /** @copydoc PDMDEVHLPR3::pfnTMTimerCreateExternal */
    1599 static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc)
    1600 {
    1601     PDMDEV_ASSERT_DEVINS(pDevIns);
    1602     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1603 
    1604     return TMR3TimerCreateExternal(pDevIns->Internal.s.pVMR3, enmClock, pfnCallback, pvUser, pszDesc);
    1605 }
    1606 
    1607 /** @copydoc PDMDEVHLPR3::pfnPCIRegister */
    1608 static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev)
    1609 {
    1610     PDMDEV_ASSERT_DEVINS(pDevIns);
    1611     PVM pVM = pDevIns->Internal.s.pVMR3;
    1612     VM_ASSERT_EMT(pVM);
    1613     LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Vhxs}\n",
    1614              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pPciDev->config));
    1615 
    1616     /*
    1617      * Validate input.
    1618      */
    1619     if (!pPciDev)
    1620     {
    1621         Assert(pPciDev);
    1622         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (pPciDev)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1623         return VERR_INVALID_PARAMETER;
    1624     }
    1625     if (!pPciDev->config[0] && !pPciDev->config[1])
    1626     {
    1627         Assert(pPciDev->config[0] || pPciDev->config[1]);
    1628         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (vendor)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1629         return VERR_INVALID_PARAMETER;
    1630     }
    1631     if (pDevIns->Internal.s.pPciDeviceR3)
    1632     {
    1633         /** @todo the PCI device vs. PDM device designed is a bit flawed if we have to
    1634          * support a PDM device with multiple PCI devices. This might become a problem
    1635          * when upgrading the chipset for instance...
    1636          */
    1637         AssertMsgFailed(("Only one PCI device per device is currently implemented!\n"));
    1638         return VERR_INTERNAL_ERROR;
    1639     }
    1640 
    1641     /*
    1642      * Choose the PCI bus for the device.
    1643      * This is simple. If the device was configured for a particular bus, it'll
    1644      * already have one. If not, we'll just take the first one.
    1645      */
    1646     PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1647     if (!pBus)
    1648         pBus = pDevIns->Internal.s.pPciBusR3 = &pVM->pdm.s.aPciBuses[0];
    1649     int rc;
    1650     if (pBus)
    1651     {
    1652         if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1653             pDevIns->Internal.s.pPciBusR0 = MMHyperR3ToR0(pVM, pDevIns->Internal.s.pPciBusR3);
    1654         else
    1655             pDevIns->Internal.s.pPciBusR0 = NIL_RTR0PTR;
    1656 
    1657         if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1658             pDevIns->Internal.s.pPciBusRC = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciBusR3);
    1659         else
    1660             pDevIns->Internal.s.pPciBusRC = NIL_RTRCPTR;
    1661 
    1662         /*
    1663          * Check the configuration for PCI device and function assignment.
    1664          */
    1665         int iDev = -1;
    1666         uint8_t     u8Device;
    1667         rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIDeviceNo", &u8Device);
    1668         if (VBOX_SUCCESS(rc))
    1669         {
    1670             if (u8Device > 31)
    1671             {
    1672                 AssertMsgFailed(("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d)\n",
    1673                                  u8Device, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1674                 return VERR_INTERNAL_ERROR;
    1675             }
    1676 
    1677             uint8_t     u8Function;
    1678             rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIFunctionNo", &u8Function);
    1679             if (VBOX_FAILURE(rc))
    1680             {
    1681                 AssertMsgFailed(("Configuration error: PCIDeviceNo, but PCIFunctionNo query failed with rc=%Vrc (%s/%d)\n",
    1682                                  rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1683                 return rc;
    1684             }
    1685             if (u8Function > 7)
    1686             {
    1687                 AssertMsgFailed(("Configuration error: PCIFunctionNo=%d, max is 7. (%s/%d)\n",
    1688                                  u8Function, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1689                 return VERR_INTERNAL_ERROR;
    1690             }
    1691             iDev = (u8Device << 3) | u8Function;
    1692         }
    1693         else if (rc != VERR_CFGM_VALUE_NOT_FOUND)
    1694         {
    1695             AssertMsgFailed(("Configuration error: PCIDeviceNo query failed with rc=%Vrc (%s/%d)\n",
    1696                              rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1697             return rc;
    1698         }
    1699 
    1700         /*
    1701          * Call the pci bus device to do the actual registration.
    1702          */
    1703         pdmLock(pVM);
    1704         rc = pBus->pfnRegisterR3(pBus->pDevInsR3, pPciDev, pDevIns->pDevReg->szDeviceName, iDev);
    1705         pdmUnlock(pVM);
    1706         if (VBOX_SUCCESS(rc))
    1707         {
    1708             pPciDev->pDevIns = pDevIns;
    1709 
    1710             pDevIns->Internal.s.pPciDeviceR3 = pPciDev;
    1711             if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0)
    1712                 pDevIns->Internal.s.pPciDeviceR0 = MMHyperR3ToR0(pVM, pPciDev);
    1713             else
    1714                 pDevIns->Internal.s.pPciDeviceR0 = NIL_RTR0PTR;
    1715 
    1716             if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1717                 pDevIns->Internal.s.pPciDeviceRC = MMHyperR3ToRC(pVM, pPciDev);
    1718             else
    1719                 pDevIns->Internal.s.pPciDeviceRC = NIL_RTRCPTR;
    1720 
    1721             Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
    1722                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev->devfn, pDevIns->Internal.s.pPciBusR3->iBus));
    1723         }
    1724     }
    1725     else
    1726     {
    1727         AssertMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
    1728         rc = VERR_PDM_NO_PCI_BUS;
    1729     }
    1730 
    1731     LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1732     return rc;
    1733 }
    1734 
    1735 
    1736 /** @copydoc PDMDEVHLPR3::pfnPCIIORegionRegister */
    1737 static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
    1738 {
    1739     PDMDEV_ASSERT_DEVINS(pDevIns);
    1740     PVM pVM = pDevIns->Internal.s.pVMR3;
    1741     VM_ASSERT_EMT(pVM);
    1742     LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: iRegion=%d cbRegion=%#x enmType=%d pfnCallback=%p\n",
    1743              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cbRegion, enmType, pfnCallback));
    1744 
    1745     /*
    1746      * Validate input.
    1747      */
    1748     if (iRegion < 0 || iRegion >= PCI_NUM_REGIONS)
    1749     {
    1750         Assert(iRegion >= 0 && iRegion < PCI_NUM_REGIONS);
    1751         LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (iRegion)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1752         return VERR_INVALID_PARAMETER;
    1753     }
    1754     switch (enmType)
    1755     {
    1756         case PCI_ADDRESS_SPACE_MEM:
    1757         case PCI_ADDRESS_SPACE_IO:
    1758         case PCI_ADDRESS_SPACE_MEM_PREFETCH:
    1759             break;
    1760         default:
    1761             AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
    1762             LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (enmType)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1763             return VERR_INVALID_PARAMETER;
    1764     }
    1765     if (!pfnCallback)
    1766     {
    1767         Assert(pfnCallback);
    1768         LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (callback)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1769         return VERR_INVALID_PARAMETER;
    1770     }
    1771     AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
    1772 
    1773     /*
    1774      * Must have a PCI device registered!
    1775      */
    1776     int rc;
    1777     PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1778     if (pPciDev)
    1779     {
    1780         /*
    1781          * We're currently restricted to page aligned MMIO regions.
    1782          */
    1783         if (    (enmType == PCI_ADDRESS_SPACE_MEM || enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH)
    1784             &&  cbRegion != RT_ALIGN_32(cbRegion, PAGE_SIZE))
    1785         {
    1786             Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %#x -> %#x\n",
    1787                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbRegion, RT_ALIGN_32(cbRegion, PAGE_SIZE)));
    1788             cbRegion = RT_ALIGN_32(cbRegion, PAGE_SIZE);
    1789         }
    1790 
    1791         PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1792         Assert(pBus);
    1793         pdmLock(pVM);
    1794         rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
    1795         pdmUnlock(pVM);
    1796     }
    1797     else
    1798     {
    1799         AssertMsgFailed(("No PCI device registered!\n"));
    1800         rc = VERR_PDM_NOT_PCI_DEVICE;
    1801     }
    1802 
    1803     LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1804     return rc;
    1805 }
    1806 
    1807 
    1808 /** @copydoc PDMDEVHLPR3::pfnPCISetConfigCallbacks */
    1809 static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
    1810                                                             PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
    1811 {
    1812     PDMDEV_ASSERT_DEVINS(pDevIns);
    1813     PVM pVM = pDevIns->Internal.s.pVMR3;
    1814     VM_ASSERT_EMT(pVM);
    1815     LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
    1816              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
    1817 
    1818     /*
    1819      * Validate input and resolve defaults.
    1820      */
    1821     AssertPtr(pfnRead);
    1822     AssertPtr(pfnWrite);
    1823     AssertPtrNull(ppfnReadOld);
    1824     AssertPtrNull(ppfnWriteOld);
    1825     AssertPtrNull(pPciDev);
    1826 
    1827     if (!pPciDev)
    1828         pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1829     AssertReleaseMsg(pPciDev, ("You must register your device first!\n"));
    1830     PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1831     AssertRelease(pBus);
    1832     AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
    1833 
    1834     /*
    1835      * Do the job.
    1836      */
    1837     pdmLock(pVM);
    1838     pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
    1839     pdmUnlock(pVM);
    1840 
    1841     LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1842 }
    1843 
    1844 
    1845 /** @copydoc PDMDEVHLPR3::pfnPCISetIrq */
    1846 static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1847 {
    1848     PDMDEV_ASSERT_DEVINS(pDevIns);
    1849     LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
    1850 
    1851     /*
    1852      * Validate input.
    1853      */
    1854     /** @todo iIrq and iLevel checks. */
    1855 
    1856     /*
    1857      * Must have a PCI device registered!
    1858      */
    1859     PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1860     if (pPciDev)
    1861     {
    1862         PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3; /** @todo the bus should be associated with the PCI device not the PDM device. */
    1863         Assert(pBus);
    1864         PVM pVM = pDevIns->Internal.s.pVMR3;
    1865         pdmLock(pVM);
    1866         pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
    1867         pdmUnlock(pVM);
    1868     }
    1869     else
    1870         AssertReleaseMsgFailed(("No PCI device registered!\n"));
    1871 
    1872     LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1873 }
    1874 
    1875 
    1876 /** @copydoc PDMDEVHLPR3::pfnPCISetIrqNoWait */
    1877 static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1878 {
    1879     pdmR3DevHlp_PCISetIrq(pDevIns, iIrq, iLevel);
    1880 }
    1881 
    1882 
    1883 /** @copydoc PDMDEVHLPR3::pfnISASetIrq */
    1884 static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1885 {
    1886     PDMDEV_ASSERT_DEVINS(pDevIns);
    1887     LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
    1888 
    1889     /*
    1890      * Validate input.
    1891      */
    1892     /** @todo iIrq and iLevel checks. */
    1893 
    1894     PVM pVM = pDevIns->Internal.s.pVMR3;
    1895     PDMIsaSetIrq(pVM, iIrq, iLevel);    /* (The API takes the lock.) */
    1896 
    1897     LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1898 }
    1899 
    1900 
    1901 /** @copydoc PDMDEVHLPR3::pfnISASetIrqNoWait */
    1902 static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1903 {
    1904     pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
    1905 }
    1906 
    1907 
    1908 /** @copydoc PDMDEVHLPR3::pfnDriverAttach */
    1909 static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
    1910 {
    1911     PDMDEV_ASSERT_DEVINS(pDevIns);
    1912     PVM pVM = pDevIns->Internal.s.pVMR3;
    1913     VM_ASSERT_EMT(pVM);
    1914     LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
    1915              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
    1916 
    1917     /*
    1918      * Lookup the LUN, it might already be registered.
    1919      */
    1920     PPDMLUN pLunPrev = NULL;
    1921     PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
    1922     for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
    1923         if (pLun->iLun == iLun)
    1924             break;
    1925 
    1926     /*
    1927      * Create the LUN if if wasn't found, else check if driver is already attached to it.
    1928      */
    1929     if (!pLun)
    1930     {
    1931         if (    !pBaseInterface
    1932             ||  !pszDesc
    1933             ||  !*pszDesc)
    1934         {
    1935             Assert(pBaseInterface);
    1936             Assert(pszDesc || *pszDesc);
    1937             return VERR_INVALID_PARAMETER;
    1938         }
    1939 
    1940         pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
    1941         if (!pLun)
    1942             return VERR_NO_MEMORY;
    1943 
    1944         pLun->iLun      = iLun;
    1945         pLun->pNext     = pLunPrev ? pLunPrev->pNext : NULL;
    1946         pLun->pTop      = NULL;
    1947         pLun->pBottom   = NULL;
    1948         pLun->pDevIns   = pDevIns;
    1949         pLun->pszDesc   = pszDesc;
    1950         pLun->pBase     = pBaseInterface;
    1951         if (!pLunPrev)
    1952             pDevIns->Internal.s.pLunsR3 = pLun;
    1953         else
    1954             pLunPrev->pNext = pLun;
    1955         Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
    1956              iLun, pszDesc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1957     }
    1958     else if (pLun->pTop)
    1959     {
    1960         AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
    1961         LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
    1962         return VERR_PDM_DRIVER_ALREADY_ATTACHED;
    1963     }
    1964     Assert(pLun->pBase == pBaseInterface);
    1965 
    1966 
    1967     /*
    1968      * Get the attached driver configuration.
    1969      */
    1970     int rc;
    1971     char szNode[48];
    1972     RTStrPrintf(szNode, sizeof(szNode), "LUN#%d", iLun);
    1973     PCFGMNODE   pNode = CFGMR3GetChild(pDevIns->Internal.s.pCfgHandle, szNode);
    1974     if (pNode)
    1975     {
    1976         char *pszName;
    1977         rc = CFGMR3QueryStringAlloc(pNode, "Driver", &pszName);
    1978         if (VBOX_SUCCESS(rc))
    1979         {
    1980             /*
    1981              * Find the driver.
    1982              */
    1983             PPDMDRV pDrv = pdmR3DrvLookup(pVM, pszName);
    1984             if (pDrv)
    1985             {
    1986                 /* config node */
    1987                 PCFGMNODE pConfigNode = CFGMR3GetChild(pNode, "Config");
    1988                 if (!pConfigNode)
    1989                     rc = CFGMR3InsertNode(pNode, "Config", &pConfigNode);
    1990                 if (VBOX_SUCCESS(rc))
    1991                 {
    1992                     CFGMR3SetRestrictedRoot(pConfigNode);
    1993 
    1994                     /*
    1995                      * Allocate the driver instance.
    1996                      */
    1997                     size_t cb = RT_OFFSETOF(PDMDRVINS, achInstanceData[pDrv->pDrvReg->cbInstance]);
    1998                     cb = RT_ALIGN_Z(cb, 16);
    1999                     PPDMDRVINS pNew = (PPDMDRVINS)MMR3HeapAllocZ(pVM, MM_TAG_PDM_DRIVER, cb);
    2000                     if (pNew)
    2001                     {
    2002                         /*
    2003                          * Initialize the instance structure (declaration order).
    2004                          */
    2005                         pNew->u32Version                = PDM_DRVINS_VERSION;
    2006                         //pNew->Internal.s.pUp            = NULL;
    2007                         //pNew->Internal.s.pDown          = NULL;
    2008                         pNew->Internal.s.pLun           = pLun;
    2009                         pNew->Internal.s.pDrv           = pDrv;
    2010                         pNew->Internal.s.pVM            = pVM;
    2011                         //pNew->Internal.s.fDetaching     = false;
    2012                         pNew->Internal.s.pCfgHandle     = pNode;
    2013                         pNew->pDrvHlp                   = &g_pdmR3DrvHlp;
    2014                         pNew->pDrvReg                   = pDrv->pDrvReg;
    2015                         pNew->pCfgHandle                = pConfigNode;
    2016                         pNew->iInstance                 = pDrv->cInstances++;
    2017                         pNew->pUpBase                   = pBaseInterface;
    2018                         //pNew->pDownBase                 = NULL;
    2019                         //pNew->IBase.pfnQueryInterface   = NULL;
    2020                         pNew->pvInstanceData            = &pNew->achInstanceData[0];
    2021 
    2022                         /*
    2023                          * Link with LUN and call the constructor.
    2024                          */
    2025                         pLun->pTop = pLun->pBottom = pNew;
    2026                         rc = pDrv->pDrvReg->pfnConstruct(pNew, pNew->pCfgHandle);
    2027                         if (VBOX_SUCCESS(rc))
    2028                         {
    2029                             MMR3HeapFree(pszName);
    2030                             *ppBaseInterface = &pNew->IBase;
    2031                             Log(("PDM: Attached driver '%s'/%d to LUN#%d on device '%s'/%d.\n",
    2032                                  pDrv->pDrvReg->szDriverName, pNew->iInstance, iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2033                             LogFlow(("pdmR3DevHlp_DriverAttach: caller '%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2034                             /*
    2035                              * Might return != VINF_SUCCESS (e.g. VINF_NAT_DNS) */
    2036                             return rc;
    2037                         }
    2038 
    2039                         /*
    2040                          * Free the driver.
    2041                          */
    2042                         pLun->pTop = pLun->pBottom = NULL;
    2043                         ASMMemFill32(pNew, cb, 0xdeadd0d0);
    2044                         MMR3HeapFree(pNew);
    2045                         pDrv->cInstances--;
    2046                     }
    2047                     else
    2048                     {
    2049                         AssertMsgFailed(("Failed to allocate %d bytes for instantiating driver '%s'\n", cb, pszName));
    2050                         rc = VERR_NO_MEMORY;
    2051                     }
    2052                 }
    2053                 else
    2054                     AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
    2055             }
    2056             else
    2057             {
    2058                 AssertMsgFailed(("Driver '%s' wasn't found!\n", pszName));
    2059                 rc = VERR_PDM_DRIVER_NOT_FOUND;
    2060             }
    2061             MMR3HeapFree(pszName);
    2062         }
    2063         else
    2064         {
    2065             AssertMsgFailed(("Query for string value of \"Driver\" -> %Vrc\n", rc));
    2066             if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    2067                 rc = VERR_PDM_CFG_MISSING_DRIVER_NAME;
    2068         }
    2069     }
    2070     else
    2071         rc = VERR_PDM_NO_ATTACHED_DRIVER;
    2072 
    2073 
    2074     LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2075     return rc;
    2076 }
    2077 
    2078 
    2079 /** @copydoc PDMDEVHLPR3::pfnMMHeapAlloc */
    2080 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
    2081 {
    2082     PDMDEV_ASSERT_DEVINS(pDevIns);
    2083     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
    2084 
    2085     void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
    2086 
    2087     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2088     return pv;
    2089 }
    2090 
    2091 
    2092 /** @copydoc PDMDEVHLPR3::pfnMMHeapAllocZ */
    2093 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
    2094 {
    2095     PDMDEV_ASSERT_DEVINS(pDevIns);
    2096     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
    2097 
    2098     void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
    2099 
    2100     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2101     return pv;
    2102 }
    2103 
    2104 
    2105 /** @copydoc PDMDEVHLPR3::pfnMMHeapFree */
    2106 static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
    2107 {
    2108     PDMDEV_ASSERT_DEVINS(pDevIns);
    2109     LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2110 
    2111     MMR3HeapFree(pv);
    2112 
    2113     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2114 }
    2115 
    2116 
    2117 /** @copydoc PDMDEVHLPR3::pfnVMSetError */
    2118 static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
    2119 {
    2120     PDMDEV_ASSERT_DEVINS(pDevIns);
    2121     va_list args;
    2122     va_start(args, pszFormat);
    2123     int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
    2124     va_end(args);
    2125     return rc;
    2126 }
    2127 
    2128 
    2129 /** @copydoc PDMDEVHLPR3::pfnVMSetErrorV */
    2130 static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
    2131 {
    2132     PDMDEV_ASSERT_DEVINS(pDevIns);
    2133     int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
    2134     return rc;
    2135 }
    2136 
    2137 
    2138 /** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeError */
    2139 static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...)
    2140 {
    2141     PDMDEV_ASSERT_DEVINS(pDevIns);
    2142     va_list args;
    2143     va_start(args, pszFormat);
    2144     int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, args);
    2145     va_end(args);
    2146     return rc;
    2147 }
    2148 
    2149 
    2150 /** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeErrorV */
    2151 static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va)
    2152 {
    2153     PDMDEV_ASSERT_DEVINS(pDevIns);
    2154     int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, va);
    2155     return rc;
    2156 }
    2157 
    2158 
    2159 /** @copydoc PDMDEVHLPR3::pfnAssertEMT */
    2160 static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    2161 {
    2162     PDMDEV_ASSERT_DEVINS(pDevIns);
    2163     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
    2164         return true;
    2165 
    2166     char szMsg[100];
    2167     RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
    2168     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    2169     AssertBreakpoint();
    2170     return false;
    2171 }
    2172 
    2173 
    2174 /** @copydoc PDMDEVHLPR3::pfnAssertOther */
    2175 static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    2176 {
    2177     PDMDEV_ASSERT_DEVINS(pDevIns);
    2178     if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
    2179         return true;
    2180 
    2181     char szMsg[100];
    2182     RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
    2183     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    2184     AssertBreakpoint();
    2185     return false;
    2186 }
    2187 
    2188 
    2189 /** @copydoc PDMDEVHLPR3::pfnDBGFStopV */
    2190 static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
    2191 {
    2192     PDMDEV_ASSERT_DEVINS(pDevIns);
    2193 #ifdef LOG_ENABLED
    2194     va_list va2;
    2195     va_copy(va2, args);
    2196     LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
    2197              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
    2198     va_end(va2);
    2199 #endif
    2200 
    2201     PVM pVM = pDevIns->Internal.s.pVMR3;
    2202     VM_ASSERT_EMT(pVM);
    2203     int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
    2204 
    2205     LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2206     return rc;
    2207 }
    2208 
    2209 
    2210 /** @copydoc PDMDEVHLPR3::pfnDBGFInfoRegister */
    2211 static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
    2212 {
    2213     PDMDEV_ASSERT_DEVINS(pDevIns);
    2214     LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
    2215              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
    2216 
    2217     PVM pVM = pDevIns->Internal.s.pVMR3;
    2218     VM_ASSERT_EMT(pVM);
    2219     int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
    2220 
    2221     LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2222     return rc;
    2223 }
    2224 
    2225 
    2226 /** @copydoc PDMDEVHLPR3::pfnSTAMRegister */
    2227 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
    2228 {
    2229     PDMDEV_ASSERT_DEVINS(pDevIns);
    2230     PVM pVM = pDevIns->Internal.s.pVMR3;
    2231     VM_ASSERT_EMT(pVM);
    2232 
    2233     STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
    2234     NOREF(pVM);
    2235 }
    2236 
    2237 
    2238 
    2239 /** @copydoc PDMDEVHLPR3::pfnSTAMRegisterF */
    2240 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    2241                                                     STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
    2242 {
    2243     PDMDEV_ASSERT_DEVINS(pDevIns);
    2244     PVM pVM = pDevIns->Internal.s.pVMR3;
    2245     VM_ASSERT_EMT(pVM);
    2246 
    2247     va_list args;
    2248     va_start(args, pszName);
    2249     int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    2250     va_end(args);
    2251     AssertRC(rc);
    2252 
    2253     NOREF(pVM);
    2254 }
    2255 
    2256 
    2257 /** @copydoc PDMDEVHLPR3::pfnSTAMRegisterV */
    2258 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    2259                                                     STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
    2260 {
    2261     PDMDEV_ASSERT_DEVINS(pDevIns);
    2262     PVM pVM = pDevIns->Internal.s.pVMR3;
    2263     VM_ASSERT_EMT(pVM);
    2264 
    2265     int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    2266     AssertRC(rc);
    2267 
    2268     NOREF(pVM);
    2269 }
    2270 
    2271 
    2272 /** @copydoc PDMDEVHLPR3::pfnRTCRegister */
    2273 static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
    2274 {
    2275     PDMDEV_ASSERT_DEVINS(pDevIns);
    2276     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2277     LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
    2278              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
    2279              pRtcReg->pfnWrite, ppRtcHlp));
    2280 
    2281     /*
    2282      * Validate input.
    2283      */
    2284     if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
    2285     {
    2286         AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
    2287                          PDM_RTCREG_VERSION));
    2288         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (version)\n",
    2289                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2290         return VERR_INVALID_PARAMETER;
    2291     }
    2292     if (    !pRtcReg->pfnWrite
    2293         ||  !pRtcReg->pfnRead)
    2294     {
    2295         Assert(pRtcReg->pfnWrite);
    2296         Assert(pRtcReg->pfnRead);
    2297         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
    2298                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2299         return VERR_INVALID_PARAMETER;
    2300     }
    2301 
    2302     if (!ppRtcHlp)
    2303     {
    2304         Assert(ppRtcHlp);
    2305         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (ppRtcHlp)\n",
    2306                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2307         return VERR_INVALID_PARAMETER;
    2308     }
    2309 
    2310     /*
    2311      * Only one DMA device.
    2312      */
    2313     PVM pVM = pDevIns->Internal.s.pVMR3;
    2314     if (pVM->pdm.s.pRtc)
    2315     {
    2316         AssertMsgFailed(("Only one RTC device is supported!\n"));
    2317         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
    2318                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2319         return VERR_INVALID_PARAMETER;
    2320     }
    2321 
    2322     /*
    2323      * Allocate and initialize pci bus structure.
    2324      */
    2325     int rc = VINF_SUCCESS;
    2326     PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
    2327     if (pRtc)
    2328     {
    2329         pRtc->pDevIns   = pDevIns;
    2330         pRtc->Reg       = *pRtcReg;
    2331         pVM->pdm.s.pRtc = pRtc;
    2332 
    2333         /* set the helper pointer. */
    2334         *ppRtcHlp = &g_pdmR3DevRtcHlp;
    2335         Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
    2336              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2337     }
    2338     else
    2339         rc = VERR_NO_MEMORY;
    2340 
    2341     LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
    2342              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2343     return rc;
    2344 }
    2345 
    2346 
    2347 /** @copydoc PDMDEVHLPR3::pfnPDMQueueCreate */
    2348 static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
    2349                                                     PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue)
    2350 {
    2351     PDMDEV_ASSERT_DEVINS(pDevIns);
    2352     LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool ppQueue=%p\n",
    2353              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue));
    2354 
    2355     PVM pVM = pDevIns->Internal.s.pVMR3;
    2356     VM_ASSERT_EMT(pVM);
    2357     int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue);
    2358 
    2359     LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppQueue));
    2360     return rc;
    2361 }
    2362 
    2363 
    2364 /** @copydoc PDMDEVHLPR3::pfnCritSectInit */
    2365 static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName)
    2366 {
    2367     PDMDEV_ASSERT_DEVINS(pDevIns);
    2368     LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%p:{%s}\n",
    2369              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pCritSect, pszName, pszName));
    2370 
    2371     PVM pVM = pDevIns->Internal.s.pVMR3;
    2372     VM_ASSERT_EMT(pVM);
    2373     int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, pszName);
    2374 
    2375     LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2376     return rc;
    2377 }
    2378 
    2379 
    2380 /** @copydoc PDMDEVHLPR3::pfnUTCNow */
    2381 static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
    2382 {
    2383     PDMDEV_ASSERT_DEVINS(pDevIns);
    2384     LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: pTime=%p\n",
    2385              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pTime));
    2386 
    2387     pTime = TMR3UTCNow(pDevIns->Internal.s.pVMR3, pTime);
    2388 
    2389     LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: returns %RU64\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
    2390     return pTime;
    2391 }
    2392 
    2393 
    2394 /** @copydoc PDMDEVHLPR3::pfnPDMThreadCreate */
    2395 static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
    2396                                                      PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
    2397 {
    2398     PDMDEV_ASSERT_DEVINS(pDevIns);
    2399     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2400     LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
    2401              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
    2402 
    2403     int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
    2404 
    2405     LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    2406             rc, *ppThread));
    2407     return rc;
    2408 }
    2409 
    2410 
    2411 /** @copydoc PDMDEVHLPR3::pfnGetVM */
    2412 static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
    2413 {
    2414     PDMDEV_ASSERT_DEVINS(pDevIns);
    2415     LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
    2416     return pDevIns->Internal.s.pVMR3;
    2417 }
    2418 
    2419 
    2420 /** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
    2421 static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
    2422 {
    2423     PDMDEV_ASSERT_DEVINS(pDevIns);
    2424     PVM pVM = pDevIns->Internal.s.pVMR3;
    2425     VM_ASSERT_EMT(pVM);
    2426     LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, .pfnSetIrqR3=%p, "
    2427              ".pfnSaveExecR3=%p, .pfnLoadExecR3=%p, .pfnFakePCIBIOSR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppPciHlpR3=%p\n",
    2428              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
    2429              pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnSetIrqR3, pPciBusReg->pfnSaveExecR3, pPciBusReg->pfnLoadExecR3,
    2430              pPciBusReg->pfnFakePCIBIOSR3, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqR0, pPciBusReg->pszSetIrqR0, ppPciHlpR3));
    2431 
    2432     /*
    2433      * Validate the structure.
    2434      */
    2435     if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
    2436     {
    2437         AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
    2438         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2439         return VERR_INVALID_PARAMETER;
    2440     }
    2441     if (    !pPciBusReg->pfnRegisterR3
    2442         ||  !pPciBusReg->pfnIORegionRegisterR3
    2443         ||  !pPciBusReg->pfnSetIrqR3
    2444         ||  !pPciBusReg->pfnSaveExecR3
    2445         ||  !pPciBusReg->pfnLoadExecR3
    2446         ||  !pPciBusReg->pfnFakePCIBIOSR3)
    2447     {
    2448         Assert(pPciBusReg->pfnRegisterR3);
    2449         Assert(pPciBusReg->pfnIORegionRegisterR3);
    2450         Assert(pPciBusReg->pfnSetIrqR3);
    2451         Assert(pPciBusReg->pfnSaveExecR3);
    2452         Assert(pPciBusReg->pfnLoadExecR3);
    2453         Assert(pPciBusReg->pfnFakePCIBIOSR3);
    2454         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2455         return VERR_INVALID_PARAMETER;
    2456     }
    2457     if (    pPciBusReg->pszSetIrqRC
    2458         &&  !VALID_PTR(pPciBusReg->pszSetIrqRC))
    2459     {
    2460         Assert(VALID_PTR(pPciBusReg->pszSetIrqRC));
    2461         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2462         return VERR_INVALID_PARAMETER;
    2463     }
    2464     if (    pPciBusReg->pszSetIrqR0
    2465         &&  !VALID_PTR(pPciBusReg->pszSetIrqR0))
    2466     {
    2467         Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
    2468         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2469         return VERR_INVALID_PARAMETER;
    2470     }
    2471      if (!ppPciHlpR3)
    2472     {
    2473         Assert(ppPciHlpR3);
    2474         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (ppPciHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2475         return VERR_INVALID_PARAMETER;
    2476     }
    2477 
    2478     /*
    2479      * Find free PCI bus entry.
    2480      */
    2481     unsigned iBus = 0;
    2482     for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
    2483         if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
    2484             break;
    2485     if (iBus >= RT_ELEMENTS(pVM->pdm.s.aPciBuses))
    2486     {
    2487         AssertMsgFailed(("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)));
    2488         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (pci bus)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2489         return VERR_INVALID_PARAMETER;
    2490     }
    2491     PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
    2492 
    2493     /*
    2494      * Resolve and init the RC bits.
    2495      */
    2496     if (pPciBusReg->pszSetIrqRC)
    2497     {
    2498         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, &pPciBus->pfnSetIrqRC);
    2499         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, rc));
    2500         if (VBOX_FAILURE(rc))
    2501         {
    2502             LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2503             return rc;
    2504         }
    2505         pPciBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2506     }
    2507     else
    2508     {
    2509         pPciBus->pfnSetIrqRC = 0;
    2510         pPciBus->pDevInsRC   = 0;
    2511     }
    2512 
    2513     /*
    2514      * Resolve and init the R0 bits.
    2515      */
    2516     if (pPciBusReg->pszSetIrqR0)
    2517     {
    2518         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
    2519         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, rc));
    2520         if (VBOX_FAILURE(rc))
    2521         {
    2522             LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2523             return rc;
    2524         }
    2525         pPciBus->pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2526     }
    2527     else
    2528     {
    2529         pPciBus->pfnSetIrqR0 = 0;
    2530         pPciBus->pDevInsR0   = 0;
    2531     }
    2532 
    2533     /*
    2534      * Init the R3 bits.
    2535      */
    2536     pPciBus->iBus                    = iBus;
    2537     pPciBus->pDevInsR3               = pDevIns;
    2538     pPciBus->pfnRegisterR3           = pPciBusReg->pfnRegisterR3;
    2539     pPciBus->pfnIORegionRegisterR3   = pPciBusReg->pfnIORegionRegisterR3;
    2540     pPciBus->pfnSetConfigCallbacksR3 = pPciBusReg->pfnSetConfigCallbacksR3;
    2541     pPciBus->pfnSetIrqR3             = pPciBusReg->pfnSetIrqR3;
    2542     pPciBus->pfnSaveExecR3           = pPciBusReg->pfnSaveExecR3;
    2543     pPciBus->pfnLoadExecR3           = pPciBusReg->pfnLoadExecR3;
    2544     pPciBus->pfnFakePCIBIOSR3        = pPciBusReg->pfnFakePCIBIOSR3;
    2545 
    2546     Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2547 
    2548     /* set the helper pointer and return. */
    2549     *ppPciHlpR3 = &g_pdmR3DevPciHlp;
    2550     LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2551     return VINF_SUCCESS;
    2552 }
    2553 
    2554 
    2555 /** @copydoc PDMDEVHLPR3::pfnPICRegister */
    2556 static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
    2557 {
    2558     PDMDEV_ASSERT_DEVINS(pDevIns);
    2559     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2560     LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pfnGetInterruptR3=%p, .pszGetIrqRC=%p:{%s}, .pszGetInterruptRC=%p:{%s}, .pszGetIrqR0=%p:{%s}, .pszGetInterruptR0=%p:{%s} } ppPicHlpR3=%p\n",
    2561              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
    2562              pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
    2563              pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
    2564              ppPicHlpR3));
    2565 
    2566     /*
    2567      * Validate input.
    2568      */
    2569     if (pPicReg->u32Version != PDM_PICREG_VERSION)
    2570     {
    2571         AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
    2572         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2573         return VERR_INVALID_PARAMETER;
    2574     }
    2575     if (    !pPicReg->pfnSetIrqR3
    2576         ||  !pPicReg->pfnGetInterruptR3)
    2577     {
    2578         Assert(pPicReg->pfnSetIrqR3);
    2579         Assert(pPicReg->pfnGetInterruptR3);
    2580         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2581         return VERR_INVALID_PARAMETER;
    2582     }
    2583     if (    (   pPicReg->pszSetIrqRC
    2584              || pPicReg->pszGetInterruptRC)
    2585         &&  (   !VALID_PTR(pPicReg->pszSetIrqRC)
    2586              || !VALID_PTR(pPicReg->pszGetInterruptRC))
    2587        )
    2588     {
    2589         Assert(VALID_PTR(pPicReg->pszSetIrqRC));
    2590         Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
    2591         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2592         return VERR_INVALID_PARAMETER;
    2593     }
    2594     if (    pPicReg->pszSetIrqRC
    2595         &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    2596     {
    2597         Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC);
    2598         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2599         return VERR_INVALID_PARAMETER;
    2600     }
    2601     if (    pPicReg->pszSetIrqR0
    2602         &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    2603     {
    2604         Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0);
    2605         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R0 flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2606         return VERR_INVALID_PARAMETER;
    2607     }
    2608     if (!ppPicHlpR3)
    2609     {
    2610         Assert(ppPicHlpR3);
    2611         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (ppPicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2612         return VERR_INVALID_PARAMETER;
    2613     }
    2614 
    2615     /*
    2616      * Only one PIC device.
    2617      */
    2618     PVM pVM = pDevIns->Internal.s.pVMR3;
    2619     if (pVM->pdm.s.Pic.pDevInsR3)
    2620     {
    2621         AssertMsgFailed(("Only one pic device is supported!\n"));
    2622         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2623         return VERR_INVALID_PARAMETER;
    2624     }
    2625 
    2626     /*
    2627      * RC stuff.
    2628      */
    2629     if (pPicReg->pszSetIrqRC)
    2630     {
    2631         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
    2632         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, rc));
    2633         if (VBOX_SUCCESS(rc))
    2634         {
    2635             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
    2636             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, rc));
    2637         }
    2638         if (VBOX_FAILURE(rc))
    2639         {
    2640             LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2641             return rc;
    2642         }
    2643         pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2644     }
    2645     else
    2646     {
    2647         pVM->pdm.s.Pic.pDevInsRC = 0;
    2648         pVM->pdm.s.Pic.pfnSetIrqRC = 0;
    2649         pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
    2650     }
    2651 
    2652     /*
    2653      * R0 stuff.
    2654      */
    2655     if (pPicReg->pszSetIrqR0)
    2656     {
    2657         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
    2658         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, rc));
    2659         if (VBOX_SUCCESS(rc))
    2660         {
    2661             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
    2662             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, rc));
    2663         }
    2664         if (VBOX_FAILURE(rc))
    2665         {
    2666             LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2667             return rc;
    2668         }
    2669         pVM->pdm.s.Pic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2670         Assert(pVM->pdm.s.Pic.pDevInsR0);
    2671     }
    2672     else
    2673     {
    2674         pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
    2675         pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
    2676         pVM->pdm.s.Pic.pDevInsR0 = 0;
    2677     }
    2678 
    2679     /*
    2680      * R3 stuff.
    2681      */
    2682     pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
    2683     pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
    2684     pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
    2685     Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2686 
    2687     /* set the helper pointer and return. */
    2688     *ppPicHlpR3 = &g_pdmR3DevPicHlp;
    2689     LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2690     return VINF_SUCCESS;
    2691 }
    2692 
    2693 
    2694 /** @copydoc PDMDEVHLPR3::pfnAPICRegister */
    2695 static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
    2696 {
    2697     PDMDEV_ASSERT_DEVINS(pDevIns);
    2698     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2699     LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptR3=%p, .pfnSetBaseR3=%p, .pfnGetBaseR3=%p, "
    2700              ".pfnSetTPRR3=%p, .pfnGetTPRR3=%p, .pfnBusDeliverR3=%p, pszGetInterruptRC=%p:{%s}, pszSetBaseRC=%p:{%s}, pszGetBaseRC=%p:{%s}, "
    2701              ".pszSetTPRRC=%p:{%s}, .pszGetTPRRC=%p:{%s}, .pszBusDeliverRC=%p:{%s}} ppApicHlpR3=%p\n",
    2702              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptR3, pApicReg->pfnSetBaseR3,
    2703              pApicReg->pfnGetBaseR3, pApicReg->pfnSetTPRR3, pApicReg->pfnGetTPRR3, pApicReg->pfnBusDeliverR3, pApicReg->pszGetInterruptRC,
    2704              pApicReg->pszGetInterruptRC, pApicReg->pszSetBaseRC, pApicReg->pszSetBaseRC, pApicReg->pszGetBaseRC, pApicReg->pszGetBaseRC,
    2705              pApicReg->pszSetTPRRC, pApicReg->pszSetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszBusDeliverRC,
    2706              pApicReg->pszBusDeliverRC, ppApicHlpR3));
    2707 
    2708     /*
    2709      * Validate input.
    2710      */
    2711     if (pApicReg->u32Version != PDM_APICREG_VERSION)
    2712     {
    2713         AssertMsgFailed(("u32Version=%#x expected %#x\n", pApicReg->u32Version, PDM_APICREG_VERSION));
    2714         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2715         return VERR_INVALID_PARAMETER;
    2716     }
    2717     if (    !pApicReg->pfnGetInterruptR3
    2718         ||  !pApicReg->pfnHasPendingIrqR3
    2719         ||  !pApicReg->pfnSetBaseR3
    2720         ||  !pApicReg->pfnGetBaseR3
    2721         ||  !pApicReg->pfnSetTPRR3
    2722         ||  !pApicReg->pfnGetTPRR3
    2723         ||  !pApicReg->pfnBusDeliverR3)
    2724     {
    2725         Assert(pApicReg->pfnGetInterruptR3);
    2726         Assert(pApicReg->pfnHasPendingIrqR3);
    2727         Assert(pApicReg->pfnSetBaseR3);
    2728         Assert(pApicReg->pfnGetBaseR3);
    2729         Assert(pApicReg->pfnSetTPRR3);
    2730         Assert(pApicReg->pfnGetTPRR3);
    2731         Assert(pApicReg->pfnBusDeliverR3);
    2732         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2733         return VERR_INVALID_PARAMETER;
    2734     }
    2735     if (   (    pApicReg->pszGetInterruptRC
    2736             ||  pApicReg->pszHasPendingIrqRC
    2737             ||  pApicReg->pszSetBaseRC
    2738             ||  pApicReg->pszGetBaseRC
    2739             ||  pApicReg->pszSetTPRRC
    2740             ||  pApicReg->pszGetTPRRC
    2741             ||  pApicReg->pszBusDeliverRC)
    2742         &&  (   !VALID_PTR(pApicReg->pszGetInterruptRC)
    2743             ||  !VALID_PTR(pApicReg->pszHasPendingIrqRC)
    2744             ||  !VALID_PTR(pApicReg->pszSetBaseRC)
    2745             ||  !VALID_PTR(pApicReg->pszGetBaseRC)
    2746             ||  !VALID_PTR(pApicReg->pszSetTPRRC)
    2747             ||  !VALID_PTR(pApicReg->pszGetTPRRC)
    2748             ||  !VALID_PTR(pApicReg->pszBusDeliverRC))
    2749        )
    2750     {
    2751         Assert(VALID_PTR(pApicReg->pszGetInterruptRC));
    2752         Assert(VALID_PTR(pApicReg->pszHasPendingIrqRC));
    2753         Assert(VALID_PTR(pApicReg->pszSetBaseRC));
    2754         Assert(VALID_PTR(pApicReg->pszGetBaseRC));
    2755         Assert(VALID_PTR(pApicReg->pszSetTPRRC));
    2756         Assert(VALID_PTR(pApicReg->pszGetTPRRC));
    2757         Assert(VALID_PTR(pApicReg->pszBusDeliverRC));
    2758         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2759         return VERR_INVALID_PARAMETER;
    2760     }
    2761     if (   (    pApicReg->pszGetInterruptR0
    2762             ||  pApicReg->pszHasPendingIrqR0
    2763             ||  pApicReg->pszSetBaseR0
    2764             ||  pApicReg->pszGetBaseR0
    2765             ||  pApicReg->pszSetTPRR0
    2766             ||  pApicReg->pszGetTPRR0
    2767             ||  pApicReg->pszBusDeliverR0)
    2768         &&  (   !VALID_PTR(pApicReg->pszGetInterruptR0)
    2769             ||  !VALID_PTR(pApicReg->pszHasPendingIrqR0)
    2770             ||  !VALID_PTR(pApicReg->pszSetBaseR0)
    2771             ||  !VALID_PTR(pApicReg->pszGetBaseR0)
    2772             ||  !VALID_PTR(pApicReg->pszSetTPRR0)
    2773             ||  !VALID_PTR(pApicReg->pszGetTPRR0)
    2774             ||  !VALID_PTR(pApicReg->pszBusDeliverR0))
    2775        )
    2776     {
    2777         Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
    2778         Assert(VALID_PTR(pApicReg->pszHasPendingIrqR0));
    2779         Assert(VALID_PTR(pApicReg->pszSetBaseR0));
    2780         Assert(VALID_PTR(pApicReg->pszGetBaseR0));
    2781         Assert(VALID_PTR(pApicReg->pszSetTPRR0));
    2782         Assert(VALID_PTR(pApicReg->pszGetTPRR0));
    2783         Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
    2784         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2785         return VERR_INVALID_PARAMETER;
    2786     }
    2787     if (!ppApicHlpR3)
    2788     {
    2789         Assert(ppApicHlpR3);
    2790         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2791         return VERR_INVALID_PARAMETER;
    2792     }
    2793 
    2794     /*
    2795      * Only one APIC device. (malc: only in UP case actually)
    2796      */
    2797     PVM pVM = pDevIns->Internal.s.pVMR3;
    2798     if (pVM->pdm.s.Apic.pDevInsR3)
    2799     {
    2800         AssertMsgFailed(("Only one apic device is supported!\n"));
    2801         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2802         return VERR_INVALID_PARAMETER;
    2803     }
    2804 
    2805     /*
    2806      * Resolve & initialize the RC bits.
    2807      */
    2808     if (pApicReg->pszGetInterruptRC)
    2809     {
    2810         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, &pVM->pdm.s.Apic.pfnGetInterruptRC);
    2811         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, rc));
    2812         if (RT_SUCCESS(rc))
    2813         {
    2814             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, &pVM->pdm.s.Apic.pfnHasPendingIrqRC);
    2815             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, rc));
    2816         }
    2817         if (RT_SUCCESS(rc))
    2818         {
    2819             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, &pVM->pdm.s.Apic.pfnSetBaseRC);
    2820             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, rc));
    2821         }
    2822         if (RT_SUCCESS(rc))
    2823         {
    2824             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, &pVM->pdm.s.Apic.pfnGetBaseRC);
    2825             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, rc));
    2826         }
    2827         if (RT_SUCCESS(rc))
    2828         {
    2829             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, &pVM->pdm.s.Apic.pfnSetTPRRC);
    2830             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, rc));
    2831         }
    2832         if (RT_SUCCESS(rc))
    2833         {
    2834             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, &pVM->pdm.s.Apic.pfnGetTPRRC);
    2835             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, rc));
    2836         }
    2837         if (RT_SUCCESS(rc))
    2838         {
    2839             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, &pVM->pdm.s.Apic.pfnBusDeliverRC);
    2840             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, rc));
    2841         }
    2842         if (VBOX_FAILURE(rc))
    2843         {
    2844             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2845             return rc;
    2846         }
    2847         pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2848     }
    2849     else
    2850     {
    2851         pVM->pdm.s.Apic.pDevInsRC           = 0;
    2852         pVM->pdm.s.Apic.pfnGetInterruptRC   = 0;
    2853         pVM->pdm.s.Apic.pfnHasPendingIrqRC  = 0;
    2854         pVM->pdm.s.Apic.pfnSetBaseRC        = 0;
    2855         pVM->pdm.s.Apic.pfnGetBaseRC        = 0;
    2856         pVM->pdm.s.Apic.pfnSetTPRRC         = 0;
    2857         pVM->pdm.s.Apic.pfnGetTPRRC         = 0;
    2858         pVM->pdm.s.Apic.pfnBusDeliverRC     = 0;
    2859     }
    2860 
    2861     /*
    2862      * Resolve & initialize the R0 bits.
    2863      */
    2864     if (pApicReg->pszGetInterruptR0)
    2865     {
    2866         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
    2867         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
    2868         if (RT_SUCCESS(rc))
    2869         {
    2870             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, &pVM->pdm.s.Apic.pfnHasPendingIrqR0);
    2871             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, rc));
    2872         }
    2873         if (RT_SUCCESS(rc))
    2874         {
    2875             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
    2876             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
    2877         }
    2878         if (RT_SUCCESS(rc))
    2879         {
    2880             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
    2881             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
    2882         }
    2883         if (RT_SUCCESS(rc))
    2884         {
    2885             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
    2886             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
    2887         }
    2888         if (RT_SUCCESS(rc))
    2889         {
    2890             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
    2891             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
    2892         }
    2893         if (RT_SUCCESS(rc))
    2894         {
    2895             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
    2896             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
    2897         }
    2898         if (VBOX_FAILURE(rc))
    2899         {
    2900             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2901             return rc;
    2902         }
    2903         pVM->pdm.s.Apic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2904         Assert(pVM->pdm.s.Apic.pDevInsR0);
    2905     }
    2906     else
    2907     {
    2908         pVM->pdm.s.Apic.pfnGetInterruptR0   = 0;
    2909         pVM->pdm.s.Apic.pfnHasPendingIrqR0  = 0;
    2910         pVM->pdm.s.Apic.pfnSetBaseR0        = 0;
    2911         pVM->pdm.s.Apic.pfnGetBaseR0        = 0;
    2912         pVM->pdm.s.Apic.pfnSetTPRR0         = 0;
    2913         pVM->pdm.s.Apic.pfnGetTPRR0         = 0;
    2914         pVM->pdm.s.Apic.pfnBusDeliverR0     = 0;
    2915         pVM->pdm.s.Apic.pDevInsR0           = 0;
    2916     }
    2917 
    2918     /*
    2919      * Initialize the HC bits.
    2920      */
    2921     pVM->pdm.s.Apic.pDevInsR3           = pDevIns;
    2922     pVM->pdm.s.Apic.pfnGetInterruptR3   = pApicReg->pfnGetInterruptR3;
    2923     pVM->pdm.s.Apic.pfnHasPendingIrqR3  = pApicReg->pfnHasPendingIrqR3;
    2924     pVM->pdm.s.Apic.pfnSetBaseR3        = pApicReg->pfnSetBaseR3;
    2925     pVM->pdm.s.Apic.pfnGetBaseR3        = pApicReg->pfnGetBaseR3;
    2926     pVM->pdm.s.Apic.pfnSetTPRR3         = pApicReg->pfnSetTPRR3;
    2927     pVM->pdm.s.Apic.pfnGetTPRR3         = pApicReg->pfnGetTPRR3;
    2928     pVM->pdm.s.Apic.pfnBusDeliverR3     = pApicReg->pfnBusDeliverR3;
    2929     Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2930 
    2931     /* set the helper pointer and return. */
    2932     *ppApicHlpR3 = &g_pdmR3DevApicHlp;
    2933     LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2934     return VINF_SUCCESS;
    2935 }
    2936 
    2937 
    2938 /** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
    2939 static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
    2940 {
    2941     PDMDEV_ASSERT_DEVINS(pDevIns);
    2942     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2943     LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
    2944              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
    2945              pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
    2946 
    2947     /*
    2948      * Validate input.
    2949      */
    2950     if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
    2951     {
    2952         AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
    2953         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2954         return VERR_INVALID_PARAMETER;
    2955     }
    2956     if (!pIoApicReg->pfnSetIrqR3)
    2957     {
    2958         Assert(pIoApicReg->pfnSetIrqR3);
    2959         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2960         return VERR_INVALID_PARAMETER;
    2961     }
    2962     if (    pIoApicReg->pszSetIrqRC
    2963         &&  !VALID_PTR(pIoApicReg->pszSetIrqRC))
    2964     {
    2965         Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
    2966         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2967         return VERR_INVALID_PARAMETER;
    2968     }
    2969     if (    pIoApicReg->pszSetIrqR0
    2970         &&  !VALID_PTR(pIoApicReg->pszSetIrqR0))
    2971     {
    2972         Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
    2973         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2974         return VERR_INVALID_PARAMETER;
    2975     }
    2976     if (!ppIoApicHlpR3)
    2977     {
    2978         Assert(ppIoApicHlpR3);
    2979         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2980         return VERR_INVALID_PARAMETER;
    2981     }
    2982 
    2983     /*
    2984      * The I/O APIC requires the APIC to be present (hacks++).
    2985      * If the I/O APIC does GC stuff so must the APIC.
    2986      */
    2987     PVM pVM = pDevIns->Internal.s.pVMR3;
    2988     if (!pVM->pdm.s.Apic.pDevInsR3)
    2989     {
    2990         AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
    2991         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2992         return VERR_INVALID_PARAMETER;
    2993     }
    2994     if (    pIoApicReg->pszSetIrqRC
    2995         &&  !pVM->pdm.s.Apic.pDevInsRC)
    2996     {
    2997         AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
    2998         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2999         return VERR_INVALID_PARAMETER;
    3000     }
    3001 
    3002     /*
    3003      * Only one I/O APIC device.
    3004      */
    3005     if (pVM->pdm.s.IoApic.pDevInsR3)
    3006     {
    3007         AssertMsgFailed(("Only one ioapic device is supported!\n"));
    3008         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3009         return VERR_INVALID_PARAMETER;
    3010     }
    3011 
    3012     /*
    3013      * Resolve & initialize the GC bits.
    3014      */
    3015     if (pIoApicReg->pszSetIrqRC)
    3016     {
    3017         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
    3018         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, rc));
    3019         if (VBOX_FAILURE(rc))
    3020         {
    3021             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3022             return rc;
    3023         }
    3024         pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    3025     }
    3026     else
    3027     {
    3028         pVM->pdm.s.IoApic.pDevInsRC   = 0;
    3029         pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
    3030     }
    3031 
    3032     /*
    3033      * Resolve & initialize the R0 bits.
    3034      */
    3035     if (pIoApicReg->pszSetIrqR0)
    3036     {
    3037         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
    3038         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
    3039         if (VBOX_FAILURE(rc))
    3040         {
    3041             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3042             return rc;
    3043         }
    3044         pVM->pdm.s.IoApic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    3045         Assert(pVM->pdm.s.IoApic.pDevInsR0);
    3046     }
    3047     else
    3048     {
    3049         pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
    3050         pVM->pdm.s.IoApic.pDevInsR0   = 0;
    3051     }
    3052 
    3053     /*
    3054      * Initialize the R3 bits.
    3055      */
    3056     pVM->pdm.s.IoApic.pDevInsR3   = pDevIns;
    3057     pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
    3058     Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    3059 
    3060     /* set the helper pointer and return. */
    3061     *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
    3062     LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    3063     return VINF_SUCCESS;
    3064 }
    3065 
    3066 
    3067 /** @copydoc PDMDEVHLPR3::pfnDMACRegister */
    3068 static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
    3069 {
    3070     PDMDEV_ASSERT_DEVINS(pDevIns);
    3071     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3072     LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: pDmacReg=%p:{.u32Version=%#x, .pfnRun=%p, .pfnRegister=%p, .pfnReadMemory=%p, .pfnWriteMemory=%p, .pfnSetDREQ=%p, .pfnGetChannelMode=%p} ppDmacHlp=%p\n",
    3073              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
    3074              pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
    3075 
    3076     /*
    3077      * Validate input.
    3078      */
    3079     if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
    3080     {
    3081         AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
    3082                          PDM_DMACREG_VERSION));
    3083         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
    3084                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3085         return VERR_INVALID_PARAMETER;
    3086     }
    3087     if (    !pDmacReg->pfnRun
    3088         ||  !pDmacReg->pfnRegister
    3089         ||  !pDmacReg->pfnReadMemory
    3090         ||  !pDmacReg->pfnWriteMemory
    3091         ||  !pDmacReg->pfnSetDREQ
    3092         ||  !pDmacReg->pfnGetChannelMode)
    3093     {
    3094         Assert(pDmacReg->pfnRun);
    3095         Assert(pDmacReg->pfnRegister);
    3096         Assert(pDmacReg->pfnReadMemory);
    3097         Assert(pDmacReg->pfnWriteMemory);
    3098         Assert(pDmacReg->pfnSetDREQ);
    3099         Assert(pDmacReg->pfnGetChannelMode);
    3100         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
    3101                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3102         return VERR_INVALID_PARAMETER;
    3103     }
    3104 
    3105     if (!ppDmacHlp)
    3106     {
    3107         Assert(ppDmacHlp);
    3108         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
    3109                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3110         return VERR_INVALID_PARAMETER;
    3111     }
    3112 
    3113     /*
    3114      * Only one DMA device.
    3115      */
    3116     PVM pVM = pDevIns->Internal.s.pVMR3;
    3117     if (pVM->pdm.s.pDmac)
    3118     {
    3119         AssertMsgFailed(("Only one DMA device is supported!\n"));
    3120         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
    3121                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3122         return VERR_INVALID_PARAMETER;
    3123     }
    3124 
    3125     /*
    3126      * Allocate and initialize pci bus structure.
    3127      */
    3128     int rc = VINF_SUCCESS;
    3129     PPDMDMAC  pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
    3130     if (pDmac)
    3131     {
    3132         pDmac->pDevIns   = pDevIns;
    3133         pDmac->Reg       = *pDmacReg;
    3134         pVM->pdm.s.pDmac = pDmac;
    3135 
    3136         /* set the helper pointer. */
    3137         *ppDmacHlp = &g_pdmR3DevDmacHlp;
    3138         Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
    3139              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    3140     }
    3141     else
    3142         rc = VERR_NO_MEMORY;
    3143 
    3144     LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
    3145              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3146     return rc;
    3147 }
    3148 
    3149 
    3150 /** @copydoc PDMDEVHLPR3::pfnPhysRead */
    3151 static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
    3152 {
    3153     PDMDEV_ASSERT_DEVINS(pDevIns);
    3154     LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
    3155              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
    3156 
    3157     /*
    3158      * For the convenience of the device we put no thread restriction on this interface.
    3159      * That means we'll have to check which thread we're in and choose our path.
    3160      */
    3161 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    3162     PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3163 #else
    3164     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    3165         PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3166     else
    3167     {
    3168         Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3169         PVMREQ pReq;
    3170         AssertCompileSize(RTGCPHYS, 4);
    3171         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    3172                                  (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3173         while (rc == VERR_TIMEOUT)
    3174             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    3175         AssertReleaseRC(rc);
    3176         VMR3ReqFree(pReq);
    3177     }
    3178 #endif
    3179     Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3180 }
    3181 
    3182 
    3183 /** @copydoc PDMDEVHLPR3::pfnPhysWrite */
    3184 static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
    3185 {
    3186     PDMDEV_ASSERT_DEVINS(pDevIns);
    3187     LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
    3188              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
    3189 
    3190     /*
    3191      * For the convenience of the device we put no thread restriction on this interface.
    3192      * That means we'll have to check which thread we're in and choose our path.
    3193      */
    3194 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    3195     PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3196 #else
    3197     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    3198         PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3199     else
    3200     {
    3201         Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3202         PVMREQ pReq;
    3203         AssertCompileSize(RTGCPHYS, 4);
    3204         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    3205                                  (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3206         while (rc == VERR_TIMEOUT)
    3207             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    3208         AssertReleaseRC(rc);
    3209         VMR3ReqFree(pReq);
    3210     }
    3211 #endif
    3212     Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3213 }
    3214 
    3215 
    3216 /** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
    3217 static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
    3218 {
    3219     PDMDEV_ASSERT_DEVINS(pDevIns);
    3220     PVM pVM = pDevIns->Internal.s.pVMR3;
    3221     VM_ASSERT_EMT(pVM);
    3222     LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
    3223              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
    3224 
    3225     if (!VM_IS_EMT(pVM))
    3226         return VERR_ACCESS_DENIED;
    3227 
    3228     int rc = PGMPhysReadGCPtr(pVM, pvDst, GCVirtSrc, cb);
    3229 
    3230     LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3231 
    3232     return rc;
    3233 }
    3234 
    3235 
    3236 /** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
    3237 static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
    3238 {
    3239     PDMDEV_ASSERT_DEVINS(pDevIns);
    3240     PVM pVM = pDevIns->Internal.s.pVMR3;
    3241     VM_ASSERT_EMT(pVM);
    3242     LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
    3243              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
    3244 
    3245     if (!VM_IS_EMT(pVM))
    3246         return VERR_ACCESS_DENIED;
    3247 
    3248     int rc = PGMPhysWriteGCPtr(pVM, GCVirtDst, pvSrc, cb);
    3249 
    3250     LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3251 
    3252     return rc;
    3253 }
    3254 
    3255 
    3256 /** @copydoc PDMDEVHLPR3::pfnPhysReserve */
    3257 static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
    3258 {
    3259     PDMDEV_ASSERT_DEVINS(pDevIns);
    3260     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3261     LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
    3262              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, pszDesc, pszDesc));
    3263 
    3264     int rc = MMR3PhysReserve(pDevIns->Internal.s.pVMR3, GCPhys, cbRange, pszDesc);
    3265 
    3266     LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3267 
    3268     return rc;
    3269 }
    3270 
    3271 
    3272 /** @copydoc PDMDEVHLPR3::pfnPhysGCPtr2GCPhys */
    3273 static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
    3274 {
    3275     PDMDEV_ASSERT_DEVINS(pDevIns);
    3276     PVM pVM = pDevIns->Internal.s.pVMR3;
    3277     VM_ASSERT_EMT(pVM);
    3278     LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%VGv pGCPhys=%p\n",
    3279              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPtr, pGCPhys));
    3280 
    3281     if (!VM_IS_EMT(pVM))
    3282         return VERR_ACCESS_DENIED;
    3283 
    3284     int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, pGCPhys);
    3285 
    3286     LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Vrc *pGCPhys=%VGp\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pGCPhys));
    3287 
    3288     return rc;
    3289 }
    3290 
    3291 
    3292 /** @copydoc PDMDEVHLPR3::pfnVMState */
    3293 static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
    3294 {
    3295     PDMDEV_ASSERT_DEVINS(pDevIns);
    3296 
    3297     VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
    3298 
    3299     LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    3300              enmVMState, VMR3GetStateName(enmVMState)));
    3301     return enmVMState;
    3302 }
    3303 
    3304 
    3305 /** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
    3306 static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
    3307 {
    3308     PDMDEV_ASSERT_DEVINS(pDevIns);
    3309     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3310 
    3311     bool fRc = PGMPhysIsA20Enabled(pDevIns->Internal.s.pVMR3);
    3312 
    3313     LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
    3314     return fRc;
    3315 }
    3316 
    3317 
    3318 /** @copydoc PDMDEVHLPR3::pfnA20Set */
    3319 static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
    3320 {
    3321     PDMDEV_ASSERT_DEVINS(pDevIns);
    3322     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3323     LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
    3324     //Assert(*(unsigned *)&fEnable <= 1);
    3325     PGMR3PhysSetA20(pDevIns->Internal.s.pVMR3, fEnable);
    3326 }
    3327 
    3328 
    3329 /** @copydoc PDMDEVHLPR3::pfnVMReset */
    3330 static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
    3331 {
    3332     PDMDEV_ASSERT_DEVINS(pDevIns);
    3333     PVM pVM = pDevIns->Internal.s.pVMR3;
    3334     VM_ASSERT_EMT(pVM);
    3335     LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
    3336              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
    3337 
    3338     /*
    3339      * We postpone this operation because we're likely to be inside a I/O instruction
    3340      * and the EIP will be updated when we return.
    3341      * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
    3342      */
    3343     bool fHaltOnReset;
    3344     int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
    3345     if (VBOX_SUCCESS(rc) && fHaltOnReset)
    3346     {
    3347         Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
    3348         rc = VINF_EM_HALT;
    3349     }
    3350     else
    3351     {
    3352         VM_FF_SET(pVM, VM_FF_RESET);
    3353         rc = VINF_EM_RESET;
    3354     }
    3355 
    3356     LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3357     return rc;
    3358 }
    3359 
    3360 
    3361 /** @copydoc PDMDEVHLPR3::pfnVMSuspend */
    3362 static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
    3363 {
    3364     PDMDEV_ASSERT_DEVINS(pDevIns);
    3365     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3366     LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
    3367              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3368 
    3369     int rc = VMR3Suspend(pDevIns->Internal.s.pVMR3);
    3370 
    3371     LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3372     return rc;
    3373 }
    3374 
    3375 
    3376 /** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
    3377 static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
    3378 {
    3379     PDMDEV_ASSERT_DEVINS(pDevIns);
    3380     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3381     LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
    3382              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3383 
    3384     int rc = VMR3PowerOff(pDevIns->Internal.s.pVMR3);
    3385 
    3386     LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3387     return rc;
    3388 }
    3389 
    3390 
    3391 /** @copydoc PDMDEVHLPR3::pfnLockVM */
    3392 static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns)
    3393 {
    3394     return VMMR3Lock(pDevIns->Internal.s.pVMR3);
    3395 }
    3396 
    3397 
    3398 /** @copydoc PDMDEVHLPR3::pfnUnlockVM */
    3399 static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns)
    3400 {
    3401     return VMMR3Unlock(pDevIns->Internal.s.pVMR3);
    3402 }
    3403 
    3404 
    3405 /** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
    3406 static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    3407 {
    3408     PVM pVM = pDevIns->Internal.s.pVMR3;
    3409     if (VMMR3LockIsOwner(pVM))
    3410         return true;
    3411 
    3412     RTNATIVETHREAD NativeThreadOwner = VMMR3LockGetOwner(pVM);
    3413     RTTHREAD ThreadOwner = RTThreadFromNative(NativeThreadOwner);
    3414     char szMsg[100];
    3415     RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
    3416                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    3417                 NativeThreadOwner, ThreadOwner, RTThreadGetName(ThreadOwner), RTThreadSelfName());
    3418     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    3419     AssertBreakpoint();
    3420     return false;
    3421 }
    3422 
    3423 /** @copydoc PDMDEVHLPR3::pfnDMARegister */
    3424 static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
    3425 {
    3426     PDMDEV_ASSERT_DEVINS(pDevIns);
    3427     PVM pVM = pDevIns->Internal.s.pVMR3;
    3428     VM_ASSERT_EMT(pVM);
    3429     LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
    3430              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
    3431     int rc = VINF_SUCCESS;
    3432     if (pVM->pdm.s.pDmac)
    3433         pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
    3434     else
    3435     {
    3436         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3437         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3438     }
    3439     LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
    3440              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3441     return rc;
    3442 }
    3443 
    3444 /** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
    3445 static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
    3446 {
    3447     PDMDEV_ASSERT_DEVINS(pDevIns);
    3448     PVM pVM = pDevIns->Internal.s.pVMR3;
    3449     VM_ASSERT_EMT(pVM);
    3450     LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
    3451              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
    3452     int rc = VINF_SUCCESS;
    3453     if (pVM->pdm.s.pDmac)
    3454     {
    3455         uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
    3456         if (pcbRead)
    3457             *pcbRead = cb;
    3458     }
    3459     else
    3460     {
    3461         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3462         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3463     }
    3464     LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
    3465              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3466     return rc;
    3467 }
    3468 
    3469 /** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
    3470 static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
    3471 {
    3472     PDMDEV_ASSERT_DEVINS(pDevIns);
    3473     PVM pVM = pDevIns->Internal.s.pVMR3;
    3474     VM_ASSERT_EMT(pVM);
    3475     LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
    3476              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
    3477     int rc = VINF_SUCCESS;
    3478     if (pVM->pdm.s.pDmac)
    3479     {
    3480         uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
    3481         if (pcbWritten)
    3482             *pcbWritten = cb;
    3483     }
    3484     else
    3485     {
    3486         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3487         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3488     }
    3489     LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
    3490              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3491     return rc;
    3492 }
    3493 
    3494 /** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
    3495 static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
    3496 {
    3497     PDMDEV_ASSERT_DEVINS(pDevIns);
    3498     PVM pVM = pDevIns->Internal.s.pVMR3;
    3499     VM_ASSERT_EMT(pVM);
    3500     LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
    3501              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, uLevel));
    3502     int rc = VINF_SUCCESS;
    3503     if (pVM->pdm.s.pDmac)
    3504         pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
    3505     else
    3506     {
    3507         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3508         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3509     }
    3510     LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
    3511              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3512     return rc;
    3513 }
    3514 
    3515 /** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
    3516 static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
    3517 {
    3518     PDMDEV_ASSERT_DEVINS(pDevIns);
    3519     PVM pVM = pDevIns->Internal.s.pVMR3;
    3520     VM_ASSERT_EMT(pVM);
    3521     LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
    3522              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel));
    3523     uint8_t u8Mode;
    3524     if (pVM->pdm.s.pDmac)
    3525         u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
    3526     else
    3527     {
    3528         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3529         u8Mode = 3 << 2 /* illegal mode type */;
    3530     }
    3531     LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
    3532              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Mode));
    3533     return u8Mode;
    3534 }
    3535 
    3536 /** @copydoc PDMDEVHLPR3::pfnDMASchedule */
    3537 static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
    3538 {
    3539     PDMDEV_ASSERT_DEVINS(pDevIns);
    3540     PVM pVM = pDevIns->Internal.s.pVMR3;
    3541     VM_ASSERT_EMT(pVM);
    3542     LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
    3543              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
    3544 
    3545     AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3546     VM_FF_SET(pVM, VM_FF_PDM_DMA);
    3547     REMR3NotifyDmaPending(pVM);
    3548     VMR3NotifyFF(pVM, true);
    3549 }
    3550 
    3551 
    3552 /** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
    3553 static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
    3554 {
    3555     PDMDEV_ASSERT_DEVINS(pDevIns);
    3556     PVM pVM = pDevIns->Internal.s.pVMR3;
    3557     VM_ASSERT_EMT(pVM);
    3558 
    3559     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
    3560              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, u8Value));
    3561     int rc;
    3562     if (pVM->pdm.s.pRtc)
    3563         rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
    3564     else
    3565         rc = VERR_PDM_NO_RTC_INSTANCE;
    3566 
    3567     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
    3568              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3569     return rc;
    3570 }
    3571 
    3572 
    3573 /** @copydoc PDMDEVHLPR3::pfnCMOSRead */
    3574 static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
    3575 {
    3576     PDMDEV_ASSERT_DEVINS(pDevIns);
    3577     PVM pVM = pDevIns->Internal.s.pVMR3;
    3578     VM_ASSERT_EMT(pVM);
    3579 
    3580     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
    3581              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, pu8Value));
    3582     int rc;
    3583     if (pVM->pdm.s.pRtc)
    3584         rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
    3585     else
    3586         rc = VERR_PDM_NO_RTC_INSTANCE;
    3587 
    3588     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
    3589              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3590     return rc;
    3591 }
    3592 
    3593 
    3594 /** @copydoc PDMDEVHLPR3::pfnGetCpuId */
    3595 static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    3596                                                uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
    3597 {
    3598     PDMDEV_ASSERT_DEVINS(pDevIns);
    3599     LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
    3600              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
    3601     AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
    3602 
    3603     CPUMGetGuestCpuId(pDevIns->Internal.s.pVMR3, iLeaf, pEax, pEbx, pEcx, pEdx);
    3604 
    3605     LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
    3606              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
    3607 }
    3608 
    3609 
    3610 /** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
    3611 static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    3612 {
    3613     PDMDEV_ASSERT_DEVINS(pDevIns);
    3614     LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
    3615              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
    3616 
    3617     int rc = MMR3PhysRomProtect(pDevIns->Internal.s.pVMR3, GCPhysStart, cbRange);
    3618 
    3619     LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3620     return rc;
    3621 }
    3622 
    3623 
    3624 /**
    3625  * @copydoc PDMDEVHLPR3::pfnMMIO2Register
    3626  */
    3627 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
    3628 {
    3629     PDMDEV_ASSERT_DEVINS(pDevIns);
    3630     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3631     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: iRegion=#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",
    3632              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cb, fFlags, ppv, pszDesc, pszDesc));
    3633 
    3634     int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, cb, fFlags, ppv, pszDesc);
    3635 
    3636     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3637     return rc;
    3638 }
    3639 
    3640 
    3641 /**
    3642  * @copydoc PDMDEVHLPR3::pfnMMIO2Deregister
    3643  */
    3644 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
    3645 {
    3646     PDMDEV_ASSERT_DEVINS(pDevIns);
    3647     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3648     LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: iRegion=#x\n",
    3649              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion));
    3650 
    3651     AssertReturn(iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);
    3652 
    3653     int rc = PGMR3PhysMMIO2Deregister(pDevIns->Internal.s.pVMR3, pDevIns, iRegion);
    3654 
    3655     LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3656     return rc;
    3657 }
    3658 
    3659 
    3660 /**
    3661  * @copydoc PDMDEVHLPR3::pfnMMIO2Map
    3662  */
    3663 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    3664 {
    3665     PDMDEV_ASSERT_DEVINS(pDevIns);
    3666     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3667     LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
    3668              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
    3669 
    3670     int rc = PGMR3PhysMMIO2Map(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
    3671 
    3672     LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3673     return rc;
    3674 }
    3675 
    3676 
    3677 /**
    3678  * @copydoc PDMDEVHLPR3::pfnMMIO2Unmap
    3679  */
    3680 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    3681 {
    3682     PDMDEV_ASSERT_DEVINS(pDevIns);
    3683     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3684     LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
    3685              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
    3686 
    3687     int rc = PGMR3PhysMMIO2Unmap(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
    3688 
    3689     LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3690     return rc;
    3691 }
    3692 
    3693 
    3694 /**
    3695  * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2
    3696  */
    3697 static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
    3698                                                      const char *pszDesc, PRTRCPTR pRCPtr)
    3699 {
    3700     PDMDEV_ASSERT_DEVINS(pDevIns);
    3701     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3702     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: iRegion=#x off=%RGp cb=%RGp pszDesc=%p:{%s} pRCPtr=%p\n",
    3703              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, off, cb, pszDesc, pszDesc, pRCPtr));
    3704 
    3705     int rc = MMR3HyperMapMMIO2(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, off, cb, pszDesc, pRCPtr);
    3706 
    3707     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc *pRCPtr=%RRv\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pRCPtr));
    3708     return rc;
    3709 }
    3710 
    3711 
    3712 /**
    3713  * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
    3714  */
    3715 static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
    3716 {
    3717     PDMDEV_ASSERT_DEVINS(pDevIns);
    3718     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3719 
    3720     int rc = PDMR3RegisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys, pvHeap, cbSize);
    3721     return rc;
    3722 }
    3723 
    3724 
    3725 /**
    3726  * @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap
    3727  */
    3728 static DECLCALLBACK(int) pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
    3729 {
    3730     PDMDEV_ASSERT_DEVINS(pDevIns);
    3731     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3732 
    3733     int rc = PDMR3UnregisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys);
    3734     return rc;
    3735 }
    3736 
    3737 
    3738 
    3739 
    3740 
    3741 /** @copydoc PDMDEVHLPR3::pfnGetVM */
    3742 static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
    3743 {
    3744     PDMDEV_ASSERT_DEVINS(pDevIns);
    3745     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3746     return NULL;
    3747 }
    3748 
    3749 
    3750 /** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
    3751 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
    3752 {
    3753     PDMDEV_ASSERT_DEVINS(pDevIns);
    3754     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3755     NOREF(pPciBusReg);
    3756     NOREF(ppPciHlpR3);
    3757     return VERR_ACCESS_DENIED;
    3758 }
    3759 
    3760 
    3761 /** @copydoc PDMDEVHLPR3::pfnPICRegister */
    3762 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
    3763 {
    3764     PDMDEV_ASSERT_DEVINS(pDevIns);
    3765     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3766     NOREF(pPicReg);
    3767     NOREF(ppPicHlpR3);
    3768     return VERR_ACCESS_DENIED;
    3769 }
    3770 
    3771 
    3772 /** @copydoc PDMDEVHLPR3::pfnAPICRegister */
    3773 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
    3774 {
    3775     PDMDEV_ASSERT_DEVINS(pDevIns);
    3776     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3777     NOREF(pApicReg);
    3778     NOREF(ppApicHlpR3);
    3779     return VERR_ACCESS_DENIED;
    3780 }
    3781 
    3782 
    3783 /** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
    3784 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
    3785 {
    3786     PDMDEV_ASSERT_DEVINS(pDevIns);
    3787     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3788     NOREF(pIoApicReg);
    3789     NOREF(ppIoApicHlpR3);
    3790     return VERR_ACCESS_DENIED;
    3791 }
    3792 
    3793 
    3794 /** @copydoc PDMDEVHLPR3::pfnDMACRegister */
    3795 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
    3796 {
    3797     PDMDEV_ASSERT_DEVINS(pDevIns);
    3798     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3799     NOREF(pDmacReg);
    3800     NOREF(ppDmacHlp);
    3801     return VERR_ACCESS_DENIED;
    3802 }
    3803 
    3804 
    3805 /** @copydoc PDMDEVHLPR3::pfnPhysRead */
    3806 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
    3807 {
    3808     PDMDEV_ASSERT_DEVINS(pDevIns);
    3809     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3810     NOREF(GCPhys);
    3811     NOREF(pvBuf);
    3812     NOREF(cbRead);
    3813 }
    3814 
    3815 
    3816 /** @copydoc PDMDEVHLPR3::pfnPhysWrite */
    3817 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
    3818 {
    3819     PDMDEV_ASSERT_DEVINS(pDevIns);
    3820     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3821     NOREF(GCPhys);
    3822     NOREF(pvBuf);
    3823     NOREF(cbWrite);
    3824 }
    3825 
    3826 
    3827 /** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
    3828 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
    3829 {
    3830     PDMDEV_ASSERT_DEVINS(pDevIns);
    3831     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3832     NOREF(pvDst);
    3833     NOREF(GCVirtSrc);
    3834     NOREF(cb);
    3835     return VERR_ACCESS_DENIED;
    3836 }
    3837 
    3838 
    3839 /** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
    3840 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
    3841 {
    3842     PDMDEV_ASSERT_DEVINS(pDevIns);
    3843     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3844     NOREF(GCVirtDst);
    3845     NOREF(pvSrc);
    3846     NOREF(cb);
    3847     return VERR_ACCESS_DENIED;
    3848 }
    3849 
    3850 
    3851 /** @copydoc PDMDEVHLPR3::pfnPhysReserve */
    3852 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
    3853 {
    3854     PDMDEV_ASSERT_DEVINS(pDevIns);
    3855     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3856     NOREF(GCPhys);
    3857     NOREF(cbRange);
    3858     return VERR_ACCESS_DENIED;
    3859 }
    3860 
    3861 
    3862 /** @copydoc PDMDEVHLPR3::pfnObsoletePhys2HCVirt */
    3863 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
    3864 {
    3865     PDMDEV_ASSERT_DEVINS(pDevIns);
    3866     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3867     NOREF(GCPhys);
    3868     NOREF(cbRange);
    3869     NOREF(ppvHC);
    3870     return VERR_ACCESS_DENIED;
    3871 }
    3872 
    3873 
    3874 /** @copydoc PDMDEVHLPR3::pfnObsoletePhysGCPtr2HCPtr */
    3875 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
    3876 {
    3877     PDMDEV_ASSERT_DEVINS(pDevIns);
    3878     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3879     NOREF(GCPtr);
    3880     NOREF(pHCPtr);
    3881     return VERR_ACCESS_DENIED;
    3882 }
    3883 
    3884 
    3885 /** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
    3886 static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
    3887 {
    3888     PDMDEV_ASSERT_DEVINS(pDevIns);
    3889     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3890     return false;
    3891 }
    3892 
    3893 
    3894 /** @copydoc PDMDEVHLPR3::pfnA20Set */
    3895 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
    3896 {
    3897     PDMDEV_ASSERT_DEVINS(pDevIns);
    3898     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3899     NOREF(fEnable);
    3900 }
    3901 
    3902 
    3903 /** @copydoc PDMDEVHLPR3::pfnVMReset */
    3904 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
    3905 {
    3906     PDMDEV_ASSERT_DEVINS(pDevIns);
    3907     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3908     return VERR_ACCESS_DENIED;
    3909 }
    3910 
    3911 
    3912 /** @copydoc PDMDEVHLPR3::pfnVMSuspend */
    3913 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
    3914 {
    3915     PDMDEV_ASSERT_DEVINS(pDevIns);
    3916     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3917     return VERR_ACCESS_DENIED;
    3918 }
    3919 
    3920 
    3921 /** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
    3922 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
    3923 {
    3924     PDMDEV_ASSERT_DEVINS(pDevIns);
    3925     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3926     return VERR_ACCESS_DENIED;
    3927 }
    3928 
    3929 
    3930 /** @copydoc PDMDEVHLPR3::pfnLockVM */
    3931 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns)
    3932 {
    3933     PDMDEV_ASSERT_DEVINS(pDevIns);
    3934     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3935     return VERR_ACCESS_DENIED;
    3936 }
    3937 
    3938 
    3939 /** @copydoc PDMDEVHLPR3::pfnUnlockVM */
    3940 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns)
    3941 {
    3942     PDMDEV_ASSERT_DEVINS(pDevIns);
    3943     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3944     return VERR_ACCESS_DENIED;
    3945 }
    3946 
    3947 
    3948 /** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
    3949 static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    3950 {
    3951     PDMDEV_ASSERT_DEVINS(pDevIns);
    3952     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3953     return false;
    3954 }
    3955 
    3956 
    3957 /** @copydoc PDMDEVHLPR3::pfnDMARegister */
    3958 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
    3959 {
    3960     PDMDEV_ASSERT_DEVINS(pDevIns);
    3961     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3962     return VERR_ACCESS_DENIED;
    3963 }
    3964 
    3965 
    3966 /** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
    3967 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
    3968 {
    3969     PDMDEV_ASSERT_DEVINS(pDevIns);
    3970     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3971     if (pcbRead)
    3972         *pcbRead = 0;
    3973     return VERR_ACCESS_DENIED;
    3974 }
    3975 
    3976 
    3977 /** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
    3978 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
    3979 {
    3980     PDMDEV_ASSERT_DEVINS(pDevIns);
    3981     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3982     if (pcbWritten)
    3983         *pcbWritten = 0;
    3984     return VERR_ACCESS_DENIED;
    3985 }
    3986 
    3987 
    3988 /** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
    3989 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
    3990 {
    3991     PDMDEV_ASSERT_DEVINS(pDevIns);
    3992     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3993     return VERR_ACCESS_DENIED;
    3994 }
    3995 
    3996 
    3997 /** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
    3998 static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
    3999 {
    4000     PDMDEV_ASSERT_DEVINS(pDevIns);
    4001     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4002     return 3 << 2 /* illegal mode type */;
    4003 }
    4004 
    4005 
    4006 /** @copydoc PDMDEVHLPR3::pfnDMASchedule */
    4007 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns)
    4008 {
    4009     PDMDEV_ASSERT_DEVINS(pDevIns);
    4010     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4011 }
    4012 
    4013 
    4014 /** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
    4015 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
    4016 {
    4017     PDMDEV_ASSERT_DEVINS(pDevIns);
    4018     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4019     return VERR_ACCESS_DENIED;
    4020 }
    4021 
    4022 
    4023 /** @copydoc PDMDEVHLPR3::pfnCMOSRead */
    4024 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
    4025 {
    4026     PDMDEV_ASSERT_DEVINS(pDevIns);
    4027     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4028     return VERR_ACCESS_DENIED;
    4029 }
    4030 
    4031 
    4032 /** @copydoc PDMDEVHLPR3::pfnGetCpuId */
    4033 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    4034                                                          uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
    4035 {
    4036     PDMDEV_ASSERT_DEVINS(pDevIns);
    4037     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4038 }
    4039 
    4040 
    4041 /** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
    4042 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    4043 {
    4044     PDMDEV_ASSERT_DEVINS(pDevIns);
    4045     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4046     return VERR_ACCESS_DENIED;
    4047 }
    4048 
    4049 
    4050 /** @copydoc PDMDEVHLPR3::pfnMMIO2Register */
    4051 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
    4052 {
    4053     PDMDEV_ASSERT_DEVINS(pDevIns);
    4054     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4055     return VERR_ACCESS_DENIED;
    4056 }
    4057 
    4058 
    4059 /** @copydoc PDMDEVHLPR3::pfnMMIO2Deregister */
    4060 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
    4061 {
    4062     PDMDEV_ASSERT_DEVINS(pDevIns);
    4063     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4064     return VERR_ACCESS_DENIED;
    4065 }
    4066 
    4067 
    4068 /** @copydoc PDMDEVHLPR3::pfnMMIO2Map */
    4069 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    4070 {
    4071     PDMDEV_ASSERT_DEVINS(pDevIns);
    4072     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4073     return VERR_ACCESS_DENIED;
    4074 }
    4075 
    4076 
    4077 /** @copydoc PDMDEVHLPR3::pfnMMIO2Unmap */
    4078 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    4079 {
    4080     PDMDEV_ASSERT_DEVINS(pDevIns);
    4081     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4082     return VERR_ACCESS_DENIED;
    4083 }
    4084 
    4085 
    4086 /** @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2 */
    4087 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr)
    4088 {
    4089     PDMDEV_ASSERT_DEVINS(pDevIns);
    4090     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4091     return VERR_ACCESS_DENIED;
    4092 }
    4093 
    4094 
    4095 /** @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap */
    4096 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
    4097 {
    4098     PDMDEV_ASSERT_DEVINS(pDevIns);
    4099     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4100     return VERR_ACCESS_DENIED;
    4101 }
    4102 
    4103 
    4104 /** @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap */
    4105 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
    4106 {
    4107     PDMDEV_ASSERT_DEVINS(pDevIns);
    4108     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4109     return VERR_ACCESS_DENIED;
    4110 }
    4111 
    4112 
    4113 
    4114 
    4115 
    4116 /** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
    4117 static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
    4118 {
    4119     PDMDEV_ASSERT_DEVINS(pDevIns);
    4120     PVM pVM = pDevIns->Internal.s.pVMR3;
    4121     LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
    4122              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pVM, 0, VM_FF_INTERRUPT_PIC)));
    4123     /* for PIC we always deliver to CPU 0, MP use APIC */
    4124     VMCPU_FF_SET(pVM, 0, VM_FF_INTERRUPT_PIC);
    4125     REMR3NotifyInterruptSet(pVM);
    4126     VMR3NotifyFF(pVM, true);
    4127 }
    4128 
    4129 
    4130 /** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
    4131 static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
    4132 {
    4133     PDMDEV_ASSERT_DEVINS(pDevIns);
    4134     LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
    4135              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC)));
    4136     /* for PIC we always deliver to CPU 0, MP use APIC */
    4137     VMCPU_FF_CLEAR(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC);
    4138     REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMR3);
    4139 }
    4140 
    4141 
    4142 /** @copydoc PDMPICHLPR3::pfnLock */
    4143 static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4144 {
    4145     PDMDEV_ASSERT_DEVINS(pDevIns);
    4146     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4147 }
    4148 
    4149 
    4150 /** @copydoc PDMPICHLPR3::pfnUnlock */
    4151 static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
    4152 {
    4153     PDMDEV_ASSERT_DEVINS(pDevIns);
    4154     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4155 }
    4156 
    4157 
    4158 /** @copydoc PDMPICHLPR3::pfnGetRCHelpers */
    4159 static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4160 {
    4161     PDMDEV_ASSERT_DEVINS(pDevIns);
    4162     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4163     RTRCPTR pRCHelpers = 0;
    4164     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPicHlp", &pRCHelpers);
    4165     AssertReleaseRC(rc);
    4166     AssertRelease(pRCHelpers);
    4167     LogFlow(("pdmR3PicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
    4168              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4169     return pRCHelpers;
    4170 }
    4171 
    4172 
    4173 /** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
    4174 static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4175 {
    4176     PDMDEV_ASSERT_DEVINS(pDevIns);
    4177     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4178     PCPDMPICHLPR0 pR0Helpers = 0;
    4179     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PicHlp", &pR0Helpers);
    4180     AssertReleaseRC(rc);
    4181     AssertRelease(pR0Helpers);
    4182     LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4183              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4184     return pR0Helpers;
    4185 }
    4186 
     132/** @} */
     133
     134
     135
     136
     137/** @name HC APIC Helpers
     138 * @{
     139 */
    4187140
    4188141/** @copydoc PDMAPICHLPR3::pfnSetInterruptFF */
     
    4289242
    4290243
     244/**
     245 * APIC Device Helpers.
     246 */
     247const PDMAPICHLPR3 g_pdmR3DevApicHlp =
     248{
     249    PDM_APICHLPR3_VERSION,
     250    pdmR3ApicHlp_SetInterruptFF,
     251    pdmR3ApicHlp_ClearInterruptFF,
     252    pdmR3ApicHlp_ChangeFeature,
     253    pdmR3ApicHlp_Lock,
     254    pdmR3ApicHlp_Unlock,
     255    pdmR3ApicHlp_GetCpuId,
     256    pdmR3ApicHlp_GetRCHelpers,
     257    pdmR3ApicHlp_GetR0Helpers,
     258    PDM_APICHLPR3_VERSION /* the end */
     259};
     260
     261/** @} */
     262
     263
     264
     265
     266/** @name HC I/O APIC Helpers
     267 * @{
     268 */
     269
    4291270/** @copydoc PDMIOAPICHLPR3::pfnApicBusDeliver */
    4292271static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
     
    4348327
    4349328
     329/**
     330 * I/O APIC Device Helpers.
     331 */
     332const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
     333{
     334    PDM_IOAPICHLPR3_VERSION,
     335    pdmR3IoApicHlp_ApicBusDeliver,
     336    pdmR3IoApicHlp_Lock,
     337    pdmR3IoApicHlp_Unlock,
     338    pdmR3IoApicHlp_GetRCHelpers,
     339    pdmR3IoApicHlp_GetR0Helpers,
     340    PDM_IOAPICHLPR3_VERSION /* the end */
     341};
     342
     343/** @} */
     344
     345
     346
     347
     348/** @name HC PCI Bus Helpers
     349 * @{
     350 */
     351
    4350352/** @copydoc PDMPCIHLPR3::pfnIsaSetIrq */
    4351353static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
     
    4424426
    4425427/**
    4426  * Locates a LUN.
    4427  *
    4428  * @returns VBox status code.
    4429  * @param   pVM             VM Handle.
    4430  * @param   pszDevice       Device name.
    4431  * @param   iInstance       Device instance.
    4432  * @param   iLun            The Logical Unit to obtain the interface of.
    4433  * @param   ppLun           Where to store the pointer to the LUN if found.
    4434  * @thread  Try only do this in EMT...
    4435  */
    4436 int pdmR3DevFindLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMLUN *ppLun)
    4437 {
    4438     /*
    4439      * Iterate registered devices looking for the device.
    4440      */
    4441     RTUINT cchDevice = strlen(pszDevice);
    4442     for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
    4443     {
    4444         if (    pDev->cchName == cchDevice
    4445             &&  !memcmp(pDev->pDevReg->szDeviceName, pszDevice, cchDevice))
    4446         {
    4447             /*
    4448              * Iterate device instances.
    4449              */
    4450             for (PPDMDEVINS pDevIns = pDev->pInstances; pDevIns; pDevIns = pDevIns->Internal.s.pPerDeviceNextR3)
    4451             {
    4452                 if (pDevIns->iInstance == iInstance)
    4453                 {
    4454                     /*
    4455                      * Iterate luns.
    4456                      */
    4457                     for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
    4458                     {
    4459                         if (pLun->iLun == iLun)
    4460                         {
    4461                             *ppLun = pLun;
    4462                             return VINF_SUCCESS;
    4463                         }
    4464                     }
    4465                     return VERR_PDM_LUN_NOT_FOUND;
    4466                 }
    4467             }
    4468             return VERR_PDM_DEVICE_INSTANCE_NOT_FOUND;
    4469         }
    4470     }
    4471     return VERR_PDM_DEVICE_NOT_FOUND;
    4472 }
    4473 
    4474 
    4475 /**
    4476  * Attaches a preconfigured driver to an existing device instance.
    4477  *
    4478  * This is used to change drivers and suchlike at runtime.
    4479  *
    4480  * @returns VBox status code.
    4481  * @param   pVM             VM Handle.
    4482  * @param   pszDevice       Device name.
    4483  * @param   iInstance       Device instance.
    4484  * @param   iLun            The Logical Unit to obtain the interface of.
    4485  * @param   ppBase          Where to store the base interface pointer. Optional.
    4486  * @thread  EMT
    4487  */
    4488 PDMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
    4489 {
    4490     VM_ASSERT_EMT(pVM);
    4491     LogFlow(("PDMR3DeviceAttach: pszDevice=%p:{%s} iInstance=%d iLun=%d ppBase=%p\n",
    4492              pszDevice, pszDevice, iInstance, iLun, ppBase));
    4493 
    4494     /*
    4495      * Find the LUN in question.
    4496      */
    4497     PPDMLUN pLun;
    4498     int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
    4499     if (VBOX_SUCCESS(rc))
    4500     {
    4501         /*
    4502          * Can we attach anything at runtime?
    4503          */
    4504         PPDMDEVINS pDevIns = pLun->pDevIns;
    4505         if (pDevIns->pDevReg->pfnAttach)
    4506         {
    4507             if (!pLun->pTop)
    4508             {
    4509                 rc = pDevIns->pDevReg->pfnAttach(pDevIns, iLun);
    4510 
    4511             }
    4512             else
    4513                 rc = VERR_PDM_DRIVER_ALREADY_ATTACHED;
    4514         }
    4515         else
    4516             rc = VERR_PDM_DEVICE_NO_RT_ATTACH;
    4517 
    4518         if (ppBase)
    4519             *ppBase = pLun->pTop ? &pLun->pTop->IBase : NULL;
    4520     }
    4521     else if (ppBase)
    4522         *ppBase = NULL;
    4523 
    4524     if (ppBase)
    4525         LogFlow(("PDMR3DeviceAttach: returns %Vrc *ppBase=%p\n", rc, *ppBase));
    4526     else
    4527         LogFlow(("PDMR3DeviceAttach: returns %Vrc\n", rc));
    4528     return rc;
    4529 }
    4530 
    4531 
    4532 /**
    4533  * Detaches a driver chain from an existing device instance.
    4534  *
    4535  * This is used to change drivers and suchlike at runtime.
    4536  *
    4537  * @returns VBox status code.
    4538  * @param   pVM             VM Handle.
    4539  * @param   pszDevice       Device name.
    4540  * @param   iInstance       Device instance.
    4541  * @param   iLun            The Logical Unit to obtain the interface of.
    4542  * @thread  EMT
    4543  */
    4544 PDMR3DECL(int) PDMR3DeviceDetach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun)
    4545 {
    4546     VM_ASSERT_EMT(pVM);
    4547     LogFlow(("PDMR3DeviceDetach: pszDevice=%p:{%s} iInstance=%d iLun=%d\n",
    4548              pszDevice, pszDevice, iInstance, iLun));
    4549 
    4550     /*
    4551      * Find the LUN in question.
    4552      */
    4553     PPDMLUN pLun;
    4554     int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
    4555     if (VBOX_SUCCESS(rc))
    4556     {
    4557         /*
    4558          * Can we detach anything at runtime?
    4559          */
    4560         PPDMDEVINS pDevIns = pLun->pDevIns;
    4561         if (pDevIns->pDevReg->pfnDetach)
    4562         {
    4563             if (pLun->pTop)
    4564                 rc = pdmR3DrvDetach(pLun->pTop);
    4565             else
    4566                 rc = VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN;
    4567         }
    4568         else
    4569             rc = VERR_PDM_DEVICE_NO_RT_DETACH;
    4570     }
    4571 
    4572     LogFlow(("PDMR3DeviceDetach: returns %Vrc\n", rc));
    4573     return rc;
    4574 }
    4575 
     428 * PCI Bus Device Helpers.
     429 */
     430const PDMPCIHLPR3 g_pdmR3DevPciHlp =
     431{
     432    PDM_PCIHLPR3_VERSION,
     433    pdmR3PciHlp_IsaSetIrq,
     434    pdmR3PciHlp_IoApicSetIrq,
     435    pdmR3PciHlp_IsMMIO2Base,
     436    pdmR3PciHlp_GetRCHelpers,
     437    pdmR3PciHlp_GetR0Helpers,
     438    pdmR3PciHlp_Lock,
     439    pdmR3PciHlp_Unlock,
     440    PDM_PCIHLPR3_VERSION, /* the end */
     441};
     442
     443/** @} */
     444
     445
     446
     447/* none yet */
     448
     449/**
     450 * DMAC Device Helpers.
     451 */
     452const PDMDMACHLP g_pdmR3DevDmacHlp =
     453{
     454    PDM_DMACHLP_VERSION
     455};
     456
     457
     458
     459
     460/* none yet */
     461
     462/**
     463 * RTC Device Helpers.
     464 */
     465const PDMRTCHLP g_pdmR3DevRtcHlp =
     466{
     467    PDM_RTCHLP_VERSION
     468};
     469
     470
  • trunk/src/VBox/VMM/PDMDevice.cpp

    r12979 r12980  
    7575static DECLCALLBACK(int)    pdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pDevReg);
    7676static DECLCALLBACK(void *) pdmR3DevReg_MMHeapAlloc(PPDMDEVREGCB pCallbacks, size_t cb);
    77 static DECLCALLBACK(bool)   pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem);
    78 
    79 /* VSlick regex:
    80 search : \om/\*\*.+?\*\/\nDECLCALLBACKMEMBER\(([^,]*), *pfn([^)]*)\)\(
    81 replace: \/\*\* @copydoc PDMDEVHLPR3::pfn\2 \*\/\nstatic DECLCALLBACK\(\1\) pdmR3DevHlp_\2\(
    82  */
    83 
    84 /** @name R3 DevHlp
    85  * @{
    86  */
    87 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn, PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc);
    88 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTRCPTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
    89 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser, const char *pszOut, const char *pszIn, const char *pszOutStr, const char *pszInStr, const char *pszDesc);
    90 static DECLCALLBACK(int)    pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts);
    91 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
    92                                                      PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
    93                                                      const char *pszDesc);
    94 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
    95                                                        const char *pszWrite, const char *pszRead, const char *pszFill,
    96                                                        const char *pszDesc);
    97 static DECLCALLBACK(int)    pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
    98                                                        const char *pszWrite, const char *pszRead, const char *pszFill,
    99                                                        const char *pszDesc);
    100 static DECLCALLBACK(int)    pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    101 static DECLCALLBACK(int)    pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc);
    102 static DECLCALLBACK(int)    pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
    103                                                     PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
    104                                                     PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone);
    105 static DECLCALLBACK(int)    pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer);
    106 static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc);
    107 static DECLCALLBACK(int)    pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev);
    108 static DECLCALLBACK(int)    pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback);
    109 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
    110                                                               PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld);
    111 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    112 static DECLCALLBACK(void)   pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    113 static DECLCALLBACK(void)   pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    114 static DECLCALLBACK(void)   pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    115 static DECLCALLBACK(int)    pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc);
    116 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb);
    117 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb);
    118 static DECLCALLBACK(void)   pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv);
    119 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
    120 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va);
    121 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...);
    122 static DECLCALLBACK(int)    pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va);
    123 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    124 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    125 static DECLCALLBACK(int)    pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args);
    126 static DECLCALLBACK(int)    pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler);
    127 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
    128 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...);
    129 static DECLCALLBACK(void)   pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args);
    130 static DECLCALLBACK(int)    pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName);
    131 static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime);
    132 static DECLCALLBACK(int)    pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
    133                                                         PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
    134 
    135 static DECLCALLBACK(PVM)    pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns);
    136 static DECLCALLBACK(int)    pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
    137 static DECLCALLBACK(int)    pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
    138 static DECLCALLBACK(int)    pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
    139 static DECLCALLBACK(int)    pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
    140 static DECLCALLBACK(int)    pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
    141 static DECLCALLBACK(int)    pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp);
    142 static DECLCALLBACK(int)    pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue);
    143 static DECLCALLBACK(void)   pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
    144 static DECLCALLBACK(void)   pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
    145 static DECLCALLBACK(int)    pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
    146 static DECLCALLBACK(int)    pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
    147 static DECLCALLBACK(int)    pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
    148 static DECLCALLBACK(int)    pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys);
    149 static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns);
    150 static DECLCALLBACK(bool)   pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns);
    151 static DECLCALLBACK(void)   pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable);
    152 static DECLCALLBACK(int)    pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns);
    153 static DECLCALLBACK(int)    pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns);
    154 static DECLCALLBACK(int)    pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns);
    155 static DECLCALLBACK(int)    pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns);
    156 static DECLCALLBACK(int)    pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns);
    157 static DECLCALLBACK(bool)   pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    158 static DECLCALLBACK(int)    pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
    159 static DECLCALLBACK(int)    pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
    160 static DECLCALLBACK(int)    pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
    161 static DECLCALLBACK(int)    pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
    162 static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
    163 static DECLCALLBACK(void)   pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns);
    164 static DECLCALLBACK(int)    pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
    165 static DECLCALLBACK(int)    pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
    166 static DECLCALLBACK(void)   pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    167                                                uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
    168 static DECLCALLBACK(int)    pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    169 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc);
    170 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion);
    171 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    172 static DECLCALLBACK(int)    pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    173 static DECLCALLBACK(int)    pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr);
    174 static DECLCALLBACK(int)    pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize);
    175 static DECLCALLBACK(int)    pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys);
    176 
    177 static DECLCALLBACK(PVM)    pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns);
    178 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3);
    179 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3);
    180 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3);
    181 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3);
    182 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp);
    183 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
    184 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
    185 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb);
    186 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb);
    187 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc);
    188 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC);
    189 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr);
    190 
    191 static DECLCALLBACK(bool)   pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns);
    192 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable);
    193 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns);
    194 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns);
    195 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns);
    196 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns);
    197 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns);
    198 static DECLCALLBACK(bool)   pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction);
    199 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser);
    200 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead);
    201 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten);
    202 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel);
    203 static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel);
    204 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns);
    205 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value);
    206 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value);
    207 static DECLCALLBACK(void)   pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    208                                                            uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
    209 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    210 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc);
    211 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion);
    212 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    213 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
    214 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr);
    215 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize);
    216 static DECLCALLBACK(int)    pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys);
    217 /** @} */
    218 
    219 
    220 /** @name HC PIC Helpers
    221  * @{
    222  */
    223 static DECLCALLBACK(void)   pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns);
    224 static DECLCALLBACK(void)   pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns);
    225 static DECLCALLBACK(int)    pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    226 static DECLCALLBACK(void)   pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns);
    227 static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    228 static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    229 /** @} */
    230 
    231 
    232 /** @name HC APIC Helpers
    233  * @{
    234  */
    235 static DECLCALLBACK(void)   pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu);
    236 static DECLCALLBACK(void)   pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu);
    237 static DECLCALLBACK(void)   pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion);
    238 static DECLCALLBACK(int)    pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    239 static DECLCALLBACK(void)   pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns);
    240 static DECLCALLBACK(VMCPUID) pdmR3ApicHlp_GetCpuId(PPDMDEVINS pDevIns);
    241 static DECLCALLBACK(PCPDMAPICHLPRC) pdmR3ApicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    242 static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    243 /** @} */
    244 
    245 
    246 /** @name HC I/O APIC Helpers
    247  * @{
    248  */
    249 static DECLCALLBACK(void)   pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
    250                                                           uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode);
    251 static DECLCALLBACK(int)    pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc);
    252 static DECLCALLBACK(void)   pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns);
    253 static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    254 static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    255 /** @} */
    256 
    257 
    258 /** @name HC PCI Bus Helpers
    259  * @{
    260  */
    261 static DECLCALLBACK(void)   pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    262 static DECLCALLBACK(void)   pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel);
    263 static DECLCALLBACK(bool)   pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys);
    264 static DECLCALLBACK(int)    pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc);
    265 static DECLCALLBACK(void)   pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns);
    266 static DECLCALLBACK(PCPDMPCIHLPRC) pdmR3PciHlp_GetRCHelpers(PPDMDEVINS pDevIns);
    267 static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns);
    268 /** @} */
    269 
    270 /** @def PDMDEV_ASSERT_DEVINS
    271  * Asserts the validity of the device instance.
    272  */
    273 #ifdef VBOX_STRICT
    274 # define PDMDEV_ASSERT_DEVINS(pDevIns)   \
    275     do { \
    276         AssertPtr(pDevIns); \
    277         Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); \
    278         Assert(pDevIns->pvInstanceDataR3 == (void *)&pDevIns->achInstanceData[0]); \
    279     } while (0)
    280 #else
    281 # define PDMDEV_ASSERT_DEVINS(pDevIns)   do { } while (0)
    282 #endif
    28377
    28478static int pdmR3DevLoadModules(PVM pVM);
     
    29286
    29387__END_DECLS
    294 
    295 /*******************************************************************************
    296 *   Global Variables                                                           *
    297 *******************************************************************************/
    298 /**
    299  * The device helper structure for trusted devices.
    300  */
    301 const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
    302 {
    303     PDM_DEVHLP_VERSION,
    304     pdmR3DevHlp_IOPortRegister,
    305     pdmR3DevHlp_IOPortRegisterGC,
    306     pdmR3DevHlp_IOPortRegisterR0,
    307     pdmR3DevHlp_IOPortDeregister,
    308     pdmR3DevHlp_MMIORegister,
    309     pdmR3DevHlp_MMIORegisterGC,
    310     pdmR3DevHlp_MMIORegisterR0,
    311     pdmR3DevHlp_MMIODeregister,
    312     pdmR3DevHlp_ROMRegister,
    313     pdmR3DevHlp_SSMRegister,
    314     pdmR3DevHlp_TMTimerCreate,
    315     pdmR3DevHlp_TMTimerCreateExternal,
    316     pdmR3DevHlp_PCIRegister,
    317     pdmR3DevHlp_PCIIORegionRegister,
    318     pdmR3DevHlp_PCISetConfigCallbacks,
    319     pdmR3DevHlp_PCISetIrq,
    320     pdmR3DevHlp_PCISetIrqNoWait,
    321     pdmR3DevHlp_ISASetIrq,
    322     pdmR3DevHlp_ISASetIrqNoWait,
    323     pdmR3DevHlp_DriverAttach,
    324     pdmR3DevHlp_MMHeapAlloc,
    325     pdmR3DevHlp_MMHeapAllocZ,
    326     pdmR3DevHlp_MMHeapFree,
    327     pdmR3DevHlp_VMSetError,
    328     pdmR3DevHlp_VMSetErrorV,
    329     pdmR3DevHlp_VMSetRuntimeError,
    330     pdmR3DevHlp_VMSetRuntimeErrorV,
    331     pdmR3DevHlp_AssertEMT,
    332     pdmR3DevHlp_AssertOther,
    333     pdmR3DevHlp_DBGFStopV,
    334     pdmR3DevHlp_DBGFInfoRegister,
    335     pdmR3DevHlp_STAMRegister,
    336     pdmR3DevHlp_STAMRegisterF,
    337     pdmR3DevHlp_STAMRegisterV,
    338     pdmR3DevHlp_RTCRegister,
    339     pdmR3DevHlp_PDMQueueCreate,
    340     pdmR3DevHlp_CritSectInit,
    341     pdmR3DevHlp_UTCNow,
    342     pdmR3DevHlp_PDMThreadCreate,
    343     pdmR3DevHlp_PhysGCPtr2GCPhys,
    344     pdmR3DevHlp_VMState,
    345     0,
    346     0,
    347     0,
    348     0,
    349     0,
    350     0,
    351     0,
    352     pdmR3DevHlp_GetVM,
    353     pdmR3DevHlp_PCIBusRegister,
    354     pdmR3DevHlp_PICRegister,
    355     pdmR3DevHlp_APICRegister,
    356     pdmR3DevHlp_IOAPICRegister,
    357     pdmR3DevHlp_DMACRegister,
    358     pdmR3DevHlp_PhysRead,
    359     pdmR3DevHlp_PhysWrite,
    360     pdmR3DevHlp_PhysReadGCVirt,
    361     pdmR3DevHlp_PhysWriteGCVirt,
    362     pdmR3DevHlp_PhysReserve,
    363     pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt,
    364     pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr,
    365     pdmR3DevHlp_A20IsEnabled,
    366     pdmR3DevHlp_A20Set,
    367     pdmR3DevHlp_VMReset,
    368     pdmR3DevHlp_VMSuspend,
    369     pdmR3DevHlp_VMPowerOff,
    370     pdmR3DevHlp_LockVM,
    371     pdmR3DevHlp_UnlockVM,
    372     pdmR3DevHlp_AssertVMLock,
    373     pdmR3DevHlp_DMARegister,
    374     pdmR3DevHlp_DMAReadMemory,
    375     pdmR3DevHlp_DMAWriteMemory,
    376     pdmR3DevHlp_DMASetDREQ,
    377     pdmR3DevHlp_DMAGetChannelMode,
    378     pdmR3DevHlp_DMASchedule,
    379     pdmR3DevHlp_CMOSWrite,
    380     pdmR3DevHlp_CMOSRead,
    381     pdmR3DevHlp_GetCpuId,
    382     pdmR3DevHlp_ROMProtectShadow,
    383     pdmR3DevHlp_MMIO2Register,
    384     pdmR3DevHlp_MMIO2Deregister,
    385     pdmR3DevHlp_MMIO2Map,
    386     pdmR3DevHlp_MMIO2Unmap,
    387     pdmR3DevHlp_MMHyperMapMMIO2,
    388     pdmR3DevHlp_RegisterVMMDevHeap,
    389     pdmR3DevHlp_UnregisterVMMDevHeap,
    390     PDM_DEVHLP_VERSION /* the end */
    391 };
    392 
    393 
    394 /**
    395  * The device helper structure for non-trusted devices.
    396  */
    397 const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
    398 {
    399     PDM_DEVHLP_VERSION,
    400     pdmR3DevHlp_IOPortRegister,
    401     pdmR3DevHlp_IOPortRegisterGC,
    402     pdmR3DevHlp_IOPortRegisterR0,
    403     pdmR3DevHlp_IOPortDeregister,
    404     pdmR3DevHlp_MMIORegister,
    405     pdmR3DevHlp_MMIORegisterGC,
    406     pdmR3DevHlp_MMIORegisterR0,
    407     pdmR3DevHlp_MMIODeregister,
    408     pdmR3DevHlp_ROMRegister,
    409     pdmR3DevHlp_SSMRegister,
    410     pdmR3DevHlp_TMTimerCreate,
    411     pdmR3DevHlp_TMTimerCreateExternal,
    412     pdmR3DevHlp_PCIRegister,
    413     pdmR3DevHlp_PCIIORegionRegister,
    414     pdmR3DevHlp_PCISetConfigCallbacks,
    415     pdmR3DevHlp_PCISetIrq,
    416     pdmR3DevHlp_PCISetIrqNoWait,
    417     pdmR3DevHlp_ISASetIrq,
    418     pdmR3DevHlp_ISASetIrqNoWait,
    419     pdmR3DevHlp_DriverAttach,
    420     pdmR3DevHlp_MMHeapAlloc,
    421     pdmR3DevHlp_MMHeapAllocZ,
    422     pdmR3DevHlp_MMHeapFree,
    423     pdmR3DevHlp_VMSetError,
    424     pdmR3DevHlp_VMSetErrorV,
    425     pdmR3DevHlp_VMSetRuntimeError,
    426     pdmR3DevHlp_VMSetRuntimeErrorV,
    427     pdmR3DevHlp_AssertEMT,
    428     pdmR3DevHlp_AssertOther,
    429     pdmR3DevHlp_DBGFStopV,
    430     pdmR3DevHlp_DBGFInfoRegister,
    431     pdmR3DevHlp_STAMRegister,
    432     pdmR3DevHlp_STAMRegisterF,
    433     pdmR3DevHlp_STAMRegisterV,
    434     pdmR3DevHlp_RTCRegister,
    435     pdmR3DevHlp_PDMQueueCreate,
    436     pdmR3DevHlp_CritSectInit,
    437     pdmR3DevHlp_UTCNow,
    438     pdmR3DevHlp_PDMThreadCreate,
    439     pdmR3DevHlp_PhysGCPtr2GCPhys,
    440     pdmR3DevHlp_VMState,
    441     0,
    442     0,
    443     0,
    444     0,
    445     0,
    446     0,
    447     0,
    448     pdmR3DevHlp_Untrusted_GetVM,
    449     pdmR3DevHlp_Untrusted_PCIBusRegister,
    450     pdmR3DevHlp_Untrusted_PICRegister,
    451     pdmR3DevHlp_Untrusted_APICRegister,
    452     pdmR3DevHlp_Untrusted_IOAPICRegister,
    453     pdmR3DevHlp_Untrusted_DMACRegister,
    454     pdmR3DevHlp_Untrusted_PhysRead,
    455     pdmR3DevHlp_Untrusted_PhysWrite,
    456     pdmR3DevHlp_Untrusted_PhysReadGCVirt,
    457     pdmR3DevHlp_Untrusted_PhysWriteGCVirt,
    458     pdmR3DevHlp_Untrusted_PhysReserve,
    459     pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt,
    460     pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr,
    461     pdmR3DevHlp_Untrusted_A20IsEnabled,
    462     pdmR3DevHlp_Untrusted_A20Set,
    463     pdmR3DevHlp_Untrusted_VMReset,
    464     pdmR3DevHlp_Untrusted_VMSuspend,
    465     pdmR3DevHlp_Untrusted_VMPowerOff,
    466     pdmR3DevHlp_Untrusted_LockVM,
    467     pdmR3DevHlp_Untrusted_UnlockVM,
    468     pdmR3DevHlp_Untrusted_AssertVMLock,
    469     pdmR3DevHlp_Untrusted_DMARegister,
    470     pdmR3DevHlp_Untrusted_DMAReadMemory,
    471     pdmR3DevHlp_Untrusted_DMAWriteMemory,
    472     pdmR3DevHlp_Untrusted_DMASetDREQ,
    473     pdmR3DevHlp_Untrusted_DMAGetChannelMode,
    474     pdmR3DevHlp_Untrusted_DMASchedule,
    475     pdmR3DevHlp_Untrusted_CMOSWrite,
    476     pdmR3DevHlp_Untrusted_CMOSRead,
    477     pdmR3DevHlp_Untrusted_GetCpuId,
    478     pdmR3DevHlp_Untrusted_ROMProtectShadow,
    479     pdmR3DevHlp_Untrusted_MMIO2Register,
    480     pdmR3DevHlp_Untrusted_MMIO2Deregister,
    481     pdmR3DevHlp_Untrusted_MMIO2Map,
    482     pdmR3DevHlp_Untrusted_MMIO2Unmap,
    483     pdmR3DevHlp_Untrusted_MMHyperMapMMIO2,
    484     pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
    485     pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap,
    486     PDM_DEVHLP_VERSION /* the end */
    487 };
    488 
    489 
    490 /**
    491  * PIC Device Helpers.
    492  */
    493 const PDMPICHLPR3 g_pdmR3DevPicHlp =
    494 {
    495     PDM_PICHLPR3_VERSION,
    496     pdmR3PicHlp_SetInterruptFF,
    497     pdmR3PicHlp_ClearInterruptFF,
    498     pdmR3PicHlp_Lock,
    499     pdmR3PicHlp_Unlock,
    500     pdmR3PicHlp_GetRCHelpers,
    501     pdmR3PicHlp_GetR0Helpers,
    502     PDM_PICHLPR3_VERSION /* the end */
    503 };
    504 
    505 
    506 /**
    507  * APIC Device Helpers.
    508  */
    509 const PDMAPICHLPR3 g_pdmR3DevApicHlp =
    510 {
    511     PDM_APICHLPR3_VERSION,
    512     pdmR3ApicHlp_SetInterruptFF,
    513     pdmR3ApicHlp_ClearInterruptFF,
    514     pdmR3ApicHlp_ChangeFeature,
    515     pdmR3ApicHlp_Lock,
    516     pdmR3ApicHlp_Unlock,
    517     pdmR3ApicHlp_GetCpuId,
    518     pdmR3ApicHlp_GetRCHelpers,
    519     pdmR3ApicHlp_GetR0Helpers,
    520     PDM_APICHLPR3_VERSION /* the end */
    521 };
    522 
    523 
    524 /**
    525  * I/O APIC Device Helpers.
    526  */
    527 const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp =
    528 {
    529     PDM_IOAPICHLPR3_VERSION,
    530     pdmR3IoApicHlp_ApicBusDeliver,
    531     pdmR3IoApicHlp_Lock,
    532     pdmR3IoApicHlp_Unlock,
    533     pdmR3IoApicHlp_GetRCHelpers,
    534     pdmR3IoApicHlp_GetR0Helpers,
    535     PDM_IOAPICHLPR3_VERSION /* the end */
    536 };
    537 
    538 
    539 /**
    540  * PCI Bus Device Helpers.
    541  */
    542 const PDMPCIHLPR3 g_pdmR3DevPciHlp =
    543 {
    544     PDM_PCIHLPR3_VERSION,
    545     pdmR3PciHlp_IsaSetIrq,
    546     pdmR3PciHlp_IoApicSetIrq,
    547     pdmR3PciHlp_IsMMIO2Base,
    548     pdmR3PciHlp_GetRCHelpers,
    549     pdmR3PciHlp_GetR0Helpers,
    550     pdmR3PciHlp_Lock,
    551     pdmR3PciHlp_Unlock,
    552     PDM_PCIHLPR3_VERSION, /* the end */
    553 };
    554 
    555 
    556 /**
    557  * DMAC Device Helpers.
    558  */
    559 const PDMDMACHLP g_pdmR3DevDmacHlp =
    560 {
    561     PDM_DMACHLP_VERSION
    562 };
    563 
    564 
    565 /**
    566  * RTC Device Helpers.
    567  */
    568 const PDMRTCHLP g_pdmR3DevRtcHlp =
    569 {
    570     PDM_RTCHLP_VERSION
    571 };
    57288
    57389
     
    1215731
    1216732
    1217 
    1218 
    1219 
    1220 /*
    1221  *
    1222  *
    1223  *
    1224  *
    1225  *   p d m R 3 D e v H l p
    1226  *   p d m R 3 D e v H l p
    1227  *   p d m R 3 D e v H l p
    1228  *
    1229  *
    1230  *
    1231  *
    1232  */
    1233 
    1234 
    1235 /**
    1236  * Queue consumer callback for internal component.
    1237  *
    1238  * @returns Success indicator.
    1239  *          If false the item will not be removed and the flushing will stop.
    1240  * @param   pVM         The VM handle.
    1241  * @param   pItem       The item to consume. Upon return this item will be freed.
    1242  */
    1243 static DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
    1244 {
    1245     PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
    1246     LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsHC));
    1247     switch (pTask->enmOp)
    1248     {
    1249         case PDMDEVHLPTASKOP_ISA_SET_IRQ:
    1250             PDMIsaSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
    1251             break;
    1252 
    1253         case PDMDEVHLPTASKOP_PCI_SET_IRQ:
    1254             pdmR3DevHlp_PCISetIrq(pTask->pDevInsHC, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
    1255             break;
    1256 
    1257         case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
    1258             PDMIoApicSetIrq(pVM, pTask->u.SetIRQ.iIrq, pTask->u.SetIRQ.iLevel);
    1259             break;
    1260 
    1261         default:
    1262             AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
    1263             break;
    1264     }
    1265     return true;
    1266 }
    1267 
    1268 
    1269 /** @copydoc PDMDEVHLPR3::pfnIOPortRegister */
    1270 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
    1271                                                     PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
    1272 {
    1273     PDMDEV_ASSERT_DEVINS(pDevIns);
    1274     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->pDevReg->szDeviceName, pDevIns->iInstance,
    1275              Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));
    1276     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1277 
    1278     int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
    1279 
    1280     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1281     return rc;
    1282 }
    1283 
    1284 
    1285 /** @copydoc PDMDEVHLPR3::pfnIOPortRegisterGC */
    1286 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterGC(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTRCPTR pvUser,
    1287                                                       const char *pszOut, const char *pszIn,
    1288                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    1289 {
    1290     PDMDEV_ASSERT_DEVINS(pDevIns);
    1291     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1292     LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1293              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    1294 
    1295     /*
    1296      * Resolve the functions (one of the can be NULL).
    1297      */
    1298     int rc = VINF_SUCCESS;
    1299     if (    pDevIns->pDevReg->szRCMod[0]
    1300         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    1301     {
    1302         RTGCPTR32 GCPtrIn = 0;
    1303         if (pszIn)
    1304         {
    1305             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszIn, &GCPtrIn);
    1306             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szRCMod, pszIn));
    1307         }
    1308         RTGCPTR32 GCPtrOut = 0;
    1309         if (pszOut && VBOX_SUCCESS(rc))
    1310         {
    1311             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOut, &GCPtrOut);
    1312             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szRCMod, pszOut));
    1313         }
    1314         RTGCPTR32 GCPtrInStr = 0;
    1315         if (pszInStr && VBOX_SUCCESS(rc))
    1316         {
    1317             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszInStr, &GCPtrInStr);
    1318             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szRCMod, pszInStr));
    1319         }
    1320         RTGCPTR32 GCPtrOutStr = 0;
    1321         if (pszOutStr && VBOX_SUCCESS(rc))
    1322         {
    1323             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszOutStr, &GCPtrOutStr);
    1324             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szRCMod, pszOutStr));
    1325         }
    1326 
    1327         if (VBOX_SUCCESS(rc))
    1328             rc = IOMR3IOPortRegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc);
    1329     }
    1330     else
    1331     {
    1332         AssertMsgFailed(("No GC module for this driver!\n"));
    1333         rc = VERR_INVALID_PARAMETER;
    1334     }
    1335 
    1336     LogFlow(("pdmR3DevHlp_IOPortRegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1337     return rc;
    1338 }
    1339 
    1340 
    1341 /** @copydoc PDMDEVHLPR3::pfnIOPortRegisterR0 */
    1342 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts, RTR0PTR pvUser,
    1343                                                       const char *pszOut, const char *pszIn,
    1344                                                       const char *pszOutStr, const char *pszInStr, const char *pszDesc)
    1345 {
    1346     PDMDEV_ASSERT_DEVINS(pDevIns);
    1347     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1348     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1349              Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
    1350 
    1351     /*
    1352      * Resolve the functions (one of the can be NULL).
    1353      */
    1354     int rc = VINF_SUCCESS;
    1355     if (    pDevIns->pDevReg->szR0Mod[0]
    1356         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    1357     {
    1358         R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;
    1359         if (pszIn)
    1360         {
    1361             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszIn, &pfnR0PtrIn);
    1362             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szR0Mod, pszIn));
    1363         }
    1364         R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;
    1365         if (pszOut && VBOX_SUCCESS(rc))
    1366         {
    1367             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOut, &pfnR0PtrOut);
    1368             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szR0Mod, pszOut));
    1369         }
    1370         R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;
    1371         if (pszInStr && VBOX_SUCCESS(rc))
    1372         {
    1373             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszInStr, &pfnR0PtrInStr);
    1374             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szR0Mod, pszInStr));
    1375         }
    1376         R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;
    1377         if (pszOutStr && VBOX_SUCCESS(rc))
    1378         {
    1379             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszOutStr, &pfnR0PtrOutStr);
    1380             AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pDevReg->szR0Mod, pszOutStr));
    1381         }
    1382 
    1383         if (VBOX_SUCCESS(rc))
    1384             rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);
    1385     }
    1386     else
    1387     {
    1388         AssertMsgFailed(("No R0 module for this driver!\n"));
    1389         rc = VERR_INVALID_PARAMETER;
    1390     }
    1391 
    1392     LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1393     return rc;
    1394 }
    1395 
    1396 
    1397 /** @copydoc PDMDEVHLPR3::pfnIOPortDeregister */
    1398 static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTUINT cPorts)
    1399 {
    1400     PDMDEV_ASSERT_DEVINS(pDevIns);
    1401     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1402     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    1403              Port, cPorts));
    1404 
    1405     int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts);
    1406 
    1407     LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1408     return rc;
    1409 }
    1410 
    1411 
    1412 /** @copydoc PDMDEVHLPR3::pfnMMIORegister */
    1413 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
    1414                                                   PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
    1415                                                   const char *pszDesc)
    1416 {
    1417     PDMDEV_ASSERT_DEVINS(pDevIns);
    1418     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1419     LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pfnWrite=%p pfnRead=%p pfnFill=%p pszDesc=%p:{%s}\n",
    1420              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc, pszDesc));
    1421 
    1422     int rc = IOMR3MMIORegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill, pszDesc);
    1423 
    1424     LogFlow(("pdmR3DevHlp_MMIORegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1425     return rc;
    1426 }
    1427 
    1428 
    1429 /** @copydoc PDMDEVHLPR3::pfnMMIORegisterGC */
    1430 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterGC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,
    1431                                                     const char *pszWrite, const char *pszRead, const char *pszFill,
    1432                                                     const char *pszDesc)
    1433 {
    1434     PDMDEV_ASSERT_DEVINS(pDevIns);
    1435     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1436     LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
    1437              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
    1438 
    1439     /*
    1440      * Resolve the functions.
    1441      * Not all function have to present, leave it to IOM to enforce this.
    1442      */
    1443     int rc = VINF_SUCCESS;
    1444     if (    pDevIns->pDevReg->szRCMod[0]
    1445         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    1446     {
    1447         RTGCPTR32 GCPtrWrite = 0;
    1448         if (pszWrite)
    1449             rc = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszWrite, &GCPtrWrite);
    1450         RTGCPTR32 GCPtrRead = 0;
    1451         int rc2 = VINF_SUCCESS;
    1452         if (pszRead)
    1453             rc2 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszRead, &GCPtrRead);
    1454         RTGCPTR32 GCPtrFill = 0;
    1455         int rc3 = VINF_SUCCESS;
    1456         if (pszFill)
    1457             rc3 = PDMR3LdrGetSymbolRCLazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szRCMod, pszFill, &GCPtrFill);
    1458         if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1459             rc = IOMR3MMIORegisterRC(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill);
    1460         else
    1461         {
    1462             AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szRCMod, pszWrite));
    1463             AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szRCMod, pszRead));
    1464             AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szRCMod, pszFill));
    1465             if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
    1466                 rc = rc2;
    1467             if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
    1468                 rc = rc3;
    1469         }
    1470     }
    1471     else
    1472     {
    1473         AssertMsgFailed(("No GC module for this driver!\n"));
    1474         rc = VERR_INVALID_PARAMETER;
    1475     }
    1476 
    1477     LogFlow(("pdmR3DevHlp_MMIORegisterGC: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1478     return rc;
    1479 }
    1480 
    1481 /** @copydoc PDMDEVHLPR3::pfnMMIORegisterR0 */
    1482 static DECLCALLBACK(int) pdmR3DevHlp_MMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,
    1483                                                     const char *pszWrite, const char *pszRead, const char *pszFill,
    1484                                                     const char *pszDesc)
    1485 {
    1486     PDMDEV_ASSERT_DEVINS(pDevIns);
    1487     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1488     LogFlow(("pdmR3DevHlp_MMIORegisterHC: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvUser=%p pszWrite=%p:{%s} pszRead=%p:{%s} pszFill=%p:{%s}\n",
    1489              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvUser, pszWrite, pszWrite, pszRead, pszRead, pszFill, pszFill));
    1490 
    1491     /*
    1492      * Resolve the functions.
    1493      * Not all function have to present, leave it to IOM to enforce this.
    1494      */
    1495     int rc = VINF_SUCCESS;
    1496     if (    pDevIns->pDevReg->szR0Mod[0]
    1497         &&  (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    1498     {
    1499         R0PTRTYPE(PFNIOMMMIOWRITE) pfnR0PtrWrite = 0;
    1500         if (pszWrite)
    1501             rc = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszWrite, &pfnR0PtrWrite);
    1502         R0PTRTYPE(PFNIOMMMIOREAD) pfnR0PtrRead = 0;
    1503         int rc2 = VINF_SUCCESS;
    1504         if (pszRead)
    1505             rc2 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszRead, &pfnR0PtrRead);
    1506         R0PTRTYPE(PFNIOMMMIOFILL) pfnR0PtrFill = 0;
    1507         int rc3 = VINF_SUCCESS;
    1508         if (pszFill)
    1509             rc3 = PDMR3LdrGetSymbolR0Lazy(pDevIns->Internal.s.pVMR3, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill);
    1510         if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1511             rc = IOMR3MMIORegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill);
    1512         else
    1513         {
    1514             AssertMsgRC(rc,  ("Failed to resolve %s.%s (pszWrite)\n", pDevIns->pDevReg->szR0Mod, pszWrite));
    1515             AssertMsgRC(rc2, ("Failed to resolve %s.%s (pszRead)\n",  pDevIns->pDevReg->szR0Mod, pszRead));
    1516             AssertMsgRC(rc3, ("Failed to resolve %s.%s (pszFill)\n",  pDevIns->pDevReg->szR0Mod, pszFill));
    1517             if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc))
    1518                 rc = rc2;
    1519             if (VBOX_FAILURE(rc3) && VBOX_SUCCESS(rc))
    1520                 rc = rc3;
    1521         }
    1522     }
    1523     else
    1524     {
    1525         AssertMsgFailed(("No R0 module for this driver!\n"));
    1526         rc = VERR_INVALID_PARAMETER;
    1527     }
    1528 
    1529     LogFlow(("pdmR3DevHlp_MMIORegisterR0: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1530     return rc;
    1531 }
    1532 
    1533 
    1534 /** @copydoc PDMDEVHLPR3::pfnMMIODeregister */
    1535 static DECLCALLBACK(int) pdmR3DevHlp_MMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    1536 {
    1537     PDMDEV_ASSERT_DEVINS(pDevIns);
    1538     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1539     LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
    1540              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
    1541 
    1542     int rc = IOMR3MMIODeregister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange);
    1543 
    1544     LogFlow(("pdmR3DevHlp_MMIODeregister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1545     return rc;
    1546 }
    1547 
    1548 
    1549 /** @copydoc PDMDEVHLPR3::pfnROMRegister */
    1550 static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, const void *pvBinary, bool fShadow, const char *pszDesc)
    1551 {
    1552     PDMDEV_ASSERT_DEVINS(pDevIns);
    1553     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1554     LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x pvBinary=%p fShadow=%RTbool pszDesc=%p:{%s}\n",
    1555              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc, pszDesc));
    1556 
    1557     int rc = MMR3PhysRomRegister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvBinary, fShadow, pszDesc);
    1558 
    1559     LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1560     return rc;
    1561 }
    1562 
    1563 
    1564 /** @copydoc PDMDEVHLPR3::pfnSSMRegister */
    1565 static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess,
    1566                                                  PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
    1567                                                  PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
    1568 {
    1569     PDMDEV_ASSERT_DEVINS(pDevIns);
    1570     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1571     LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: pszName=%p:{%s} u32Instance=%#x u32Version=#x cbGuess=%#x pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoaddone=%p\n",
    1572              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, u32Instance, u32Version, cbGuess, pfnSavePrep, pfnSaveExec, pfnSaveDone, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
    1573 
    1574     int rc = SSMR3Register(pDevIns->Internal.s.pVMR3, pDevIns, pszName, u32Instance, u32Version, cbGuess,
    1575                            pfnSavePrep, pfnSaveExec, pfnSaveDone,
    1576                            pfnLoadPrep, pfnLoadExec, pfnLoadDone);
    1577 
    1578     LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1579     return rc;
    1580 }
    1581 
    1582 
    1583 /** @copydoc PDMDEVHLPR3::pfnTMTimerCreate */
    1584 static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
    1585 {
    1586     PDMDEV_ASSERT_DEVINS(pDevIns);
    1587     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1588     LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
    1589              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
    1590 
    1591     int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
    1592 
    1593     LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1594     return rc;
    1595 }
    1596 
    1597 
    1598 /** @copydoc PDMDEVHLPR3::pfnTMTimerCreateExternal */
    1599 static DECLCALLBACK(PTMTIMERR3) pdmR3DevHlp_TMTimerCreateExternal(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc)
    1600 {
    1601     PDMDEV_ASSERT_DEVINS(pDevIns);
    1602     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    1603 
    1604     return TMR3TimerCreateExternal(pDevIns->Internal.s.pVMR3, enmClock, pfnCallback, pvUser, pszDesc);
    1605 }
    1606 
    1607 /** @copydoc PDMDEVHLPR3::pfnPCIRegister */
    1608 static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev)
    1609 {
    1610     PDMDEV_ASSERT_DEVINS(pDevIns);
    1611     PVM pVM = pDevIns->Internal.s.pVMR3;
    1612     VM_ASSERT_EMT(pVM);
    1613     LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Vhxs}\n",
    1614              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pPciDev->config));
    1615 
    1616     /*
    1617      * Validate input.
    1618      */
    1619     if (!pPciDev)
    1620     {
    1621         Assert(pPciDev);
    1622         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (pPciDev)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1623         return VERR_INVALID_PARAMETER;
    1624     }
    1625     if (!pPciDev->config[0] && !pPciDev->config[1])
    1626     {
    1627         Assert(pPciDev->config[0] || pPciDev->config[1]);
    1628         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (vendor)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1629         return VERR_INVALID_PARAMETER;
    1630     }
    1631     if (pDevIns->Internal.s.pPciDeviceR3)
    1632     {
    1633         /** @todo the PCI device vs. PDM device designed is a bit flawed if we have to
    1634          * support a PDM device with multiple PCI devices. This might become a problem
    1635          * when upgrading the chipset for instance...
    1636          */
    1637         AssertMsgFailed(("Only one PCI device per device is currently implemented!\n"));
    1638         return VERR_INTERNAL_ERROR;
    1639     }
    1640 
    1641     /*
    1642      * Choose the PCI bus for the device.
    1643      * This is simple. If the device was configured for a particular bus, it'll
    1644      * already have one. If not, we'll just take the first one.
    1645      */
    1646     PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1647     if (!pBus)
    1648         pBus = pDevIns->Internal.s.pPciBusR3 = &pVM->pdm.s.aPciBuses[0];
    1649     int rc;
    1650     if (pBus)
    1651     {
    1652         if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1653             pDevIns->Internal.s.pPciBusR0 = MMHyperR3ToR0(pVM, pDevIns->Internal.s.pPciBusR3);
    1654         else
    1655             pDevIns->Internal.s.pPciBusR0 = NIL_RTR0PTR;
    1656 
    1657         if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1658             pDevIns->Internal.s.pPciBusRC = MMHyperR3ToRC(pVM, pDevIns->Internal.s.pPciBusR3);
    1659         else
    1660             pDevIns->Internal.s.pPciBusRC = NIL_RTRCPTR;
    1661 
    1662         /*
    1663          * Check the configuration for PCI device and function assignment.
    1664          */
    1665         int iDev = -1;
    1666         uint8_t     u8Device;
    1667         rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIDeviceNo", &u8Device);
    1668         if (VBOX_SUCCESS(rc))
    1669         {
    1670             if (u8Device > 31)
    1671             {
    1672                 AssertMsgFailed(("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d)\n",
    1673                                  u8Device, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1674                 return VERR_INTERNAL_ERROR;
    1675             }
    1676 
    1677             uint8_t     u8Function;
    1678             rc = CFGMR3QueryU8(pDevIns->Internal.s.pCfgHandle, "PCIFunctionNo", &u8Function);
    1679             if (VBOX_FAILURE(rc))
    1680             {
    1681                 AssertMsgFailed(("Configuration error: PCIDeviceNo, but PCIFunctionNo query failed with rc=%Vrc (%s/%d)\n",
    1682                                  rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1683                 return rc;
    1684             }
    1685             if (u8Function > 7)
    1686             {
    1687                 AssertMsgFailed(("Configuration error: PCIFunctionNo=%d, max is 7. (%s/%d)\n",
    1688                                  u8Function, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1689                 return VERR_INTERNAL_ERROR;
    1690             }
    1691             iDev = (u8Device << 3) | u8Function;
    1692         }
    1693         else if (rc != VERR_CFGM_VALUE_NOT_FOUND)
    1694         {
    1695             AssertMsgFailed(("Configuration error: PCIDeviceNo query failed with rc=%Vrc (%s/%d)\n",
    1696                              rc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1697             return rc;
    1698         }
    1699 
    1700         /*
    1701          * Call the pci bus device to do the actual registration.
    1702          */
    1703         pdmLock(pVM);
    1704         rc = pBus->pfnRegisterR3(pBus->pDevInsR3, pPciDev, pDevIns->pDevReg->szDeviceName, iDev);
    1705         pdmUnlock(pVM);
    1706         if (VBOX_SUCCESS(rc))
    1707         {
    1708             pPciDev->pDevIns = pDevIns;
    1709 
    1710             pDevIns->Internal.s.pPciDeviceR3 = pPciDev;
    1711             if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0)
    1712                 pDevIns->Internal.s.pPciDeviceR0 = MMHyperR3ToR0(pVM, pPciDev);
    1713             else
    1714                 pDevIns->Internal.s.pPciDeviceR0 = NIL_RTR0PTR;
    1715 
    1716             if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC)
    1717                 pDevIns->Internal.s.pPciDeviceRC = MMHyperR3ToRC(pVM, pPciDev);
    1718             else
    1719                 pDevIns->Internal.s.pPciDeviceRC = NIL_RTRCPTR;
    1720 
    1721             Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
    1722                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev->devfn, pDevIns->Internal.s.pPciBusR3->iBus));
    1723         }
    1724     }
    1725     else
    1726     {
    1727         AssertMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
    1728         rc = VERR_PDM_NO_PCI_BUS;
    1729     }
    1730 
    1731     LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1732     return rc;
    1733 }
    1734 
    1735 
    1736 /** @copydoc PDMDEVHLPR3::pfnPCIIORegionRegister */
    1737 static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
    1738 {
    1739     PDMDEV_ASSERT_DEVINS(pDevIns);
    1740     PVM pVM = pDevIns->Internal.s.pVMR3;
    1741     VM_ASSERT_EMT(pVM);
    1742     LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: iRegion=%d cbRegion=%#x enmType=%d pfnCallback=%p\n",
    1743              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cbRegion, enmType, pfnCallback));
    1744 
    1745     /*
    1746      * Validate input.
    1747      */
    1748     if (iRegion < 0 || iRegion >= PCI_NUM_REGIONS)
    1749     {
    1750         Assert(iRegion >= 0 && iRegion < PCI_NUM_REGIONS);
    1751         LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (iRegion)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1752         return VERR_INVALID_PARAMETER;
    1753     }
    1754     switch (enmType)
    1755     {
    1756         case PCI_ADDRESS_SPACE_MEM:
    1757         case PCI_ADDRESS_SPACE_IO:
    1758         case PCI_ADDRESS_SPACE_MEM_PREFETCH:
    1759             break;
    1760         default:
    1761             AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
    1762             LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (enmType)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1763             return VERR_INVALID_PARAMETER;
    1764     }
    1765     if (!pfnCallback)
    1766     {
    1767         Assert(pfnCallback);
    1768         LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc (callback)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    1769         return VERR_INVALID_PARAMETER;
    1770     }
    1771     AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
    1772 
    1773     /*
    1774      * Must have a PCI device registered!
    1775      */
    1776     int rc;
    1777     PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1778     if (pPciDev)
    1779     {
    1780         /*
    1781          * We're currently restricted to page aligned MMIO regions.
    1782          */
    1783         if (    (enmType == PCI_ADDRESS_SPACE_MEM || enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH)
    1784             &&  cbRegion != RT_ALIGN_32(cbRegion, PAGE_SIZE))
    1785         {
    1786             Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %#x -> %#x\n",
    1787                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbRegion, RT_ALIGN_32(cbRegion, PAGE_SIZE)));
    1788             cbRegion = RT_ALIGN_32(cbRegion, PAGE_SIZE);
    1789         }
    1790 
    1791         PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1792         Assert(pBus);
    1793         pdmLock(pVM);
    1794         rc = pBus->pfnIORegionRegisterR3(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, pfnCallback);
    1795         pdmUnlock(pVM);
    1796     }
    1797     else
    1798     {
    1799         AssertMsgFailed(("No PCI device registered!\n"));
    1800         rc = VERR_PDM_NOT_PCI_DEVICE;
    1801     }
    1802 
    1803     LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    1804     return rc;
    1805 }
    1806 
    1807 
    1808 /** @copydoc PDMDEVHLPR3::pfnPCISetConfigCallbacks */
    1809 static DECLCALLBACK(void) pdmR3DevHlp_PCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
    1810                                                             PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
    1811 {
    1812     PDMDEV_ASSERT_DEVINS(pDevIns);
    1813     PVM pVM = pDevIns->Internal.s.pVMR3;
    1814     VM_ASSERT_EMT(pVM);
    1815     LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: pPciDev=%p pfnRead=%p ppfnReadOld=%p pfnWrite=%p ppfnWriteOld=%p\n",
    1816              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld));
    1817 
    1818     /*
    1819      * Validate input and resolve defaults.
    1820      */
    1821     AssertPtr(pfnRead);
    1822     AssertPtr(pfnWrite);
    1823     AssertPtrNull(ppfnReadOld);
    1824     AssertPtrNull(ppfnWriteOld);
    1825     AssertPtrNull(pPciDev);
    1826 
    1827     if (!pPciDev)
    1828         pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1829     AssertReleaseMsg(pPciDev, ("You must register your device first!\n"));
    1830     PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3;
    1831     AssertRelease(pBus);
    1832     AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
    1833 
    1834     /*
    1835      * Do the job.
    1836      */
    1837     pdmLock(pVM);
    1838     pBus->pfnSetConfigCallbacksR3(pBus->pDevInsR3, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
    1839     pdmUnlock(pVM);
    1840 
    1841     LogFlow(("pdmR3DevHlp_PCISetConfigCallbacks: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1842 }
    1843 
    1844 
    1845 /** @copydoc PDMDEVHLPR3::pfnPCISetIrq */
    1846 static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1847 {
    1848     PDMDEV_ASSERT_DEVINS(pDevIns);
    1849     LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
    1850 
    1851     /*
    1852      * Validate input.
    1853      */
    1854     /** @todo iIrq and iLevel checks. */
    1855 
    1856     /*
    1857      * Must have a PCI device registered!
    1858      */
    1859     PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR3;
    1860     if (pPciDev)
    1861     {
    1862         PPDMPCIBUS pBus = pDevIns->Internal.s.pPciBusR3; /** @todo the bus should be associated with the PCI device not the PDM device. */
    1863         Assert(pBus);
    1864         PVM pVM = pDevIns->Internal.s.pVMR3;
    1865         pdmLock(pVM);
    1866         pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel);
    1867         pdmUnlock(pVM);
    1868     }
    1869     else
    1870         AssertReleaseMsgFailed(("No PCI device registered!\n"));
    1871 
    1872     LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1873 }
    1874 
    1875 
    1876 /** @copydoc PDMDEVHLPR3::pfnPCISetIrqNoWait */
    1877 static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1878 {
    1879     pdmR3DevHlp_PCISetIrq(pDevIns, iIrq, iLevel);
    1880 }
    1881 
    1882 
    1883 /** @copydoc PDMDEVHLPR3::pfnISASetIrq */
    1884 static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1885 {
    1886     PDMDEV_ASSERT_DEVINS(pDevIns);
    1887     LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iIrq, iLevel));
    1888 
    1889     /*
    1890      * Validate input.
    1891      */
    1892     /** @todo iIrq and iLevel checks. */
    1893 
    1894     PVM pVM = pDevIns->Internal.s.pVMR3;
    1895     PDMIsaSetIrq(pVM, iIrq, iLevel);    /* (The API takes the lock.) */
    1896 
    1897     LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1898 }
    1899 
    1900 
    1901 /** @copydoc PDMDEVHLPR3::pfnISASetIrqNoWait */
    1902 static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    1903 {
    1904     pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
    1905 }
    1906 
    1907 
    1908 /** @copydoc PDMDEVHLPR3::pfnDriverAttach */
    1909 static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
    1910 {
    1911     PDMDEV_ASSERT_DEVINS(pDevIns);
    1912     PVM pVM = pDevIns->Internal.s.pVMR3;
    1913     VM_ASSERT_EMT(pVM);
    1914     LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
    1915              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
    1916 
    1917     /*
    1918      * Lookup the LUN, it might already be registered.
    1919      */
    1920     PPDMLUN pLunPrev = NULL;
    1921     PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
    1922     for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
    1923         if (pLun->iLun == iLun)
    1924             break;
    1925 
    1926     /*
    1927      * Create the LUN if if wasn't found, else check if driver is already attached to it.
    1928      */
    1929     if (!pLun)
    1930     {
    1931         if (    !pBaseInterface
    1932             ||  !pszDesc
    1933             ||  !*pszDesc)
    1934         {
    1935             Assert(pBaseInterface);
    1936             Assert(pszDesc || *pszDesc);
    1937             return VERR_INVALID_PARAMETER;
    1938         }
    1939 
    1940         pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
    1941         if (!pLun)
    1942             return VERR_NO_MEMORY;
    1943 
    1944         pLun->iLun      = iLun;
    1945         pLun->pNext     = pLunPrev ? pLunPrev->pNext : NULL;
    1946         pLun->pTop      = NULL;
    1947         pLun->pBottom   = NULL;
    1948         pLun->pDevIns   = pDevIns;
    1949         pLun->pszDesc   = pszDesc;
    1950         pLun->pBase     = pBaseInterface;
    1951         if (!pLunPrev)
    1952             pDevIns->Internal.s.pLunsR3 = pLun;
    1953         else
    1954             pLunPrev->pNext = pLun;
    1955         Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
    1956              iLun, pszDesc, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1957     }
    1958     else if (pLun->pTop)
    1959     {
    1960         AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
    1961         LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
    1962         return VERR_PDM_DRIVER_ALREADY_ATTACHED;
    1963     }
    1964     Assert(pLun->pBase == pBaseInterface);
    1965 
    1966 
    1967     /*
    1968      * Get the attached driver configuration.
    1969      */
    1970     int rc;
    1971     char szNode[48];
    1972     RTStrPrintf(szNode, sizeof(szNode), "LUN#%d", iLun);
    1973     PCFGMNODE   pNode = CFGMR3GetChild(pDevIns->Internal.s.pCfgHandle, szNode);
    1974     if (pNode)
    1975     {
    1976         char *pszName;
    1977         rc = CFGMR3QueryStringAlloc(pNode, "Driver", &pszName);
    1978         if (VBOX_SUCCESS(rc))
    1979         {
    1980             /*
    1981              * Find the driver.
    1982              */
    1983             PPDMDRV pDrv = pdmR3DrvLookup(pVM, pszName);
    1984             if (pDrv)
    1985             {
    1986                 /* config node */
    1987                 PCFGMNODE pConfigNode = CFGMR3GetChild(pNode, "Config");
    1988                 if (!pConfigNode)
    1989                     rc = CFGMR3InsertNode(pNode, "Config", &pConfigNode);
    1990                 if (VBOX_SUCCESS(rc))
    1991                 {
    1992                     CFGMR3SetRestrictedRoot(pConfigNode);
    1993 
    1994                     /*
    1995                      * Allocate the driver instance.
    1996                      */
    1997                     size_t cb = RT_OFFSETOF(PDMDRVINS, achInstanceData[pDrv->pDrvReg->cbInstance]);
    1998                     cb = RT_ALIGN_Z(cb, 16);
    1999                     PPDMDRVINS pNew = (PPDMDRVINS)MMR3HeapAllocZ(pVM, MM_TAG_PDM_DRIVER, cb);
    2000                     if (pNew)
    2001                     {
    2002                         /*
    2003                          * Initialize the instance structure (declaration order).
    2004                          */
    2005                         pNew->u32Version                = PDM_DRVINS_VERSION;
    2006                         //pNew->Internal.s.pUp            = NULL;
    2007                         //pNew->Internal.s.pDown          = NULL;
    2008                         pNew->Internal.s.pLun           = pLun;
    2009                         pNew->Internal.s.pDrv           = pDrv;
    2010                         pNew->Internal.s.pVM            = pVM;
    2011                         //pNew->Internal.s.fDetaching     = false;
    2012                         pNew->Internal.s.pCfgHandle     = pNode;
    2013                         pNew->pDrvHlp                   = &g_pdmR3DrvHlp;
    2014                         pNew->pDrvReg                   = pDrv->pDrvReg;
    2015                         pNew->pCfgHandle                = pConfigNode;
    2016                         pNew->iInstance                 = pDrv->cInstances++;
    2017                         pNew->pUpBase                   = pBaseInterface;
    2018                         //pNew->pDownBase                 = NULL;
    2019                         //pNew->IBase.pfnQueryInterface   = NULL;
    2020                         pNew->pvInstanceData            = &pNew->achInstanceData[0];
    2021 
    2022                         /*
    2023                          * Link with LUN and call the constructor.
    2024                          */
    2025                         pLun->pTop = pLun->pBottom = pNew;
    2026                         rc = pDrv->pDrvReg->pfnConstruct(pNew, pNew->pCfgHandle);
    2027                         if (VBOX_SUCCESS(rc))
    2028                         {
    2029                             MMR3HeapFree(pszName);
    2030                             *ppBaseInterface = &pNew->IBase;
    2031                             Log(("PDM: Attached driver '%s'/%d to LUN#%d on device '%s'/%d.\n",
    2032                                  pDrv->pDrvReg->szDriverName, pNew->iInstance, iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2033                             LogFlow(("pdmR3DevHlp_DriverAttach: caller '%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2034                             /*
    2035                              * Might return != VINF_SUCCESS (e.g. VINF_NAT_DNS) */
    2036                             return rc;
    2037                         }
    2038 
    2039                         /*
    2040                          * Free the driver.
    2041                          */
    2042                         pLun->pTop = pLun->pBottom = NULL;
    2043                         ASMMemFill32(pNew, cb, 0xdeadd0d0);
    2044                         MMR3HeapFree(pNew);
    2045                         pDrv->cInstances--;
    2046                     }
    2047                     else
    2048                     {
    2049                         AssertMsgFailed(("Failed to allocate %d bytes for instantiating driver '%s'\n", cb, pszName));
    2050                         rc = VERR_NO_MEMORY;
    2051                     }
    2052                 }
    2053                 else
    2054                     AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
    2055             }
    2056             else
    2057             {
    2058                 AssertMsgFailed(("Driver '%s' wasn't found!\n", pszName));
    2059                 rc = VERR_PDM_DRIVER_NOT_FOUND;
    2060             }
    2061             MMR3HeapFree(pszName);
    2062         }
    2063         else
    2064         {
    2065             AssertMsgFailed(("Query for string value of \"Driver\" -> %Vrc\n", rc));
    2066             if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    2067                 rc = VERR_PDM_CFG_MISSING_DRIVER_NAME;
    2068         }
    2069     }
    2070     else
    2071         rc = VERR_PDM_NO_ATTACHED_DRIVER;
    2072 
    2073 
    2074     LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2075     return rc;
    2076 }
    2077 
    2078 
    2079 /** @copydoc PDMDEVHLPR3::pfnMMHeapAlloc */
    2080 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
    2081 {
    2082     PDMDEV_ASSERT_DEVINS(pDevIns);
    2083     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
    2084 
    2085     void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
    2086 
    2087     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2088     return pv;
    2089 }
    2090 
    2091 
    2092 /** @copydoc PDMDEVHLPR3::pfnMMHeapAllocZ */
    2093 static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
    2094 {
    2095     PDMDEV_ASSERT_DEVINS(pDevIns);
    2096     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
    2097 
    2098     void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
    2099 
    2100     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2101     return pv;
    2102 }
    2103 
    2104 
    2105 /** @copydoc PDMDEVHLPR3::pfnMMHeapFree */
    2106 static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
    2107 {
    2108     PDMDEV_ASSERT_DEVINS(pDevIns);
    2109     LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
    2110 
    2111     MMR3HeapFree(pv);
    2112 
    2113     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    2114 }
    2115 
    2116 
    2117 /** @copydoc PDMDEVHLPR3::pfnVMSetError */
    2118 static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
    2119 {
    2120     PDMDEV_ASSERT_DEVINS(pDevIns);
    2121     va_list args;
    2122     va_start(args, pszFormat);
    2123     int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
    2124     va_end(args);
    2125     return rc;
    2126 }
    2127 
    2128 
    2129 /** @copydoc PDMDEVHLPR3::pfnVMSetErrorV */
    2130 static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
    2131 {
    2132     PDMDEV_ASSERT_DEVINS(pDevIns);
    2133     int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
    2134     return rc;
    2135 }
    2136 
    2137 
    2138 /** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeError */
    2139 static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, ...)
    2140 {
    2141     PDMDEV_ASSERT_DEVINS(pDevIns);
    2142     va_list args;
    2143     va_start(args, pszFormat);
    2144     int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, args);
    2145     va_end(args);
    2146     return rc;
    2147 }
    2148 
    2149 
    2150 /** @copydoc PDMDEVHLPR3::pfnVMSetRuntimeErrorV */
    2151 static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list va)
    2152 {
    2153     PDMDEV_ASSERT_DEVINS(pDevIns);
    2154     int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFatal, pszErrorID, pszFormat, va);
    2155     return rc;
    2156 }
    2157 
    2158 
    2159 /** @copydoc PDMDEVHLPR3::pfnAssertEMT */
    2160 static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    2161 {
    2162     PDMDEV_ASSERT_DEVINS(pDevIns);
    2163     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
    2164         return true;
    2165 
    2166     char szMsg[100];
    2167     RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
    2168     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    2169     AssertBreakpoint();
    2170     return false;
    2171 }
    2172 
    2173 
    2174 /** @copydoc PDMDEVHLPR3::pfnAssertOther */
    2175 static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    2176 {
    2177     PDMDEV_ASSERT_DEVINS(pDevIns);
    2178     if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
    2179         return true;
    2180 
    2181     char szMsg[100];
    2182     RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
    2183     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    2184     AssertBreakpoint();
    2185     return false;
    2186 }
    2187 
    2188 
    2189 /** @copydoc PDMDEVHLPR3::pfnDBGFStopV */
    2190 static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
    2191 {
    2192     PDMDEV_ASSERT_DEVINS(pDevIns);
    2193 #ifdef LOG_ENABLED
    2194     va_list va2;
    2195     va_copy(va2, args);
    2196     LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
    2197              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
    2198     va_end(va2);
    2199 #endif
    2200 
    2201     PVM pVM = pDevIns->Internal.s.pVMR3;
    2202     VM_ASSERT_EMT(pVM);
    2203     int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
    2204 
    2205     LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2206     return rc;
    2207 }
    2208 
    2209 
    2210 /** @copydoc PDMDEVHLPR3::pfnDBGFInfoRegister */
    2211 static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
    2212 {
    2213     PDMDEV_ASSERT_DEVINS(pDevIns);
    2214     LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
    2215              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
    2216 
    2217     PVM pVM = pDevIns->Internal.s.pVMR3;
    2218     VM_ASSERT_EMT(pVM);
    2219     int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
    2220 
    2221     LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2222     return rc;
    2223 }
    2224 
    2225 
    2226 /** @copydoc PDMDEVHLPR3::pfnSTAMRegister */
    2227 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
    2228 {
    2229     PDMDEV_ASSERT_DEVINS(pDevIns);
    2230     PVM pVM = pDevIns->Internal.s.pVMR3;
    2231     VM_ASSERT_EMT(pVM);
    2232 
    2233     STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
    2234     NOREF(pVM);
    2235 }
    2236 
    2237 
    2238 
    2239 /** @copydoc PDMDEVHLPR3::pfnSTAMRegisterF */
    2240 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    2241                                                     STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
    2242 {
    2243     PDMDEV_ASSERT_DEVINS(pDevIns);
    2244     PVM pVM = pDevIns->Internal.s.pVMR3;
    2245     VM_ASSERT_EMT(pVM);
    2246 
    2247     va_list args;
    2248     va_start(args, pszName);
    2249     int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    2250     va_end(args);
    2251     AssertRC(rc);
    2252 
    2253     NOREF(pVM);
    2254 }
    2255 
    2256 
    2257 /** @copydoc PDMDEVHLPR3::pfnSTAMRegisterV */
    2258 static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    2259                                                     STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
    2260 {
    2261     PDMDEV_ASSERT_DEVINS(pDevIns);
    2262     PVM pVM = pDevIns->Internal.s.pVMR3;
    2263     VM_ASSERT_EMT(pVM);
    2264 
    2265     int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    2266     AssertRC(rc);
    2267 
    2268     NOREF(pVM);
    2269 }
    2270 
    2271 
    2272 /** @copydoc PDMDEVHLPR3::pfnRTCRegister */
    2273 static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
    2274 {
    2275     PDMDEV_ASSERT_DEVINS(pDevIns);
    2276     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2277     LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
    2278              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
    2279              pRtcReg->pfnWrite, ppRtcHlp));
    2280 
    2281     /*
    2282      * Validate input.
    2283      */
    2284     if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
    2285     {
    2286         AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
    2287                          PDM_RTCREG_VERSION));
    2288         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (version)\n",
    2289                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2290         return VERR_INVALID_PARAMETER;
    2291     }
    2292     if (    !pRtcReg->pfnWrite
    2293         ||  !pRtcReg->pfnRead)
    2294     {
    2295         Assert(pRtcReg->pfnWrite);
    2296         Assert(pRtcReg->pfnRead);
    2297         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
    2298                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2299         return VERR_INVALID_PARAMETER;
    2300     }
    2301 
    2302     if (!ppRtcHlp)
    2303     {
    2304         Assert(ppRtcHlp);
    2305         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (ppRtcHlp)\n",
    2306                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2307         return VERR_INVALID_PARAMETER;
    2308     }
    2309 
    2310     /*
    2311      * Only one DMA device.
    2312      */
    2313     PVM pVM = pDevIns->Internal.s.pVMR3;
    2314     if (pVM->pdm.s.pRtc)
    2315     {
    2316         AssertMsgFailed(("Only one RTC device is supported!\n"));
    2317         LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
    2318                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2319         return VERR_INVALID_PARAMETER;
    2320     }
    2321 
    2322     /*
    2323      * Allocate and initialize pci bus structure.
    2324      */
    2325     int rc = VINF_SUCCESS;
    2326     PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
    2327     if (pRtc)
    2328     {
    2329         pRtc->pDevIns   = pDevIns;
    2330         pRtc->Reg       = *pRtcReg;
    2331         pVM->pdm.s.pRtc = pRtc;
    2332 
    2333         /* set the helper pointer. */
    2334         *ppRtcHlp = &g_pdmR3DevRtcHlp;
    2335         Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
    2336              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2337     }
    2338     else
    2339         rc = VERR_NO_MEMORY;
    2340 
    2341     LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
    2342              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2343     return rc;
    2344 }
    2345 
    2346 
    2347 /** @copydoc PDMDEVHLPR3::pfnPDMQueueCreate */
    2348 static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
    2349                                                     PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue)
    2350 {
    2351     PDMDEV_ASSERT_DEVINS(pDevIns);
    2352     LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool ppQueue=%p\n",
    2353              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue));
    2354 
    2355     PVM pVM = pDevIns->Internal.s.pVMR3;
    2356     VM_ASSERT_EMT(pVM);
    2357     int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue);
    2358 
    2359     LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppQueue));
    2360     return rc;
    2361 }
    2362 
    2363 
    2364 /** @copydoc PDMDEVHLPR3::pfnCritSectInit */
    2365 static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName)
    2366 {
    2367     PDMDEV_ASSERT_DEVINS(pDevIns);
    2368     LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%p:{%s}\n",
    2369              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pCritSect, pszName, pszName));
    2370 
    2371     PVM pVM = pDevIns->Internal.s.pVMR3;
    2372     VM_ASSERT_EMT(pVM);
    2373     int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, pszName);
    2374 
    2375     LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2376     return rc;
    2377 }
    2378 
    2379 
    2380 /** @copydoc PDMDEVHLPR3::pfnUTCNow */
    2381 static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_UTCNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
    2382 {
    2383     PDMDEV_ASSERT_DEVINS(pDevIns);
    2384     LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: pTime=%p\n",
    2385              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pTime));
    2386 
    2387     pTime = TMR3UTCNow(pDevIns->Internal.s.pVMR3, pTime);
    2388 
    2389     LogFlow(("pdmR3DevHlp_UTCNow: caller='%s'/%d: returns %RU64\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
    2390     return pTime;
    2391 }
    2392 
    2393 
    2394 /** @copydoc PDMDEVHLPR3::pfnPDMThreadCreate */
    2395 static DECLCALLBACK(int) pdmR3DevHlp_PDMThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
    2396                                                      PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
    2397 {
    2398     PDMDEV_ASSERT_DEVINS(pDevIns);
    2399     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2400     LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
    2401              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
    2402 
    2403     int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
    2404 
    2405     LogFlow(("pdmR3DevHlp_PDMThreadCreate: caller='%s'/%d: returns %Vrc *ppThread=%RTthrd\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    2406             rc, *ppThread));
    2407     return rc;
    2408 }
    2409 
    2410 
    2411 /** @copydoc PDMDEVHLPR3::pfnGetVM */
    2412 static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
    2413 {
    2414     PDMDEV_ASSERT_DEVINS(pDevIns);
    2415     LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
    2416     return pDevIns->Internal.s.pVMR3;
    2417 }
    2418 
    2419 
    2420 /** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
    2421 static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
    2422 {
    2423     PDMDEV_ASSERT_DEVINS(pDevIns);
    2424     PVM pVM = pDevIns->Internal.s.pVMR3;
    2425     VM_ASSERT_EMT(pVM);
    2426     LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, .pfnSetIrqR3=%p, "
    2427              ".pfnSaveExecR3=%p, .pfnLoadExecR3=%p, .pfnFakePCIBIOSR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppPciHlpR3=%p\n",
    2428              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
    2429              pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnSetIrqR3, pPciBusReg->pfnSaveExecR3, pPciBusReg->pfnLoadExecR3,
    2430              pPciBusReg->pfnFakePCIBIOSR3, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqRC, pPciBusReg->pszSetIrqR0, pPciBusReg->pszSetIrqR0, ppPciHlpR3));
    2431 
    2432     /*
    2433      * Validate the structure.
    2434      */
    2435     if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
    2436     {
    2437         AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
    2438         LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2439         return VERR_INVALID_PARAMETER;
    2440     }
    2441     if (    !pPciBusReg->pfnRegisterR3
    2442         ||  !pPciBusReg->pfnIORegionRegisterR3
    2443         ||  !pPciBusReg->pfnSetIrqR3
    2444         ||  !pPciBusReg->pfnSaveExecR3
    2445         ||  !pPciBusReg->pfnLoadExecR3
    2446         ||  !pPciBusReg->pfnFakePCIBIOSR3)
    2447     {
    2448         Assert(pPciBusReg->pfnRegisterR3);
    2449         Assert(pPciBusReg->pfnIORegionRegisterR3);
    2450         Assert(pPciBusReg->pfnSetIrqR3);
    2451         Assert(pPciBusReg->pfnSaveExecR3);
    2452         Assert(pPciBusReg->pfnLoadExecR3);
    2453         Assert(pPciBusReg->pfnFakePCIBIOSR3);
    2454         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2455         return VERR_INVALID_PARAMETER;
    2456     }
    2457     if (    pPciBusReg->pszSetIrqRC
    2458         &&  !VALID_PTR(pPciBusReg->pszSetIrqRC))
    2459     {
    2460         Assert(VALID_PTR(pPciBusReg->pszSetIrqRC));
    2461         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2462         return VERR_INVALID_PARAMETER;
    2463     }
    2464     if (    pPciBusReg->pszSetIrqR0
    2465         &&  !VALID_PTR(pPciBusReg->pszSetIrqR0))
    2466     {
    2467         Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
    2468         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2469         return VERR_INVALID_PARAMETER;
    2470     }
    2471      if (!ppPciHlpR3)
    2472     {
    2473         Assert(ppPciHlpR3);
    2474         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (ppPciHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2475         return VERR_INVALID_PARAMETER;
    2476     }
    2477 
    2478     /*
    2479      * Find free PCI bus entry.
    2480      */
    2481     unsigned iBus = 0;
    2482     for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
    2483         if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
    2484             break;
    2485     if (iBus >= RT_ELEMENTS(pVM->pdm.s.aPciBuses))
    2486     {
    2487         AssertMsgFailed(("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)));
    2488         LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (pci bus)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2489         return VERR_INVALID_PARAMETER;
    2490     }
    2491     PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
    2492 
    2493     /*
    2494      * Resolve and init the RC bits.
    2495      */
    2496     if (pPciBusReg->pszSetIrqRC)
    2497     {
    2498         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, &pPciBus->pfnSetIrqRC);
    2499         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPciBusReg->pszSetIrqRC, rc));
    2500         if (VBOX_FAILURE(rc))
    2501         {
    2502             LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2503             return rc;
    2504         }
    2505         pPciBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2506     }
    2507     else
    2508     {
    2509         pPciBus->pfnSetIrqRC = 0;
    2510         pPciBus->pDevInsRC   = 0;
    2511     }
    2512 
    2513     /*
    2514      * Resolve and init the R0 bits.
    2515      */
    2516     if (pPciBusReg->pszSetIrqR0)
    2517     {
    2518         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, &pPciBus->pfnSetIrqR0);
    2519         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, rc));
    2520         if (VBOX_FAILURE(rc))
    2521         {
    2522             LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2523             return rc;
    2524         }
    2525         pPciBus->pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2526     }
    2527     else
    2528     {
    2529         pPciBus->pfnSetIrqR0 = 0;
    2530         pPciBus->pDevInsR0   = 0;
    2531     }
    2532 
    2533     /*
    2534      * Init the R3 bits.
    2535      */
    2536     pPciBus->iBus                    = iBus;
    2537     pPciBus->pDevInsR3               = pDevIns;
    2538     pPciBus->pfnRegisterR3           = pPciBusReg->pfnRegisterR3;
    2539     pPciBus->pfnIORegionRegisterR3   = pPciBusReg->pfnIORegionRegisterR3;
    2540     pPciBus->pfnSetConfigCallbacksR3 = pPciBusReg->pfnSetConfigCallbacksR3;
    2541     pPciBus->pfnSetIrqR3             = pPciBusReg->pfnSetIrqR3;
    2542     pPciBus->pfnSaveExecR3           = pPciBusReg->pfnSaveExecR3;
    2543     pPciBus->pfnLoadExecR3           = pPciBusReg->pfnLoadExecR3;
    2544     pPciBus->pfnFakePCIBIOSR3        = pPciBusReg->pfnFakePCIBIOSR3;
    2545 
    2546     Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2547 
    2548     /* set the helper pointer and return. */
    2549     *ppPciHlpR3 = &g_pdmR3DevPciHlp;
    2550     LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2551     return VINF_SUCCESS;
    2552 }
    2553 
    2554 
    2555 /** @copydoc PDMDEVHLPR3::pfnPICRegister */
    2556 static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
    2557 {
    2558     PDMDEV_ASSERT_DEVINS(pDevIns);
    2559     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2560     LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pfnGetInterruptR3=%p, .pszGetIrqRC=%p:{%s}, .pszGetInterruptRC=%p:{%s}, .pszGetIrqR0=%p:{%s}, .pszGetInterruptR0=%p:{%s} } ppPicHlpR3=%p\n",
    2561              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
    2562              pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
    2563              pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
    2564              ppPicHlpR3));
    2565 
    2566     /*
    2567      * Validate input.
    2568      */
    2569     if (pPicReg->u32Version != PDM_PICREG_VERSION)
    2570     {
    2571         AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
    2572         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2573         return VERR_INVALID_PARAMETER;
    2574     }
    2575     if (    !pPicReg->pfnSetIrqR3
    2576         ||  !pPicReg->pfnGetInterruptR3)
    2577     {
    2578         Assert(pPicReg->pfnSetIrqR3);
    2579         Assert(pPicReg->pfnGetInterruptR3);
    2580         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2581         return VERR_INVALID_PARAMETER;
    2582     }
    2583     if (    (   pPicReg->pszSetIrqRC
    2584              || pPicReg->pszGetInterruptRC)
    2585         &&  (   !VALID_PTR(pPicReg->pszSetIrqRC)
    2586              || !VALID_PTR(pPicReg->pszGetInterruptRC))
    2587        )
    2588     {
    2589         Assert(VALID_PTR(pPicReg->pszSetIrqRC));
    2590         Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
    2591         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2592         return VERR_INVALID_PARAMETER;
    2593     }
    2594     if (    pPicReg->pszSetIrqRC
    2595         &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC))
    2596     {
    2597         Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_RC);
    2598         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (RC flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2599         return VERR_INVALID_PARAMETER;
    2600     }
    2601     if (    pPicReg->pszSetIrqR0
    2602         &&  !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
    2603     {
    2604         Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0);
    2605         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R0 flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2606         return VERR_INVALID_PARAMETER;
    2607     }
    2608     if (!ppPicHlpR3)
    2609     {
    2610         Assert(ppPicHlpR3);
    2611         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (ppPicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2612         return VERR_INVALID_PARAMETER;
    2613     }
    2614 
    2615     /*
    2616      * Only one PIC device.
    2617      */
    2618     PVM pVM = pDevIns->Internal.s.pVMR3;
    2619     if (pVM->pdm.s.Pic.pDevInsR3)
    2620     {
    2621         AssertMsgFailed(("Only one pic device is supported!\n"));
    2622         LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2623         return VERR_INVALID_PARAMETER;
    2624     }
    2625 
    2626     /*
    2627      * RC stuff.
    2628      */
    2629     if (pPicReg->pszSetIrqRC)
    2630     {
    2631         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
    2632         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszSetIrqRC, rc));
    2633         if (VBOX_SUCCESS(rc))
    2634         {
    2635             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
    2636             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pPicReg->pszGetInterruptRC, rc));
    2637         }
    2638         if (VBOX_FAILURE(rc))
    2639         {
    2640             LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2641             return rc;
    2642         }
    2643         pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2644     }
    2645     else
    2646     {
    2647         pVM->pdm.s.Pic.pDevInsRC = 0;
    2648         pVM->pdm.s.Pic.pfnSetIrqRC = 0;
    2649         pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
    2650     }
    2651 
    2652     /*
    2653      * R0 stuff.
    2654      */
    2655     if (pPicReg->pszSetIrqR0)
    2656     {
    2657         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
    2658         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, rc));
    2659         if (VBOX_SUCCESS(rc))
    2660         {
    2661             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
    2662             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, rc));
    2663         }
    2664         if (VBOX_FAILURE(rc))
    2665         {
    2666             LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2667             return rc;
    2668         }
    2669         pVM->pdm.s.Pic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2670         Assert(pVM->pdm.s.Pic.pDevInsR0);
    2671     }
    2672     else
    2673     {
    2674         pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
    2675         pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
    2676         pVM->pdm.s.Pic.pDevInsR0 = 0;
    2677     }
    2678 
    2679     /*
    2680      * R3 stuff.
    2681      */
    2682     pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
    2683     pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
    2684     pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
    2685     Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2686 
    2687     /* set the helper pointer and return. */
    2688     *ppPicHlpR3 = &g_pdmR3DevPicHlp;
    2689     LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2690     return VINF_SUCCESS;
    2691 }
    2692 
    2693 
    2694 /** @copydoc PDMDEVHLPR3::pfnAPICRegister */
    2695 static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
    2696 {
    2697     PDMDEV_ASSERT_DEVINS(pDevIns);
    2698     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2699     LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptR3=%p, .pfnSetBaseR3=%p, .pfnGetBaseR3=%p, "
    2700              ".pfnSetTPRR3=%p, .pfnGetTPRR3=%p, .pfnBusDeliverR3=%p, pszGetInterruptRC=%p:{%s}, pszSetBaseRC=%p:{%s}, pszGetBaseRC=%p:{%s}, "
    2701              ".pszSetTPRRC=%p:{%s}, .pszGetTPRRC=%p:{%s}, .pszBusDeliverRC=%p:{%s}} ppApicHlpR3=%p\n",
    2702              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptR3, pApicReg->pfnSetBaseR3,
    2703              pApicReg->pfnGetBaseR3, pApicReg->pfnSetTPRR3, pApicReg->pfnGetTPRR3, pApicReg->pfnBusDeliverR3, pApicReg->pszGetInterruptRC,
    2704              pApicReg->pszGetInterruptRC, pApicReg->pszSetBaseRC, pApicReg->pszSetBaseRC, pApicReg->pszGetBaseRC, pApicReg->pszGetBaseRC,
    2705              pApicReg->pszSetTPRRC, pApicReg->pszSetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszGetTPRRC, pApicReg->pszBusDeliverRC,
    2706              pApicReg->pszBusDeliverRC, ppApicHlpR3));
    2707 
    2708     /*
    2709      * Validate input.
    2710      */
    2711     if (pApicReg->u32Version != PDM_APICREG_VERSION)
    2712     {
    2713         AssertMsgFailed(("u32Version=%#x expected %#x\n", pApicReg->u32Version, PDM_APICREG_VERSION));
    2714         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2715         return VERR_INVALID_PARAMETER;
    2716     }
    2717     if (    !pApicReg->pfnGetInterruptR3
    2718         ||  !pApicReg->pfnHasPendingIrqR3
    2719         ||  !pApicReg->pfnSetBaseR3
    2720         ||  !pApicReg->pfnGetBaseR3
    2721         ||  !pApicReg->pfnSetTPRR3
    2722         ||  !pApicReg->pfnGetTPRR3
    2723         ||  !pApicReg->pfnBusDeliverR3)
    2724     {
    2725         Assert(pApicReg->pfnGetInterruptR3);
    2726         Assert(pApicReg->pfnHasPendingIrqR3);
    2727         Assert(pApicReg->pfnSetBaseR3);
    2728         Assert(pApicReg->pfnGetBaseR3);
    2729         Assert(pApicReg->pfnSetTPRR3);
    2730         Assert(pApicReg->pfnGetTPRR3);
    2731         Assert(pApicReg->pfnBusDeliverR3);
    2732         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2733         return VERR_INVALID_PARAMETER;
    2734     }
    2735     if (   (    pApicReg->pszGetInterruptRC
    2736             ||  pApicReg->pszHasPendingIrqRC
    2737             ||  pApicReg->pszSetBaseRC
    2738             ||  pApicReg->pszGetBaseRC
    2739             ||  pApicReg->pszSetTPRRC
    2740             ||  pApicReg->pszGetTPRRC
    2741             ||  pApicReg->pszBusDeliverRC)
    2742         &&  (   !VALID_PTR(pApicReg->pszGetInterruptRC)
    2743             ||  !VALID_PTR(pApicReg->pszHasPendingIrqRC)
    2744             ||  !VALID_PTR(pApicReg->pszSetBaseRC)
    2745             ||  !VALID_PTR(pApicReg->pszGetBaseRC)
    2746             ||  !VALID_PTR(pApicReg->pszSetTPRRC)
    2747             ||  !VALID_PTR(pApicReg->pszGetTPRRC)
    2748             ||  !VALID_PTR(pApicReg->pszBusDeliverRC))
    2749        )
    2750     {
    2751         Assert(VALID_PTR(pApicReg->pszGetInterruptRC));
    2752         Assert(VALID_PTR(pApicReg->pszHasPendingIrqRC));
    2753         Assert(VALID_PTR(pApicReg->pszSetBaseRC));
    2754         Assert(VALID_PTR(pApicReg->pszGetBaseRC));
    2755         Assert(VALID_PTR(pApicReg->pszSetTPRRC));
    2756         Assert(VALID_PTR(pApicReg->pszGetTPRRC));
    2757         Assert(VALID_PTR(pApicReg->pszBusDeliverRC));
    2758         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (RC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2759         return VERR_INVALID_PARAMETER;
    2760     }
    2761     if (   (    pApicReg->pszGetInterruptR0
    2762             ||  pApicReg->pszHasPendingIrqR0
    2763             ||  pApicReg->pszSetBaseR0
    2764             ||  pApicReg->pszGetBaseR0
    2765             ||  pApicReg->pszSetTPRR0
    2766             ||  pApicReg->pszGetTPRR0
    2767             ||  pApicReg->pszBusDeliverR0)
    2768         &&  (   !VALID_PTR(pApicReg->pszGetInterruptR0)
    2769             ||  !VALID_PTR(pApicReg->pszHasPendingIrqR0)
    2770             ||  !VALID_PTR(pApicReg->pszSetBaseR0)
    2771             ||  !VALID_PTR(pApicReg->pszGetBaseR0)
    2772             ||  !VALID_PTR(pApicReg->pszSetTPRR0)
    2773             ||  !VALID_PTR(pApicReg->pszGetTPRR0)
    2774             ||  !VALID_PTR(pApicReg->pszBusDeliverR0))
    2775        )
    2776     {
    2777         Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
    2778         Assert(VALID_PTR(pApicReg->pszHasPendingIrqR0));
    2779         Assert(VALID_PTR(pApicReg->pszSetBaseR0));
    2780         Assert(VALID_PTR(pApicReg->pszGetBaseR0));
    2781         Assert(VALID_PTR(pApicReg->pszSetTPRR0));
    2782         Assert(VALID_PTR(pApicReg->pszGetTPRR0));
    2783         Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
    2784         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2785         return VERR_INVALID_PARAMETER;
    2786     }
    2787     if (!ppApicHlpR3)
    2788     {
    2789         Assert(ppApicHlpR3);
    2790         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2791         return VERR_INVALID_PARAMETER;
    2792     }
    2793 
    2794     /*
    2795      * Only one APIC device. (malc: only in UP case actually)
    2796      */
    2797     PVM pVM = pDevIns->Internal.s.pVMR3;
    2798     if (pVM->pdm.s.Apic.pDevInsR3)
    2799     {
    2800         AssertMsgFailed(("Only one apic device is supported!\n"));
    2801         LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2802         return VERR_INVALID_PARAMETER;
    2803     }
    2804 
    2805     /*
    2806      * Resolve & initialize the RC bits.
    2807      */
    2808     if (pApicReg->pszGetInterruptRC)
    2809     {
    2810         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, &pVM->pdm.s.Apic.pfnGetInterruptRC);
    2811         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetInterruptRC, rc));
    2812         if (RT_SUCCESS(rc))
    2813         {
    2814             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, &pVM->pdm.s.Apic.pfnHasPendingIrqRC);
    2815             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszHasPendingIrqRC, rc));
    2816         }
    2817         if (RT_SUCCESS(rc))
    2818         {
    2819             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, &pVM->pdm.s.Apic.pfnSetBaseRC);
    2820             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetBaseRC, rc));
    2821         }
    2822         if (RT_SUCCESS(rc))
    2823         {
    2824             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, &pVM->pdm.s.Apic.pfnGetBaseRC);
    2825             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetBaseRC, rc));
    2826         }
    2827         if (RT_SUCCESS(rc))
    2828         {
    2829             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, &pVM->pdm.s.Apic.pfnSetTPRRC);
    2830             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszSetTPRRC, rc));
    2831         }
    2832         if (RT_SUCCESS(rc))
    2833         {
    2834             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, &pVM->pdm.s.Apic.pfnGetTPRRC);
    2835             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszGetTPRRC, rc));
    2836         }
    2837         if (RT_SUCCESS(rc))
    2838         {
    2839             rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, &pVM->pdm.s.Apic.pfnBusDeliverRC);
    2840             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pApicReg->pszBusDeliverRC, rc));
    2841         }
    2842         if (VBOX_FAILURE(rc))
    2843         {
    2844             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2845             return rc;
    2846         }
    2847         pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    2848     }
    2849     else
    2850     {
    2851         pVM->pdm.s.Apic.pDevInsRC           = 0;
    2852         pVM->pdm.s.Apic.pfnGetInterruptRC   = 0;
    2853         pVM->pdm.s.Apic.pfnHasPendingIrqRC  = 0;
    2854         pVM->pdm.s.Apic.pfnSetBaseRC        = 0;
    2855         pVM->pdm.s.Apic.pfnGetBaseRC        = 0;
    2856         pVM->pdm.s.Apic.pfnSetTPRRC         = 0;
    2857         pVM->pdm.s.Apic.pfnGetTPRRC         = 0;
    2858         pVM->pdm.s.Apic.pfnBusDeliverRC     = 0;
    2859     }
    2860 
    2861     /*
    2862      * Resolve & initialize the R0 bits.
    2863      */
    2864     if (pApicReg->pszGetInterruptR0)
    2865     {
    2866         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
    2867         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
    2868         if (RT_SUCCESS(rc))
    2869         {
    2870             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, &pVM->pdm.s.Apic.pfnHasPendingIrqR0);
    2871             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, rc));
    2872         }
    2873         if (RT_SUCCESS(rc))
    2874         {
    2875             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
    2876             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
    2877         }
    2878         if (RT_SUCCESS(rc))
    2879         {
    2880             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
    2881             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
    2882         }
    2883         if (RT_SUCCESS(rc))
    2884         {
    2885             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
    2886             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
    2887         }
    2888         if (RT_SUCCESS(rc))
    2889         {
    2890             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
    2891             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
    2892         }
    2893         if (RT_SUCCESS(rc))
    2894         {
    2895             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
    2896             AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
    2897         }
    2898         if (VBOX_FAILURE(rc))
    2899         {
    2900             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    2901             return rc;
    2902         }
    2903         pVM->pdm.s.Apic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    2904         Assert(pVM->pdm.s.Apic.pDevInsR0);
    2905     }
    2906     else
    2907     {
    2908         pVM->pdm.s.Apic.pfnGetInterruptR0   = 0;
    2909         pVM->pdm.s.Apic.pfnHasPendingIrqR0  = 0;
    2910         pVM->pdm.s.Apic.pfnSetBaseR0        = 0;
    2911         pVM->pdm.s.Apic.pfnGetBaseR0        = 0;
    2912         pVM->pdm.s.Apic.pfnSetTPRR0         = 0;
    2913         pVM->pdm.s.Apic.pfnGetTPRR0         = 0;
    2914         pVM->pdm.s.Apic.pfnBusDeliverR0     = 0;
    2915         pVM->pdm.s.Apic.pDevInsR0           = 0;
    2916     }
    2917 
    2918     /*
    2919      * Initialize the HC bits.
    2920      */
    2921     pVM->pdm.s.Apic.pDevInsR3           = pDevIns;
    2922     pVM->pdm.s.Apic.pfnGetInterruptR3   = pApicReg->pfnGetInterruptR3;
    2923     pVM->pdm.s.Apic.pfnHasPendingIrqR3  = pApicReg->pfnHasPendingIrqR3;
    2924     pVM->pdm.s.Apic.pfnSetBaseR3        = pApicReg->pfnSetBaseR3;
    2925     pVM->pdm.s.Apic.pfnGetBaseR3        = pApicReg->pfnGetBaseR3;
    2926     pVM->pdm.s.Apic.pfnSetTPRR3         = pApicReg->pfnSetTPRR3;
    2927     pVM->pdm.s.Apic.pfnGetTPRR3         = pApicReg->pfnGetTPRR3;
    2928     pVM->pdm.s.Apic.pfnBusDeliverR3     = pApicReg->pfnBusDeliverR3;
    2929     Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    2930 
    2931     /* set the helper pointer and return. */
    2932     *ppApicHlpR3 = &g_pdmR3DevApicHlp;
    2933     LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    2934     return VINF_SUCCESS;
    2935 }
    2936 
    2937 
    2938 /** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
    2939 static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
    2940 {
    2941     PDMDEV_ASSERT_DEVINS(pDevIns);
    2942     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    2943     LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
    2944              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
    2945              pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
    2946 
    2947     /*
    2948      * Validate input.
    2949      */
    2950     if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
    2951     {
    2952         AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
    2953         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2954         return VERR_INVALID_PARAMETER;
    2955     }
    2956     if (!pIoApicReg->pfnSetIrqR3)
    2957     {
    2958         Assert(pIoApicReg->pfnSetIrqR3);
    2959         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (R3 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2960         return VERR_INVALID_PARAMETER;
    2961     }
    2962     if (    pIoApicReg->pszSetIrqRC
    2963         &&  !VALID_PTR(pIoApicReg->pszSetIrqRC))
    2964     {
    2965         Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
    2966         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2967         return VERR_INVALID_PARAMETER;
    2968     }
    2969     if (    pIoApicReg->pszSetIrqR0
    2970         &&  !VALID_PTR(pIoApicReg->pszSetIrqR0))
    2971     {
    2972         Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
    2973         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2974         return VERR_INVALID_PARAMETER;
    2975     }
    2976     if (!ppIoApicHlpR3)
    2977     {
    2978         Assert(ppIoApicHlpR3);
    2979         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2980         return VERR_INVALID_PARAMETER;
    2981     }
    2982 
    2983     /*
    2984      * The I/O APIC requires the APIC to be present (hacks++).
    2985      * If the I/O APIC does GC stuff so must the APIC.
    2986      */
    2987     PVM pVM = pDevIns->Internal.s.pVMR3;
    2988     if (!pVM->pdm.s.Apic.pDevInsR3)
    2989     {
    2990         AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
    2991         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2992         return VERR_INVALID_PARAMETER;
    2993     }
    2994     if (    pIoApicReg->pszSetIrqRC
    2995         &&  !pVM->pdm.s.Apic.pDevInsRC)
    2996     {
    2997         AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
    2998         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    2999         return VERR_INVALID_PARAMETER;
    3000     }
    3001 
    3002     /*
    3003      * Only one I/O APIC device.
    3004      */
    3005     if (pVM->pdm.s.IoApic.pDevInsR3)
    3006     {
    3007         AssertMsgFailed(("Only one ioapic device is supported!\n"));
    3008         LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3009         return VERR_INVALID_PARAMETER;
    3010     }
    3011 
    3012     /*
    3013      * Resolve & initialize the GC bits.
    3014      */
    3015     if (pIoApicReg->pszSetIrqRC)
    3016     {
    3017         int rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
    3018         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szRCMod, pIoApicReg->pszSetIrqRC, rc));
    3019         if (VBOX_FAILURE(rc))
    3020         {
    3021             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3022             return rc;
    3023         }
    3024         pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    3025     }
    3026     else
    3027     {
    3028         pVM->pdm.s.IoApic.pDevInsRC   = 0;
    3029         pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
    3030     }
    3031 
    3032     /*
    3033      * Resolve & initialize the R0 bits.
    3034      */
    3035     if (pIoApicReg->pszSetIrqR0)
    3036     {
    3037         int rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
    3038         AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
    3039         if (VBOX_FAILURE(rc))
    3040         {
    3041             LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3042             return rc;
    3043         }
    3044         pVM->pdm.s.IoApic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
    3045         Assert(pVM->pdm.s.IoApic.pDevInsR0);
    3046     }
    3047     else
    3048     {
    3049         pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
    3050         pVM->pdm.s.IoApic.pDevInsR0   = 0;
    3051     }
    3052 
    3053     /*
    3054      * Initialize the R3 bits.
    3055      */
    3056     pVM->pdm.s.IoApic.pDevInsR3   = pDevIns;
    3057     pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
    3058     Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    3059 
    3060     /* set the helper pointer and return. */
    3061     *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
    3062     LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
    3063     return VINF_SUCCESS;
    3064 }
    3065 
    3066 
    3067 /** @copydoc PDMDEVHLPR3::pfnDMACRegister */
    3068 static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
    3069 {
    3070     PDMDEV_ASSERT_DEVINS(pDevIns);
    3071     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3072     LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: pDmacReg=%p:{.u32Version=%#x, .pfnRun=%p, .pfnRegister=%p, .pfnReadMemory=%p, .pfnWriteMemory=%p, .pfnSetDREQ=%p, .pfnGetChannelMode=%p} ppDmacHlp=%p\n",
    3073              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
    3074              pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
    3075 
    3076     /*
    3077      * Validate input.
    3078      */
    3079     if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
    3080     {
    3081         AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
    3082                          PDM_DMACREG_VERSION));
    3083         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
    3084                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3085         return VERR_INVALID_PARAMETER;
    3086     }
    3087     if (    !pDmacReg->pfnRun
    3088         ||  !pDmacReg->pfnRegister
    3089         ||  !pDmacReg->pfnReadMemory
    3090         ||  !pDmacReg->pfnWriteMemory
    3091         ||  !pDmacReg->pfnSetDREQ
    3092         ||  !pDmacReg->pfnGetChannelMode)
    3093     {
    3094         Assert(pDmacReg->pfnRun);
    3095         Assert(pDmacReg->pfnRegister);
    3096         Assert(pDmacReg->pfnReadMemory);
    3097         Assert(pDmacReg->pfnWriteMemory);
    3098         Assert(pDmacReg->pfnSetDREQ);
    3099         Assert(pDmacReg->pfnGetChannelMode);
    3100         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
    3101                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3102         return VERR_INVALID_PARAMETER;
    3103     }
    3104 
    3105     if (!ppDmacHlp)
    3106     {
    3107         Assert(ppDmacHlp);
    3108         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
    3109                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3110         return VERR_INVALID_PARAMETER;
    3111     }
    3112 
    3113     /*
    3114      * Only one DMA device.
    3115      */
    3116     PVM pVM = pDevIns->Internal.s.pVMR3;
    3117     if (pVM->pdm.s.pDmac)
    3118     {
    3119         AssertMsgFailed(("Only one DMA device is supported!\n"));
    3120         LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
    3121                  pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
    3122         return VERR_INVALID_PARAMETER;
    3123     }
    3124 
    3125     /*
    3126      * Allocate and initialize pci bus structure.
    3127      */
    3128     int rc = VINF_SUCCESS;
    3129     PPDMDMAC  pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
    3130     if (pDmac)
    3131     {
    3132         pDmac->pDevIns   = pDevIns;
    3133         pDmac->Reg       = *pDmacReg;
    3134         pVM->pdm.s.pDmac = pDmac;
    3135 
    3136         /* set the helper pointer. */
    3137         *ppDmacHlp = &g_pdmR3DevDmacHlp;
    3138         Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
    3139              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
    3140     }
    3141     else
    3142         rc = VERR_NO_MEMORY;
    3143 
    3144     LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
    3145              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3146     return rc;
    3147 }
    3148 
    3149 
    3150 /** @copydoc PDMDEVHLPR3::pfnPhysRead */
    3151 static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
    3152 {
    3153     PDMDEV_ASSERT_DEVINS(pDevIns);
    3154     LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
    3155              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
    3156 
    3157     /*
    3158      * For the convenience of the device we put no thread restriction on this interface.
    3159      * That means we'll have to check which thread we're in and choose our path.
    3160      */
    3161 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    3162     PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3163 #else
    3164     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    3165         PGMPhysRead(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3166     else
    3167     {
    3168         Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3169         PVMREQ pReq;
    3170         AssertCompileSize(RTGCPHYS, 4);
    3171         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    3172                                  (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbRead);
    3173         while (rc == VERR_TIMEOUT)
    3174             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    3175         AssertReleaseRC(rc);
    3176         VMR3ReqFree(pReq);
    3177     }
    3178 #endif
    3179     Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3180 }
    3181 
    3182 
    3183 /** @copydoc PDMDEVHLPR3::pfnPhysWrite */
    3184 static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
    3185 {
    3186     PDMDEV_ASSERT_DEVINS(pDevIns);
    3187     LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
    3188              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
    3189 
    3190     /*
    3191      * For the convenience of the device we put no thread restriction on this interface.
    3192      * That means we'll have to check which thread we're in and choose our path.
    3193      */
    3194 #ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
    3195     PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3196 #else
    3197     if (VM_IS_EMT(pDevIns->Internal.s.pVMR3) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMR3))
    3198         PGMPhysWrite(pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3199     else
    3200     {
    3201         Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3202         PVMREQ pReq;
    3203         AssertCompileSize(RTGCPHYS, 4);
    3204         int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMR3, &pReq, RT_INDEFINITE_WAIT,
    3205                                  (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMR3, GCPhys, pvBuf, cbWrite);
    3206         while (rc == VERR_TIMEOUT)
    3207             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    3208         AssertReleaseRC(rc);
    3209         VMR3ReqFree(pReq);
    3210     }
    3211 #endif
    3212     Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3213 }
    3214 
    3215 
    3216 /** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
    3217 static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
    3218 {
    3219     PDMDEV_ASSERT_DEVINS(pDevIns);
    3220     PVM pVM = pDevIns->Internal.s.pVMR3;
    3221     VM_ASSERT_EMT(pVM);
    3222     LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
    3223              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
    3224 
    3225     if (!VM_IS_EMT(pVM))
    3226         return VERR_ACCESS_DENIED;
    3227 
    3228     int rc = PGMPhysReadGCPtr(pVM, pvDst, GCVirtSrc, cb);
    3229 
    3230     LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3231 
    3232     return rc;
    3233 }
    3234 
    3235 
    3236 /** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
    3237 static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
    3238 {
    3239     PDMDEV_ASSERT_DEVINS(pDevIns);
    3240     PVM pVM = pDevIns->Internal.s.pVMR3;
    3241     VM_ASSERT_EMT(pVM);
    3242     LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
    3243              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
    3244 
    3245     if (!VM_IS_EMT(pVM))
    3246         return VERR_ACCESS_DENIED;
    3247 
    3248     int rc = PGMPhysWriteGCPtr(pVM, GCVirtDst, pvSrc, cb);
    3249 
    3250     LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3251 
    3252     return rc;
    3253 }
    3254 
    3255 
    3256 /** @copydoc PDMDEVHLPR3::pfnPhysReserve */
    3257 static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
    3258 {
    3259     PDMDEV_ASSERT_DEVINS(pDevIns);
    3260     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3261     LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
    3262              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, pszDesc, pszDesc));
    3263 
    3264     int rc = MMR3PhysReserve(pDevIns->Internal.s.pVMR3, GCPhys, cbRange, pszDesc);
    3265 
    3266     LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3267 
    3268     return rc;
    3269 }
    3270 
    3271 
    3272 /** @copydoc PDMDEVHLPR3::pfnPhysGCPtr2GCPhys */
    3273 static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
    3274 {
    3275     PDMDEV_ASSERT_DEVINS(pDevIns);
    3276     PVM pVM = pDevIns->Internal.s.pVMR3;
    3277     VM_ASSERT_EMT(pVM);
    3278     LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%VGv pGCPhys=%p\n",
    3279              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPtr, pGCPhys));
    3280 
    3281     if (!VM_IS_EMT(pVM))
    3282         return VERR_ACCESS_DENIED;
    3283 
    3284     int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, pGCPhys);
    3285 
    3286     LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Vrc *pGCPhys=%VGp\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pGCPhys));
    3287 
    3288     return rc;
    3289 }
    3290 
    3291 
    3292 /** @copydoc PDMDEVHLPR3::pfnVMState */
    3293 static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
    3294 {
    3295     PDMDEV_ASSERT_DEVINS(pDevIns);
    3296 
    3297     VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
    3298 
    3299     LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    3300              enmVMState, VMR3GetStateName(enmVMState)));
    3301     return enmVMState;
    3302 }
    3303 
    3304 
    3305 /** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
    3306 static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
    3307 {
    3308     PDMDEV_ASSERT_DEVINS(pDevIns);
    3309     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3310 
    3311     bool fRc = PGMPhysIsA20Enabled(pDevIns->Internal.s.pVMR3);
    3312 
    3313     LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
    3314     return fRc;
    3315 }
    3316 
    3317 
    3318 /** @copydoc PDMDEVHLPR3::pfnA20Set */
    3319 static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
    3320 {
    3321     PDMDEV_ASSERT_DEVINS(pDevIns);
    3322     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3323     LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
    3324     //Assert(*(unsigned *)&fEnable <= 1);
    3325     PGMR3PhysSetA20(pDevIns->Internal.s.pVMR3, fEnable);
    3326 }
    3327 
    3328 
    3329 /** @copydoc PDMDEVHLPR3::pfnVMReset */
    3330 static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
    3331 {
    3332     PDMDEV_ASSERT_DEVINS(pDevIns);
    3333     PVM pVM = pDevIns->Internal.s.pVMR3;
    3334     VM_ASSERT_EMT(pVM);
    3335     LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
    3336              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
    3337 
    3338     /*
    3339      * We postpone this operation because we're likely to be inside a I/O instruction
    3340      * and the EIP will be updated when we return.
    3341      * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
    3342      */
    3343     bool fHaltOnReset;
    3344     int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
    3345     if (VBOX_SUCCESS(rc) && fHaltOnReset)
    3346     {
    3347         Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
    3348         rc = VINF_EM_HALT;
    3349     }
    3350     else
    3351     {
    3352         VM_FF_SET(pVM, VM_FF_RESET);
    3353         rc = VINF_EM_RESET;
    3354     }
    3355 
    3356     LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3357     return rc;
    3358 }
    3359 
    3360 
    3361 /** @copydoc PDMDEVHLPR3::pfnVMSuspend */
    3362 static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
    3363 {
    3364     PDMDEV_ASSERT_DEVINS(pDevIns);
    3365     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3366     LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
    3367              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3368 
    3369     int rc = VMR3Suspend(pDevIns->Internal.s.pVMR3);
    3370 
    3371     LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3372     return rc;
    3373 }
    3374 
    3375 
    3376 /** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
    3377 static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
    3378 {
    3379     PDMDEV_ASSERT_DEVINS(pDevIns);
    3380     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3381     LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
    3382              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3383 
    3384     int rc = VMR3PowerOff(pDevIns->Internal.s.pVMR3);
    3385 
    3386     LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3387     return rc;
    3388 }
    3389 
    3390 
    3391 /** @copydoc PDMDEVHLPR3::pfnLockVM */
    3392 static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns)
    3393 {
    3394     return VMMR3Lock(pDevIns->Internal.s.pVMR3);
    3395 }
    3396 
    3397 
    3398 /** @copydoc PDMDEVHLPR3::pfnUnlockVM */
    3399 static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns)
    3400 {
    3401     return VMMR3Unlock(pDevIns->Internal.s.pVMR3);
    3402 }
    3403 
    3404 
    3405 /** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
    3406 static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    3407 {
    3408     PVM pVM = pDevIns->Internal.s.pVMR3;
    3409     if (VMMR3LockIsOwner(pVM))
    3410         return true;
    3411 
    3412     RTNATIVETHREAD NativeThreadOwner = VMMR3LockGetOwner(pVM);
    3413     RTTHREAD ThreadOwner = RTThreadFromNative(NativeThreadOwner);
    3414     char szMsg[100];
    3415     RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
    3416                 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
    3417                 NativeThreadOwner, ThreadOwner, RTThreadGetName(ThreadOwner), RTThreadSelfName());
    3418     AssertMsg1(szMsg, iLine, pszFile, pszFunction);
    3419     AssertBreakpoint();
    3420     return false;
    3421 }
    3422 
    3423 /** @copydoc PDMDEVHLPR3::pfnDMARegister */
    3424 static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
    3425 {
    3426     PDMDEV_ASSERT_DEVINS(pDevIns);
    3427     PVM pVM = pDevIns->Internal.s.pVMR3;
    3428     VM_ASSERT_EMT(pVM);
    3429     LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
    3430              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
    3431     int rc = VINF_SUCCESS;
    3432     if (pVM->pdm.s.pDmac)
    3433         pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
    3434     else
    3435     {
    3436         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3437         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3438     }
    3439     LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
    3440              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3441     return rc;
    3442 }
    3443 
    3444 /** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
    3445 static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
    3446 {
    3447     PDMDEV_ASSERT_DEVINS(pDevIns);
    3448     PVM pVM = pDevIns->Internal.s.pVMR3;
    3449     VM_ASSERT_EMT(pVM);
    3450     LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
    3451              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
    3452     int rc = VINF_SUCCESS;
    3453     if (pVM->pdm.s.pDmac)
    3454     {
    3455         uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
    3456         if (pcbRead)
    3457             *pcbRead = cb;
    3458     }
    3459     else
    3460     {
    3461         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3462         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3463     }
    3464     LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
    3465              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3466     return rc;
    3467 }
    3468 
    3469 /** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
    3470 static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
    3471 {
    3472     PDMDEV_ASSERT_DEVINS(pDevIns);
    3473     PVM pVM = pDevIns->Internal.s.pVMR3;
    3474     VM_ASSERT_EMT(pVM);
    3475     LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
    3476              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
    3477     int rc = VINF_SUCCESS;
    3478     if (pVM->pdm.s.pDmac)
    3479     {
    3480         uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
    3481         if (pcbWritten)
    3482             *pcbWritten = cb;
    3483     }
    3484     else
    3485     {
    3486         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3487         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3488     }
    3489     LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
    3490              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3491     return rc;
    3492 }
    3493 
    3494 /** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
    3495 static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
    3496 {
    3497     PDMDEV_ASSERT_DEVINS(pDevIns);
    3498     PVM pVM = pDevIns->Internal.s.pVMR3;
    3499     VM_ASSERT_EMT(pVM);
    3500     LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
    3501              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, uLevel));
    3502     int rc = VINF_SUCCESS;
    3503     if (pVM->pdm.s.pDmac)
    3504         pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
    3505     else
    3506     {
    3507         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3508         rc = VERR_PDM_NO_DMAC_INSTANCE;
    3509     }
    3510     LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
    3511              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3512     return rc;
    3513 }
    3514 
    3515 /** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
    3516 static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
    3517 {
    3518     PDMDEV_ASSERT_DEVINS(pDevIns);
    3519     PVM pVM = pDevIns->Internal.s.pVMR3;
    3520     VM_ASSERT_EMT(pVM);
    3521     LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
    3522              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel));
    3523     uint8_t u8Mode;
    3524     if (pVM->pdm.s.pDmac)
    3525         u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
    3526     else
    3527     {
    3528         AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3529         u8Mode = 3 << 2 /* illegal mode type */;
    3530     }
    3531     LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
    3532              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Mode));
    3533     return u8Mode;
    3534 }
    3535 
    3536 /** @copydoc PDMDEVHLPR3::pfnDMASchedule */
    3537 static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
    3538 {
    3539     PDMDEV_ASSERT_DEVINS(pDevIns);
    3540     PVM pVM = pDevIns->Internal.s.pVMR3;
    3541     VM_ASSERT_EMT(pVM);
    3542     LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
    3543              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
    3544 
    3545     AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
    3546     VM_FF_SET(pVM, VM_FF_PDM_DMA);
    3547     REMR3NotifyDmaPending(pVM);
    3548     VMR3NotifyFF(pVM, true);
    3549 }
    3550 
    3551 
    3552 /** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
    3553 static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
    3554 {
    3555     PDMDEV_ASSERT_DEVINS(pDevIns);
    3556     PVM pVM = pDevIns->Internal.s.pVMR3;
    3557     VM_ASSERT_EMT(pVM);
    3558 
    3559     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
    3560              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, u8Value));
    3561     int rc;
    3562     if (pVM->pdm.s.pRtc)
    3563         rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
    3564     else
    3565         rc = VERR_PDM_NO_RTC_INSTANCE;
    3566 
    3567     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
    3568              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3569     return rc;
    3570 }
    3571 
    3572 
    3573 /** @copydoc PDMDEVHLPR3::pfnCMOSRead */
    3574 static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
    3575 {
    3576     PDMDEV_ASSERT_DEVINS(pDevIns);
    3577     PVM pVM = pDevIns->Internal.s.pVMR3;
    3578     VM_ASSERT_EMT(pVM);
    3579 
    3580     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
    3581              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, pu8Value));
    3582     int rc;
    3583     if (pVM->pdm.s.pRtc)
    3584         rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
    3585     else
    3586         rc = VERR_PDM_NO_RTC_INSTANCE;
    3587 
    3588     LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
    3589              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3590     return rc;
    3591 }
    3592 
    3593 
    3594 /** @copydoc PDMDEVHLPR3::pfnGetCpuId */
    3595 static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    3596                                                uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
    3597 {
    3598     PDMDEV_ASSERT_DEVINS(pDevIns);
    3599     LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
    3600              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
    3601     AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
    3602 
    3603     CPUMGetGuestCpuId(pDevIns->Internal.s.pVMR3, iLeaf, pEax, pEbx, pEcx, pEdx);
    3604 
    3605     LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
    3606              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
    3607 }
    3608 
    3609 
    3610 /** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
    3611 static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    3612 {
    3613     PDMDEV_ASSERT_DEVINS(pDevIns);
    3614     LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
    3615              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
    3616 
    3617     int rc = MMR3PhysRomProtect(pDevIns->Internal.s.pVMR3, GCPhysStart, cbRange);
    3618 
    3619     LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3620     return rc;
    3621 }
    3622 
    3623 
    3624 /**
    3625  * @copydoc PDMDEVHLPR3::pfnMMIO2Register
    3626  */
    3627 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
    3628 {
    3629     PDMDEV_ASSERT_DEVINS(pDevIns);
    3630     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3631     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: iRegion=#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",
    3632              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cb, fFlags, ppv, pszDesc, pszDesc));
    3633 
    3634     int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, cb, fFlags, ppv, pszDesc);
    3635 
    3636     LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3637     return rc;
    3638 }
    3639 
    3640 
    3641 /**
    3642  * @copydoc PDMDEVHLPR3::pfnMMIO2Deregister
    3643  */
    3644 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
    3645 {
    3646     PDMDEV_ASSERT_DEVINS(pDevIns);
    3647     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3648     LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: iRegion=#x\n",
    3649              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion));
    3650 
    3651     AssertReturn(iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);
    3652 
    3653     int rc = PGMR3PhysMMIO2Deregister(pDevIns->Internal.s.pVMR3, pDevIns, iRegion);
    3654 
    3655     LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3656     return rc;
    3657 }
    3658 
    3659 
    3660 /**
    3661  * @copydoc PDMDEVHLPR3::pfnMMIO2Map
    3662  */
    3663 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    3664 {
    3665     PDMDEV_ASSERT_DEVINS(pDevIns);
    3666     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3667     LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
    3668              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
    3669 
    3670     int rc = PGMR3PhysMMIO2Map(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
    3671 
    3672     LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3673     return rc;
    3674 }
    3675 
    3676 
    3677 /**
    3678  * @copydoc PDMDEVHLPR3::pfnMMIO2Unmap
    3679  */
    3680 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    3681 {
    3682     PDMDEV_ASSERT_DEVINS(pDevIns);
    3683     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3684     LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
    3685              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
    3686 
    3687     int rc = PGMR3PhysMMIO2Unmap(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, GCPhys);
    3688 
    3689     LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    3690     return rc;
    3691 }
    3692 
    3693 
    3694 /**
    3695  * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2
    3696  */
    3697 static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
    3698                                                      const char *pszDesc, PRTRCPTR pRCPtr)
    3699 {
    3700     PDMDEV_ASSERT_DEVINS(pDevIns);
    3701     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3702     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: iRegion=#x off=%RGp cb=%RGp pszDesc=%p:{%s} pRCPtr=%p\n",
    3703              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, off, cb, pszDesc, pszDesc, pRCPtr));
    3704 
    3705     int rc = MMR3HyperMapMMIO2(pDevIns->Internal.s.pVMR3, pDevIns, iRegion, off, cb, pszDesc, pRCPtr);
    3706 
    3707     LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc *pRCPtr=%RRv\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pRCPtr));
    3708     return rc;
    3709 }
    3710 
    3711 
    3712 /**
    3713  * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
    3714  */
    3715 static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
    3716 {
    3717     PDMDEV_ASSERT_DEVINS(pDevIns);
    3718     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3719 
    3720     int rc = PDMR3RegisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys, pvHeap, cbSize);
    3721     return rc;
    3722 }
    3723 
    3724 
    3725 /**
    3726  * @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap
    3727  */
    3728 static DECLCALLBACK(int) pdmR3DevHlp_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
    3729 {
    3730     PDMDEV_ASSERT_DEVINS(pDevIns);
    3731     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    3732 
    3733     int rc = PDMR3UnregisterVMMDevHeap(pDevIns->Internal.s.pVMR3, GCPhys);
    3734     return rc;
    3735 }
    3736 
    3737 
    3738 
    3739 
    3740 
    3741 /** @copydoc PDMDEVHLPR3::pfnGetVM */
    3742 static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
    3743 {
    3744     PDMDEV_ASSERT_DEVINS(pDevIns);
    3745     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3746     return NULL;
    3747 }
    3748 
    3749 
    3750 /** @copydoc PDMDEVHLPR3::pfnPCIBusRegister */
    3751 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
    3752 {
    3753     PDMDEV_ASSERT_DEVINS(pDevIns);
    3754     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3755     NOREF(pPciBusReg);
    3756     NOREF(ppPciHlpR3);
    3757     return VERR_ACCESS_DENIED;
    3758 }
    3759 
    3760 
    3761 /** @copydoc PDMDEVHLPR3::pfnPICRegister */
    3762 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
    3763 {
    3764     PDMDEV_ASSERT_DEVINS(pDevIns);
    3765     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3766     NOREF(pPicReg);
    3767     NOREF(ppPicHlpR3);
    3768     return VERR_ACCESS_DENIED;
    3769 }
    3770 
    3771 
    3772 /** @copydoc PDMDEVHLPR3::pfnAPICRegister */
    3773 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
    3774 {
    3775     PDMDEV_ASSERT_DEVINS(pDevIns);
    3776     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3777     NOREF(pApicReg);
    3778     NOREF(ppApicHlpR3);
    3779     return VERR_ACCESS_DENIED;
    3780 }
    3781 
    3782 
    3783 /** @copydoc PDMDEVHLPR3::pfnIOAPICRegister */
    3784 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
    3785 {
    3786     PDMDEV_ASSERT_DEVINS(pDevIns);
    3787     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3788     NOREF(pIoApicReg);
    3789     NOREF(ppIoApicHlpR3);
    3790     return VERR_ACCESS_DENIED;
    3791 }
    3792 
    3793 
    3794 /** @copydoc PDMDEVHLPR3::pfnDMACRegister */
    3795 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
    3796 {
    3797     PDMDEV_ASSERT_DEVINS(pDevIns);
    3798     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3799     NOREF(pDmacReg);
    3800     NOREF(ppDmacHlp);
    3801     return VERR_ACCESS_DENIED;
    3802 }
    3803 
    3804 
    3805 /** @copydoc PDMDEVHLPR3::pfnPhysRead */
    3806 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
    3807 {
    3808     PDMDEV_ASSERT_DEVINS(pDevIns);
    3809     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3810     NOREF(GCPhys);
    3811     NOREF(pvBuf);
    3812     NOREF(cbRead);
    3813 }
    3814 
    3815 
    3816 /** @copydoc PDMDEVHLPR3::pfnPhysWrite */
    3817 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
    3818 {
    3819     PDMDEV_ASSERT_DEVINS(pDevIns);
    3820     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3821     NOREF(GCPhys);
    3822     NOREF(pvBuf);
    3823     NOREF(cbWrite);
    3824 }
    3825 
    3826 
    3827 /** @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt */
    3828 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
    3829 {
    3830     PDMDEV_ASSERT_DEVINS(pDevIns);
    3831     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3832     NOREF(pvDst);
    3833     NOREF(GCVirtSrc);
    3834     NOREF(cb);
    3835     return VERR_ACCESS_DENIED;
    3836 }
    3837 
    3838 
    3839 /** @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt */
    3840 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
    3841 {
    3842     PDMDEV_ASSERT_DEVINS(pDevIns);
    3843     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3844     NOREF(GCVirtDst);
    3845     NOREF(pvSrc);
    3846     NOREF(cb);
    3847     return VERR_ACCESS_DENIED;
    3848 }
    3849 
    3850 
    3851 /** @copydoc PDMDEVHLPR3::pfnPhysReserve */
    3852 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
    3853 {
    3854     PDMDEV_ASSERT_DEVINS(pDevIns);
    3855     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3856     NOREF(GCPhys);
    3857     NOREF(cbRange);
    3858     return VERR_ACCESS_DENIED;
    3859 }
    3860 
    3861 
    3862 /** @copydoc PDMDEVHLPR3::pfnObsoletePhys2HCVirt */
    3863 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
    3864 {
    3865     PDMDEV_ASSERT_DEVINS(pDevIns);
    3866     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3867     NOREF(GCPhys);
    3868     NOREF(cbRange);
    3869     NOREF(ppvHC);
    3870     return VERR_ACCESS_DENIED;
    3871 }
    3872 
    3873 
    3874 /** @copydoc PDMDEVHLPR3::pfnObsoletePhysGCPtr2HCPtr */
    3875 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
    3876 {
    3877     PDMDEV_ASSERT_DEVINS(pDevIns);
    3878     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3879     NOREF(GCPtr);
    3880     NOREF(pHCPtr);
    3881     return VERR_ACCESS_DENIED;
    3882 }
    3883 
    3884 
    3885 /** @copydoc PDMDEVHLPR3::pfnA20IsEnabled */
    3886 static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
    3887 {
    3888     PDMDEV_ASSERT_DEVINS(pDevIns);
    3889     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3890     return false;
    3891 }
    3892 
    3893 
    3894 /** @copydoc PDMDEVHLPR3::pfnA20Set */
    3895 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
    3896 {
    3897     PDMDEV_ASSERT_DEVINS(pDevIns);
    3898     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3899     NOREF(fEnable);
    3900 }
    3901 
    3902 
    3903 /** @copydoc PDMDEVHLPR3::pfnVMReset */
    3904 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
    3905 {
    3906     PDMDEV_ASSERT_DEVINS(pDevIns);
    3907     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3908     return VERR_ACCESS_DENIED;
    3909 }
    3910 
    3911 
    3912 /** @copydoc PDMDEVHLPR3::pfnVMSuspend */
    3913 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
    3914 {
    3915     PDMDEV_ASSERT_DEVINS(pDevIns);
    3916     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3917     return VERR_ACCESS_DENIED;
    3918 }
    3919 
    3920 
    3921 /** @copydoc PDMDEVHLPR3::pfnVMPowerOff */
    3922 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
    3923 {
    3924     PDMDEV_ASSERT_DEVINS(pDevIns);
    3925     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3926     return VERR_ACCESS_DENIED;
    3927 }
    3928 
    3929 
    3930 /** @copydoc PDMDEVHLPR3::pfnLockVM */
    3931 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns)
    3932 {
    3933     PDMDEV_ASSERT_DEVINS(pDevIns);
    3934     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3935     return VERR_ACCESS_DENIED;
    3936 }
    3937 
    3938 
    3939 /** @copydoc PDMDEVHLPR3::pfnUnlockVM */
    3940 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns)
    3941 {
    3942     PDMDEV_ASSERT_DEVINS(pDevIns);
    3943     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3944     return VERR_ACCESS_DENIED;
    3945 }
    3946 
    3947 
    3948 /** @copydoc PDMDEVHLPR3::pfnAssertVMLock */
    3949 static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
    3950 {
    3951     PDMDEV_ASSERT_DEVINS(pDevIns);
    3952     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3953     return false;
    3954 }
    3955 
    3956 
    3957 /** @copydoc PDMDEVHLPR3::pfnDMARegister */
    3958 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
    3959 {
    3960     PDMDEV_ASSERT_DEVINS(pDevIns);
    3961     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3962     return VERR_ACCESS_DENIED;
    3963 }
    3964 
    3965 
    3966 /** @copydoc PDMDEVHLPR3::pfnDMAReadMemory */
    3967 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
    3968 {
    3969     PDMDEV_ASSERT_DEVINS(pDevIns);
    3970     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3971     if (pcbRead)
    3972         *pcbRead = 0;
    3973     return VERR_ACCESS_DENIED;
    3974 }
    3975 
    3976 
    3977 /** @copydoc PDMDEVHLPR3::pfnDMAWriteMemory */
    3978 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
    3979 {
    3980     PDMDEV_ASSERT_DEVINS(pDevIns);
    3981     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3982     if (pcbWritten)
    3983         *pcbWritten = 0;
    3984     return VERR_ACCESS_DENIED;
    3985 }
    3986 
    3987 
    3988 /** @copydoc PDMDEVHLPR3::pfnDMASetDREQ */
    3989 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
    3990 {
    3991     PDMDEV_ASSERT_DEVINS(pDevIns);
    3992     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    3993     return VERR_ACCESS_DENIED;
    3994 }
    3995 
    3996 
    3997 /** @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode */
    3998 static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
    3999 {
    4000     PDMDEV_ASSERT_DEVINS(pDevIns);
    4001     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4002     return 3 << 2 /* illegal mode type */;
    4003 }
    4004 
    4005 
    4006 /** @copydoc PDMDEVHLPR3::pfnDMASchedule */
    4007 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns)
    4008 {
    4009     PDMDEV_ASSERT_DEVINS(pDevIns);
    4010     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4011 }
    4012 
    4013 
    4014 /** @copydoc PDMDEVHLPR3::pfnCMOSWrite */
    4015 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
    4016 {
    4017     PDMDEV_ASSERT_DEVINS(pDevIns);
    4018     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4019     return VERR_ACCESS_DENIED;
    4020 }
    4021 
    4022 
    4023 /** @copydoc PDMDEVHLPR3::pfnCMOSRead */
    4024 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
    4025 {
    4026     PDMDEV_ASSERT_DEVINS(pDevIns);
    4027     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4028     return VERR_ACCESS_DENIED;
    4029 }
    4030 
    4031 
    4032 /** @copydoc PDMDEVHLPR3::pfnGetCpuId */
    4033 static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
    4034                                                          uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
    4035 {
    4036     PDMDEV_ASSERT_DEVINS(pDevIns);
    4037     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4038 }
    4039 
    4040 
    4041 /** @copydoc PDMDEVHLPR3::pfnROMProtectShadow */
    4042 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
    4043 {
    4044     PDMDEV_ASSERT_DEVINS(pDevIns);
    4045     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4046     return VERR_ACCESS_DENIED;
    4047 }
    4048 
    4049 
    4050 /** @copydoc PDMDEVHLPR3::pfnMMIO2Register */
    4051 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
    4052 {
    4053     PDMDEV_ASSERT_DEVINS(pDevIns);
    4054     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4055     return VERR_ACCESS_DENIED;
    4056 }
    4057 
    4058 
    4059 /** @copydoc PDMDEVHLPR3::pfnMMIO2Deregister */
    4060 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
    4061 {
    4062     PDMDEV_ASSERT_DEVINS(pDevIns);
    4063     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4064     return VERR_ACCESS_DENIED;
    4065 }
    4066 
    4067 
    4068 /** @copydoc PDMDEVHLPR3::pfnMMIO2Map */
    4069 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    4070 {
    4071     PDMDEV_ASSERT_DEVINS(pDevIns);
    4072     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4073     return VERR_ACCESS_DENIED;
    4074 }
    4075 
    4076 
    4077 /** @copydoc PDMDEVHLPR3::pfnMMIO2Unmap */
    4078 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
    4079 {
    4080     PDMDEV_ASSERT_DEVINS(pDevIns);
    4081     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4082     return VERR_ACCESS_DENIED;
    4083 }
    4084 
    4085 
    4086 /** @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2 */
    4087 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr)
    4088 {
    4089     PDMDEV_ASSERT_DEVINS(pDevIns);
    4090     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4091     return VERR_ACCESS_DENIED;
    4092 }
    4093 
    4094 
    4095 /** @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap */
    4096 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
    4097 {
    4098     PDMDEV_ASSERT_DEVINS(pDevIns);
    4099     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4100     return VERR_ACCESS_DENIED;
    4101 }
    4102 
    4103 
    4104 /** @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap */
    4105 static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
    4106 {
    4107     PDMDEV_ASSERT_DEVINS(pDevIns);
    4108     AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    4109     return VERR_ACCESS_DENIED;
    4110 }
    4111 
    4112 
    4113 
    4114 
    4115 
    4116 /** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
    4117 static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
    4118 {
    4119     PDMDEV_ASSERT_DEVINS(pDevIns);
    4120     PVM pVM = pDevIns->Internal.s.pVMR3;
    4121     LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
    4122              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pVM, 0, VM_FF_INTERRUPT_PIC)));
    4123     /* for PIC we always deliver to CPU 0, MP use APIC */
    4124     VMCPU_FF_SET(pVM, 0, VM_FF_INTERRUPT_PIC);
    4125     REMR3NotifyInterruptSet(pVM);
    4126     VMR3NotifyFF(pVM, true);
    4127 }
    4128 
    4129 
    4130 /** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
    4131 static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
    4132 {
    4133     PDMDEV_ASSERT_DEVINS(pDevIns);
    4134     LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
    4135              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC)));
    4136     /* for PIC we always deliver to CPU 0, MP use APIC */
    4137     VMCPU_FF_CLEAR(pDevIns->Internal.s.pVMR3, 0, VM_FF_INTERRUPT_PIC);
    4138     REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMR3);
    4139 }
    4140 
    4141 
    4142 /** @copydoc PDMPICHLPR3::pfnLock */
    4143 static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4144 {
    4145     PDMDEV_ASSERT_DEVINS(pDevIns);
    4146     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4147 }
    4148 
    4149 
    4150 /** @copydoc PDMPICHLPR3::pfnUnlock */
    4151 static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
    4152 {
    4153     PDMDEV_ASSERT_DEVINS(pDevIns);
    4154     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4155 }
    4156 
    4157 
    4158 /** @copydoc PDMPICHLPR3::pfnGetRCHelpers */
    4159 static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4160 {
    4161     PDMDEV_ASSERT_DEVINS(pDevIns);
    4162     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4163     RTRCPTR pRCHelpers = 0;
    4164     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPicHlp", &pRCHelpers);
    4165     AssertReleaseRC(rc);
    4166     AssertRelease(pRCHelpers);
    4167     LogFlow(("pdmR3PicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
    4168              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4169     return pRCHelpers;
    4170 }
    4171 
    4172 
    4173 /** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
    4174 static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4175 {
    4176     PDMDEV_ASSERT_DEVINS(pDevIns);
    4177     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4178     PCPDMPICHLPR0 pR0Helpers = 0;
    4179     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PicHlp", &pR0Helpers);
    4180     AssertReleaseRC(rc);
    4181     AssertRelease(pR0Helpers);
    4182     LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4183              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4184     return pR0Helpers;
    4185 }
    4186 
    4187 
    4188 /** @copydoc PDMAPICHLPR3::pfnSetInterruptFF */
    4189 static DECLCALLBACK(void) pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu)
    4190 {
    4191     PDMDEV_ASSERT_DEVINS(pDevIns);
    4192     PVM pVM = pDevIns->Internal.s.pVMR3;
    4193     LogFlow(("pdmR3ApicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 1\n",
    4194              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pVM, idCpu, VM_FF_INTERRUPT_APIC)));
    4195     VMCPU_FF_SET(pVM, idCpu, VM_FF_INTERRUPT_APIC);
    4196     REMR3NotifyInterruptSet(pVM);
    4197     VMR3NotifyFF(pVM, true);
    4198 }
    4199 
    4200 
    4201 /** @copydoc PDMAPICHLPR3::pfnClearInterruptFF */
    4202 static DECLCALLBACK(void) pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns, VMCPUID idCpu)
    4203 {
    4204     PDMDEV_ASSERT_DEVINS(pDevIns);
    4205     LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 0\n",
    4206              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VMCPU_FF_ISSET(pDevIns->Internal.s.pVMR3, idCpu, VM_FF_INTERRUPT_APIC)));
    4207     VMCPU_FF_CLEAR(pDevIns->Internal.s.pVMR3, idCpu, VM_FF_INTERRUPT_APIC);
    4208     REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMR3);
    4209 }
    4210 
    4211 
    4212 /** @copydoc PDMAPICHLPR3::pfnChangeFeature */
    4213 static DECLCALLBACK(void) pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion)
    4214 {
    4215     PDMDEV_ASSERT_DEVINS(pDevIns);
    4216     LogFlow(("pdmR3ApicHlp_ChangeFeature: caller='%s'/%d: version=%d\n",
    4217              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, (int)enmVersion));
    4218     switch (enmVersion)
    4219     {
    4220         case PDMAPICVERSION_NONE:
    4221             CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
    4222             CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
    4223             break;
    4224         case PDMAPICVERSION_APIC:
    4225             CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
    4226             CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
    4227             break;
    4228         case PDMAPICVERSION_X2APIC:
    4229             CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_X2APIC);
    4230             CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMR3, CPUMCPUIDFEATURE_APIC);
    4231             break;
    4232         default:
    4233             AssertMsgFailed(("Unknown APIC version: %d\n", (int)enmVersion));
    4234     }
    4235 }
    4236 
    4237 /** @copydoc PDMAPICHLPR3::pfnLock */
    4238 static DECLCALLBACK(int) pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4239 {
    4240     PDMDEV_ASSERT_DEVINS(pDevIns);
    4241     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4242 }
    4243 
    4244 
    4245 /** @copydoc PDMAPICHLPR3::pfnUnlock */
    4246 static DECLCALLBACK(void) pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns)
    4247 {
    4248     PDMDEV_ASSERT_DEVINS(pDevIns);
    4249     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4250 }
    4251 
    4252 
    4253 /** @copydoc PDMAPICHLPR3::pfnGetCpuId */
    4254 static DECLCALLBACK(VMCPUID) pdmR3ApicHlp_GetCpuId(PPDMDEVINS pDevIns)
    4255 {
    4256     PDMDEV_ASSERT_DEVINS(pDevIns);
    4257     return VMMGetCpuId(pDevIns->Internal.s.pVMR3);
    4258 }
    4259 
    4260 
    4261 /** @copydoc PDMAPICHLPR3::pfnGetRCHelpers */
    4262 static DECLCALLBACK(PCPDMAPICHLPRC) pdmR3ApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4263 {
    4264     PDMDEV_ASSERT_DEVINS(pDevIns);
    4265     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4266     RTRCPTR pRCHelpers = 0;
    4267     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCApicHlp", &pRCHelpers);
    4268     AssertReleaseRC(rc);
    4269     AssertRelease(pRCHelpers);
    4270     LogFlow(("pdmR3ApicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
    4271              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4272     return pRCHelpers;
    4273 }
    4274 
    4275 
    4276 /** @copydoc PDMAPICHLPR3::pfnGetR0Helpers */
    4277 static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4278 {
    4279     PDMDEV_ASSERT_DEVINS(pDevIns);
    4280     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4281     PCPDMAPICHLPR0 pR0Helpers = 0;
    4282     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0ApicHlp", &pR0Helpers);
    4283     AssertReleaseRC(rc);
    4284     AssertRelease(pR0Helpers);
    4285     LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4286              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4287     return pR0Helpers;
    4288 }
    4289 
    4290 
    4291 /** @copydoc PDMIOAPICHLPR3::pfnApicBusDeliver */
    4292 static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
    4293                                                         uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
    4294 {
    4295     PDMDEV_ASSERT_DEVINS(pDevIns);
    4296     PVM pVM = pDevIns->Internal.s.pVMR3;
    4297     LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
    4298              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
    4299     if (pVM->pdm.s.Apic.pfnBusDeliverR3)
    4300         pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
    4301 }
    4302 
    4303 
    4304 /** @copydoc PDMIOAPICHLPR3::pfnLock */
    4305 static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4306 {
    4307     PDMDEV_ASSERT_DEVINS(pDevIns);
    4308     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4309 }
    4310 
    4311 
    4312 /** @copydoc PDMIOAPICHLPR3::pfnUnlock */
    4313 static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
    4314 {
    4315     PDMDEV_ASSERT_DEVINS(pDevIns);
    4316     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4317 }
    4318 
    4319 
    4320 /** @copydoc PDMIOAPICHLPR3::pfnGetRCHelpers */
    4321 static DECLCALLBACK(PCPDMIOAPICHLPRC) pdmR3IoApicHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4322 {
    4323     PDMDEV_ASSERT_DEVINS(pDevIns);
    4324     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4325     RTRCPTR pRCHelpers = 0;
    4326     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCIoApicHlp", &pRCHelpers);
    4327     AssertReleaseRC(rc);
    4328     AssertRelease(pRCHelpers);
    4329     LogFlow(("pdmR3IoApicHlp_GetRCHelpers: caller='%s'/%d: returns %VGv\n",
    4330              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4331     return pRCHelpers;
    4332 }
    4333 
    4334 
    4335 /** @copydoc PDMIOAPICHLPR3::pfnGetR0Helpers */
    4336 static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4337 {
    4338     PDMDEV_ASSERT_DEVINS(pDevIns);
    4339     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4340     PCPDMIOAPICHLPR0 pR0Helpers = 0;
    4341     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0IoApicHlp", &pR0Helpers);
    4342     AssertReleaseRC(rc);
    4343     AssertRelease(pR0Helpers);
    4344     LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4345              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4346     return pR0Helpers;
    4347 }
    4348 
    4349 
    4350 /** @copydoc PDMPCIHLPR3::pfnIsaSetIrq */
    4351 static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    4352 {
    4353     PDMDEV_ASSERT_DEVINS(pDevIns);
    4354     Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
    4355     PDMIsaSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel);
    4356 }
    4357 
    4358 
    4359 /** @copydoc PDMPCIHLPR3::pfnIoApicSetIrq */
    4360 static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
    4361 {
    4362     PDMDEV_ASSERT_DEVINS(pDevIns);
    4363     Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
    4364     PDMIoApicSetIrq(pDevIns->Internal.s.pVMR3, iIrq, iLevel);
    4365 }
    4366 
    4367 
    4368 /** @copydoc PDMPCIHLPR3::pfnIsMMIO2Base */
    4369 static DECLCALLBACK(bool) pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys)
    4370 {
    4371     PDMDEV_ASSERT_DEVINS(pDevIns);
    4372     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4373     bool fRc = PGMR3PhysMMIO2IsBase(pDevIns->Internal.s.pVMR3, pOwner, GCPhys);
    4374     Log4(("pdmR3PciHlp_IsMMIO2Base: pOwner=%p GCPhys=%RGp -> %RTbool\n", pOwner, GCPhys, fRc));
    4375     return fRc;
    4376 }
    4377 
    4378 
    4379 /** @copydoc PDMPCIHLPR3::pfnLock */
    4380 static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
    4381 {
    4382     PDMDEV_ASSERT_DEVINS(pDevIns);
    4383     return pdmLockEx(pDevIns->Internal.s.pVMR3, rc);
    4384 }
    4385 
    4386 
    4387 /** @copydoc PDMPCIHLPR3::pfnUnlock */
    4388 static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
    4389 {
    4390     PDMDEV_ASSERT_DEVINS(pDevIns);
    4391     pdmUnlock(pDevIns->Internal.s.pVMR3);
    4392 }
    4393 
    4394 
    4395 /** @copydoc PDMPCIHLPR3::pfnGetRCHelpers */
    4396 static DECLCALLBACK(PCPDMPCIHLPRC) pdmR3PciHlp_GetRCHelpers(PPDMDEVINS pDevIns)
    4397 {
    4398     PDMDEV_ASSERT_DEVINS(pDevIns);
    4399     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4400     RTRCPTR pRCHelpers = 0;
    4401     int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCPciHlp", &pRCHelpers);
    4402     AssertReleaseRC(rc);
    4403     AssertRelease(pRCHelpers);
    4404     LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n",
    4405              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRCHelpers));
    4406     return pRCHelpers;
    4407 }
    4408 
    4409 
    4410 /** @copydoc PDMPCIHLPR3::pfnGetR0Helpers */
    4411 static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns)
    4412 {
    4413     PDMDEV_ASSERT_DEVINS(pDevIns);
    4414     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
    4415     PCPDMPCIHLPR0 pR0Helpers = 0;
    4416     int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PciHlp", &pR0Helpers);
    4417     AssertReleaseRC(rc);
    4418     AssertRelease(pR0Helpers);
    4419     LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
    4420              pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
    4421     return pR0Helpers;
    4422 }
    4423 
    4424 
    4425733/**
    4426734 * Locates a LUN.
  • trunk/src/VBox/VMM/PDMInternal.h

    r12975 r12980  
    906906*******************************************************************************/
    907907#ifdef IN_RING3
    908 extern const PDMDRVHLP g_pdmR3DrvHlp;
     908extern const PDMDRVHLP      g_pdmR3DrvHlp;
     909extern const PDMDEVHLPR3    g_pdmR3DevHlpTrusted;
     910extern const PDMDEVHLPR3    g_pdmR3DevHlpUnTrusted;
     911extern const PDMPICHLPR3    g_pdmR3DevPicHlp;
     912extern const PDMAPICHLPR3   g_pdmR3DevApicHlp;
     913extern const PDMIOAPICHLPR3 g_pdmR3DevIoApicHlp;
     914extern const PDMPCIHLPR3    g_pdmR3DevPciHlp;
     915extern const PDMDMACHLP     g_pdmR3DevDmacHlp;
     916extern const PDMRTCHLP      g_pdmR3DevRtcHlp;
     917#endif
     918
     919
     920/*******************************************************************************
     921*   Defined Constants And Macros                                               *
     922*******************************************************************************/
     923/** @def PDMDEV_ASSERT_DEVINS
     924 * Asserts the validity of the device instance.
     925 */
     926#ifdef VBOX_STRICT
     927# define PDMDEV_ASSERT_DEVINS(pDevIns)   \
     928    do { \
     929        AssertPtr(pDevIns); \
     930        Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); \
     931        Assert(pDevIns->CTX_SUFF(pvInstanceData) == (void *)&pDevIns->achInstanceData[0]); \
     932    } while (0)
     933#else
     934# define PDMDEV_ASSERT_DEVINS(pDevIns)   do { } while (0)
    909935#endif
    910936
     
    923949PPDMDEV     pdmR3DevLookup(PVM pVM, const char *pszName);
    924950int         pdmR3DevFindLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMLUN *ppLun);
     951DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem);
    925952
    926953int         pdmR3UsbLoadModules(PVM pVM);
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