VirtualBox

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

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

Added TMR3UCTNow, exported it as a DevHlp and made VMMDev use it as time source. TMR3UCTNow adjust for lag we intend to catchup so the guest time wont run ahead of real-world time.

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