VirtualBox

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

Last change on this file since 87519 was 87494, checked in by vboxsync, 4 years ago

AMD IOMMU: bugref:9654 PDM IOMMU code de-duplication and cleanup, part 3.

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