VirtualBox

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

Last change on this file since 84044 was 83987, checked in by vboxsync, 4 years ago

AMD IOMMU: bugref:9654 Naming nit.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use