VirtualBox

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

Last change on this file since 90368 was 90348, checked in by vboxsync, 4 years ago

VMM: Removed the VM pointers from the internal critsect structures. bugref:9218 bugref:10074

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