VirtualBox

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

Last change on this file since 11043 was 10841, checked in by vboxsync, 16 years ago

Changed the assertion on pfnConstruct failure into a LogRel.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 181.3 KB
Line 
1/* $Id: PDMDevice.cpp 10841 2008-07-23 19:54:12Z 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 LogRel(("PDM: 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->pfnHasPendingIrqHC
2648 || !pApicReg->pfnSetBaseHC
2649 || !pApicReg->pfnGetBaseHC
2650 || !pApicReg->pfnSetTPRHC
2651 || !pApicReg->pfnGetTPRHC
2652 || !pApicReg->pfnBusDeliverHC)
2653 {
2654 Assert(pApicReg->pfnGetInterruptHC);
2655 Assert(pApicReg->pfnHasPendingIrqHC);
2656 Assert(pApicReg->pfnSetBaseHC);
2657 Assert(pApicReg->pfnGetBaseHC);
2658 Assert(pApicReg->pfnSetTPRHC);
2659 Assert(pApicReg->pfnGetTPRHC);
2660 Assert(pApicReg->pfnBusDeliverHC);
2661 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2662 return VERR_INVALID_PARAMETER;
2663 }
2664 if ( ( pApicReg->pszGetInterruptGC
2665 || pApicReg->pszHasPendingIrqGC
2666 || pApicReg->pszSetBaseGC
2667 || pApicReg->pszGetBaseGC
2668 || pApicReg->pszSetTPRGC
2669 || pApicReg->pszGetTPRGC
2670 || pApicReg->pszBusDeliverGC)
2671 && ( !VALID_PTR(pApicReg->pszGetInterruptGC)
2672 || !VALID_PTR(pApicReg->pszHasPendingIrqGC)
2673 || !VALID_PTR(pApicReg->pszSetBaseGC)
2674 || !VALID_PTR(pApicReg->pszGetBaseGC)
2675 || !VALID_PTR(pApicReg->pszSetTPRGC)
2676 || !VALID_PTR(pApicReg->pszGetTPRGC)
2677 || !VALID_PTR(pApicReg->pszBusDeliverGC))
2678 )
2679 {
2680 Assert(VALID_PTR(pApicReg->pszGetInterruptGC));
2681 Assert(VALID_PTR(pApicReg->pszHasPendingIrqGC));
2682 Assert(VALID_PTR(pApicReg->pszSetBaseGC));
2683 Assert(VALID_PTR(pApicReg->pszGetBaseGC));
2684 Assert(VALID_PTR(pApicReg->pszSetTPRGC));
2685 Assert(VALID_PTR(pApicReg->pszGetTPRGC));
2686 Assert(VALID_PTR(pApicReg->pszBusDeliverGC));
2687 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2688 return VERR_INVALID_PARAMETER;
2689 }
2690 if ( ( pApicReg->pszGetInterruptR0
2691 || pApicReg->pszHasPendingIrqR0
2692 || pApicReg->pszSetBaseR0
2693 || pApicReg->pszGetBaseR0
2694 || pApicReg->pszSetTPRR0
2695 || pApicReg->pszGetTPRR0
2696 || pApicReg->pszBusDeliverR0)
2697 && ( !VALID_PTR(pApicReg->pszGetInterruptR0)
2698 || !VALID_PTR(pApicReg->pszHasPendingIrqR0)
2699 || !VALID_PTR(pApicReg->pszSetBaseR0)
2700 || !VALID_PTR(pApicReg->pszGetBaseR0)
2701 || !VALID_PTR(pApicReg->pszSetTPRR0)
2702 || !VALID_PTR(pApicReg->pszGetTPRR0)
2703 || !VALID_PTR(pApicReg->pszBusDeliverR0))
2704 )
2705 {
2706 Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
2707 Assert(VALID_PTR(pApicReg->pszHasPendingIrqR0));
2708 Assert(VALID_PTR(pApicReg->pszSetBaseR0));
2709 Assert(VALID_PTR(pApicReg->pszGetBaseR0));
2710 Assert(VALID_PTR(pApicReg->pszSetTPRR0));
2711 Assert(VALID_PTR(pApicReg->pszGetTPRR0));
2712 Assert(VALID_PTR(pApicReg->pszBusDeliverR0));
2713 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (R0 callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2714 return VERR_INVALID_PARAMETER;
2715 }
2716 if (!ppApicHlpR3)
2717 {
2718 Assert(ppApicHlpR3);
2719 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc (ppApicHlpR3)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2720 return VERR_INVALID_PARAMETER;
2721 }
2722
2723 /*
2724 * Only one APIC device. (malc: only in UP case actually)
2725 */
2726 PVM pVM = pDevIns->Internal.s.pVMHC;
2727 if (pVM->pdm.s.Apic.pDevInsR3)
2728 {
2729 AssertMsgFailed(("Only one apic device is supported!\n"));
2730 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2731 return VERR_INVALID_PARAMETER;
2732 }
2733
2734 /*
2735 * Resolve & initialize the GC bits.
2736 */
2737 if (pApicReg->pszGetInterruptGC)
2738 {
2739 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetInterruptGC, &pVM->pdm.s.Apic.pfnGetInterruptGC);
2740 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetInterruptGC, rc));
2741 if (RT_SUCCESS(rc))
2742 {
2743 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszHasPendingIrqGC, &pVM->pdm.s.Apic.pfnHasPendingIrqGC);
2744 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszHasPendingIrqGC, rc));
2745 }
2746 if (RT_SUCCESS(rc))
2747 {
2748 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetBaseGC, &pVM->pdm.s.Apic.pfnSetBaseGC);
2749 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszSetBaseGC, rc));
2750 }
2751 if (RT_SUCCESS(rc))
2752 {
2753 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetBaseGC, &pVM->pdm.s.Apic.pfnGetBaseGC);
2754 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetBaseGC, rc));
2755 }
2756 if (RT_SUCCESS(rc))
2757 {
2758 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszSetTPRGC, &pVM->pdm.s.Apic.pfnSetTPRGC);
2759 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszSetTPRGC, rc));
2760 }
2761 if (RT_SUCCESS(rc))
2762 {
2763 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszGetTPRGC, &pVM->pdm.s.Apic.pfnGetTPRGC);
2764 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszGetTPRGC, rc));
2765 }
2766 if (RT_SUCCESS(rc))
2767 {
2768 rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pApicReg->pszBusDeliverGC, &pVM->pdm.s.Apic.pfnBusDeliverGC);
2769 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pApicReg->pszBusDeliverGC, rc));
2770 }
2771 if (VBOX_FAILURE(rc))
2772 {
2773 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2774 return rc;
2775 }
2776 pVM->pdm.s.Apic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2777 }
2778 else
2779 {
2780 pVM->pdm.s.Apic.pDevInsGC = 0;
2781 pVM->pdm.s.Apic.pfnGetInterruptGC = 0;
2782 pVM->pdm.s.Apic.pfnHasPendingIrqGC = 0;
2783 pVM->pdm.s.Apic.pfnSetBaseGC = 0;
2784 pVM->pdm.s.Apic.pfnGetBaseGC = 0;
2785 pVM->pdm.s.Apic.pfnSetTPRGC = 0;
2786 pVM->pdm.s.Apic.pfnGetTPRGC = 0;
2787 pVM->pdm.s.Apic.pfnBusDeliverGC = 0;
2788 }
2789
2790 /*
2791 * Resolve & initialize the R0 bits.
2792 */
2793 if (pApicReg->pszGetInterruptR0)
2794 {
2795 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, &pVM->pdm.s.Apic.pfnGetInterruptR0);
2796 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetInterruptR0, rc));
2797 if (RT_SUCCESS(rc))
2798 {
2799 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, &pVM->pdm.s.Apic.pfnHasPendingIrqR0);
2800 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszHasPendingIrqR0, rc));
2801 }
2802 if (RT_SUCCESS(rc))
2803 {
2804 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, &pVM->pdm.s.Apic.pfnSetBaseR0);
2805 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetBaseR0, rc));
2806 }
2807 if (RT_SUCCESS(rc))
2808 {
2809 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, &pVM->pdm.s.Apic.pfnGetBaseR0);
2810 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetBaseR0, rc));
2811 }
2812 if (RT_SUCCESS(rc))
2813 {
2814 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, &pVM->pdm.s.Apic.pfnSetTPRR0);
2815 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszSetTPRR0, rc));
2816 }
2817 if (RT_SUCCESS(rc))
2818 {
2819 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, &pVM->pdm.s.Apic.pfnGetTPRR0);
2820 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszGetTPRR0, rc));
2821 }
2822 if (RT_SUCCESS(rc))
2823 {
2824 rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, &pVM->pdm.s.Apic.pfnBusDeliverR0);
2825 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pApicReg->pszBusDeliverR0, rc));
2826 }
2827 if (VBOX_FAILURE(rc))
2828 {
2829 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2830 return rc;
2831 }
2832 pVM->pdm.s.Apic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2833 Assert(pVM->pdm.s.Apic.pDevInsR0);
2834 }
2835 else
2836 {
2837 pVM->pdm.s.Apic.pfnGetInterruptR0 = 0;
2838 pVM->pdm.s.Apic.pfnHasPendingIrqR0 = 0;
2839 pVM->pdm.s.Apic.pfnSetBaseR0 = 0;
2840 pVM->pdm.s.Apic.pfnGetBaseR0 = 0;
2841 pVM->pdm.s.Apic.pfnSetTPRR0 = 0;
2842 pVM->pdm.s.Apic.pfnGetTPRR0 = 0;
2843 pVM->pdm.s.Apic.pfnBusDeliverR0 = 0;
2844 pVM->pdm.s.Apic.pDevInsR0 = 0;
2845 }
2846
2847 /*
2848 * Initialize the HC bits.
2849 */
2850 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
2851 pVM->pdm.s.Apic.pfnGetInterruptR3 = pApicReg->pfnGetInterruptHC;
2852 pVM->pdm.s.Apic.pfnHasPendingIrqR3 = pApicReg->pfnHasPendingIrqHC;
2853 pVM->pdm.s.Apic.pfnSetBaseR3 = pApicReg->pfnSetBaseHC;
2854 pVM->pdm.s.Apic.pfnGetBaseR3 = pApicReg->pfnGetBaseHC;
2855 pVM->pdm.s.Apic.pfnSetTPRR3 = pApicReg->pfnSetTPRHC;
2856 pVM->pdm.s.Apic.pfnGetTPRR3 = pApicReg->pfnGetTPRHC;
2857 pVM->pdm.s.Apic.pfnBusDeliverR3 = pApicReg->pfnBusDeliverHC;
2858 Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2859
2860 /* set the helper pointer and return. */
2861 *ppApicHlpR3 = &g_pdmR3DevApicHlp;
2862 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2863 return VINF_SUCCESS;
2864}
2865
2866
2867/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
2868static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
2869{
2870 PDMDEV_ASSERT_DEVINS(pDevIns);
2871 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
2872 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqHC=%p, .pszSetIrqGC=%p:{%s}} ppIoApicHlpR3=%p\n",
2873 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqHC, pIoApicReg->pszSetIrqGC,
2874 pIoApicReg->pszSetIrqGC, ppIoApicHlpR3));
2875
2876 /*
2877 * Validate input.
2878 */
2879 if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
2880 {
2881 AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
2882 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (version)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2883 return VERR_INVALID_PARAMETER;
2884 }
2885 if (!pIoApicReg->pfnSetIrqHC)
2886 {
2887 Assert(pIoApicReg->pfnSetIrqHC);
2888 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (HC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2889 return VERR_INVALID_PARAMETER;
2890 }
2891 if ( pIoApicReg->pszSetIrqGC
2892 && !VALID_PTR(pIoApicReg->pszSetIrqGC))
2893 {
2894 Assert(VALID_PTR(pIoApicReg->pszSetIrqGC));
2895 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2896 return VERR_INVALID_PARAMETER;
2897 }
2898 if ( pIoApicReg->pszSetIrqR0
2899 && !VALID_PTR(pIoApicReg->pszSetIrqR0))
2900 {
2901 Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
2902 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (GC callbacks)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2903 return VERR_INVALID_PARAMETER;
2904 }
2905 if (!ppIoApicHlpR3)
2906 {
2907 Assert(ppIoApicHlpR3);
2908 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (ppApicHlp)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2909 return VERR_INVALID_PARAMETER;
2910 }
2911
2912 /*
2913 * The I/O APIC requires the APIC to be present (hacks++).
2914 * If the I/O APIC does GC stuff so must the APIC.
2915 */
2916 PVM pVM = pDevIns->Internal.s.pVMHC;
2917 if (!pVM->pdm.s.Apic.pDevInsR3)
2918 {
2919 AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
2920 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2921 return VERR_INVALID_PARAMETER;
2922 }
2923 if ( pIoApicReg->pszSetIrqGC
2924 && !pVM->pdm.s.Apic.pDevInsGC)
2925 {
2926 AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
2927 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (no GC APIC)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2928 return VERR_INVALID_PARAMETER;
2929 }
2930
2931 /*
2932 * Only one I/O APIC device.
2933 */
2934 if (pVM->pdm.s.IoApic.pDevInsR3)
2935 {
2936 AssertMsgFailed(("Only one ioapic device is supported!\n"));
2937 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc (only one)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2938 return VERR_INVALID_PARAMETER;
2939 }
2940
2941 /*
2942 * Resolve & initialize the GC bits.
2943 */
2944 if (pIoApicReg->pszSetIrqGC)
2945 {
2946 int rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, pIoApicReg->pszSetIrqGC, &pVM->pdm.s.IoApic.pfnSetIrqGC);
2947 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szGCMod, pIoApicReg->pszSetIrqGC, rc));
2948 if (VBOX_FAILURE(rc))
2949 {
2950 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2951 return rc;
2952 }
2953 pVM->pdm.s.IoApic.pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
2954 }
2955 else
2956 {
2957 pVM->pdm.s.IoApic.pDevInsGC = 0;
2958 pVM->pdm.s.IoApic.pfnSetIrqGC = 0;
2959 }
2960
2961 /*
2962 * Resolve & initialize the R0 bits.
2963 */
2964 if (pIoApicReg->pszSetIrqR0)
2965 {
2966 int rc = PDMR3GetSymbolR0Lazy(pVM, pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
2967 AssertMsgRC(rc, ("%s::%s rc=%Vrc\n", pDevIns->pDevReg->szR0Mod, pIoApicReg->pszSetIrqR0, rc));
2968 if (VBOX_FAILURE(rc))
2969 {
2970 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
2971 return rc;
2972 }
2973 pVM->pdm.s.IoApic.pDevInsR0 = MMHyperR3ToR0(pVM, pDevIns);
2974 Assert(pVM->pdm.s.IoApic.pDevInsR0);
2975 }
2976 else
2977 {
2978 pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
2979 pVM->pdm.s.IoApic.pDevInsR0 = 0;
2980 }
2981
2982 /*
2983 * Initialize the HC bits.
2984 */
2985 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
2986 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqHC;
2987 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
2988
2989 /* set the helper pointer and return. */
2990 *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
2991 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VINF_SUCCESS));
2992 return VINF_SUCCESS;
2993}
2994
2995
2996/** @copydoc PDMDEVHLP::pfnDMACRegister */
2997static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
2998{
2999 PDMDEV_ASSERT_DEVINS(pDevIns);
3000 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3001 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",
3002 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3003 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3004
3005 /*
3006 * Validate input.
3007 */
3008 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3009 {
3010 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3011 PDM_DMACREG_VERSION));
3012 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (version)\n",
3013 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3014 return VERR_INVALID_PARAMETER;
3015 }
3016 if ( !pDmacReg->pfnRun
3017 || !pDmacReg->pfnRegister
3018 || !pDmacReg->pfnReadMemory
3019 || !pDmacReg->pfnWriteMemory
3020 || !pDmacReg->pfnSetDREQ
3021 || !pDmacReg->pfnGetChannelMode)
3022 {
3023 Assert(pDmacReg->pfnRun);
3024 Assert(pDmacReg->pfnRegister);
3025 Assert(pDmacReg->pfnReadMemory);
3026 Assert(pDmacReg->pfnWriteMemory);
3027 Assert(pDmacReg->pfnSetDREQ);
3028 Assert(pDmacReg->pfnGetChannelMode);
3029 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (callbacks)\n",
3030 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3031 return VERR_INVALID_PARAMETER;
3032 }
3033
3034 if (!ppDmacHlp)
3035 {
3036 Assert(ppDmacHlp);
3037 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc (ppDmacHlp)\n",
3038 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3039 return VERR_INVALID_PARAMETER;
3040 }
3041
3042 /*
3043 * Only one DMA device.
3044 */
3045 PVM pVM = pDevIns->Internal.s.pVMHC;
3046 if (pVM->pdm.s.pDmac)
3047 {
3048 AssertMsgFailed(("Only one DMA device is supported!\n"));
3049 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
3050 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3051 return VERR_INVALID_PARAMETER;
3052 }
3053
3054 /*
3055 * Allocate and initialize pci bus structure.
3056 */
3057 int rc = VINF_SUCCESS;
3058 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMHC, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3059 if (pDmac)
3060 {
3061 pDmac->pDevIns = pDevIns;
3062 pDmac->Reg = *pDmacReg;
3063 pVM->pdm.s.pDmac = pDmac;
3064
3065 /* set the helper pointer. */
3066 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3067 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3068 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pDevIns));
3069 }
3070 else
3071 rc = VERR_NO_MEMORY;
3072
3073 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Vrc\n",
3074 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3075 return rc;
3076}
3077
3078
3079/** @copydoc PDMDEVHLP::pfnPhysRead */
3080static DECLCALLBACK(void) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
3081{
3082 PDMDEV_ASSERT_DEVINS(pDevIns);
3083 LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbRead=%#x\n",
3084 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
3085
3086 /*
3087 * For the convenience of the device we put no thread restriction on this interface.
3088 * That means we'll have to check which thread we're in and choose our path.
3089 */
3090#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
3091 PGMPhysRead(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3092#else
3093 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
3094 PGMPhysRead(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3095 else
3096 {
3097 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3098 PVMREQ pReq;
3099 AssertCompileSize(RTGCPHYS, 4);
3100 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
3101 (PFNRT)PGMPhysRead, 4, pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbRead);
3102 while (rc == VERR_TIMEOUT)
3103 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
3104 AssertReleaseRC(rc);
3105 VMR3ReqFree(pReq);
3106 }
3107#endif
3108 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3109}
3110
3111
3112/** @copydoc PDMDEVHLP::pfnPhysWrite */
3113static DECLCALLBACK(void) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
3114{
3115 PDMDEV_ASSERT_DEVINS(pDevIns);
3116 LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%VGp pvBuf=%p cbWrite=%#x\n",
3117 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
3118
3119 /*
3120 * For the convenience of the device we put no thread restriction on this interface.
3121 * That means we'll have to check which thread we're in and choose our path.
3122 */
3123#ifdef PDM_PHYS_READWRITE_FROM_ANY_THREAD
3124 PGMPhysWrite(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3125#else
3126 if (VM_IS_EMT(pDevIns->Internal.s.pVMHC) || VMMR3LockIsOwner(pDevIns->Internal.s.pVMHC))
3127 PGMPhysWrite(pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3128 else
3129 {
3130 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: Requesting call in EMT...\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3131 PVMREQ pReq;
3132 AssertCompileSize(RTGCPHYS, 4);
3133 int rc = VMR3ReqCallVoid(pDevIns->Internal.s.pVMHC, &pReq, RT_INDEFINITE_WAIT,
3134 (PFNRT)PGMPhysWrite, 4, pDevIns->Internal.s.pVMHC, GCPhys, pvBuf, cbWrite);
3135 while (rc == VERR_TIMEOUT)
3136 rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
3137 AssertReleaseRC(rc);
3138 VMR3ReqFree(pReq);
3139 }
3140#endif
3141 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns void\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3142}
3143
3144
3145/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
3146static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
3147{
3148 PDMDEV_ASSERT_DEVINS(pDevIns);
3149 PVM pVM = pDevIns->Internal.s.pVMHC;
3150 VM_ASSERT_EMT(pVM);
3151 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%VGv cb=%#x\n",
3152 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
3153
3154 if (!VM_IS_EMT(pVM))
3155 return VERR_ACCESS_DENIED;
3156
3157 int rc = PGMPhysReadGCPtr(pVM, pvDst, GCVirtSrc, cb);
3158
3159 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3160
3161 return rc;
3162}
3163
3164
3165/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
3166static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
3167{
3168 PDMDEV_ASSERT_DEVINS(pDevIns);
3169 PVM pVM = pDevIns->Internal.s.pVMHC;
3170 VM_ASSERT_EMT(pVM);
3171 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%VGv pvSrc=%p cb=%#x\n",
3172 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
3173
3174 if (!VM_IS_EMT(pVM))
3175 return VERR_ACCESS_DENIED;
3176
3177 int rc = PGMPhysWriteGCPtr(pVM, GCVirtDst, pvSrc, cb);
3178
3179 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3180
3181 return rc;
3182}
3183
3184
3185/** @copydoc PDMDEVHLP::pfnPhysReserve */
3186static DECLCALLBACK(int) pdmR3DevHlp_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
3187{
3188 PDMDEV_ASSERT_DEVINS(pDevIns);
3189 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3190 LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: GCPhys=%VGp cbRange=%#x pszDesc=%p:{%s}\n",
3191 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhys, cbRange, pszDesc, pszDesc));
3192
3193 int rc = MMR3PhysReserve(pDevIns->Internal.s.pVMHC, GCPhys, cbRange, pszDesc);
3194
3195 LogFlow(("pdmR3DevHlp_PhysReserve: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3196
3197 return rc;
3198}
3199
3200
3201/** @copydoc PDMDEVHLP::pfnPhysGCPtr2GCPhys */
3202static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
3203{
3204 PDMDEV_ASSERT_DEVINS(pDevIns);
3205 PVM pVM = pDevIns->Internal.s.pVMHC;
3206 VM_ASSERT_EMT(pVM);
3207 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%VGv pGCPhys=%p\n",
3208 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPtr, pGCPhys));
3209
3210 if (!VM_IS_EMT(pVM))
3211 return VERR_ACCESS_DENIED;
3212
3213 int rc = PGMPhysGCPtr2GCPhys(pVM, GCPtr, pGCPhys);
3214
3215 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Vrc *pGCPhys=%VGp\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pGCPhys));
3216
3217 return rc;
3218}
3219
3220
3221/** @copydoc PDMDEVHLP::pfnVMState */
3222static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
3223{
3224 PDMDEV_ASSERT_DEVINS(pDevIns);
3225
3226 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMHC);
3227
3228 LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
3229 enmVMState, VMR3GetStateName(enmVMState)));
3230 return enmVMState;
3231}
3232
3233
3234/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
3235static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
3236{
3237 PDMDEV_ASSERT_DEVINS(pDevIns);
3238 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3239
3240 bool fRc = PGMPhysIsA20Enabled(pDevIns->Internal.s.pVMHC);
3241
3242 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fRc));
3243 return fRc;
3244}
3245
3246
3247/** @copydoc PDMDEVHLP::pfnA20Set */
3248static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3249{
3250 PDMDEV_ASSERT_DEVINS(pDevIns);
3251 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3252 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnable));
3253 //Assert(*(unsigned *)&fEnable <= 1);
3254 PGMR3PhysSetA20(pDevIns->Internal.s.pVMHC, fEnable);
3255}
3256
3257
3258/** @copydoc PDMDEVHLP::pfnVMReset */
3259static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns)
3260{
3261 PDMDEV_ASSERT_DEVINS(pDevIns);
3262 PVM pVM = pDevIns->Internal.s.pVMHC;
3263 VM_ASSERT_EMT(pVM);
3264 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: VM_FF_RESET %d -> 1\n",
3265 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_RESET)));
3266
3267 /*
3268 * We postpone this operation because we're likely to be inside a I/O instruction
3269 * and the EIP will be updated when we return.
3270 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3271 */
3272 bool fHaltOnReset;
3273 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3274 if (VBOX_SUCCESS(rc) && fHaltOnReset)
3275 {
3276 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3277 rc = VINF_EM_HALT;
3278 }
3279 else
3280 {
3281 VM_FF_SET(pVM, VM_FF_RESET);
3282 rc = VINF_EM_RESET;
3283 }
3284
3285 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3286 return rc;
3287}
3288
3289
3290/** @copydoc PDMDEVHLP::pfnVMSuspend */
3291static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3292{
3293 PDMDEV_ASSERT_DEVINS(pDevIns);
3294 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3295 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3296 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3297
3298 int rc = VMR3Suspend(pDevIns->Internal.s.pVMHC);
3299
3300 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3301 return rc;
3302}
3303
3304
3305/** @copydoc PDMDEVHLP::pfnVMPowerOff */
3306static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
3307{
3308 PDMDEV_ASSERT_DEVINS(pDevIns);
3309 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3310 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
3311 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3312
3313 int rc = VMR3PowerOff(pDevIns->Internal.s.pVMHC);
3314
3315 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3316 return rc;
3317}
3318
3319
3320/** @copydoc PDMDEVHLP::pfnLockVM */
3321static DECLCALLBACK(int) pdmR3DevHlp_LockVM(PPDMDEVINS pDevIns)
3322{
3323 return VMMR3Lock(pDevIns->Internal.s.pVMHC);
3324}
3325
3326
3327/** @copydoc PDMDEVHLP::pfnUnlockVM */
3328static DECLCALLBACK(int) pdmR3DevHlp_UnlockVM(PPDMDEVINS pDevIns)
3329{
3330 return VMMR3Unlock(pDevIns->Internal.s.pVMHC);
3331}
3332
3333
3334/** @copydoc PDMDEVHLP::pfnAssertVMLock */
3335static DECLCALLBACK(bool) pdmR3DevHlp_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3336{
3337 PVM pVM = pDevIns->Internal.s.pVMHC;
3338 if (VMMR3LockIsOwner(pVM))
3339 return true;
3340
3341 RTNATIVETHREAD NativeThreadOwner = VMMR3LockGetOwner(pVM);
3342 RTTHREAD ThreadOwner = RTThreadFromNative(NativeThreadOwner);
3343 char szMsg[100];
3344 RTStrPrintf(szMsg, sizeof(szMsg), "AssertVMLocked '%s'/%d ThreadOwner=%RTnthrd/%RTthrd/'%s' Self='%s'\n",
3345 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance,
3346 NativeThreadOwner, ThreadOwner, RTThreadGetName(ThreadOwner), RTThreadSelfName());
3347 AssertMsg1(szMsg, iLine, pszFile, pszFunction);
3348 AssertBreakpoint();
3349 return false;
3350}
3351
3352/** @copydoc PDMDEVHLP::pfnDMARegister */
3353static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3354{
3355 PDMDEV_ASSERT_DEVINS(pDevIns);
3356 PVM pVM = pDevIns->Internal.s.pVMHC;
3357 VM_ASSERT_EMT(pVM);
3358 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
3359 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
3360 int rc = VINF_SUCCESS;
3361 if (pVM->pdm.s.pDmac)
3362 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
3363 else
3364 {
3365 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3366 rc = VERR_PDM_NO_DMAC_INSTANCE;
3367 }
3368 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Vrc\n",
3369 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3370 return rc;
3371}
3372
3373/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
3374static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3375{
3376 PDMDEV_ASSERT_DEVINS(pDevIns);
3377 PVM pVM = pDevIns->Internal.s.pVMHC;
3378 VM_ASSERT_EMT(pVM);
3379 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
3380 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
3381 int rc = VINF_SUCCESS;
3382 if (pVM->pdm.s.pDmac)
3383 {
3384 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3385 if (pcbRead)
3386 *pcbRead = cb;
3387 }
3388 else
3389 {
3390 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3391 rc = VERR_PDM_NO_DMAC_INSTANCE;
3392 }
3393 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Vrc\n",
3394 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3395 return rc;
3396}
3397
3398/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
3399static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3400{
3401 PDMDEV_ASSERT_DEVINS(pDevIns);
3402 PVM pVM = pDevIns->Internal.s.pVMHC;
3403 VM_ASSERT_EMT(pVM);
3404 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
3405 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
3406 int rc = VINF_SUCCESS;
3407 if (pVM->pdm.s.pDmac)
3408 {
3409 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3410 if (pcbWritten)
3411 *pcbWritten = cb;
3412 }
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_DMAWriteMemory: caller='%s'/%d: returns %Vrc\n",
3419 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3420 return rc;
3421}
3422
3423/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
3424static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3425{
3426 PDMDEV_ASSERT_DEVINS(pDevIns);
3427 PVM pVM = pDevIns->Internal.s.pVMHC;
3428 VM_ASSERT_EMT(pVM);
3429 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
3430 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel, uLevel));
3431 int rc = VINF_SUCCESS;
3432 if (pVM->pdm.s.pDmac)
3433 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
3434 else
3435 {
3436 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3437 rc = VERR_PDM_NO_DMAC_INSTANCE;
3438 }
3439 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Vrc\n",
3440 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3441 return rc;
3442}
3443
3444/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
3445static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3446{
3447 PDMDEV_ASSERT_DEVINS(pDevIns);
3448 PVM pVM = pDevIns->Internal.s.pVMHC;
3449 VM_ASSERT_EMT(pVM);
3450 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
3451 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, uChannel));
3452 uint8_t u8Mode;
3453 if (pVM->pdm.s.pDmac)
3454 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
3455 else
3456 {
3457 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3458 u8Mode = 3 << 2 /* illegal mode type */;
3459 }
3460 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
3461 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Mode));
3462 return u8Mode;
3463}
3464
3465/** @copydoc PDMDEVHLP::pfnDMASchedule */
3466static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
3467{
3468 PDMDEV_ASSERT_DEVINS(pDevIns);
3469 PVM pVM = pDevIns->Internal.s.pVMHC;
3470 VM_ASSERT_EMT(pVM);
3471 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
3472 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_PDM_DMA)));
3473
3474 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3475 VM_FF_SET(pVM, VM_FF_PDM_DMA);
3476 REMR3NotifyDmaPending(pVM);
3477 VMR3NotifyFF(pVM, true);
3478}
3479
3480
3481/** @copydoc PDMDEVHLP::pfnCMOSWrite */
3482static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
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 u8Value=%#04x\n",
3489 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, u8Value));
3490 int rc;
3491 if (pVM->pdm.s.pRtc)
3492 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pVM->pdm.s.pRtc->pDevIns, iReg, u8Value);
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::pfnCMOSRead */
3503static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3504{
3505 PDMDEV_ASSERT_DEVINS(pDevIns);
3506 PVM pVM = pDevIns->Internal.s.pVMHC;
3507 VM_ASSERT_EMT(pVM);
3508
3509 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
3510 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iReg, pu8Value));
3511 int rc;
3512 if (pVM->pdm.s.pRtc)
3513 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pVM->pdm.s.pRtc->pDevIns, iReg, pu8Value);
3514 else
3515 rc = VERR_PDM_NO_RTC_INSTANCE;
3516
3517 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Vrc\n",
3518 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3519 return rc;
3520}
3521
3522
3523/** @copydoc PDMDEVHLP::pfnGetCpuId */
3524static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3525 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3526{
3527 PDMDEV_ASSERT_DEVINS(pDevIns);
3528 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
3529 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
3530 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
3531
3532 CPUMGetGuestCpuId(pDevIns->Internal.s.pVMHC, iLeaf, pEax, pEbx, pEcx, pEdx);
3533
3534 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
3535 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
3536}
3537
3538
3539/** @copydoc PDMDEVHLP::pfnROMProtectShadow */
3540static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
3541{
3542 PDMDEV_ASSERT_DEVINS(pDevIns);
3543 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%VGp cbRange=%#x\n",
3544 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, GCPhysStart, cbRange));
3545
3546 int rc = MMR3PhysRomProtect(pDevIns->Internal.s.pVMHC, GCPhysStart, cbRange);
3547
3548 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Vrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3549 return rc;
3550}
3551
3552
3553/**
3554 * @copydoc PDMDEVHLP::pfnMMIO2Register
3555 */
3556static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
3557{
3558 PDMDEV_ASSERT_DEVINS(pDevIns);
3559 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3560 LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: iRegion=#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",
3561 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, cb, fFlags, ppv, pszDesc, pszDesc));
3562
3563 int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMHC, pDevIns, iRegion, cb, fFlags, ppv, pszDesc);
3564
3565 LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3566 return rc;
3567}
3568
3569
3570/**
3571 * @copydoc PDMDEVHLP::pfnMMIO2Deregister
3572 */
3573static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
3574{
3575 PDMDEV_ASSERT_DEVINS(pDevIns);
3576 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3577 LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: iRegion=#x\n",
3578 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion));
3579
3580 AssertReturn(iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);
3581
3582 int rc = PGMR3PhysMMIO2Deregister(pDevIns->Internal.s.pVMHC, pDevIns, iRegion);
3583
3584 LogFlow(("pdmR3DevHlp_MMIO2Deregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3585 return rc;
3586}
3587
3588
3589/**
3590 * @copydoc PDMDEVHLP::pfnMMIO2Map
3591 */
3592static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
3593{
3594 PDMDEV_ASSERT_DEVINS(pDevIns);
3595 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3596 LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
3597 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
3598
3599 int rc = PGMR3PhysMMIO2Map(pDevIns->Internal.s.pVMHC, pDevIns, iRegion, GCPhys);
3600
3601 LogFlow(("pdmR3DevHlp_MMIO2Map: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3602 return rc;
3603}
3604
3605
3606/**
3607 * @copydoc PDMDEVHLP::pfnMMIO2Unmap
3608 */
3609static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
3610{
3611 PDMDEV_ASSERT_DEVINS(pDevIns);
3612 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3613 LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: iRegion=#x GCPhys=%#RGp\n",
3614 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, GCPhys));
3615
3616 int rc = PGMR3PhysMMIO2Unmap(pDevIns->Internal.s.pVMHC, pDevIns, iRegion, GCPhys);
3617
3618 LogFlow(("pdmR3DevHlp_MMIO2Unmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3619 return rc;
3620}
3621
3622
3623/**
3624 * @copydoc PDMDEVHLP::pfnMMHyperMapMMIO2
3625 */
3626static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
3627 const char *pszDesc, PRTGCPTR pGCPtr)
3628{
3629 PDMDEV_ASSERT_DEVINS(pDevIns);
3630 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
3631 LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: iRegion=#x off=%RGp cb=%RGp pszDesc=%p:{%s} pGCPtr=%p\n",
3632 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, iRegion, off, cb, pszDesc, pszDesc, pGCPtr));
3633
3634 int rc = MMR3HyperMapMMIO2(pDevIns->Internal.s.pVMHC, pDevIns, iRegion, off, cb, pszDesc, pGCPtr);
3635
3636 LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
3637 return rc;
3638}
3639
3640
3641
3642
3643
3644/** @copydoc PDMDEVHLP::pfnGetVM */
3645static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
3646{
3647 PDMDEV_ASSERT_DEVINS(pDevIns);
3648 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3649 return NULL;
3650}
3651
3652
3653/** @copydoc PDMDEVHLP::pfnPCIBusRegister */
3654static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
3655{
3656 PDMDEV_ASSERT_DEVINS(pDevIns);
3657 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3658 NOREF(pPciBusReg);
3659 NOREF(ppPciHlpR3);
3660 return VERR_ACCESS_DENIED;
3661}
3662
3663
3664/** @copydoc PDMDEVHLP::pfnPICRegister */
3665static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
3666{
3667 PDMDEV_ASSERT_DEVINS(pDevIns);
3668 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3669 NOREF(pPicReg);
3670 NOREF(ppPicHlpR3);
3671 return VERR_ACCESS_DENIED;
3672}
3673
3674
3675/** @copydoc PDMDEVHLP::pfnAPICRegister */
3676static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_APICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
3677{
3678 PDMDEV_ASSERT_DEVINS(pDevIns);
3679 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3680 NOREF(pApicReg);
3681 NOREF(ppApicHlpR3);
3682 return VERR_ACCESS_DENIED;
3683}
3684
3685
3686/** @copydoc PDMDEVHLP::pfnIOAPICRegister */
3687static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
3688{
3689 PDMDEV_ASSERT_DEVINS(pDevIns);
3690 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3691 NOREF(pIoApicReg);
3692 NOREF(ppIoApicHlpR3);
3693 return VERR_ACCESS_DENIED;
3694}
3695
3696
3697/** @copydoc PDMDEVHLP::pfnDMACRegister */
3698static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3699{
3700 PDMDEV_ASSERT_DEVINS(pDevIns);
3701 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3702 NOREF(pDmacReg);
3703 NOREF(ppDmacHlp);
3704 return VERR_ACCESS_DENIED;
3705}
3706
3707
3708/** @copydoc PDMDEVHLP::pfnPhysRead */
3709static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
3710{
3711 PDMDEV_ASSERT_DEVINS(pDevIns);
3712 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3713 NOREF(GCPhys);
3714 NOREF(pvBuf);
3715 NOREF(cbRead);
3716}
3717
3718
3719/** @copydoc PDMDEVHLP::pfnPhysWrite */
3720static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
3721{
3722 PDMDEV_ASSERT_DEVINS(pDevIns);
3723 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3724 NOREF(GCPhys);
3725 NOREF(pvBuf);
3726 NOREF(cbWrite);
3727}
3728
3729
3730/** @copydoc PDMDEVHLP::pfnPhysReadGCVirt */
3731static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
3732{
3733 PDMDEV_ASSERT_DEVINS(pDevIns);
3734 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3735 NOREF(pvDst);
3736 NOREF(GCVirtSrc);
3737 NOREF(cb);
3738 return VERR_ACCESS_DENIED;
3739}
3740
3741
3742/** @copydoc PDMDEVHLP::pfnPhysWriteGCVirt */
3743static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
3744{
3745 PDMDEV_ASSERT_DEVINS(pDevIns);
3746 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3747 NOREF(GCVirtDst);
3748 NOREF(pvSrc);
3749 NOREF(cb);
3750 return VERR_ACCESS_DENIED;
3751}
3752
3753
3754/** @copydoc PDMDEVHLP::pfnPhysReserve */
3755static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PhysReserve(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, const char *pszDesc)
3756{
3757 PDMDEV_ASSERT_DEVINS(pDevIns);
3758 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3759 NOREF(GCPhys);
3760 NOREF(cbRange);
3761 return VERR_ACCESS_DENIED;
3762}
3763
3764
3765/** @copydoc PDMDEVHLP::pfnPhys2HCVirt */
3766static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_Phys2HCVirt(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTUINT cbRange, PRTHCPTR ppvHC)
3767{
3768 PDMDEV_ASSERT_DEVINS(pDevIns);
3769 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3770 NOREF(GCPhys);
3771 NOREF(cbRange);
3772 NOREF(ppvHC);
3773 return VERR_ACCESS_DENIED;
3774}
3775
3776
3777/** @copydoc PDMDEVHLP::pfnPhysGCPtr2HCPtr */
3778static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_Obsolete_PhysGCPtr2HCPtr(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTHCPTR pHCPtr)
3779{
3780 PDMDEV_ASSERT_DEVINS(pDevIns);
3781 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3782 NOREF(GCPtr);
3783 NOREF(pHCPtr);
3784 return VERR_ACCESS_DENIED;
3785}
3786
3787
3788/** @copydoc PDMDEVHLP::pfnA20IsEnabled */
3789static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
3790{
3791 PDMDEV_ASSERT_DEVINS(pDevIns);
3792 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3793 return false;
3794}
3795
3796
3797/** @copydoc PDMDEVHLP::pfnA20Set */
3798static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3799{
3800 PDMDEV_ASSERT_DEVINS(pDevIns);
3801 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3802 NOREF(fEnable);
3803}
3804
3805
3806/** @copydoc PDMDEVHLP::pfnVMReset */
3807static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns)
3808{
3809 PDMDEV_ASSERT_DEVINS(pDevIns);
3810 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3811 return VERR_ACCESS_DENIED;
3812}
3813
3814
3815/** @copydoc PDMDEVHLP::pfnVMSuspend */
3816static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
3817{
3818 PDMDEV_ASSERT_DEVINS(pDevIns);
3819 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3820 return VERR_ACCESS_DENIED;
3821}
3822
3823
3824/** @copydoc PDMDEVHLP::pfnVMPowerOff */
3825static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
3826{
3827 PDMDEV_ASSERT_DEVINS(pDevIns);
3828 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3829 return VERR_ACCESS_DENIED;
3830}
3831
3832
3833/** @copydoc PDMDEVHLP::pfnLockVM */
3834static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_LockVM(PPDMDEVINS pDevIns)
3835{
3836 PDMDEV_ASSERT_DEVINS(pDevIns);
3837 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3838 return VERR_ACCESS_DENIED;
3839}
3840
3841
3842/** @copydoc PDMDEVHLP::pfnUnlockVM */
3843static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_UnlockVM(PPDMDEVINS pDevIns)
3844{
3845 PDMDEV_ASSERT_DEVINS(pDevIns);
3846 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3847 return VERR_ACCESS_DENIED;
3848}
3849
3850
3851/** @copydoc PDMDEVHLP::pfnAssertVMLock */
3852static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_AssertVMLock(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3853{
3854 PDMDEV_ASSERT_DEVINS(pDevIns);
3855 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3856 return false;
3857}
3858
3859
3860/** @copydoc PDMDEVHLP::pfnDMARegister */
3861static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3862{
3863 PDMDEV_ASSERT_DEVINS(pDevIns);
3864 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3865 return VERR_ACCESS_DENIED;
3866}
3867
3868
3869/** @copydoc PDMDEVHLP::pfnDMAReadMemory */
3870static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3871{
3872 PDMDEV_ASSERT_DEVINS(pDevIns);
3873 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3874 if (pcbRead)
3875 *pcbRead = 0;
3876 return VERR_ACCESS_DENIED;
3877}
3878
3879
3880/** @copydoc PDMDEVHLP::pfnDMAWriteMemory */
3881static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3882{
3883 PDMDEV_ASSERT_DEVINS(pDevIns);
3884 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3885 if (pcbWritten)
3886 *pcbWritten = 0;
3887 return VERR_ACCESS_DENIED;
3888}
3889
3890
3891/** @copydoc PDMDEVHLP::pfnDMASetDREQ */
3892static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3893{
3894 PDMDEV_ASSERT_DEVINS(pDevIns);
3895 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3896 return VERR_ACCESS_DENIED;
3897}
3898
3899
3900/** @copydoc PDMDEVHLP::pfnDMAGetChannelMode */
3901static DECLCALLBACK(uint8_t) pdmR3DevHlp_Untrusted_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3902{
3903 PDMDEV_ASSERT_DEVINS(pDevIns);
3904 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3905 return 3 << 2 /* illegal mode type */;
3906}
3907
3908
3909/** @copydoc PDMDEVHLP::pfnDMASchedule */
3910static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_DMASchedule(PPDMDEVINS pDevIns)
3911{
3912 PDMDEV_ASSERT_DEVINS(pDevIns);
3913 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3914}
3915
3916
3917/** @copydoc PDMDEVHLP::pfnCMOSWrite */
3918static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3919{
3920 PDMDEV_ASSERT_DEVINS(pDevIns);
3921 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3922 return VERR_ACCESS_DENIED;
3923}
3924
3925
3926/** @copydoc PDMDEVHLP::pfnCMOSRead */
3927static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3928{
3929 PDMDEV_ASSERT_DEVINS(pDevIns);
3930 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3931 return VERR_ACCESS_DENIED;
3932}
3933
3934
3935/** @copydoc PDMDEVHLP::pfnQueryCPUId */
3936static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_QueryCPUId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3937 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3938{
3939 PDMDEV_ASSERT_DEVINS(pDevIns);
3940 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3941}
3942
3943
3944/** @copydoc PDMDEVHLP::pfnROMProtectShadow */
3945static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange)
3946{
3947 PDMDEV_ASSERT_DEVINS(pDevIns);
3948 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3949 return VERR_ACCESS_DENIED;
3950}
3951
3952
3953/** @copydoc PDMDEVHLP::pfnMMIO2Register */
3954static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
3955{
3956 PDMDEV_ASSERT_DEVINS(pDevIns);
3957 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3958 return VERR_ACCESS_DENIED;
3959}
3960
3961
3962/** @copydoc PDMDEVHLP::pfnMMIO2Deregister */
3963static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
3964{
3965 PDMDEV_ASSERT_DEVINS(pDevIns);
3966 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3967 return VERR_ACCESS_DENIED;
3968}
3969
3970
3971/** @copydoc PDMDEVHLP::pfnMMIO2Map */
3972static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
3973{
3974 PDMDEV_ASSERT_DEVINS(pDevIns);
3975 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3976 return VERR_ACCESS_DENIED;
3977}
3978
3979
3980/** @copydoc PDMDEVHLP::pfnMMIO2Unmap */
3981static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
3982{
3983 PDMDEV_ASSERT_DEVINS(pDevIns);
3984 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3985 return VERR_ACCESS_DENIED;
3986}
3987
3988
3989/** @copydoc PDMDEVHLP::pfnMMHyperMapMMIO2 */
3990static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_MMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTGCPTR pGCPtr)
3991{
3992 PDMDEV_ASSERT_DEVINS(pDevIns);
3993 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
3994 return VERR_ACCESS_DENIED;
3995}
3996
3997
3998
3999
4000/** @copydoc PDMPICHLPR3::pfnSetInterruptFF */
4001static DECLCALLBACK(void) pdmR3PicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
4002{
4003 PDMDEV_ASSERT_DEVINS(pDevIns);
4004 PVM pVM = pDevIns->Internal.s.pVMHC;
4005 LogFlow(("pdmR3PicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 1\n",
4006 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_PIC)));
4007 VM_FF_SET(pVM, VM_FF_INTERRUPT_PIC);
4008 REMR3NotifyInterruptSet(pVM);
4009 VMR3NotifyFF(pVM, true);
4010}
4011
4012
4013/** @copydoc PDMPICHLPR3::pfnClearInterruptFF */
4014static DECLCALLBACK(void) pdmR3PicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
4015{
4016 PDMDEV_ASSERT_DEVINS(pDevIns);
4017 LogFlow(("pdmR3PicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT_PIC %d -> 0\n",
4018 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_PIC)));
4019 VM_FF_CLEAR(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_PIC);
4020 REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMHC);
4021}
4022
4023
4024/** @copydoc PDMPICHLPR3::pfnLock */
4025static DECLCALLBACK(int) pdmR3PicHlp_Lock(PPDMDEVINS pDevIns, int rc)
4026{
4027 PDMDEV_ASSERT_DEVINS(pDevIns);
4028 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
4029}
4030
4031
4032/** @copydoc PDMPICHLPR3::pfnUnlock */
4033static DECLCALLBACK(void) pdmR3PicHlp_Unlock(PPDMDEVINS pDevIns)
4034{
4035 PDMDEV_ASSERT_DEVINS(pDevIns);
4036 pdmUnlock(pDevIns->Internal.s.pVMHC);
4037}
4038
4039
4040/** @copydoc PDMPICHLPR3::pfnGetGCHelpers */
4041static DECLCALLBACK(PCPDMPICHLPGC) pdmR3PicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
4042{
4043 PDMDEV_ASSERT_DEVINS(pDevIns);
4044 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4045 RTGCPTR32 pGCHelpers = 0;
4046 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCPicHlp", &pGCHelpers);
4047 AssertReleaseRC(rc);
4048 AssertRelease(pGCHelpers);
4049 LogFlow(("pdmR3PicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
4050 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
4051 return pGCHelpers;
4052}
4053
4054
4055/** @copydoc PDMPICHLPR3::pfnGetR0Helpers */
4056static DECLCALLBACK(PCPDMPICHLPR0) pdmR3PicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4057{
4058 PDMDEV_ASSERT_DEVINS(pDevIns);
4059 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4060 PCPDMPICHLPR0 pR0Helpers = 0;
4061 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0PicHlp", &pR0Helpers);
4062 AssertReleaseRC(rc);
4063 AssertRelease(pR0Helpers);
4064 LogFlow(("pdmR3PicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4065 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4066 return pR0Helpers;
4067}
4068
4069
4070/** @copydoc PDMAPICHLPR3::pfnSetInterruptFF */
4071static DECLCALLBACK(void) pdmR3ApicHlp_SetInterruptFF(PPDMDEVINS pDevIns)
4072{
4073 PDMDEV_ASSERT_DEVINS(pDevIns);
4074 PVM pVM = pDevIns->Internal.s.pVMHC;
4075 LogFlow(("pdmR3ApicHlp_SetInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 1\n",
4076 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pVM, VM_FF_INTERRUPT_APIC)));
4077 VM_FF_SET(pVM, VM_FF_INTERRUPT_APIC);
4078 REMR3NotifyInterruptSet(pVM);
4079 VMR3NotifyFF(pVM, true);
4080}
4081
4082
4083/** @copydoc PDMAPICHLPR3::pfnClearInterruptFF */
4084static DECLCALLBACK(void) pdmR3ApicHlp_ClearInterruptFF(PPDMDEVINS pDevIns)
4085{
4086 PDMDEV_ASSERT_DEVINS(pDevIns);
4087 LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: VM_FF_INTERRUPT %d -> 0\n",
4088 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, VM_FF_ISSET(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_APIC)));
4089 VM_FF_CLEAR(pDevIns->Internal.s.pVMHC, VM_FF_INTERRUPT_APIC);
4090 REMR3NotifyInterruptClear(pDevIns->Internal.s.pVMHC);
4091}
4092
4093
4094/** @copydoc PDMAPICHLPR3::pfnChangeFeature */
4095static DECLCALLBACK(void) pdmR3ApicHlp_ChangeFeature(PPDMDEVINS pDevIns, bool fEnabled)
4096{
4097 PDMDEV_ASSERT_DEVINS(pDevIns);
4098 LogFlow(("pdmR3ApicHlp_ClearInterruptFF: caller='%s'/%d: fEnabled=%RTbool\n",
4099 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, fEnabled));
4100 if (fEnabled)
4101 CPUMSetGuestCpuIdFeature(pDevIns->Internal.s.pVMHC, CPUMCPUIDFEATURE_APIC);
4102 else
4103 CPUMClearGuestCpuIdFeature(pDevIns->Internal.s.pVMHC, CPUMCPUIDFEATURE_APIC);
4104}
4105
4106/** @copydoc PDMAPICHLPR3::pfnLock */
4107static DECLCALLBACK(int) pdmR3ApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
4108{
4109 PDMDEV_ASSERT_DEVINS(pDevIns);
4110 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
4111}
4112
4113
4114/** @copydoc PDMAPICHLPR3::pfnUnlock */
4115static DECLCALLBACK(void) pdmR3ApicHlp_Unlock(PPDMDEVINS pDevIns)
4116{
4117 PDMDEV_ASSERT_DEVINS(pDevIns);
4118 pdmUnlock(pDevIns->Internal.s.pVMHC);
4119}
4120
4121
4122/** @copydoc PDMAPICHLPR3::pfnGetGCHelpers */
4123static DECLCALLBACK(PCPDMAPICHLPGC) pdmR3ApicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
4124{
4125 PDMDEV_ASSERT_DEVINS(pDevIns);
4126 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4127 RTGCPTR32 pGCHelpers = 0;
4128 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCApicHlp", &pGCHelpers);
4129 AssertReleaseRC(rc);
4130 AssertRelease(pGCHelpers);
4131 LogFlow(("pdmR3ApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
4132 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
4133 return pGCHelpers;
4134}
4135
4136
4137/** @copydoc PDMAPICHLPR3::pfnGetR0Helpers */
4138static DECLCALLBACK(PCPDMAPICHLPR0) pdmR3ApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4139{
4140 PDMDEV_ASSERT_DEVINS(pDevIns);
4141 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4142 PCPDMAPICHLPR0 pR0Helpers = 0;
4143 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0ApicHlp", &pR0Helpers);
4144 AssertReleaseRC(rc);
4145 AssertRelease(pR0Helpers);
4146 LogFlow(("pdmR3ApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4147 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4148 return pR0Helpers;
4149}
4150
4151
4152/** @copydoc PDMIOAPICHLPR3::pfnApicBusDeliver */
4153static DECLCALLBACK(void) pdmR3IoApicHlp_ApicBusDeliver(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
4154 uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode)
4155{
4156 PDMDEV_ASSERT_DEVINS(pDevIns);
4157 PVM pVM = pDevIns->Internal.s.pVMHC;
4158 LogFlow(("pdmR3IoApicHlp_ApicBusDeliver: caller='%s'/%d: u8Dest=%RX8 u8DestMode=%RX8 u8DeliveryMode=%RX8 iVector=%RX8 u8Polarity=%RX8 u8TriggerMode=%RX8\n",
4159 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
4160 if (pVM->pdm.s.Apic.pfnBusDeliverR3)
4161 pVM->pdm.s.Apic.pfnBusDeliverR3(pVM->pdm.s.Apic.pDevInsR3, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
4162}
4163
4164
4165/** @copydoc PDMIOAPICHLPR3::pfnLock */
4166static DECLCALLBACK(int) pdmR3IoApicHlp_Lock(PPDMDEVINS pDevIns, int rc)
4167{
4168 PDMDEV_ASSERT_DEVINS(pDevIns);
4169 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
4170}
4171
4172
4173/** @copydoc PDMIOAPICHLPR3::pfnUnlock */
4174static DECLCALLBACK(void) pdmR3IoApicHlp_Unlock(PPDMDEVINS pDevIns)
4175{
4176 PDMDEV_ASSERT_DEVINS(pDevIns);
4177 pdmUnlock(pDevIns->Internal.s.pVMHC);
4178}
4179
4180
4181/** @copydoc PDMIOAPICHLPR3::pfnGetGCHelpers */
4182static DECLCALLBACK(PCPDMIOAPICHLPGC) pdmR3IoApicHlp_GetGCHelpers(PPDMDEVINS pDevIns)
4183{
4184 PDMDEV_ASSERT_DEVINS(pDevIns);
4185 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4186 RTGCPTR32 pGCHelpers = 0;
4187 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCIoApicHlp", &pGCHelpers);
4188 AssertReleaseRC(rc);
4189 AssertRelease(pGCHelpers);
4190 LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
4191 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
4192 return pGCHelpers;
4193}
4194
4195
4196/** @copydoc PDMIOAPICHLPR3::pfnGetR0Helpers */
4197static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4198{
4199 PDMDEV_ASSERT_DEVINS(pDevIns);
4200 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4201 PCPDMIOAPICHLPR0 pR0Helpers = 0;
4202 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0IoApicHlp", &pR0Helpers);
4203 AssertReleaseRC(rc);
4204 AssertRelease(pR0Helpers);
4205 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4206 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4207 return pR0Helpers;
4208}
4209
4210
4211/** @copydoc PDMPCIHLPR3::pfnIsaSetIrq */
4212static DECLCALLBACK(void) pdmR3PciHlp_IsaSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
4213{
4214 PDMDEV_ASSERT_DEVINS(pDevIns);
4215 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
4216 PDMIsaSetIrq(pDevIns->Internal.s.pVMHC, iIrq, iLevel);
4217}
4218
4219
4220/** @copydoc PDMPCIHLPR3::pfnIoApicSetIrq */
4221static DECLCALLBACK(void) pdmR3PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
4222{
4223 PDMDEV_ASSERT_DEVINS(pDevIns);
4224 Log4(("pdmR3PciHlp_IsaSetIrq: iIrq=%d iLevel=%d\n", iIrq, iLevel));
4225 PDMIoApicSetIrq(pDevIns->Internal.s.pVMHC, iIrq, iLevel);
4226}
4227
4228
4229/** @copydoc PDMPCIHLPR3::pfnIsMMIO2Base */
4230static DECLCALLBACK(bool) pdmR3PciHlp_IsMMIO2Base(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys)
4231{
4232 PDMDEV_ASSERT_DEVINS(pDevIns);
4233 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4234 bool fRc = PGMR3PhysMMIO2IsBase(pDevIns->Internal.s.pVMHC, pOwner, GCPhys);
4235 Log4(("pdmR3PciHlp_IsMMIO2Base: pOwner=%p GCPhys=%RGp -> %RTbool\n", pOwner, GCPhys, fRc));
4236 return fRc;
4237}
4238
4239
4240/** @copydoc PDMPCIHLPR3::pfnLock */
4241static DECLCALLBACK(int) pdmR3PciHlp_Lock(PPDMDEVINS pDevIns, int rc)
4242{
4243 PDMDEV_ASSERT_DEVINS(pDevIns);
4244 return pdmLockEx(pDevIns->Internal.s.pVMHC, rc);
4245}
4246
4247
4248/** @copydoc PDMPCIHLPR3::pfnUnlock */
4249static DECLCALLBACK(void) pdmR3PciHlp_Unlock(PPDMDEVINS pDevIns)
4250{
4251 PDMDEV_ASSERT_DEVINS(pDevIns);
4252 pdmUnlock(pDevIns->Internal.s.pVMHC);
4253}
4254
4255
4256/** @copydoc PDMPCIHLPR3::pfnGetGCHelpers */
4257static DECLCALLBACK(PCPDMPCIHLPGC) pdmR3PciHlp_GetGCHelpers(PPDMDEVINS pDevIns)
4258{
4259 PDMDEV_ASSERT_DEVINS(pDevIns);
4260 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4261 RTGCPTR32 pGCHelpers = 0;
4262 int rc = PDMR3GetSymbolGC(pDevIns->Internal.s.pVMHC, NULL, "g_pdmGCPciHlp", &pGCHelpers);
4263 AssertReleaseRC(rc);
4264 AssertRelease(pGCHelpers);
4265 LogFlow(("pdmR3IoApicHlp_GetGCHelpers: caller='%s'/%d: returns %VGv\n",
4266 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pGCHelpers));
4267 return pGCHelpers;
4268}
4269
4270
4271/** @copydoc PDMPCIHLPR3::pfnGetR0Helpers */
4272static DECLCALLBACK(PCPDMPCIHLPR0) pdmR3PciHlp_GetR0Helpers(PPDMDEVINS pDevIns)
4273{
4274 PDMDEV_ASSERT_DEVINS(pDevIns);
4275 VM_ASSERT_EMT(pDevIns->Internal.s.pVMHC);
4276 PCPDMPCIHLPR0 pR0Helpers = 0;
4277 int rc = PDMR3GetSymbolR0(pDevIns->Internal.s.pVMHC, NULL, "g_pdmR0PciHlp", &pR0Helpers);
4278 AssertReleaseRC(rc);
4279 AssertRelease(pR0Helpers);
4280 LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %VHv\n",
4281 pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pR0Helpers));
4282 return pR0Helpers;
4283}
4284
4285
4286/**
4287 * Locates a LUN.
4288 *
4289 * @returns VBox status code.
4290 * @param pVM VM Handle.
4291 * @param pszDevice Device name.
4292 * @param iInstance Device instance.
4293 * @param iLun The Logical Unit to obtain the interface of.
4294 * @param ppLun Where to store the pointer to the LUN if found.
4295 * @thread Try only do this in EMT...
4296 */
4297int pdmR3DevFindLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMLUN *ppLun)
4298{
4299 /*
4300 * Iterate registered devices looking for the device.
4301 */
4302 RTUINT cchDevice = strlen(pszDevice);
4303 for (PPDMDEV pDev = pVM->pdm.s.pDevs; pDev; pDev = pDev->pNext)
4304 {
4305 if ( pDev->cchName == cchDevice
4306 && !memcmp(pDev->pDevReg->szDeviceName, pszDevice, cchDevice))
4307 {
4308 /*
4309 * Iterate device instances.
4310 */
4311 for (PPDMDEVINS pDevIns = pDev->pInstances; pDevIns; pDevIns = pDevIns->Internal.s.pPerDeviceNextHC)
4312 {
4313 if (pDevIns->iInstance == iInstance)
4314 {
4315 /*
4316 * Iterate luns.
4317 */
4318 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsHC; pLun; pLun = pLun->pNext)
4319 {
4320 if (pLun->iLun == iLun)
4321 {
4322 *ppLun = pLun;
4323 return VINF_SUCCESS;
4324 }
4325 }
4326 return VERR_PDM_LUN_NOT_FOUND;
4327 }
4328 }
4329 return VERR_PDM_DEVICE_INSTANCE_NOT_FOUND;
4330 }
4331 }
4332 return VERR_PDM_DEVICE_NOT_FOUND;
4333}
4334
4335
4336/**
4337 * Attaches a preconfigured driver to an existing device instance.
4338 *
4339 * This is used to change drivers and suchlike at runtime.
4340 *
4341 * @returns VBox status code.
4342 * @param pVM VM Handle.
4343 * @param pszDevice Device name.
4344 * @param iInstance Device instance.
4345 * @param iLun The Logical Unit to obtain the interface of.
4346 * @param ppBase Where to store the base interface pointer. Optional.
4347 * @thread EMT
4348 */
4349PDMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
4350{
4351 VM_ASSERT_EMT(pVM);
4352 LogFlow(("PDMR3DeviceAttach: pszDevice=%p:{%s} iInstance=%d iLun=%d ppBase=%p\n",
4353 pszDevice, pszDevice, iInstance, iLun, ppBase));
4354
4355 /*
4356 * Find the LUN in question.
4357 */
4358 PPDMLUN pLun;
4359 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
4360 if (VBOX_SUCCESS(rc))
4361 {
4362 /*
4363 * Can we attach anything at runtime?
4364 */
4365 PPDMDEVINS pDevIns = pLun->pDevIns;
4366 if (pDevIns->pDevReg->pfnAttach)
4367 {
4368 if (!pLun->pTop)
4369 {
4370 rc = pDevIns->pDevReg->pfnAttach(pDevIns, iLun);
4371
4372 }
4373 else
4374 rc = VERR_PDM_DRIVER_ALREADY_ATTACHED;
4375 }
4376 else
4377 rc = VERR_PDM_DEVICE_NO_RT_ATTACH;
4378
4379 if (ppBase)
4380 *ppBase = pLun->pTop ? &pLun->pTop->IBase : NULL;
4381 }
4382 else if (ppBase)
4383 *ppBase = NULL;
4384
4385 if (ppBase)
4386 LogFlow(("PDMR3DeviceAttach: returns %Vrc *ppBase=%p\n", rc, *ppBase));
4387 else
4388 LogFlow(("PDMR3DeviceAttach: returns %Vrc\n", rc));
4389 return rc;
4390}
4391
4392
4393/**
4394 * Detaches a driver chain from an existing device instance.
4395 *
4396 * This is used to change drivers and suchlike at runtime.
4397 *
4398 * @returns VBox status code.
4399 * @param pVM VM Handle.
4400 * @param pszDevice Device name.
4401 * @param iInstance Device instance.
4402 * @param iLun The Logical Unit to obtain the interface of.
4403 * @thread EMT
4404 */
4405PDMR3DECL(int) PDMR3DeviceDetach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun)
4406{
4407 VM_ASSERT_EMT(pVM);
4408 LogFlow(("PDMR3DeviceDetach: pszDevice=%p:{%s} iInstance=%d iLun=%d\n",
4409 pszDevice, pszDevice, iInstance, iLun));
4410
4411 /*
4412 * Find the LUN in question.
4413 */
4414 PPDMLUN pLun;
4415 int rc = pdmR3DevFindLun(pVM, pszDevice, iInstance, iLun, &pLun);
4416 if (VBOX_SUCCESS(rc))
4417 {
4418 /*
4419 * Can we detach anything at runtime?
4420 */
4421 PPDMDEVINS pDevIns = pLun->pDevIns;
4422 if (pDevIns->pDevReg->pfnDetach)
4423 {
4424 if (pLun->pTop)
4425 rc = pdmR3DrvDetach(pLun->pTop);
4426 else
4427 rc = VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN;
4428 }
4429 else
4430 rc = VERR_PDM_DEVICE_NO_RT_DETACH;
4431 }
4432
4433 LogFlow(("PDMR3DeviceDetach: returns %Vrc\n", rc));
4434 return rc;
4435}
4436
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