VirtualBox

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

Last change on this file since 2705 was 2638, checked in by vboxsync, 18 years ago

fixed debug build

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