VirtualBox

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

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

pfnDriverAttach has to pass the real return value of pfnConstruct, not VINF_SUCCESS. I checked that every device is able to handle this correctly.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 168.8 KB
Line 
1/* $Id: PDMDevice.cpp 1858 2007-04-02 12:29:41Z 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, RTHCPTR 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, RTHCPTR 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->pvInstanceDataHC == (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", (void **)&pDevHlpR0);
543 AssertReleaseRCReturn(rc, rc);
544
545 rc = PDMR3QueueCreateInternal(pVM, sizeof(PDMDEVHLPTASK), 8, 0, pdmR3DevHlpQueueConsumer, true, &pVM->pdm.s.pDevHlpQueueHC);
546 AssertRCReturn(rc, rc);
547 pVM->pdm.s.pDevHlpQueueGC = PDMQueueGCPtr(pVM->pdm.s.pDevHlpQueueHC);
548
549
550 /*
551 * Initialize the callback structure.
552 */
553 PDMDEVREGCBINT RegCB;
554 RegCB.Core.u32Version = PDM_DEVREG_CB_VERSION;
555 RegCB.Core.pfnRegister = pdmR3DevReg_Register;
556 RegCB.Core.pfnMMHeapAlloc = pdmR3DevReg_MMHeapAlloc;
557 RegCB.pVM = pVM;
558
559 /*
560 * Load the builtin module
561 */
562 PCFGMNODE pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM/Devices");
563 bool fLoadBuiltin;
564 rc = CFGMR3QueryBool(pDevicesNode, "LoadBuiltin", &fLoadBuiltin);
565 if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
566 fLoadBuiltin = true;
567 else if (VBOX_FAILURE(rc))
568 {
569 AssertMsgFailed(("Configuration error: Querying boolean \"LoadBuiltin\" failed with %Vrc\n", rc));
570 return rc;
571 }
572 if (fLoadBuiltin)
573 {
574 /* make filename */
575 char *pszFilename = pdmR3FileR3("VBoxDD", /*fShared=*/true);
576 if (!pszFilename)
577 return VERR_NO_TMP_MEMORY;
578 rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD");
579 RTMemTmpFree(pszFilename);
580 if (VBOX_FAILURE(rc))
581 return rc;
582
583 /* make filename */
584 pszFilename = pdmR3FileR3("VBoxDD2", /*fShared=*/true);
585 if (!pszFilename)
586 return VERR_NO_TMP_MEMORY;
587 rc = pdmR3DevLoad(pVM, &RegCB, pszFilename, "VBoxDD2");
588 RTMemTmpFree(pszFilename);
589 if (VBOX_FAILURE(rc))
590 return rc;
591 }
592
593 /*
594 * Load additional device modules.
595 */
596 PCFGMNODE pCur;
597 for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
598 {
599 /*
600 * Get the name and path.
601 */
602 char szName[PDMMOD_NAME_LEN];
603 rc = CFGMR3GetName(pCur, &szName[0], sizeof(szName));
604 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
605 {
606 AssertMsgFailed(("configuration error: The module name is too long, cchName=%d.\n", CFGMR3GetNameLen(pCur)));
607 return VERR_PDM_MODULE_NAME_TOO_LONG;
608 }
609 else if (VBOX_FAILURE(rc))
610 {
611 AssertMsgFailed(("CFGMR3GetName -> %Vrc.\n", rc));
612 return rc;
613 }
614
615 /* the path is optional, if no path the module name + path is used. */
616 char szFilename[RTPATH_MAX];
617 rc = CFGMR3QueryString(pCur, "Path", &szFilename[0], sizeof(szFilename));
618 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
619 strcpy(szFilename, szName);
620 else if (VBOX_FAILURE(rc))
621 {
622 AssertMsgFailed(("configuration error: Failure to query the module path, rc=%Vrc.\n", rc));
623 return rc;
624 }
625
626 /* prepend path? */
627 if (!RTPathHavePath(szFilename))
628 {
629 char *psz = pdmR3FileR3(szFilename);
630 if (!psz)
631 return VERR_NO_TMP_MEMORY;
632 size_t cch = strlen(psz) + 1;
633 if (cch > sizeof(szFilename))
634 {
635 RTMemTmpFree(psz);
636 AssertMsgFailed(("Filename too long! cch=%d '%s'\n", cch, psz));
637 return VERR_FILENAME_TOO_LONG;
638 }
639 memcpy(szFilename, psz, cch);
640 RTMemTmpFree(psz);
641 }
642
643 /*
644 * Load the module and register it's devices.
645 */
646 rc = pdmR3DevLoad(pVM, &RegCB, szFilename, szName);
647 if (VBOX_FAILURE(rc))
648 return rc;
649 }
650
651
652 /*
653 *
654 * Enumerate the device instance configurations
655 * and come up with a instantiation order.
656 *
657 */
658 /* Switch to /Devices, which contains the device instantiations. */
659 pDevicesNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "Devices");
660
661 /*
662 * Count the device instances.
663 */
664 PCFGMNODE pInstanceNode;
665 unsigned cDevs = 0;
666 for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
667 for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
668 cDevs++;
669 if (!cDevs)
670 {
671 Log(("PDM: No devices were configured!\n"));
672 return VINF_SUCCESS;
673 }
674 Log2(("PDM: cDevs=%d!\n", cDevs));
675
676 /*
677 * Collect info on each device instance.
678 */
679 struct DEVORDER
680 {
681 /** Configuration node. */
682 PCFGMNODE pNode;
683 /** Pointer to device. */
684 PPDMDEV pDev;
685 /** VBox instance number. */
686 RTUINT iInstance;
687 /** Init order. */
688 uint32_t u32Order;
689 } *paDevs = (struct DEVORDER *)alloca(sizeof(paDevs[0]) * (cDevs + 1)); /* (One extra for swapping) */
690 Assert(paDevs);
691 unsigned i = 0;
692 for (pCur = CFGMR3GetFirstChild(pDevicesNode); pCur; pCur = CFGMR3GetNextChild(pCur))
693 {
694 RTUINT iInstance = 0;
695 for (pInstanceNode = CFGMR3GetFirstChild(pCur); pInstanceNode; pInstanceNode = CFGMR3GetNextChild(pInstanceNode))
696 {
697 /* basics */
698 paDevs[i].pNode = pInstanceNode;
699 paDevs[i].iInstance = iInstance;
700
701 /* Get the device name. */
702 char szName[sizeof(paDevs[0].pDev->pDevReg->szDeviceName)];
703 rc = CFGMR3GetName(pCur, szName, sizeof(szName));
704 if (VBOX_FAILURE(rc))
705 {
706 AssertMsgFailed(("Configuration error: device name is too long (or something)! rc=%Vrc\n", rc));
707 return rc;
708 }
709
710 /* Get the device. */
711 paDevs[i].pDev = pdmR3DevLookup(pVM, szName);
712 if (!paDevs[i].pDev)
713 {
714 AssertMsgFailed(("Configuration error: device '%s' not found!\n", szName));
715 return VERR_PDM_DEVICE_NOT_FOUND;
716 }
717
718 /* Configured priority or use default based on device class? */
719 rc = CFGMR3QueryU32(pCur, "Priority", &paDevs[i].u32Order);
720 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
721 {
722 uint32_t u32 = paDevs[i].pDev->pDevReg->fClass;
723 for (paDevs[i].u32Order = 1; !(u32 & paDevs[i].u32Order); paDevs[i].u32Order <<= 1)
724 /* nop */;
725 }
726 else if (VBOX_FAILURE(rc))
727 {
728 AssertMsgFailed(("Configuration error: reading \"Priority\" for the '%s' device failed rc=%Vrc!\n", szName, rc));
729 return rc;
730 }
731
732 /* next instance */
733 iInstance++;
734 i++;
735 } /* instances */
736 } /* devices */
737 Assert(i == cDevs);
738
739 /*
740 * Sort the device array ascending on u32Order. (bubble)
741 */
742 unsigned c = cDevs - 1;
743 while (c)
744 {
745 unsigned j = 0;
746 for (i = 0; i < c; i++)
747 if (paDevs[i].u32Order > paDevs[i + 1].u32Order)
748 {
749 paDevs[cDevs] = paDevs[i + 1];
750 paDevs[i + 1] = paDevs[i];
751 paDevs[i] = paDevs[cDevs];
752 j = i;
753 }
754 c = j;
755 }
756
757
758 /*
759 *
760 * Instantiate the devices.
761 *
762 */
763 for (i = 0; i < cDevs; i++)
764 {
765 /*
766 * Gather a bit of config.
767 */
768 /* trusted */
769 bool fTrusted;
770 rc = CFGMR3QueryBool(paDevs[i].pNode, "Trusted", &fTrusted);
771 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
772 fTrusted = false;
773 else if (VBOX_FAILURE(rc))
774 {
775 AssertMsgFailed(("configuration error: failed to query boolean \"Trusted\", rc=%Vrc\n", rc));
776 return rc;
777 }
778 /* config node */
779 PCFGMNODE pConfigNode = CFGMR3GetChild(paDevs[i].pNode, "Config");
780 if (!pConfigNode)
781 {
782 rc = CFGMR3InsertNode(paDevs[i].pNode, "Config", &pConfigNode);
783 if (VBOX_FAILURE(rc))
784 {
785 AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
786 return rc;
787 }
788 }
789 CFGMR3SetRestrictedRoot(pConfigNode);
790
791 /*
792 * Allocate the device instance.
793 */
794 size_t cb = RT_OFFSETOF(PDMDEVINS, achInstanceData[paDevs[i].pDev->pDevReg->cbInstance]);
795 cb = RT_ALIGN_Z(cb, 16);
796 PPDMDEVINS pDevIns;
797 if (paDevs[i].pDev->pDevReg->fFlags & (PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0))
798 rc = MMR3HyperAllocOnceNoRel(pVM, cb, 0, MM_TAG_PDM_DEVICE, (void **)&pDevIns);
799 else
800 rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_DEVICE, cb, (void **)&pDevIns);
801 if (VBOX_FAILURE(rc))
802 {
803 AssertMsgFailed(("Failed to allocate %d bytes of instance data for device '%s'. rc=%Vrc\n",
804 cb, paDevs[i].pDev->pDevReg->szDeviceName, rc));
805 return rc;
806 }
807
808 /*
809 * Initialize it.
810 */
811 pDevIns->u32Version = PDM_DEVINS_VERSION;
812 //pDevIns->Internal.s.pNextHC = NULL;
813 //pDevIns->Internal.s.pPerDeviceNextHC = NULL;
814 pDevIns->Internal.s.pDevHC = paDevs[i].pDev;
815 pDevIns->Internal.s.pVMHC = pVM;
816 pDevIns->Internal.s.pVMGC = pVM->pVMGC;
817 //pDevIns->Internal.s.pLunsHC = NULL;
818 pDevIns->Internal.s.pCfgHandle = paDevs[i].pNode;
819 //pDevIns->Internal.s.pPciDevice = NULL;
820 //pDevIns->Internal.s.pPciBus = NULL; /** @todo pci bus selection. (in 2008 perhaps) */
821 pDevIns->pDevHlp = fTrusted ? &g_pdmR3DevHlpTrusted : &g_pdmR3DevHlpUnTrusted;
822 pDevIns->pDevHlpGC = pDevHlpGC;
823 pDevIns->pDevHlpR0 = pDevHlpR0;
824 pDevIns->pDevReg = paDevs[i].pDev->pDevReg;
825 pDevIns->pCfgHandle = pConfigNode;
826 pDevIns->iInstance = paDevs[i].iInstance;
827 pDevIns->pvInstanceDataHC = &pDevIns->achInstanceData[0];
828 pDevIns->pvInstanceDataGC = pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC
829 ? MMHyperHC2GC(pVM, pDevIns->pvInstanceDataHC) : 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, RTHCPTR 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 PFNIOMIOPORTIN pfnR0PtrIn = 0;
1228 if (pszIn)
1229 {
1230 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszIn, (void **)&pfnR0PtrIn);
1231 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pDevReg->szR0Mod, pszIn));
1232 }
1233 PFNIOMIOPORTOUT pfnR0PtrOut = 0;
1234 if (pszOut && VBOX_SUCCESS(rc))
1235 {
1236 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszOut, (void **)&pfnR0PtrOut);
1237 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pDevReg->szR0Mod, pszOut));
1238 }
1239 PFNIOMIOPORTINSTRING pfnR0PtrInStr = 0;
1240 if (pszInStr && VBOX_SUCCESS(rc))
1241 {
1242 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszInStr, (void **)&pfnR0PtrInStr);
1243 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pDevReg->szR0Mod, pszInStr));
1244 }
1245 PFNIOMIOPORTOUTSTRING pfnR0PtrOutStr = 0;
1246 if (pszOutStr && VBOX_SUCCESS(rc))
1247 {
1248 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszOutStr, (void **)&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, RTHCPTR 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 PFNIOMMMIOWRITE pfnR0PtrWrite = 0;
1372 if (pszWrite)
1373 rc = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszWrite, (void **)&pfnR0PtrWrite);
1374 PFNIOMMMIOREAD pfnR0PtrRead = 0;
1375 int rc2 = VINF_SUCCESS;
1376 if (pszRead)
1377 rc2 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszRead, (void **)&pfnR0PtrRead);
1378 PFNIOMMMIOFILL pfnR0PtrFill = 0;
1379 int rc3 = VINF_SUCCESS;
1380 if (pszFill)
1381 rc3 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszFill, (void **)&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, (void **)&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, (void **)&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, (void **)&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, (void **)&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, (void **)&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, (void **)&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, (void **)&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, (void **)&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, (void **)&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, (void **)&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", (void **)&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", (void **)&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", (void **)&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", (void **)&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