VirtualBox

source: vbox/trunk/src/VBox/VMM/PDMDevice.cpp@ 12977

Last change on this file since 12977 was 12977, checked in by vboxsync, 16 years ago

#1865: Updated PDMDEVREG with pfnSoftReset, u32VersionEnd and some flag/name cleanups.

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

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