VirtualBox

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

Last change on this file since 2397 was 2291, checked in by vboxsync, 18 years ago

More ring-0/ring-3 type safety (callbacks and PDM symbol resolving).

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