VirtualBox

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

Last change on this file since 11938 was 11311, checked in by vboxsync, 16 years ago

VMM: ELEMENTS -> RT_ELEMENTS.

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