VirtualBox

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

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

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