VirtualBox

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

Last change on this file since 91535 was 90997, checked in by vboxsync, 3 years ago

VMM,PDM,PGM: Restrict the VMSetError and VMSetRuntimeError APIs to ring-3, these never worked properly in ring-0 or raw-mode. A PAEmode runtime error was the only place any of these were used, but given that the VMSetRuntimeError codepath starts with an assertion, it can't have been used/tested. The PAEmode runtime error shouldn't necessarily be triggered by PGM anyway, but IEM. Removed VMMCALLRING3_VM_SET_ERROR and VMMCALLRING3_VM_SET_RUNTIME_ERROR. bugref:10093

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

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