VirtualBox

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

Last change on this file since 9098 was 8564, checked in by vboxsync, 17 years ago

NoDmik -> NOT_DMIK.

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