VirtualBox

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

Last change on this file since 10228 was 10202, checked in by vboxsync, 16 years ago

removed VBOX_WITH_PDM_LOCK

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