VirtualBox

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

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

Treat the instance node name as the instance number to make it simpler to address the devices using PDMR3QueryDeviceLun().

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