VirtualBox

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.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • 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
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