VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp@ 88344

Last change on this file since 88344 was 88306, checked in by vboxsync, 4 years ago

VMM/PDMDevHlp: Added pfnSTAMDeregisterByPrefix. bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 207.7 KB
Line 
1/* $Id: PDMDevHlp.cpp 88306 2021-03-26 21:17:46Z vboxsync $ */
2/** @file
3 * PDM - Pluggable Device and Driver Manager, Device Helpers.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM_DEVICE
23#define PDMPCIDEV_INCLUDE_PRIVATE /* Hack to get pdmpcidevint.h included at the right point. */
24#include "PDMInternal.h"
25#include <VBox/vmm/pdm.h>
26#include <VBox/vmm/mm.h>
27#include <VBox/vmm/hm.h>
28#include <VBox/vmm/pgm.h>
29#include <VBox/vmm/iom.h>
30#include <VBox/vmm/dbgf.h>
31#include <VBox/vmm/ssm.h>
32#include <VBox/vmm/vmapi.h>
33#include <VBox/vmm/vmm.h>
34#include <VBox/vmm/vmcc.h>
35
36#include <VBox/version.h>
37#include <VBox/log.h>
38#include <VBox/pci.h>
39#include <VBox/err.h>
40#include <iprt/asm.h>
41#include <iprt/assert.h>
42#include <iprt/ctype.h>
43#include <iprt/string.h>
44#include <iprt/thread.h>
45#include <iprt/mem.h>
46
47#include "dtrace/VBoxVMM.h"
48#include "PDMInline.h"
49
50
51/*********************************************************************************************************************************
52* Defined Constants And Macros *
53*********************************************************************************************************************************/
54/** @def PDM_DEVHLP_DEADLOCK_DETECTION
55 * Define this to enable the deadlock detection when accessing physical memory.
56 */
57#if /*defined(DEBUG_bird) ||*/ defined(DOXYGEN_RUNNING)
58# define PDM_DEVHLP_DEADLOCK_DETECTION /**< @todo enable DevHlp deadlock detection! */
59#endif
60
61
62
63/** @name R3 DevHlp
64 * @{
65 */
66
67
68/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortCreateEx} */
69static DECLCALLBACK(int) pdmR3DevHlp_IoPortCreateEx(PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
70 uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
71 PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, RTR3PTR pvUser,
72 const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
73{
74 PDMDEV_ASSERT_DEVINS(pDevIns);
75 LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: cPorts=%#x fFlags=%#x pPciDev=%p iPciRegion=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p pszDesc=%p:{%s} paExtDescs=%p phIoPorts=%p\n",
76 pDevIns->pReg->szName, pDevIns->iInstance, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr,
77 pvUser, pszDesc, pszDesc, paExtDescs, phIoPorts));
78 PVM pVM = pDevIns->Internal.s.pVMR3;
79 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
80 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
81
82 int rc = IOMR3IoPortCreate(pVM, pDevIns, cPorts, fFlags, pPciDev, iPciRegion,
83 pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, paExtDescs, phIoPorts);
84
85 LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: returns %Rrc (*phIoPorts=%#x)\n",
86 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phIoPorts));
87 return rc;
88}
89
90
91/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortMap} */
92static DECLCALLBACK(int) pdmR3DevHlp_IoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port)
93{
94 PDMDEV_ASSERT_DEVINS(pDevIns);
95 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x Port=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, Port));
96 PVM pVM = pDevIns->Internal.s.pVMR3;
97 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
98
99 int rc = IOMR3IoPortMap(pVM, pDevIns, hIoPorts, Port);
100
101 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
102 return rc;
103}
104
105
106/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortUnmap} */
107static DECLCALLBACK(int) pdmR3DevHlp_IoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
108{
109 PDMDEV_ASSERT_DEVINS(pDevIns);
110 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
111 PVM pVM = pDevIns->Internal.s.pVMR3;
112 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
113
114 int rc = IOMR3IoPortUnmap(pVM, pDevIns, hIoPorts);
115
116 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
117 return rc;
118}
119
120
121/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortGetMappingAddress} */
122static DECLCALLBACK(uint32_t) pdmR3DevHlp_IoPortGetMappingAddress(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
123{
124 PDMDEV_ASSERT_DEVINS(pDevIns);
125 LogFlow(("pdmR3DevHlp_IoPortGetMappingAddress: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
126
127 uint32_t uAddress = IOMR3IoPortGetMappingAddress(pDevIns->Internal.s.pVMR3, pDevIns, hIoPorts);
128
129 LogFlow(("pdmR3DevHlp_IoPortGetMappingAddress: caller='%s'/%d: returns %#RX32\n", pDevIns->pReg->szName, pDevIns->iInstance, uAddress));
130 return uAddress;
131}
132
133
134/** @interface_method_impl{PDMDEVHLPR3,pfnMmioCreateEx} */
135static DECLCALLBACK(int) pdmR3DevHlp_MmioCreateEx(PPDMDEVINS pDevIns, RTGCPHYS cbRegion,
136 uint32_t fFlags, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
137 PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill,
138 void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion)
139{
140 PDMDEV_ASSERT_DEVINS(pDevIns);
141 LogFlow(("pdmR3DevHlp_MmioCreateEx: caller='%s'/%d: cbRegion=%#RGp fFlags=%#x pPciDev=%p iPciRegion=%#x pfnWrite=%p pfnRead=%p pfnFill=%p pvUser=%p pszDesc=%p:{%s} phRegion=%p\n",
142 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, fFlags, pPciDev, iPciRegion, pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, pszDesc, phRegion));
143 PVM pVM = pDevIns->Internal.s.pVMR3;
144 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
145 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE);
146
147 if (pDevIns->iInstance > 0)
148 {
149 pszDesc = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);
150 AssertReturn(pszDesc, VERR_NO_STR_MEMORY);
151 }
152
153 /* HACK ALERT! Round the size up to page size. The PCI bus should do something similar before mapping it. */
154 /** @todo It's possible we need to do dummy MMIO fill-in of the PCI bus or
155 * guest adds more alignment to an region. */
156 cbRegion = RT_ALIGN_T(cbRegion, PAGE_SIZE, RTGCPHYS);
157
158 int rc = IOMR3MmioCreate(pVM, pDevIns, cbRegion, fFlags, pPciDev, iPciRegion,
159 pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, phRegion);
160
161 LogFlow(("pdmR3DevHlp_MmioCreateEx: caller='%s'/%d: returns %Rrc (*phRegion=%#x)\n",
162 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phRegion));
163 return rc;
164}
165
166
167/** @interface_method_impl{PDMDEVHLPR3,pfnMmioMap} */
168static DECLCALLBACK(int) pdmR3DevHlp_MmioMap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys)
169{
170 PDMDEV_ASSERT_DEVINS(pDevIns);
171 LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: hRegion=%#x GCPhys=%#RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, GCPhys));
172 PVM pVM = pDevIns->Internal.s.pVMR3;
173 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
174
175 int rc = IOMR3MmioMap(pVM, pDevIns, hRegion, GCPhys);
176
177 LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
178 return rc;
179}
180
181
182/** @interface_method_impl{PDMDEVHLPR3,pfnMmioUnmap} */
183static DECLCALLBACK(int) pdmR3DevHlp_MmioUnmap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
184{
185 PDMDEV_ASSERT_DEVINS(pDevIns);
186 LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: hRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
187 PVM pVM = pDevIns->Internal.s.pVMR3;
188 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
189
190 int rc = IOMR3MmioUnmap(pVM, pDevIns, hRegion);
191
192 LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
193 return rc;
194}
195
196
197/** @interface_method_impl{PDMDEVHLPR3,pfnMmioReduce} */
198static DECLCALLBACK(int) pdmR3DevHlp_MmioReduce(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion)
199{
200 PDMDEV_ASSERT_DEVINS(pDevIns);
201 LogFlow(("pdmR3DevHlp_MmioReduce: caller='%s'/%d: hRegion=%#x cbRegion=%#RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, cbRegion));
202 PVM pVM = pDevIns->Internal.s.pVMR3;
203 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
204 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_LOADING, VERR_VM_INVALID_VM_STATE);
205
206 int rc = IOMR3MmioReduce(pVM, pDevIns, hRegion, cbRegion);
207
208 LogFlow(("pdmR3DevHlp_MmioReduce: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
209 return rc;
210}
211
212
213/** @interface_method_impl{PDMDEVHLPR3,pfnMmioGetMappingAddress} */
214static DECLCALLBACK(RTGCPHYS) pdmR3DevHlp_MmioGetMappingAddress(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
215{
216 PDMDEV_ASSERT_DEVINS(pDevIns);
217 LogFlow(("pdmR3DevHlp_MmioGetMappingAddress: caller='%s'/%d: hRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
218
219 RTGCPHYS GCPhys = IOMR3MmioGetMappingAddress(pDevIns->Internal.s.pVMR3, pDevIns, hRegion);
220
221 LogFlow(("pdmR3DevHlp_MmioGetMappingAddress: caller='%s'/%d: returns %RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys));
222 return GCPhys;
223}
224
225
226/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Create} */
227static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Create(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iPciRegion, RTGCPHYS cbRegion,
228 uint32_t fFlags, const char *pszDesc, void **ppvMapping, PPGMMMIO2HANDLE phRegion)
229{
230 PDMDEV_ASSERT_DEVINS(pDevIns);
231 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
232 LogFlow(("pdmR3DevHlp_Mmio2Create: caller='%s'/%d: pPciDev=%p (%#x) iPciRegion=%#x cbRegion=%#RGp fFlags=%RX32 pszDesc=%p:{%s} ppvMapping=%p phRegion=%p\n",
233 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iPciRegion, cbRegion,
234 fFlags, pszDesc, pszDesc, ppvMapping, phRegion));
235 *ppvMapping = NULL;
236 *phRegion = NIL_PGMMMIO2HANDLE;
237 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);
238
239 PVM pVM = pDevIns->Internal.s.pVMR3;
240 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
241 AssertMsgReturn( pVM->enmVMState == VMSTATE_CREATING
242 || pVM->enmVMState == VMSTATE_LOADING,
243 ("state %s, expected CREATING or LOADING\n", VMGetStateName(pVM->enmVMState)), VERR_VM_INVALID_VM_STATE);
244
245 AssertReturn(!(iPciRegion & UINT16_MAX), VERR_INVALID_PARAMETER); /* not implemented. */
246
247 /** @todo PGMR3PhysMmio2Register mangles the description, move it here and
248 * use a real string cache. */
249 int rc = PGMR3PhysMmio2Register(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iPciRegion >> 16,
250 cbRegion, fFlags, pszDesc, ppvMapping, phRegion);
251
252 LogFlow(("pdmR3DevHlp_Mmio2Create: caller='%s'/%d: returns %Rrc *ppvMapping=%p phRegion=%#RX64\n",
253 pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppvMapping, *phRegion));
254 return rc;
255}
256
257
258/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Destroy} */
259static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Destroy(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
260{
261 PDMDEV_ASSERT_DEVINS(pDevIns);
262 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
263 LogFlow(("pdmR3DevHlp_Mmio2Destroy: caller='%s'/%d: hRegion=%#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
264
265 PVM pVM = pDevIns->Internal.s.pVMR3;
266 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
267 AssertMsgReturn( pVM->enmVMState == VMSTATE_DESTROYING
268 || pVM->enmVMState == VMSTATE_LOADING,
269 ("state %s, expected DESTROYING or LOADING\n", VMGetStateName(pVM->enmVMState)), VERR_VM_INVALID_VM_STATE);
270
271 int rc = PGMR3PhysMmio2Deregister(pDevIns->Internal.s.pVMR3, pDevIns, hRegion);
272
273 LogFlow(("pdmR3DevHlp_Mmio2Destroy: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
274 return rc;
275}
276
277
278/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Map} */
279static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Map(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS GCPhys)
280{
281 PDMDEV_ASSERT_DEVINS(pDevIns);
282 LogFlow(("pdmR3DevHlp_Mmio2Map: caller='%s'/%d: hRegion=%#RX64 GCPhys=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, GCPhys));
283
284 PVM pVM = pDevIns->Internal.s.pVMR3;
285 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
286
287 int rc = PGMR3PhysMmio2Map(pDevIns->Internal.s.pVMR3, pDevIns, hRegion, GCPhys);
288
289 LogFlow(("pdmR3DevHlp_Mmio2Map: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
290 return rc;
291}
292
293
294/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Unmap} */
295static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Unmap(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
296{
297 PDMDEV_ASSERT_DEVINS(pDevIns);
298 LogFlow(("pdmR3DevHlp_Mmio2Unmap: caller='%s'/%d: hRegion=%#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
299
300 PVM pVM = pDevIns->Internal.s.pVMR3;
301 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
302
303 int rc = PGMR3PhysMmio2Unmap(pDevIns->Internal.s.pVMR3, pDevIns, hRegion, NIL_RTGCPHYS);
304
305 LogFlow(("pdmR3DevHlp_Mmio2Unmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
306 return rc;
307}
308
309
310/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Reduce} */
311static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Reduce(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS cbRegion)
312{
313 PDMDEV_ASSERT_DEVINS(pDevIns);
314 LogFlow(("pdmR3DevHlp_Mmio2Reduce: caller='%s'/%d: hRegion=%#RX64 cbRegion=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, cbRegion));
315 PVM pVM = pDevIns->Internal.s.pVMR3;
316 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
317 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_LOADING, VERR_VM_INVALID_VM_STATE);
318
319 int rc = PGMR3PhysMmio2Reduce(pDevIns->Internal.s.pVMR3, pDevIns, hRegion, cbRegion);
320
321 LogFlow(("pdmR3DevHlp_Mmio2Reduce: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
322 return rc;
323}
324
325
326/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2GetMappingAddress} */
327static DECLCALLBACK(RTGCPHYS) pdmR3DevHlp_Mmio2GetMappingAddress(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
328{
329 PDMDEV_ASSERT_DEVINS(pDevIns);
330 PVM pVM = pDevIns->Internal.s.pVMR3;
331 LogFlow(("pdmR3DevHlp_Mmio2GetMappingAddress: caller='%s'/%d: hRegion=%#RX6r\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
332 VM_ASSERT_EMT0_RETURN(pVM, NIL_RTGCPHYS);
333
334 RTGCPHYS GCPhys = PGMR3PhysMmio2GetMappingAddress(pVM, pDevIns, hRegion);
335
336 LogFlow(("pdmR3DevHlp_Mmio2GetMappingAddress: caller='%s'/%d: returns %RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys));
337 return GCPhys;
338}
339
340/**
341 * @copydoc PDMDEVHLPR3::pfnMmio2ChangeRegionNo
342 */
343static DECLCALLBACK(int) pdmR3DevHlp_Mmio2ChangeRegionNo(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, uint32_t iNewRegion)
344{
345 PDMDEV_ASSERT_DEVINS(pDevIns);
346 PVM pVM = pDevIns->Internal.s.pVMR3;
347 LogFlow(("pdmR3DevHlp_Mmio2ChangeRegionNo: caller='%s'/%d: hRegion=%#RX6r iNewRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, iNewRegion));
348 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
349
350 int rc = PGMR3PhysMmio2ChangeRegionNo(pVM, pDevIns, hRegion, iNewRegion);
351
352 LogFlow(("pdmR3DevHlp_Mmio2ChangeRegionNo: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
353 return rc;
354}
355
356
357/** @interface_method_impl{PDMDEVHLPR3,pfnROMRegister} */
358static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange,
359 const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc)
360{
361 PDMDEV_ASSERT_DEVINS(pDevIns);
362 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
363 LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%RGp cbRange=%#x pvBinary=%p cbBinary=%#x fFlags=%#RX32 pszDesc=%p:{%s}\n",
364 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, cbBinary, fFlags, pszDesc, pszDesc));
365
366/** @todo can we mangle pszDesc? */
367 int rc = PGMR3PhysRomRegister(pDevIns->Internal.s.pVMR3, pDevIns, GCPhysStart, cbRange, pvBinary, cbBinary, fFlags, pszDesc);
368
369 LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
370 return rc;
371}
372
373
374/** @interface_method_impl{PDMDEVHLPR3,pfnROMProtectShadow} */
375static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, PGMROMPROT enmProt)
376{
377 PDMDEV_ASSERT_DEVINS(pDevIns);
378 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%RGp cbRange=%#x enmProt=%d\n",
379 pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, enmProt));
380
381 int rc = PGMR3PhysRomProtect(pDevIns->Internal.s.pVMR3, GCPhysStart, cbRange, enmProt);
382
383 LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
384 return rc;
385}
386
387
388/** @interface_method_impl{PDMDEVHLPR3,pfnSSMRegister} */
389static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
390 PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
391 PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
392 PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
393{
394 PDMDEV_ASSERT_DEVINS(pDevIns);
395 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
396 LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: uVersion=%#x cbGuess=%#x pszBefore=%p:{%s}\n"
397 " pfnLivePrep=%p pfnLiveExec=%p pfnLiveVote=%p pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoadDone=%p\n",
398 pDevIns->pReg->szName, pDevIns->iInstance, uVersion, cbGuess, pszBefore, pszBefore,
399 pfnLivePrep, pfnLiveExec, pfnLiveVote,
400 pfnSavePrep, pfnSaveExec, pfnSaveDone,
401 pfnLoadPrep, pfnLoadExec, pfnLoadDone));
402
403 int rc = SSMR3RegisterDevice(pDevIns->Internal.s.pVMR3, pDevIns, pDevIns->pReg->szName, pDevIns->iInstance,
404 uVersion, cbGuess, pszBefore,
405 pfnLivePrep, pfnLiveExec, pfnLiveVote,
406 pfnSavePrep, pfnSaveExec, pfnSaveDone,
407 pfnLoadPrep, pfnLoadExec, pfnLoadDone);
408
409 LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
410 return rc;
411}
412
413
414/** @interface_method_impl{PDMDEVHLPR3,pfnTimerCreate} */
415static DECLCALLBACK(int) pdmR3DevHlp_TimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback,
416 void *pvUser, uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer)
417{
418 PDMDEV_ASSERT_DEVINS(pDevIns);
419 PVM pVM = pDevIns->Internal.s.pVMR3;
420 VM_ASSERT_EMT(pVM);
421 LogFlow(("pdmR3DevHlp_TimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pvUser=%p fFlags=%#x pszDesc=%p:{%s} phTimer=%p\n",
422 pDevIns->pReg->szName, pDevIns->iInstance, enmClock, pfnCallback, pvUser, fFlags, pszDesc, pszDesc, phTimer));
423
424 /* Mangle the timer name if there are more than one instance of this device. */
425 char szName[32];
426 AssertReturn(strlen(pszDesc) < sizeof(szName) - 3, VERR_INVALID_NAME);
427 if (pDevIns->iInstance > 0)
428 {
429 RTStrPrintf(szName, sizeof(szName), "%s[%u]", pszDesc, pDevIns->iInstance);
430 pszDesc = szName;
431 }
432
433 /* Clear the ring-0 flag if the device isn't configured for ring-0. */
434 if (fFlags & TMTIMER_FLAGS_RING0)
435 {
436 Assert(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_R0);
437 if (!(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED))
438 fFlags &= ~TMTIMER_FLAGS_RING0;
439 }
440 else
441 Assert(fFlags & TMTIMER_FLAGS_NO_RING0 /* just to make sure all devices has been considered */);
442
443 int rc = TMR3TimerCreateDevice(pVM, pDevIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, phTimer);
444
445 LogFlow(("pdmR3DevHlp_TimerCreate: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
446 return rc;
447}
448
449
450/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromMicro} */
451static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
452{
453 PDMDEV_ASSERT_DEVINS(pDevIns);
454 return TMTimerFromMicro(pDevIns->Internal.s.pVMR3, hTimer, cMicroSecs);
455}
456
457
458/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromMilli} */
459static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromMilli(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
460{
461 PDMDEV_ASSERT_DEVINS(pDevIns);
462 return TMTimerFromMilli(pDevIns->Internal.s.pVMR3, hTimer, cMilliSecs);
463}
464
465
466/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromNano} */
467static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
468{
469 PDMDEV_ASSERT_DEVINS(pDevIns);
470 return TMTimerFromNano(pDevIns->Internal.s.pVMR3, hTimer, cNanoSecs);
471}
472
473/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGet} */
474static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
475{
476 PDMDEV_ASSERT_DEVINS(pDevIns);
477 return TMTimerGet(pDevIns->Internal.s.pVMR3, hTimer);
478}
479
480
481/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGetFreq} */
482static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGetFreq(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
483{
484 PDMDEV_ASSERT_DEVINS(pDevIns);
485 return TMTimerGetFreq(pDevIns->Internal.s.pVMR3, hTimer);
486}
487
488
489/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGetNano} */
490static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
491{
492 PDMDEV_ASSERT_DEVINS(pDevIns);
493 return TMTimerGetNano(pDevIns->Internal.s.pVMR3, hTimer);
494}
495
496
497/** @interface_method_impl{PDMDEVHLPR3,pfnTimerIsActive} */
498static DECLCALLBACK(bool) pdmR3DevHlp_TimerIsActive(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
499{
500 PDMDEV_ASSERT_DEVINS(pDevIns);
501 return TMTimerIsActive(pDevIns->Internal.s.pVMR3, hTimer);
502}
503
504
505/** @interface_method_impl{PDMDEVHLPR3,pfnTimerIsLockOwner} */
506static DECLCALLBACK(bool) pdmR3DevHlp_TimerIsLockOwner(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
507{
508 PDMDEV_ASSERT_DEVINS(pDevIns);
509 return TMTimerIsLockOwner(pDevIns->Internal.s.pVMR3, hTimer);
510}
511
512
513/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLockClock} */
514static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlp_TimerLockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy)
515{
516 PDMDEV_ASSERT_DEVINS(pDevIns);
517 return TMTimerLock(pDevIns->Internal.s.pVMR3, hTimer, rcBusy);
518}
519
520
521/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLockClock2} */
522static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlp_TimerLockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer,
523 PPDMCRITSECT pCritSect, int rcBusy)
524{
525 PDMDEV_ASSERT_DEVINS(pDevIns);
526 VBOXSTRICTRC rc = TMTimerLock(pDevIns->Internal.s.pVMR3, hTimer, rcBusy);
527 if (rc == VINF_SUCCESS)
528 {
529 rc = PDMCritSectEnter(pCritSect, rcBusy);
530 if (rc == VINF_SUCCESS)
531 return rc;
532 AssertRC(VBOXSTRICTRC_VAL(rc));
533 TMTimerUnlock(pDevIns->Internal.s.pVMR3, hTimer);
534 }
535 else
536 AssertRC(VBOXSTRICTRC_VAL(rc));
537 return rc;
538}
539
540
541/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSet} */
542static DECLCALLBACK(int) pdmR3DevHlp_TimerSet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
543{
544 PDMDEV_ASSERT_DEVINS(pDevIns);
545 return TMTimerSet(pDevIns->Internal.s.pVMR3, hTimer, uExpire);
546}
547
548
549/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetFrequencyHint} */
550static DECLCALLBACK(int) pdmR3DevHlp_TimerSetFrequencyHint(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz)
551{
552 PDMDEV_ASSERT_DEVINS(pDevIns);
553 return TMTimerSetFrequencyHint(pDevIns->Internal.s.pVMR3, hTimer, uHz);
554}
555
556
557/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetMicro} */
558static DECLCALLBACK(int) pdmR3DevHlp_TimerSetMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
559{
560 PDMDEV_ASSERT_DEVINS(pDevIns);
561 return TMTimerSetMicro(pDevIns->Internal.s.pVMR3, hTimer, cMicrosToNext);
562}
563
564
565/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetMillies} */
566static DECLCALLBACK(int) pdmR3DevHlp_TimerSetMillies(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
567{
568 PDMDEV_ASSERT_DEVINS(pDevIns);
569 return TMTimerSetMillies(pDevIns->Internal.s.pVMR3, hTimer, cMilliesToNext);
570}
571
572
573/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetNano} */
574static DECLCALLBACK(int) pdmR3DevHlp_TimerSetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
575{
576 PDMDEV_ASSERT_DEVINS(pDevIns);
577 return TMTimerSetNano(pDevIns->Internal.s.pVMR3, hTimer, cNanosToNext);
578}
579
580
581/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetRelative} */
582static DECLCALLBACK(int) pdmR3DevHlp_TimerSetRelative(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
583{
584 PDMDEV_ASSERT_DEVINS(pDevIns);
585 return TMTimerSetRelative(pDevIns->Internal.s.pVMR3, hTimer, cTicksToNext, pu64Now);
586}
587
588
589/** @interface_method_impl{PDMDEVHLPR3,pfnTimerStop} */
590static DECLCALLBACK(int) pdmR3DevHlp_TimerStop(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
591{
592 PDMDEV_ASSERT_DEVINS(pDevIns);
593 return TMTimerStop(pDevIns->Internal.s.pVMR3, hTimer);
594}
595
596
597/** @interface_method_impl{PDMDEVHLPR3,pfnTimerUnlockClock} */
598static DECLCALLBACK(void) pdmR3DevHlp_TimerUnlockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
599{
600 PDMDEV_ASSERT_DEVINS(pDevIns);
601 TMTimerUnlock(pDevIns->Internal.s.pVMR3, hTimer);
602}
603
604
605/** @interface_method_impl{PDMDEVHLPR3,pfnTimerUnlockClock2} */
606static DECLCALLBACK(void) pdmR3DevHlp_TimerUnlockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
607{
608 PDMDEV_ASSERT_DEVINS(pDevIns);
609 TMTimerUnlock(pDevIns->Internal.s.pVMR3, hTimer);
610 int rc = PDMCritSectLeave(pCritSect);
611 AssertRC(rc);
612}
613
614
615/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetCritSect} */
616static DECLCALLBACK(int) pdmR3DevHlp_TimerSetCritSect(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
617{
618 PDMDEV_ASSERT_DEVINS(pDevIns);
619 return TMR3TimerSetCritSect(pDevIns->Internal.s.pVMR3, hTimer, pCritSect);
620}
621
622
623/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSave} */
624static DECLCALLBACK(int) pdmR3DevHlp_TimerSave(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
625{
626 PDMDEV_ASSERT_DEVINS(pDevIns);
627 return TMR3TimerSave(pDevIns->Internal.s.pVMR3, hTimer, pSSM);
628}
629
630
631/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLoad} */
632static DECLCALLBACK(int) pdmR3DevHlp_TimerLoad(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
633{
634 PDMDEV_ASSERT_DEVINS(pDevIns);
635 return TMR3TimerLoad(pDevIns->Internal.s.pVMR3, hTimer, pSSM);
636}
637
638
639/** @interface_method_impl{PDMDEVHLPR3,pfnTimerDestroy} */
640static DECLCALLBACK(int) pdmR3DevHlp_TimerDestroy(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
641{
642 PDMDEV_ASSERT_DEVINS(pDevIns);
643 return TMR3TimerDestroy(pDevIns->Internal.s.pVMR3, hTimer);
644}
645
646
647/** @interface_method_impl{PDMDEVHLPR3,pfnTMUtcNow} */
648static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_TMUtcNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
649{
650 PDMDEV_ASSERT_DEVINS(pDevIns);
651 LogFlow(("pdmR3DevHlp_TMUtcNow: caller='%s'/%d: pTime=%p\n",
652 pDevIns->pReg->szName, pDevIns->iInstance, pTime));
653
654 pTime = TMR3UtcNow(pDevIns->Internal.s.pVMR3, pTime);
655
656 LogFlow(("pdmR3DevHlp_TMUtcNow: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
657 return pTime;
658}
659
660
661/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGet} */
662static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
663{
664 PDMDEV_ASSERT_DEVINS(pDevIns);
665 LogFlow(("pdmR3DevHlp_TMTimeVirtGet: caller='%s'/%d\n",
666 pDevIns->pReg->szName, pDevIns->iInstance));
667
668 uint64_t u64Time = TMVirtualSyncGet(pDevIns->Internal.s.pVMR3);
669
670 LogFlow(("pdmR3DevHlp_TMTimeVirtGet: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Time));
671 return u64Time;
672}
673
674
675/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGetFreq} */
676static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
677{
678 PDMDEV_ASSERT_DEVINS(pDevIns);
679 LogFlow(("pdmR3DevHlp_TMTimeVirtGetFreq: caller='%s'/%d\n",
680 pDevIns->pReg->szName, pDevIns->iInstance));
681
682 uint64_t u64Freq = TMVirtualGetFreq(pDevIns->Internal.s.pVMR3);
683
684 LogFlow(("pdmR3DevHlp_TMTimeVirtGetFreq: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Freq));
685 return u64Freq;
686}
687
688
689/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGetNano} */
690static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
691{
692 PDMDEV_ASSERT_DEVINS(pDevIns);
693 LogFlow(("pdmR3DevHlp_TMTimeVirtGetNano: caller='%s'/%d\n",
694 pDevIns->pReg->szName, pDevIns->iInstance));
695
696 uint64_t u64Time = TMVirtualGet(pDevIns->Internal.s.pVMR3);
697 uint64_t u64Nano = TMVirtualToNano(pDevIns->Internal.s.pVMR3, u64Time);
698
699 LogFlow(("pdmR3DevHlp_TMTimeVirtGetNano: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Nano));
700 return u64Nano;
701}
702
703
704/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
705static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_GetSupDrvSession(PPDMDEVINS pDevIns)
706{
707 PDMDEV_ASSERT_DEVINS(pDevIns);
708 LogFlow(("pdmR3DevHlp_GetSupDrvSession: caller='%s'/%d\n",
709 pDevIns->pReg->szName, pDevIns->iInstance));
710
711 PSUPDRVSESSION pSession = pDevIns->Internal.s.pVMR3->pSession;
712
713 LogFlow(("pdmR3DevHlp_GetSupDrvSession: caller='%s'/%d: returns %#p\n", pDevIns->pReg->szName, pDevIns->iInstance, pSession));
714 return pSession;
715}
716
717
718/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
719static DECLCALLBACK(void *) pdmR3DevHlp_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
720{
721 PDMDEV_ASSERT_DEVINS(pDevIns);
722 LogFlow(("pdmR3DevHlp_QueryGenericUserObject: caller='%s'/%d: pUuid=%p:%RTuuid\n",
723 pDevIns->pReg->szName, pDevIns->iInstance, pUuid, pUuid));
724
725#if defined(DEBUG_bird) || defined(DEBUG_ramshankar) || defined(DEBUG_sunlover) || defined(DEBUG_michael) || defined(DEBUG_andy)
726 AssertMsgFailed(("'%s' wants %RTuuid - external only interface!\n", pDevIns->pReg->szName, pUuid));
727#endif
728
729 void *pvRet;
730 PUVM pUVM = pDevIns->Internal.s.pVMR3->pUVM;
731 if (pUVM->pVmm2UserMethods->pfnQueryGenericObject)
732 pvRet = pUVM->pVmm2UserMethods->pfnQueryGenericObject(pUVM->pVmm2UserMethods, pUVM, pUuid);
733 else
734 pvRet = NULL;
735
736 LogRel(("pdmR3DevHlp_QueryGenericUserObject: caller='%s'/%d: returns %#p for %RTuuid\n",
737 pDevIns->pReg->szName, pDevIns->iInstance, pvRet, pUuid));
738 return pvRet;
739}
740
741
742/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalTypeRegister} */
743static DECLCALLBACK(int) pdmR3DevHlp_PGMHandlerPhysicalTypeRegister(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
744 R3PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR3,
745 const char *pszHandlerR0, const char *pszPfHandlerR0,
746 const char *pszHandlerRC, const char *pszPfHandlerRC,
747 const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
748{
749 PDMDEV_ASSERT_DEVINS(pDevIns);
750 PVM pVM = pDevIns->Internal.s.pVMR3;
751 LogFlow(("pdmR3DevHlp_PGMHandlerPhysicalTypeRegister: caller='%s'/%d: enmKind=%d pfnHandlerR3=%p pszHandlerR0=%p:{%s} pszPfHandlerR0=%p:{%s} pszHandlerRC=%p:{%s} pszPfHandlerRC=%p:{%s} pszDesc=%p:{%s} phType=%p\n",
752 pDevIns->pReg->szName, pDevIns->iInstance, enmKind, pfnHandlerR3,
753 pszHandlerR0, pszHandlerR0, pszPfHandlerR0, pszPfHandlerR0,
754 pszHandlerRC, pszHandlerRC, pszPfHandlerRC, pszPfHandlerRC,
755 pszDesc, pszDesc, phType));
756
757 int rc = PGMR3HandlerPhysicalTypeRegister(pVM, enmKind, pfnHandlerR3,
758 pDevIns->pReg->pszR0Mod, pszHandlerR0, pszPfHandlerR0,
759 pDevIns->pReg->pszRCMod, pszHandlerRC, pszPfHandlerRC,
760 pszDesc, phType);
761
762 Log(("pdmR3DevHlp_PGMHandlerPhysicalTypeRegister: caller='%s'/%d: returns %Rrc\n",
763 pDevIns->pReg->szName, pDevIns->iInstance, rc));
764 return rc;
765}
766
767
768/** @interface_method_impl{PDMDEVHLPR3,pfnPhysRead} */
769static DECLCALLBACK(int) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
770{
771 RT_NOREF(fFlags);
772
773 PDMDEV_ASSERT_DEVINS(pDevIns);
774 PVM pVM = pDevIns->Internal.s.pVMR3;
775 LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
776 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
777
778#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
779 if (!VM_IS_EMT(pVM))
780 {
781 char szNames[128];
782 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
783 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
784 }
785#endif
786
787 VBOXSTRICTRC rcStrict;
788 if (VM_IS_EMT(pVM))
789 rcStrict = PGMPhysRead(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
790 else
791 rcStrict = PGMR3PhysReadExternal(pVM, GCPhys, pvBuf, cbRead, PGMACCESSORIGIN_DEVICE);
792 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
793
794 Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
795 return VBOXSTRICTRC_VAL(rcStrict);
796}
797
798
799/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWrite} */
800static DECLCALLBACK(int) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
801{
802 RT_NOREF(fFlags);
803
804 PDMDEV_ASSERT_DEVINS(pDevIns);
805 PVM pVM = pDevIns->Internal.s.pVMR3;
806 LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
807 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
808
809#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
810 if (!VM_IS_EMT(pVM))
811 {
812 char szNames[128];
813 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
814 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
815 }
816#endif
817
818 VBOXSTRICTRC rcStrict;
819 if (VM_IS_EMT(pVM))
820 rcStrict = PGMPhysWrite(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
821 else
822 rcStrict = PGMR3PhysWriteExternal(pVM, GCPhys, pvBuf, cbWrite, PGMACCESSORIGIN_DEVICE);
823 AssertMsg(rcStrict == VINF_SUCCESS, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /** @todo track down the users for this bugger. */
824
825 Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
826 return VBOXSTRICTRC_VAL(rcStrict);
827}
828
829
830/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPhys2CCPtr} */
831static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPhys2CCPtr(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock)
832{
833 PDMDEV_ASSERT_DEVINS(pDevIns);
834 PVM pVM = pDevIns->Internal.s.pVMR3;
835 LogFlow(("pdmR3DevHlp_PhysGCPhys2CCPtr: caller='%s'/%d: GCPhys=%RGp fFlags=%#x ppv=%p pLock=%p\n",
836 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, fFlags, ppv, pLock));
837 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
838
839#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
840 if (!VM_IS_EMT(pVM))
841 {
842 char szNames[128];
843 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
844 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
845 }
846#endif
847
848 int rc = PGMR3PhysGCPhys2CCPtrExternal(pVM, GCPhys, ppv, pLock);
849
850 Log(("pdmR3DevHlp_PhysGCPhys2CCPtr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
851 return rc;
852}
853
854
855/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPhys2CCPtrReadOnly} */
856static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, const void **ppv, PPGMPAGEMAPLOCK pLock)
857{
858 PDMDEV_ASSERT_DEVINS(pDevIns);
859 PVM pVM = pDevIns->Internal.s.pVMR3;
860 LogFlow(("pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly: caller='%s'/%d: GCPhys=%RGp fFlags=%#x ppv=%p pLock=%p\n",
861 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, fFlags, ppv, pLock));
862 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
863
864#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
865 if (!VM_IS_EMT(pVM))
866 {
867 char szNames[128];
868 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
869 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
870 }
871#endif
872
873 int rc = PGMR3PhysGCPhys2CCPtrReadOnlyExternal(pVM, GCPhys, ppv, pLock);
874
875 Log(("pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
876 return rc;
877}
878
879
880/** @interface_method_impl{PDMDEVHLPR3,pfnPhysReleasePageMappingLock} */
881static DECLCALLBACK(void) pdmR3DevHlp_PhysReleasePageMappingLock(PPDMDEVINS pDevIns, PPGMPAGEMAPLOCK pLock)
882{
883 PDMDEV_ASSERT_DEVINS(pDevIns);
884 PVM pVM = pDevIns->Internal.s.pVMR3;
885 LogFlow(("pdmR3DevHlp_PhysReleasePageMappingLock: caller='%s'/%d: pLock=%p\n",
886 pDevIns->pReg->szName, pDevIns->iInstance, pLock));
887
888 PGMPhysReleasePageMappingLock(pVM, pLock);
889
890 Log(("pdmR3DevHlp_PhysReleasePageMappingLock: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
891}
892
893
894/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkGCPhys2CCPtr} */
895static DECLCALLBACK(int) pdmR3DevHlp_PhysBulkGCPhys2CCPtr(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
896 uint32_t fFlags, void **papvPages, PPGMPAGEMAPLOCK paLocks)
897{
898 PDMDEV_ASSERT_DEVINS(pDevIns);
899 PVM pVM = pDevIns->Internal.s.pVMR3;
900 LogFlow(("pdmR3DevHlp_PhysBulkGCPhys2CCPtr: caller='%s'/%d: cPages=%#x paGCPhysPages=%p (%RGp,..) fFlags=%#x papvPages=%p paLocks=%p\n",
901 pDevIns->pReg->szName, pDevIns->iInstance, cPages, paGCPhysPages, paGCPhysPages[0], fFlags, papvPages, paLocks));
902 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
903 AssertReturn(cPages > 0, VERR_INVALID_PARAMETER);
904
905#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
906 if (!VM_IS_EMT(pVM))
907 {
908 char szNames[128];
909 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
910 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
911 }
912#endif
913
914 int rc = PGMR3PhysBulkGCPhys2CCPtrExternal(pVM, cPages, paGCPhysPages, papvPages, paLocks);
915
916 Log(("pdmR3DevHlp_PhysBulkGCPhys2CCPtr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
917 return rc;
918}
919
920
921/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkGCPhys2CCPtrReadOnly} */
922static DECLCALLBACK(int) pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
923 uint32_t fFlags, const void **papvPages, PPGMPAGEMAPLOCK paLocks)
924{
925 PDMDEV_ASSERT_DEVINS(pDevIns);
926 PVM pVM = pDevIns->Internal.s.pVMR3;
927 LogFlow(("pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly: caller='%s'/%d: cPages=%#x paGCPhysPages=%p (%RGp,...) fFlags=%#x papvPages=%p paLocks=%p\n",
928 pDevIns->pReg->szName, pDevIns->iInstance, cPages, paGCPhysPages, paGCPhysPages[0], fFlags, papvPages, paLocks));
929 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
930 AssertReturn(cPages > 0, VERR_INVALID_PARAMETER);
931
932#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
933 if (!VM_IS_EMT(pVM))
934 {
935 char szNames[128];
936 uint32_t cLocks = PDMR3CritSectCountOwned(pVM, szNames, sizeof(szNames));
937 AssertMsg(cLocks == 0, ("cLocks=%u %s\n", cLocks, szNames));
938 }
939#endif
940
941 int rc = PGMR3PhysBulkGCPhys2CCPtrReadOnlyExternal(pVM, cPages, paGCPhysPages, papvPages, paLocks);
942
943 Log(("pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
944 return rc;
945}
946
947
948/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkReleasePageMappingLocks} */
949static DECLCALLBACK(void) pdmR3DevHlp_PhysBulkReleasePageMappingLocks(PPDMDEVINS pDevIns, uint32_t cPages, PPGMPAGEMAPLOCK paLocks)
950{
951 PDMDEV_ASSERT_DEVINS(pDevIns);
952 PVM pVM = pDevIns->Internal.s.pVMR3;
953 LogFlow(("pdmR3DevHlp_PhysBulkReleasePageMappingLocks: caller='%s'/%d: cPages=%#x paLocks=%p\n",
954 pDevIns->pReg->szName, pDevIns->iInstance, cPages, paLocks));
955 Assert(cPages > 0);
956
957 PGMPhysBulkReleasePageMappingLocks(pVM, cPages, paLocks);
958
959 Log(("pdmR3DevHlp_PhysBulkReleasePageMappingLocks: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
960}
961
962
963/** @interface_method_impl{PDMDEVHLPR3,pfnCpuGetGuestMicroarch} */
964static DECLCALLBACK(CPUMMICROARCH) pdmR3DevHlp_CpuGetGuestMicroarch(PPDMDEVINS pDevIns)
965{
966 PDMDEV_ASSERT_DEVINS(pDevIns);
967 PVM pVM = pDevIns->Internal.s.pVMR3;
968 LogFlow(("pdmR3DevHlp_CpuGetGuestMicroarch: caller='%s'/%d\n",
969 pDevIns->pReg->szName, pDevIns->iInstance));
970
971 CPUMMICROARCH enmMicroarch = CPUMGetGuestMicroarch(pVM);
972
973 Log(("pdmR3DevHlp_CpuGetGuestMicroarch: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, enmMicroarch));
974 return enmMicroarch;
975}
976
977
978/** @interface_method_impl{PDMDEVHLPR3,pfnCpuGetGuestAddrWidths} */
979static DECLCALLBACK(void) pdmR3DevHlp_CpuGetGuestAddrWidths(PPDMDEVINS pDevIns, uint8_t *pcPhysAddrWidth,
980 uint8_t *pcLinearAddrWidth)
981{
982 PDMDEV_ASSERT_DEVINS(pDevIns);
983 PVM pVM = pDevIns->Internal.s.pVMR3;
984 LogFlow(("pdmR3DevHlp_CpuGetGuestAddrWidths: caller='%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
985 AssertPtrReturnVoid(pcPhysAddrWidth);
986 AssertPtrReturnVoid(pcLinearAddrWidth);
987
988 CPUMGetGuestAddrWidths(pVM, pcPhysAddrWidth, pcLinearAddrWidth);
989
990 Log(("pdmR3DevHlp_CpuGetGuestAddrWidths: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
991}
992
993
994/** @interface_method_impl{PDMDEVHLPR3,pfnPhysReadGCVirt} */
995static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
996{
997 PDMDEV_ASSERT_DEVINS(pDevIns);
998 PVM pVM = pDevIns->Internal.s.pVMR3;
999 VM_ASSERT_EMT(pVM);
1000 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%RGv cb=%#x\n",
1001 pDevIns->pReg->szName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
1002
1003 PVMCPU pVCpu = VMMGetCpu(pVM);
1004 if (!pVCpu)
1005 return VERR_ACCESS_DENIED;
1006#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1007 /** @todo SMP. */
1008#endif
1009
1010 int rc = PGMPhysSimpleReadGCPtr(pVCpu, pvDst, GCVirtSrc, cb);
1011
1012 LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1013
1014 return rc;
1015}
1016
1017
1018/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWriteGCVirt} */
1019static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
1020{
1021 PDMDEV_ASSERT_DEVINS(pDevIns);
1022 PVM pVM = pDevIns->Internal.s.pVMR3;
1023 VM_ASSERT_EMT(pVM);
1024 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%RGv pvSrc=%p cb=%#x\n",
1025 pDevIns->pReg->szName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
1026
1027 PVMCPU pVCpu = VMMGetCpu(pVM);
1028 if (!pVCpu)
1029 return VERR_ACCESS_DENIED;
1030#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1031 /** @todo SMP. */
1032#endif
1033
1034 int rc = PGMPhysSimpleWriteGCPtr(pVCpu, GCVirtDst, pvSrc, cb);
1035
1036 LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1037
1038 return rc;
1039}
1040
1041
1042/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPtr2GCPhys} */
1043static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
1044{
1045 PDMDEV_ASSERT_DEVINS(pDevIns);
1046 PVM pVM = pDevIns->Internal.s.pVMR3;
1047 VM_ASSERT_EMT(pVM);
1048 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%RGv pGCPhys=%p\n",
1049 pDevIns->pReg->szName, pDevIns->iInstance, GCPtr, pGCPhys));
1050
1051 PVMCPU pVCpu = VMMGetCpu(pVM);
1052 if (!pVCpu)
1053 return VERR_ACCESS_DENIED;
1054#if defined(VBOX_STRICT) && defined(PDM_DEVHLP_DEADLOCK_DETECTION)
1055 /** @todo SMP. */
1056#endif
1057
1058 int rc = PGMPhysGCPtr2GCPhys(pVCpu, GCPtr, pGCPhys);
1059
1060 LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Rrc *pGCPhys=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pGCPhys));
1061
1062 return rc;
1063}
1064
1065
1066/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapAlloc} */
1067static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
1068{
1069 PDMDEV_ASSERT_DEVINS(pDevIns);
1070 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
1071
1072 void *pv = MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
1073
1074 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
1075 return pv;
1076}
1077
1078
1079/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapAllocZ} */
1080static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
1081{
1082 PDMDEV_ASSERT_DEVINS(pDevIns);
1083 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
1084
1085 void *pv = MMR3HeapAllocZ(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE_USER, cb);
1086
1087 LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
1088 return pv;
1089}
1090
1091
1092/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapFree} */
1093static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
1094{
1095 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
1096 LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
1097
1098 MMR3HeapFree(pv);
1099
1100 LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1101}
1102
1103
1104/** @interface_method_impl{PDMDEVHLPR3,pfnVMState} */
1105static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
1106{
1107 PDMDEV_ASSERT_DEVINS(pDevIns);
1108
1109 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
1110
1111 LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d (%s)\n", pDevIns->pReg->szName, pDevIns->iInstance,
1112 enmVMState, VMR3GetStateName(enmVMState)));
1113 return enmVMState;
1114}
1115
1116
1117/** @interface_method_impl{PDMDEVHLPR3,pfnVMTeleportedAndNotFullyResumedYet} */
1118static DECLCALLBACK(bool) pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet(PPDMDEVINS pDevIns)
1119{
1120 PDMDEV_ASSERT_DEVINS(pDevIns);
1121
1122 bool fRc = VMR3TeleportedAndNotFullyResumedYet(pDevIns->Internal.s.pVMR3);
1123
1124 LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance,
1125 fRc));
1126 return fRc;
1127}
1128
1129
1130/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetError} */
1131static DECLCALLBACK(int) pdmR3DevHlp_VMSetError(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
1132{
1133 PDMDEV_ASSERT_DEVINS(pDevIns);
1134 va_list args;
1135 va_start(args, pszFormat);
1136 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, args); Assert(rc2 == rc); NOREF(rc2);
1137 va_end(args);
1138 return rc;
1139}
1140
1141
1142/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetErrorV} */
1143static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
1144{
1145 PDMDEV_ASSERT_DEVINS(pDevIns);
1146 int rc2 = VMSetErrorV(pDevIns->Internal.s.pVMR3, rc, RT_SRC_POS_ARGS, pszFormat, va); Assert(rc2 == rc); NOREF(rc2);
1147 return rc;
1148}
1149
1150
1151/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetRuntimeError} */
1152static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
1153{
1154 PDMDEV_ASSERT_DEVINS(pDevIns);
1155 va_list args;
1156 va_start(args, pszFormat);
1157 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFlags, pszErrorId, pszFormat, args);
1158 va_end(args);
1159 return rc;
1160}
1161
1162
1163/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetRuntimeErrorV} */
1164static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
1165{
1166 PDMDEV_ASSERT_DEVINS(pDevIns);
1167 int rc = VMSetRuntimeErrorV(pDevIns->Internal.s.pVMR3, fFlags, pszErrorId, pszFormat, va);
1168 return rc;
1169}
1170
1171
1172/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFStopV} */
1173static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
1174{
1175 PDMDEV_ASSERT_DEVINS(pDevIns);
1176#ifdef LOG_ENABLED
1177 va_list va2;
1178 va_copy(va2, args);
1179 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
1180 pDevIns->pReg->szName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
1181 va_end(va2);
1182#endif
1183
1184 PVM pVM = pDevIns->Internal.s.pVMR3;
1185 VM_ASSERT_EMT(pVM);
1186 int rc = DBGFR3EventSrcV(pVM, DBGFEVENT_DEV_STOP, pszFile, iLine, pszFunction, pszFormat, args);
1187 if (rc == VERR_DBGF_NOT_ATTACHED)
1188 rc = VINF_SUCCESS;
1189
1190 LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1191 return rc;
1192}
1193
1194
1195/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFInfoRegister} */
1196static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
1197{
1198 PDMDEV_ASSERT_DEVINS(pDevIns);
1199 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
1200 pDevIns->pReg->szName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
1201
1202 PVM pVM = pDevIns->Internal.s.pVMR3;
1203 VM_ASSERT_EMT(pVM);
1204 int rc = DBGFR3InfoRegisterDevice(pVM, pszName, pszDesc, pfnHandler, pDevIns);
1205
1206 LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1207 return rc;
1208}
1209
1210
1211/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFInfoRegisterArgv} */
1212static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegisterArgv(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDEV pfnHandler)
1213{
1214 PDMDEV_ASSERT_DEVINS(pDevIns);
1215 LogFlow(("pdmR3DevHlp_DBGFInfoRegisterArgv: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
1216 pDevIns->pReg->szName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
1217
1218 PVM pVM = pDevIns->Internal.s.pVMR3;
1219 VM_ASSERT_EMT(pVM);
1220 int rc = DBGFR3InfoRegisterDeviceArgv(pVM, pszName, pszDesc, pfnHandler, pDevIns);
1221
1222 LogFlow(("pdmR3DevHlp_DBGFInfoRegisterArgv: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1223 return rc;
1224}
1225
1226
1227/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFRegRegister} */
1228static DECLCALLBACK(int) pdmR3DevHlp_DBGFRegRegister(PPDMDEVINS pDevIns, PCDBGFREGDESC paRegisters)
1229{
1230 PDMDEV_ASSERT_DEVINS(pDevIns);
1231 LogFlow(("pdmR3DevHlp_DBGFRegRegister: caller='%s'/%d: paRegisters=%p\n",
1232 pDevIns->pReg->szName, pDevIns->iInstance, paRegisters));
1233
1234 PVM pVM = pDevIns->Internal.s.pVMR3;
1235 VM_ASSERT_EMT(pVM);
1236 int rc = DBGFR3RegRegisterDevice(pVM, paRegisters, pDevIns, pDevIns->pReg->szName, pDevIns->iInstance);
1237
1238 LogFlow(("pdmR3DevHlp_DBGFRegRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1239 return rc;
1240}
1241
1242
1243/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFTraceBuf} */
1244static DECLCALLBACK(RTTRACEBUF) pdmR3DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
1245{
1246 PDMDEV_ASSERT_DEVINS(pDevIns);
1247 RTTRACEBUF hTraceBuf = pDevIns->Internal.s.pVMR3->hTraceBufR3;
1248 LogFlow(("pdmR3DevHlp_DBGFTraceBuf: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, hTraceBuf));
1249 return hTraceBuf;
1250}
1251
1252
1253/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegister} */
1254static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName,
1255 STAMUNIT enmUnit, const char *pszDesc)
1256{
1257 PDMDEV_ASSERT_DEVINS(pDevIns);
1258 PVM pVM = pDevIns->Internal.s.pVMR3;
1259 VM_ASSERT_EMT(pVM);
1260
1261 int rc;
1262 if (*pszName == '/')
1263 rc = STAMR3Register(pVM, pvSample, enmType, STAMVISIBILITY_ALWAYS, pszName, enmUnit, pszDesc);
1264 /* Provide default device statistics prefix: */
1265 else if (pDevIns->pReg->cMaxInstances == 1)
1266 rc = STAMR3RegisterF(pVM, pvSample, enmType, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
1267 "/Devices/%s/%s", pDevIns->pReg->szName, pszName);
1268 else
1269 rc = STAMR3RegisterF(pVM, pvSample, enmType, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
1270 "/Devices/%s#%u/%s", pDevIns->pReg->szName, pDevIns->iInstance, pszName);
1271 AssertRC(rc);
1272}
1273
1274
1275/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegisterV} */
1276static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
1277 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
1278{
1279 PDMDEV_ASSERT_DEVINS(pDevIns);
1280 PVM pVM = pDevIns->Internal.s.pVMR3;
1281 VM_ASSERT_EMT(pVM);
1282
1283 int rc;
1284 if (*pszName == '/')
1285 rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1286 else
1287 {
1288 /* Provide default device statistics prefix: */
1289 va_list vaCopy;
1290 va_copy(vaCopy, args);
1291 if (pDevIns->pReg->cMaxInstances == 1)
1292 rc = STAMR3RegisterF(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc,
1293 "/Devices/%s/%N", pDevIns->pReg->szName, pszName, &vaCopy);
1294 else
1295 rc = STAMR3RegisterF(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc,
1296 "/Devices/%s#%u/%N", pDevIns->pReg->szName, pDevIns->iInstance, pszName, &vaCopy);
1297 va_end(vaCopy);
1298 }
1299 AssertRC(rc);
1300}
1301
1302
1303/**
1304 * @interface_method_impl{PDMDEVHLPR3,pfnSTAMDeregisterByPrefix}
1305 */
1306static DECLCALLBACK(int) pdmR3DevHlp_STAMDeregisterByPrefix(PPDMDEVINS pDevIns, const char *pszPrefix)
1307{
1308 PDMDEV_ASSERT_DEVINS(pDevIns);
1309 PVM pVM = pDevIns->Internal.s.pVMR3;
1310 VM_ASSERT_EMT(pVM);
1311
1312 int rc;
1313 if (*pszPrefix == '/')
1314 rc = STAMR3DeregisterByPrefix(pVM->pUVM, pszPrefix);
1315 else
1316 {
1317 char szQualifiedPrefix[1024];
1318 ssize_t cch;
1319 if (pDevIns->pReg->cMaxInstances == 1)
1320 cch = RTStrPrintf2(szQualifiedPrefix, sizeof(szQualifiedPrefix), "/Devices/%s/%s", pDevIns->pReg->szName, pszPrefix);
1321 else
1322 cch = RTStrPrintf2(szQualifiedPrefix, sizeof(szQualifiedPrefix), "/Devices/%s#%u/%s",
1323 pDevIns->pReg->szName, pDevIns->iInstance, pszPrefix);
1324 AssertReturn(cch > 0, VERR_OUT_OF_RANGE);
1325 rc = STAMR3DeregisterByPrefix(pVM->pUVM, szQualifiedPrefix);
1326 }
1327 AssertRC(rc);
1328 return rc;
1329}
1330
1331
1332/**
1333 * @interface_method_impl{PDMDEVHLPR3,pfnPCIRegister}
1334 */
1335static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t fFlags,
1336 uint8_t uPciDevNo, uint8_t uPciFunNo, const char *pszName)
1337{
1338 PDMDEV_ASSERT_DEVINS(pDevIns);
1339 PVM pVM = pDevIns->Internal.s.pVMR3;
1340 VM_ASSERT_EMT(pVM);
1341 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Rhxs} fFlags=%#x uPciDevNo=%#x uPciFunNo=%#x pszName=%p:{%s}\n",
1342 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->abConfig, fFlags, uPciDevNo, uPciFunNo, pszName, pszName ? pszName : ""));
1343
1344 /*
1345 * Validate input.
1346 */
1347 AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
1348 ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
1349 VERR_WRONG_ORDER);
1350 AssertLogRelMsgReturn(RT_VALID_PTR(pPciDev),
1351 ("'%s'/%d: Invalid pPciDev value: %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pPciDev),
1352 VERR_INVALID_POINTER);
1353 AssertLogRelMsgReturn(PDMPciDevGetVendorId(pPciDev),
1354 ("'%s'/%d: Vendor ID is not set!\n", pDevIns->pReg->szName, pDevIns->iInstance),
1355 VERR_INVALID_POINTER);
1356 AssertLogRelMsgReturn( uPciDevNo < 32
1357 || uPciDevNo == PDMPCIDEVREG_DEV_NO_FIRST_UNUSED
1358 || uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV,
1359 ("'%s'/%d: Invalid PCI device number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciDevNo),
1360 VERR_INVALID_PARAMETER);
1361 AssertLogRelMsgReturn( uPciFunNo < 8
1362 || uPciFunNo == PDMPCIDEVREG_FUN_NO_FIRST_UNUSED,
1363 ("'%s'/%d: Invalid PCI funcion number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciFunNo),
1364 VERR_INVALID_PARAMETER);
1365 AssertLogRelMsgReturn(!(fFlags & ~PDMPCIDEVREG_F_VALID_MASK),
1366 ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
1367 VERR_INVALID_FLAGS);
1368 if (!pszName)
1369 pszName = pDevIns->pReg->szName;
1370 AssertLogRelReturn(RT_VALID_PTR(pszName), VERR_INVALID_POINTER);
1371 AssertLogRelReturn(!pPciDev->Int.s.fRegistered, VERR_PDM_NOT_PCI_DEVICE);
1372 AssertLogRelReturn(pPciDev == PDMDEV_GET_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
1373 AssertLogRelReturn(pPciDev == PDMDEV_CALC_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
1374 AssertMsgReturn(pPciDev->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", pPciDev->u32Magic), VERR_PDM_NOT_PCI_DEVICE);
1375
1376 /*
1377 * Check the registration order - must be following PDMDEVINSR3::apPciDevs.
1378 */
1379 PPDMPCIDEV const pPrevPciDev = pPciDev->Int.s.idxSubDev == 0 ? NULL
1380 : PDMDEV_GET_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev - 1);
1381 if (pPrevPciDev)
1382 {
1383 AssertLogRelReturn(pPrevPciDev->u32Magic == PDMPCIDEV_MAGIC, VERR_INVALID_MAGIC);
1384 AssertLogRelReturn(pPrevPciDev->Int.s.fRegistered, VERR_WRONG_ORDER);
1385 }
1386
1387 /*
1388 * Resolve the PCI configuration node for the device. The default (zero'th)
1389 * is the same as the PDM device, the rest are "PciCfg1..255" CFGM sub-nodes.
1390 */
1391 PCFGMNODE pCfg = pDevIns->Internal.s.pCfgHandle;
1392 if (pPciDev->Int.s.idxSubDev > 0)
1393 pCfg = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "PciCfg%u", pPciDev->Int.s.idxSubDev);
1394
1395 /*
1396 * We resolve PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, the PCI bus handles
1397 * PDMPCIDEVREG_DEV_NO_FIRST_UNUSED and PDMPCIDEVREG_FUN_NO_FIRST_UNUSED.
1398 */
1399 uint8_t const uPciDevNoRaw = uPciDevNo;
1400 uint32_t uDefPciBusNo = 0;
1401 if (uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV)
1402 {
1403 if (pPrevPciDev)
1404 {
1405 uPciDevNo = pPrevPciDev->uDevFn >> 3;
1406 uDefPciBusNo = pPrevPciDev->Int.s.idxPdmBus;
1407 }
1408 else
1409 {
1410 /* Look for PCI device registered with an earlier device instance so we can more
1411 easily have multiple functions spanning multiple PDM device instances. */
1412 PPDMDEVINS pPrevIns = pDevIns->Internal.s.pDevR3->pInstances;
1413 for (;;)
1414 {
1415 AssertLogRelMsgReturn(pPrevIns && pPrevIns != pDevIns,
1416 ("'%s'/%d: Can't use PDMPCIDEVREG_DEV_NO_SAME_AS_PREV without a previously registered PCI device by the same or earlier PDM device instance!\n",
1417 pDevIns->pReg->szName, pDevIns->iInstance), VERR_WRONG_ORDER);
1418 if (pPrevIns->Internal.s.pNextR3 == pDevIns)
1419 break;
1420 pPrevIns = pPrevIns->Internal.s.pNextR3;
1421 }
1422
1423 PPDMPCIDEV pOtherPciDev = PDMDEV_GET_PPCIDEV(pPrevIns, 0);
1424 AssertLogRelMsgReturn(pOtherPciDev && pOtherPciDev->Int.s.fRegistered,
1425 ("'%s'/%d: Can't use PDMPCIDEVREG_DEV_NO_SAME_AS_PREV without a previously registered PCI device by the same or earlier PDM device instance!\n",
1426 pDevIns->pReg->szName, pDevIns->iInstance),
1427 VERR_WRONG_ORDER);
1428 for (uint32_t iPrevPciDev = 1; iPrevPciDev < pDevIns->cPciDevs; iPrevPciDev++)
1429 {
1430 PPDMPCIDEV pCur = PDMDEV_GET_PPCIDEV(pPrevIns, iPrevPciDev);
1431 AssertBreak(pCur);
1432 if (!pCur->Int.s.fRegistered)
1433 break;
1434 pOtherPciDev = pCur;
1435 }
1436
1437 uPciDevNo = pOtherPciDev->uDevFn >> 3;
1438 uDefPciBusNo = pOtherPciDev->Int.s.idxPdmBus;
1439 }
1440 }
1441
1442 /*
1443 * Choose the PCI bus for the device.
1444 *
1445 * This is simple. If the device was configured for a particular bus, the PCIBusNo
1446 * configuration value will be set. If not the default bus is 0.
1447 */
1448 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIBusNo, uint8_t, 0, 7, 0}
1449 * Selects the PCI bus number of a device. The default value isn't necessarily
1450 * zero if the device is registered using PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, it
1451 * will then also inherit the bus number from the previously registered device.
1452 */
1453 uint8_t u8Bus;
1454 int rc = CFGMR3QueryU8Def(pCfg, "PCIBusNo", &u8Bus, (uint8_t)uDefPciBusNo);
1455 AssertLogRelMsgRCReturn(rc, ("Configuration error: PCIBusNo query failed with rc=%Rrc (%s/%d)\n",
1456 rc, pDevIns->pReg->szName, pDevIns->iInstance), rc);
1457 AssertLogRelMsgReturn(u8Bus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
1458 ("Configuration error: PCIBusNo=%d, max is %d. (%s/%d)\n", u8Bus,
1459 RT_ELEMENTS(pVM->pdm.s.aPciBuses), pDevIns->pReg->szName, pDevIns->iInstance),
1460 VERR_PDM_NO_PCI_BUS);
1461 pPciDev->Int.s.idxPdmBus = u8Bus;
1462 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[u8Bus];
1463 if (pBus->pDevInsR3)
1464 {
1465 /*
1466 * Check the configuration for PCI device and function assignment.
1467 */
1468 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIDeviceNo, uint8_t, 0, 31}
1469 * Overrides the default PCI device number of a device.
1470 */
1471 uint8_t uCfgDevice;
1472 rc = CFGMR3QueryU8(pCfg, "PCIDeviceNo", &uCfgDevice);
1473 if (RT_SUCCESS(rc))
1474 {
1475 AssertMsgReturn(uCfgDevice <= 31,
1476 ("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d/%d)\n",
1477 uCfgDevice, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1478 VERR_PDM_BAD_PCI_CONFIG);
1479 uPciDevNo = uCfgDevice;
1480 }
1481 else
1482 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1483 ("Configuration error: PCIDeviceNo query failed with rc=%Rrc (%s/%d/%d)\n",
1484 rc, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1485 rc);
1486
1487 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIFunctionNo, uint8_t, 0, 7}
1488 * Overrides the default PCI function number of a device.
1489 */
1490 uint8_t uCfgFunction;
1491 rc = CFGMR3QueryU8(pCfg, "PCIFunctionNo", &uCfgFunction);
1492 if (RT_SUCCESS(rc))
1493 {
1494 AssertMsgReturn(uCfgFunction <= 7,
1495 ("Configuration error: PCIFunctionNo=%#x, max is 7. (%s/%d/%d)\n",
1496 uCfgFunction, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1497 VERR_PDM_BAD_PCI_CONFIG);
1498 uPciFunNo = uCfgFunction;
1499 }
1500 else
1501 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1502 ("Configuration error: PCIFunctionNo query failed with rc=%Rrc (%s/%d/%d)\n",
1503 rc, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1504 rc);
1505
1506#ifdef VBOX_WITH_IOMMU_AMD
1507 /** @todo IOMMU: Restrict this to the AMD flavor of IOMMU only at runtime. */
1508 PPDMIOMMUR3 pIommu = &pVM->pdm.s.aIommus[0];
1509 PPDMDEVINS pDevInsIommu = pIommu->CTX_SUFF(pDevIns);
1510 if (pDevInsIommu)
1511 {
1512 /*
1513 * If the PCI device/function number has been explicitly specified via CFGM,
1514 * ensure it's not the BDF reserved for the southbridge I/O APIC expected
1515 * by linux guests when using an AMD IOMMU, see @bugref{9654#c23}.
1516 */
1517 uint16_t const uDevFn = VBOX_PCI_DEVFN_MAKE(uPciDevNo, uPciFunNo);
1518 uint16_t const uBusDevFn = PCIBDF_MAKE(u8Bus, uDevFn);
1519 if (uBusDevFn == VBOX_PCI_BDF_SB_IOAPIC)
1520 {
1521 LogRel(("Configuration error: PCI BDF (%u:%u:%u) conflicts with SB I/O APIC (%s/%d/%d)\n", u8Bus,
1522 uCfgDevice, uCfgFunction, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev));
1523 return VERR_NOT_AVAILABLE;
1524 }
1525 }
1526#endif
1527
1528 /*
1529 * Initialize the internal data. We only do the wipe and the members
1530 * owned by PDM, the PCI bus does the rest in the registration call.
1531 */
1532 RT_ZERO(pPciDev->Int);
1533
1534 pPciDev->Int.s.idxDevCfg = pPciDev->Int.s.idxSubDev;
1535 pPciDev->Int.s.fReassignableDevNo = uPciDevNoRaw >= VBOX_PCI_MAX_DEVICES;
1536 pPciDev->Int.s.fReassignableFunNo = uPciFunNo >= VBOX_PCI_MAX_FUNCTIONS;
1537 pPciDev->Int.s.pDevInsR3 = pDevIns;
1538 pPciDev->Int.s.idxPdmBus = u8Bus;
1539 pPciDev->Int.s.fRegistered = true;
1540
1541 /* Set some of the public members too. */
1542 pPciDev->pszNameR3 = pszName;
1543
1544 /*
1545 * Call the pci bus device to do the actual registration.
1546 */
1547 pdmLock(pVM);
1548 rc = pBus->pfnRegister(pBus->pDevInsR3, pPciDev, fFlags, uPciDevNo, uPciFunNo, pszName);
1549 pdmUnlock(pVM);
1550 if (RT_SUCCESS(rc))
1551 Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
1552 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->uDevFn, pBus->iBus));
1553 else
1554 pPciDev->Int.s.fRegistered = false;
1555 }
1556 else
1557 {
1558 AssertLogRelMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
1559 rc = VERR_PDM_NO_PCI_BUS;
1560 }
1561
1562 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1563 return rc;
1564}
1565
1566
1567/** @interface_method_impl{PDMDEVHLPR3,pfnPCIRegisterMsi} */
1568static DECLCALLBACK(int) pdmR3DevHlp_PCIRegisterMsi(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg)
1569{
1570 PDMDEV_ASSERT_DEVINS(pDevIns);
1571 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1572 pPciDev = pDevIns->apPciDevs[0];
1573 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1574 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: pPciDev=%p:{%#x} pMsgReg=%p:{cMsiVectors=%d, cMsixVectors=%d}\n",
1575 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, pMsiReg, pMsiReg->cMsiVectors, pMsiReg->cMsixVectors));
1576 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
1577
1578 AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
1579 ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
1580 VERR_WRONG_ORDER);
1581 AssertLogRelMsgReturn(pMsiReg->cMsixVectors <= pDevIns->pReg->cMaxMsixVectors,
1582 ("'%s'/%d: cMsixVectors=%u cMaxMsixVectors=%u\n",
1583 pDevIns->pReg->szName, pDevIns->iInstance, pMsiReg->cMsixVectors, pDevIns->pReg->cMaxMsixVectors),
1584 VERR_INVALID_FLAGS);
1585
1586 PVM pVM = pDevIns->Internal.s.pVMR3;
1587 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1588 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
1589 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1590
1591 pdmLock(pVM);
1592 int rc;
1593 if (pBus->pfnRegisterMsi)
1594 rc = pBus->pfnRegisterMsi(pBus->pDevInsR3, pPciDev, pMsiReg);
1595 else
1596 rc = VERR_NOT_IMPLEMENTED;
1597 pdmUnlock(pVM);
1598
1599 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1600 return rc;
1601}
1602
1603
1604/** @interface_method_impl{PDMDEVHLPR3,pfnPCIIORegionRegister} */
1605static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
1606 RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, uint32_t fFlags,
1607 uint64_t hHandle, PFNPCIIOREGIONMAP pfnMapUnmap)
1608{
1609 PDMDEV_ASSERT_DEVINS(pDevIns);
1610 PVM pVM = pDevIns->Internal.s.pVMR3;
1611 VM_ASSERT_EMT(pVM);
1612 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1613 pPciDev = pDevIns->apPciDevs[0];
1614 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1615 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%d cbRegion=%RGp enmType=%d fFlags=%#x, hHandle=%#RX64 pfnMapUnmap=%p\n",
1616 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iRegion, cbRegion, enmType, fFlags, hHandle, pfnMapUnmap));
1617 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
1618
1619 /*
1620 * Validate input.
1621 */
1622 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
1623 AssertLogRelMsgReturn(VMR3GetState(pVM) == VMSTATE_CREATING,
1624 ("caller='%s'/%d: %s\n", pDevIns->pReg->szName, pDevIns->iInstance, VMR3GetStateName(VMR3GetState(pVM))),
1625 VERR_WRONG_ORDER);
1626
1627 if (iRegion >= VBOX_PCI_NUM_REGIONS)
1628 {
1629 Assert(iRegion < VBOX_PCI_NUM_REGIONS);
1630 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (iRegion)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1631 return VERR_INVALID_PARAMETER;
1632 }
1633
1634 switch ((int)enmType)
1635 {
1636 case PCI_ADDRESS_SPACE_IO:
1637 /*
1638 * Sanity check: don't allow to register more than 32K of the PCI I/O space.
1639 */
1640 AssertLogRelMsgReturn(cbRegion <= _32K,
1641 ("caller='%s'/%d: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cbRegion),
1642 VERR_INVALID_PARAMETER);
1643 break;
1644
1645 case PCI_ADDRESS_SPACE_MEM:
1646 case PCI_ADDRESS_SPACE_MEM_PREFETCH:
1647 /*
1648 * Sanity check: Don't allow to register more than 2GB of the PCI MMIO space.
1649 */
1650 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_32_MAX,
1651 ("caller='%s'/%d: %RGp (max %RGp)\n",
1652 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, (RTGCPHYS)MM_MMIO_32_MAX),
1653 VERR_OUT_OF_RANGE);
1654 break;
1655
1656 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM:
1657 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH:
1658 /*
1659 * Sanity check: Don't allow to register more than 64GB of the 64-bit PCI MMIO space.
1660 */
1661 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_64_MAX,
1662 ("caller='%s'/%d: %RGp (max %RGp)\n",
1663 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, MM_MMIO_64_MAX),
1664 VERR_OUT_OF_RANGE);
1665 break;
1666
1667 default:
1668 AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
1669 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (enmType)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
1670 return VERR_INVALID_PARAMETER;
1671 }
1672
1673 AssertMsgReturn( pfnMapUnmap
1674 || ( hHandle != UINT64_MAX
1675 && (fFlags & PDMPCIDEV_IORGN_F_HANDLE_MASK) != PDMPCIDEV_IORGN_F_NO_HANDLE),
1676 ("caller='%s'/%d: fFlags=%#x hHandle=%#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags, hHandle),
1677 VERR_INVALID_PARAMETER);
1678
1679 AssertMsgReturn(!(fFlags & ~PDMPCIDEV_IORGN_F_VALID_MASK), ("fFlags=%#x\n", fFlags), VERR_INVALID_FLAGS);
1680 int rc;
1681 switch (fFlags & PDMPCIDEV_IORGN_F_HANDLE_MASK)
1682 {
1683 case PDMPCIDEV_IORGN_F_NO_HANDLE:
1684 break;
1685 case PDMPCIDEV_IORGN_F_IOPORT_HANDLE:
1686 AssertReturn(enmType == PCI_ADDRESS_SPACE_IO, VERR_INVALID_FLAGS);
1687 rc = IOMR3IoPortValidateHandle(pVM, pDevIns, (IOMIOPORTHANDLE)hHandle);
1688 AssertRCReturn(rc, rc);
1689 break;
1690 case PDMPCIDEV_IORGN_F_MMIO_HANDLE:
1691 AssertReturn( (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM
1692 || (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM_PREFETCH,
1693 VERR_INVALID_FLAGS);
1694 rc = IOMR3MmioValidateHandle(pVM, pDevIns, (IOMMMIOHANDLE)hHandle);
1695 AssertRCReturn(rc, rc);
1696 break;
1697 case PDMPCIDEV_IORGN_F_MMIO2_HANDLE:
1698 AssertReturn( (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM
1699 || (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM_PREFETCH,
1700 VERR_INVALID_FLAGS);
1701 rc = PGMR3PhysMmio2ValidateHandle(pVM, pDevIns, (PGMMMIO2HANDLE)hHandle);
1702 AssertRCReturn(rc, rc);
1703 break;
1704 default:
1705 AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
1706 break;
1707 }
1708
1709 /* This flag is required now. */
1710 AssertLogRelMsgReturn(fFlags & PDMPCIDEV_IORGN_F_NEW_STYLE,
1711 ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
1712 VERR_INVALID_FLAGS);
1713
1714 /*
1715 * We're currently restricted to page aligned MMIO regions.
1716 */
1717 if ( ((enmType & ~(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH)) == PCI_ADDRESS_SPACE_MEM)
1718 && cbRegion != RT_ALIGN_64(cbRegion, PAGE_SIZE))
1719 {
1720 Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %RGp -> %RGp\n",
1721 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, RT_ALIGN_64(cbRegion, PAGE_SIZE)));
1722 cbRegion = RT_ALIGN_64(cbRegion, PAGE_SIZE);
1723 }
1724
1725 /*
1726 * For registering PCI MMIO memory or PCI I/O memory, the size of the region must be a power of 2!
1727 */
1728 int iLastSet = ASMBitLastSetU64(cbRegion);
1729 Assert(iLastSet > 0);
1730 uint64_t cbRegionAligned = RT_BIT_64(iLastSet - 1);
1731 if (cbRegion > cbRegionAligned)
1732 cbRegion = cbRegionAligned * 2; /* round up */
1733
1734 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1735 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
1736 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1737
1738 pdmLock(pVM);
1739 rc = pBus->pfnIORegionRegister(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, fFlags, hHandle, pfnMapUnmap);
1740 pdmUnlock(pVM);
1741
1742 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1743 return rc;
1744}
1745
1746
1747/** @interface_method_impl{PDMDEVHLPR3,pfnPCIInterceptConfigAccesses} */
1748static DECLCALLBACK(int) pdmR3DevHlp_PCIInterceptConfigAccesses(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
1749 PFNPCICONFIGREAD pfnRead, PFNPCICONFIGWRITE pfnWrite)
1750{
1751 PDMDEV_ASSERT_DEVINS(pDevIns);
1752 PVM pVM = pDevIns->Internal.s.pVMR3;
1753 VM_ASSERT_EMT(pVM);
1754 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1755 pPciDev = pDevIns->apPciDevs[0];
1756 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1757 LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: pPciDev=%p pfnRead=%p pfnWrite=%p\n",
1758 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pfnRead, pfnWrite));
1759 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
1760
1761 /*
1762 * Validate input.
1763 */
1764 AssertPtr(pfnRead);
1765 AssertPtr(pfnWrite);
1766 AssertPtr(pPciDev);
1767
1768 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1769 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
1770 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1771 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
1772
1773 /*
1774 * Do the job.
1775 */
1776 pdmLock(pVM);
1777 pBus->pfnInterceptConfigAccesses(pBus->pDevInsR3, pPciDev, pfnRead, pfnWrite);
1778 pdmUnlock(pVM);
1779
1780 LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: returns VINF_SUCCESS\n",
1781 pDevIns->pReg->szName, pDevIns->iInstance));
1782 return VINF_SUCCESS;
1783}
1784
1785
1786/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigWrite} */
1787static DECLCALLBACK(VBOXSTRICTRC)
1788pdmR3DevHlp_PCIConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t u32Value)
1789{
1790 PDMDEV_ASSERT_DEVINS(pDevIns);
1791 PVM pVM = pDevIns->Internal.s.pVMR3;
1792 AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1793 LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d u32Value=%#x\n",
1794 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, u32Value));
1795
1796 /*
1797 * Resolve the bus.
1798 */
1799 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1800 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
1801 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1802
1803 /*
1804 * Do the job.
1805 */
1806 VBOXSTRICTRC rcStrict = pBus->pfnConfigWrite(pBus->pDevInsR3, pPciDev, uAddress, cb, u32Value);
1807
1808 LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: returns %Rrc\n",
1809 pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict)));
1810 return rcStrict;
1811}
1812
1813
1814/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigRead} */
1815static DECLCALLBACK(VBOXSTRICTRC)
1816pdmR3DevHlp_PCIConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t *pu32Value)
1817{
1818 PDMDEV_ASSERT_DEVINS(pDevIns);
1819 PVM pVM = pDevIns->Internal.s.pVMR3;
1820 AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1821 LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d pu32Value=%p:{%#x}\n",
1822 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, pu32Value, *pu32Value));
1823
1824 /*
1825 * Resolve the bus.
1826 */
1827 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1828 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
1829 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1830
1831 /*
1832 * Do the job.
1833 */
1834 VBOXSTRICTRC rcStrict = pBus->pfnConfigRead(pBus->pDevInsR3, pPciDev, uAddress, cb, pu32Value);
1835
1836 LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: returns %Rrc (*pu32Value=%#x)\n",
1837 pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict), *pu32Value));
1838 return rcStrict;
1839}
1840
1841
1842/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysRead} */
1843static DECLCALLBACK(int)
1844pdmR3DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
1845{
1846 PDMDEV_ASSERT_DEVINS(pDevIns);
1847 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1848 pPciDev = pDevIns->apPciDevs[0];
1849 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1850 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1851
1852#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
1853 /*
1854 * Just check the busmaster setting here and forward the request to the generic read helper.
1855 */
1856 if (PCIDevIsBusmaster(pPciDev))
1857 { /* likely */ }
1858 else
1859 {
1860 Log(("pdmR3DevHlp_PCIPhysRead: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
1861 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
1862 memset(pvBuf, 0xff, cbRead);
1863 return VERR_PDM_NOT_PCI_BUS_MASTER;
1864 }
1865#endif
1866
1867#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
1868 int rc = pdmIommuMemAccessRead(pDevIns, pPciDev, GCPhys, pvBuf, cbRead, fFlags);
1869 if (RT_SUCCESS(rc) || rc != VERR_IOMMU_NOT_PRESENT)
1870 return rc;
1871#endif
1872
1873 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, fFlags);
1874}
1875
1876
1877/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
1878static DECLCALLBACK(int)
1879pdmR3DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
1880{
1881 PDMDEV_ASSERT_DEVINS(pDevIns);
1882 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1883 pPciDev = pDevIns->apPciDevs[0];
1884 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1885 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1886
1887#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
1888 /*
1889 * Just check the busmaster setting here and forward the request to the generic read helper.
1890 */
1891 if (PCIDevIsBusmaster(pPciDev))
1892 { /* likely */ }
1893 else
1894 {
1895 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
1896 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
1897 return VERR_PDM_NOT_PCI_BUS_MASTER;
1898 }
1899#endif
1900
1901#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
1902 int rc = pdmIommuMemAccessWrite(pDevIns, pPciDev, GCPhys, pvBuf, cbWrite, fFlags);
1903 if (RT_SUCCESS(rc) || rc != VERR_IOMMU_NOT_PRESENT)
1904 return rc;
1905#endif
1906
1907 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, fFlags);
1908}
1909
1910
1911/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysGCPhys2CCPtr} */
1912static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysGCPhys2CCPtr(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
1913 uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock)
1914{
1915 PDMDEV_ASSERT_DEVINS(pDevIns);
1916 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1917 pPciDev = pDevIns->apPciDevs[0];
1918 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1919 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1920
1921#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
1922 if (PCIDevIsBusmaster(pPciDev))
1923 { /* likely */ }
1924 else
1925 {
1926 LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp fFlags=%#RX32\n",
1927 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, fFlags));
1928 return VERR_PDM_NOT_PCI_BUS_MASTER;
1929 }
1930#endif
1931
1932#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
1933 int rc = pdmR3IommuMemAccessWriteCCPtr(pDevIns, pPciDev, GCPhys, fFlags, ppv, pLock);
1934 if (RT_SUCCESS(rc) || rc != VERR_IOMMU_NOT_PRESENT)
1935 return rc;
1936#endif
1937
1938 return pDevIns->pHlpR3->pfnPhysGCPhys2CCPtr(pDevIns, GCPhys, fFlags, ppv, pLock);
1939}
1940
1941
1942/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysGCPhys2CCPtrReadOnly} */
1943static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
1944 uint32_t fFlags, void const **ppv, PPGMPAGEMAPLOCK pLock)
1945{
1946 PDMDEV_ASSERT_DEVINS(pDevIns);
1947 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1948 pPciDev = pDevIns->apPciDevs[0];
1949 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1950 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1951
1952#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
1953 if (PCIDevIsBusmaster(pPciDev))
1954 { /* likely */ }
1955 else
1956 {
1957 LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp fFlags=%#RX32\n",
1958 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, fFlags));
1959 return VERR_PDM_NOT_PCI_BUS_MASTER;
1960 }
1961#endif
1962
1963#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
1964 int rc = pdmR3IommuMemAccessReadCCPtr(pDevIns, pPciDev, GCPhys, fFlags, ppv, pLock);
1965 if (RT_SUCCESS(rc) || rc != VERR_IOMMU_NOT_PRESENT)
1966 return rc;
1967#endif
1968
1969 return pDevIns->pHlpR3->pfnPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhys, fFlags, ppv, pLock);
1970}
1971
1972
1973/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysBulkGCPhys2CCPtr} */
1974static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
1975 PCRTGCPHYS paGCPhysPages, uint32_t fFlags, void **papvPages,
1976 PPGMPAGEMAPLOCK paLocks)
1977{
1978 PDMDEV_ASSERT_DEVINS(pDevIns);
1979 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1980 pPciDev = pDevIns->apPciDevs[0];
1981 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1982 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1983
1984#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
1985 if (PCIDevIsBusmaster(pPciDev))
1986 { /* likely */ }
1987 else
1988 {
1989 LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! cPages=%zu fFlags=%#RX32\n",
1990 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, cPages, fFlags));
1991 return VERR_PDM_NOT_PCI_BUS_MASTER;
1992 }
1993#endif
1994
1995#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
1996 int rc = pdmR3IommuMemAccessBulkWriteCCPtr(pDevIns, pPciDev, cPages, paGCPhysPages, fFlags, papvPages, paLocks);
1997 if (RT_SUCCESS(rc) || rc != VERR_IOMMU_NOT_PRESENT)
1998 return rc;
1999#endif
2000
2001 return pDevIns->pHlpR3->pfnPhysBulkGCPhys2CCPtr(pDevIns, cPages, paGCPhysPages, fFlags, papvPages, paLocks);
2002}
2003
2004
2005/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysBulkGCPhys2CCPtrReadOnly} */
2006static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
2007 PCRTGCPHYS paGCPhysPages, uint32_t fFlags,
2008 const void **papvPages, PPGMPAGEMAPLOCK paLocks)
2009{
2010 PDMDEV_ASSERT_DEVINS(pDevIns);
2011 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2012 pPciDev = pDevIns->apPciDevs[0];
2013 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2014 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2015
2016#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
2017 if (PCIDevIsBusmaster(pPciDev))
2018 { /* likely */ }
2019 else
2020 {
2021 LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! cPages=%zu fFlags=%#RX32\n",
2022 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, cPages, fFlags));
2023 return VERR_PDM_NOT_PCI_BUS_MASTER;
2024 }
2025#endif
2026
2027#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
2028 int rc = pdmR3IommuMemAccessBulkReadCCPtr(pDevIns, pPciDev, cPages, paGCPhysPages, fFlags, papvPages, paLocks);
2029 if (RT_SUCCESS(rc) || rc != VERR_IOMMU_NOT_PRESENT)
2030 return rc;
2031#endif
2032
2033 return pDevIns->pHlpR3->pfnPhysBulkGCPhys2CCPtrReadOnly(pDevIns, cPages, paGCPhysPages, fFlags, papvPages, paLocks);
2034}
2035
2036
2037/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
2038static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2039{
2040 PDMDEV_ASSERT_DEVINS(pDevIns);
2041 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2042 pPciDev = pDevIns->apPciDevs[0];
2043 AssertReturnVoid(pPciDev);
2044 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
2045 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
2046 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2047
2048 /*
2049 * Validate input.
2050 */
2051 Assert(iIrq == 0);
2052 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2053
2054 /*
2055 * Must have a PCI device registered!
2056 */
2057 PVM pVM = pDevIns->Internal.s.pVMR3;
2058 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2059 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
2060 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2061
2062 pdmLock(pVM);
2063 uint32_t uTagSrc;
2064 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2065 {
2066 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2067 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2068 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2069 else
2070 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2071 }
2072 else
2073 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2074
2075 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
2076
2077 if (iLevel == PDM_IRQ_LEVEL_LOW)
2078 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2079 pdmUnlock(pVM);
2080
2081 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2082}
2083
2084
2085/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
2086static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2087{
2088 pdmR3DevHlp_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
2089}
2090
2091
2092/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
2093static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2094{
2095 PDMDEV_ASSERT_DEVINS(pDevIns);
2096 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
2097
2098 /*
2099 * Validate input.
2100 */
2101 Assert(iIrq < 16);
2102 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2103
2104 PVM pVM = pDevIns->Internal.s.pVMR3;
2105
2106 /*
2107 * Do the job.
2108 */
2109 pdmLock(pVM);
2110 uint32_t uTagSrc;
2111 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2112 {
2113 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2114 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2115 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2116 else
2117 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2118 }
2119 else
2120 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2121
2122 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
2123
2124 if (iLevel == PDM_IRQ_LEVEL_LOW)
2125 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2126 pdmUnlock(pVM);
2127
2128 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2129}
2130
2131
2132/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
2133static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2134{
2135 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
2136}
2137
2138
2139/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
2140static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
2141{
2142 PDMDEV_ASSERT_DEVINS(pDevIns);
2143 PVM pVM = pDevIns->Internal.s.pVMR3;
2144 VM_ASSERT_EMT(pVM);
2145 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
2146 pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
2147
2148 /*
2149 * Lookup the LUN, it might already be registered.
2150 */
2151 PPDMLUN pLunPrev = NULL;
2152 PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
2153 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
2154 if (pLun->iLun == iLun)
2155 break;
2156
2157 /*
2158 * Create the LUN if if wasn't found, else check if driver is already attached to it.
2159 */
2160 if (!pLun)
2161 {
2162 if ( !pBaseInterface
2163 || !pszDesc
2164 || !*pszDesc)
2165 {
2166 Assert(pBaseInterface);
2167 Assert(pszDesc || *pszDesc);
2168 return VERR_INVALID_PARAMETER;
2169 }
2170
2171 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
2172 if (!pLun)
2173 return VERR_NO_MEMORY;
2174
2175 pLun->iLun = iLun;
2176 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
2177 pLun->pTop = NULL;
2178 pLun->pBottom = NULL;
2179 pLun->pDevIns = pDevIns;
2180 pLun->pUsbIns = NULL;
2181 pLun->pszDesc = pszDesc;
2182 pLun->pBase = pBaseInterface;
2183 if (!pLunPrev)
2184 pDevIns->Internal.s.pLunsR3 = pLun;
2185 else
2186 pLunPrev->pNext = pLun;
2187 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
2188 iLun, pszDesc, pDevIns->pReg->szName, pDevIns->iInstance));
2189 }
2190 else if (pLun->pTop)
2191 {
2192 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
2193 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
2194 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
2195 }
2196 Assert(pLun->pBase == pBaseInterface);
2197
2198
2199 /*
2200 * Get the attached driver configuration.
2201 */
2202 int rc;
2203 PCFGMNODE pNode = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "LUN#%u", iLun);
2204 if (pNode)
2205 rc = pdmR3DrvInstantiate(pVM, pNode, pBaseInterface, NULL /*pDrvAbove*/, pLun, ppBaseInterface);
2206 else
2207 rc = VERR_PDM_NO_ATTACHED_DRIVER;
2208
2209 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2210 return rc;
2211}
2212
2213
2214/** @interface_method_impl{PDMDEVHLPR3,pfnDriverDetach} */
2215static DECLCALLBACK(int) pdmR3DevHlp_DriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
2216{
2217 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
2218 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: pDrvIns=%p\n",
2219 pDevIns->pReg->szName, pDevIns->iInstance, pDrvIns));
2220
2221#ifdef VBOX_STRICT
2222 PVM pVM = pDevIns->Internal.s.pVMR3;
2223 VM_ASSERT_EMT(pVM);
2224#endif
2225
2226 int rc = pdmR3DrvDetach(pDrvIns, fFlags);
2227
2228 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2229 return rc;
2230}
2231
2232
2233/** @interface_method_impl{PDMDEVHLPR3,pfnDriverReconfigure} */
2234static DECLCALLBACK(int) pdmR3DevHlp_DriverReconfigure(PPDMDEVINS pDevIns, uint32_t iLun, uint32_t cDepth,
2235 const char * const *papszDrivers, PCFGMNODE *papConfigs, uint32_t fFlags)
2236{
2237 PDMDEV_ASSERT_DEVINS(pDevIns);
2238 PVM pVM = pDevIns->Internal.s.pVMR3;
2239 VM_ASSERT_EMT(pVM);
2240 LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: iLun=%u cDepth=%u fFlags=%#x\n",
2241 pDevIns->pReg->szName, pDevIns->iInstance, iLun, cDepth, fFlags));
2242
2243 /*
2244 * Validate input.
2245 */
2246 AssertReturn(cDepth <= 8, VERR_INVALID_PARAMETER);
2247 AssertPtrReturn(papszDrivers, VERR_INVALID_POINTER);
2248 AssertPtrNullReturn(papConfigs, VERR_INVALID_POINTER);
2249 for (uint32_t i = 0; i < cDepth; i++)
2250 {
2251 AssertPtrReturn(papszDrivers[i], VERR_INVALID_POINTER);
2252 size_t cchDriver = strlen(papszDrivers[i]);
2253 AssertReturn(cchDriver > 0 && cchDriver < RT_SIZEOFMEMB(PDMDRVREG, szName), VERR_OUT_OF_RANGE);
2254
2255 if (papConfigs)
2256 AssertPtrNullReturn(papConfigs[i], VERR_INVALID_POINTER);
2257 }
2258 AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
2259
2260 /*
2261 * Do we have to detach an existing driver first?
2262 */
2263 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
2264 if (pLun->iLun == iLun)
2265 {
2266 if (pLun->pTop)
2267 {
2268 int rc = pdmR3DrvDetach(pLun->pTop, 0);
2269 AssertRCReturn(rc, rc);
2270 }
2271 break;
2272 }
2273
2274 /*
2275 * Remove the old tree.
2276 */
2277 PCFGMNODE pCfgDev = CFGMR3GetChildF(CFGMR3GetRoot(pVM), "Devices/%s/%u/", pDevIns->pReg->szName, pDevIns->iInstance);
2278 AssertReturn(pCfgDev, VERR_INTERNAL_ERROR_2);
2279 PCFGMNODE pCfgLun = CFGMR3GetChildF(pCfgDev, "LUN#%u", iLun);
2280 if (pCfgLun)
2281 CFGMR3RemoveNode(pCfgLun);
2282
2283 /*
2284 * Construct a new tree.
2285 */
2286 int rc = CFGMR3InsertNodeF(pCfgDev, &pCfgLun, "LUN#%u", iLun);
2287 AssertRCReturn(rc, rc);
2288 PCFGMNODE pCfgDrv = pCfgLun;
2289 for (uint32_t i = 0; i < cDepth; i++)
2290 {
2291 rc = CFGMR3InsertString(pCfgDrv, "Driver", papszDrivers[i]);
2292 AssertRCReturn(rc, rc);
2293 if (papConfigs && papConfigs[i])
2294 {
2295 rc = CFGMR3InsertSubTree(pCfgDrv, "Config", papConfigs[i], NULL);
2296 AssertRCReturn(rc, rc);
2297 papConfigs[i] = NULL;
2298 }
2299 else
2300 {
2301 rc = CFGMR3InsertNode(pCfgDrv, "Config", NULL);
2302 AssertRCReturn(rc, rc);
2303 }
2304
2305 if (i + 1 >= cDepth)
2306 break;
2307 rc = CFGMR3InsertNode(pCfgDrv, "AttachedDriver", &pCfgDrv);
2308 AssertRCReturn(rc, rc);
2309 }
2310
2311 LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2312 return rc;
2313}
2314
2315
2316/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreatePtr} */
2317static DECLCALLBACK(int) pdmR3DevHlp_QueueCreatePtr(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2318 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)
2319{
2320 PDMDEV_ASSERT_DEVINS(pDevIns);
2321 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} ppQueue=%p\n",
2322 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, ppQueue));
2323
2324 PVM pVM = pDevIns->Internal.s.pVMR3;
2325 VM_ASSERT_EMT(pVM);
2326
2327 if (pDevIns->iInstance > 0)
2328 {
2329 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2330 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2331 }
2332
2333 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, ppQueue);
2334
2335 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppQueue));
2336 return rc;
2337}
2338
2339
2340/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
2341static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2342 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName,
2343 PDMQUEUEHANDLE *phQueue)
2344{
2345 PDMDEV_ASSERT_DEVINS(pDevIns);
2346 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} phQueue=%p\n",
2347 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, phQueue));
2348
2349 PVM pVM = pDevIns->Internal.s.pVMR3;
2350 VM_ASSERT_EMT(pVM);
2351
2352 if (pDevIns->iInstance > 0)
2353 {
2354 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2355 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2356 }
2357
2358 PPDMQUEUE pQueue = NULL;
2359 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, &pQueue);
2360 *phQueue = (uintptr_t)pQueue;
2361
2362 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phQueue));
2363 return rc;
2364}
2365
2366
2367/** @interface_method_impl{PDMDEVHLPR3,pfnQueueToPtr} */
2368static DECLCALLBACK(PPDMQUEUE) pdmR3DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2369{
2370 PDMDEV_ASSERT_DEVINS(pDevIns);
2371 RT_NOREF(pDevIns);
2372 return (PPDMQUEUE)hQueue;
2373}
2374
2375
2376/** @interface_method_impl{PDMDEVHLPR3,pfnQueueAlloc} */
2377static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR3DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2378{
2379 return PDMQueueAlloc(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2380}
2381
2382
2383/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsert} */
2384static DECLCALLBACK(void) pdmR3DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
2385{
2386 return PDMQueueInsert(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem);
2387}
2388
2389
2390/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsertEx} */
2391static DECLCALLBACK(void) pdmR3DevHlp_QueueInsertEx(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem,
2392 uint64_t cNanoMaxDelay)
2393{
2394 return PDMQueueInsertEx(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem, cNanoMaxDelay);
2395}
2396
2397
2398/** @interface_method_impl{PDMDEVHLPR3,pfnQueueFlushIfNecessary} */
2399static DECLCALLBACK(bool) pdmR3DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2400{
2401 return PDMQueueFlushIfNecessary(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2402}
2403
2404
2405/** @interface_method_impl{PDMDEVHLPR3,pfnTaskCreate} */
2406static DECLCALLBACK(int) pdmR3DevHlp_TaskCreate(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszName,
2407 PFNPDMTASKDEV pfnCallback, void *pvUser, PDMTASKHANDLE *phTask)
2408{
2409 PDMDEV_ASSERT_DEVINS(pDevIns);
2410 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: pfnCallback=%p fFlags=%#x pszName=%p:{%s} phTask=%p\n",
2411 pDevIns->pReg->szName, pDevIns->iInstance, pfnCallback, fFlags, pszName, pszName, phTask));
2412 PVM pVM = pDevIns->Internal.s.pVMR3;
2413 VM_ASSERT_EMT(pVM);
2414
2415 int rc = PDMR3TaskCreate(pVM, fFlags, pszName, PDMTASKTYPE_DEV, pDevIns, (PFNRT)pfnCallback, pvUser, phTask);
2416
2417 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2418 return rc;
2419}
2420
2421
2422/** @interface_method_impl{PDMDEVHLPR3,pfnTaskTrigger} */
2423static DECLCALLBACK(int) pdmR3DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
2424{
2425 PDMDEV_ASSERT_DEVINS(pDevIns);
2426 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
2427
2428 int rc = PDMTaskTrigger(pDevIns->Internal.s.pVMR3, PDMTASKTYPE_DEV, pDevIns, hTask);
2429
2430 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2431 return rc;
2432}
2433
2434
2435/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventCreate} */
2436static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventCreate(PPDMDEVINS pDevIns, PSUPSEMEVENT phEvent)
2437{
2438 PDMDEV_ASSERT_DEVINS(pDevIns);
2439 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEvent));
2440 PVM pVM = pDevIns->Internal.s.pVMR3;
2441 VM_ASSERT_EMT(pVM);
2442
2443 int rc = SUPSemEventCreate(pVM->pSession, phEvent);
2444
2445 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: returns %Rrc *phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEvent));
2446 return rc;
2447}
2448
2449
2450/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventClose} */
2451static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventClose(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2452{
2453 PDMDEV_ASSERT_DEVINS(pDevIns);
2454 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2455
2456 int rc = SUPSemEventClose(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2457
2458 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2459 return rc;
2460}
2461
2462
2463/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventSignal} */
2464static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2465{
2466 PDMDEV_ASSERT_DEVINS(pDevIns);
2467 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2468
2469 int rc = SUPSemEventSignal(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2470
2471 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2472 return rc;
2473}
2474
2475
2476/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNoResume} */
2477static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
2478{
2479 PDMDEV_ASSERT_DEVINS(pDevIns);
2480 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
2481 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
2482
2483 int rc = SUPSemEventWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEvent, cMillies);
2484
2485 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2486 return rc;
2487}
2488
2489
2490/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsAbsIntr} */
2491static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
2492{
2493 PDMDEV_ASSERT_DEVINS(pDevIns);
2494 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
2495 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
2496
2497 int rc = SUPSemEventWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, uNsTimeout);
2498
2499 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2500 return rc;
2501}
2502
2503
2504/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsRelIntr} */
2505static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
2506{
2507 PDMDEV_ASSERT_DEVINS(pDevIns);
2508 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
2509 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
2510
2511 int rc = SUPSemEventWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, cNsTimeout);
2512
2513 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2514 return rc;
2515}
2516
2517
2518/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventGetResolution} */
2519static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
2520{
2521 PDMDEV_ASSERT_DEVINS(pDevIns);
2522 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2523
2524 uint32_t cNsResolution = SUPSemEventGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2525
2526 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2527 return cNsResolution;
2528}
2529
2530
2531/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiCreate} */
2532static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiCreate(PPDMDEVINS pDevIns, PSUPSEMEVENTMULTI phEventMulti)
2533{
2534 PDMDEV_ASSERT_DEVINS(pDevIns);
2535 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEventMulti));
2536 PVM pVM = pDevIns->Internal.s.pVMR3;
2537 VM_ASSERT_EMT(pVM);
2538
2539 int rc = SUPSemEventMultiCreate(pVM->pSession, phEventMulti);
2540
2541 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: returns %Rrc *phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEventMulti));
2542 return rc;
2543}
2544
2545
2546/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiClose} */
2547static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiClose(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2548{
2549 PDMDEV_ASSERT_DEVINS(pDevIns);
2550 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2551
2552 int rc = SUPSemEventMultiClose(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2553
2554 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2555 return rc;
2556}
2557
2558
2559/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiSignal} */
2560static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2561{
2562 PDMDEV_ASSERT_DEVINS(pDevIns);
2563 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2564
2565 int rc = SUPSemEventMultiSignal(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2566
2567 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2568 return rc;
2569}
2570
2571
2572/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiReset} */
2573static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2574{
2575 PDMDEV_ASSERT_DEVINS(pDevIns);
2576 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2577
2578 int rc = SUPSemEventMultiReset(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2579
2580 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2581 return rc;
2582}
2583
2584
2585/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNoResume} */
2586static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2587 uint32_t cMillies)
2588{
2589 PDMDEV_ASSERT_DEVINS(pDevIns);
2590 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
2591 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
2592
2593 int rc = SUPSemEventMultiWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cMillies);
2594
2595 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2596 return rc;
2597}
2598
2599
2600/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsAbsIntr} */
2601static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2602 uint64_t uNsTimeout)
2603{
2604 PDMDEV_ASSERT_DEVINS(pDevIns);
2605 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
2606 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
2607
2608 int rc = SUPSemEventMultiWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, uNsTimeout);
2609
2610 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2611 return rc;
2612}
2613
2614
2615/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsRelIntr} */
2616static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2617 uint64_t cNsTimeout)
2618{
2619 PDMDEV_ASSERT_DEVINS(pDevIns);
2620 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
2621 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
2622
2623 int rc = SUPSemEventMultiWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cNsTimeout);
2624
2625 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2626 return rc;
2627}
2628
2629
2630/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiGetResolution} */
2631static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
2632{
2633 PDMDEV_ASSERT_DEVINS(pDevIns);
2634 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2635
2636 uint32_t cNsResolution = SUPSemEventMultiGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2637
2638 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2639 return cNsResolution;
2640}
2641
2642
2643/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
2644static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
2645 const char *pszNameFmt, va_list va)
2646{
2647 PDMDEV_ASSERT_DEVINS(pDevIns);
2648 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
2649 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
2650
2651 PVM pVM = pDevIns->Internal.s.pVMR3;
2652 VM_ASSERT_EMT(pVM);
2653 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
2654
2655 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2656 return rc;
2657}
2658
2659
2660/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
2661static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
2662{
2663 PDMDEV_ASSERT_DEVINS(pDevIns);
2664 PVM pVM = pDevIns->Internal.s.pVMR3;
2665 VM_ASSERT_EMT(pVM);
2666
2667 PPDMCRITSECT pCritSect = PDMR3CritSectGetNop(pVM);
2668 LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
2669 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2670 return pCritSect;
2671}
2672
2673
2674/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopR0} */
2675static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopR0(PPDMDEVINS pDevIns)
2676{
2677 PDMDEV_ASSERT_DEVINS(pDevIns);
2678 PVM pVM = pDevIns->Internal.s.pVMR3;
2679 VM_ASSERT_EMT(pVM);
2680
2681 R0PTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopR0(pVM);
2682 LogFlow(("pdmR3DevHlp_CritSectGetNopR0: caller='%s'/%d: return %RHv\n",
2683 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2684 return pCritSect;
2685}
2686
2687
2688/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopRC} */
2689static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopRC(PPDMDEVINS pDevIns)
2690{
2691 PDMDEV_ASSERT_DEVINS(pDevIns);
2692 PVM pVM = pDevIns->Internal.s.pVMR3;
2693 VM_ASSERT_EMT(pVM);
2694
2695 RCPTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopRC(pVM);
2696 LogFlow(("pdmR3DevHlp_CritSectGetNopRC: caller='%s'/%d: return %RRv\n",
2697 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2698 return pCritSect;
2699}
2700
2701
2702/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
2703static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2704{
2705 /*
2706 * Validate input.
2707 *
2708 * Note! We only allow the automatically created default critical section
2709 * to be replaced by this API.
2710 */
2711 PDMDEV_ASSERT_DEVINS(pDevIns);
2712 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
2713 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
2714 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
2715 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
2716 PVM pVM = pDevIns->Internal.s.pVMR3;
2717 AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
2718
2719 VM_ASSERT_EMT(pVM);
2720 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
2721
2722 AssertReturn(pDevIns->pCritSectRoR3, VERR_PDM_DEV_IPE_1);
2723 AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
2724 AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
2725 AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
2726
2727 /*
2728 * Replace the critical section and destroy the automatic default section.
2729 */
2730 PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
2731 pDevIns->pCritSectRoR3 = pCritSect;
2732 pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_CHANGED_CRITSECT;
2733
2734 Assert(RT_BOOL(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED) == pDevIns->fR0Enabled);
2735 if ( (pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)
2736 && !(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_NEW_STYLE))
2737 {
2738 PDMDEVICECOMPATSETCRITSECTREQ Req;
2739 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
2740 Req.Hdr.cbReq = sizeof(Req);
2741 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
2742 Req.pDevInsR3 = pDevIns;
2743 Req.pCritSectR3 = pCritSect;
2744 int rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT, 0, &Req.Hdr);
2745 AssertLogRelRCReturn(rc, rc);
2746 }
2747
2748 PDMR3CritSectDelete(pOldCritSect);
2749 Assert((uintptr_t)pOldCritSect - (uintptr_t)pDevIns < pDevIns->cbRing3);
2750
2751 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2752 return VINF_SUCCESS;
2753}
2754
2755
2756/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectYield} */
2757static DECLCALLBACK(bool) pdmR3DevHlp_CritSectYield(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2758{
2759 PDMDEV_ASSERT_DEVINS(pDevIns);
2760 return PDMR3CritSectYield(pDevIns->Internal.s.pVMR3, pCritSect);
2761}
2762
2763
2764/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnter} */
2765static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
2766{
2767 PDMDEV_ASSERT_DEVINS(pDevIns);
2768 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2769 return PDMCritSectEnter(pCritSect, rcBusy);
2770}
2771
2772
2773/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnterDebug} */
2774static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2775{
2776 PDMDEV_ASSERT_DEVINS(pDevIns);
2777 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2778 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2779}
2780
2781
2782/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnter} */
2783static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2784{
2785 PDMDEV_ASSERT_DEVINS(pDevIns);
2786 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2787 return PDMCritSectTryEnter(pCritSect);
2788}
2789
2790
2791/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnterDebug} */
2792static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2793{
2794 PDMDEV_ASSERT_DEVINS(pDevIns);
2795 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2796 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
2797}
2798
2799
2800/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectLeave} */
2801static DECLCALLBACK(int) pdmR3DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2802{
2803 PDMDEV_ASSERT_DEVINS(pDevIns);
2804 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2805 return PDMCritSectLeave(pCritSect);
2806}
2807
2808
2809/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsOwner} */
2810static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2811{
2812 PDMDEV_ASSERT_DEVINS(pDevIns);
2813 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2814 return PDMCritSectIsOwner(pCritSect);
2815}
2816
2817
2818/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsInitialized} */
2819static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2820{
2821 PDMDEV_ASSERT_DEVINS(pDevIns);
2822 RT_NOREF(pDevIns);
2823 return PDMCritSectIsInitialized(pCritSect);
2824}
2825
2826
2827/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectHasWaiters} */
2828static DECLCALLBACK(bool) pdmR3DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2829{
2830 PDMDEV_ASSERT_DEVINS(pDevIns);
2831 RT_NOREF(pDevIns);
2832 return PDMCritSectHasWaiters(pCritSect);
2833}
2834
2835
2836/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetRecursion} */
2837static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2838{
2839 PDMDEV_ASSERT_DEVINS(pDevIns);
2840 RT_NOREF(pDevIns);
2841 return PDMCritSectGetRecursion(pCritSect);
2842}
2843
2844
2845/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectScheduleExitEvent} */
2846static DECLCALLBACK(int) pdmR3DevHlp_CritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect,
2847 SUPSEMEVENT hEventToSignal)
2848{
2849 PDMDEV_ASSERT_DEVINS(pDevIns);
2850 RT_NOREF(pDevIns);
2851 return PDMHCCritSectScheduleExitEvent(pCritSect, hEventToSignal);
2852}
2853
2854
2855/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectDelete} */
2856static DECLCALLBACK(int) pdmR3DevHlp_CritSectDelete(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2857{
2858 PDMDEV_ASSERT_DEVINS(pDevIns);
2859 RT_NOREF(pDevIns);
2860 return PDMR3CritSectDelete(pCritSect);
2861}
2862
2863
2864/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
2865static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
2866 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
2867{
2868 PDMDEV_ASSERT_DEVINS(pDevIns);
2869 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2870 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
2871 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
2872
2873 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
2874
2875 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
2876 rc, *ppThread));
2877 return rc;
2878}
2879
2880
2881/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
2882static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
2883{
2884 PDMDEV_ASSERT_DEVINS(pDevIns);
2885 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
2886 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
2887
2888 int rc = VINF_SUCCESS;
2889 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
2890 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
2891 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
2892 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
2893 AssertStmt( enmVMState == VMSTATE_SUSPENDING
2894 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2895 || enmVMState == VMSTATE_SUSPENDING_LS
2896 || enmVMState == VMSTATE_RESETTING
2897 || enmVMState == VMSTATE_RESETTING_LS
2898 || enmVMState == VMSTATE_POWERING_OFF
2899 || enmVMState == VMSTATE_POWERING_OFF_LS,
2900 rc = VERR_INVALID_STATE);
2901
2902 if (RT_SUCCESS(rc))
2903 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
2904
2905 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2906 return rc;
2907}
2908
2909
2910/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
2911static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
2912{
2913 PDMDEV_ASSERT_DEVINS(pDevIns);
2914 PVM pVM = pDevIns->Internal.s.pVMR3;
2915
2916 VMSTATE enmVMState = VMR3GetState(pVM);
2917 if ( enmVMState == VMSTATE_SUSPENDING
2918 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2919 || enmVMState == VMSTATE_SUSPENDING_LS
2920 || enmVMState == VMSTATE_RESETTING
2921 || enmVMState == VMSTATE_RESETTING_LS
2922 || enmVMState == VMSTATE_POWERING_OFF
2923 || enmVMState == VMSTATE_POWERING_OFF_LS)
2924 {
2925 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2926 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
2927 }
2928 else
2929 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
2930}
2931
2932
2933/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
2934static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
2935{
2936 PDMDEV_ASSERT_DEVINS(pDevIns);
2937 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2938 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
2939 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
2940 pRtcReg->pfnWrite, ppRtcHlp));
2941
2942 /*
2943 * Validate input.
2944 */
2945 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
2946 {
2947 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
2948 PDM_RTCREG_VERSION));
2949 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
2950 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2951 return VERR_INVALID_PARAMETER;
2952 }
2953 if ( !pRtcReg->pfnWrite
2954 || !pRtcReg->pfnRead)
2955 {
2956 Assert(pRtcReg->pfnWrite);
2957 Assert(pRtcReg->pfnRead);
2958 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
2959 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2960 return VERR_INVALID_PARAMETER;
2961 }
2962
2963 if (!ppRtcHlp)
2964 {
2965 Assert(ppRtcHlp);
2966 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
2967 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2968 return VERR_INVALID_PARAMETER;
2969 }
2970
2971 /*
2972 * Only one DMA device.
2973 */
2974 PVM pVM = pDevIns->Internal.s.pVMR3;
2975 if (pVM->pdm.s.pRtc)
2976 {
2977 AssertMsgFailed(("Only one RTC device is supported!\n"));
2978 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2979 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2980 return VERR_INVALID_PARAMETER;
2981 }
2982
2983 /*
2984 * Allocate and initialize pci bus structure.
2985 */
2986 int rc = VINF_SUCCESS;
2987 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
2988 if (pRtc)
2989 {
2990 pRtc->pDevIns = pDevIns;
2991 pRtc->Reg = *pRtcReg;
2992 pVM->pdm.s.pRtc = pRtc;
2993
2994 /* set the helper pointer. */
2995 *ppRtcHlp = &g_pdmR3DevRtcHlp;
2996 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
2997 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2998 }
2999 else
3000 rc = VERR_NO_MEMORY;
3001
3002 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
3003 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3004 return rc;
3005}
3006
3007
3008/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
3009static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3010{
3011 PDMDEV_ASSERT_DEVINS(pDevIns);
3012 PVM pVM = pDevIns->Internal.s.pVMR3;
3013 VM_ASSERT_EMT(pVM);
3014 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
3015 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
3016 int rc = VINF_SUCCESS;
3017 if (pVM->pdm.s.pDmac)
3018 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pDevIns, pfnTransferHandler, pvUser);
3019 else
3020 {
3021 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3022 rc = VERR_PDM_NO_DMAC_INSTANCE;
3023 }
3024 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
3025 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3026 return rc;
3027}
3028
3029
3030/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
3031static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3032{
3033 PDMDEV_ASSERT_DEVINS(pDevIns);
3034 PVM pVM = pDevIns->Internal.s.pVMR3;
3035 VM_ASSERT_EMT(pVM);
3036 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
3037 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
3038 int rc = VINF_SUCCESS;
3039 if (pVM->pdm.s.pDmac)
3040 {
3041 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3042 if (pcbRead)
3043 *pcbRead = cb;
3044 }
3045 else
3046 {
3047 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3048 rc = VERR_PDM_NO_DMAC_INSTANCE;
3049 }
3050 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
3051 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3052 return rc;
3053}
3054
3055
3056/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
3057static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3058{
3059 PDMDEV_ASSERT_DEVINS(pDevIns);
3060 PVM pVM = pDevIns->Internal.s.pVMR3;
3061 VM_ASSERT_EMT(pVM);
3062 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
3063 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
3064 int rc = VINF_SUCCESS;
3065 if (pVM->pdm.s.pDmac)
3066 {
3067 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3068 if (pcbWritten)
3069 *pcbWritten = cb;
3070 }
3071 else
3072 {
3073 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3074 rc = VERR_PDM_NO_DMAC_INSTANCE;
3075 }
3076 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
3077 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3078 return rc;
3079}
3080
3081
3082/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
3083static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3084{
3085 PDMDEV_ASSERT_DEVINS(pDevIns);
3086 PVM pVM = pDevIns->Internal.s.pVMR3;
3087 VM_ASSERT_EMT(pVM);
3088 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
3089 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
3090 int rc = VINF_SUCCESS;
3091 if (pVM->pdm.s.pDmac)
3092 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
3093 else
3094 {
3095 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3096 rc = VERR_PDM_NO_DMAC_INSTANCE;
3097 }
3098 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
3099 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3100 return rc;
3101}
3102
3103/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
3104static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3105{
3106 PDMDEV_ASSERT_DEVINS(pDevIns);
3107 PVM pVM = pDevIns->Internal.s.pVMR3;
3108 VM_ASSERT_EMT(pVM);
3109 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
3110 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
3111 uint8_t u8Mode;
3112 if (pVM->pdm.s.pDmac)
3113 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
3114 else
3115 {
3116 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3117 u8Mode = 3 << 2 /* illegal mode type */;
3118 }
3119 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
3120 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
3121 return u8Mode;
3122}
3123
3124/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
3125static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
3126{
3127 PDMDEV_ASSERT_DEVINS(pDevIns);
3128 PVM pVM = pDevIns->Internal.s.pVMR3;
3129 VM_ASSERT_EMT(pVM);
3130 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
3131 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_IS_SET(pVM, VM_FF_PDM_DMA)));
3132
3133 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3134 VM_FF_SET(pVM, VM_FF_PDM_DMA);
3135 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
3136}
3137
3138
3139/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
3140static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3141{
3142 PDMDEV_ASSERT_DEVINS(pDevIns);
3143 PVM pVM = pDevIns->Internal.s.pVMR3;
3144 VM_ASSERT_EMT(pVM);
3145
3146 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
3147 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
3148 int rc;
3149 if (pVM->pdm.s.pRtc)
3150 {
3151 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3152 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3153 if (RT_SUCCESS(rc))
3154 {
3155 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pDevInsRtc, iReg, u8Value);
3156 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
3157 }
3158 }
3159 else
3160 rc = VERR_PDM_NO_RTC_INSTANCE;
3161
3162 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3163 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3164 return rc;
3165}
3166
3167
3168/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
3169static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3170{
3171 PDMDEV_ASSERT_DEVINS(pDevIns);
3172 PVM pVM = pDevIns->Internal.s.pVMR3;
3173 VM_ASSERT_EMT(pVM);
3174
3175 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
3176 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
3177 int rc;
3178 if (pVM->pdm.s.pRtc)
3179 {
3180 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3181 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3182 if (RT_SUCCESS(rc))
3183 {
3184 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pDevInsRtc, iReg, pu8Value);
3185 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
3186 }
3187 }
3188 else
3189 rc = VERR_PDM_NO_RTC_INSTANCE;
3190
3191 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3192 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3193 return rc;
3194}
3195
3196
3197/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
3198static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3199{
3200 PDMDEV_ASSERT_DEVINS(pDevIns);
3201 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3202 return true;
3203
3204 char szMsg[100];
3205 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3206 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3207 AssertBreakpoint();
3208 return false;
3209}
3210
3211
3212/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
3213static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3214{
3215 PDMDEV_ASSERT_DEVINS(pDevIns);
3216 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3217 return true;
3218
3219 char szMsg[100];
3220 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3221 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3222 AssertBreakpoint();
3223 return false;
3224}
3225
3226
3227/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
3228static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3229 const char *pszSymPrefix, const char *pszSymList)
3230{
3231 PDMDEV_ASSERT_DEVINS(pDevIns);
3232 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3233 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3234 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3235
3236 int rc;
3237 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3238 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3239 {
3240 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
3241 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3242 pvInterface, cbInterface,
3243 pDevIns->pReg->pszRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
3244 pszSymPrefix, pszSymList,
3245 false /*fRing0OrRC*/);
3246 else
3247 {
3248 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
3249 rc = VERR_PERMISSION_DENIED;
3250 }
3251 }
3252 else
3253 {
3254 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3255 pszSymPrefix, pDevIns->pReg->szName));
3256 rc = VERR_INVALID_NAME;
3257 }
3258
3259 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3260 pDevIns->iInstance, rc));
3261 return rc;
3262}
3263
3264
3265/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
3266static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3267 const char *pszSymPrefix, const char *pszSymList)
3268{
3269 PDMDEV_ASSERT_DEVINS(pDevIns);
3270 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3271 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3272 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3273
3274 int rc;
3275 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3276 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3277 {
3278 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3279 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3280 pvInterface, cbInterface,
3281 pDevIns->pReg->pszR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
3282 pszSymPrefix, pszSymList,
3283 true /*fRing0OrRC*/);
3284 else
3285 {
3286 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
3287 rc = VERR_PERMISSION_DENIED;
3288 }
3289 }
3290 else
3291 {
3292 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3293 pszSymPrefix, pDevIns->pReg->szName));
3294 rc = VERR_INVALID_NAME;
3295 }
3296
3297 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3298 pDevIns->iInstance, rc));
3299 return rc;
3300}
3301
3302
3303/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
3304static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
3305{
3306 PDMDEV_ASSERT_DEVINS(pDevIns);
3307 PVM pVM = pDevIns->Internal.s.pVMR3;
3308 PVMCPU pVCpu = VMMGetCpu(pVM);
3309 AssertReturn(pVCpu, VERR_VM_THREAD_IS_EMT);
3310 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
3311 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
3312
3313 /*
3314 * Resolve the ring-0 entry point. There is not need to remember this like
3315 * we do for drivers since this is mainly for construction time hacks and
3316 * other things that aren't performance critical.
3317 */
3318 int rc;
3319 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3320 {
3321 /*
3322 * Make the ring-0 call.
3323 */
3324 PDMDEVICEGENCALLREQ Req;
3325 RT_ZERO(Req.Params);
3326 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
3327 Req.Hdr.cbReq = sizeof(Req);
3328 Req.pDevInsR3 = pDevIns;
3329 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
3330 Req.enmCall = PDMDEVICEGENCALL_REQUEST;
3331 Req.Params.Req.uReq = uOperation;
3332 Req.Params.Req.uArg = u64Arg;
3333 rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_PDM_DEVICE_GEN_CALL, 0, &Req.Hdr);
3334 }
3335 else
3336 rc = VERR_ACCESS_DENIED;
3337 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3338 pDevIns->iInstance, rc));
3339 return rc;
3340}
3341
3342
3343/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
3344static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
3345{
3346 PDMDEV_ASSERT_DEVINS(pDevIns);
3347 PVM pVM = pDevIns->Internal.s.pVMR3;
3348 VM_ASSERT_EMT(pVM);
3349 VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
3350 LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
3351 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3352 return enmReason;
3353}
3354
3355
3356/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
3357static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
3358{
3359 PDMDEV_ASSERT_DEVINS(pDevIns);
3360 PVM pVM = pDevIns->Internal.s.pVMR3;
3361 VM_ASSERT_EMT(pVM);
3362 VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
3363 LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
3364 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3365 return enmReason;
3366}
3367
3368
3369/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
3370static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
3371{
3372 PDMDEV_ASSERT_DEVINS(pDevIns);
3373 LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3374 return pDevIns->Internal.s.pVMR3->pUVM;
3375}
3376
3377
3378/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3379static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
3380{
3381 PDMDEV_ASSERT_DEVINS(pDevIns);
3382 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3383 return pDevIns->Internal.s.pVMR3;
3384}
3385
3386
3387/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3388static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
3389{
3390 PDMDEV_ASSERT_DEVINS(pDevIns);
3391 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3392 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
3393 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
3394}
3395
3396
3397/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
3398static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
3399{
3400 PDMDEV_ASSERT_DEVINS(pDevIns);
3401 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR3);
3402 LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
3403 return idCpu;
3404}
3405
3406
3407/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
3408static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
3409 PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
3410{
3411 PDMDEV_ASSERT_DEVINS(pDevIns);
3412 PVM pVM = pDevIns->Internal.s.pVMR3;
3413 VM_ASSERT_EMT(pVM);
3414 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
3415 ".pfnInterceptConfigAccesses=%p, pfnConfigRead=%p, pfnConfigWrite=%p, .pfnSetIrqR3=%p, .u32EndVersion=%#x} ppPciHlpR3=%p piBus=%p\n",
3416 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
3417 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnInterceptConfigAccesses, pPciBusReg->pfnConfigRead,
3418 pPciBusReg->pfnConfigWrite, pPciBusReg->pfnSetIrqR3, pPciBusReg->u32EndVersion, ppPciHlp, piBus));
3419
3420 /*
3421 * Validate the structure and output parameters.
3422 */
3423 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGR3_VERSION,
3424 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3425 VERR_INVALID_PARAMETER);
3426 AssertPtrReturn(pPciBusReg->pfnRegisterR3, VERR_INVALID_PARAMETER);
3427 AssertPtrNullReturn(pPciBusReg->pfnRegisterMsiR3, VERR_INVALID_POINTER);
3428 AssertPtrReturn(pPciBusReg->pfnIORegionRegisterR3, VERR_INVALID_POINTER);
3429 AssertPtrReturn(pPciBusReg->pfnInterceptConfigAccesses, VERR_INVALID_POINTER);
3430 AssertPtrReturn(pPciBusReg->pfnConfigWrite, VERR_INVALID_POINTER);
3431 AssertPtrReturn(pPciBusReg->pfnConfigRead, VERR_INVALID_POINTER);
3432 AssertPtrReturn(pPciBusReg->pfnSetIrqR3, VERR_INVALID_POINTER);
3433 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGR3_VERSION,
3434 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3435 VERR_INVALID_PARAMETER);
3436 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
3437 AssertPtrNullReturn(piBus, VERR_INVALID_POINTER);
3438 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3439
3440 /*
3441 * Find free PCI bus entry.
3442 */
3443 unsigned iBus = 0;
3444 for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
3445 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
3446 break;
3447 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
3448 ("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)),
3449 VERR_OUT_OF_RESOURCES);
3450 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
3451
3452 /*
3453 * Init the R3 bits.
3454 */
3455 pPciBus->iBus = iBus;
3456 pPciBus->pDevInsR3 = pDevIns;
3457 pPciBus->pfnRegister = pPciBusReg->pfnRegisterR3;
3458 pPciBus->pfnRegisterMsi = pPciBusReg->pfnRegisterMsiR3;
3459 pPciBus->pfnIORegionRegister = pPciBusReg->pfnIORegionRegisterR3;
3460 pPciBus->pfnInterceptConfigAccesses = pPciBusReg->pfnInterceptConfigAccesses;
3461 pPciBus->pfnConfigRead = pPciBusReg->pfnConfigRead;
3462 pPciBus->pfnConfigWrite = pPciBusReg->pfnConfigWrite;
3463 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
3464
3465 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3466
3467 /* set the helper pointer and return. */
3468 *ppPciHlp = &g_pdmR3DevPciHlp;
3469 if (piBus)
3470 *piBus = iBus;
3471 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS, iBus));
3472 return VINF_SUCCESS;
3473}
3474
3475
3476/** @interface_method_impl{PDMDEVHLPR3,pfnIommuRegister} */
3477static DECLCALLBACK(int) pdmR3DevHlp_IommuRegister(PPDMDEVINS pDevIns, PPDMIOMMUREGR3 pIommuReg, PCPDMIOMMUHLPR3 *ppIommuHlp,
3478 uint32_t *pidxIommu)
3479{
3480 PDMDEV_ASSERT_DEVINS(pDevIns);
3481 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3482 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: pIommuReg=%p:{.u32Version=%#x, .u32TheEnd=%#x } ppIommuHlp=%p\n",
3483 pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
3484 PVM pVM = pDevIns->Internal.s.pVMR3;
3485
3486 /*
3487 * Validate input.
3488 */
3489 AssertMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGR3_VERSION,
3490 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32Version, PDM_IOMMUREGR3_VERSION),
3491 VERR_INVALID_PARAMETER);
3492 AssertPtrReturn(pIommuReg->pfnMemAccess, VERR_INVALID_POINTER);
3493 AssertPtrReturn(pIommuReg->pfnMemBulkAccess, VERR_INVALID_POINTER);
3494 AssertPtrReturn(pIommuReg->pfnMsiRemap, VERR_INVALID_POINTER);
3495 AssertMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGR3_VERSION,
3496 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32TheEnd, PDM_IOMMUREGR3_VERSION),
3497 VERR_INVALID_PARAMETER);
3498 AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
3499
3500 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3501 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3502
3503 /*
3504 * Find free IOMMU slot.
3505 * The IOMMU at the root complex is the one at 0.
3506 */
3507 unsigned idxIommu = 0;
3508#if 0
3509 for (idxIommu = 0; idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus); idxIommu++)
3510 if (!pVM->pdm.s.aIommus[idxIommu].pDevInsR3)
3511 break;
3512 AssertLogRelMsgReturn(idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus),
3513 ("Too many IOMMUs. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aIommus)),
3514 VERR_OUT_OF_RESOURCES);
3515#else
3516 /* Currently we support only a single IOMMU. */
3517 AssertMsgReturn(!pVM->pdm.s.aIommus[0].pDevInsR3,
3518 ("%s/%u: Only one IOMMU device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3519 VERR_ALREADY_EXISTS);
3520#endif
3521 PPDMIOMMUR3 pIommu = &pVM->pdm.s.aIommus[idxIommu];
3522
3523 /*
3524 * Init the R3 bits.
3525 */
3526 pIommu->idxIommu = idxIommu;
3527 pIommu->pDevInsR3 = pDevIns;
3528 pIommu->pfnMemAccess = pIommuReg->pfnMemAccess;
3529 pIommu->pfnMemBulkAccess = pIommuReg->pfnMemBulkAccess;
3530 pIommu->pfnMsiRemap = pIommuReg->pfnMsiRemap;
3531 Log(("PDM: Registered IOMMU device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3532
3533 /* Set the helper pointer and return. */
3534 *ppIommuHlp = &g_pdmR3DevIommuHlp;
3535 if (pidxIommu)
3536 *pidxIommu = idxIommu;
3537 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3538 return VINF_SUCCESS;
3539}
3540
3541
3542
3543/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
3544static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
3545{
3546 PDMDEV_ASSERT_DEVINS(pDevIns);
3547 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3548 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
3549 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
3550 PVM pVM = pDevIns->Internal.s.pVMR3;
3551
3552 /*
3553 * Validate input.
3554 */
3555 AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
3556 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
3557 VERR_INVALID_PARAMETER);
3558 AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
3559 AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
3560 AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
3561 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
3562 VERR_INVALID_PARAMETER);
3563 AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
3564
3565 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3566 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3567
3568 /*
3569 * Only one PIC device.
3570 */
3571 AssertMsgReturn(pVM->pdm.s.Pic.pDevInsR3 == NULL, ("%s/%d: Only one PIC!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3572 VERR_ALREADY_EXISTS);
3573
3574 /*
3575 * Take down the callbacks and instance.
3576 */
3577 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3578 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrq;
3579 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterrupt;
3580 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3581
3582 /* set the helper pointer and return. */
3583 *ppPicHlp = &g_pdmR3DevPicHlp;
3584 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3585 return VINF_SUCCESS;
3586}
3587
3588
3589/** @interface_method_impl{PDMDEVHLPR3,pfnApicRegister} */
3590static DECLCALLBACK(int) pdmR3DevHlp_ApicRegister(PPDMDEVINS pDevIns)
3591{
3592 PDMDEV_ASSERT_DEVINS(pDevIns);
3593
3594 /*
3595 * Validate caller context.
3596 */
3597 PVM pVM = pDevIns->Internal.s.pVMR3;
3598 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3599 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3600
3601 /*
3602 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3603 * as they need to communicate and share state easily.
3604 */
3605 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 == NULL,
3606 ("%s/%u: Only one APIC device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3607 VERR_ALREADY_EXISTS);
3608
3609 /*
3610 * Set the ring-3 and raw-mode bits, leave the ring-0 to ring-0 setup.
3611 */
3612 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3613 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3614 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3615
3616 LogFlow(("pdmR3DevHlp_ApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3617 return VINF_SUCCESS;
3618}
3619
3620
3621/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicRegister} */
3622static DECLCALLBACK(int) pdmR3DevHlp_IoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
3623{
3624 PDMDEV_ASSERT_DEVINS(pDevIns);
3625 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
3626 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
3627 PVM pVM = pDevIns->Internal.s.pVMR3;
3628
3629 /*
3630 * Validate input.
3631 */
3632 AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
3633 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
3634 VERR_VERSION_MISMATCH);
3635 AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
3636 AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
3637 AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
3638 AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
3639 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
3640 VERR_VERSION_MISMATCH);
3641 AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
3642 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3643 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3644
3645 /*
3646 * The I/O APIC requires the APIC to be present (hacks++).
3647 * If the I/O APIC does GC stuff so must the APIC.
3648 */
3649 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 != NULL, ("Configuration error / Init order error! No APIC!\n"), VERR_WRONG_ORDER);
3650
3651 /*
3652 * Only one I/O APIC device.
3653 */
3654 AssertMsgReturn(pVM->pdm.s.IoApic.pDevInsR3 == NULL,
3655 ("Only one IOAPIC device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3656 VERR_ALREADY_EXISTS);
3657
3658 /*
3659 * Initialize the R3 bits.
3660 */
3661 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3662 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrq;
3663 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsi;
3664 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoi;
3665 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3666
3667 /* set the helper pointer and return. */
3668 *ppIoApicHlp = &g_pdmR3DevIoApicHlp;
3669 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3670 return VINF_SUCCESS;
3671}
3672
3673
3674/** @interface_method_impl{PDMDEVHLPR3,pfnHpetRegister} */
3675static DECLCALLBACK(int) pdmR3DevHlp_HpetRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
3676{
3677 PDMDEV_ASSERT_DEVINS(pDevIns);
3678 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3679 PVM pVM = pDevIns->Internal.s.pVMR3;
3680
3681 /*
3682 * Validate input.
3683 */
3684 AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
3685 ("%s/%u: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
3686 VERR_VERSION_MISMATCH);
3687 AssertPtrReturn(ppHpetHlpR3, VERR_INVALID_POINTER);
3688 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3689 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3690
3691 /*
3692 * Only one HPET device.
3693 */
3694 AssertMsgReturn(pVM->pdm.s.pHpet == NULL,
3695 ("Only one HPET device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3696 VERR_ALREADY_EXISTS);
3697
3698 /*
3699 * Do the job (what there is of it).
3700 */
3701 pVM->pdm.s.pHpet = pDevIns;
3702 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
3703
3704 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3705 return VINF_SUCCESS;
3706}
3707
3708
3709/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
3710static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
3711{
3712 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3713 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3714 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3715
3716 /*
3717 * Validate input.
3718 */
3719 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
3720 {
3721 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
3722 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3723 return VERR_INVALID_PARAMETER;
3724 }
3725
3726 if (!ppPciRawHlpR3)
3727 {
3728 Assert(ppPciRawHlpR3);
3729 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3730 return VERR_INVALID_PARAMETER;
3731 }
3732
3733 /* set the helper pointer and return. */
3734 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
3735 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3736 return VINF_SUCCESS;
3737}
3738
3739
3740/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
3741static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3742{
3743 PDMDEV_ASSERT_DEVINS(pDevIns);
3744 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3745 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",
3746 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3747 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3748
3749 /*
3750 * Validate input.
3751 */
3752 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3753 {
3754 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3755 PDM_DMACREG_VERSION));
3756 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
3757 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3758 return VERR_INVALID_PARAMETER;
3759 }
3760 if ( !pDmacReg->pfnRun
3761 || !pDmacReg->pfnRegister
3762 || !pDmacReg->pfnReadMemory
3763 || !pDmacReg->pfnWriteMemory
3764 || !pDmacReg->pfnSetDREQ
3765 || !pDmacReg->pfnGetChannelMode)
3766 {
3767 Assert(pDmacReg->pfnRun);
3768 Assert(pDmacReg->pfnRegister);
3769 Assert(pDmacReg->pfnReadMemory);
3770 Assert(pDmacReg->pfnWriteMemory);
3771 Assert(pDmacReg->pfnSetDREQ);
3772 Assert(pDmacReg->pfnGetChannelMode);
3773 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3774 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3775 return VERR_INVALID_PARAMETER;
3776 }
3777
3778 if (!ppDmacHlp)
3779 {
3780 Assert(ppDmacHlp);
3781 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
3782 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3783 return VERR_INVALID_PARAMETER;
3784 }
3785
3786 /*
3787 * Only one DMA device.
3788 */
3789 PVM pVM = pDevIns->Internal.s.pVMR3;
3790 if (pVM->pdm.s.pDmac)
3791 {
3792 AssertMsgFailed(("Only one DMA device is supported!\n"));
3793 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3794 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3795 return VERR_INVALID_PARAMETER;
3796 }
3797
3798 /*
3799 * Allocate and initialize pci bus structure.
3800 */
3801 int rc = VINF_SUCCESS;
3802 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3803 if (pDmac)
3804 {
3805 pDmac->pDevIns = pDevIns;
3806 pDmac->Reg = *pDmacReg;
3807 pVM->pdm.s.pDmac = pDmac;
3808
3809 /* set the helper pointer. */
3810 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3811 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3812 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3813 }
3814 else
3815 rc = VERR_NO_MEMORY;
3816
3817 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3818 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3819 return rc;
3820}
3821
3822
3823/**
3824 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3825 */
3826static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
3827{
3828 PDMDEV_ASSERT_DEVINS(pDevIns);
3829 PVM pVM = pDevIns->Internal.s.pVMR3;
3830 VM_ASSERT_EMT(pVM);
3831 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
3832 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
3833
3834 if (pVM->pdm.s.pvVMMDevHeap == NULL)
3835 {
3836 pVM->pdm.s.pvVMMDevHeap = pvHeap;
3837 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3838 pVM->pdm.s.cbVMMDevHeap = cbHeap;
3839 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
3840 }
3841 else
3842 {
3843 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
3844 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
3845 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
3846 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
3847 {
3848 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3849 if (pVM->pdm.s.pfnVMMDevHeapNotify)
3850 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
3851 }
3852 }
3853
3854 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
3855 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3856 return VINF_SUCCESS;
3857}
3858
3859
3860/**
3861 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
3862 */
3863static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
3864{
3865 PDMDEV_ASSERT_DEVINS(pDevIns);
3866 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3867 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
3868 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
3869
3870 /*
3871 * Validate input.
3872 */
3873 if (pFwReg->u32Version != PDM_FWREG_VERSION)
3874 {
3875 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
3876 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
3877 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3878 return VERR_INVALID_PARAMETER;
3879 }
3880 if (!pFwReg->pfnIsHardReset)
3881 {
3882 Assert(pFwReg->pfnIsHardReset);
3883 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3884 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3885 return VERR_INVALID_PARAMETER;
3886 }
3887
3888 if (!ppFwHlp)
3889 {
3890 Assert(ppFwHlp);
3891 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
3892 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3893 return VERR_INVALID_PARAMETER;
3894 }
3895
3896 /*
3897 * Only one DMA device.
3898 */
3899 PVM pVM = pDevIns->Internal.s.pVMR3;
3900 if (pVM->pdm.s.pFirmware)
3901 {
3902 AssertMsgFailed(("Only one firmware device is supported!\n"));
3903 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3904 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3905 return VERR_INVALID_PARAMETER;
3906 }
3907
3908 /*
3909 * Allocate and initialize pci bus structure.
3910 */
3911 int rc = VINF_SUCCESS;
3912 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
3913 if (pFirmware)
3914 {
3915 pFirmware->pDevIns = pDevIns;
3916 pFirmware->Reg = *pFwReg;
3917 pVM->pdm.s.pFirmware = pFirmware;
3918
3919 /* set the helper pointer. */
3920 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
3921 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
3922 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3923 }
3924 else
3925 rc = VERR_NO_MEMORY;
3926
3927 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3928 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3929 return rc;
3930}
3931
3932
3933/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3934static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
3935{
3936 PDMDEV_ASSERT_DEVINS(pDevIns);
3937 PVM pVM = pDevIns->Internal.s.pVMR3;
3938 VM_ASSERT_EMT(pVM);
3939 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
3940 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
3941
3942 /*
3943 * We postpone this operation because we're likely to be inside a I/O instruction
3944 * and the EIP will be updated when we return.
3945 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3946 */
3947 bool fHaltOnReset;
3948 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3949 if (RT_SUCCESS(rc) && fHaltOnReset)
3950 {
3951 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3952 rc = VINF_EM_HALT;
3953 }
3954 else
3955 {
3956 pVM->pdm.s.fResetFlags = fFlags;
3957 VM_FF_SET(pVM, VM_FF_RESET);
3958 rc = VINF_EM_RESET;
3959 }
3960
3961 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3962 return rc;
3963}
3964
3965
3966/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3967static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3968{
3969 int rc;
3970 PDMDEV_ASSERT_DEVINS(pDevIns);
3971 PVM pVM = pDevIns->Internal.s.pVMR3;
3972 VM_ASSERT_EMT(pVM);
3973 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3974 pDevIns->pReg->szName, pDevIns->iInstance));
3975
3976 /** @todo Always take the SMP path - fewer code paths. */
3977 if (pVM->cCpus > 1)
3978 {
3979 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3980 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
3981 AssertRC(rc);
3982 rc = VINF_EM_SUSPEND;
3983 }
3984 else
3985 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3986
3987 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3988 return rc;
3989}
3990
3991
3992/**
3993 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
3994 * EMT request to avoid deadlocks.
3995 *
3996 * @returns VBox status code fit for scheduling.
3997 * @param pVM The cross context VM structure.
3998 * @param pDevIns The device that triggered this action.
3999 */
4000static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
4001{
4002 /*
4003 * Suspend the VM first then do the saving.
4004 */
4005 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
4006 if (RT_SUCCESS(rc))
4007 {
4008 PUVM pUVM = pVM->pUVM;
4009 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
4010
4011 /*
4012 * On success, power off the VM, on failure we'll leave it suspended.
4013 */
4014 if (RT_SUCCESS(rc))
4015 {
4016 rc = VMR3PowerOff(pVM->pUVM);
4017 if (RT_FAILURE(rc))
4018 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
4019 }
4020 else
4021 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
4022 }
4023 else
4024 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
4025 return rc;
4026}
4027
4028
4029/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4030static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4031{
4032 PDMDEV_ASSERT_DEVINS(pDevIns);
4033 PVM pVM = pDevIns->Internal.s.pVMR3;
4034 VM_ASSERT_EMT(pVM);
4035 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
4036 pDevIns->pReg->szName, pDevIns->iInstance));
4037
4038 int rc;
4039 if ( pVM->pUVM->pVmm2UserMethods
4040 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
4041 {
4042 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
4043 if (RT_SUCCESS(rc))
4044 {
4045 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
4046 rc = VINF_EM_SUSPEND;
4047 }
4048 }
4049 else
4050 rc = VERR_NOT_SUPPORTED;
4051
4052 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4053 return rc;
4054}
4055
4056
4057/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4058static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
4059{
4060 int rc;
4061 PDMDEV_ASSERT_DEVINS(pDevIns);
4062 PVM pVM = pDevIns->Internal.s.pVMR3;
4063 VM_ASSERT_EMT(pVM);
4064 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
4065 pDevIns->pReg->szName, pDevIns->iInstance));
4066
4067 /** @todo Always take the SMP path - fewer code paths. */
4068 if (pVM->cCpus > 1)
4069 {
4070 /* We might be holding locks here and could cause a deadlock since
4071 VMR3PowerOff rendezvous with the other CPUs. */
4072 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
4073 AssertRC(rc);
4074 /* Set the VCPU state to stopped here as well to make sure no
4075 inconsistency with the EM state occurs. */
4076 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
4077 rc = VINF_EM_OFF;
4078 }
4079 else
4080 rc = VMR3PowerOff(pVM->pUVM);
4081
4082 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4083 return rc;
4084}
4085
4086
4087/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4088static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
4089{
4090 PDMDEV_ASSERT_DEVINS(pDevIns);
4091 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4092
4093 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
4094
4095 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
4096 return fRc;
4097}
4098
4099
4100/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4101static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4102{
4103 PDMDEV_ASSERT_DEVINS(pDevIns);
4104 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4105 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
4106 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
4107}
4108
4109
4110/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4111static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4112 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4113{
4114 PDMDEV_ASSERT_DEVINS(pDevIns);
4115 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4116
4117 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
4118 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
4119 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
4120
4121 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
4122
4123 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
4124 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
4125}
4126
4127
4128/**
4129 * The device helper structure for trusted devices.
4130 */
4131const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
4132{
4133 PDM_DEVHLPR3_VERSION,
4134 pdmR3DevHlp_IoPortCreateEx,
4135 pdmR3DevHlp_IoPortMap,
4136 pdmR3DevHlp_IoPortUnmap,
4137 pdmR3DevHlp_IoPortGetMappingAddress,
4138 pdmR3DevHlp_MmioCreateEx,
4139 pdmR3DevHlp_MmioMap,
4140 pdmR3DevHlp_MmioUnmap,
4141 pdmR3DevHlp_MmioReduce,
4142 pdmR3DevHlp_MmioGetMappingAddress,
4143 pdmR3DevHlp_Mmio2Create,
4144 pdmR3DevHlp_Mmio2Destroy,
4145 pdmR3DevHlp_Mmio2Map,
4146 pdmR3DevHlp_Mmio2Unmap,
4147 pdmR3DevHlp_Mmio2Reduce,
4148 pdmR3DevHlp_Mmio2GetMappingAddress,
4149 pdmR3DevHlp_Mmio2ChangeRegionNo,
4150 pdmR3DevHlp_ROMRegister,
4151 pdmR3DevHlp_ROMProtectShadow,
4152 pdmR3DevHlp_SSMRegister,
4153 SSMR3PutStruct,
4154 SSMR3PutStructEx,
4155 SSMR3PutBool,
4156 SSMR3PutU8,
4157 SSMR3PutS8,
4158 SSMR3PutU16,
4159 SSMR3PutS16,
4160 SSMR3PutU32,
4161 SSMR3PutS32,
4162 SSMR3PutU64,
4163 SSMR3PutS64,
4164 SSMR3PutU128,
4165 SSMR3PutS128,
4166 SSMR3PutUInt,
4167 SSMR3PutSInt,
4168 SSMR3PutGCUInt,
4169 SSMR3PutGCUIntReg,
4170 SSMR3PutGCPhys32,
4171 SSMR3PutGCPhys64,
4172 SSMR3PutGCPhys,
4173 SSMR3PutGCPtr,
4174 SSMR3PutGCUIntPtr,
4175 SSMR3PutRCPtr,
4176 SSMR3PutIOPort,
4177 SSMR3PutSel,
4178 SSMR3PutMem,
4179 SSMR3PutStrZ,
4180 SSMR3GetStruct,
4181 SSMR3GetStructEx,
4182 SSMR3GetBool,
4183 SSMR3GetBoolV,
4184 SSMR3GetU8,
4185 SSMR3GetU8V,
4186 SSMR3GetS8,
4187 SSMR3GetS8V,
4188 SSMR3GetU16,
4189 SSMR3GetU16V,
4190 SSMR3GetS16,
4191 SSMR3GetS16V,
4192 SSMR3GetU32,
4193 SSMR3GetU32V,
4194 SSMR3GetS32,
4195 SSMR3GetS32V,
4196 SSMR3GetU64,
4197 SSMR3GetU64V,
4198 SSMR3GetS64,
4199 SSMR3GetS64V,
4200 SSMR3GetU128,
4201 SSMR3GetU128V,
4202 SSMR3GetS128,
4203 SSMR3GetS128V,
4204 SSMR3GetGCPhys32,
4205 SSMR3GetGCPhys32V,
4206 SSMR3GetGCPhys64,
4207 SSMR3GetGCPhys64V,
4208 SSMR3GetGCPhys,
4209 SSMR3GetGCPhysV,
4210 SSMR3GetUInt,
4211 SSMR3GetSInt,
4212 SSMR3GetGCUInt,
4213 SSMR3GetGCUIntReg,
4214 SSMR3GetGCPtr,
4215 SSMR3GetGCUIntPtr,
4216 SSMR3GetRCPtr,
4217 SSMR3GetIOPort,
4218 SSMR3GetSel,
4219 SSMR3GetMem,
4220 SSMR3GetStrZ,
4221 SSMR3GetStrZEx,
4222 SSMR3Skip,
4223 SSMR3SkipToEndOfUnit,
4224 SSMR3SetLoadError,
4225 SSMR3SetLoadErrorV,
4226 SSMR3SetCfgError,
4227 SSMR3SetCfgErrorV,
4228 SSMR3HandleGetStatus,
4229 SSMR3HandleGetAfter,
4230 SSMR3HandleIsLiveSave,
4231 SSMR3HandleMaxDowntime,
4232 SSMR3HandleHostBits,
4233 SSMR3HandleRevision,
4234 SSMR3HandleVersion,
4235 SSMR3HandleHostOSAndArch,
4236 pdmR3DevHlp_TimerCreate,
4237 pdmR3DevHlp_TimerFromMicro,
4238 pdmR3DevHlp_TimerFromMilli,
4239 pdmR3DevHlp_TimerFromNano,
4240 pdmR3DevHlp_TimerGet,
4241 pdmR3DevHlp_TimerGetFreq,
4242 pdmR3DevHlp_TimerGetNano,
4243 pdmR3DevHlp_TimerIsActive,
4244 pdmR3DevHlp_TimerIsLockOwner,
4245 pdmR3DevHlp_TimerLockClock,
4246 pdmR3DevHlp_TimerLockClock2,
4247 pdmR3DevHlp_TimerSet,
4248 pdmR3DevHlp_TimerSetFrequencyHint,
4249 pdmR3DevHlp_TimerSetMicro,
4250 pdmR3DevHlp_TimerSetMillies,
4251 pdmR3DevHlp_TimerSetNano,
4252 pdmR3DevHlp_TimerSetRelative,
4253 pdmR3DevHlp_TimerStop,
4254 pdmR3DevHlp_TimerUnlockClock,
4255 pdmR3DevHlp_TimerUnlockClock2,
4256 pdmR3DevHlp_TimerSetCritSect,
4257 pdmR3DevHlp_TimerSave,
4258 pdmR3DevHlp_TimerLoad,
4259 pdmR3DevHlp_TimerDestroy,
4260 TMR3TimerSkip,
4261 pdmR3DevHlp_TMUtcNow,
4262 CFGMR3Exists,
4263 CFGMR3QueryType,
4264 CFGMR3QuerySize,
4265 CFGMR3QueryInteger,
4266 CFGMR3QueryIntegerDef,
4267 CFGMR3QueryString,
4268 CFGMR3QueryStringDef,
4269 CFGMR3QueryBytes,
4270 CFGMR3QueryU64,
4271 CFGMR3QueryU64Def,
4272 CFGMR3QueryS64,
4273 CFGMR3QueryS64Def,
4274 CFGMR3QueryU32,
4275 CFGMR3QueryU32Def,
4276 CFGMR3QueryS32,
4277 CFGMR3QueryS32Def,
4278 CFGMR3QueryU16,
4279 CFGMR3QueryU16Def,
4280 CFGMR3QueryS16,
4281 CFGMR3QueryS16Def,
4282 CFGMR3QueryU8,
4283 CFGMR3QueryU8Def,
4284 CFGMR3QueryS8,
4285 CFGMR3QueryS8Def,
4286 CFGMR3QueryBool,
4287 CFGMR3QueryBoolDef,
4288 CFGMR3QueryPort,
4289 CFGMR3QueryPortDef,
4290 CFGMR3QueryUInt,
4291 CFGMR3QueryUIntDef,
4292 CFGMR3QuerySInt,
4293 CFGMR3QuerySIntDef,
4294 CFGMR3QueryPtr,
4295 CFGMR3QueryPtrDef,
4296 CFGMR3QueryGCPtr,
4297 CFGMR3QueryGCPtrDef,
4298 CFGMR3QueryGCPtrU,
4299 CFGMR3QueryGCPtrUDef,
4300 CFGMR3QueryGCPtrS,
4301 CFGMR3QueryGCPtrSDef,
4302 CFGMR3QueryStringAlloc,
4303 CFGMR3QueryStringAllocDef,
4304 CFGMR3GetParent,
4305 CFGMR3GetChild,
4306 CFGMR3GetChildF,
4307 CFGMR3GetChildFV,
4308 CFGMR3GetFirstChild,
4309 CFGMR3GetNextChild,
4310 CFGMR3GetName,
4311 CFGMR3GetNameLen,
4312 CFGMR3AreChildrenValid,
4313 CFGMR3GetFirstValue,
4314 CFGMR3GetNextValue,
4315 CFGMR3GetValueName,
4316 CFGMR3GetValueNameLen,
4317 CFGMR3GetValueType,
4318 CFGMR3AreValuesValid,
4319 CFGMR3ValidateConfig,
4320 pdmR3DevHlp_PhysRead,
4321 pdmR3DevHlp_PhysWrite,
4322 pdmR3DevHlp_PhysGCPhys2CCPtr,
4323 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4324 pdmR3DevHlp_PhysReleasePageMappingLock,
4325 pdmR3DevHlp_PhysReadGCVirt,
4326 pdmR3DevHlp_PhysWriteGCVirt,
4327 pdmR3DevHlp_PhysGCPtr2GCPhys,
4328 pdmR3DevHlp_MMHeapAlloc,
4329 pdmR3DevHlp_MMHeapAllocZ,
4330 pdmR3DevHlp_MMHeapFree,
4331 pdmR3DevHlp_VMState,
4332 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4333 pdmR3DevHlp_VMSetError,
4334 pdmR3DevHlp_VMSetErrorV,
4335 pdmR3DevHlp_VMSetRuntimeError,
4336 pdmR3DevHlp_VMSetRuntimeErrorV,
4337 pdmR3DevHlp_DBGFStopV,
4338 pdmR3DevHlp_DBGFInfoRegister,
4339 pdmR3DevHlp_DBGFInfoRegisterArgv,
4340 pdmR3DevHlp_DBGFRegRegister,
4341 pdmR3DevHlp_DBGFTraceBuf,
4342 pdmR3DevHlp_STAMRegister,
4343 pdmR3DevHlp_STAMRegisterV,
4344 pdmR3DevHlp_PCIRegister,
4345 pdmR3DevHlp_PCIRegisterMsi,
4346 pdmR3DevHlp_PCIIORegionRegister,
4347 pdmR3DevHlp_PCIInterceptConfigAccesses,
4348 pdmR3DevHlp_PCIConfigWrite,
4349 pdmR3DevHlp_PCIConfigRead,
4350 pdmR3DevHlp_PCIPhysRead,
4351 pdmR3DevHlp_PCIPhysWrite,
4352 pdmR3DevHlp_PCIPhysGCPhys2CCPtr,
4353 pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly,
4354 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr,
4355 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly,
4356 pdmR3DevHlp_PCISetIrq,
4357 pdmR3DevHlp_PCISetIrqNoWait,
4358 pdmR3DevHlp_ISASetIrq,
4359 pdmR3DevHlp_ISASetIrqNoWait,
4360 pdmR3DevHlp_DriverAttach,
4361 pdmR3DevHlp_DriverDetach,
4362 pdmR3DevHlp_DriverReconfigure,
4363 pdmR3DevHlp_QueueCreatePtr,
4364 pdmR3DevHlp_QueueCreate,
4365 pdmR3DevHlp_QueueToPtr,
4366 pdmR3DevHlp_QueueAlloc,
4367 pdmR3DevHlp_QueueInsert,
4368 pdmR3DevHlp_QueueInsertEx,
4369 pdmR3DevHlp_QueueFlushIfNecessary,
4370 pdmR3DevHlp_TaskCreate,
4371 pdmR3DevHlp_TaskTrigger,
4372 pdmR3DevHlp_SUPSemEventCreate,
4373 pdmR3DevHlp_SUPSemEventClose,
4374 pdmR3DevHlp_SUPSemEventSignal,
4375 pdmR3DevHlp_SUPSemEventWaitNoResume,
4376 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4377 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4378 pdmR3DevHlp_SUPSemEventGetResolution,
4379 pdmR3DevHlp_SUPSemEventMultiCreate,
4380 pdmR3DevHlp_SUPSemEventMultiClose,
4381 pdmR3DevHlp_SUPSemEventMultiSignal,
4382 pdmR3DevHlp_SUPSemEventMultiReset,
4383 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4384 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4385 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4386 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4387 pdmR3DevHlp_CritSectInit,
4388 pdmR3DevHlp_CritSectGetNop,
4389 pdmR3DevHlp_CritSectGetNopR0,
4390 pdmR3DevHlp_CritSectGetNopRC,
4391 pdmR3DevHlp_SetDeviceCritSect,
4392 pdmR3DevHlp_CritSectYield,
4393 pdmR3DevHlp_CritSectEnter,
4394 pdmR3DevHlp_CritSectEnterDebug,
4395 pdmR3DevHlp_CritSectTryEnter,
4396 pdmR3DevHlp_CritSectTryEnterDebug,
4397 pdmR3DevHlp_CritSectLeave,
4398 pdmR3DevHlp_CritSectIsOwner,
4399 pdmR3DevHlp_CritSectIsInitialized,
4400 pdmR3DevHlp_CritSectHasWaiters,
4401 pdmR3DevHlp_CritSectGetRecursion,
4402 pdmR3DevHlp_CritSectScheduleExitEvent,
4403 pdmR3DevHlp_CritSectDelete,
4404 pdmR3DevHlp_ThreadCreate,
4405 PDMR3ThreadDestroy,
4406 PDMR3ThreadIAmSuspending,
4407 PDMR3ThreadIAmRunning,
4408 PDMR3ThreadSleep,
4409 PDMR3ThreadSuspend,
4410 PDMR3ThreadResume,
4411 pdmR3DevHlp_SetAsyncNotification,
4412 pdmR3DevHlp_AsyncNotificationCompleted,
4413 pdmR3DevHlp_RTCRegister,
4414 pdmR3DevHlp_PCIBusRegister,
4415 pdmR3DevHlp_IommuRegister,
4416 pdmR3DevHlp_PICRegister,
4417 pdmR3DevHlp_ApicRegister,
4418 pdmR3DevHlp_IoApicRegister,
4419 pdmR3DevHlp_HpetRegister,
4420 pdmR3DevHlp_PciRawRegister,
4421 pdmR3DevHlp_DMACRegister,
4422 pdmR3DevHlp_DMARegister,
4423 pdmR3DevHlp_DMAReadMemory,
4424 pdmR3DevHlp_DMAWriteMemory,
4425 pdmR3DevHlp_DMASetDREQ,
4426 pdmR3DevHlp_DMAGetChannelMode,
4427 pdmR3DevHlp_DMASchedule,
4428 pdmR3DevHlp_CMOSWrite,
4429 pdmR3DevHlp_CMOSRead,
4430 pdmR3DevHlp_AssertEMT,
4431 pdmR3DevHlp_AssertOther,
4432 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4433 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4434 pdmR3DevHlp_CallR0,
4435 pdmR3DevHlp_VMGetSuspendReason,
4436 pdmR3DevHlp_VMGetResumeReason,
4437 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4438 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4439 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4440 pdmR3DevHlp_CpuGetGuestMicroarch,
4441 pdmR3DevHlp_CpuGetGuestAddrWidths,
4442 pdmR3DevHlp_STAMDeregisterByPrefix,
4443 0,
4444 0,
4445 0,
4446 0,
4447 0,
4448 0,
4449 0,
4450 0,
4451 0,
4452 pdmR3DevHlp_GetUVM,
4453 pdmR3DevHlp_GetVM,
4454 pdmR3DevHlp_GetVMCPU,
4455 pdmR3DevHlp_GetCurrentCpuId,
4456 pdmR3DevHlp_RegisterVMMDevHeap,
4457 pdmR3DevHlp_FirmwareRegister,
4458 pdmR3DevHlp_VMReset,
4459 pdmR3DevHlp_VMSuspend,
4460 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4461 pdmR3DevHlp_VMPowerOff,
4462 pdmR3DevHlp_A20IsEnabled,
4463 pdmR3DevHlp_A20Set,
4464 pdmR3DevHlp_GetCpuId,
4465 pdmR3DevHlp_TMTimeVirtGet,
4466 pdmR3DevHlp_TMTimeVirtGetFreq,
4467 pdmR3DevHlp_TMTimeVirtGetNano,
4468 pdmR3DevHlp_GetSupDrvSession,
4469 pdmR3DevHlp_QueryGenericUserObject,
4470 pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
4471 PDM_DEVHLPR3_VERSION /* the end */
4472};
4473
4474
4475#ifdef VBOX_WITH_DBGF_TRACING
4476/**
4477 * The device helper structure for trusted devices - tracing variant.
4478 */
4479const PDMDEVHLPR3 g_pdmR3DevHlpTracing =
4480{
4481 PDM_DEVHLPR3_VERSION,
4482 pdmR3DevHlpTracing_IoPortCreateEx,
4483 pdmR3DevHlpTracing_IoPortMap,
4484 pdmR3DevHlpTracing_IoPortUnmap,
4485 pdmR3DevHlp_IoPortGetMappingAddress,
4486 pdmR3DevHlpTracing_MmioCreateEx,
4487 pdmR3DevHlpTracing_MmioMap,
4488 pdmR3DevHlpTracing_MmioUnmap,
4489 pdmR3DevHlp_MmioReduce,
4490 pdmR3DevHlp_MmioGetMappingAddress,
4491 pdmR3DevHlp_Mmio2Create,
4492 pdmR3DevHlp_Mmio2Destroy,
4493 pdmR3DevHlp_Mmio2Map,
4494 pdmR3DevHlp_Mmio2Unmap,
4495 pdmR3DevHlp_Mmio2Reduce,
4496 pdmR3DevHlp_Mmio2GetMappingAddress,
4497 pdmR3DevHlp_Mmio2ChangeRegionNo,
4498 pdmR3DevHlp_ROMRegister,
4499 pdmR3DevHlp_ROMProtectShadow,
4500 pdmR3DevHlp_SSMRegister,
4501 SSMR3PutStruct,
4502 SSMR3PutStructEx,
4503 SSMR3PutBool,
4504 SSMR3PutU8,
4505 SSMR3PutS8,
4506 SSMR3PutU16,
4507 SSMR3PutS16,
4508 SSMR3PutU32,
4509 SSMR3PutS32,
4510 SSMR3PutU64,
4511 SSMR3PutS64,
4512 SSMR3PutU128,
4513 SSMR3PutS128,
4514 SSMR3PutUInt,
4515 SSMR3PutSInt,
4516 SSMR3PutGCUInt,
4517 SSMR3PutGCUIntReg,
4518 SSMR3PutGCPhys32,
4519 SSMR3PutGCPhys64,
4520 SSMR3PutGCPhys,
4521 SSMR3PutGCPtr,
4522 SSMR3PutGCUIntPtr,
4523 SSMR3PutRCPtr,
4524 SSMR3PutIOPort,
4525 SSMR3PutSel,
4526 SSMR3PutMem,
4527 SSMR3PutStrZ,
4528 SSMR3GetStruct,
4529 SSMR3GetStructEx,
4530 SSMR3GetBool,
4531 SSMR3GetBoolV,
4532 SSMR3GetU8,
4533 SSMR3GetU8V,
4534 SSMR3GetS8,
4535 SSMR3GetS8V,
4536 SSMR3GetU16,
4537 SSMR3GetU16V,
4538 SSMR3GetS16,
4539 SSMR3GetS16V,
4540 SSMR3GetU32,
4541 SSMR3GetU32V,
4542 SSMR3GetS32,
4543 SSMR3GetS32V,
4544 SSMR3GetU64,
4545 SSMR3GetU64V,
4546 SSMR3GetS64,
4547 SSMR3GetS64V,
4548 SSMR3GetU128,
4549 SSMR3GetU128V,
4550 SSMR3GetS128,
4551 SSMR3GetS128V,
4552 SSMR3GetGCPhys32,
4553 SSMR3GetGCPhys32V,
4554 SSMR3GetGCPhys64,
4555 SSMR3GetGCPhys64V,
4556 SSMR3GetGCPhys,
4557 SSMR3GetGCPhysV,
4558 SSMR3GetUInt,
4559 SSMR3GetSInt,
4560 SSMR3GetGCUInt,
4561 SSMR3GetGCUIntReg,
4562 SSMR3GetGCPtr,
4563 SSMR3GetGCUIntPtr,
4564 SSMR3GetRCPtr,
4565 SSMR3GetIOPort,
4566 SSMR3GetSel,
4567 SSMR3GetMem,
4568 SSMR3GetStrZ,
4569 SSMR3GetStrZEx,
4570 SSMR3Skip,
4571 SSMR3SkipToEndOfUnit,
4572 SSMR3SetLoadError,
4573 SSMR3SetLoadErrorV,
4574 SSMR3SetCfgError,
4575 SSMR3SetCfgErrorV,
4576 SSMR3HandleGetStatus,
4577 SSMR3HandleGetAfter,
4578 SSMR3HandleIsLiveSave,
4579 SSMR3HandleMaxDowntime,
4580 SSMR3HandleHostBits,
4581 SSMR3HandleRevision,
4582 SSMR3HandleVersion,
4583 SSMR3HandleHostOSAndArch,
4584 pdmR3DevHlp_TimerCreate,
4585 pdmR3DevHlp_TimerFromMicro,
4586 pdmR3DevHlp_TimerFromMilli,
4587 pdmR3DevHlp_TimerFromNano,
4588 pdmR3DevHlp_TimerGet,
4589 pdmR3DevHlp_TimerGetFreq,
4590 pdmR3DevHlp_TimerGetNano,
4591 pdmR3DevHlp_TimerIsActive,
4592 pdmR3DevHlp_TimerIsLockOwner,
4593 pdmR3DevHlp_TimerLockClock,
4594 pdmR3DevHlp_TimerLockClock2,
4595 pdmR3DevHlp_TimerSet,
4596 pdmR3DevHlp_TimerSetFrequencyHint,
4597 pdmR3DevHlp_TimerSetMicro,
4598 pdmR3DevHlp_TimerSetMillies,
4599 pdmR3DevHlp_TimerSetNano,
4600 pdmR3DevHlp_TimerSetRelative,
4601 pdmR3DevHlp_TimerStop,
4602 pdmR3DevHlp_TimerUnlockClock,
4603 pdmR3DevHlp_TimerUnlockClock2,
4604 pdmR3DevHlp_TimerSetCritSect,
4605 pdmR3DevHlp_TimerSave,
4606 pdmR3DevHlp_TimerLoad,
4607 pdmR3DevHlp_TimerDestroy,
4608 TMR3TimerSkip,
4609 pdmR3DevHlp_TMUtcNow,
4610 CFGMR3Exists,
4611 CFGMR3QueryType,
4612 CFGMR3QuerySize,
4613 CFGMR3QueryInteger,
4614 CFGMR3QueryIntegerDef,
4615 CFGMR3QueryString,
4616 CFGMR3QueryStringDef,
4617 CFGMR3QueryBytes,
4618 CFGMR3QueryU64,
4619 CFGMR3QueryU64Def,
4620 CFGMR3QueryS64,
4621 CFGMR3QueryS64Def,
4622 CFGMR3QueryU32,
4623 CFGMR3QueryU32Def,
4624 CFGMR3QueryS32,
4625 CFGMR3QueryS32Def,
4626 CFGMR3QueryU16,
4627 CFGMR3QueryU16Def,
4628 CFGMR3QueryS16,
4629 CFGMR3QueryS16Def,
4630 CFGMR3QueryU8,
4631 CFGMR3QueryU8Def,
4632 CFGMR3QueryS8,
4633 CFGMR3QueryS8Def,
4634 CFGMR3QueryBool,
4635 CFGMR3QueryBoolDef,
4636 CFGMR3QueryPort,
4637 CFGMR3QueryPortDef,
4638 CFGMR3QueryUInt,
4639 CFGMR3QueryUIntDef,
4640 CFGMR3QuerySInt,
4641 CFGMR3QuerySIntDef,
4642 CFGMR3QueryPtr,
4643 CFGMR3QueryPtrDef,
4644 CFGMR3QueryGCPtr,
4645 CFGMR3QueryGCPtrDef,
4646 CFGMR3QueryGCPtrU,
4647 CFGMR3QueryGCPtrUDef,
4648 CFGMR3QueryGCPtrS,
4649 CFGMR3QueryGCPtrSDef,
4650 CFGMR3QueryStringAlloc,
4651 CFGMR3QueryStringAllocDef,
4652 CFGMR3GetParent,
4653 CFGMR3GetChild,
4654 CFGMR3GetChildF,
4655 CFGMR3GetChildFV,
4656 CFGMR3GetFirstChild,
4657 CFGMR3GetNextChild,
4658 CFGMR3GetName,
4659 CFGMR3GetNameLen,
4660 CFGMR3AreChildrenValid,
4661 CFGMR3GetFirstValue,
4662 CFGMR3GetNextValue,
4663 CFGMR3GetValueName,
4664 CFGMR3GetValueNameLen,
4665 CFGMR3GetValueType,
4666 CFGMR3AreValuesValid,
4667 CFGMR3ValidateConfig,
4668 pdmR3DevHlpTracing_PhysRead,
4669 pdmR3DevHlpTracing_PhysWrite,
4670 pdmR3DevHlp_PhysGCPhys2CCPtr,
4671 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4672 pdmR3DevHlp_PhysReleasePageMappingLock,
4673 pdmR3DevHlp_PhysReadGCVirt,
4674 pdmR3DevHlp_PhysWriteGCVirt,
4675 pdmR3DevHlp_PhysGCPtr2GCPhys,
4676 pdmR3DevHlp_MMHeapAlloc,
4677 pdmR3DevHlp_MMHeapAllocZ,
4678 pdmR3DevHlp_MMHeapFree,
4679 pdmR3DevHlp_VMState,
4680 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4681 pdmR3DevHlp_VMSetError,
4682 pdmR3DevHlp_VMSetErrorV,
4683 pdmR3DevHlp_VMSetRuntimeError,
4684 pdmR3DevHlp_VMSetRuntimeErrorV,
4685 pdmR3DevHlp_DBGFStopV,
4686 pdmR3DevHlp_DBGFInfoRegister,
4687 pdmR3DevHlp_DBGFInfoRegisterArgv,
4688 pdmR3DevHlp_DBGFRegRegister,
4689 pdmR3DevHlp_DBGFTraceBuf,
4690 pdmR3DevHlp_STAMRegister,
4691 pdmR3DevHlp_STAMRegisterV,
4692 pdmR3DevHlp_PCIRegister,
4693 pdmR3DevHlp_PCIRegisterMsi,
4694 pdmR3DevHlp_PCIIORegionRegister,
4695 pdmR3DevHlp_PCIInterceptConfigAccesses,
4696 pdmR3DevHlp_PCIConfigWrite,
4697 pdmR3DevHlp_PCIConfigRead,
4698 pdmR3DevHlpTracing_PCIPhysRead,
4699 pdmR3DevHlpTracing_PCIPhysWrite,
4700 pdmR3DevHlp_PCIPhysGCPhys2CCPtr,
4701 pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly,
4702 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr,
4703 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly,
4704 pdmR3DevHlpTracing_PCISetIrq,
4705 pdmR3DevHlpTracing_PCISetIrqNoWait,
4706 pdmR3DevHlpTracing_ISASetIrq,
4707 pdmR3DevHlpTracing_ISASetIrqNoWait,
4708 pdmR3DevHlp_DriverAttach,
4709 pdmR3DevHlp_DriverDetach,
4710 pdmR3DevHlp_DriverReconfigure,
4711 pdmR3DevHlp_QueueCreatePtr,
4712 pdmR3DevHlp_QueueCreate,
4713 pdmR3DevHlp_QueueToPtr,
4714 pdmR3DevHlp_QueueAlloc,
4715 pdmR3DevHlp_QueueInsert,
4716 pdmR3DevHlp_QueueInsertEx,
4717 pdmR3DevHlp_QueueFlushIfNecessary,
4718 pdmR3DevHlp_TaskCreate,
4719 pdmR3DevHlp_TaskTrigger,
4720 pdmR3DevHlp_SUPSemEventCreate,
4721 pdmR3DevHlp_SUPSemEventClose,
4722 pdmR3DevHlp_SUPSemEventSignal,
4723 pdmR3DevHlp_SUPSemEventWaitNoResume,
4724 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4725 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4726 pdmR3DevHlp_SUPSemEventGetResolution,
4727 pdmR3DevHlp_SUPSemEventMultiCreate,
4728 pdmR3DevHlp_SUPSemEventMultiClose,
4729 pdmR3DevHlp_SUPSemEventMultiSignal,
4730 pdmR3DevHlp_SUPSemEventMultiReset,
4731 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4732 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4733 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4734 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4735 pdmR3DevHlp_CritSectInit,
4736 pdmR3DevHlp_CritSectGetNop,
4737 pdmR3DevHlp_CritSectGetNopR0,
4738 pdmR3DevHlp_CritSectGetNopRC,
4739 pdmR3DevHlp_SetDeviceCritSect,
4740 pdmR3DevHlp_CritSectYield,
4741 pdmR3DevHlp_CritSectEnter,
4742 pdmR3DevHlp_CritSectEnterDebug,
4743 pdmR3DevHlp_CritSectTryEnter,
4744 pdmR3DevHlp_CritSectTryEnterDebug,
4745 pdmR3DevHlp_CritSectLeave,
4746 pdmR3DevHlp_CritSectIsOwner,
4747 pdmR3DevHlp_CritSectIsInitialized,
4748 pdmR3DevHlp_CritSectHasWaiters,
4749 pdmR3DevHlp_CritSectGetRecursion,
4750 pdmR3DevHlp_CritSectScheduleExitEvent,
4751 pdmR3DevHlp_CritSectDelete,
4752 pdmR3DevHlp_ThreadCreate,
4753 PDMR3ThreadDestroy,
4754 PDMR3ThreadIAmSuspending,
4755 PDMR3ThreadIAmRunning,
4756 PDMR3ThreadSleep,
4757 PDMR3ThreadSuspend,
4758 PDMR3ThreadResume,
4759 pdmR3DevHlp_SetAsyncNotification,
4760 pdmR3DevHlp_AsyncNotificationCompleted,
4761 pdmR3DevHlp_RTCRegister,
4762 pdmR3DevHlp_PCIBusRegister,
4763 pdmR3DevHlp_IommuRegister,
4764 pdmR3DevHlp_PICRegister,
4765 pdmR3DevHlp_ApicRegister,
4766 pdmR3DevHlp_IoApicRegister,
4767 pdmR3DevHlp_HpetRegister,
4768 pdmR3DevHlp_PciRawRegister,
4769 pdmR3DevHlp_DMACRegister,
4770 pdmR3DevHlp_DMARegister,
4771 pdmR3DevHlp_DMAReadMemory,
4772 pdmR3DevHlp_DMAWriteMemory,
4773 pdmR3DevHlp_DMASetDREQ,
4774 pdmR3DevHlp_DMAGetChannelMode,
4775 pdmR3DevHlp_DMASchedule,
4776 pdmR3DevHlp_CMOSWrite,
4777 pdmR3DevHlp_CMOSRead,
4778 pdmR3DevHlp_AssertEMT,
4779 pdmR3DevHlp_AssertOther,
4780 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4781 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4782 pdmR3DevHlp_CallR0,
4783 pdmR3DevHlp_VMGetSuspendReason,
4784 pdmR3DevHlp_VMGetResumeReason,
4785 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4786 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4787 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4788 pdmR3DevHlp_CpuGetGuestMicroarch,
4789 pdmR3DevHlp_CpuGetGuestAddrWidths,
4790 pdmR3DevHlp_STAMDeregisterByPrefix,
4791 0,
4792 0,
4793 0,
4794 0,
4795 0,
4796 0,
4797 0,
4798 0,
4799 0,
4800 pdmR3DevHlp_GetUVM,
4801 pdmR3DevHlp_GetVM,
4802 pdmR3DevHlp_GetVMCPU,
4803 pdmR3DevHlp_GetCurrentCpuId,
4804 pdmR3DevHlp_RegisterVMMDevHeap,
4805 pdmR3DevHlp_FirmwareRegister,
4806 pdmR3DevHlp_VMReset,
4807 pdmR3DevHlp_VMSuspend,
4808 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4809 pdmR3DevHlp_VMPowerOff,
4810 pdmR3DevHlp_A20IsEnabled,
4811 pdmR3DevHlp_A20Set,
4812 pdmR3DevHlp_GetCpuId,
4813 pdmR3DevHlp_TMTimeVirtGet,
4814 pdmR3DevHlp_TMTimeVirtGetFreq,
4815 pdmR3DevHlp_TMTimeVirtGetNano,
4816 pdmR3DevHlp_GetSupDrvSession,
4817 pdmR3DevHlp_QueryGenericUserObject,
4818 pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
4819 PDM_DEVHLPR3_VERSION /* the end */
4820};
4821#endif /* VBOX_WITH_DBGF_TRACING */
4822
4823
4824
4825
4826/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
4827static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
4828{
4829 PDMDEV_ASSERT_DEVINS(pDevIns);
4830 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4831 return NULL;
4832}
4833
4834
4835/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
4836static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
4837{
4838 PDMDEV_ASSERT_DEVINS(pDevIns);
4839 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4840 return NULL;
4841}
4842
4843
4844/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
4845static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
4846{
4847 PDMDEV_ASSERT_DEVINS(pDevIns);
4848 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4849 return NULL;
4850}
4851
4852
4853/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
4854static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(PPDMDEVINS pDevIns)
4855{
4856 PDMDEV_ASSERT_DEVINS(pDevIns);
4857 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4858 return NIL_VMCPUID;
4859}
4860
4861
4862/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
4863static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
4864 RTR3PTR pvHeap, unsigned cbHeap)
4865{
4866 PDMDEV_ASSERT_DEVINS(pDevIns);
4867 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
4868 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4869 return VERR_ACCESS_DENIED;
4870}
4871
4872
4873/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
4874static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4875{
4876 PDMDEV_ASSERT_DEVINS(pDevIns);
4877 NOREF(pFwReg); NOREF(ppFwHlp);
4878 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4879 return VERR_ACCESS_DENIED;
4880}
4881
4882
4883/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4884static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4885{
4886 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
4887 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4888 return VERR_ACCESS_DENIED;
4889}
4890
4891
4892/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4893static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
4894{
4895 PDMDEV_ASSERT_DEVINS(pDevIns);
4896 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4897 return VERR_ACCESS_DENIED;
4898}
4899
4900
4901/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4902static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4903{
4904 PDMDEV_ASSERT_DEVINS(pDevIns);
4905 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4906 return VERR_ACCESS_DENIED;
4907}
4908
4909
4910/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4911static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
4912{
4913 PDMDEV_ASSERT_DEVINS(pDevIns);
4914 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4915 return VERR_ACCESS_DENIED;
4916}
4917
4918
4919/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4920static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
4921{
4922 PDMDEV_ASSERT_DEVINS(pDevIns);
4923 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4924 return false;
4925}
4926
4927
4928/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4929static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4930{
4931 PDMDEV_ASSERT_DEVINS(pDevIns);
4932 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4933 NOREF(fEnable);
4934}
4935
4936
4937/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4938static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4939 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4940{
4941 PDMDEV_ASSERT_DEVINS(pDevIns);
4942 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
4943 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4944}
4945
4946
4947/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
4948static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(PPDMDEVINS pDevIns)
4949{
4950 PDMDEV_ASSERT_DEVINS(pDevIns);
4951 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4952 return (PSUPDRVSESSION)0;
4953}
4954
4955
4956/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
4957static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
4958{
4959 PDMDEV_ASSERT_DEVINS(pDevIns);
4960 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
4961 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
4962 return NULL;
4963}
4964
4965
4966/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalTypeRegister} */
4967static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
4968 R3PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR3,
4969 const char *pszHandlerR0, const char *pszPfHandlerR0,
4970 const char *pszHandlerRC, const char *pszPfHandlerRC,
4971 const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
4972{
4973 PDMDEV_ASSERT_DEVINS(pDevIns);
4974 RT_NOREF(enmKind, pfnHandlerR3, pszHandlerR0, pszPfHandlerR0, pszHandlerRC, pszPfHandlerRC, pszDesc, phType);
4975 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
4976 pDevIns->pReg->szName, pDevIns->iInstance));
4977 return VERR_ACCESS_DENIED;
4978}
4979
4980
4981/**
4982 * The device helper structure for non-trusted devices.
4983 */
4984const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
4985{
4986 PDM_DEVHLPR3_VERSION,
4987 pdmR3DevHlp_IoPortCreateEx,
4988 pdmR3DevHlp_IoPortMap,
4989 pdmR3DevHlp_IoPortUnmap,
4990 pdmR3DevHlp_IoPortGetMappingAddress,
4991 pdmR3DevHlp_MmioCreateEx,
4992 pdmR3DevHlp_MmioMap,
4993 pdmR3DevHlp_MmioUnmap,
4994 pdmR3DevHlp_MmioReduce,
4995 pdmR3DevHlp_MmioGetMappingAddress,
4996 pdmR3DevHlp_Mmio2Create,
4997 pdmR3DevHlp_Mmio2Destroy,
4998 pdmR3DevHlp_Mmio2Map,
4999 pdmR3DevHlp_Mmio2Unmap,
5000 pdmR3DevHlp_Mmio2Reduce,
5001 pdmR3DevHlp_Mmio2GetMappingAddress,
5002 pdmR3DevHlp_Mmio2ChangeRegionNo,
5003 pdmR3DevHlp_ROMRegister,
5004 pdmR3DevHlp_ROMProtectShadow,
5005 pdmR3DevHlp_SSMRegister,
5006 SSMR3PutStruct,
5007 SSMR3PutStructEx,
5008 SSMR3PutBool,
5009 SSMR3PutU8,
5010 SSMR3PutS8,
5011 SSMR3PutU16,
5012 SSMR3PutS16,
5013 SSMR3PutU32,
5014 SSMR3PutS32,
5015 SSMR3PutU64,
5016 SSMR3PutS64,
5017 SSMR3PutU128,
5018 SSMR3PutS128,
5019 SSMR3PutUInt,
5020 SSMR3PutSInt,
5021 SSMR3PutGCUInt,
5022 SSMR3PutGCUIntReg,
5023 SSMR3PutGCPhys32,
5024 SSMR3PutGCPhys64,
5025 SSMR3PutGCPhys,
5026 SSMR3PutGCPtr,
5027 SSMR3PutGCUIntPtr,
5028 SSMR3PutRCPtr,
5029 SSMR3PutIOPort,
5030 SSMR3PutSel,
5031 SSMR3PutMem,
5032 SSMR3PutStrZ,
5033 SSMR3GetStruct,
5034 SSMR3GetStructEx,
5035 SSMR3GetBool,
5036 SSMR3GetBoolV,
5037 SSMR3GetU8,
5038 SSMR3GetU8V,
5039 SSMR3GetS8,
5040 SSMR3GetS8V,
5041 SSMR3GetU16,
5042 SSMR3GetU16V,
5043 SSMR3GetS16,
5044 SSMR3GetS16V,
5045 SSMR3GetU32,
5046 SSMR3GetU32V,
5047 SSMR3GetS32,
5048 SSMR3GetS32V,
5049 SSMR3GetU64,
5050 SSMR3GetU64V,
5051 SSMR3GetS64,
5052 SSMR3GetS64V,
5053 SSMR3GetU128,
5054 SSMR3GetU128V,
5055 SSMR3GetS128,
5056 SSMR3GetS128V,
5057 SSMR3GetGCPhys32,
5058 SSMR3GetGCPhys32V,
5059 SSMR3GetGCPhys64,
5060 SSMR3GetGCPhys64V,
5061 SSMR3GetGCPhys,
5062 SSMR3GetGCPhysV,
5063 SSMR3GetUInt,
5064 SSMR3GetSInt,
5065 SSMR3GetGCUInt,
5066 SSMR3GetGCUIntReg,
5067 SSMR3GetGCPtr,
5068 SSMR3GetGCUIntPtr,
5069 SSMR3GetRCPtr,
5070 SSMR3GetIOPort,
5071 SSMR3GetSel,
5072 SSMR3GetMem,
5073 SSMR3GetStrZ,
5074 SSMR3GetStrZEx,
5075 SSMR3Skip,
5076 SSMR3SkipToEndOfUnit,
5077 SSMR3SetLoadError,
5078 SSMR3SetLoadErrorV,
5079 SSMR3SetCfgError,
5080 SSMR3SetCfgErrorV,
5081 SSMR3HandleGetStatus,
5082 SSMR3HandleGetAfter,
5083 SSMR3HandleIsLiveSave,
5084 SSMR3HandleMaxDowntime,
5085 SSMR3HandleHostBits,
5086 SSMR3HandleRevision,
5087 SSMR3HandleVersion,
5088 SSMR3HandleHostOSAndArch,
5089 pdmR3DevHlp_TimerCreate,
5090 pdmR3DevHlp_TimerFromMicro,
5091 pdmR3DevHlp_TimerFromMilli,
5092 pdmR3DevHlp_TimerFromNano,
5093 pdmR3DevHlp_TimerGet,
5094 pdmR3DevHlp_TimerGetFreq,
5095 pdmR3DevHlp_TimerGetNano,
5096 pdmR3DevHlp_TimerIsActive,
5097 pdmR3DevHlp_TimerIsLockOwner,
5098 pdmR3DevHlp_TimerLockClock,
5099 pdmR3DevHlp_TimerLockClock2,
5100 pdmR3DevHlp_TimerSet,
5101 pdmR3DevHlp_TimerSetFrequencyHint,
5102 pdmR3DevHlp_TimerSetMicro,
5103 pdmR3DevHlp_TimerSetMillies,
5104 pdmR3DevHlp_TimerSetNano,
5105 pdmR3DevHlp_TimerSetRelative,
5106 pdmR3DevHlp_TimerStop,
5107 pdmR3DevHlp_TimerUnlockClock,
5108 pdmR3DevHlp_TimerUnlockClock2,
5109 pdmR3DevHlp_TimerSetCritSect,
5110 pdmR3DevHlp_TimerSave,
5111 pdmR3DevHlp_TimerLoad,
5112 pdmR3DevHlp_TimerDestroy,
5113 TMR3TimerSkip,
5114 pdmR3DevHlp_TMUtcNow,
5115 CFGMR3Exists,
5116 CFGMR3QueryType,
5117 CFGMR3QuerySize,
5118 CFGMR3QueryInteger,
5119 CFGMR3QueryIntegerDef,
5120 CFGMR3QueryString,
5121 CFGMR3QueryStringDef,
5122 CFGMR3QueryBytes,
5123 CFGMR3QueryU64,
5124 CFGMR3QueryU64Def,
5125 CFGMR3QueryS64,
5126 CFGMR3QueryS64Def,
5127 CFGMR3QueryU32,
5128 CFGMR3QueryU32Def,
5129 CFGMR3QueryS32,
5130 CFGMR3QueryS32Def,
5131 CFGMR3QueryU16,
5132 CFGMR3QueryU16Def,
5133 CFGMR3QueryS16,
5134 CFGMR3QueryS16Def,
5135 CFGMR3QueryU8,
5136 CFGMR3QueryU8Def,
5137 CFGMR3QueryS8,
5138 CFGMR3QueryS8Def,
5139 CFGMR3QueryBool,
5140 CFGMR3QueryBoolDef,
5141 CFGMR3QueryPort,
5142 CFGMR3QueryPortDef,
5143 CFGMR3QueryUInt,
5144 CFGMR3QueryUIntDef,
5145 CFGMR3QuerySInt,
5146 CFGMR3QuerySIntDef,
5147 CFGMR3QueryPtr,
5148 CFGMR3QueryPtrDef,
5149 CFGMR3QueryGCPtr,
5150 CFGMR3QueryGCPtrDef,
5151 CFGMR3QueryGCPtrU,
5152 CFGMR3QueryGCPtrUDef,
5153 CFGMR3QueryGCPtrS,
5154 CFGMR3QueryGCPtrSDef,
5155 CFGMR3QueryStringAlloc,
5156 CFGMR3QueryStringAllocDef,
5157 CFGMR3GetParent,
5158 CFGMR3GetChild,
5159 CFGMR3GetChildF,
5160 CFGMR3GetChildFV,
5161 CFGMR3GetFirstChild,
5162 CFGMR3GetNextChild,
5163 CFGMR3GetName,
5164 CFGMR3GetNameLen,
5165 CFGMR3AreChildrenValid,
5166 CFGMR3GetFirstValue,
5167 CFGMR3GetNextValue,
5168 CFGMR3GetValueName,
5169 CFGMR3GetValueNameLen,
5170 CFGMR3GetValueType,
5171 CFGMR3AreValuesValid,
5172 CFGMR3ValidateConfig,
5173 pdmR3DevHlp_PhysRead,
5174 pdmR3DevHlp_PhysWrite,
5175 pdmR3DevHlp_PhysGCPhys2CCPtr,
5176 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
5177 pdmR3DevHlp_PhysReleasePageMappingLock,
5178 pdmR3DevHlp_PhysReadGCVirt,
5179 pdmR3DevHlp_PhysWriteGCVirt,
5180 pdmR3DevHlp_PhysGCPtr2GCPhys,
5181 pdmR3DevHlp_MMHeapAlloc,
5182 pdmR3DevHlp_MMHeapAllocZ,
5183 pdmR3DevHlp_MMHeapFree,
5184 pdmR3DevHlp_VMState,
5185 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
5186 pdmR3DevHlp_VMSetError,
5187 pdmR3DevHlp_VMSetErrorV,
5188 pdmR3DevHlp_VMSetRuntimeError,
5189 pdmR3DevHlp_VMSetRuntimeErrorV,
5190 pdmR3DevHlp_DBGFStopV,
5191 pdmR3DevHlp_DBGFInfoRegister,
5192 pdmR3DevHlp_DBGFInfoRegisterArgv,
5193 pdmR3DevHlp_DBGFRegRegister,
5194 pdmR3DevHlp_DBGFTraceBuf,
5195 pdmR3DevHlp_STAMRegister,
5196 pdmR3DevHlp_STAMRegisterV,
5197 pdmR3DevHlp_PCIRegister,
5198 pdmR3DevHlp_PCIRegisterMsi,
5199 pdmR3DevHlp_PCIIORegionRegister,
5200 pdmR3DevHlp_PCIInterceptConfigAccesses,
5201 pdmR3DevHlp_PCIConfigWrite,
5202 pdmR3DevHlp_PCIConfigRead,
5203 pdmR3DevHlp_PCIPhysRead,
5204 pdmR3DevHlp_PCIPhysWrite,
5205 pdmR3DevHlp_PCIPhysGCPhys2CCPtr,
5206 pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly,
5207 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr,
5208 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly,
5209 pdmR3DevHlp_PCISetIrq,
5210 pdmR3DevHlp_PCISetIrqNoWait,
5211 pdmR3DevHlp_ISASetIrq,
5212 pdmR3DevHlp_ISASetIrqNoWait,
5213 pdmR3DevHlp_DriverAttach,
5214 pdmR3DevHlp_DriverDetach,
5215 pdmR3DevHlp_DriverReconfigure,
5216 pdmR3DevHlp_QueueCreatePtr,
5217 pdmR3DevHlp_QueueCreate,
5218 pdmR3DevHlp_QueueToPtr,
5219 pdmR3DevHlp_QueueAlloc,
5220 pdmR3DevHlp_QueueInsert,
5221 pdmR3DevHlp_QueueInsertEx,
5222 pdmR3DevHlp_QueueFlushIfNecessary,
5223 pdmR3DevHlp_TaskCreate,
5224 pdmR3DevHlp_TaskTrigger,
5225 pdmR3DevHlp_SUPSemEventCreate,
5226 pdmR3DevHlp_SUPSemEventClose,
5227 pdmR3DevHlp_SUPSemEventSignal,
5228 pdmR3DevHlp_SUPSemEventWaitNoResume,
5229 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
5230 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
5231 pdmR3DevHlp_SUPSemEventGetResolution,
5232 pdmR3DevHlp_SUPSemEventMultiCreate,
5233 pdmR3DevHlp_SUPSemEventMultiClose,
5234 pdmR3DevHlp_SUPSemEventMultiSignal,
5235 pdmR3DevHlp_SUPSemEventMultiReset,
5236 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
5237 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
5238 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
5239 pdmR3DevHlp_SUPSemEventMultiGetResolution,
5240 pdmR3DevHlp_CritSectInit,
5241 pdmR3DevHlp_CritSectGetNop,
5242 pdmR3DevHlp_CritSectGetNopR0,
5243 pdmR3DevHlp_CritSectGetNopRC,
5244 pdmR3DevHlp_SetDeviceCritSect,
5245 pdmR3DevHlp_CritSectYield,
5246 pdmR3DevHlp_CritSectEnter,
5247 pdmR3DevHlp_CritSectEnterDebug,
5248 pdmR3DevHlp_CritSectTryEnter,
5249 pdmR3DevHlp_CritSectTryEnterDebug,
5250 pdmR3DevHlp_CritSectLeave,
5251 pdmR3DevHlp_CritSectIsOwner,
5252 pdmR3DevHlp_CritSectIsInitialized,
5253 pdmR3DevHlp_CritSectHasWaiters,
5254 pdmR3DevHlp_CritSectGetRecursion,
5255 pdmR3DevHlp_CritSectScheduleExitEvent,
5256 pdmR3DevHlp_CritSectDelete,
5257 pdmR3DevHlp_ThreadCreate,
5258 PDMR3ThreadDestroy,
5259 PDMR3ThreadIAmSuspending,
5260 PDMR3ThreadIAmRunning,
5261 PDMR3ThreadSleep,
5262 PDMR3ThreadSuspend,
5263 PDMR3ThreadResume,
5264 pdmR3DevHlp_SetAsyncNotification,
5265 pdmR3DevHlp_AsyncNotificationCompleted,
5266 pdmR3DevHlp_RTCRegister,
5267 pdmR3DevHlp_PCIBusRegister,
5268 pdmR3DevHlp_IommuRegister,
5269 pdmR3DevHlp_PICRegister,
5270 pdmR3DevHlp_ApicRegister,
5271 pdmR3DevHlp_IoApicRegister,
5272 pdmR3DevHlp_HpetRegister,
5273 pdmR3DevHlp_PciRawRegister,
5274 pdmR3DevHlp_DMACRegister,
5275 pdmR3DevHlp_DMARegister,
5276 pdmR3DevHlp_DMAReadMemory,
5277 pdmR3DevHlp_DMAWriteMemory,
5278 pdmR3DevHlp_DMASetDREQ,
5279 pdmR3DevHlp_DMAGetChannelMode,
5280 pdmR3DevHlp_DMASchedule,
5281 pdmR3DevHlp_CMOSWrite,
5282 pdmR3DevHlp_CMOSRead,
5283 pdmR3DevHlp_AssertEMT,
5284 pdmR3DevHlp_AssertOther,
5285 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
5286 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
5287 pdmR3DevHlp_CallR0,
5288 pdmR3DevHlp_VMGetSuspendReason,
5289 pdmR3DevHlp_VMGetResumeReason,
5290 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
5291 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
5292 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
5293 pdmR3DevHlp_CpuGetGuestMicroarch,
5294 pdmR3DevHlp_CpuGetGuestAddrWidths,
5295 pdmR3DevHlp_STAMDeregisterByPrefix,
5296 0,
5297 0,
5298 0,
5299 0,
5300 0,
5301 0,
5302 0,
5303 0,
5304 0,
5305 pdmR3DevHlp_Untrusted_GetUVM,
5306 pdmR3DevHlp_Untrusted_GetVM,
5307 pdmR3DevHlp_Untrusted_GetVMCPU,
5308 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
5309 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
5310 pdmR3DevHlp_Untrusted_FirmwareRegister,
5311 pdmR3DevHlp_Untrusted_VMReset,
5312 pdmR3DevHlp_Untrusted_VMSuspend,
5313 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
5314 pdmR3DevHlp_Untrusted_VMPowerOff,
5315 pdmR3DevHlp_Untrusted_A20IsEnabled,
5316 pdmR3DevHlp_Untrusted_A20Set,
5317 pdmR3DevHlp_Untrusted_GetCpuId,
5318 pdmR3DevHlp_TMTimeVirtGet,
5319 pdmR3DevHlp_TMTimeVirtGetFreq,
5320 pdmR3DevHlp_TMTimeVirtGetNano,
5321 pdmR3DevHlp_Untrusted_GetSupDrvSession,
5322 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
5323 pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister,
5324 PDM_DEVHLPR3_VERSION /* the end */
5325};
5326
5327
5328
5329/**
5330 * Queue consumer callback for internal component.
5331 *
5332 * @returns Success indicator.
5333 * If false the item will not be removed and the flushing will stop.
5334 * @param pVM The cross context VM structure.
5335 * @param pItem The item to consume. Upon return this item will be freed.
5336 */
5337DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
5338{
5339 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
5340 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
5341 switch (pTask->enmOp)
5342 {
5343 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
5344 PDMIsaSetIrq(pVM, pTask->u.IsaSetIRQ.iIrq, pTask->u.IsaSetIRQ.iLevel, pTask->u.IsaSetIRQ.uTagSrc);
5345 break;
5346
5347 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
5348 {
5349 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
5350 PPDMPCIDEV pPciDev = pTask->u.PciSetIRQ.pPciDevR3;
5351 if (pPciDev)
5352 {
5353 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
5354 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
5355 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
5356
5357 pdmLock(pVM);
5358 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIRQ.iIrq,
5359 pTask->u.PciSetIRQ.iLevel, pTask->u.PciSetIRQ.uTagSrc);
5360 pdmUnlock(pVM);
5361 }
5362 else
5363 AssertReleaseMsgFailed(("No PCI device registered!\n"));
5364 break;
5365 }
5366
5367 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
5368 {
5369 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIRQ.uBusDevFn, pTask->u.IoApicSetIRQ.iIrq, pTask->u.IoApicSetIRQ.iLevel,
5370 pTask->u.IoApicSetIRQ.uTagSrc);
5371 break;
5372 }
5373
5374 default:
5375 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
5376 break;
5377 }
5378 return true;
5379}
5380
5381/** @} */
5382
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