VirtualBox

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

Last change on this file since 4745 was 4569, checked in by vboxsync, 17 years ago

Read and write to GC virt is only allowed from EMT.

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