VirtualBox

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

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

GC Phys to HC virt conversion changes for dynamic RAM allocation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 168.7 KB
Line 
1/* $Id: PDMDevice.cpp 838 2007-02-12 12:05:52Z 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");
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");
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 return VINF_SUCCESS;
1954 }
1955
1956 /*
1957 * Free the driver.
1958 */
1959 pLun->pTop = NULL;
1960 ASMMemFill32(pNew, cb, 0xdeadd0d0);
1961 MMR3HeapFree(pNew);
1962 pDrv->cInstances--;
1963 }
1964 else
1965 {
1966 AssertMsgFailed(("Failed to allocate %d bytes for instantiating driver '%s'\n", cb, pszName));
1967 rc = VERR_NO_MEMORY;
1968 }
1969 }
1970 else
1971 AssertMsgFailed(("Failed to create Config node! rc=%Vrc\n", rc));
1972 }
1973 else
1974 {
1975 AssertMsgFailed(("Driver '%s' wasn't found!\n", pszName));
1976 rc = VERR_PDM_DRIVER_NOT_FOUND;
1977 }
1978 MMR3HeapFree(pszName);
1979 }
1980 else
1981 {
1982 AssertMsgFailed(("Query for string value of \"Driver\" -> %Vrc\n", rc));
1983 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1984 rc = VERR_PDM_CFG_MISSING_DRIVER_NAME;
1985 }
1986 }
1987 else
1988 rc = VERR_PDM_NO_ATTACHED_DRIVER;
1989
1990
1991 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
1992 return rc;
1993}
1994
1995
1996/** @copydoc PDMDEVHLP::pfnMMHeapAlloc */
1997static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
1998{
1999 PDMDEV_ASSERT_DEVINS(pDevIns);
2000 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
2001
2002 void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE_USER, cb);
2003
2004 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
2005 return pv;
2006}
2007
2008
2009/** @copydoc PDMDEVHLP::pfnMMHeapAllocZ */
2010static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
2011{
2012 PDMDEV_ASSERT_DEVINS(pDevIns);
2013 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cb));
2014
2015 void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE_USER, cb);
2016
2017 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
2018 return pv;
2019}
2020
2021
2022/** @copydoc PDMDEVHLP::pfnMMHeapFree */
2023static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
2024{
2025 PDMDEV_ASSERT_DEVINS(pDevIns);
2026 LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pv));
2027
2028 MMR3HeapFree(pv);
2029
2030 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
2031}
2032
2033
2034/** @copydoc PDMDEVHLP::pfnVMSetError */
2035static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
2036{
2037 PDMDEV_ASSERT_DEVINS(pDevIns);
2038 va_list args;
2039 va_start(args, pszFormat);
2040 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMHC, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
2041 va_end(args);
2042 return rc;
2043}
2044
2045
2046/** @copydoc PDMDEVHLP::pfnVMSetErrorV */
2047static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
2048{
2049 PDMDEV_ASSERT_DEVINS(pDevIns);
2050 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMHC, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
2051 return rc;
2052}
2053
2054
2055/** @copydoc PDMDEVHLP::pfnAssertEMT */
2056static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2057{
2058 PDMDEV_ASSERT_DEVINS(pDevIns);
2059 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC))
2060 return true;
2061
2062 char szMsg[100];
2063 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
2064 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
2065 AssertBreakpoint();
2066 return false;
2067}
2068
2069
2070/** @copydoc PDMDEVHLP::pfnAssertOther */
2071static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
2072{
2073 PDMDEV_ASSERT_DEVINS(pDevIns);
2074 if (!VM_IS_EMT(pDevIns->Internal.s.pVMHC))
2075 return true;
2076
2077 char szMsg[100];
2078 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance);
2079 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
2080 AssertBreakpoint();
2081 return false;
2082}
2083
2084
2085/** @copydoc PDMDEVHLP::pfnDBGFStopV */
2086static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
2087{
2088 PDMDEV_ASSERT_DEVINS(pDevIns);
2089 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
2090 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &args));
2091
2092 PVM pVM = pDevIns->Internal.s.pVMHC;
2093 VM_ASSERT_EMT(pVM);
2094 int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
2095
2096 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2097 return rc;
2098}
2099
2100
2101/** @copydoc PDMDEVHLP::pfnDBGFInfoRegister */
2102static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
2103{
2104 PDMDEV_ASSERT_DEVINS(pDevIns);
2105 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
2106 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
2107
2108 PVM pVM = pDevIns->Internal.s.pVMHC;
2109 VM_ASSERT_EMT(pVM);
2110 int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
2111
2112 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2113 return rc;
2114}
2115
2116
2117/** @copydoc PDMDEVHLP::pfnSTAMRegister */
2118static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
2119{
2120 PDMDEV_ASSERT_DEVINS(pDevIns);
2121 PVM pVM = pDevIns->Internal.s.pVMHC;
2122 VM_ASSERT_EMT(pVM);
2123
2124 STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);
2125 NOREF(pVM);
2126}
2127
2128
2129
2130/** @copydoc PDMDEVHLP::pfnSTAMRegisterF */
2131static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
2132 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
2133{
2134 PDMDEV_ASSERT_DEVINS(pDevIns);
2135 PVM pVM = pDevIns->Internal.s.pVMHC;
2136 VM_ASSERT_EMT(pVM);
2137
2138 va_list args;
2139 va_start(args, pszName);
2140 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
2141 va_end(args);
2142 AssertRC(rc);
2143
2144 NOREF(pVM);
2145}
2146
2147
2148/** @copydoc PDMDEVHLP::pfnSTAMRegisterV */
2149static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
2150 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
2151{
2152 PDMDEV_ASSERT_DEVINS(pDevIns);
2153 PVM pVM = pDevIns->Internal.s.pVMHC;
2154 VM_ASSERT_EMT(pVM);
2155
2156 int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
2157 AssertRC(rc);
2158
2159 NOREF(pVM);
2160}
2161
2162
2163/** @copydoc PDMDEVHLP::pfnRTCRegister */
2164static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
2165{
2166 PDMDEV_ASSERT_DEVINS(pDevIns);
2167 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2168 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
2169 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
2170 pRtcReg->pfnWrite, ppRtcHlp));
2171
2172 /*
2173 * Validate input.
2174 */
2175 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
2176 {
2177 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
2178 PDM_RTCREG_VERSION));
2179 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (version)\n",
2180 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2181 return VERR_INVALID_PARAMETER;
2182 }
2183 if ( !pRtcReg->pfnWrite
2184 || !pRtcReg->pfnRead)
2185 {
2186 Assert(pRtcReg->pfnWrite);
2187 Assert(pRtcReg->pfnRead);
2188 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
2189 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2190 return VERR_INVALID_PARAMETER;
2191 }
2192
2193 if (!ppRtcHlp)
2194 {
2195 Assert(ppRtcHlp);
2196 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc (ppRtcHlp)\n",
2197 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2198 return VERR_INVALID_PARAMETER;
2199 }
2200
2201 /*
2202 * Only one DMA device.
2203 */
2204 PVM pVM = pDevIns->Internal.s.pVMHC;
2205 if (pVM->pdm.s.pRtc)
2206 {
2207 AssertMsgFailed(("Only one RTC device is supported!\n"));
2208 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
2209 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2210 return VERR_INVALID_PARAMETER;
2211 }
2212
2213 /*
2214 * Allocate and initialize pci bus structure.
2215 */
2216 int rc = VINF_SUCCESS;
2217 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
2218 if (pRtc)
2219 {
2220 pRtc->pDevIns = pDevIns;
2221 pRtc->Reg = *pRtcReg;
2222 pVM->pdm.s.pRtc = pRtc;
2223
2224 /* set the helper pointer. */
2225 *ppRtcHlp = &g_pdmR3DevRtcHlp;
2226 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
2227 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2228 }
2229 else
2230 rc = VERR_NO_MEMORY;
2231
2232 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Vrc\n",
2233 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2234 return rc;
2235}
2236
2237
2238/** @copydoc PDMDEVHLP::pfnPDMQueueCreate */
2239static DECLCALLBACK(int) pdmR3DevHlp_PDMQueueCreate(PPDMDEVINS pDevIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
2240 PFNPDMQUEUEDEV pfnCallback, bool fGCEnabled, PPDMQUEUE *ppQueue)
2241{
2242 PDMDEV_ASSERT_DEVINS(pDevIns);
2243 LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fGCEnabled=%RTbool ppQueue=%p\n",
2244 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue));
2245
2246 PVM pVM = pDevIns->Internal.s.pVMHC;
2247 VM_ASSERT_EMT(pVM);
2248 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fGCEnabled, ppQueue);
2249
2250 LogFlow(("pdmR3DevHlp_PDMQueueCreate: caller='%s'/%d: returns %Vrc *ppQueue=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppQueue));
2251 return rc;
2252}
2253
2254
2255/** @copydoc PDMDEVHLP::pfnCritSectInit */
2256static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, const char *pszName)
2257{
2258 PDMDEV_ASSERT_DEVINS(pDevIns);
2259 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%p:{%s}\n",
2260 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pCritSect, pszName, pszName));
2261
2262 PVM pVM = pDevIns->Internal.s.pVMHC;
2263 VM_ASSERT_EMT(pVM);
2264 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, pszName);
2265
2266 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2267 return rc;
2268}
2269
2270
2271/** @copydoc PDMDEVHLP::pfnGetVM */
2272static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
2273{
2274 PDMDEV_ASSERT_DEVINS(pDevIns);
2275 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns->Internal.s.pVMHC));
2276 return pDevIns->Internal.s.pVMHC;
2277}
2278
2279
2280/** @copydoc PDMDEVHLP::pfnPCIBusRegister */
2281static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
2282{
2283 PDMDEV_ASSERT_DEVINS(pDevIns);
2284 PVM pVM = pDevIns->Internal.s.pVMHC;
2285 VM_ASSERT_EMT(pVM);
2286 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterHC=%p, .pfnIORegionRegisterHC=%p, .pfnSetIrqHC=%p, "
2287 ".pfnSaveExecHC=%p, .pfnLoadExecHC=%p, .pfnFakePCIBIOSHC=%p, .pszSetIrqGC=%p:{%s}} ppPciHlpR3=%p\n",
2288 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterHC,
2289 pPciBusReg->pfnIORegionRegisterHC, pPciBusReg->pfnSetIrqHC, pPciBusReg->pfnSaveExecHC, pPciBusReg->pfnLoadExecHC,
2290 pPciBusReg->pfnFakePCIBIOSHC, pPciBusReg->pszSetIrqGC, pPciBusReg->pszSetIrqGC, ppPciHlpR3));
2291
2292 /*
2293 * Validate the structure.
2294 */
2295 if (pPciBusReg->u32Version != PDM_PCIBUSREG_VERSION)
2296 {
2297 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREG_VERSION));
2298 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2299 return VERR_INVALID_PARAMETER;
2300 }
2301 if ( !pPciBusReg->pfnRegisterHC
2302 || !pPciBusReg->pfnIORegionRegisterHC
2303 || !pPciBusReg->pfnSetIrqHC
2304 || !pPciBusReg->pfnSaveExecHC
2305 || !pPciBusReg->pfnLoadExecHC
2306 || !pPciBusReg->pfnFakePCIBIOSHC)
2307 {
2308 Assert(pPciBusReg->pfnRegisterHC);
2309 Assert(pPciBusReg->pfnIORegionRegisterHC);
2310 Assert(pPciBusReg->pfnSetIrqHC);
2311 Assert(pPciBusReg->pfnSaveExecHC);
2312 Assert(pPciBusReg->pfnLoadExecHC);
2313 Assert(pPciBusReg->pfnFakePCIBIOSHC);
2314 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2315 return VERR_INVALID_PARAMETER;
2316 }
2317 if ( pPciBusReg->pszSetIrqGC
2318 && !VALID_PTR(pPciBusReg->pszSetIrqGC))
2319 {
2320 Assert(VALID_PTR(pPciBusReg->pszSetIrqGC));
2321 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2322 return VERR_INVALID_PARAMETER;
2323 }
2324 if ( pPciBusReg->pszSetIrqR0
2325 && !VALID_PTR(pPciBusReg->pszSetIrqR0))
2326 {
2327 Assert(VALID_PTR(pPciBusReg->pszSetIrqR0));
2328 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2329 return VERR_INVALID_PARAMETER;
2330 }
2331 if (!ppPciHlpR3)
2332 {
2333 Assert(ppPciHlpR3);
2334 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (ppPciHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2335 return VERR_INVALID_PARAMETER;
2336 }
2337
2338 /*
2339 * Find free PCI bus entry.
2340 */
2341 unsigned iBus = 0;
2342 for (iBus = 0; iBus < ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
2343 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
2344 break;
2345 if (iBus >= ELEMENTS(pVM->pdm.s.aPciBuses))
2346 {
2347 AssertMsgFailed(("Too many PCI buses. Max=%u\n", ELEMENTS(pVM->pdm.s.aPciBuses)));
2348 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc (pci bus)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2349 return VERR_INVALID_PARAMETER;
2350 }
2351 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
2352
2353 /*
2354 * Resolve and init the GC bits.
2355 */
2356 if (pPciBusReg->pszSetIrqGC)
2357 {
2358 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPciBusReg->pszSetIrqGC, &pPciBus->pfnSetIrqGC);
2359 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pPciBusReg->pszSetIrqGC, rc));
2360 if (VBOX_FAILURE(rc))
2361 {
2362 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2363 return rc;
2364 }
2365 pPciBus->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2366 }
2367 else
2368 {
2369 pPciBus->pfnSetIrqGC = 0;
2370 pPciBus->pDevInsGC = 0;
2371 }
2372
2373 /*
2374 * Resolve and init the R0 bits.
2375 */
2376 if ( HWACCMR3IsAllowed(pVM)
2377 && pPciBusReg->pszSetIrqR0)
2378 {
2379 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, (void **)&pPciBus->pfnSetIrqR0);
2380 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPciBusReg->pszSetIrqR0, rc));
2381 if (VBOX_FAILURE(rc))
2382 {
2383 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2384 return rc;
2385 }
2386 pPciBus->pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2387 }
2388 else
2389 {
2390 pPciBus->pfnSetIrqR0 = 0;
2391 pPciBus->pDevInsR0 = 0;
2392 }
2393
2394 /*
2395 * Init the HC bits.
2396 */
2397 pPciBus->iBus = iBus;
2398 pPciBus->pDevInsR3 = pDevIns;
2399 pPciBus->pfnRegisterR3 = pPciBusReg->pfnRegisterHC;
2400 pPciBus->pfnIORegionRegisterR3 = pPciBusReg->pfnIORegionRegisterHC;
2401 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqHC;
2402 pPciBus->pfnSaveExecR3 = pPciBusReg->pfnSaveExecHC;
2403 pPciBus->pfnLoadExecR3 = pPciBusReg->pfnLoadExecHC;
2404 pPciBus->pfnFakePCIBIOSR3 = pPciBusReg->pfnFakePCIBIOSHC;
2405
2406 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2407
2408 /* set the helper pointer and return. */
2409 *ppPciHlpR3 = &g_pdmR3DevPciHlp;
2410 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2411 return VINF_SUCCESS;
2412}
2413
2414
2415/** @copydoc PDMDEVHLP::pfnPICRegister */
2416static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
2417{
2418 PDMDEV_ASSERT_DEVINS(pDevIns);
2419 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2420 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrqHC=%p, .pfnGetInterruptHC=%p, .pszGetIrqGC=%p:{%s}, .pszGetInterruptGC=%p:{%s}} ppPicHlpR3=%p\n",
2421 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqHC, pPicReg->pfnGetInterruptHC,
2422 pPicReg->pszSetIrqGC, pPicReg->pszSetIrqGC, pPicReg->pszGetInterruptGC, pPicReg->pszGetInterruptGC, ppPicHlpR3));
2423
2424 /*
2425 * Validate input.
2426 */
2427 if (pPicReg->u32Version != PDM_PICREG_VERSION)
2428 {
2429 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
2430 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2431 return VERR_INVALID_PARAMETER;
2432 }
2433 if ( !pPicReg->pfnSetIrqHC
2434 || !pPicReg->pfnGetInterruptHC)
2435 {
2436 Assert(pPicReg->pfnSetIrqHC);
2437 Assert(pPicReg->pfnGetInterruptHC);
2438 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2439 return VERR_INVALID_PARAMETER;
2440 }
2441 if ( ( pPicReg->pszSetIrqGC
2442 || pPicReg->pszGetInterruptGC)
2443 && ( !VALID_PTR(pPicReg->pszSetIrqGC)
2444 || !VALID_PTR(pPicReg->pszGetInterruptGC))
2445 )
2446 {
2447 Assert(VALID_PTR(pPicReg->pszSetIrqGC));
2448 Assert(VALID_PTR(pPicReg->pszGetInterruptGC));
2449 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2450 return VERR_INVALID_PARAMETER;
2451 }
2452 if ( pPicReg->pszSetIrqGC
2453 && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC))
2454 {
2455 Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_GC);
2456 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (GC flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2457 return VERR_INVALID_PARAMETER;
2458 }
2459 if ( pPicReg->pszSetIrqR0
2460 && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0))
2461 {
2462 Assert(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_R0);
2463 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (R0 flag)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2464 return VERR_INVALID_PARAMETER;
2465 }
2466 if (!ppPicHlpR3)
2467 {
2468 Assert(ppPicHlpR3);
2469 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc (ppPicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2470 return VERR_INVALID_PARAMETER;
2471 }
2472
2473 /*
2474 * Only one PIC device.
2475 */
2476 PVM pVM = pDevIns->Internal.s.pVMHC;
2477 if (pVM->pdm.s.Pic.pDevInsR3)
2478 {
2479 AssertMsgFailed(("Only one pic device is supported!\n"));
2480 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2481 return VERR_INVALID_PARAMETER;
2482 }
2483
2484 /*
2485 * GC stuff.
2486 */
2487 if (pPicReg->pszSetIrqGC)
2488 {
2489 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPicReg->pszSetIrqGC, &pVM->pdm.s.Pic.pfnSetIrqGC);
2490 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pPicReg->pszSetIrqGC, rc));
2491 if (VBOX_SUCCESS(rc))
2492 {
2493 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pPicReg->pszGetInterruptGC, &pVM->pdm.s.Pic.pfnGetInterruptGC);
2494 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pPicReg->pszGetInterruptGC, rc));
2495 }
2496 if (VBOX_FAILURE(rc))
2497 {
2498 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2499 return rc;
2500 }
2501 pVM->pdm.s.Pic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2502 }
2503 else
2504 {
2505 pVM->pdm.s.Pic.pDevInsGC = 0;
2506 pVM->pdm.s.Pic.pfnSetIrqGC = 0;
2507 pVM->pdm.s.Pic.pfnGetInterruptGC = 0;
2508 }
2509
2510 /*
2511 * R0 stuff.
2512 */
2513 if ( HWACCMR3IsAllowed(pVM)
2514 && pPicReg->pszSetIrqR0)
2515 {
2516 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, (void **)&pVM->pdm.s.Pic.pfnSetIrqR0);
2517 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszSetIrqR0, rc));
2518 if (VBOX_SUCCESS(rc))
2519 {
2520 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, (void **)&pVM->pdm.s.Pic.pfnGetInterruptR0);
2521 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pPicReg->pszGetInterruptR0, rc));
2522 }
2523 if (VBOX_FAILURE(rc))
2524 {
2525 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2526 return rc;
2527 }
2528 pVM->pdm.s.Pic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2529 Assert(pVM->pdm.s.Pic.pDevInsR0);
2530 }
2531 else
2532 {
2533 pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
2534 pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
2535 pVM->pdm.s.Pic.pDevInsR0 = 0;
2536 }
2537
2538 /*
2539 * HC stuff.
2540 */
2541 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
2542 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqHC;
2543 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptHC;
2544 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2545
2546 /* set the helper pointer and return. */
2547 *ppPicHlpR3 = &g_pdmR3DevPicHlp;
2548 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2549 return VINF_SUCCESS;
2550}
2551
2552
2553/** @copydoc PDMDEVHLP::pfnAPICRegister */
2554static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
2555{
2556 PDMDEV_ASSERT_DEVINS(pDevIns);
2557 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2558 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: pApicReg=%p:{.u32Version=%#x, .pfnGetInterruptHC=%p, .pfnSetBaseHC=%p, .pfnGetBaseHC=%p, "
2559 ".pfnSetTPRHC=%p, .pfnGetTPRHC=%p, .pfnBusDeliverHC=%p, pszGetInterruptGC=%p:{%s}, pszSetBaseGC=%p:{%s}, pszGetBaseGC=%p:{%s}, "
2560 ".pszSetTPRGC=%p:{%s}, .pszGetTPRGC=%p:{%s}, .pszBusDeliverGC=%p:{%s}} ppApicHlpR3=%p\n",
2561 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pApicReg, pApicReg->u32Version, pApicReg->pfnGetInterruptHC, pApicReg->pfnSetBaseHC,
2562 pApicReg->pfnGetBaseHC, pApicReg->pfnSetTPRHC, pApicReg->pfnGetTPRHC, pApicReg->pfnBusDeliverHC, pApicReg->pszGetInterruptGC,
2563 pApicReg->pszGetInterruptGC, pApicReg->pszSetBaseGC, pApicReg->pszSetBaseGC, pApicReg->pszGetBaseGC, pApicReg->pszGetBaseGC,
2564 pApicReg->pszSetTPRGC, pApicReg->pszSetTPRGC, pApicReg->pszGetTPRGC, pApicReg->pszGetTPRGC, pApicReg->pszBusDeliverGC,
2565 pApicReg->pszBusDeliverGC, ppApicHlpR3));
2566
2567 /*
2568 * Validate input.
2569 */
2570 if (pApicReg->u32Version != PDM_APICREG_VERSION)
2571 {
2572 AssertMsgFailed(("u32Version=%#x expected %#x\n", pApicReg->u32Version, PDM_APICREG_VERSION));
2573 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2574 return VERR_INVALID_PARAMETER;
2575 }
2576 if ( !pApicReg->pfnGetInterruptHC
2577 || !pApicReg->pfnSetBaseHC
2578 || !pApicReg->pfnGetBaseHC
2579 || !pApicReg->pfnSetTPRHC
2580 || !pApicReg->pfnGetTPRHC
2581 || !pApicReg->pfnBusDeliverHC)
2582 {
2583 Assert(pApicReg->pfnGetInterruptHC);
2584 Assert(pApicReg->pfnSetBaseHC);
2585 Assert(pApicReg->pfnGetBaseHC);
2586 Assert(pApicReg->pfnSetTPRHC);
2587 Assert(pApicReg->pfnGetTPRHC);
2588 Assert(pApicReg->pfnBusDeliverHC);
2589 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2590 return VERR_INVALID_PARAMETER;
2591 }
2592 if ( ( pApicReg->pszGetInterruptGC
2593 || pApicReg->pszSetBaseGC
2594 || pApicReg->pszGetBaseGC
2595 || pApicReg->pszSetTPRGC
2596 || pApicReg->pszGetTPRGC
2597 || pApicReg->pszBusDeliverGC)
2598 && ( !VALID_PTR(pApicReg->pszGetInterruptGC)
2599 || !VALID_PTR(pApicReg->pszSetBaseGC)
2600 || !VALID_PTR(pApicReg->pszGetBaseGC)
2601 || !VALID_PTR(pApicReg->pszSetTPRGC)
2602 || !VALID_PTR(pApicReg->pszGetTPRGC)
2603 || !VALID_PTR(pApicReg->pszBusDeliverGC))
2604 )
2605 {
2606 Assert(VALID_PTR(pApicReg->pszGetInterruptGC));
2607 Assert(VALID_PTR(pApicReg->pszSetBaseGC));
2608 Assert(VALID_PTR(pApicReg->pszGetBaseGC));
2609 Assert(VALID_PTR(pApicReg->pszSetTPRGC));
2610 Assert(VALID_PTR(pApicReg->pszGetTPRGC));
2611 Assert(VALID_PTR(pApicReg->pszBusDeliverGC));
2612 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2613 return VERR_INVALID_PARAMETER;
2614 }
2615 if ( ( pApicReg->pszGetInterruptR0
2616 || pApicReg->pszSetBaseR0
2617 || pApicReg->pszGetBaseR0
2618 || pApicReg->pszSetTPRR0
2619 || pApicReg->pszGetTPRR0
2620 || pApicReg->pszBusDeliverR0)
2621 && ( !VALID_PTR(pApicReg->pszGetInterruptR0)
2622 || !VALID_PTR(pApicReg->pszSetBaseR0)
2623 || !VALID_PTR(pApicReg->pszGetBaseR0)
2624 || !VALID_PTR(pApicReg->pszSetTPRR0)
2625 || !VALID_PTR(pApicReg->pszGetTPRR0)
2626 || !VALID_PTR(pApicReg->pszBusDeliverR0))
2627 )
2628 {
2629 Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
2630 Assert(VALID_PTR(pApicReg->pszSetBaseR0));
2631 Assert(VALID_PTR(pApicReg->pszGetBaseR0));
2632 Assert(VALID_PTR(pApicReg->pszSetTPRR0));
2633 Assert(VALID_PTR(pApicReg->pszGetTPRR0));
2634 Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
2635 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2636 return VERR_INVALID_PARAMETER;
2637 }
2638 if (!ppApicHlpR3)
2639 {
2640 Assert(ppApicHlpR3);
2641 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2642 return VERR_INVALID_PARAMETER;
2643 }
2644
2645 /*
2646 * Only one APIC device. (malc: only in UP case actually)
2647 */
2648 PVM pVM = pDevIns->Internal.s.pVMHC;
2649 if (pVM->pdm.s.Apic.pDevInsR3)
2650 {
2651 AssertMsgFailed(("Only one apic device is supported!\n"));
2652 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2653 return VERR_INVALID_PARAMETER;
2654 }
2655
2656 /*
2657 * Resolve & initialize the GC bits.
2658 */
2659 if (pApicReg->pszGetInterruptGC)
2660 {
2661 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetInterruptGC, &pVM->pdm.s.Apic.pfnGetInterruptGC);
2662 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetInterruptGC, rc));
2663 if (RT_SUCCESS(rc))
2664 {
2665 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetBaseGC, &pVM->pdm.s.Apic.pfnSetBaseGC);
2666 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszSetBaseGC, rc));
2667 }
2668 if (RT_SUCCESS(rc))
2669 {
2670 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetBaseGC, &pVM->pdm.s.Apic.pfnGetBaseGC);
2671 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetBaseGC, rc));
2672 }
2673 if (RT_SUCCESS(rc))
2674 {
2675 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetTPRGC, &pVM->pdm.s.Apic.pfnSetTPRGC);
2676 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszSetTPRGC, rc));
2677 }
2678 if (RT_SUCCESS(rc))
2679 {
2680 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetTPRGC, &pVM->pdm.s.Apic.pfnGetTPRGC);
2681 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetTPRGC, rc));
2682 }
2683 if (RT_SUCCESS(rc))
2684 {
2685 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszBusDeliverGC, &pVM->pdm.s.Apic.pfnBusDeliverGC);
2686 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszBusDeliverGC, rc));
2687 }
2688 if (VBOX_FAILURE(rc))
2689 {
2690 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2691 return rc;
2692 }
2693 pVM->pdm.s.Apic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2694 }
2695 else
2696 {
2697 pVM->pdm.s.Apic.pDevInsGC = 0;
2698 pVM->pdm.s.Apic.pfnGetInterruptGC = 0;
2699 pVM->pdm.s.Apic.pfnSetBaseGC = 0;
2700 pVM->pdm.s.Apic.pfnGetBaseGC = 0;
2701 pVM->pdm.s.Apic.pfnSetTPRGC = 0;
2702 pVM->pdm.s.Apic.pfnGetTPRGC = 0;
2703 pVM->pdm.s.Apic.pfnBusDeliverGC = 0;
2704 }
2705
2706 /*
2707 * Resolve & initialize the R0 bits.
2708 */
2709 if ( HWACCMR3IsAllowed(pVM)
2710 && pApicReg->pszGetInterruptR0)
2711 {
2712 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, (void **)&pVM->pdm.s.Apic.pfnGetInterruptR0);
2713 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
2714 if (RT_SUCCESS(rc))
2715 {
2716 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, (void **)&pVM->pdm.s.Apic.pfnSetBaseR0);
2717 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
2718 }
2719 if (RT_SUCCESS(rc))
2720 {
2721 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, (void **)&pVM->pdm.s.Apic.pfnGetBaseR0);
2722 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
2723 }
2724 if (RT_SUCCESS(rc))
2725 {
2726 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, (void **)&pVM->pdm.s.Apic.pfnSetTPRR0);
2727 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
2728 }
2729 if (RT_SUCCESS(rc))
2730 {
2731 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, (void **)&pVM->pdm.s.Apic.pfnGetTPRR0);
2732 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
2733 }
2734 if (RT_SUCCESS(rc))
2735 {
2736 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, (void **)&pVM->pdm.s.Apic.pfnBusDeliverR0);
2737 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
2738 }
2739 if (VBOX_FAILURE(rc))
2740 {
2741 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2742 return rc;
2743 }
2744 pVM->pdm.s.Apic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2745 Assert(pVM->pdm.s.Apic.pDevInsR0);
2746 }
2747 else
2748 {
2749 pVM->pdm.s.Apic.pfnGetInterruptR0 = 0;
2750 pVM->pdm.s.Apic.pfnSetBaseR0 = 0;
2751 pVM->pdm.s.Apic.pfnGetBaseR0 = 0;
2752 pVM->pdm.s.Apic.pfnSetTPRR0 = 0;
2753 pVM->pdm.s.Apic.pfnGetTPRR0 = 0;
2754 pVM->pdm.s.Apic.pfnBusDeliverR0 = 0;
2755 pVM->pdm.s.Apic.pDevInsR0 = 0;
2756 }
2757
2758 /*
2759 * Initialize the HC bits.
2760 */
2761 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
2762 pVM->pdm.s.Apic.pfnGetInterruptR3 = pApicReg->pfnGetInterruptHC;
2763 pVM->pdm.s.Apic.pfnSetBaseR3 = pApicReg->pfnSetBaseHC;
2764 pVM->pdm.s.Apic.pfnGetBaseR3 = pApicReg->pfnGetBaseHC;
2765 pVM->pdm.s.Apic.pfnSetTPRR3 = pApicReg->pfnSetTPRHC;
2766 pVM->pdm.s.Apic.pfnGetTPRR3 = pApicReg->pfnGetTPRHC;
2767 pVM->pdm.s.Apic.pfnBusDeliverR3 = pApicReg->pfnBusDeliverHC;
2768 Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2769
2770 /* set the helper pointer and return. */
2771 *ppApicHlpR3 = &g_pdmR3DevApicHlp;
2772 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2773 return VINF_SUCCESS;
2774}
2775
2776
2777/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
2778static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
2779{
2780 PDMDEV_ASSERT_DEVINS(pDevIns);
2781 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2782 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqHC=%p, .pszSetIrqGC=%p:{%s}} ppIoApicHlpR3=%p\n",
2783 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqHC, pIoApicReg->pszSetIrqGC,
2784 pIoApicReg->pszSetIrqGC, ppIoApicHlpR3));
2785
2786 /*
2787 * Validate input.
2788 */
2789 if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
2790 {
2791 AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
2792 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2793 return VERR_INVALID_PARAMETER;
2794 }
2795 if (!pIoApicReg->pfnSetIrqHC)
2796 {
2797 Assert(pIoApicReg->pfnSetIrqHC);
2798 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2799 return VERR_INVALID_PARAMETER;
2800 }
2801 if ( pIoApicReg->pszSetIrqGC
2802 && !VALID_PTR(pIoApicReg->pszSetIrqGC))
2803 {
2804 Assert(VALID_PTR(pIoApicReg->pszSetIrqGC));
2805 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2806 return VERR_INVALID_PARAMETER;
2807 }
2808 if ( pIoApicReg->pszSetIrqR0
2809 && !VALID_PTR(pIoApicReg->pszSetIrqR0))
2810 {
2811 Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
2812 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2813 return VERR_INVALID_PARAMETER;
2814 }
2815 if (!ppIoApicHlpR3)
2816 {
2817 Assert(ppIoApicHlpR3);
2818 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2819 return VERR_INVALID_PARAMETER;
2820 }
2821
2822 /*
2823 * The I/O APIC requires the APIC to be present (hacks++).
2824 * If the I/O APIC does GC stuff so must the APIC.
2825 */
2826 PVM pVM = pDevIns->Internal.s.pVMHC;
2827 if (!pVM->pdm.s.Apic.pDevInsR3)
2828 {
2829 AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
2830 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2831 return VERR_INVALID_PARAMETER;
2832 }
2833 if ( pIoApicReg->pszSetIrqGC
2834 && !pVM->pdm.s.Apic.pDevInsGC)
2835 {
2836 AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
2837 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2838 return VERR_INVALID_PARAMETER;
2839 }
2840
2841 /*
2842 * Only one I/O APIC device.
2843 */
2844 if (pVM->pdm.s.IoApic.pDevInsR3)
2845 {
2846 AssertMsgFailed(("Only one ioapic device is supported!\n"));
2847 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2848 return VERR_INVALID_PARAMETER;
2849 }
2850
2851 /*
2852 * Resolve & initialize the GC bits.
2853 */
2854 if (pIoApicReg->pszSetIrqGC)
2855 {
2856 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pIoApicReg->pszSetIrqGC, &pVM->pdm.s.IoApic.pfnSetIrqGC);
2857 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pIoApicReg->pszSetIrqGC, rc));
2858 if (VBOX_FAILURE(rc))
2859 {
2860 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2861 return rc;
2862 }
2863 pVM->pdm.s.IoApic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2864 }
2865 else
2866 {
2867 pVM->pdm.s.IoApic.pDevInsGC = 0;
2868 pVM->pdm.s.IoApic.pfnSetIrqGC = 0;
2869 }
2870
2871 /*
2872 * Resolve & initialize the R0 bits.
2873 */
2874 if ( HWACCMR3IsAllowed(pVM)
2875 && pIoApicReg->pszSetIrqR0)
2876 {
2877 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, (void **)&pVM->pdm.s.IoApic.pfnSetIrqR0);
2878 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
2879 if (VBOX_FAILURE(rc))
2880 {
2881 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2882 return rc;
2883 }
2884 pVM->pdm.s.IoApic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2885 Assert(pVM->pdm.s.IoApic.pDevInsR0);
2886 }
2887 else
2888 {
2889 pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
2890 pVM->pdm.s.IoApic.pDevInsR0 = 0;
2891 }
2892
2893 /*
2894 * Initialize the HC bits.
2895 */
2896 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
2897 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqHC;
2898 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2899
2900 /* set the helper pointer and return. */
2901 *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
2902 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2903 return VINF_SUCCESS;
2904}
2905
2906
2907/** @copydoc PDMDEVHLP::pfnDMACRegister */
2908static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
2909{
2910 PDMDEV_ASSERT_DEVINS(pDevIns);
2911 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2912 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",
2913 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
2914 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
2915
2916 /*
2917 * Validate input.
2918 */
2919 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
2920 {
2921 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
2922 PDM_DMACREG_VERSION));
2923 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
2924 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2925 return VERR_INVALID_PARAMETER;
2926 }
2927 if ( !pDmacReg->pfnRun
2928 || !pDmacReg->pfnRegister
2929 || !pDmacReg->pfnReadMemory
2930 || !pDmacReg->pfnWriteMemory
2931 || !pDmacReg->pfnSetDREQ
2932 || !pDmacReg->pfnGetChannelMode)
2933 {
2934 Assert(pDmacReg->pfnRun);
2935 Assert(pDmacReg->pfnRegister);
2936 Assert(pDmacReg->pfnReadMemory);
2937 Assert(pDmacReg->pfnWriteMemory);
2938 Assert(pDmacReg->pfnSetDREQ);
2939 Assert(pDmacReg->pfnGetChannelMode);
2940 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
2941 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2942 return VERR_INVALID_PARAMETER;
2943 }
2944
2945 if (!ppDmacHlp)
2946 {
2947 Assert(ppDmacHlp);
2948 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
2949 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2950 return VERR_INVALID_PARAMETER;
2951 }
2952
2953 /*
2954 * Only one DMA device.
2955 */
2956 PVM pVM = pDevIns->Internal.s.pVMHC;
2957 if (pVM->pdm.s.pDmac)
2958 {
2959 AssertMsgFailed(("Only one DMA device is supported!\n"));
2960 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
2961 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2962 return VERR_INVALID_PARAMETER;
2963 }
2964
2965 /*
2966 * Allocate and initialize pci bus structure.
2967 */
2968 int rc = VINF_SUCCESS;
2969 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
2970 if (pDmac)
2971 {
2972 pDmac->pDevIns = pDevIns;
2973 pDmac->Reg = *pDmacReg;
2974 pVM->pdm.s.pDmac = pDmac;
2975
2976 /* set the helper pointer. */
2977 *ppDmacHlp = &g_pdmR3DevDmacHlp;
2978 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
2979 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2980 }
2981 else
2982 rc = VERR_NO_MEMORY;
2983
2984 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
2985 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2986 return rc;
2987}
2988
2989
2990/** @copydoc PDMDEVHLP::pfnPhysRead */
2991static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
2992{
2993 PDMDEV_ASSERT_DEVINS(pDevIns);
2994 LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
2995 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
2996
2997 /*
2998 * For the convenience of the device we put no thread restriction on this interface.
2999 * That means we'll have to check which thread we're in and choose our path.
3000 */
3001#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
3002 PGMPhysRead(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3003#else
3004 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
3005 PGMPhysRead(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3006 else
3007 {
3008 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3009 PVMREQ pReq;
3010 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
3011 (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3012 while (rc == VERR_TIMEOUT)
3013 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
3014 AssertReleaseRC(rc);
3015 VMR3ReqFree(pReq);
3016 }
3017#endif
3018 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3019}
3020
3021
3022/** @copydoc PDMDEVHLP::pfnPhysWrite */
3023static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
3024{
3025 PDMDEV_ASSERT_DEVINS(pDevIns);
3026 LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
3027 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
3028
3029 /*
3030 * For the convenience of the device we put no thread restriction on this interface.
3031 * That means we'll have to check which thread we're in and choose our path.
3032 */
3033#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
3034 PGMPhysWrite(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3035#else
3036 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
3037 PGMPhysWrite(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3038 else
3039 {
3040 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3041 PVMREQ pReq;
3042 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
3043 (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3044 while (rc == VERR_TIMEOUT)
3045 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
3046 AssertReleaseRC(rc);
3047 VMR3ReqFree(pReq);
3048 }
3049#endif
3050 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3051}
3052
3053
3054/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
3055static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
3056{
3057 PDMDEV_ASSERT_DEVINS(pDevIns);
3058 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
3059 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
3060
3061 int rc = PGMPhysReadGCPtr(pDevIns->Internal.s.pVMHC, pvDst, GCVirtSrc, cb);
3062
3063 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3064
3065 return rc;
3066}
3067
3068
3069/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
3070static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
3071{
3072 PDMDEV_ASSERT_DEVINS(pDevIns);
3073 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
3074 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
3075
3076 int rc = PGMPhysWriteGCPtr(pDevIns->Internal.s.pVMHC, GCVirtDst, pvSrc, cb);
3077
3078 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3079
3080 return rc;
3081}
3082
3083
3084/** @copydoc PDMDEVHLP::pfnPhysReserve */
3085static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
3086{
3087 PDMDEV_ASSERT_DEVINS(pDevIns);
3088 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3089 LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
3090 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, pszDesc, pszDesc));
3091
3092 int rc = MMR3PhysReserve(pDevIns->Internal.s.pVMHC, GCPhys, cbRange, pszDesc);
3093
3094 LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3095
3096 return rc;
3097}
3098
3099
3100/** @copydoc PDMDEVHLP::pfnPhys2HCVirt */
3101static DECLCALLBACK(int) pdmR3DevHlp_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
3102{
3103 PDMDEV_ASSERT_DEVINS(pDevIns);
3104 LogFlow(("pdmR3DevHlp_Phys2HCVirt: caller='%s'/%d: GCPhys=%VGp cbRange=%#x ppvHC=%p\n",
3105 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, ppvHC));
3106
3107 int rc = PGMPhysGCPhys2HCPtr(pDevIns->Internal.s.pVMHC, GCPhys, cbRange, ppvHC);
3108
3109 LogFlow(("pdmR3DevHlp_Phys2HCVirt: caller='%s'/%d: returns %Vrc *ppvHC=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *ppvHC));
3110
3111 return rc;
3112}
3113
3114
3115/** @copydoc PDMDEVHLP::pfnPhysGCPtr2HCPtr */
3116static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
3117{
3118 PDMDEV_ASSERT_DEVINS(pDevIns);
3119 PVM pVM = pDevIns->Internal.s.pVMHC;
3120 VM_ASSERT_EMT(pVM);
3121 LogFlow(("pdmR3DevHlp_PhysGCPtr2HCPtr: caller='%s'/%d: GCPtr=%VGv pHCPtr=%p\n",
3122 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPtr, pHCPtr));
3123
3124 int rc = PGMPhysGCPtr2HCPtr(pVM, GCPtr, pHCPtr);
3125
3126 LogFlow(("pdmR3DevHlp_PhysGCPtr2HCPtr: caller='%s'/%d: returns %Vrc *pHCPtr=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pHCPtr));
3127
3128 return rc;
3129}
3130
3131
3132/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
3133static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
3134{
3135 PDMDEV_ASSERT_DEVINS(pDevIns);
3136 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3137
3138 bool fRc = PGMPhysIsA20Enabled(pDevIns->Internal.s.pVMHC);
3139
3140 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
3141 return fRc;
3142}
3143
3144
3145/** @copydoc PDMDEVHLP::pfnA20Set */
3146static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3147{
3148 PDMDEV_ASSERT_DEVINS(pDevIns);
3149 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3150 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
3151 //Assert(*(unsigned *)&fEnable <= 1);
3152 PGMR3PhysSetA20(pDevIns->Internal.s.pVMHC, fEnable);
3153}
3154
3155
3156/** @copydoc PDMDEVHLP::pfnVMReset */
3157static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
3158{
3159 PDMDEV_ASSERT_DEVINS(pDevIns);
3160 PVM pVM = pDevIns->Internal.s.pVMHC;
3161 VM_ASSERT_EMT(pVM);
3162 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
3163 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
3164
3165 /*
3166 * We postpone this operation because we're likely to be inside a I/O instruction
3167 * and the EIP will be updated when we return.
3168 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3169 */
3170 bool fHaltOnReset;
3171 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3172 if (VBOX_SUCCESS(rc) && fHaltOnReset)
3173 {
3174 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3175 rc = VINF_EM_HALT;
3176 }
3177 else
3178 {
3179 VM_FF_SET(pVM, VM_FF_RESET);
3180 rc = VINF_EM_RESET;
3181 }
3182
3183 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3184 return rc;
3185}
3186
3187
3188/** @copydoc PDMDEVHLP::pfnVMSuspend */
3189static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3190{
3191 PDMDEV_ASSERT_DEVINS(pDevIns);
3192 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3193 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3194 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3195
3196 int rc = VMR3Suspend(pDevIns->Internal.s.pVMHC);
3197
3198 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3199 return rc;
3200}
3201
3202
3203/** @copydoc PDMDEVHLP::pfnVMPowerOff */
3204static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
3205{
3206 PDMDEV_ASSERT_DEVINS(pDevIns);
3207 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3208 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
3209 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3210
3211 int rc = VMR3PowerOff(pDevIns->Internal.s.pVMHC);
3212
3213 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3214 return rc;
3215}
3216
3217
3218/** @copydoc PDMDEVHLP::pfnLockVM */
3219static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns)
3220{
3221 return VMMR3Lock(pDevIns->Internal.s.pVMHC);
3222}
3223
3224
3225/** @copydoc PDMDEVHLP::pfnUnlockVM */
3226static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns)
3227{
3228 return VMMR3Unlock(pDevIns->Internal.s.pVMHC);
3229}
3230
3231
3232/** @copydoc PDMDEVHLP::pfnAssertVMLock */
3233static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3234{
3235 PVM pVM = pDevIns->Internal.s.pVMHC;
3236 if (VMMR3LockIsOwner(pVM))
3237 return true;
3238
3239 RTNATIVETHREAD NativeThreadOwner = VMMR3LockGetOwner(pVM);
3240 RTTHREAD ThreadOwner = RTThreadFromNative(NativeThreadOwner);
3241 char szMsg[100];
3242 RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
3243 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
3244 NativeThreadOwner, ThreadOwner, RTThreadGetName(ThreadOwner), RTThreadSelfName());
3245 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
3246 AssertBreakpoint();
3247 return false;
3248}
3249
3250/** @copydoc PDMDEVHLP::pfnDMARegister */
3251static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3252{
3253 PDMDEV_ASSERT_DEVINS(pDevIns);
3254 PVM pVM = pDevIns->Internal.s.pVMHC;
3255 VM_ASSERT_EMT(pVM);
3256 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
3257 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
3258 int rc = VINF_SUCCESS;
3259 if (pVM->pdm.s.pDmac)
3260 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
3261 else
3262 {
3263 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3264 rc = VERR_PDM_NO_DMAC_INSTANCE;
3265 }
3266 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
3267 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3268 return rc;
3269}
3270
3271/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
3272static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3273{
3274 PDMDEV_ASSERT_DEVINS(pDevIns);
3275 PVM pVM = pDevIns->Internal.s.pVMHC;
3276 VM_ASSERT_EMT(pVM);
3277 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
3278 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
3279 int rc = VINF_SUCCESS;
3280 if (pVM->pdm.s.pDmac)
3281 {
3282 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3283 if (pcbRead)
3284 *pcbRead = cb;
3285 }
3286 else
3287 {
3288 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3289 rc = VERR_PDM_NO_DMAC_INSTANCE;
3290 }
3291 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
3292 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3293 return rc;
3294}
3295
3296/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
3297static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3298{
3299 PDMDEV_ASSERT_DEVINS(pDevIns);
3300 PVM pVM = pDevIns->Internal.s.pVMHC;
3301 VM_ASSERT_EMT(pVM);
3302 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
3303 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
3304 int rc = VINF_SUCCESS;
3305 if (pVM->pdm.s.pDmac)
3306 {
3307 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3308 if (pcbWritten)
3309 *pcbWritten = cb;
3310 }
3311 else
3312 {
3313 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3314 rc = VERR_PDM_NO_DMAC_INSTANCE;
3315 }
3316 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
3317 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3318 return rc;
3319}
3320
3321/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
3322static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3323{
3324 PDMDEV_ASSERT_DEVINS(pDevIns);
3325 PVM pVM = pDevIns->Internal.s.pVMHC;
3326 VM_ASSERT_EMT(pVM);
3327 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
3328 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, uLevel));
3329 int rc = VINF_SUCCESS;
3330 if (pVM->pdm.s.pDmac)
3331 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
3332 else
3333 {
3334 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3335 rc = VERR_PDM_NO_DMAC_INSTANCE;
3336 }
3337 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
3338 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3339 return rc;
3340}
3341
3342/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
3343static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3344{
3345 PDMDEV_ASSERT_DEVINS(pDevIns);
3346 PVM pVM = pDevIns->Internal.s.pVMHC;
3347 VM_ASSERT_EMT(pVM);
3348 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
3349 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel));
3350 uint8_t u8Mode;
3351 if (pVM->pdm.s.pDmac)
3352 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
3353 else
3354 {
3355 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3356 u8Mode = 3 << 2 /* illegal mode type */;
3357 }
3358 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
3359 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Mode));
3360 return u8Mode;
3361}
3362
3363/** @copydoc PDMDEVHLP::pfnDMASchedule */
3364static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
3365{
3366 PDMDEV_ASSERT_DEVINS(pDevIns);
3367 PVM pVM = pDevIns->Internal.s.pVMHC;
3368 VM_ASSERT_EMT(pVM);
3369 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
3370 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
3371
3372 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3373 VM_FF_SET(pVM, VM_FF_PDM_DMA);
3374 REMR3NotifyDmaPending(pVM);
3375 VMR3NotifyFF(pVM, true);
3376}
3377
3378
3379/** @copydoc PDMDEVHLP::pfnCMOSWrite */
3380static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3381{
3382 PDMDEV_ASSERT_DEVINS(pDevIns);
3383 PVM pVM = pDevIns->Internal.s.pVMHC;
3384 VM_ASSERT_EMT(pVM);
3385
3386 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
3387 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, u8Value));
3388 int rc;
3389 if (pVM->pdm.s.pRtc)
3390 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
3391 else
3392 rc = VERR_PDM_NO_RTC_INSTANCE;
3393
3394 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
3395 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3396 return rc;
3397}
3398
3399
3400/** @copydoc PDMDEVHLP::pfnCMOSRead */
3401static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3402{
3403 PDMDEV_ASSERT_DEVINS(pDevIns);
3404 PVM pVM = pDevIns->Internal.s.pVMHC;
3405 VM_ASSERT_EMT(pVM);
3406
3407 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
3408 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, pu8Value));
3409 int rc;
3410 if (pVM->pdm.s.pRtc)
3411 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
3412 else
3413 rc = VERR_PDM_NO_RTC_INSTANCE;
3414
3415 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
3416 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3417 return rc;
3418}
3419
3420
3421
3422
3423/** @copydoc PDMDEVHLP::pfnGetVM */
3424static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
3425{
3426 PDMDEV_ASSERT_DEVINS(pDevIns);
3427 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3428 return NULL;
3429}
3430
3431
3432/** @copydoc PDMDEVHLP::pfnPCIBusRegister */
3433static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
3434{
3435 PDMDEV_ASSERT_DEVINS(pDevIns);
3436 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3437 NOREF(pPciBusReg);
3438 NOREF(ppPciHlpR3);
3439 return VERR_ACCESS_DENIED;
3440}
3441
3442
3443/** @copydoc PDMDEVHLP::pfnPICRegister */
3444static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
3445{
3446 PDMDEV_ASSERT_DEVINS(pDevIns);
3447 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3448 NOREF(pPicReg);
3449 NOREF(ppPicHlpR3);
3450 return VERR_ACCESS_DENIED;
3451}
3452
3453
3454/** @copydoc PDMDEVHLP::pfnAPICRegister */
3455static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
3456{
3457 PDMDEV_ASSERT_DEVINS(pDevIns);
3458 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3459 NOREF(pApicReg);
3460 NOREF(ppApicHlpR3);
3461 return VERR_ACCESS_DENIED;
3462}
3463
3464
3465/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
3466static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
3467{
3468 PDMDEV_ASSERT_DEVINS(pDevIns);
3469 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3470 NOREF(pIoApicReg);
3471 NOREF(ppIoApicHlpR3);
3472 return VERR_ACCESS_DENIED;
3473}
3474
3475
3476/** @copydoc PDMDEVHLP::pfnDMACRegister */
3477static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3478{
3479 PDMDEV_ASSERT_DEVINS(pDevIns);
3480 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3481 NOREF(pDmacReg);
3482 NOREF(ppDmacHlp);
3483 return VERR_ACCESS_DENIED;
3484}
3485
3486
3487/** @copydoc PDMDEVHLP::pfnPhysRead */
3488static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
3489{
3490 PDMDEV_ASSERT_DEVINS(pDevIns);
3491 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3492 NOREF(GCPhys);
3493 NOREF(pvBuf);
3494 NOREF(cbRead);
3495}
3496
3497
3498/** @copydoc PDMDEVHLP::pfnPhysWrite */
3499static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
3500{
3501 PDMDEV_ASSERT_DEVINS(pDevIns);
3502 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3503 NOREF(GCPhys);
3504 NOREF(pvBuf);
3505 NOREF(cbWrite);
3506}
3507
3508
3509/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
3510static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
3511{
3512 PDMDEV_ASSERT_DEVINS(pDevIns);
3513 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3514 NOREF(pvDst);
3515 NOREF(GCVirtSrc);
3516 NOREF(cb);
3517 return VERR_ACCESS_DENIED;
3518}
3519
3520
3521/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
3522static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
3523{
3524 PDMDEV_ASSERT_DEVINS(pDevIns);
3525 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3526 NOREF(GCVirtDst);
3527 NOREF(pvSrc);
3528 NOREF(cb);
3529 return VERR_ACCESS_DENIED;
3530}
3531
3532
3533/** @copydoc PDMDEVHLP::pfnPhysReserve */
3534static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
3535{
3536 PDMDEV_ASSERT_DEVINS(pDevIns);
3537 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3538 NOREF(GCPhys);
3539 NOREF(cbRange);
3540 return VERR_ACCESS_DENIED;
3541}
3542
3543
3544/** @copydoc PDMDEVHLP::pfnPhys2HCVirt */
3545static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
3546{
3547 PDMDEV_ASSERT_DEVINS(pDevIns);
3548 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3549 NOREF(GCPhys);
3550 NOREF(cbRange);
3551 NOREF(ppvHC);
3552 return VERR_ACCESS_DENIED;
3553}
3554
3555
3556/** @copydoc PDMDEVHLP::pfnPhysGCPtr2HCPtr */
3557static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
3558{
3559 PDMDEV_ASSERT_DEVINS(pDevIns);
3560 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3561 NOREF(GCPtr);
3562 NOREF(pHCPtr);
3563 return VERR_ACCESS_DENIED;
3564}
3565
3566
3567/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
3568static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
3569{
3570 PDMDEV_ASSERT_DEVINS(pDevIns);
3571 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3572 return false;
3573}
3574
3575
3576/** @copydoc PDMDEVHLP::pfnA20Set */
3577static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3578{
3579 PDMDEV_ASSERT_DEVINS(pDevIns);
3580 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3581 NOREF(fEnable);
3582}
3583
3584
3585/** @copydoc PDMDEVHLP::pfnVMReset */
3586static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
3587{
3588 PDMDEV_ASSERT_DEVINS(pDevIns);
3589 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3590 return VERR_ACCESS_DENIED;
3591}
3592
3593
3594/** @copydoc PDMDEVHLP::pfnVMSuspend */
3595static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
3596{
3597 PDMDEV_ASSERT_DEVINS(pDevIns);
3598 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3599 return VERR_ACCESS_DENIED;
3600}
3601
3602
3603/** @copydoc PDMDEVHLP::pfnVMPowerOff */
3604static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
3605{
3606 PDMDEV_ASSERT_DEVINS(pDevIns);
3607 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3608 return VERR_ACCESS_DENIED;
3609}
3610
3611
3612/** @copydoc PDMDEVHLP::pfnLockVM */
3613static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns)
3614{
3615 PDMDEV_ASSERT_DEVINS(pDevIns);
3616 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3617 return VERR_ACCESS_DENIED;
3618}
3619
3620
3621/** @copydoc PDMDEVHLP::pfnUnlockVM */
3622static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns)
3623{
3624 PDMDEV_ASSERT_DEVINS(pDevIns);
3625 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3626 return VERR_ACCESS_DENIED;
3627}
3628
3629
3630/** @copydoc PDMDEVHLP::pfnAssertVMLock */
3631static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3632{
3633 PDMDEV_ASSERT_DEVINS(pDevIns);
3634 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3635 return false;
3636}
3637
3638
3639/** @copydoc PDMDEVHLP::pfnDMARegister */
3640static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3641{
3642 PDMDEV_ASSERT_DEVINS(pDevIns);
3643 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3644 return VERR_ACCESS_DENIED;
3645}
3646
3647
3648/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
3649static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3650{
3651 PDMDEV_ASSERT_DEVINS(pDevIns);
3652 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3653 if (pcbRead)
3654 *pcbRead = 0;
3655 return VERR_ACCESS_DENIED;
3656}
3657
3658
3659/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
3660static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3661{
3662 PDMDEV_ASSERT_DEVINS(pDevIns);
3663 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3664 if (pcbWritten)
3665 *pcbWritten = 0;
3666 return VERR_ACCESS_DENIED;
3667}
3668
3669
3670/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
3671static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3672{
3673 PDMDEV_ASSERT_DEVINS(pDevIns);
3674 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3675 return VERR_ACCESS_DENIED;
3676}
3677
3678
3679/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
3680static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3681{
3682 PDMDEV_ASSERT_DEVINS(pDevIns);
3683 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3684 return 3 << 2 /* illegal mode type */;
3685}
3686
3687
3688/** @copydoc PDMDEVHLP::pfnDMASchedule */
3689static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns)
3690{
3691 PDMDEV_ASSERT_DEVINS(pDevIns);
3692 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3693}
3694
3695
3696/** @copydoc PDMDEVHLP::pfnCMOSWrite */
3697static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3698{
3699 PDMDEV_ASSERT_DEVINS(pDevIns);
3700 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3701 return VERR_ACCESS_DENIED;
3702}
3703
3704
3705/** @copydoc PDMDEVHLP::pfnCMOSRead */
3706static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3707{
3708 PDMDEV_ASSERT_DEVINS(pDevIns);
3709 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3710 return VERR_ACCESS_DENIED;
3711}
3712
3713
3714
3715
3716/** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
3717static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
3718{
3719 PDMDEV_ASSERT_DEVINS(pDevIns);
3720 PVM pVM = pDevIns->Internal.s.pVMHC;
3721 LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
3722 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_PIC)));
3723 VM_FF_SET(pVM, VM_FF_INTERRUPT_PIC);
3724 REMR3NotifyInterruptSet(pVM);
3725#ifdef VBOX_WITH_PDM_LOCK
3726 VMR3NotifyFF(pVM, true);
3727#endif
3728}
3729
3730
3731/** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
3732static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
3733{
3734 PDMDEV_ASSERT_DEVINS(pDevIns);
3735 LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
3736 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_PIC)));
3737 VM_FF_CLEAR(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_PIC);
3738 REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMHC);
3739}
3740
3741
3742#ifdef VBOX_WITH_PDM_LOCK
3743/** @copydoc PDMPICHLPR3::pfnLock */
3744static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
3745{
3746 PDMDEV_ASSERT_DEVINS(pDevIns);
3747 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
3748}
3749
3750
3751/** @copydoc PDMPICHLPR3::pfnUnlock */
3752static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
3753{
3754 PDMDEV_ASSERT_DEVINS(pDevIns);
3755 pdmUnlock(pDevIns->Internal.s.pVMHC);
3756}
3757#endif /* VBOX_WITH_PDM_LOCK */
3758
3759
3760/** @copydoc PDMPICHLPR3::pfnGetGCHelpers */
3761static DECLCALLBACK(PCPDMPICHLPGC) pdmR3PicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
3762{
3763 PDMDEV_ASSERT_DEVINS(pDevIns);
3764 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3765 RTGCPTR pGCHelpers = 0;
3766 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCPicHlp", &pGCHelpers);
3767 AssertReleaseRC(rc);
3768 AssertRelease(pGCHelpers);
3769 LogFlow(("pdmR3PicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
3770 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
3771 return pGCHelpers;
3772}
3773
3774
3775/** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
3776static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
3777{
3778 PDMDEV_ASSERT_DEVINS(pDevIns);
3779 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3780 PCPDMPICHLPR0 pR0Helpers = 0;
3781 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0PicHlp", (void **)&pR0Helpers);
3782 AssertReleaseRC(rc);
3783 AssertRelease(pR0Helpers);
3784 LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
3785 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
3786 return pR0Helpers;
3787}
3788
3789
3790/** @copydoc PDMAPICHLPR3::pfnSetInterruptFF */
3791static DECLCALLBACK(void) pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
3792{
3793 PDMDEV_ASSERT_DEVINS(pDevIns);
3794 PVM pVM = pDevIns->Internal.s.pVMHC;
3795 LogFlow(("pdmR3ApicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 1\n",
3796 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_APIC)));
3797 VM_FF_SET(pVM, VM_FF_INTERRUPT_APIC);
3798 REMR3NotifyInterruptSet(pVM);
3799#ifdef VBOX_WITH_PDM_LOCK
3800 VMR3NotifyFF(pVM, true);
3801#endif
3802}
3803
3804
3805/** @copydoc PDMAPICHLPR3::pfnClearInterruptFF */
3806static DECLCALLBACK(void) pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
3807{
3808 PDMDEV_ASSERT_DEVINS(pDevIns);
3809 LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 0\n",
3810 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_APIC)));
3811 VM_FF_CLEAR(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_APIC);
3812 REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMHC);
3813}
3814
3815
3816/** @copydoc PDMAPICHLPR3::pfnChangeFeature */
3817static DECLCALLBACK(void) pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, bool fEnabled)
3818{
3819 PDMDEV_ASSERT_DEVINS(pDevIns);
3820 LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: fEnabled=%RTbool\n",
3821 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnabled));
3822 if (fEnabled)
3823 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMHC, CPUMCPUIDFEATURE_APIC);
3824 else
3825 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMHC, CPUMCPUIDFEATURE_APIC);
3826}
3827
3828
3829#ifdef VBOX_WITH_PDM_LOCK
3830/** @copydoc PDMAPICHLPR3::pfnLock */
3831static DECLCALLBACK(int) pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
3832{
3833 PDMDEV_ASSERT_DEVINS(pDevIns);
3834 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
3835}
3836
3837
3838/** @copydoc PDMAPICHLPR3::pfnUnlock */
3839static DECLCALLBACK(void) pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns)
3840{
3841 PDMDEV_ASSERT_DEVINS(pDevIns);
3842 pdmUnlock(pDevIns->Internal.s.pVMHC);
3843}
3844#endif /* VBOX_WITH_PDM_LOCK */
3845
3846
3847/** @copydoc PDMAPICHLPR3::pfnGetGCHelpers */
3848static DECLCALLBACK(PCPDMAPICHLPGC) pdmR3ApicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
3849{
3850 PDMDEV_ASSERT_DEVINS(pDevIns);
3851 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3852 RTGCPTR pGCHelpers = 0;
3853 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCApicHlp", &pGCHelpers);
3854 AssertReleaseRC(rc);
3855 AssertRelease(pGCHelpers);
3856 LogFlow(("pdmR3ApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
3857 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
3858 return pGCHelpers;
3859}
3860
3861
3862/** @copydoc PDMAPICHLPR3::pfnGetR0Helpers */
3863static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
3864{
3865 PDMDEV_ASSERT_DEVINS(pDevIns);
3866 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3867 PCPDMAPICHLPR0 pR0Helpers = 0;
3868 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0ApicHlp", (void **)&pR0Helpers);
3869 AssertReleaseRC(rc);
3870 AssertRelease(pR0Helpers);
3871 LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
3872 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
3873 return pR0Helpers;
3874}
3875
3876
3877/** @copydoc PDMIOAPICHLPR3::pfnApicBusDeliver */
3878static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
3879 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
3880{
3881 PDMDEV_ASSERT_DEVINS(pDevIns);
3882 PVM pVM = pDevIns->Internal.s.pVMHC;
3883#ifndef VBOX_WITH_PDM_LOCK
3884 VM_ASSERT_EMT(pVM);
3885#endif
3886 LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
3887 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
3888 if (pVM->pdm.s.Apic.pfnBusDeliverR3)
3889 pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
3890}
3891
3892
3893#ifdef VBOX_WITH_PDM_LOCK
3894/** @copydoc PDMIOAPICHLPR3::pfnLock */
3895static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
3896{
3897 PDMDEV_ASSERT_DEVINS(pDevIns);
3898 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
3899}
3900
3901
3902/** @copydoc PDMIOAPICHLPR3::pfnUnlock */
3903static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
3904{
3905 PDMDEV_ASSERT_DEVINS(pDevIns);
3906 pdmUnlock(pDevIns->Internal.s.pVMHC);
3907}
3908#endif /* VBOX_WITH_PDM_LOCK */
3909
3910
3911/** @copydoc PDMIOAPICHLPR3::pfnGetGCHelpers */
3912static DECLCALLBACK(PCPDMIOAPICHLPGC) pdmR3IoApicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
3913{
3914 PDMDEV_ASSERT_DEVINS(pDevIns);
3915 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3916 RTGCPTR pGCHelpers = 0;
3917 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCIoApicHlp", &pGCHelpers);
3918 AssertReleaseRC(rc);
3919 AssertRelease(pGCHelpers);
3920 LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
3921 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
3922 return pGCHelpers;
3923}
3924
3925
3926/** @copydoc PDMIOAPICHLPR3::pfnGetR0Helpers */
3927static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
3928{
3929 PDMDEV_ASSERT_DEVINS(pDevIns);
3930 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3931 PCPDMIOAPICHLPR0 pR0Helpers = 0;
3932 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0IoApicHlp", (void **)&pR0Helpers);
3933 AssertReleaseRC(rc);
3934 AssertRelease(pR0Helpers);
3935 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
3936 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
3937 return pR0Helpers;
3938}
3939
3940
3941/** @copydoc PDMPCIHLPR3::pfnIsaSetIrq */
3942static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
3943{
3944 PDMDEV_ASSERT_DEVINS(pDevIns);
3945#ifndef VBOX_WITH_PDM_LOCK
3946 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3947#endif
3948 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
3949 PDMIsaSetIrq(pDevIns->Internal.s.pVMHC, iIrq, iLevel);
3950}
3951
3952
3953/** @copydoc PDMPCIHLPR3::pfnIoApicSetIrq */
3954static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
3955{
3956 PDMDEV_ASSERT_DEVINS(pDevIns);
3957#ifndef VBOX_WITH_PDM_LOCK
3958 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3959#endif
3960 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
3961 PDMIoApicSetIrq(pDevIns->Internal.s.pVMHC, iIrq, iLevel);
3962}
3963
3964
3965#ifdef VBOX_WITH_PDM_LOCK
3966/** @copydoc PDMPCIHLPR3::pfnLock */
3967static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
3968{
3969 PDMDEV_ASSERT_DEVINS(pDevIns);
3970 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
3971}
3972
3973
3974/** @copydoc PDMPCIHLPR3::pfnUnlock */
3975static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
3976{
3977 PDMDEV_ASSERT_DEVINS(pDevIns);
3978 pdmUnlock(pDevIns->Internal.s.pVMHC);
3979}
3980#endif /* VBOX_WITH_PDM_LOCK */
3981
3982
3983/** @copydoc PDMPCIHLPR3::pfnGetGCHelpers */
3984static DECLCALLBACK(PCPDMPCIHLPGC) pdmR3PciHlp_GetGCHelpers(PPDMDEVINS pDevIns)
3985{
3986 PDMDEV_ASSERT_DEVINS(pDevIns);
3987 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3988 RTGCPTR pGCHelpers = 0;
3989 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCPciHlp", &pGCHelpers);
3990 AssertReleaseRC(rc);
3991 AssertRelease(pGCHelpers);
3992 LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
3993 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
3994 return pGCHelpers;
3995}
3996
3997
3998/** @copydoc PDMPCIHLPR3::pfnGetR0Helpers */
3999static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4000{
4001 PDMDEV_ASSERT_DEVINS(pDevIns);
4002 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4003 PCPDMPCIHLPR0 pR0Helpers = 0;
4004 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0PciHlp", (void **)&pR0Helpers);
4005 AssertReleaseRC(rc);
4006 AssertRelease(pR0Helpers);
4007 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4008 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4009 return pR0Helpers;
4010}
4011
4012
4013/**
4014 * Locates a LUN.
4015 *
4016 * @returns VBox status code.
4017 * @param pVM VM Handle.
4018 * @param pszDevice Device name.
4019 * @param iInstance Device instance.
4020 * @param iLun The Logical Unit to obtain the interface of.
4021 * @param ppLun Where to store the pointer to the LUN if found.
4022 * @thread Try only do this in EMT...
4023 */
4024int pdmR3DevFindLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMLUN *ppLun)
4025{
4026 /*
4027 * Iterate registered devices looking for the device.
4028 */
4029 RTUINT cchDevice = strlen(pszDevice);
4030 for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
4031 {
4032 if ( pDev->cchName == cchDevice
4033 && !memcmp(pDev->pDevReg->szDeviceName, pszDevice, cchDevice))
4034 {
4035 /*
4036 * Iterate device instances.
4037 */
4038 for (PPDMDEVINS pDevIns = pDev->pInstances; pDevIns; pDevIns = pDevIns->Internal.s.pPerDeviceNextHC)
4039 {
4040 if (pDevIns->iInstance == iInstance)
4041 {
4042 /*
4043 * Iterate luns.
4044 */
4045 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
4046 {
4047 if (pLun->iLun == iLun)
4048 {
4049 *ppLun = pLun;
4050 return VINF_SUCCESS;
4051 }
4052 }
4053 return VERR_PDM_LUN_NOT_FOUND;
4054 }
4055 }
4056 return VERR_PDM_DEVICE_INSTANCE_NOT_FOUND;
4057 }
4058 }
4059 return VERR_PDM_DEVICE_NOT_FOUND;
4060}
4061
4062
4063/**
4064 * Attaches a preconfigured driver to an existing device instance.
4065 *
4066 * This is used to change drivers and suchlike at runtime.
4067 *
4068 * @returns VBox status code.
4069 * @param pVM VM Handle.
4070 * @param pszDevice Device name.
4071 * @param iInstance Device instance.
4072 * @param iLun The Logical Unit to obtain the interface of.
4073 * @param ppBase Where to store the base interface pointer. Optional.
4074 * @thread EMT
4075 */
4076PDMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
4077{
4078 VM_ASSERT_EMT(pVM);
4079 LogFlow(("PDMR3DeviceAttach: pszDevice=%p:{%s} iInstance=%d iLun=%d ppBase=%p\n",
4080 pszDevice, pszDevice, iInstance, iLun, ppBase));
4081
4082 /*
4083 * Find the LUN in question.
4084 */
4085 PPDMLUN pLun;
4086 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
4087 if (VBOX_SUCCESS(rc))
4088 {
4089 /*
4090 * Can we attach anything at runtime?
4091 */
4092 PPDMDEVINS pDevIns = pLun->pDevIns;
4093 if (pDevIns->pDevReg->pfnAttach)
4094 {
4095 if (!pLun->pTop)
4096 {
4097 rc = pDevIns->pDevReg->pfnAttach(pDevIns, iLun);
4098
4099 }
4100 else
4101 rc = VERR_PDM_DRIVER_ALREADY_ATTACHED;
4102 }
4103 else
4104 rc = VERR_PDM_DEVICE_NO_RT_ATTACH;
4105
4106 if (ppBase)
4107 *ppBase = pLun->pTop ? &pLun->pTop->IBase : NULL;
4108 }
4109 else if (ppBase)
4110 *ppBase = NULL;
4111
4112 if (ppBase)
4113 LogFlow(("PDMR3DeviceAttach: returns %Vrc *ppBase=%p\n", rc, *ppBase));
4114 else
4115 LogFlow(("PDMR3DeviceAttach: returns %Vrc\n", rc));
4116 return rc;
4117}
4118
4119
4120/**
4121 * Detaches a driver from an existing device instance.
4122 *
4123 * This is used to change drivers and suchlike at runtime.
4124 *
4125 * @returns VBox status code.
4126 * @param pVM VM Handle.
4127 * @param pszDevice Device name.
4128 * @param iInstance Device instance.
4129 * @param iLun The Logical Unit to obtain the interface of.
4130 * @thread EMT
4131 */
4132PDMR3DECL(int) PDMR3DeviceDetach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun)
4133{
4134 VM_ASSERT_EMT(pVM);
4135 LogFlow(("PDMR3DeviceDetach: pszDevice=%p:{%s} iInstance=%d iLun=%d\n",
4136 pszDevice, pszDevice, iInstance, iLun));
4137
4138 /*
4139 * Find the LUN in question.
4140 */
4141 PPDMLUN pLun;
4142 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
4143 if (VBOX_SUCCESS(rc))
4144 {
4145 /*
4146 * Can we detach anything at runtime?
4147 */
4148 PPDMDEVINS pDevIns = pLun->pDevIns;
4149 if (pDevIns->pDevReg->pfnDetach)
4150 {
4151 if (pLun->pTop)
4152 rc = pdmR3DrvDetach(pLun->pTop);
4153 else
4154 rc = VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN;
4155 }
4156 else
4157 rc = VERR_PDM_DEVICE_NO_RT_DETACH;
4158 }
4159
4160 LogFlow(("PDMR3DeviceDetach: returns %Vrc\n", rc));
4161 return rc;
4162}
4163
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