VirtualBox

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

Last change on this file since 90904 was 90502, checked in by vboxsync, 4 years ago

VMM/PDM: Added device helpers for read/write critical sections. bugref:6695

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 217.0 KB
Line 
1/* $Id: PDMDevHlp.cpp 90502 2021-08-03 21:20:34Z 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,pfnCritSectRwInit} */
2878static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwInit(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
2879 const char *pszNameFmt, va_list va)
2880{
2881 PDMDEV_ASSERT_DEVINS(pDevIns);
2882 LogFlow(("pdmR3DevHlp_CritSectRwInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
2883 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
2884
2885 PVM pVM = pDevIns->Internal.s.pVMR3;
2886 VM_ASSERT_EMT(pVM);
2887 int rc = pdmR3CritSectRwInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
2888
2889 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2890 return rc;
2891}
2892
2893
2894/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwDelete} */
2895static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwDelete(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
2896{
2897 PDMDEV_ASSERT_DEVINS(pDevIns);
2898 return PDMR3CritSectRwDelete(pDevIns->Internal.s.pVMR3, pCritSect);
2899}
2900
2901
2902/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterShared} */
2903static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
2904{
2905 PDMDEV_ASSERT_DEVINS(pDevIns);
2906 return PDMCritSectRwEnterShared(pDevIns->Internal.s.pVMR3, pCritSect, rcBusy);
2907}
2908
2909
2910/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterSharedDebug} */
2911static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy,
2912 RTHCUINTPTR uId, RT_SRC_POS_DECL)
2913{
2914 PDMDEV_ASSERT_DEVINS(pDevIns);
2915 return PDMCritSectRwEnterSharedDebug(pDevIns->Internal.s.pVMR3, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2916}
2917
2918
2919/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterShared} */
2920static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
2921{
2922 PDMDEV_ASSERT_DEVINS(pDevIns);
2923 return PDMCritSectRwTryEnterShared(pDevIns->Internal.s.pVMR3, pCritSect);
2924}
2925
2926
2927/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterSharedDebug} */
2928static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect,
2929 RTHCUINTPTR uId, RT_SRC_POS_DECL)
2930{
2931 PDMDEV_ASSERT_DEVINS(pDevIns);
2932 return PDMCritSectRwTryEnterSharedDebug(pDevIns->Internal.s.pVMR3, pCritSect, uId, RT_SRC_POS_ARGS);
2933}
2934
2935
2936/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwLeaveShared} */
2937static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwLeaveShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
2938{
2939 PDMDEV_ASSERT_DEVINS(pDevIns);
2940 return PDMCritSectRwLeaveShared(pDevIns->Internal.s.pVMR3, pCritSect);
2941}
2942
2943
2944/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterExcl} */
2945static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
2946{
2947 PDMDEV_ASSERT_DEVINS(pDevIns);
2948 return PDMCritSectRwEnterExcl(pDevIns->Internal.s.pVMR3, pCritSect, rcBusy);
2949}
2950
2951
2952/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterExclDebug} */
2953static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy,
2954 RTHCUINTPTR uId, RT_SRC_POS_DECL)
2955{
2956 PDMDEV_ASSERT_DEVINS(pDevIns);
2957 return PDMCritSectRwEnterExclDebug(pDevIns->Internal.s.pVMR3, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2958}
2959
2960
2961/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterExcl} */
2962static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
2963{
2964 PDMDEV_ASSERT_DEVINS(pDevIns);
2965 return PDMCritSectRwTryEnterExcl(pDevIns->Internal.s.pVMR3, pCritSect);
2966}
2967
2968
2969/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterExclDebug} */
2970static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect,
2971 RTHCUINTPTR uId, RT_SRC_POS_DECL)
2972{
2973 PDMDEV_ASSERT_DEVINS(pDevIns);
2974 return PDMCritSectRwTryEnterExclDebug(pDevIns->Internal.s.pVMR3, pCritSect, uId, RT_SRC_POS_ARGS);
2975}
2976
2977
2978/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwLeaveExcl} */
2979static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwLeaveExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
2980{
2981 PDMDEV_ASSERT_DEVINS(pDevIns);
2982 return PDMCritSectRwLeaveExcl(pDevIns->Internal.s.pVMR3, pCritSect);
2983}
2984
2985
2986/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwIsWriteOwner} */
2987static DECLCALLBACK(bool) pdmR3DevHlp_CritSectRwIsWriteOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
2988{
2989 PDMDEV_ASSERT_DEVINS(pDevIns);
2990 return PDMCritSectRwIsWriteOwner(pDevIns->Internal.s.pVMR3, pCritSect);
2991}
2992
2993
2994/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwIsReadOwner} */
2995static DECLCALLBACK(bool) pdmR3DevHlp_CritSectRwIsReadOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, bool fWannaHear)
2996{
2997 PDMDEV_ASSERT_DEVINS(pDevIns);
2998 return PDMCritSectRwIsReadOwner(pDevIns->Internal.s.pVMR3, pCritSect, fWannaHear);
2999}
3000
3001
3002/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwGetWriteRecursion} */
3003static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectRwGetWriteRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
3004{
3005 PDMDEV_ASSERT_DEVINS(pDevIns);
3006 RT_NOREF(pDevIns);
3007 return PDMCritSectRwGetWriteRecursion(pCritSect);
3008}
3009
3010
3011/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwGetWriterReadRecursion} */
3012static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectRwGetWriterReadRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
3013{
3014 PDMDEV_ASSERT_DEVINS(pDevIns);
3015 RT_NOREF(pDevIns);
3016 return PDMCritSectRwGetWriterReadRecursion(pCritSect);
3017}
3018
3019
3020/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwGetReadCount} */
3021static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectRwGetReadCount(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
3022{
3023 PDMDEV_ASSERT_DEVINS(pDevIns);
3024 RT_NOREF(pDevIns);
3025 return PDMCritSectRwGetReadCount(pCritSect);
3026}
3027
3028
3029/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwIsInitialized} */
3030static DECLCALLBACK(bool) pdmR3DevHlp_CritSectRwIsInitialized(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
3031{
3032 PDMDEV_ASSERT_DEVINS(pDevIns);
3033 RT_NOREF(pDevIns);
3034 return PDMCritSectRwIsInitialized(pCritSect);
3035}
3036
3037
3038/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
3039static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
3040 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
3041{
3042 PDMDEV_ASSERT_DEVINS(pDevIns);
3043 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3044 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
3045 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
3046
3047 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
3048
3049 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
3050 rc, *ppThread));
3051 return rc;
3052}
3053
3054
3055/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
3056static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
3057{
3058 PDMDEV_ASSERT_DEVINS(pDevIns);
3059 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
3060 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
3061
3062 int rc = VINF_SUCCESS;
3063 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
3064 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
3065 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
3066 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
3067 AssertStmt( enmVMState == VMSTATE_SUSPENDING
3068 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
3069 || enmVMState == VMSTATE_SUSPENDING_LS
3070 || enmVMState == VMSTATE_RESETTING
3071 || enmVMState == VMSTATE_RESETTING_LS
3072 || enmVMState == VMSTATE_POWERING_OFF
3073 || enmVMState == VMSTATE_POWERING_OFF_LS,
3074 rc = VERR_INVALID_STATE);
3075
3076 if (RT_SUCCESS(rc))
3077 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
3078
3079 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3080 return rc;
3081}
3082
3083
3084/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
3085static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
3086{
3087 PDMDEV_ASSERT_DEVINS(pDevIns);
3088 PVM pVM = pDevIns->Internal.s.pVMR3;
3089
3090 VMSTATE enmVMState = VMR3GetState(pVM);
3091 if ( enmVMState == VMSTATE_SUSPENDING
3092 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
3093 || enmVMState == VMSTATE_SUSPENDING_LS
3094 || enmVMState == VMSTATE_RESETTING
3095 || enmVMState == VMSTATE_RESETTING_LS
3096 || enmVMState == VMSTATE_POWERING_OFF
3097 || enmVMState == VMSTATE_POWERING_OFF_LS)
3098 {
3099 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3100 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
3101 }
3102 else
3103 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
3104}
3105
3106
3107/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
3108static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
3109{
3110 PDMDEV_ASSERT_DEVINS(pDevIns);
3111 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3112 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
3113 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
3114 pRtcReg->pfnWrite, ppRtcHlp));
3115
3116 /*
3117 * Validate input.
3118 */
3119 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
3120 {
3121 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
3122 PDM_RTCREG_VERSION));
3123 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
3124 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3125 return VERR_INVALID_PARAMETER;
3126 }
3127 if ( !pRtcReg->pfnWrite
3128 || !pRtcReg->pfnRead)
3129 {
3130 Assert(pRtcReg->pfnWrite);
3131 Assert(pRtcReg->pfnRead);
3132 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3133 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3134 return VERR_INVALID_PARAMETER;
3135 }
3136
3137 if (!ppRtcHlp)
3138 {
3139 Assert(ppRtcHlp);
3140 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
3141 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3142 return VERR_INVALID_PARAMETER;
3143 }
3144
3145 /*
3146 * Only one DMA device.
3147 */
3148 PVM pVM = pDevIns->Internal.s.pVMR3;
3149 if (pVM->pdm.s.pRtc)
3150 {
3151 AssertMsgFailed(("Only one RTC device is supported!\n"));
3152 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
3153 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3154 return VERR_INVALID_PARAMETER;
3155 }
3156
3157 /*
3158 * Allocate and initialize pci bus structure.
3159 */
3160 int rc = VINF_SUCCESS;
3161 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
3162 if (pRtc)
3163 {
3164 pRtc->pDevIns = pDevIns;
3165 pRtc->Reg = *pRtcReg;
3166 pVM->pdm.s.pRtc = pRtc;
3167
3168 /* set the helper pointer. */
3169 *ppRtcHlp = &g_pdmR3DevRtcHlp;
3170 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
3171 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3172 }
3173 else
3174 rc = VERR_NO_MEMORY;
3175
3176 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
3177 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3178 return rc;
3179}
3180
3181
3182/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
3183static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3184{
3185 PDMDEV_ASSERT_DEVINS(pDevIns);
3186 PVM pVM = pDevIns->Internal.s.pVMR3;
3187 VM_ASSERT_EMT(pVM);
3188 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
3189 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
3190 int rc = VINF_SUCCESS;
3191 if (pVM->pdm.s.pDmac)
3192 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pDevIns, pfnTransferHandler, pvUser);
3193 else
3194 {
3195 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3196 rc = VERR_PDM_NO_DMAC_INSTANCE;
3197 }
3198 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
3199 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3200 return rc;
3201}
3202
3203
3204/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
3205static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3206{
3207 PDMDEV_ASSERT_DEVINS(pDevIns);
3208 PVM pVM = pDevIns->Internal.s.pVMR3;
3209 VM_ASSERT_EMT(pVM);
3210 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
3211 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
3212 int rc = VINF_SUCCESS;
3213 if (pVM->pdm.s.pDmac)
3214 {
3215 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3216 if (pcbRead)
3217 *pcbRead = cb;
3218 }
3219 else
3220 {
3221 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3222 rc = VERR_PDM_NO_DMAC_INSTANCE;
3223 }
3224 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
3225 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3226 return rc;
3227}
3228
3229
3230/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
3231static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3232{
3233 PDMDEV_ASSERT_DEVINS(pDevIns);
3234 PVM pVM = pDevIns->Internal.s.pVMR3;
3235 VM_ASSERT_EMT(pVM);
3236 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
3237 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
3238 int rc = VINF_SUCCESS;
3239 if (pVM->pdm.s.pDmac)
3240 {
3241 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3242 if (pcbWritten)
3243 *pcbWritten = cb;
3244 }
3245 else
3246 {
3247 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3248 rc = VERR_PDM_NO_DMAC_INSTANCE;
3249 }
3250 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
3251 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3252 return rc;
3253}
3254
3255
3256/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
3257static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3258{
3259 PDMDEV_ASSERT_DEVINS(pDevIns);
3260 PVM pVM = pDevIns->Internal.s.pVMR3;
3261 VM_ASSERT_EMT(pVM);
3262 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
3263 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
3264 int rc = VINF_SUCCESS;
3265 if (pVM->pdm.s.pDmac)
3266 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
3267 else
3268 {
3269 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3270 rc = VERR_PDM_NO_DMAC_INSTANCE;
3271 }
3272 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
3273 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3274 return rc;
3275}
3276
3277/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
3278static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3279{
3280 PDMDEV_ASSERT_DEVINS(pDevIns);
3281 PVM pVM = pDevIns->Internal.s.pVMR3;
3282 VM_ASSERT_EMT(pVM);
3283 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
3284 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
3285 uint8_t u8Mode;
3286 if (pVM->pdm.s.pDmac)
3287 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
3288 else
3289 {
3290 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3291 u8Mode = 3 << 2 /* illegal mode type */;
3292 }
3293 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
3294 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
3295 return u8Mode;
3296}
3297
3298/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
3299static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
3300{
3301 PDMDEV_ASSERT_DEVINS(pDevIns);
3302 PVM pVM = pDevIns->Internal.s.pVMR3;
3303 VM_ASSERT_EMT(pVM);
3304 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
3305 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_IS_SET(pVM, VM_FF_PDM_DMA)));
3306
3307 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3308 VM_FF_SET(pVM, VM_FF_PDM_DMA);
3309 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
3310}
3311
3312
3313/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
3314static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3315{
3316 PDMDEV_ASSERT_DEVINS(pDevIns);
3317 PVM pVM = pDevIns->Internal.s.pVMR3;
3318 VM_ASSERT_EMT(pVM);
3319
3320 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
3321 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
3322 int rc;
3323 if (pVM->pdm.s.pRtc)
3324 {
3325 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3326 rc = PDMCritSectEnter(pVM, pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3327 if (RT_SUCCESS(rc))
3328 {
3329 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pDevInsRtc, iReg, u8Value);
3330 PDMCritSectLeave(pVM, pDevInsRtc->pCritSectRoR3);
3331 }
3332 }
3333 else
3334 rc = VERR_PDM_NO_RTC_INSTANCE;
3335
3336 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3337 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3338 return rc;
3339}
3340
3341
3342/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
3343static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3344{
3345 PDMDEV_ASSERT_DEVINS(pDevIns);
3346 PVM pVM = pDevIns->Internal.s.pVMR3;
3347 VM_ASSERT_EMT(pVM);
3348
3349 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
3350 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
3351 int rc;
3352 if (pVM->pdm.s.pRtc)
3353 {
3354 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3355 rc = PDMCritSectEnter(pVM, pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3356 if (RT_SUCCESS(rc))
3357 {
3358 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pDevInsRtc, iReg, pu8Value);
3359 PDMCritSectLeave(pVM, pDevInsRtc->pCritSectRoR3);
3360 }
3361 }
3362 else
3363 rc = VERR_PDM_NO_RTC_INSTANCE;
3364
3365 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3366 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3367 return rc;
3368}
3369
3370
3371/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
3372static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3373{
3374 PDMDEV_ASSERT_DEVINS(pDevIns);
3375 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3376 return true;
3377
3378 char szMsg[100];
3379 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3380 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3381 AssertBreakpoint();
3382 return false;
3383}
3384
3385
3386/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
3387static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3388{
3389 PDMDEV_ASSERT_DEVINS(pDevIns);
3390 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3391 return true;
3392
3393 char szMsg[100];
3394 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3395 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3396 AssertBreakpoint();
3397 return false;
3398}
3399
3400
3401/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
3402static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3403 const char *pszSymPrefix, const char *pszSymList)
3404{
3405 PDMDEV_ASSERT_DEVINS(pDevIns);
3406 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3407 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3408 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3409
3410 int rc;
3411 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3412 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3413 {
3414 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
3415 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3416 pvInterface, cbInterface,
3417 pDevIns->pReg->pszRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
3418 pszSymPrefix, pszSymList,
3419 false /*fRing0OrRC*/);
3420 else
3421 {
3422 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
3423 rc = VERR_PERMISSION_DENIED;
3424 }
3425 }
3426 else
3427 {
3428 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3429 pszSymPrefix, pDevIns->pReg->szName));
3430 rc = VERR_INVALID_NAME;
3431 }
3432
3433 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3434 pDevIns->iInstance, rc));
3435 return rc;
3436}
3437
3438
3439/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
3440static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3441 const char *pszSymPrefix, const char *pszSymList)
3442{
3443 PDMDEV_ASSERT_DEVINS(pDevIns);
3444 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3445 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3446 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3447
3448 int rc;
3449 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3450 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3451 {
3452 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3453 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3454 pvInterface, cbInterface,
3455 pDevIns->pReg->pszR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
3456 pszSymPrefix, pszSymList,
3457 true /*fRing0OrRC*/);
3458 else
3459 {
3460 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
3461 rc = VERR_PERMISSION_DENIED;
3462 }
3463 }
3464 else
3465 {
3466 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3467 pszSymPrefix, pDevIns->pReg->szName));
3468 rc = VERR_INVALID_NAME;
3469 }
3470
3471 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3472 pDevIns->iInstance, rc));
3473 return rc;
3474}
3475
3476
3477/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
3478static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
3479{
3480 PDMDEV_ASSERT_DEVINS(pDevIns);
3481 PVM pVM = pDevIns->Internal.s.pVMR3;
3482 PVMCPU pVCpu = VMMGetCpu(pVM);
3483 AssertReturn(pVCpu, VERR_VM_THREAD_IS_EMT);
3484 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
3485 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
3486
3487 /*
3488 * Resolve the ring-0 entry point. There is not need to remember this like
3489 * we do for drivers since this is mainly for construction time hacks and
3490 * other things that aren't performance critical.
3491 */
3492 int rc;
3493 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3494 {
3495 /*
3496 * Make the ring-0 call.
3497 */
3498 PDMDEVICEGENCALLREQ Req;
3499 RT_ZERO(Req.Params);
3500 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
3501 Req.Hdr.cbReq = sizeof(Req);
3502 Req.pDevInsR3 = pDevIns;
3503 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
3504 Req.enmCall = PDMDEVICEGENCALL_REQUEST;
3505 Req.Params.Req.uReq = uOperation;
3506 Req.Params.Req.uArg = u64Arg;
3507 rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_PDM_DEVICE_GEN_CALL, 0, &Req.Hdr);
3508 }
3509 else
3510 rc = VERR_ACCESS_DENIED;
3511 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3512 pDevIns->iInstance, rc));
3513 return rc;
3514}
3515
3516
3517/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
3518static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
3519{
3520 PDMDEV_ASSERT_DEVINS(pDevIns);
3521 PVM pVM = pDevIns->Internal.s.pVMR3;
3522 VM_ASSERT_EMT(pVM);
3523 VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
3524 LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
3525 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3526 return enmReason;
3527}
3528
3529
3530/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
3531static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
3532{
3533 PDMDEV_ASSERT_DEVINS(pDevIns);
3534 PVM pVM = pDevIns->Internal.s.pVMR3;
3535 VM_ASSERT_EMT(pVM);
3536 VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
3537 LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
3538 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3539 return enmReason;
3540}
3541
3542
3543/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
3544static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
3545{
3546 PDMDEV_ASSERT_DEVINS(pDevIns);
3547 LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3548 return pDevIns->Internal.s.pVMR3->pUVM;
3549}
3550
3551
3552/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3553static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
3554{
3555 PDMDEV_ASSERT_DEVINS(pDevIns);
3556 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3557 return pDevIns->Internal.s.pVMR3;
3558}
3559
3560
3561/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3562static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
3563{
3564 PDMDEV_ASSERT_DEVINS(pDevIns);
3565 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3566 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
3567 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
3568}
3569
3570
3571/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
3572static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
3573{
3574 PDMDEV_ASSERT_DEVINS(pDevIns);
3575 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR3);
3576 LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
3577 return idCpu;
3578}
3579
3580
3581/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
3582static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
3583 PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
3584{
3585 PDMDEV_ASSERT_DEVINS(pDevIns);
3586 PVM pVM = pDevIns->Internal.s.pVMR3;
3587 VM_ASSERT_EMT(pVM);
3588 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
3589 ".pfnInterceptConfigAccesses=%p, pfnConfigRead=%p, pfnConfigWrite=%p, .pfnSetIrqR3=%p, .u32EndVersion=%#x} ppPciHlpR3=%p piBus=%p\n",
3590 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
3591 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnInterceptConfigAccesses, pPciBusReg->pfnConfigRead,
3592 pPciBusReg->pfnConfigWrite, pPciBusReg->pfnSetIrqR3, pPciBusReg->u32EndVersion, ppPciHlp, piBus));
3593
3594 /*
3595 * Validate the structure and output parameters.
3596 */
3597 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGR3_VERSION,
3598 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3599 VERR_INVALID_PARAMETER);
3600 AssertPtrReturn(pPciBusReg->pfnRegisterR3, VERR_INVALID_PARAMETER);
3601 AssertPtrNullReturn(pPciBusReg->pfnRegisterMsiR3, VERR_INVALID_POINTER);
3602 AssertPtrReturn(pPciBusReg->pfnIORegionRegisterR3, VERR_INVALID_POINTER);
3603 AssertPtrReturn(pPciBusReg->pfnInterceptConfigAccesses, VERR_INVALID_POINTER);
3604 AssertPtrReturn(pPciBusReg->pfnConfigWrite, VERR_INVALID_POINTER);
3605 AssertPtrReturn(pPciBusReg->pfnConfigRead, VERR_INVALID_POINTER);
3606 AssertPtrReturn(pPciBusReg->pfnSetIrqR3, VERR_INVALID_POINTER);
3607 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGR3_VERSION,
3608 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3609 VERR_INVALID_PARAMETER);
3610 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
3611 AssertPtrNullReturn(piBus, VERR_INVALID_POINTER);
3612 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3613
3614 /*
3615 * Find free PCI bus entry.
3616 */
3617 unsigned iBus = 0;
3618 for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
3619 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
3620 break;
3621 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
3622 ("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)),
3623 VERR_OUT_OF_RESOURCES);
3624 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
3625
3626 /*
3627 * Init the R3 bits.
3628 */
3629 pPciBus->iBus = iBus;
3630 pPciBus->pDevInsR3 = pDevIns;
3631 pPciBus->pfnRegister = pPciBusReg->pfnRegisterR3;
3632 pPciBus->pfnRegisterMsi = pPciBusReg->pfnRegisterMsiR3;
3633 pPciBus->pfnIORegionRegister = pPciBusReg->pfnIORegionRegisterR3;
3634 pPciBus->pfnInterceptConfigAccesses = pPciBusReg->pfnInterceptConfigAccesses;
3635 pPciBus->pfnConfigRead = pPciBusReg->pfnConfigRead;
3636 pPciBus->pfnConfigWrite = pPciBusReg->pfnConfigWrite;
3637 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
3638
3639 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3640
3641 /* set the helper pointer and return. */
3642 *ppPciHlp = &g_pdmR3DevPciHlp;
3643 if (piBus)
3644 *piBus = iBus;
3645 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS, iBus));
3646 return VINF_SUCCESS;
3647}
3648
3649
3650/** @interface_method_impl{PDMDEVHLPR3,pfnIommuRegister} */
3651static DECLCALLBACK(int) pdmR3DevHlp_IommuRegister(PPDMDEVINS pDevIns, PPDMIOMMUREGR3 pIommuReg, PCPDMIOMMUHLPR3 *ppIommuHlp,
3652 uint32_t *pidxIommu)
3653{
3654 PDMDEV_ASSERT_DEVINS(pDevIns);
3655 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3656 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: pIommuReg=%p:{.u32Version=%#x, .u32TheEnd=%#x } ppIommuHlp=%p\n",
3657 pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
3658 PVM pVM = pDevIns->Internal.s.pVMR3;
3659
3660 /*
3661 * Validate input.
3662 */
3663 AssertMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGR3_VERSION,
3664 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32Version, PDM_IOMMUREGR3_VERSION),
3665 VERR_INVALID_PARAMETER);
3666 AssertPtrReturn(pIommuReg->pfnMemAccess, VERR_INVALID_POINTER);
3667 AssertPtrReturn(pIommuReg->pfnMemBulkAccess, VERR_INVALID_POINTER);
3668 AssertPtrReturn(pIommuReg->pfnMsiRemap, VERR_INVALID_POINTER);
3669 AssertMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGR3_VERSION,
3670 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32TheEnd, PDM_IOMMUREGR3_VERSION),
3671 VERR_INVALID_PARAMETER);
3672 AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
3673
3674 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3675 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3676
3677 /*
3678 * Find free IOMMU slot.
3679 * The IOMMU at the root complex is the one at 0.
3680 */
3681 unsigned idxIommu = 0;
3682#if 0
3683 for (idxIommu = 0; idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus); idxIommu++)
3684 if (!pVM->pdm.s.aIommus[idxIommu].pDevInsR3)
3685 break;
3686 AssertLogRelMsgReturn(idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus),
3687 ("Too many IOMMUs. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aIommus)),
3688 VERR_OUT_OF_RESOURCES);
3689#else
3690 /* Currently we support only a single IOMMU. */
3691 AssertMsgReturn(!pVM->pdm.s.aIommus[0].pDevInsR3,
3692 ("%s/%u: Only one IOMMU device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3693 VERR_ALREADY_EXISTS);
3694#endif
3695 PPDMIOMMUR3 pIommu = &pVM->pdm.s.aIommus[idxIommu];
3696
3697 /*
3698 * Init the R3 bits.
3699 */
3700 pIommu->idxIommu = idxIommu;
3701 pIommu->pDevInsR3 = pDevIns;
3702 pIommu->pfnMemAccess = pIommuReg->pfnMemAccess;
3703 pIommu->pfnMemBulkAccess = pIommuReg->pfnMemBulkAccess;
3704 pIommu->pfnMsiRemap = pIommuReg->pfnMsiRemap;
3705 Log(("PDM: Registered IOMMU device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3706
3707 /* Set the helper pointer and return. */
3708 *ppIommuHlp = &g_pdmR3DevIommuHlp;
3709 if (pidxIommu)
3710 *pidxIommu = idxIommu;
3711 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3712 return VINF_SUCCESS;
3713}
3714
3715
3716
3717/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
3718static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
3719{
3720 PDMDEV_ASSERT_DEVINS(pDevIns);
3721 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3722 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
3723 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
3724 PVM pVM = pDevIns->Internal.s.pVMR3;
3725
3726 /*
3727 * Validate input.
3728 */
3729 AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
3730 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
3731 VERR_INVALID_PARAMETER);
3732 AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
3733 AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
3734 AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
3735 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
3736 VERR_INVALID_PARAMETER);
3737 AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
3738
3739 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3740 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3741
3742 /*
3743 * Only one PIC device.
3744 */
3745 AssertMsgReturn(pVM->pdm.s.Pic.pDevInsR3 == NULL, ("%s/%d: Only one PIC!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3746 VERR_ALREADY_EXISTS);
3747
3748 /*
3749 * Take down the callbacks and instance.
3750 */
3751 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3752 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrq;
3753 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterrupt;
3754 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3755
3756 /* set the helper pointer and return. */
3757 *ppPicHlp = &g_pdmR3DevPicHlp;
3758 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3759 return VINF_SUCCESS;
3760}
3761
3762
3763/** @interface_method_impl{PDMDEVHLPR3,pfnApicRegister} */
3764static DECLCALLBACK(int) pdmR3DevHlp_ApicRegister(PPDMDEVINS pDevIns)
3765{
3766 PDMDEV_ASSERT_DEVINS(pDevIns);
3767
3768 /*
3769 * Validate caller context.
3770 */
3771 PVM pVM = pDevIns->Internal.s.pVMR3;
3772 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3773 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3774
3775 /*
3776 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3777 * as they need to communicate and share state easily.
3778 */
3779 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 == NULL,
3780 ("%s/%u: Only one APIC device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3781 VERR_ALREADY_EXISTS);
3782
3783 /*
3784 * Set the ring-3 and raw-mode bits, leave the ring-0 to ring-0 setup.
3785 */
3786 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3787 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3788 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3789
3790 LogFlow(("pdmR3DevHlp_ApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3791 return VINF_SUCCESS;
3792}
3793
3794
3795/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicRegister} */
3796static DECLCALLBACK(int) pdmR3DevHlp_IoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
3797{
3798 PDMDEV_ASSERT_DEVINS(pDevIns);
3799 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
3800 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
3801 PVM pVM = pDevIns->Internal.s.pVMR3;
3802
3803 /*
3804 * Validate input.
3805 */
3806 AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
3807 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
3808 VERR_VERSION_MISMATCH);
3809 AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
3810 AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
3811 AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
3812 AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
3813 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
3814 VERR_VERSION_MISMATCH);
3815 AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
3816 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3817 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3818
3819 /*
3820 * The I/O APIC requires the APIC to be present (hacks++).
3821 * If the I/O APIC does GC stuff so must the APIC.
3822 */
3823 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 != NULL, ("Configuration error / Init order error! No APIC!\n"), VERR_WRONG_ORDER);
3824
3825 /*
3826 * Only one I/O APIC device.
3827 */
3828 AssertMsgReturn(pVM->pdm.s.IoApic.pDevInsR3 == NULL,
3829 ("Only one IOAPIC device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3830 VERR_ALREADY_EXISTS);
3831
3832 /*
3833 * Initialize the R3 bits.
3834 */
3835 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3836 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrq;
3837 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsi;
3838 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoi;
3839 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3840
3841 /* set the helper pointer and return. */
3842 *ppIoApicHlp = &g_pdmR3DevIoApicHlp;
3843 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3844 return VINF_SUCCESS;
3845}
3846
3847
3848/** @interface_method_impl{PDMDEVHLPR3,pfnHpetRegister} */
3849static DECLCALLBACK(int) pdmR3DevHlp_HpetRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
3850{
3851 PDMDEV_ASSERT_DEVINS(pDevIns);
3852 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3853 PVM pVM = pDevIns->Internal.s.pVMR3;
3854
3855 /*
3856 * Validate input.
3857 */
3858 AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
3859 ("%s/%u: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
3860 VERR_VERSION_MISMATCH);
3861 AssertPtrReturn(ppHpetHlpR3, VERR_INVALID_POINTER);
3862 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3863 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3864
3865 /*
3866 * Only one HPET device.
3867 */
3868 AssertMsgReturn(pVM->pdm.s.pHpet == NULL,
3869 ("Only one HPET device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3870 VERR_ALREADY_EXISTS);
3871
3872 /*
3873 * Do the job (what there is of it).
3874 */
3875 pVM->pdm.s.pHpet = pDevIns;
3876 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
3877
3878 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3879 return VINF_SUCCESS;
3880}
3881
3882
3883/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
3884static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
3885{
3886 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3887 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3888 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3889
3890 /*
3891 * Validate input.
3892 */
3893 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
3894 {
3895 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
3896 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3897 return VERR_INVALID_PARAMETER;
3898 }
3899
3900 if (!ppPciRawHlpR3)
3901 {
3902 Assert(ppPciRawHlpR3);
3903 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3904 return VERR_INVALID_PARAMETER;
3905 }
3906
3907 /* set the helper pointer and return. */
3908 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
3909 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3910 return VINF_SUCCESS;
3911}
3912
3913
3914/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
3915static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3916{
3917 PDMDEV_ASSERT_DEVINS(pDevIns);
3918 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3919 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",
3920 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3921 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3922
3923 /*
3924 * Validate input.
3925 */
3926 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3927 {
3928 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3929 PDM_DMACREG_VERSION));
3930 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
3931 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3932 return VERR_INVALID_PARAMETER;
3933 }
3934 if ( !pDmacReg->pfnRun
3935 || !pDmacReg->pfnRegister
3936 || !pDmacReg->pfnReadMemory
3937 || !pDmacReg->pfnWriteMemory
3938 || !pDmacReg->pfnSetDREQ
3939 || !pDmacReg->pfnGetChannelMode)
3940 {
3941 Assert(pDmacReg->pfnRun);
3942 Assert(pDmacReg->pfnRegister);
3943 Assert(pDmacReg->pfnReadMemory);
3944 Assert(pDmacReg->pfnWriteMemory);
3945 Assert(pDmacReg->pfnSetDREQ);
3946 Assert(pDmacReg->pfnGetChannelMode);
3947 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3948 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3949 return VERR_INVALID_PARAMETER;
3950 }
3951
3952 if (!ppDmacHlp)
3953 {
3954 Assert(ppDmacHlp);
3955 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
3956 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3957 return VERR_INVALID_PARAMETER;
3958 }
3959
3960 /*
3961 * Only one DMA device.
3962 */
3963 PVM pVM = pDevIns->Internal.s.pVMR3;
3964 if (pVM->pdm.s.pDmac)
3965 {
3966 AssertMsgFailed(("Only one DMA device is supported!\n"));
3967 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3968 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3969 return VERR_INVALID_PARAMETER;
3970 }
3971
3972 /*
3973 * Allocate and initialize pci bus structure.
3974 */
3975 int rc = VINF_SUCCESS;
3976 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3977 if (pDmac)
3978 {
3979 pDmac->pDevIns = pDevIns;
3980 pDmac->Reg = *pDmacReg;
3981 pVM->pdm.s.pDmac = pDmac;
3982
3983 /* set the helper pointer. */
3984 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3985 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3986 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3987 }
3988 else
3989 rc = VERR_NO_MEMORY;
3990
3991 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3992 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3993 return rc;
3994}
3995
3996
3997/**
3998 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3999 */
4000static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
4001{
4002 PDMDEV_ASSERT_DEVINS(pDevIns);
4003 PVM pVM = pDevIns->Internal.s.pVMR3;
4004 VM_ASSERT_EMT(pVM);
4005 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
4006 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
4007
4008 if (pVM->pdm.s.pvVMMDevHeap == NULL)
4009 {
4010 pVM->pdm.s.pvVMMDevHeap = pvHeap;
4011 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
4012 pVM->pdm.s.cbVMMDevHeap = cbHeap;
4013 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
4014 }
4015 else
4016 {
4017 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
4018 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
4019 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
4020 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
4021 {
4022 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
4023 if (pVM->pdm.s.pfnVMMDevHeapNotify)
4024 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
4025 }
4026 }
4027
4028 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
4029 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
4030 return VINF_SUCCESS;
4031}
4032
4033
4034/**
4035 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
4036 */
4037static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4038{
4039 PDMDEV_ASSERT_DEVINS(pDevIns);
4040 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4041 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
4042 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
4043
4044 /*
4045 * Validate input.
4046 */
4047 if (pFwReg->u32Version != PDM_FWREG_VERSION)
4048 {
4049 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
4050 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
4051 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4052 return VERR_INVALID_PARAMETER;
4053 }
4054 if (!pFwReg->pfnIsHardReset)
4055 {
4056 Assert(pFwReg->pfnIsHardReset);
4057 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
4058 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4059 return VERR_INVALID_PARAMETER;
4060 }
4061
4062 if (!ppFwHlp)
4063 {
4064 Assert(ppFwHlp);
4065 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
4066 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4067 return VERR_INVALID_PARAMETER;
4068 }
4069
4070 /*
4071 * Only one DMA device.
4072 */
4073 PVM pVM = pDevIns->Internal.s.pVMR3;
4074 if (pVM->pdm.s.pFirmware)
4075 {
4076 AssertMsgFailed(("Only one firmware device is supported!\n"));
4077 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
4078 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4079 return VERR_INVALID_PARAMETER;
4080 }
4081
4082 /*
4083 * Allocate and initialize pci bus structure.
4084 */
4085 int rc = VINF_SUCCESS;
4086 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
4087 if (pFirmware)
4088 {
4089 pFirmware->pDevIns = pDevIns;
4090 pFirmware->Reg = *pFwReg;
4091 pVM->pdm.s.pFirmware = pFirmware;
4092
4093 /* set the helper pointer. */
4094 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
4095 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
4096 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
4097 }
4098 else
4099 rc = VERR_NO_MEMORY;
4100
4101 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
4102 pDevIns->pReg->szName, pDevIns->iInstance, rc));
4103 return rc;
4104}
4105
4106
4107/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4108static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4109{
4110 PDMDEV_ASSERT_DEVINS(pDevIns);
4111 PVM pVM = pDevIns->Internal.s.pVMR3;
4112 VM_ASSERT_EMT(pVM);
4113 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
4114 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
4115
4116 /*
4117 * We postpone this operation because we're likely to be inside a I/O instruction
4118 * and the EIP will be updated when we return.
4119 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
4120 */
4121 bool fHaltOnReset;
4122 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
4123 if (RT_SUCCESS(rc) && fHaltOnReset)
4124 {
4125 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
4126 rc = VINF_EM_HALT;
4127 }
4128 else
4129 {
4130 pVM->pdm.s.fResetFlags = fFlags;
4131 VM_FF_SET(pVM, VM_FF_RESET);
4132 rc = VINF_EM_RESET;
4133 }
4134
4135 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4136 return rc;
4137}
4138
4139
4140/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4141static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
4142{
4143 int rc;
4144 PDMDEV_ASSERT_DEVINS(pDevIns);
4145 PVM pVM = pDevIns->Internal.s.pVMR3;
4146 VM_ASSERT_EMT(pVM);
4147 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
4148 pDevIns->pReg->szName, pDevIns->iInstance));
4149
4150 /** @todo Always take the SMP path - fewer code paths. */
4151 if (pVM->cCpus > 1)
4152 {
4153 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
4154 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
4155 AssertRC(rc);
4156 rc = VINF_EM_SUSPEND;
4157 }
4158 else
4159 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
4160
4161 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4162 return rc;
4163}
4164
4165
4166/**
4167 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
4168 * EMT request to avoid deadlocks.
4169 *
4170 * @returns VBox status code fit for scheduling.
4171 * @param pVM The cross context VM structure.
4172 * @param pDevIns The device that triggered this action.
4173 */
4174static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
4175{
4176 /*
4177 * Suspend the VM first then do the saving.
4178 */
4179 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
4180 if (RT_SUCCESS(rc))
4181 {
4182 PUVM pUVM = pVM->pUVM;
4183 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
4184
4185 /*
4186 * On success, power off the VM, on failure we'll leave it suspended.
4187 */
4188 if (RT_SUCCESS(rc))
4189 {
4190 rc = VMR3PowerOff(pVM->pUVM);
4191 if (RT_FAILURE(rc))
4192 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
4193 }
4194 else
4195 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
4196 }
4197 else
4198 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
4199 return rc;
4200}
4201
4202
4203/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4204static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4205{
4206 PDMDEV_ASSERT_DEVINS(pDevIns);
4207 PVM pVM = pDevIns->Internal.s.pVMR3;
4208 VM_ASSERT_EMT(pVM);
4209 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
4210 pDevIns->pReg->szName, pDevIns->iInstance));
4211
4212 int rc;
4213 if ( pVM->pUVM->pVmm2UserMethods
4214 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
4215 {
4216 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
4217 if (RT_SUCCESS(rc))
4218 {
4219 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
4220 rc = VINF_EM_SUSPEND;
4221 }
4222 }
4223 else
4224 rc = VERR_NOT_SUPPORTED;
4225
4226 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4227 return rc;
4228}
4229
4230
4231/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4232static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
4233{
4234 int rc;
4235 PDMDEV_ASSERT_DEVINS(pDevIns);
4236 PVM pVM = pDevIns->Internal.s.pVMR3;
4237 VM_ASSERT_EMT(pVM);
4238 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
4239 pDevIns->pReg->szName, pDevIns->iInstance));
4240
4241 /** @todo Always take the SMP path - fewer code paths. */
4242 if (pVM->cCpus > 1)
4243 {
4244 /* We might be holding locks here and could cause a deadlock since
4245 VMR3PowerOff rendezvous with the other CPUs. */
4246 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
4247 AssertRC(rc);
4248 /* Set the VCPU state to stopped here as well to make sure no
4249 inconsistency with the EM state occurs. */
4250 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
4251 rc = VINF_EM_OFF;
4252 }
4253 else
4254 rc = VMR3PowerOff(pVM->pUVM);
4255
4256 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4257 return rc;
4258}
4259
4260
4261/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4262static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
4263{
4264 PDMDEV_ASSERT_DEVINS(pDevIns);
4265 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4266
4267 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
4268
4269 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
4270 return fRc;
4271}
4272
4273
4274/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4275static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4276{
4277 PDMDEV_ASSERT_DEVINS(pDevIns);
4278 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4279 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
4280 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
4281}
4282
4283
4284/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4285static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4286 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4287{
4288 PDMDEV_ASSERT_DEVINS(pDevIns);
4289 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4290
4291 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
4292 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
4293 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
4294
4295 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
4296
4297 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
4298 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
4299}
4300
4301
4302/**
4303 * The device helper structure for trusted devices.
4304 */
4305const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
4306{
4307 PDM_DEVHLPR3_VERSION,
4308 pdmR3DevHlp_IoPortCreateEx,
4309 pdmR3DevHlp_IoPortMap,
4310 pdmR3DevHlp_IoPortUnmap,
4311 pdmR3DevHlp_IoPortGetMappingAddress,
4312 pdmR3DevHlp_MmioCreateEx,
4313 pdmR3DevHlp_MmioMap,
4314 pdmR3DevHlp_MmioUnmap,
4315 pdmR3DevHlp_MmioReduce,
4316 pdmR3DevHlp_MmioGetMappingAddress,
4317 pdmR3DevHlp_Mmio2Create,
4318 pdmR3DevHlp_Mmio2Destroy,
4319 pdmR3DevHlp_Mmio2Map,
4320 pdmR3DevHlp_Mmio2Unmap,
4321 pdmR3DevHlp_Mmio2Reduce,
4322 pdmR3DevHlp_Mmio2GetMappingAddress,
4323 pdmR3DevHlp_Mmio2ChangeRegionNo,
4324 pdmR3DevHlp_ROMRegister,
4325 pdmR3DevHlp_ROMProtectShadow,
4326 pdmR3DevHlp_SSMRegister,
4327 SSMR3PutStruct,
4328 SSMR3PutStructEx,
4329 SSMR3PutBool,
4330 SSMR3PutU8,
4331 SSMR3PutS8,
4332 SSMR3PutU16,
4333 SSMR3PutS16,
4334 SSMR3PutU32,
4335 SSMR3PutS32,
4336 SSMR3PutU64,
4337 SSMR3PutS64,
4338 SSMR3PutU128,
4339 SSMR3PutS128,
4340 SSMR3PutUInt,
4341 SSMR3PutSInt,
4342 SSMR3PutGCUInt,
4343 SSMR3PutGCUIntReg,
4344 SSMR3PutGCPhys32,
4345 SSMR3PutGCPhys64,
4346 SSMR3PutGCPhys,
4347 SSMR3PutGCPtr,
4348 SSMR3PutGCUIntPtr,
4349 SSMR3PutRCPtr,
4350 SSMR3PutIOPort,
4351 SSMR3PutSel,
4352 SSMR3PutMem,
4353 SSMR3PutStrZ,
4354 SSMR3GetStruct,
4355 SSMR3GetStructEx,
4356 SSMR3GetBool,
4357 SSMR3GetBoolV,
4358 SSMR3GetU8,
4359 SSMR3GetU8V,
4360 SSMR3GetS8,
4361 SSMR3GetS8V,
4362 SSMR3GetU16,
4363 SSMR3GetU16V,
4364 SSMR3GetS16,
4365 SSMR3GetS16V,
4366 SSMR3GetU32,
4367 SSMR3GetU32V,
4368 SSMR3GetS32,
4369 SSMR3GetS32V,
4370 SSMR3GetU64,
4371 SSMR3GetU64V,
4372 SSMR3GetS64,
4373 SSMR3GetS64V,
4374 SSMR3GetU128,
4375 SSMR3GetU128V,
4376 SSMR3GetS128,
4377 SSMR3GetS128V,
4378 SSMR3GetGCPhys32,
4379 SSMR3GetGCPhys32V,
4380 SSMR3GetGCPhys64,
4381 SSMR3GetGCPhys64V,
4382 SSMR3GetGCPhys,
4383 SSMR3GetGCPhysV,
4384 SSMR3GetUInt,
4385 SSMR3GetSInt,
4386 SSMR3GetGCUInt,
4387 SSMR3GetGCUIntReg,
4388 SSMR3GetGCPtr,
4389 SSMR3GetGCUIntPtr,
4390 SSMR3GetRCPtr,
4391 SSMR3GetIOPort,
4392 SSMR3GetSel,
4393 SSMR3GetMem,
4394 SSMR3GetStrZ,
4395 SSMR3GetStrZEx,
4396 SSMR3Skip,
4397 SSMR3SkipToEndOfUnit,
4398 SSMR3SetLoadError,
4399 SSMR3SetLoadErrorV,
4400 SSMR3SetCfgError,
4401 SSMR3SetCfgErrorV,
4402 SSMR3HandleGetStatus,
4403 SSMR3HandleGetAfter,
4404 SSMR3HandleIsLiveSave,
4405 SSMR3HandleMaxDowntime,
4406 SSMR3HandleHostBits,
4407 SSMR3HandleRevision,
4408 SSMR3HandleVersion,
4409 SSMR3HandleHostOSAndArch,
4410 pdmR3DevHlp_TimerCreate,
4411 pdmR3DevHlp_TimerFromMicro,
4412 pdmR3DevHlp_TimerFromMilli,
4413 pdmR3DevHlp_TimerFromNano,
4414 pdmR3DevHlp_TimerGet,
4415 pdmR3DevHlp_TimerGetFreq,
4416 pdmR3DevHlp_TimerGetNano,
4417 pdmR3DevHlp_TimerIsActive,
4418 pdmR3DevHlp_TimerIsLockOwner,
4419 pdmR3DevHlp_TimerLockClock,
4420 pdmR3DevHlp_TimerLockClock2,
4421 pdmR3DevHlp_TimerSet,
4422 pdmR3DevHlp_TimerSetFrequencyHint,
4423 pdmR3DevHlp_TimerSetMicro,
4424 pdmR3DevHlp_TimerSetMillies,
4425 pdmR3DevHlp_TimerSetNano,
4426 pdmR3DevHlp_TimerSetRelative,
4427 pdmR3DevHlp_TimerStop,
4428 pdmR3DevHlp_TimerUnlockClock,
4429 pdmR3DevHlp_TimerUnlockClock2,
4430 pdmR3DevHlp_TimerSetCritSect,
4431 pdmR3DevHlp_TimerSave,
4432 pdmR3DevHlp_TimerLoad,
4433 pdmR3DevHlp_TimerDestroy,
4434 TMR3TimerSkip,
4435 pdmR3DevHlp_TMUtcNow,
4436 CFGMR3Exists,
4437 CFGMR3QueryType,
4438 CFGMR3QuerySize,
4439 CFGMR3QueryInteger,
4440 CFGMR3QueryIntegerDef,
4441 CFGMR3QueryString,
4442 CFGMR3QueryStringDef,
4443 CFGMR3QueryBytes,
4444 CFGMR3QueryU64,
4445 CFGMR3QueryU64Def,
4446 CFGMR3QueryS64,
4447 CFGMR3QueryS64Def,
4448 CFGMR3QueryU32,
4449 CFGMR3QueryU32Def,
4450 CFGMR3QueryS32,
4451 CFGMR3QueryS32Def,
4452 CFGMR3QueryU16,
4453 CFGMR3QueryU16Def,
4454 CFGMR3QueryS16,
4455 CFGMR3QueryS16Def,
4456 CFGMR3QueryU8,
4457 CFGMR3QueryU8Def,
4458 CFGMR3QueryS8,
4459 CFGMR3QueryS8Def,
4460 CFGMR3QueryBool,
4461 CFGMR3QueryBoolDef,
4462 CFGMR3QueryPort,
4463 CFGMR3QueryPortDef,
4464 CFGMR3QueryUInt,
4465 CFGMR3QueryUIntDef,
4466 CFGMR3QuerySInt,
4467 CFGMR3QuerySIntDef,
4468 CFGMR3QueryPtr,
4469 CFGMR3QueryPtrDef,
4470 CFGMR3QueryGCPtr,
4471 CFGMR3QueryGCPtrDef,
4472 CFGMR3QueryGCPtrU,
4473 CFGMR3QueryGCPtrUDef,
4474 CFGMR3QueryGCPtrS,
4475 CFGMR3QueryGCPtrSDef,
4476 CFGMR3QueryStringAlloc,
4477 CFGMR3QueryStringAllocDef,
4478 CFGMR3GetParent,
4479 CFGMR3GetChild,
4480 CFGMR3GetChildF,
4481 CFGMR3GetChildFV,
4482 CFGMR3GetFirstChild,
4483 CFGMR3GetNextChild,
4484 CFGMR3GetName,
4485 CFGMR3GetNameLen,
4486 CFGMR3AreChildrenValid,
4487 CFGMR3GetFirstValue,
4488 CFGMR3GetNextValue,
4489 CFGMR3GetValueName,
4490 CFGMR3GetValueNameLen,
4491 CFGMR3GetValueType,
4492 CFGMR3AreValuesValid,
4493 CFGMR3ValidateConfig,
4494 pdmR3DevHlp_PhysRead,
4495 pdmR3DevHlp_PhysWrite,
4496 pdmR3DevHlp_PhysGCPhys2CCPtr,
4497 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4498 pdmR3DevHlp_PhysReleasePageMappingLock,
4499 pdmR3DevHlp_PhysReadGCVirt,
4500 pdmR3DevHlp_PhysWriteGCVirt,
4501 pdmR3DevHlp_PhysGCPtr2GCPhys,
4502 pdmR3DevHlp_MMHeapAlloc,
4503 pdmR3DevHlp_MMHeapAllocZ,
4504 pdmR3DevHlp_MMHeapFree,
4505 pdmR3DevHlp_VMState,
4506 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4507 pdmR3DevHlp_VMSetError,
4508 pdmR3DevHlp_VMSetErrorV,
4509 pdmR3DevHlp_VMSetRuntimeError,
4510 pdmR3DevHlp_VMSetRuntimeErrorV,
4511 pdmR3DevHlp_DBGFStopV,
4512 pdmR3DevHlp_DBGFInfoRegister,
4513 pdmR3DevHlp_DBGFInfoRegisterArgv,
4514 pdmR3DevHlp_DBGFRegRegister,
4515 pdmR3DevHlp_DBGFTraceBuf,
4516 pdmR3DevHlp_STAMRegister,
4517 pdmR3DevHlp_STAMRegisterV,
4518 pdmR3DevHlp_PCIRegister,
4519 pdmR3DevHlp_PCIRegisterMsi,
4520 pdmR3DevHlp_PCIIORegionRegister,
4521 pdmR3DevHlp_PCIInterceptConfigAccesses,
4522 pdmR3DevHlp_PCIConfigWrite,
4523 pdmR3DevHlp_PCIConfigRead,
4524 pdmR3DevHlp_PCIPhysRead,
4525 pdmR3DevHlp_PCIPhysWrite,
4526 pdmR3DevHlp_PCIPhysGCPhys2CCPtr,
4527 pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly,
4528 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr,
4529 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly,
4530 pdmR3DevHlp_PCISetIrq,
4531 pdmR3DevHlp_PCISetIrqNoWait,
4532 pdmR3DevHlp_ISASetIrq,
4533 pdmR3DevHlp_ISASetIrqNoWait,
4534 pdmR3DevHlp_DriverAttach,
4535 pdmR3DevHlp_DriverDetach,
4536 pdmR3DevHlp_DriverReconfigure,
4537 pdmR3DevHlp_QueueCreatePtr,
4538 pdmR3DevHlp_QueueCreate,
4539 pdmR3DevHlp_QueueToPtr,
4540 pdmR3DevHlp_QueueAlloc,
4541 pdmR3DevHlp_QueueInsert,
4542 pdmR3DevHlp_QueueInsertEx,
4543 pdmR3DevHlp_QueueFlushIfNecessary,
4544 pdmR3DevHlp_TaskCreate,
4545 pdmR3DevHlp_TaskTrigger,
4546 pdmR3DevHlp_SUPSemEventCreate,
4547 pdmR3DevHlp_SUPSemEventClose,
4548 pdmR3DevHlp_SUPSemEventSignal,
4549 pdmR3DevHlp_SUPSemEventWaitNoResume,
4550 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4551 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4552 pdmR3DevHlp_SUPSemEventGetResolution,
4553 pdmR3DevHlp_SUPSemEventMultiCreate,
4554 pdmR3DevHlp_SUPSemEventMultiClose,
4555 pdmR3DevHlp_SUPSemEventMultiSignal,
4556 pdmR3DevHlp_SUPSemEventMultiReset,
4557 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4558 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4559 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4560 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4561 pdmR3DevHlp_CritSectInit,
4562 pdmR3DevHlp_CritSectGetNop,
4563 pdmR3DevHlp_CritSectGetNopR0,
4564 pdmR3DevHlp_CritSectGetNopRC,
4565 pdmR3DevHlp_SetDeviceCritSect,
4566 pdmR3DevHlp_CritSectYield,
4567 pdmR3DevHlp_CritSectEnter,
4568 pdmR3DevHlp_CritSectEnterDebug,
4569 pdmR3DevHlp_CritSectTryEnter,
4570 pdmR3DevHlp_CritSectTryEnterDebug,
4571 pdmR3DevHlp_CritSectLeave,
4572 pdmR3DevHlp_CritSectIsOwner,
4573 pdmR3DevHlp_CritSectIsInitialized,
4574 pdmR3DevHlp_CritSectHasWaiters,
4575 pdmR3DevHlp_CritSectGetRecursion,
4576 pdmR3DevHlp_CritSectScheduleExitEvent,
4577 pdmR3DevHlp_CritSectDelete,
4578 pdmR3DevHlp_CritSectRwInit,
4579 pdmR3DevHlp_CritSectRwDelete,
4580 pdmR3DevHlp_CritSectRwEnterShared,
4581 pdmR3DevHlp_CritSectRwEnterSharedDebug,
4582 pdmR3DevHlp_CritSectRwTryEnterShared,
4583 pdmR3DevHlp_CritSectRwTryEnterSharedDebug,
4584 pdmR3DevHlp_CritSectRwLeaveShared,
4585 pdmR3DevHlp_CritSectRwEnterExcl,
4586 pdmR3DevHlp_CritSectRwEnterExclDebug,
4587 pdmR3DevHlp_CritSectRwTryEnterExcl,
4588 pdmR3DevHlp_CritSectRwTryEnterExclDebug,
4589 pdmR3DevHlp_CritSectRwLeaveExcl,
4590 pdmR3DevHlp_CritSectRwIsWriteOwner,
4591 pdmR3DevHlp_CritSectRwIsReadOwner,
4592 pdmR3DevHlp_CritSectRwGetWriteRecursion,
4593 pdmR3DevHlp_CritSectRwGetWriterReadRecursion,
4594 pdmR3DevHlp_CritSectRwGetReadCount,
4595 pdmR3DevHlp_CritSectRwIsInitialized,
4596 pdmR3DevHlp_ThreadCreate,
4597 PDMR3ThreadDestroy,
4598 PDMR3ThreadIAmSuspending,
4599 PDMR3ThreadIAmRunning,
4600 PDMR3ThreadSleep,
4601 PDMR3ThreadSuspend,
4602 PDMR3ThreadResume,
4603 pdmR3DevHlp_SetAsyncNotification,
4604 pdmR3DevHlp_AsyncNotificationCompleted,
4605 pdmR3DevHlp_RTCRegister,
4606 pdmR3DevHlp_PCIBusRegister,
4607 pdmR3DevHlp_IommuRegister,
4608 pdmR3DevHlp_PICRegister,
4609 pdmR3DevHlp_ApicRegister,
4610 pdmR3DevHlp_IoApicRegister,
4611 pdmR3DevHlp_HpetRegister,
4612 pdmR3DevHlp_PciRawRegister,
4613 pdmR3DevHlp_DMACRegister,
4614 pdmR3DevHlp_DMARegister,
4615 pdmR3DevHlp_DMAReadMemory,
4616 pdmR3DevHlp_DMAWriteMemory,
4617 pdmR3DevHlp_DMASetDREQ,
4618 pdmR3DevHlp_DMAGetChannelMode,
4619 pdmR3DevHlp_DMASchedule,
4620 pdmR3DevHlp_CMOSWrite,
4621 pdmR3DevHlp_CMOSRead,
4622 pdmR3DevHlp_AssertEMT,
4623 pdmR3DevHlp_AssertOther,
4624 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4625 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4626 pdmR3DevHlp_CallR0,
4627 pdmR3DevHlp_VMGetSuspendReason,
4628 pdmR3DevHlp_VMGetResumeReason,
4629 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4630 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4631 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4632 pdmR3DevHlp_CpuGetGuestMicroarch,
4633 pdmR3DevHlp_CpuGetGuestAddrWidths,
4634 pdmR3DevHlp_STAMDeregisterByPrefix,
4635 0,
4636 0,
4637 0,
4638 0,
4639 0,
4640 0,
4641 0,
4642 0,
4643 0,
4644 pdmR3DevHlp_GetUVM,
4645 pdmR3DevHlp_GetVM,
4646 pdmR3DevHlp_GetVMCPU,
4647 pdmR3DevHlp_GetCurrentCpuId,
4648 pdmR3DevHlp_RegisterVMMDevHeap,
4649 pdmR3DevHlp_FirmwareRegister,
4650 pdmR3DevHlp_VMReset,
4651 pdmR3DevHlp_VMSuspend,
4652 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4653 pdmR3DevHlp_VMPowerOff,
4654 pdmR3DevHlp_A20IsEnabled,
4655 pdmR3DevHlp_A20Set,
4656 pdmR3DevHlp_GetCpuId,
4657 pdmR3DevHlp_TMTimeVirtGet,
4658 pdmR3DevHlp_TMTimeVirtGetFreq,
4659 pdmR3DevHlp_TMTimeVirtGetNano,
4660 pdmR3DevHlp_GetSupDrvSession,
4661 pdmR3DevHlp_QueryGenericUserObject,
4662 pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
4663 PDM_DEVHLPR3_VERSION /* the end */
4664};
4665
4666
4667#ifdef VBOX_WITH_DBGF_TRACING
4668/**
4669 * The device helper structure for trusted devices - tracing variant.
4670 */
4671const PDMDEVHLPR3 g_pdmR3DevHlpTracing =
4672{
4673 PDM_DEVHLPR3_VERSION,
4674 pdmR3DevHlpTracing_IoPortCreateEx,
4675 pdmR3DevHlpTracing_IoPortMap,
4676 pdmR3DevHlpTracing_IoPortUnmap,
4677 pdmR3DevHlp_IoPortGetMappingAddress,
4678 pdmR3DevHlpTracing_MmioCreateEx,
4679 pdmR3DevHlpTracing_MmioMap,
4680 pdmR3DevHlpTracing_MmioUnmap,
4681 pdmR3DevHlp_MmioReduce,
4682 pdmR3DevHlp_MmioGetMappingAddress,
4683 pdmR3DevHlp_Mmio2Create,
4684 pdmR3DevHlp_Mmio2Destroy,
4685 pdmR3DevHlp_Mmio2Map,
4686 pdmR3DevHlp_Mmio2Unmap,
4687 pdmR3DevHlp_Mmio2Reduce,
4688 pdmR3DevHlp_Mmio2GetMappingAddress,
4689 pdmR3DevHlp_Mmio2ChangeRegionNo,
4690 pdmR3DevHlp_ROMRegister,
4691 pdmR3DevHlp_ROMProtectShadow,
4692 pdmR3DevHlp_SSMRegister,
4693 SSMR3PutStruct,
4694 SSMR3PutStructEx,
4695 SSMR3PutBool,
4696 SSMR3PutU8,
4697 SSMR3PutS8,
4698 SSMR3PutU16,
4699 SSMR3PutS16,
4700 SSMR3PutU32,
4701 SSMR3PutS32,
4702 SSMR3PutU64,
4703 SSMR3PutS64,
4704 SSMR3PutU128,
4705 SSMR3PutS128,
4706 SSMR3PutUInt,
4707 SSMR3PutSInt,
4708 SSMR3PutGCUInt,
4709 SSMR3PutGCUIntReg,
4710 SSMR3PutGCPhys32,
4711 SSMR3PutGCPhys64,
4712 SSMR3PutGCPhys,
4713 SSMR3PutGCPtr,
4714 SSMR3PutGCUIntPtr,
4715 SSMR3PutRCPtr,
4716 SSMR3PutIOPort,
4717 SSMR3PutSel,
4718 SSMR3PutMem,
4719 SSMR3PutStrZ,
4720 SSMR3GetStruct,
4721 SSMR3GetStructEx,
4722 SSMR3GetBool,
4723 SSMR3GetBoolV,
4724 SSMR3GetU8,
4725 SSMR3GetU8V,
4726 SSMR3GetS8,
4727 SSMR3GetS8V,
4728 SSMR3GetU16,
4729 SSMR3GetU16V,
4730 SSMR3GetS16,
4731 SSMR3GetS16V,
4732 SSMR3GetU32,
4733 SSMR3GetU32V,
4734 SSMR3GetS32,
4735 SSMR3GetS32V,
4736 SSMR3GetU64,
4737 SSMR3GetU64V,
4738 SSMR3GetS64,
4739 SSMR3GetS64V,
4740 SSMR3GetU128,
4741 SSMR3GetU128V,
4742 SSMR3GetS128,
4743 SSMR3GetS128V,
4744 SSMR3GetGCPhys32,
4745 SSMR3GetGCPhys32V,
4746 SSMR3GetGCPhys64,
4747 SSMR3GetGCPhys64V,
4748 SSMR3GetGCPhys,
4749 SSMR3GetGCPhysV,
4750 SSMR3GetUInt,
4751 SSMR3GetSInt,
4752 SSMR3GetGCUInt,
4753 SSMR3GetGCUIntReg,
4754 SSMR3GetGCPtr,
4755 SSMR3GetGCUIntPtr,
4756 SSMR3GetRCPtr,
4757 SSMR3GetIOPort,
4758 SSMR3GetSel,
4759 SSMR3GetMem,
4760 SSMR3GetStrZ,
4761 SSMR3GetStrZEx,
4762 SSMR3Skip,
4763 SSMR3SkipToEndOfUnit,
4764 SSMR3SetLoadError,
4765 SSMR3SetLoadErrorV,
4766 SSMR3SetCfgError,
4767 SSMR3SetCfgErrorV,
4768 SSMR3HandleGetStatus,
4769 SSMR3HandleGetAfter,
4770 SSMR3HandleIsLiveSave,
4771 SSMR3HandleMaxDowntime,
4772 SSMR3HandleHostBits,
4773 SSMR3HandleRevision,
4774 SSMR3HandleVersion,
4775 SSMR3HandleHostOSAndArch,
4776 pdmR3DevHlp_TimerCreate,
4777 pdmR3DevHlp_TimerFromMicro,
4778 pdmR3DevHlp_TimerFromMilli,
4779 pdmR3DevHlp_TimerFromNano,
4780 pdmR3DevHlp_TimerGet,
4781 pdmR3DevHlp_TimerGetFreq,
4782 pdmR3DevHlp_TimerGetNano,
4783 pdmR3DevHlp_TimerIsActive,
4784 pdmR3DevHlp_TimerIsLockOwner,
4785 pdmR3DevHlp_TimerLockClock,
4786 pdmR3DevHlp_TimerLockClock2,
4787 pdmR3DevHlp_TimerSet,
4788 pdmR3DevHlp_TimerSetFrequencyHint,
4789 pdmR3DevHlp_TimerSetMicro,
4790 pdmR3DevHlp_TimerSetMillies,
4791 pdmR3DevHlp_TimerSetNano,
4792 pdmR3DevHlp_TimerSetRelative,
4793 pdmR3DevHlp_TimerStop,
4794 pdmR3DevHlp_TimerUnlockClock,
4795 pdmR3DevHlp_TimerUnlockClock2,
4796 pdmR3DevHlp_TimerSetCritSect,
4797 pdmR3DevHlp_TimerSave,
4798 pdmR3DevHlp_TimerLoad,
4799 pdmR3DevHlp_TimerDestroy,
4800 TMR3TimerSkip,
4801 pdmR3DevHlp_TMUtcNow,
4802 CFGMR3Exists,
4803 CFGMR3QueryType,
4804 CFGMR3QuerySize,
4805 CFGMR3QueryInteger,
4806 CFGMR3QueryIntegerDef,
4807 CFGMR3QueryString,
4808 CFGMR3QueryStringDef,
4809 CFGMR3QueryBytes,
4810 CFGMR3QueryU64,
4811 CFGMR3QueryU64Def,
4812 CFGMR3QueryS64,
4813 CFGMR3QueryS64Def,
4814 CFGMR3QueryU32,
4815 CFGMR3QueryU32Def,
4816 CFGMR3QueryS32,
4817 CFGMR3QueryS32Def,
4818 CFGMR3QueryU16,
4819 CFGMR3QueryU16Def,
4820 CFGMR3QueryS16,
4821 CFGMR3QueryS16Def,
4822 CFGMR3QueryU8,
4823 CFGMR3QueryU8Def,
4824 CFGMR3QueryS8,
4825 CFGMR3QueryS8Def,
4826 CFGMR3QueryBool,
4827 CFGMR3QueryBoolDef,
4828 CFGMR3QueryPort,
4829 CFGMR3QueryPortDef,
4830 CFGMR3QueryUInt,
4831 CFGMR3QueryUIntDef,
4832 CFGMR3QuerySInt,
4833 CFGMR3QuerySIntDef,
4834 CFGMR3QueryPtr,
4835 CFGMR3QueryPtrDef,
4836 CFGMR3QueryGCPtr,
4837 CFGMR3QueryGCPtrDef,
4838 CFGMR3QueryGCPtrU,
4839 CFGMR3QueryGCPtrUDef,
4840 CFGMR3QueryGCPtrS,
4841 CFGMR3QueryGCPtrSDef,
4842 CFGMR3QueryStringAlloc,
4843 CFGMR3QueryStringAllocDef,
4844 CFGMR3GetParent,
4845 CFGMR3GetChild,
4846 CFGMR3GetChildF,
4847 CFGMR3GetChildFV,
4848 CFGMR3GetFirstChild,
4849 CFGMR3GetNextChild,
4850 CFGMR3GetName,
4851 CFGMR3GetNameLen,
4852 CFGMR3AreChildrenValid,
4853 CFGMR3GetFirstValue,
4854 CFGMR3GetNextValue,
4855 CFGMR3GetValueName,
4856 CFGMR3GetValueNameLen,
4857 CFGMR3GetValueType,
4858 CFGMR3AreValuesValid,
4859 CFGMR3ValidateConfig,
4860 pdmR3DevHlpTracing_PhysRead,
4861 pdmR3DevHlpTracing_PhysWrite,
4862 pdmR3DevHlp_PhysGCPhys2CCPtr,
4863 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4864 pdmR3DevHlp_PhysReleasePageMappingLock,
4865 pdmR3DevHlp_PhysReadGCVirt,
4866 pdmR3DevHlp_PhysWriteGCVirt,
4867 pdmR3DevHlp_PhysGCPtr2GCPhys,
4868 pdmR3DevHlp_MMHeapAlloc,
4869 pdmR3DevHlp_MMHeapAllocZ,
4870 pdmR3DevHlp_MMHeapFree,
4871 pdmR3DevHlp_VMState,
4872 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4873 pdmR3DevHlp_VMSetError,
4874 pdmR3DevHlp_VMSetErrorV,
4875 pdmR3DevHlp_VMSetRuntimeError,
4876 pdmR3DevHlp_VMSetRuntimeErrorV,
4877 pdmR3DevHlp_DBGFStopV,
4878 pdmR3DevHlp_DBGFInfoRegister,
4879 pdmR3DevHlp_DBGFInfoRegisterArgv,
4880 pdmR3DevHlp_DBGFRegRegister,
4881 pdmR3DevHlp_DBGFTraceBuf,
4882 pdmR3DevHlp_STAMRegister,
4883 pdmR3DevHlp_STAMRegisterV,
4884 pdmR3DevHlp_PCIRegister,
4885 pdmR3DevHlp_PCIRegisterMsi,
4886 pdmR3DevHlp_PCIIORegionRegister,
4887 pdmR3DevHlp_PCIInterceptConfigAccesses,
4888 pdmR3DevHlp_PCIConfigWrite,
4889 pdmR3DevHlp_PCIConfigRead,
4890 pdmR3DevHlpTracing_PCIPhysRead,
4891 pdmR3DevHlpTracing_PCIPhysWrite,
4892 pdmR3DevHlp_PCIPhysGCPhys2CCPtr,
4893 pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly,
4894 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr,
4895 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly,
4896 pdmR3DevHlpTracing_PCISetIrq,
4897 pdmR3DevHlpTracing_PCISetIrqNoWait,
4898 pdmR3DevHlpTracing_ISASetIrq,
4899 pdmR3DevHlpTracing_ISASetIrqNoWait,
4900 pdmR3DevHlp_DriverAttach,
4901 pdmR3DevHlp_DriverDetach,
4902 pdmR3DevHlp_DriverReconfigure,
4903 pdmR3DevHlp_QueueCreatePtr,
4904 pdmR3DevHlp_QueueCreate,
4905 pdmR3DevHlp_QueueToPtr,
4906 pdmR3DevHlp_QueueAlloc,
4907 pdmR3DevHlp_QueueInsert,
4908 pdmR3DevHlp_QueueInsertEx,
4909 pdmR3DevHlp_QueueFlushIfNecessary,
4910 pdmR3DevHlp_TaskCreate,
4911 pdmR3DevHlp_TaskTrigger,
4912 pdmR3DevHlp_SUPSemEventCreate,
4913 pdmR3DevHlp_SUPSemEventClose,
4914 pdmR3DevHlp_SUPSemEventSignal,
4915 pdmR3DevHlp_SUPSemEventWaitNoResume,
4916 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4917 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4918 pdmR3DevHlp_SUPSemEventGetResolution,
4919 pdmR3DevHlp_SUPSemEventMultiCreate,
4920 pdmR3DevHlp_SUPSemEventMultiClose,
4921 pdmR3DevHlp_SUPSemEventMultiSignal,
4922 pdmR3DevHlp_SUPSemEventMultiReset,
4923 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4924 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4925 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4926 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4927 pdmR3DevHlp_CritSectInit,
4928 pdmR3DevHlp_CritSectGetNop,
4929 pdmR3DevHlp_CritSectGetNopR0,
4930 pdmR3DevHlp_CritSectGetNopRC,
4931 pdmR3DevHlp_SetDeviceCritSect,
4932 pdmR3DevHlp_CritSectYield,
4933 pdmR3DevHlp_CritSectEnter,
4934 pdmR3DevHlp_CritSectEnterDebug,
4935 pdmR3DevHlp_CritSectTryEnter,
4936 pdmR3DevHlp_CritSectTryEnterDebug,
4937 pdmR3DevHlp_CritSectLeave,
4938 pdmR3DevHlp_CritSectIsOwner,
4939 pdmR3DevHlp_CritSectIsInitialized,
4940 pdmR3DevHlp_CritSectHasWaiters,
4941 pdmR3DevHlp_CritSectGetRecursion,
4942 pdmR3DevHlp_CritSectScheduleExitEvent,
4943 pdmR3DevHlp_CritSectDelete,
4944 pdmR3DevHlp_CritSectRwInit,
4945 pdmR3DevHlp_CritSectRwDelete,
4946 pdmR3DevHlp_CritSectRwEnterShared,
4947 pdmR3DevHlp_CritSectRwEnterSharedDebug,
4948 pdmR3DevHlp_CritSectRwTryEnterShared,
4949 pdmR3DevHlp_CritSectRwTryEnterSharedDebug,
4950 pdmR3DevHlp_CritSectRwLeaveShared,
4951 pdmR3DevHlp_CritSectRwEnterExcl,
4952 pdmR3DevHlp_CritSectRwEnterExclDebug,
4953 pdmR3DevHlp_CritSectRwTryEnterExcl,
4954 pdmR3DevHlp_CritSectRwTryEnterExclDebug,
4955 pdmR3DevHlp_CritSectRwLeaveExcl,
4956 pdmR3DevHlp_CritSectRwIsWriteOwner,
4957 pdmR3DevHlp_CritSectRwIsReadOwner,
4958 pdmR3DevHlp_CritSectRwGetWriteRecursion,
4959 pdmR3DevHlp_CritSectRwGetWriterReadRecursion,
4960 pdmR3DevHlp_CritSectRwGetReadCount,
4961 pdmR3DevHlp_CritSectRwIsInitialized,
4962 pdmR3DevHlp_ThreadCreate,
4963 PDMR3ThreadDestroy,
4964 PDMR3ThreadIAmSuspending,
4965 PDMR3ThreadIAmRunning,
4966 PDMR3ThreadSleep,
4967 PDMR3ThreadSuspend,
4968 PDMR3ThreadResume,
4969 pdmR3DevHlp_SetAsyncNotification,
4970 pdmR3DevHlp_AsyncNotificationCompleted,
4971 pdmR3DevHlp_RTCRegister,
4972 pdmR3DevHlp_PCIBusRegister,
4973 pdmR3DevHlp_IommuRegister,
4974 pdmR3DevHlp_PICRegister,
4975 pdmR3DevHlp_ApicRegister,
4976 pdmR3DevHlp_IoApicRegister,
4977 pdmR3DevHlp_HpetRegister,
4978 pdmR3DevHlp_PciRawRegister,
4979 pdmR3DevHlp_DMACRegister,
4980 pdmR3DevHlp_DMARegister,
4981 pdmR3DevHlp_DMAReadMemory,
4982 pdmR3DevHlp_DMAWriteMemory,
4983 pdmR3DevHlp_DMASetDREQ,
4984 pdmR3DevHlp_DMAGetChannelMode,
4985 pdmR3DevHlp_DMASchedule,
4986 pdmR3DevHlp_CMOSWrite,
4987 pdmR3DevHlp_CMOSRead,
4988 pdmR3DevHlp_AssertEMT,
4989 pdmR3DevHlp_AssertOther,
4990 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4991 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4992 pdmR3DevHlp_CallR0,
4993 pdmR3DevHlp_VMGetSuspendReason,
4994 pdmR3DevHlp_VMGetResumeReason,
4995 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4996 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4997 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4998 pdmR3DevHlp_CpuGetGuestMicroarch,
4999 pdmR3DevHlp_CpuGetGuestAddrWidths,
5000 pdmR3DevHlp_STAMDeregisterByPrefix,
5001 0,
5002 0,
5003 0,
5004 0,
5005 0,
5006 0,
5007 0,
5008 0,
5009 0,
5010 pdmR3DevHlp_GetUVM,
5011 pdmR3DevHlp_GetVM,
5012 pdmR3DevHlp_GetVMCPU,
5013 pdmR3DevHlp_GetCurrentCpuId,
5014 pdmR3DevHlp_RegisterVMMDevHeap,
5015 pdmR3DevHlp_FirmwareRegister,
5016 pdmR3DevHlp_VMReset,
5017 pdmR3DevHlp_VMSuspend,
5018 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
5019 pdmR3DevHlp_VMPowerOff,
5020 pdmR3DevHlp_A20IsEnabled,
5021 pdmR3DevHlp_A20Set,
5022 pdmR3DevHlp_GetCpuId,
5023 pdmR3DevHlp_TMTimeVirtGet,
5024 pdmR3DevHlp_TMTimeVirtGetFreq,
5025 pdmR3DevHlp_TMTimeVirtGetNano,
5026 pdmR3DevHlp_GetSupDrvSession,
5027 pdmR3DevHlp_QueryGenericUserObject,
5028 pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
5029 PDM_DEVHLPR3_VERSION /* the end */
5030};
5031#endif /* VBOX_WITH_DBGF_TRACING */
5032
5033
5034
5035
5036/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
5037static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
5038{
5039 PDMDEV_ASSERT_DEVINS(pDevIns);
5040 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5041 return NULL;
5042}
5043
5044
5045/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
5046static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
5047{
5048 PDMDEV_ASSERT_DEVINS(pDevIns);
5049 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5050 return NULL;
5051}
5052
5053
5054/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
5055static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
5056{
5057 PDMDEV_ASSERT_DEVINS(pDevIns);
5058 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5059 return NULL;
5060}
5061
5062
5063/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
5064static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(PPDMDEVINS pDevIns)
5065{
5066 PDMDEV_ASSERT_DEVINS(pDevIns);
5067 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5068 return NIL_VMCPUID;
5069}
5070
5071
5072/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
5073static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
5074 RTR3PTR pvHeap, unsigned cbHeap)
5075{
5076 PDMDEV_ASSERT_DEVINS(pDevIns);
5077 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
5078 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5079 return VERR_ACCESS_DENIED;
5080}
5081
5082
5083/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
5084static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
5085{
5086 PDMDEV_ASSERT_DEVINS(pDevIns);
5087 NOREF(pFwReg); NOREF(ppFwHlp);
5088 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5089 return VERR_ACCESS_DENIED;
5090}
5091
5092
5093/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
5094static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
5095{
5096 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
5097 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5098 return VERR_ACCESS_DENIED;
5099}
5100
5101
5102/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
5103static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
5104{
5105 PDMDEV_ASSERT_DEVINS(pDevIns);
5106 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5107 return VERR_ACCESS_DENIED;
5108}
5109
5110
5111/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
5112static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
5113{
5114 PDMDEV_ASSERT_DEVINS(pDevIns);
5115 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5116 return VERR_ACCESS_DENIED;
5117}
5118
5119
5120/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
5121static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
5122{
5123 PDMDEV_ASSERT_DEVINS(pDevIns);
5124 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5125 return VERR_ACCESS_DENIED;
5126}
5127
5128
5129/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
5130static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
5131{
5132 PDMDEV_ASSERT_DEVINS(pDevIns);
5133 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5134 return false;
5135}
5136
5137
5138/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
5139static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
5140{
5141 PDMDEV_ASSERT_DEVINS(pDevIns);
5142 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5143 NOREF(fEnable);
5144}
5145
5146
5147/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
5148static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
5149 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
5150{
5151 PDMDEV_ASSERT_DEVINS(pDevIns);
5152 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
5153 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5154}
5155
5156
5157/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
5158static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(PPDMDEVINS pDevIns)
5159{
5160 PDMDEV_ASSERT_DEVINS(pDevIns);
5161 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
5162 return (PSUPDRVSESSION)0;
5163}
5164
5165
5166/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
5167static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
5168{
5169 PDMDEV_ASSERT_DEVINS(pDevIns);
5170 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
5171 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
5172 return NULL;
5173}
5174
5175
5176/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalTypeRegister} */
5177static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
5178 R3PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR3,
5179 const char *pszHandlerR0, const char *pszPfHandlerR0,
5180 const char *pszHandlerRC, const char *pszPfHandlerRC,
5181 const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
5182{
5183 PDMDEV_ASSERT_DEVINS(pDevIns);
5184 RT_NOREF(enmKind, pfnHandlerR3, pszHandlerR0, pszPfHandlerR0, pszHandlerRC, pszPfHandlerRC, pszDesc, phType);
5185 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
5186 pDevIns->pReg->szName, pDevIns->iInstance));
5187 return VERR_ACCESS_DENIED;
5188}
5189
5190
5191/**
5192 * The device helper structure for non-trusted devices.
5193 */
5194const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
5195{
5196 PDM_DEVHLPR3_VERSION,
5197 pdmR3DevHlp_IoPortCreateEx,
5198 pdmR3DevHlp_IoPortMap,
5199 pdmR3DevHlp_IoPortUnmap,
5200 pdmR3DevHlp_IoPortGetMappingAddress,
5201 pdmR3DevHlp_MmioCreateEx,
5202 pdmR3DevHlp_MmioMap,
5203 pdmR3DevHlp_MmioUnmap,
5204 pdmR3DevHlp_MmioReduce,
5205 pdmR3DevHlp_MmioGetMappingAddress,
5206 pdmR3DevHlp_Mmio2Create,
5207 pdmR3DevHlp_Mmio2Destroy,
5208 pdmR3DevHlp_Mmio2Map,
5209 pdmR3DevHlp_Mmio2Unmap,
5210 pdmR3DevHlp_Mmio2Reduce,
5211 pdmR3DevHlp_Mmio2GetMappingAddress,
5212 pdmR3DevHlp_Mmio2ChangeRegionNo,
5213 pdmR3DevHlp_ROMRegister,
5214 pdmR3DevHlp_ROMProtectShadow,
5215 pdmR3DevHlp_SSMRegister,
5216 SSMR3PutStruct,
5217 SSMR3PutStructEx,
5218 SSMR3PutBool,
5219 SSMR3PutU8,
5220 SSMR3PutS8,
5221 SSMR3PutU16,
5222 SSMR3PutS16,
5223 SSMR3PutU32,
5224 SSMR3PutS32,
5225 SSMR3PutU64,
5226 SSMR3PutS64,
5227 SSMR3PutU128,
5228 SSMR3PutS128,
5229 SSMR3PutUInt,
5230 SSMR3PutSInt,
5231 SSMR3PutGCUInt,
5232 SSMR3PutGCUIntReg,
5233 SSMR3PutGCPhys32,
5234 SSMR3PutGCPhys64,
5235 SSMR3PutGCPhys,
5236 SSMR3PutGCPtr,
5237 SSMR3PutGCUIntPtr,
5238 SSMR3PutRCPtr,
5239 SSMR3PutIOPort,
5240 SSMR3PutSel,
5241 SSMR3PutMem,
5242 SSMR3PutStrZ,
5243 SSMR3GetStruct,
5244 SSMR3GetStructEx,
5245 SSMR3GetBool,
5246 SSMR3GetBoolV,
5247 SSMR3GetU8,
5248 SSMR3GetU8V,
5249 SSMR3GetS8,
5250 SSMR3GetS8V,
5251 SSMR3GetU16,
5252 SSMR3GetU16V,
5253 SSMR3GetS16,
5254 SSMR3GetS16V,
5255 SSMR3GetU32,
5256 SSMR3GetU32V,
5257 SSMR3GetS32,
5258 SSMR3GetS32V,
5259 SSMR3GetU64,
5260 SSMR3GetU64V,
5261 SSMR3GetS64,
5262 SSMR3GetS64V,
5263 SSMR3GetU128,
5264 SSMR3GetU128V,
5265 SSMR3GetS128,
5266 SSMR3GetS128V,
5267 SSMR3GetGCPhys32,
5268 SSMR3GetGCPhys32V,
5269 SSMR3GetGCPhys64,
5270 SSMR3GetGCPhys64V,
5271 SSMR3GetGCPhys,
5272 SSMR3GetGCPhysV,
5273 SSMR3GetUInt,
5274 SSMR3GetSInt,
5275 SSMR3GetGCUInt,
5276 SSMR3GetGCUIntReg,
5277 SSMR3GetGCPtr,
5278 SSMR3GetGCUIntPtr,
5279 SSMR3GetRCPtr,
5280 SSMR3GetIOPort,
5281 SSMR3GetSel,
5282 SSMR3GetMem,
5283 SSMR3GetStrZ,
5284 SSMR3GetStrZEx,
5285 SSMR3Skip,
5286 SSMR3SkipToEndOfUnit,
5287 SSMR3SetLoadError,
5288 SSMR3SetLoadErrorV,
5289 SSMR3SetCfgError,
5290 SSMR3SetCfgErrorV,
5291 SSMR3HandleGetStatus,
5292 SSMR3HandleGetAfter,
5293 SSMR3HandleIsLiveSave,
5294 SSMR3HandleMaxDowntime,
5295 SSMR3HandleHostBits,
5296 SSMR3HandleRevision,
5297 SSMR3HandleVersion,
5298 SSMR3HandleHostOSAndArch,
5299 pdmR3DevHlp_TimerCreate,
5300 pdmR3DevHlp_TimerFromMicro,
5301 pdmR3DevHlp_TimerFromMilli,
5302 pdmR3DevHlp_TimerFromNano,
5303 pdmR3DevHlp_TimerGet,
5304 pdmR3DevHlp_TimerGetFreq,
5305 pdmR3DevHlp_TimerGetNano,
5306 pdmR3DevHlp_TimerIsActive,
5307 pdmR3DevHlp_TimerIsLockOwner,
5308 pdmR3DevHlp_TimerLockClock,
5309 pdmR3DevHlp_TimerLockClock2,
5310 pdmR3DevHlp_TimerSet,
5311 pdmR3DevHlp_TimerSetFrequencyHint,
5312 pdmR3DevHlp_TimerSetMicro,
5313 pdmR3DevHlp_TimerSetMillies,
5314 pdmR3DevHlp_TimerSetNano,
5315 pdmR3DevHlp_TimerSetRelative,
5316 pdmR3DevHlp_TimerStop,
5317 pdmR3DevHlp_TimerUnlockClock,
5318 pdmR3DevHlp_TimerUnlockClock2,
5319 pdmR3DevHlp_TimerSetCritSect,
5320 pdmR3DevHlp_TimerSave,
5321 pdmR3DevHlp_TimerLoad,
5322 pdmR3DevHlp_TimerDestroy,
5323 TMR3TimerSkip,
5324 pdmR3DevHlp_TMUtcNow,
5325 CFGMR3Exists,
5326 CFGMR3QueryType,
5327 CFGMR3QuerySize,
5328 CFGMR3QueryInteger,
5329 CFGMR3QueryIntegerDef,
5330 CFGMR3QueryString,
5331 CFGMR3QueryStringDef,
5332 CFGMR3QueryBytes,
5333 CFGMR3QueryU64,
5334 CFGMR3QueryU64Def,
5335 CFGMR3QueryS64,
5336 CFGMR3QueryS64Def,
5337 CFGMR3QueryU32,
5338 CFGMR3QueryU32Def,
5339 CFGMR3QueryS32,
5340 CFGMR3QueryS32Def,
5341 CFGMR3QueryU16,
5342 CFGMR3QueryU16Def,
5343 CFGMR3QueryS16,
5344 CFGMR3QueryS16Def,
5345 CFGMR3QueryU8,
5346 CFGMR3QueryU8Def,
5347 CFGMR3QueryS8,
5348 CFGMR3QueryS8Def,
5349 CFGMR3QueryBool,
5350 CFGMR3QueryBoolDef,
5351 CFGMR3QueryPort,
5352 CFGMR3QueryPortDef,
5353 CFGMR3QueryUInt,
5354 CFGMR3QueryUIntDef,
5355 CFGMR3QuerySInt,
5356 CFGMR3QuerySIntDef,
5357 CFGMR3QueryPtr,
5358 CFGMR3QueryPtrDef,
5359 CFGMR3QueryGCPtr,
5360 CFGMR3QueryGCPtrDef,
5361 CFGMR3QueryGCPtrU,
5362 CFGMR3QueryGCPtrUDef,
5363 CFGMR3QueryGCPtrS,
5364 CFGMR3QueryGCPtrSDef,
5365 CFGMR3QueryStringAlloc,
5366 CFGMR3QueryStringAllocDef,
5367 CFGMR3GetParent,
5368 CFGMR3GetChild,
5369 CFGMR3GetChildF,
5370 CFGMR3GetChildFV,
5371 CFGMR3GetFirstChild,
5372 CFGMR3GetNextChild,
5373 CFGMR3GetName,
5374 CFGMR3GetNameLen,
5375 CFGMR3AreChildrenValid,
5376 CFGMR3GetFirstValue,
5377 CFGMR3GetNextValue,
5378 CFGMR3GetValueName,
5379 CFGMR3GetValueNameLen,
5380 CFGMR3GetValueType,
5381 CFGMR3AreValuesValid,
5382 CFGMR3ValidateConfig,
5383 pdmR3DevHlp_PhysRead,
5384 pdmR3DevHlp_PhysWrite,
5385 pdmR3DevHlp_PhysGCPhys2CCPtr,
5386 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
5387 pdmR3DevHlp_PhysReleasePageMappingLock,
5388 pdmR3DevHlp_PhysReadGCVirt,
5389 pdmR3DevHlp_PhysWriteGCVirt,
5390 pdmR3DevHlp_PhysGCPtr2GCPhys,
5391 pdmR3DevHlp_MMHeapAlloc,
5392 pdmR3DevHlp_MMHeapAllocZ,
5393 pdmR3DevHlp_MMHeapFree,
5394 pdmR3DevHlp_VMState,
5395 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
5396 pdmR3DevHlp_VMSetError,
5397 pdmR3DevHlp_VMSetErrorV,
5398 pdmR3DevHlp_VMSetRuntimeError,
5399 pdmR3DevHlp_VMSetRuntimeErrorV,
5400 pdmR3DevHlp_DBGFStopV,
5401 pdmR3DevHlp_DBGFInfoRegister,
5402 pdmR3DevHlp_DBGFInfoRegisterArgv,
5403 pdmR3DevHlp_DBGFRegRegister,
5404 pdmR3DevHlp_DBGFTraceBuf,
5405 pdmR3DevHlp_STAMRegister,
5406 pdmR3DevHlp_STAMRegisterV,
5407 pdmR3DevHlp_PCIRegister,
5408 pdmR3DevHlp_PCIRegisterMsi,
5409 pdmR3DevHlp_PCIIORegionRegister,
5410 pdmR3DevHlp_PCIInterceptConfigAccesses,
5411 pdmR3DevHlp_PCIConfigWrite,
5412 pdmR3DevHlp_PCIConfigRead,
5413 pdmR3DevHlp_PCIPhysRead,
5414 pdmR3DevHlp_PCIPhysWrite,
5415 pdmR3DevHlp_PCIPhysGCPhys2CCPtr,
5416 pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly,
5417 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr,
5418 pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly,
5419 pdmR3DevHlp_PCISetIrq,
5420 pdmR3DevHlp_PCISetIrqNoWait,
5421 pdmR3DevHlp_ISASetIrq,
5422 pdmR3DevHlp_ISASetIrqNoWait,
5423 pdmR3DevHlp_DriverAttach,
5424 pdmR3DevHlp_DriverDetach,
5425 pdmR3DevHlp_DriverReconfigure,
5426 pdmR3DevHlp_QueueCreatePtr,
5427 pdmR3DevHlp_QueueCreate,
5428 pdmR3DevHlp_QueueToPtr,
5429 pdmR3DevHlp_QueueAlloc,
5430 pdmR3DevHlp_QueueInsert,
5431 pdmR3DevHlp_QueueInsertEx,
5432 pdmR3DevHlp_QueueFlushIfNecessary,
5433 pdmR3DevHlp_TaskCreate,
5434 pdmR3DevHlp_TaskTrigger,
5435 pdmR3DevHlp_SUPSemEventCreate,
5436 pdmR3DevHlp_SUPSemEventClose,
5437 pdmR3DevHlp_SUPSemEventSignal,
5438 pdmR3DevHlp_SUPSemEventWaitNoResume,
5439 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
5440 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
5441 pdmR3DevHlp_SUPSemEventGetResolution,
5442 pdmR3DevHlp_SUPSemEventMultiCreate,
5443 pdmR3DevHlp_SUPSemEventMultiClose,
5444 pdmR3DevHlp_SUPSemEventMultiSignal,
5445 pdmR3DevHlp_SUPSemEventMultiReset,
5446 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
5447 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
5448 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
5449 pdmR3DevHlp_SUPSemEventMultiGetResolution,
5450 pdmR3DevHlp_CritSectInit,
5451 pdmR3DevHlp_CritSectGetNop,
5452 pdmR3DevHlp_CritSectGetNopR0,
5453 pdmR3DevHlp_CritSectGetNopRC,
5454 pdmR3DevHlp_SetDeviceCritSect,
5455 pdmR3DevHlp_CritSectYield,
5456 pdmR3DevHlp_CritSectEnter,
5457 pdmR3DevHlp_CritSectEnterDebug,
5458 pdmR3DevHlp_CritSectTryEnter,
5459 pdmR3DevHlp_CritSectTryEnterDebug,
5460 pdmR3DevHlp_CritSectLeave,
5461 pdmR3DevHlp_CritSectIsOwner,
5462 pdmR3DevHlp_CritSectIsInitialized,
5463 pdmR3DevHlp_CritSectHasWaiters,
5464 pdmR3DevHlp_CritSectGetRecursion,
5465 pdmR3DevHlp_CritSectScheduleExitEvent,
5466 pdmR3DevHlp_CritSectDelete,
5467 pdmR3DevHlp_CritSectRwInit,
5468 pdmR3DevHlp_CritSectRwDelete,
5469 pdmR3DevHlp_CritSectRwEnterShared,
5470 pdmR3DevHlp_CritSectRwEnterSharedDebug,
5471 pdmR3DevHlp_CritSectRwTryEnterShared,
5472 pdmR3DevHlp_CritSectRwTryEnterSharedDebug,
5473 pdmR3DevHlp_CritSectRwLeaveShared,
5474 pdmR3DevHlp_CritSectRwEnterExcl,
5475 pdmR3DevHlp_CritSectRwEnterExclDebug,
5476 pdmR3DevHlp_CritSectRwTryEnterExcl,
5477 pdmR3DevHlp_CritSectRwTryEnterExclDebug,
5478 pdmR3DevHlp_CritSectRwLeaveExcl,
5479 pdmR3DevHlp_CritSectRwIsWriteOwner,
5480 pdmR3DevHlp_CritSectRwIsReadOwner,
5481 pdmR3DevHlp_CritSectRwGetWriteRecursion,
5482 pdmR3DevHlp_CritSectRwGetWriterReadRecursion,
5483 pdmR3DevHlp_CritSectRwGetReadCount,
5484 pdmR3DevHlp_CritSectRwIsInitialized,
5485 pdmR3DevHlp_ThreadCreate,
5486 PDMR3ThreadDestroy,
5487 PDMR3ThreadIAmSuspending,
5488 PDMR3ThreadIAmRunning,
5489 PDMR3ThreadSleep,
5490 PDMR3ThreadSuspend,
5491 PDMR3ThreadResume,
5492 pdmR3DevHlp_SetAsyncNotification,
5493 pdmR3DevHlp_AsyncNotificationCompleted,
5494 pdmR3DevHlp_RTCRegister,
5495 pdmR3DevHlp_PCIBusRegister,
5496 pdmR3DevHlp_IommuRegister,
5497 pdmR3DevHlp_PICRegister,
5498 pdmR3DevHlp_ApicRegister,
5499 pdmR3DevHlp_IoApicRegister,
5500 pdmR3DevHlp_HpetRegister,
5501 pdmR3DevHlp_PciRawRegister,
5502 pdmR3DevHlp_DMACRegister,
5503 pdmR3DevHlp_DMARegister,
5504 pdmR3DevHlp_DMAReadMemory,
5505 pdmR3DevHlp_DMAWriteMemory,
5506 pdmR3DevHlp_DMASetDREQ,
5507 pdmR3DevHlp_DMAGetChannelMode,
5508 pdmR3DevHlp_DMASchedule,
5509 pdmR3DevHlp_CMOSWrite,
5510 pdmR3DevHlp_CMOSRead,
5511 pdmR3DevHlp_AssertEMT,
5512 pdmR3DevHlp_AssertOther,
5513 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
5514 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
5515 pdmR3DevHlp_CallR0,
5516 pdmR3DevHlp_VMGetSuspendReason,
5517 pdmR3DevHlp_VMGetResumeReason,
5518 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
5519 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
5520 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
5521 pdmR3DevHlp_CpuGetGuestMicroarch,
5522 pdmR3DevHlp_CpuGetGuestAddrWidths,
5523 pdmR3DevHlp_STAMDeregisterByPrefix,
5524 0,
5525 0,
5526 0,
5527 0,
5528 0,
5529 0,
5530 0,
5531 0,
5532 0,
5533 pdmR3DevHlp_Untrusted_GetUVM,
5534 pdmR3DevHlp_Untrusted_GetVM,
5535 pdmR3DevHlp_Untrusted_GetVMCPU,
5536 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
5537 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
5538 pdmR3DevHlp_Untrusted_FirmwareRegister,
5539 pdmR3DevHlp_Untrusted_VMReset,
5540 pdmR3DevHlp_Untrusted_VMSuspend,
5541 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
5542 pdmR3DevHlp_Untrusted_VMPowerOff,
5543 pdmR3DevHlp_Untrusted_A20IsEnabled,
5544 pdmR3DevHlp_Untrusted_A20Set,
5545 pdmR3DevHlp_Untrusted_GetCpuId,
5546 pdmR3DevHlp_TMTimeVirtGet,
5547 pdmR3DevHlp_TMTimeVirtGetFreq,
5548 pdmR3DevHlp_TMTimeVirtGetNano,
5549 pdmR3DevHlp_Untrusted_GetSupDrvSession,
5550 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
5551 pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister,
5552 PDM_DEVHLPR3_VERSION /* the end */
5553};
5554
5555
5556
5557/**
5558 * Queue consumer callback for internal component.
5559 *
5560 * @returns Success indicator.
5561 * If false the item will not be removed and the flushing will stop.
5562 * @param pVM The cross context VM structure.
5563 * @param pItem The item to consume. Upon return this item will be freed.
5564 */
5565DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
5566{
5567 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
5568 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
5569 switch (pTask->enmOp)
5570 {
5571 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
5572 PDMIsaSetIrq(pVM, pTask->u.IsaSetIrq.iIrq, pTask->u.IsaSetIrq.iLevel, pTask->u.IsaSetIrq.uTagSrc);
5573 break;
5574
5575 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
5576 {
5577 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
5578 PPDMPCIDEV pPciDev = pTask->u.PciSetIrq.pPciDevR3;
5579 if (pPciDev)
5580 {
5581 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
5582 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
5583 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
5584
5585 pdmLock(pVM);
5586 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIrq.iIrq,
5587 pTask->u.PciSetIrq.iLevel, pTask->u.PciSetIrq.uTagSrc);
5588 pdmUnlock(pVM);
5589 }
5590 else
5591 AssertReleaseMsgFailed(("No PCI device registered!\n"));
5592 break;
5593 }
5594
5595 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
5596 {
5597 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIrq.uBusDevFn, pTask->u.IoApicSetIrq.iIrq, pTask->u.IoApicSetIrq.iLevel,
5598 pTask->u.IoApicSetIrq.uTagSrc);
5599 break;
5600 }
5601
5602 case PDMDEVHLPTASKOP_IOAPIC_SEND_MSI:
5603 {
5604 PDMIoApicSendMsi(pVM, pTask->u.IoApicSendMsi.uBusDevFn, &pTask->u.IoApicSendMsi.Msi, pTask->u.IoApicSendMsi.uTagSrc);
5605 break;
5606 }
5607
5608 case PDMDEVHLPTASKOP_IOAPIC_SET_EOI:
5609 {
5610 PDMIoApicBroadcastEoi(pVM, pTask->u.IoApicSetEoi.uVector);
5611 break;
5612 }
5613
5614 default:
5615 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
5616 break;
5617 }
5618 return true;
5619}
5620
5621/** @} */
5622
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette