VirtualBox

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

Last change on this file since 7802 was 7768, checked in by vboxsync, 17 years ago

Added a VMState dev/usb/drvhlp.

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