VirtualBox

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

Last change on this file since 83773 was 83283, checked in by vboxsync, 5 years ago

PDMDevHlp,tstDevice: Create two more wrappers used by the graphics device to eliminate direct imports from the VMM library [build fix]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 189.6 KB
Line 
1/* $Id: PDMDevHlp.cpp 83283 2020-03-13 13:04:46Z 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 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
1790}
1791
1792
1793/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
1794static DECLCALLBACK(int)
1795pdmR3DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
1796{
1797 PDMDEV_ASSERT_DEVINS(pDevIns);
1798 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1799 pPciDev = pDevIns->apPciDevs[0];
1800 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1801 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1802
1803#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
1804 /*
1805 * Just check the busmaster setting here and forward the request to the generic read helper.
1806 */
1807 if (PCIDevIsBusmaster(pPciDev))
1808 { /* likely */ }
1809 else
1810 {
1811 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
1812 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
1813 return VERR_PDM_NOT_PCI_BUS_MASTER;
1814 }
1815#endif
1816
1817 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
1818}
1819
1820
1821/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
1822static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
1823{
1824 PDMDEV_ASSERT_DEVINS(pDevIns);
1825 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1826 pPciDev = pDevIns->apPciDevs[0];
1827 AssertReturnVoid(pPciDev);
1828 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
1829 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
1830 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
1831
1832 /*
1833 * Validate input.
1834 */
1835 Assert(iIrq == 0);
1836 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
1837
1838 /*
1839 * Must have a PCI device registered!
1840 */
1841 PVM pVM = pDevIns->Internal.s.pVMR3;
1842 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1843 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
1844 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1845
1846 pdmLock(pVM);
1847 uint32_t uTagSrc;
1848 if (iLevel & PDM_IRQ_LEVEL_HIGH)
1849 {
1850 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
1851 if (iLevel == PDM_IRQ_LEVEL_HIGH)
1852 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1853 else
1854 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1855 }
1856 else
1857 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
1858
1859 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
1860
1861 if (iLevel == PDM_IRQ_LEVEL_LOW)
1862 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1863 pdmUnlock(pVM);
1864
1865 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1866}
1867
1868
1869/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
1870static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
1871{
1872 pdmR3DevHlp_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
1873}
1874
1875
1876/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
1877static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1878{
1879 PDMDEV_ASSERT_DEVINS(pDevIns);
1880 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
1881
1882 /*
1883 * Validate input.
1884 */
1885 Assert(iIrq < 16);
1886 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
1887
1888 PVM pVM = pDevIns->Internal.s.pVMR3;
1889
1890 /*
1891 * Do the job.
1892 */
1893 pdmLock(pVM);
1894 uint32_t uTagSrc;
1895 if (iLevel & PDM_IRQ_LEVEL_HIGH)
1896 {
1897 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
1898 if (iLevel == PDM_IRQ_LEVEL_HIGH)
1899 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1900 else
1901 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1902 }
1903 else
1904 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
1905
1906 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
1907
1908 if (iLevel == PDM_IRQ_LEVEL_LOW)
1909 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1910 pdmUnlock(pVM);
1911
1912 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1913}
1914
1915
1916/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
1917static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
1918{
1919 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
1920}
1921
1922
1923/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicSendMsi} */
1924static DECLCALLBACK(void) pdmR3DevHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue)
1925{
1926 PDMDEV_ASSERT_DEVINS(pDevIns);
1927 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: GCPhys=%RGp uValue=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, uValue));
1928
1929 /*
1930 * Validate input.
1931 */
1932 Assert(GCPhys != 0);
1933 Assert(uValue != 0);
1934
1935 PVM pVM = pDevIns->Internal.s.pVMR3;
1936
1937 /*
1938 * Do the job.
1939 */
1940 pdmLock(pVM);
1941 uint32_t uTagSrc;
1942 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
1943 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
1944
1945 PDMIoApicSendMsi(pVM, GCPhys, uValue, uTagSrc); /* (The API takes the lock recursively.) */
1946
1947 pdmUnlock(pVM);
1948
1949 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
1950}
1951
1952
1953/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
1954static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
1955{
1956 PDMDEV_ASSERT_DEVINS(pDevIns);
1957 PVM pVM = pDevIns->Internal.s.pVMR3;
1958 VM_ASSERT_EMT(pVM);
1959 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
1960 pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
1961
1962 /*
1963 * Lookup the LUN, it might already be registered.
1964 */
1965 PPDMLUN pLunPrev = NULL;
1966 PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
1967 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
1968 if (pLun->iLun == iLun)
1969 break;
1970
1971 /*
1972 * Create the LUN if if wasn't found, else check if driver is already attached to it.
1973 */
1974 if (!pLun)
1975 {
1976 if ( !pBaseInterface
1977 || !pszDesc
1978 || !*pszDesc)
1979 {
1980 Assert(pBaseInterface);
1981 Assert(pszDesc || *pszDesc);
1982 return VERR_INVALID_PARAMETER;
1983 }
1984
1985 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
1986 if (!pLun)
1987 return VERR_NO_MEMORY;
1988
1989 pLun->iLun = iLun;
1990 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
1991 pLun->pTop = NULL;
1992 pLun->pBottom = NULL;
1993 pLun->pDevIns = pDevIns;
1994 pLun->pUsbIns = NULL;
1995 pLun->pszDesc = pszDesc;
1996 pLun->pBase = pBaseInterface;
1997 if (!pLunPrev)
1998 pDevIns->Internal.s.pLunsR3 = pLun;
1999 else
2000 pLunPrev->pNext = pLun;
2001 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
2002 iLun, pszDesc, pDevIns->pReg->szName, pDevIns->iInstance));
2003 }
2004 else if (pLun->pTop)
2005 {
2006 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
2007 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
2008 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
2009 }
2010 Assert(pLun->pBase == pBaseInterface);
2011
2012
2013 /*
2014 * Get the attached driver configuration.
2015 */
2016 int rc;
2017 PCFGMNODE pNode = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "LUN#%u", iLun);
2018 if (pNode)
2019 rc = pdmR3DrvInstantiate(pVM, pNode, pBaseInterface, NULL /*pDrvAbove*/, pLun, ppBaseInterface);
2020 else
2021 rc = VERR_PDM_NO_ATTACHED_DRIVER;
2022
2023 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2024 return rc;
2025}
2026
2027
2028/** @interface_method_impl{PDMDEVHLPR3,pfnDriverDetach} */
2029static DECLCALLBACK(int) pdmR3DevHlp_DriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
2030{
2031 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
2032 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: pDrvIns=%p\n",
2033 pDevIns->pReg->szName, pDevIns->iInstance, pDrvIns));
2034
2035#ifdef VBOX_STRICT
2036 PVM pVM = pDevIns->Internal.s.pVMR3;
2037 VM_ASSERT_EMT(pVM);
2038#endif
2039
2040 int rc = pdmR3DrvDetach(pDrvIns, fFlags);
2041
2042 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2043 return rc;
2044}
2045
2046
2047/** @interface_method_impl{PDMDEVHLPR3,pfnDriverReconfigure} */
2048static DECLCALLBACK(int) pdmR3DevHlp_DriverReconfigure(PPDMDEVINS pDevIns, uint32_t iLun, uint32_t cDepth,
2049 const char * const *papszDrivers, PCFGMNODE *papConfigs, uint32_t fFlags)
2050{
2051 PDMDEV_ASSERT_DEVINS(pDevIns);
2052 PVM pVM = pDevIns->Internal.s.pVMR3;
2053 VM_ASSERT_EMT(pVM);
2054 LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: iLun=%u cDepth=%u fFlags=%#x\n",
2055 pDevIns->pReg->szName, pDevIns->iInstance, iLun, cDepth, fFlags));
2056
2057 /*
2058 * Validate input.
2059 */
2060 AssertReturn(cDepth <= 8, VERR_INVALID_PARAMETER);
2061 AssertPtrReturn(papszDrivers, VERR_INVALID_POINTER);
2062 AssertPtrNullReturn(papConfigs, VERR_INVALID_POINTER);
2063 for (uint32_t i = 0; i < cDepth; i++)
2064 {
2065 AssertPtrReturn(papszDrivers[i], VERR_INVALID_POINTER);
2066 size_t cchDriver = strlen(papszDrivers[i]);
2067 AssertPtrReturn(cchDriver > 0 && cchDriver < RT_SIZEOFMEMB(PDMDRVREG, szName), VERR_OUT_OF_RANGE);
2068
2069 if (papConfigs)
2070 AssertPtrNullReturn(papConfigs[i], VERR_INVALID_POINTER);
2071 }
2072 AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
2073
2074 /*
2075 * Do we have to detach an existing driver first?
2076 */
2077 for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
2078 if (pLun->iLun == iLun)
2079 {
2080 if (pLun->pTop)
2081 {
2082 int rc = pdmR3DrvDetach(pLun->pTop, 0);
2083 AssertRCReturn(rc, rc);
2084 }
2085 break;
2086 }
2087
2088 /*
2089 * Remove the old tree.
2090 */
2091 PCFGMNODE pCfgDev = CFGMR3GetChildF(CFGMR3GetRoot(pVM), "Devices/%s/%u/", pDevIns->pReg->szName, pDevIns->iInstance);
2092 AssertReturn(pCfgDev, VERR_INTERNAL_ERROR_2);
2093 PCFGMNODE pCfgLun = CFGMR3GetChildF(pCfgDev, "LUN#%u", iLun);
2094 if (pCfgLun)
2095 CFGMR3RemoveNode(pCfgLun);
2096
2097 /*
2098 * Construct a new tree.
2099 */
2100 int rc = CFGMR3InsertNodeF(pCfgDev, &pCfgLun, "LUN#%u", iLun);
2101 AssertRCReturn(rc, rc);
2102 PCFGMNODE pCfgDrv = pCfgLun;
2103 for (uint32_t i = 0; i < cDepth; i++)
2104 {
2105 rc = CFGMR3InsertString(pCfgDrv, "Driver", papszDrivers[i]);
2106 AssertRCReturn(rc, rc);
2107 if (papConfigs && papConfigs[i])
2108 {
2109 rc = CFGMR3InsertSubTree(pCfgDrv, "Config", papConfigs[i], NULL);
2110 AssertRCReturn(rc, rc);
2111 papConfigs[i] = NULL;
2112 }
2113 else
2114 {
2115 rc = CFGMR3InsertNode(pCfgDrv, "Config", NULL);
2116 AssertRCReturn(rc, rc);
2117 }
2118
2119 if (i + 1 >= cDepth)
2120 break;
2121 rc = CFGMR3InsertNode(pCfgDrv, "AttachedDriver", &pCfgDrv);
2122 AssertRCReturn(rc, rc);
2123 }
2124
2125 LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2126 return rc;
2127}
2128
2129
2130/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreatePtr} */
2131static DECLCALLBACK(int) pdmR3DevHlp_QueueCreatePtr(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2132 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)
2133{
2134 PDMDEV_ASSERT_DEVINS(pDevIns);
2135 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} ppQueue=%p\n",
2136 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, ppQueue));
2137
2138 PVM pVM = pDevIns->Internal.s.pVMR3;
2139 VM_ASSERT_EMT(pVM);
2140
2141 if (pDevIns->iInstance > 0)
2142 {
2143 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2144 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2145 }
2146
2147 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, ppQueue);
2148
2149 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppQueue));
2150 return rc;
2151}
2152
2153
2154/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
2155static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2156 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName,
2157 PDMQUEUEHANDLE *phQueue)
2158{
2159 PDMDEV_ASSERT_DEVINS(pDevIns);
2160 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} phQueue=%p\n",
2161 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, phQueue));
2162
2163 PVM pVM = pDevIns->Internal.s.pVMR3;
2164 VM_ASSERT_EMT(pVM);
2165
2166 if (pDevIns->iInstance > 0)
2167 {
2168 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2169 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2170 }
2171
2172 PPDMQUEUE pQueue = NULL;
2173 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, &pQueue);
2174 *phQueue = (uintptr_t)pQueue;
2175
2176 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phQueue));
2177 return rc;
2178}
2179
2180
2181/** @interface_method_impl{PDMDEVHLPR3,pfnQueueToPtr} */
2182static DECLCALLBACK(PPDMQUEUE) pdmR3DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2183{
2184 PDMDEV_ASSERT_DEVINS(pDevIns);
2185 RT_NOREF(pDevIns);
2186 return (PPDMQUEUE)hQueue;
2187}
2188
2189
2190/** @interface_method_impl{PDMDEVHLPR3,pfnQueueAlloc} */
2191static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR3DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2192{
2193 return PDMQueueAlloc(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2194}
2195
2196
2197/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsert} */
2198static DECLCALLBACK(void) pdmR3DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
2199{
2200 return PDMQueueInsert(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem);
2201}
2202
2203
2204/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsertEx} */
2205static DECLCALLBACK(void) pdmR3DevHlp_QueueInsertEx(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem,
2206 uint64_t cNanoMaxDelay)
2207{
2208 return PDMQueueInsertEx(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem, cNanoMaxDelay);
2209}
2210
2211
2212/** @interface_method_impl{PDMDEVHLPR3,pfnQueueFlushIfNecessary} */
2213static DECLCALLBACK(bool) pdmR3DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2214{
2215 return PDMQueueFlushIfNecessary(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2216}
2217
2218
2219/** @interface_method_impl{PDMDEVHLPR3,pfnTaskCreate} */
2220static DECLCALLBACK(int) pdmR3DevHlp_TaskCreate(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszName,
2221 PFNPDMTASKDEV pfnCallback, void *pvUser, PDMTASKHANDLE *phTask)
2222{
2223 PDMDEV_ASSERT_DEVINS(pDevIns);
2224 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: pfnCallback=%p fFlags=%#x pszName=%p:{%s} phTask=%p\n",
2225 pDevIns->pReg->szName, pDevIns->iInstance, pfnCallback, fFlags, pszName, pszName, phTask));
2226 PVM pVM = pDevIns->Internal.s.pVMR3;
2227 VM_ASSERT_EMT(pVM);
2228
2229 int rc = PDMR3TaskCreate(pVM, fFlags, pszName, PDMTASKTYPE_DEV, pDevIns, (PFNRT)pfnCallback, pvUser, phTask);
2230
2231 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2232 return rc;
2233}
2234
2235
2236/** @interface_method_impl{PDMDEVHLPR3,pfnTaskTrigger} */
2237static DECLCALLBACK(int) pdmR3DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
2238{
2239 PDMDEV_ASSERT_DEVINS(pDevIns);
2240 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
2241
2242 int rc = PDMTaskTrigger(pDevIns->Internal.s.pVMR3, PDMTASKTYPE_DEV, pDevIns, hTask);
2243
2244 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2245 return rc;
2246}
2247
2248
2249/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventCreate} */
2250static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventCreate(PPDMDEVINS pDevIns, PSUPSEMEVENT phEvent)
2251{
2252 PDMDEV_ASSERT_DEVINS(pDevIns);
2253 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEvent));
2254 PVM pVM = pDevIns->Internal.s.pVMR3;
2255 VM_ASSERT_EMT(pVM);
2256
2257 int rc = SUPSemEventCreate(pVM->pSession, phEvent);
2258
2259 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: returns %Rrc *phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEvent));
2260 return rc;
2261}
2262
2263
2264/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventClose} */
2265static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventClose(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2266{
2267 PDMDEV_ASSERT_DEVINS(pDevIns);
2268 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2269
2270 int rc = SUPSemEventClose(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2271
2272 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2273 return rc;
2274}
2275
2276
2277/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventSignal} */
2278static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2279{
2280 PDMDEV_ASSERT_DEVINS(pDevIns);
2281 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2282
2283 int rc = SUPSemEventSignal(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2284
2285 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2286 return rc;
2287}
2288
2289
2290/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNoResume} */
2291static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
2292{
2293 PDMDEV_ASSERT_DEVINS(pDevIns);
2294 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
2295 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
2296
2297 int rc = SUPSemEventWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEvent, cMillies);
2298
2299 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2300 return rc;
2301}
2302
2303
2304/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsAbsIntr} */
2305static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
2306{
2307 PDMDEV_ASSERT_DEVINS(pDevIns);
2308 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
2309 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
2310
2311 int rc = SUPSemEventWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, uNsTimeout);
2312
2313 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2314 return rc;
2315}
2316
2317
2318/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsRelIntr} */
2319static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
2320{
2321 PDMDEV_ASSERT_DEVINS(pDevIns);
2322 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
2323 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
2324
2325 int rc = SUPSemEventWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, cNsTimeout);
2326
2327 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2328 return rc;
2329}
2330
2331
2332/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventGetResolution} */
2333static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
2334{
2335 PDMDEV_ASSERT_DEVINS(pDevIns);
2336 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2337
2338 uint32_t cNsResolution = SUPSemEventGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2339
2340 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2341 return cNsResolution;
2342}
2343
2344
2345/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiCreate} */
2346static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiCreate(PPDMDEVINS pDevIns, PSUPSEMEVENTMULTI phEventMulti)
2347{
2348 PDMDEV_ASSERT_DEVINS(pDevIns);
2349 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEventMulti));
2350 PVM pVM = pDevIns->Internal.s.pVMR3;
2351 VM_ASSERT_EMT(pVM);
2352
2353 int rc = SUPSemEventMultiCreate(pVM->pSession, phEventMulti);
2354
2355 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: returns %Rrc *phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEventMulti));
2356 return rc;
2357}
2358
2359
2360/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiClose} */
2361static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiClose(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2362{
2363 PDMDEV_ASSERT_DEVINS(pDevIns);
2364 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2365
2366 int rc = SUPSemEventMultiClose(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2367
2368 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2369 return rc;
2370}
2371
2372
2373/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiSignal} */
2374static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2375{
2376 PDMDEV_ASSERT_DEVINS(pDevIns);
2377 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2378
2379 int rc = SUPSemEventMultiSignal(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2380
2381 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2382 return rc;
2383}
2384
2385
2386/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiReset} */
2387static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2388{
2389 PDMDEV_ASSERT_DEVINS(pDevIns);
2390 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2391
2392 int rc = SUPSemEventMultiReset(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2393
2394 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2395 return rc;
2396}
2397
2398
2399/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNoResume} */
2400static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2401 uint32_t cMillies)
2402{
2403 PDMDEV_ASSERT_DEVINS(pDevIns);
2404 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
2405 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
2406
2407 int rc = SUPSemEventMultiWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cMillies);
2408
2409 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2410 return rc;
2411}
2412
2413
2414/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsAbsIntr} */
2415static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2416 uint64_t uNsTimeout)
2417{
2418 PDMDEV_ASSERT_DEVINS(pDevIns);
2419 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
2420 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
2421
2422 int rc = SUPSemEventMultiWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, uNsTimeout);
2423
2424 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2425 return rc;
2426}
2427
2428
2429/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsRelIntr} */
2430static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2431 uint64_t cNsTimeout)
2432{
2433 PDMDEV_ASSERT_DEVINS(pDevIns);
2434 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
2435 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
2436
2437 int rc = SUPSemEventMultiWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cNsTimeout);
2438
2439 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2440 return rc;
2441}
2442
2443
2444/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiGetResolution} */
2445static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
2446{
2447 PDMDEV_ASSERT_DEVINS(pDevIns);
2448 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2449
2450 uint32_t cNsResolution = SUPSemEventMultiGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2451
2452 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2453 return cNsResolution;
2454}
2455
2456
2457/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
2458static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
2459 const char *pszNameFmt, va_list va)
2460{
2461 PDMDEV_ASSERT_DEVINS(pDevIns);
2462 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
2463 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
2464
2465 PVM pVM = pDevIns->Internal.s.pVMR3;
2466 VM_ASSERT_EMT(pVM);
2467 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
2468
2469 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2470 return rc;
2471}
2472
2473
2474/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
2475static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
2476{
2477 PDMDEV_ASSERT_DEVINS(pDevIns);
2478 PVM pVM = pDevIns->Internal.s.pVMR3;
2479 VM_ASSERT_EMT(pVM);
2480
2481 PPDMCRITSECT pCritSect = PDMR3CritSectGetNop(pVM);
2482 LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
2483 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2484 return pCritSect;
2485}
2486
2487
2488/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopR0} */
2489static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopR0(PPDMDEVINS pDevIns)
2490{
2491 PDMDEV_ASSERT_DEVINS(pDevIns);
2492 PVM pVM = pDevIns->Internal.s.pVMR3;
2493 VM_ASSERT_EMT(pVM);
2494
2495 R0PTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopR0(pVM);
2496 LogFlow(("pdmR3DevHlp_CritSectGetNopR0: caller='%s'/%d: return %RHv\n",
2497 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2498 return pCritSect;
2499}
2500
2501
2502/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopRC} */
2503static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopRC(PPDMDEVINS pDevIns)
2504{
2505 PDMDEV_ASSERT_DEVINS(pDevIns);
2506 PVM pVM = pDevIns->Internal.s.pVMR3;
2507 VM_ASSERT_EMT(pVM);
2508
2509 RCPTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopRC(pVM);
2510 LogFlow(("pdmR3DevHlp_CritSectGetNopRC: caller='%s'/%d: return %RRv\n",
2511 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2512 return pCritSect;
2513}
2514
2515
2516/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
2517static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2518{
2519 /*
2520 * Validate input.
2521 *
2522 * Note! We only allow the automatically created default critical section
2523 * to be replaced by this API.
2524 */
2525 PDMDEV_ASSERT_DEVINS(pDevIns);
2526 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
2527 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
2528 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
2529 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
2530 PVM pVM = pDevIns->Internal.s.pVMR3;
2531 AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
2532
2533 VM_ASSERT_EMT(pVM);
2534 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
2535
2536 AssertReturn(pDevIns->pCritSectRoR3, VERR_PDM_DEV_IPE_1);
2537 AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
2538 AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
2539 AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
2540
2541 /*
2542 * Replace the critical section and destroy the automatic default section.
2543 */
2544 PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
2545 pDevIns->pCritSectRoR3 = pCritSect;
2546 pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_CHANGED_CRITSECT;
2547
2548 Assert(RT_BOOL(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED) == pDevIns->fR0Enabled);
2549 if ( (pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)
2550 && !(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_NEW_STYLE))
2551 {
2552 PDMDEVICECOMPATSETCRITSECTREQ Req;
2553 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
2554 Req.Hdr.cbReq = sizeof(Req);
2555 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
2556 Req.pDevInsR3 = pDevIns;
2557 Req.pCritSectR3 = pCritSect;
2558 int rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT, 0, &Req.Hdr);
2559 AssertLogRelRCReturn(rc, rc);
2560 }
2561
2562 PDMR3CritSectDelete(pOldCritSect);
2563 Assert((uintptr_t)pOldCritSect - (uintptr_t)pDevIns < pDevIns->cbRing3);
2564
2565 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2566 return VINF_SUCCESS;
2567}
2568
2569
2570/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectYield} */
2571static DECLCALLBACK(bool) pdmR3DevHlp_CritSectYield(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2572{
2573 PDMDEV_ASSERT_DEVINS(pDevIns);
2574 return PDMR3CritSectYield(pDevIns->Internal.s.pVMR3, pCritSect);
2575}
2576
2577
2578/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnter} */
2579static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
2580{
2581 PDMDEV_ASSERT_DEVINS(pDevIns);
2582 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2583 return PDMCritSectEnter(pCritSect, rcBusy);
2584}
2585
2586
2587/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnterDebug} */
2588static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2589{
2590 PDMDEV_ASSERT_DEVINS(pDevIns);
2591 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2592 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2593}
2594
2595
2596/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnter} */
2597static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2598{
2599 PDMDEV_ASSERT_DEVINS(pDevIns);
2600 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2601 return PDMCritSectTryEnter(pCritSect);
2602}
2603
2604
2605/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnterDebug} */
2606static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2607{
2608 PDMDEV_ASSERT_DEVINS(pDevIns);
2609 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2610 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
2611}
2612
2613
2614/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectLeave} */
2615static DECLCALLBACK(int) pdmR3DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2616{
2617 PDMDEV_ASSERT_DEVINS(pDevIns);
2618 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2619 return PDMCritSectLeave(pCritSect);
2620}
2621
2622
2623/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsOwner} */
2624static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2625{
2626 PDMDEV_ASSERT_DEVINS(pDevIns);
2627 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2628 return PDMCritSectIsOwner(pCritSect);
2629}
2630
2631
2632/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsInitialized} */
2633static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2634{
2635 PDMDEV_ASSERT_DEVINS(pDevIns);
2636 RT_NOREF(pDevIns);
2637 return PDMCritSectIsInitialized(pCritSect);
2638}
2639
2640
2641/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectHasWaiters} */
2642static DECLCALLBACK(bool) pdmR3DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2643{
2644 PDMDEV_ASSERT_DEVINS(pDevIns);
2645 RT_NOREF(pDevIns);
2646 return PDMCritSectHasWaiters(pCritSect);
2647}
2648
2649
2650/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetRecursion} */
2651static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
2652{
2653 PDMDEV_ASSERT_DEVINS(pDevIns);
2654 RT_NOREF(pDevIns);
2655 return PDMCritSectGetRecursion(pCritSect);
2656}
2657
2658
2659/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectScheduleExitEvent} */
2660static DECLCALLBACK(int) pdmR3DevHlp_CritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect,
2661 SUPSEMEVENT hEventToSignal)
2662{
2663 PDMDEV_ASSERT_DEVINS(pDevIns);
2664 RT_NOREF(pDevIns);
2665 return PDMHCCritSectScheduleExitEvent(pCritSect, hEventToSignal);
2666}
2667
2668
2669/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectDelete} */
2670static DECLCALLBACK(int) pdmR3DevHlp_CritSectDelete(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2671{
2672 PDMDEV_ASSERT_DEVINS(pDevIns);
2673 RT_NOREF(pDevIns);
2674 return PDMR3CritSectDelete(pCritSect);
2675}
2676
2677
2678/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
2679static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
2680 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
2681{
2682 PDMDEV_ASSERT_DEVINS(pDevIns);
2683 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2684 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
2685 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
2686
2687 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
2688
2689 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
2690 rc, *ppThread));
2691 return rc;
2692}
2693
2694
2695/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
2696static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
2697{
2698 PDMDEV_ASSERT_DEVINS(pDevIns);
2699 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
2700 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
2701
2702 int rc = VINF_SUCCESS;
2703 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
2704 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
2705 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
2706 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
2707 AssertStmt( enmVMState == VMSTATE_SUSPENDING
2708 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2709 || enmVMState == VMSTATE_SUSPENDING_LS
2710 || enmVMState == VMSTATE_RESETTING
2711 || enmVMState == VMSTATE_RESETTING_LS
2712 || enmVMState == VMSTATE_POWERING_OFF
2713 || enmVMState == VMSTATE_POWERING_OFF_LS,
2714 rc = VERR_INVALID_STATE);
2715
2716 if (RT_SUCCESS(rc))
2717 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
2718
2719 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2720 return rc;
2721}
2722
2723
2724/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
2725static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
2726{
2727 PDMDEV_ASSERT_DEVINS(pDevIns);
2728 PVM pVM = pDevIns->Internal.s.pVMR3;
2729
2730 VMSTATE enmVMState = VMR3GetState(pVM);
2731 if ( enmVMState == VMSTATE_SUSPENDING
2732 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
2733 || enmVMState == VMSTATE_SUSPENDING_LS
2734 || enmVMState == VMSTATE_RESETTING
2735 || enmVMState == VMSTATE_RESETTING_LS
2736 || enmVMState == VMSTATE_POWERING_OFF
2737 || enmVMState == VMSTATE_POWERING_OFF_LS)
2738 {
2739 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2740 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
2741 }
2742 else
2743 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
2744}
2745
2746
2747/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
2748static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
2749{
2750 PDMDEV_ASSERT_DEVINS(pDevIns);
2751 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
2752 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
2753 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
2754 pRtcReg->pfnWrite, ppRtcHlp));
2755
2756 /*
2757 * Validate input.
2758 */
2759 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
2760 {
2761 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
2762 PDM_RTCREG_VERSION));
2763 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
2764 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2765 return VERR_INVALID_PARAMETER;
2766 }
2767 if ( !pRtcReg->pfnWrite
2768 || !pRtcReg->pfnRead)
2769 {
2770 Assert(pRtcReg->pfnWrite);
2771 Assert(pRtcReg->pfnRead);
2772 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
2773 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2774 return VERR_INVALID_PARAMETER;
2775 }
2776
2777 if (!ppRtcHlp)
2778 {
2779 Assert(ppRtcHlp);
2780 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
2781 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2782 return VERR_INVALID_PARAMETER;
2783 }
2784
2785 /*
2786 * Only one DMA device.
2787 */
2788 PVM pVM = pDevIns->Internal.s.pVMR3;
2789 if (pVM->pdm.s.pRtc)
2790 {
2791 AssertMsgFailed(("Only one RTC device is supported!\n"));
2792 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2793 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2794 return VERR_INVALID_PARAMETER;
2795 }
2796
2797 /*
2798 * Allocate and initialize pci bus structure.
2799 */
2800 int rc = VINF_SUCCESS;
2801 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
2802 if (pRtc)
2803 {
2804 pRtc->pDevIns = pDevIns;
2805 pRtc->Reg = *pRtcReg;
2806 pVM->pdm.s.pRtc = pRtc;
2807
2808 /* set the helper pointer. */
2809 *ppRtcHlp = &g_pdmR3DevRtcHlp;
2810 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
2811 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
2812 }
2813 else
2814 rc = VERR_NO_MEMORY;
2815
2816 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
2817 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2818 return rc;
2819}
2820
2821
2822/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
2823static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
2824{
2825 PDMDEV_ASSERT_DEVINS(pDevIns);
2826 PVM pVM = pDevIns->Internal.s.pVMR3;
2827 VM_ASSERT_EMT(pVM);
2828 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
2829 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
2830 int rc = VINF_SUCCESS;
2831 if (pVM->pdm.s.pDmac)
2832 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
2833 else
2834 {
2835 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2836 rc = VERR_PDM_NO_DMAC_INSTANCE;
2837 }
2838 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
2839 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2840 return rc;
2841}
2842
2843
2844/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
2845static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
2846{
2847 PDMDEV_ASSERT_DEVINS(pDevIns);
2848 PVM pVM = pDevIns->Internal.s.pVMR3;
2849 VM_ASSERT_EMT(pVM);
2850 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
2851 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
2852 int rc = VINF_SUCCESS;
2853 if (pVM->pdm.s.pDmac)
2854 {
2855 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2856 if (pcbRead)
2857 *pcbRead = cb;
2858 }
2859 else
2860 {
2861 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2862 rc = VERR_PDM_NO_DMAC_INSTANCE;
2863 }
2864 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
2865 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2866 return rc;
2867}
2868
2869
2870/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
2871static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
2872{
2873 PDMDEV_ASSERT_DEVINS(pDevIns);
2874 PVM pVM = pDevIns->Internal.s.pVMR3;
2875 VM_ASSERT_EMT(pVM);
2876 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
2877 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
2878 int rc = VINF_SUCCESS;
2879 if (pVM->pdm.s.pDmac)
2880 {
2881 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
2882 if (pcbWritten)
2883 *pcbWritten = cb;
2884 }
2885 else
2886 {
2887 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2888 rc = VERR_PDM_NO_DMAC_INSTANCE;
2889 }
2890 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
2891 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2892 return rc;
2893}
2894
2895
2896/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
2897static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
2898{
2899 PDMDEV_ASSERT_DEVINS(pDevIns);
2900 PVM pVM = pDevIns->Internal.s.pVMR3;
2901 VM_ASSERT_EMT(pVM);
2902 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
2903 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
2904 int rc = VINF_SUCCESS;
2905 if (pVM->pdm.s.pDmac)
2906 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
2907 else
2908 {
2909 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2910 rc = VERR_PDM_NO_DMAC_INSTANCE;
2911 }
2912 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
2913 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2914 return rc;
2915}
2916
2917/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
2918static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
2919{
2920 PDMDEV_ASSERT_DEVINS(pDevIns);
2921 PVM pVM = pDevIns->Internal.s.pVMR3;
2922 VM_ASSERT_EMT(pVM);
2923 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
2924 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
2925 uint8_t u8Mode;
2926 if (pVM->pdm.s.pDmac)
2927 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
2928 else
2929 {
2930 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2931 u8Mode = 3 << 2 /* illegal mode type */;
2932 }
2933 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
2934 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
2935 return u8Mode;
2936}
2937
2938/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
2939static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
2940{
2941 PDMDEV_ASSERT_DEVINS(pDevIns);
2942 PVM pVM = pDevIns->Internal.s.pVMR3;
2943 VM_ASSERT_EMT(pVM);
2944 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
2945 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_IS_SET(pVM, VM_FF_PDM_DMA)));
2946
2947 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
2948 VM_FF_SET(pVM, VM_FF_PDM_DMA);
2949 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
2950}
2951
2952
2953/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
2954static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
2955{
2956 PDMDEV_ASSERT_DEVINS(pDevIns);
2957 PVM pVM = pDevIns->Internal.s.pVMR3;
2958 VM_ASSERT_EMT(pVM);
2959
2960 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
2961 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
2962 int rc;
2963 if (pVM->pdm.s.pRtc)
2964 {
2965 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
2966 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
2967 if (RT_SUCCESS(rc))
2968 {
2969 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pDevInsRtc, iReg, u8Value);
2970 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
2971 }
2972 }
2973 else
2974 rc = VERR_PDM_NO_RTC_INSTANCE;
2975
2976 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
2977 pDevIns->pReg->szName, pDevIns->iInstance, rc));
2978 return rc;
2979}
2980
2981
2982/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
2983static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
2984{
2985 PDMDEV_ASSERT_DEVINS(pDevIns);
2986 PVM pVM = pDevIns->Internal.s.pVMR3;
2987 VM_ASSERT_EMT(pVM);
2988
2989 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
2990 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
2991 int rc;
2992 if (pVM->pdm.s.pRtc)
2993 {
2994 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
2995 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
2996 if (RT_SUCCESS(rc))
2997 {
2998 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pDevInsRtc, iReg, pu8Value);
2999 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
3000 }
3001 }
3002 else
3003 rc = VERR_PDM_NO_RTC_INSTANCE;
3004
3005 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3006 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3007 return rc;
3008}
3009
3010
3011/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
3012static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3013{
3014 PDMDEV_ASSERT_DEVINS(pDevIns);
3015 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3016 return true;
3017
3018 char szMsg[100];
3019 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3020 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3021 AssertBreakpoint();
3022 return false;
3023}
3024
3025
3026/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
3027static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3028{
3029 PDMDEV_ASSERT_DEVINS(pDevIns);
3030 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3031 return true;
3032
3033 char szMsg[100];
3034 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3035 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3036 AssertBreakpoint();
3037 return false;
3038}
3039
3040
3041/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
3042static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3043 const char *pszSymPrefix, const char *pszSymList)
3044{
3045 PDMDEV_ASSERT_DEVINS(pDevIns);
3046 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3047 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3048 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3049
3050 int rc;
3051 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3052 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3053 {
3054 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
3055 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3056 pvInterface, cbInterface,
3057 pDevIns->pReg->pszRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
3058 pszSymPrefix, pszSymList,
3059 false /*fRing0OrRC*/);
3060 else
3061 {
3062 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
3063 rc = VERR_PERMISSION_DENIED;
3064 }
3065 }
3066 else
3067 {
3068 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3069 pszSymPrefix, pDevIns->pReg->szName));
3070 rc = VERR_INVALID_NAME;
3071 }
3072
3073 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3074 pDevIns->iInstance, rc));
3075 return rc;
3076}
3077
3078
3079/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
3080static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3081 const char *pszSymPrefix, const char *pszSymList)
3082{
3083 PDMDEV_ASSERT_DEVINS(pDevIns);
3084 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3085 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3086 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3087
3088 int rc;
3089 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3090 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3091 {
3092 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3093 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3094 pvInterface, cbInterface,
3095 pDevIns->pReg->pszR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
3096 pszSymPrefix, pszSymList,
3097 true /*fRing0OrRC*/);
3098 else
3099 {
3100 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
3101 rc = VERR_PERMISSION_DENIED;
3102 }
3103 }
3104 else
3105 {
3106 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3107 pszSymPrefix, pDevIns->pReg->szName));
3108 rc = VERR_INVALID_NAME;
3109 }
3110
3111 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3112 pDevIns->iInstance, rc));
3113 return rc;
3114}
3115
3116
3117/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
3118static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
3119{
3120 PDMDEV_ASSERT_DEVINS(pDevIns);
3121 PVM pVM = pDevIns->Internal.s.pVMR3;
3122 PVMCPU pVCpu = VMMGetCpu(pVM);
3123 AssertReturn(pVCpu, VERR_VM_THREAD_IS_EMT);
3124 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
3125 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
3126
3127 /*
3128 * Resolve the ring-0 entry point. There is not need to remember this like
3129 * we do for drivers since this is mainly for construction time hacks and
3130 * other things that aren't performance critical.
3131 */
3132 int rc;
3133 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3134 {
3135 /*
3136 * Make the ring-0 call.
3137 */
3138 PDMDEVICEGENCALLREQ Req;
3139 RT_ZERO(Req.Params);
3140 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
3141 Req.Hdr.cbReq = sizeof(Req);
3142 Req.pDevInsR3 = pDevIns;
3143 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
3144 Req.enmCall = PDMDEVICEGENCALL_REQUEST;
3145 Req.Params.Req.uReq = uOperation;
3146 Req.Params.Req.uArg = u64Arg;
3147 rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_PDM_DEVICE_GEN_CALL, 0, &Req.Hdr);
3148 }
3149 else
3150 rc = VERR_ACCESS_DENIED;
3151 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3152 pDevIns->iInstance, rc));
3153 return rc;
3154}
3155
3156
3157/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
3158static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
3159{
3160 PDMDEV_ASSERT_DEVINS(pDevIns);
3161 PVM pVM = pDevIns->Internal.s.pVMR3;
3162 VM_ASSERT_EMT(pVM);
3163 VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
3164 LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
3165 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3166 return enmReason;
3167}
3168
3169
3170/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
3171static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
3172{
3173 PDMDEV_ASSERT_DEVINS(pDevIns);
3174 PVM pVM = pDevIns->Internal.s.pVMR3;
3175 VM_ASSERT_EMT(pVM);
3176 VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
3177 LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
3178 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3179 return enmReason;
3180}
3181
3182
3183/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
3184static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
3185{
3186 PDMDEV_ASSERT_DEVINS(pDevIns);
3187 LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3188 return pDevIns->Internal.s.pVMR3->pUVM;
3189}
3190
3191
3192/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3193static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
3194{
3195 PDMDEV_ASSERT_DEVINS(pDevIns);
3196 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3197 return pDevIns->Internal.s.pVMR3;
3198}
3199
3200
3201/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3202static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
3203{
3204 PDMDEV_ASSERT_DEVINS(pDevIns);
3205 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3206 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
3207 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
3208}
3209
3210
3211/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
3212static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
3213{
3214 PDMDEV_ASSERT_DEVINS(pDevIns);
3215 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR3);
3216 LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
3217 return idCpu;
3218}
3219
3220
3221/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
3222static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
3223 PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
3224{
3225 PDMDEV_ASSERT_DEVINS(pDevIns);
3226 PVM pVM = pDevIns->Internal.s.pVMR3;
3227 VM_ASSERT_EMT(pVM);
3228 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
3229 ".pfnInterceptConfigAccesses=%p, pfnConfigRead=%p, pfnConfigWrite=%p, .pfnSetIrqR3=%p, .u32EndVersion=%#x} ppPciHlpR3=%p piBus=%p\n",
3230 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
3231 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnInterceptConfigAccesses, pPciBusReg->pfnConfigRead,
3232 pPciBusReg->pfnConfigWrite, pPciBusReg->pfnSetIrqR3, pPciBusReg->u32EndVersion, ppPciHlp, piBus));
3233
3234 /*
3235 * Validate the structure and output parameters.
3236 */
3237 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGR3_VERSION,
3238 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3239 VERR_INVALID_PARAMETER);
3240 AssertPtrReturn(pPciBusReg->pfnRegisterR3, VERR_INVALID_PARAMETER);
3241 AssertPtrNullReturn(pPciBusReg->pfnRegisterMsiR3, VERR_INVALID_POINTER);
3242 AssertPtrReturn(pPciBusReg->pfnIORegionRegisterR3, VERR_INVALID_POINTER);
3243 AssertPtrReturn(pPciBusReg->pfnInterceptConfigAccesses, VERR_INVALID_POINTER);
3244 AssertPtrReturn(pPciBusReg->pfnConfigWrite, VERR_INVALID_POINTER);
3245 AssertPtrReturn(pPciBusReg->pfnConfigRead, VERR_INVALID_POINTER);
3246 AssertPtrReturn(pPciBusReg->pfnSetIrqR3, VERR_INVALID_POINTER);
3247 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGR3_VERSION,
3248 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3249 VERR_INVALID_PARAMETER);
3250 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
3251 AssertPtrNullReturn(piBus, VERR_INVALID_POINTER);
3252 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3253
3254 /*
3255 * Find free PCI bus entry.
3256 */
3257 unsigned iBus = 0;
3258 for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
3259 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
3260 break;
3261 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
3262 ("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)),
3263 VERR_OUT_OF_RESOURCES);
3264 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
3265
3266 /*
3267 * Init the R3 bits.
3268 */
3269 pPciBus->iBus = iBus;
3270 pPciBus->pDevInsR3 = pDevIns;
3271 pPciBus->pfnRegister = pPciBusReg->pfnRegisterR3;
3272 pPciBus->pfnRegisterMsi = pPciBusReg->pfnRegisterMsiR3;
3273 pPciBus->pfnIORegionRegister = pPciBusReg->pfnIORegionRegisterR3;
3274 pPciBus->pfnInterceptConfigAccesses = pPciBusReg->pfnInterceptConfigAccesses;
3275 pPciBus->pfnConfigRead = pPciBusReg->pfnConfigRead;
3276 pPciBus->pfnConfigWrite = pPciBusReg->pfnConfigWrite;
3277 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
3278
3279 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3280
3281 /* set the helper pointer and return. */
3282 *ppPciHlp = &g_pdmR3DevPciHlp;
3283 if (piBus)
3284 *piBus = iBus;
3285 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS, iBus));
3286 return VINF_SUCCESS;
3287}
3288
3289
3290/** @interface_method_impl{PDMDEVHLPR3,pfnIommuRegister} */
3291static DECLCALLBACK(int) pdmR3DevHlp_IommuRegister(PPDMDEVINS pDevIns, PPDMIOMMUREGR3 pIommuReg, PCPDMIOMMUHLPR3 *ppIommuHlp)
3292{
3293 PDMDEV_ASSERT_DEVINS(pDevIns);
3294 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3295 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: pIommuReg=%p:{.u32Version=%#x, .u32TheEnd=%#x } ppIommuHlp=%p\n",
3296 pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
3297 PVM pVM = pDevIns->Internal.s.pVMR3;
3298
3299 /*
3300 * Validate input.
3301 */
3302 AssertMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGR3_VERSION,
3303 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32Version, PDM_IOMMUREGR3_VERSION),
3304 VERR_INVALID_PARAMETER);
3305 /** @todo IOMMU: Validate other parameters, see also tstDevicePdmDevHlp.cpp. */
3306 AssertMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGR3_VERSION,
3307 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32TheEnd, PDM_IOMMUREGR3_VERSION),
3308 VERR_INVALID_PARAMETER);
3309 AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
3310
3311 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3312 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3313
3314 /*
3315 * Find free IOMMU slot.
3316 */
3317 unsigned idxIommu = 0;
3318 for (idxIommu = 0; idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus); idxIommu++)
3319 if (!pVM->pdm.s.aIommus[idxIommu].pDevInsR3)
3320 break;
3321 AssertLogRelMsgReturn(idxIommu < RT_ELEMENTS(pVM->pdm.s.aIommus),
3322 ("Too many IOMMUs. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aIommus)),
3323 VERR_OUT_OF_RESOURCES);
3324 PPDMIOMMU pIommu = &pVM->pdm.s.aIommus[idxIommu];
3325
3326 /*
3327 * Init the R3 bits.
3328 */
3329 pIommu->idxIommu = idxIommu;
3330 pIommu->pDevInsR3 = pDevIns;
3331 Log(("PDM: Registered IOMMU device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3332
3333 /* Set the helper pointer and return. */
3334 *ppIommuHlp = &g_pdmR3DevIommuHlp;
3335 LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3336 return VINF_SUCCESS;
3337}
3338
3339
3340
3341/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
3342static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
3343{
3344 PDMDEV_ASSERT_DEVINS(pDevIns);
3345 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3346 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
3347 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
3348 PVM pVM = pDevIns->Internal.s.pVMR3;
3349
3350 /*
3351 * Validate input.
3352 */
3353 AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
3354 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
3355 VERR_INVALID_PARAMETER);
3356 AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
3357 AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
3358 AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
3359 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
3360 VERR_INVALID_PARAMETER);
3361 AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
3362
3363 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3364 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3365
3366 /*
3367 * Only one PIC device.
3368 */
3369 AssertMsgReturn(pVM->pdm.s.Pic.pDevInsR3 == NULL, ("%s/%d: Only one PIC!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3370 VERR_ALREADY_EXISTS);
3371
3372 /*
3373 * Take down the callbacks and instance.
3374 */
3375 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3376 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrq;
3377 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterrupt;
3378 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3379
3380 /* set the helper pointer and return. */
3381 *ppPicHlp = &g_pdmR3DevPicHlp;
3382 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3383 return VINF_SUCCESS;
3384}
3385
3386
3387/** @interface_method_impl{PDMDEVHLPR3,pfnApicRegister} */
3388static DECLCALLBACK(int) pdmR3DevHlp_ApicRegister(PPDMDEVINS pDevIns)
3389{
3390 PDMDEV_ASSERT_DEVINS(pDevIns);
3391
3392 /*
3393 * Validate caller context.
3394 */
3395 PVM pVM = pDevIns->Internal.s.pVMR3;
3396 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3397 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3398
3399 /*
3400 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3401 * as they need to communicate and share state easily.
3402 */
3403 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 == NULL,
3404 ("%s/%u: Only one APIC device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3405 VERR_ALREADY_EXISTS);
3406
3407 /*
3408 * Set the ring-3 and raw-mode bits, leave the ring-0 to ring-0 setup.
3409 */
3410 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3411 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3412 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3413
3414 LogFlow(("pdmR3DevHlp_ApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3415 return VINF_SUCCESS;
3416}
3417
3418
3419/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicRegister} */
3420static DECLCALLBACK(int) pdmR3DevHlp_IoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
3421{
3422 PDMDEV_ASSERT_DEVINS(pDevIns);
3423 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
3424 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
3425 PVM pVM = pDevIns->Internal.s.pVMR3;
3426
3427 /*
3428 * Validate input.
3429 */
3430 AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
3431 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
3432 VERR_VERSION_MISMATCH);
3433 AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
3434 AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
3435 AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
3436 AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
3437 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
3438 VERR_VERSION_MISMATCH);
3439 AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
3440 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3441 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3442
3443 /*
3444 * The I/O APIC requires the APIC to be present (hacks++).
3445 * If the I/O APIC does GC stuff so must the APIC.
3446 */
3447 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 != NULL, ("Configuration error / Init order error! No APIC!\n"), VERR_WRONG_ORDER);
3448
3449 /*
3450 * Only one I/O APIC device.
3451 */
3452 AssertMsgReturn(pVM->pdm.s.IoApic.pDevInsR3 == NULL,
3453 ("Only one IOAPIC device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3454 VERR_ALREADY_EXISTS);
3455
3456 /*
3457 * Initialize the R3 bits.
3458 */
3459 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3460 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrq;
3461 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsi;
3462 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoi;
3463 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3464
3465 /* set the helper pointer and return. */
3466 *ppIoApicHlp = &g_pdmR3DevIoApicHlp;
3467 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3468 return VINF_SUCCESS;
3469}
3470
3471
3472/** @interface_method_impl{PDMDEVHLPR3,pfnHpetRegister} */
3473static DECLCALLBACK(int) pdmR3DevHlp_HpetRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
3474{
3475 PDMDEV_ASSERT_DEVINS(pDevIns);
3476 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3477 PVM pVM = pDevIns->Internal.s.pVMR3;
3478
3479 /*
3480 * Validate input.
3481 */
3482 AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
3483 ("%s/%u: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
3484 VERR_VERSION_MISMATCH);
3485 AssertPtrReturn(ppHpetHlpR3, 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 * Only one HPET device.
3491 */
3492 AssertMsgReturn(pVM->pdm.s.pHpet == NULL,
3493 ("Only one HPET device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3494 VERR_ALREADY_EXISTS);
3495
3496 /*
3497 * Do the job (what there is of it).
3498 */
3499 pVM->pdm.s.pHpet = pDevIns;
3500 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
3501
3502 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3503 return VINF_SUCCESS;
3504}
3505
3506
3507/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
3508static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
3509{
3510 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3511 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3512 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3513
3514 /*
3515 * Validate input.
3516 */
3517 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
3518 {
3519 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
3520 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3521 return VERR_INVALID_PARAMETER;
3522 }
3523
3524 if (!ppPciRawHlpR3)
3525 {
3526 Assert(ppPciRawHlpR3);
3527 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3528 return VERR_INVALID_PARAMETER;
3529 }
3530
3531 /* set the helper pointer and return. */
3532 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
3533 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3534 return VINF_SUCCESS;
3535}
3536
3537
3538/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
3539static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3540{
3541 PDMDEV_ASSERT_DEVINS(pDevIns);
3542 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3543 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",
3544 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3545 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3546
3547 /*
3548 * Validate input.
3549 */
3550 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3551 {
3552 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3553 PDM_DMACREG_VERSION));
3554 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
3555 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3556 return VERR_INVALID_PARAMETER;
3557 }
3558 if ( !pDmacReg->pfnRun
3559 || !pDmacReg->pfnRegister
3560 || !pDmacReg->pfnReadMemory
3561 || !pDmacReg->pfnWriteMemory
3562 || !pDmacReg->pfnSetDREQ
3563 || !pDmacReg->pfnGetChannelMode)
3564 {
3565 Assert(pDmacReg->pfnRun);
3566 Assert(pDmacReg->pfnRegister);
3567 Assert(pDmacReg->pfnReadMemory);
3568 Assert(pDmacReg->pfnWriteMemory);
3569 Assert(pDmacReg->pfnSetDREQ);
3570 Assert(pDmacReg->pfnGetChannelMode);
3571 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3572 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3573 return VERR_INVALID_PARAMETER;
3574 }
3575
3576 if (!ppDmacHlp)
3577 {
3578 Assert(ppDmacHlp);
3579 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
3580 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3581 return VERR_INVALID_PARAMETER;
3582 }
3583
3584 /*
3585 * Only one DMA device.
3586 */
3587 PVM pVM = pDevIns->Internal.s.pVMR3;
3588 if (pVM->pdm.s.pDmac)
3589 {
3590 AssertMsgFailed(("Only one DMA device is supported!\n"));
3591 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3592 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3593 return VERR_INVALID_PARAMETER;
3594 }
3595
3596 /*
3597 * Allocate and initialize pci bus structure.
3598 */
3599 int rc = VINF_SUCCESS;
3600 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3601 if (pDmac)
3602 {
3603 pDmac->pDevIns = pDevIns;
3604 pDmac->Reg = *pDmacReg;
3605 pVM->pdm.s.pDmac = pDmac;
3606
3607 /* set the helper pointer. */
3608 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3609 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3610 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3611 }
3612 else
3613 rc = VERR_NO_MEMORY;
3614
3615 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3616 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3617 return rc;
3618}
3619
3620
3621/**
3622 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3623 */
3624static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
3625{
3626 PDMDEV_ASSERT_DEVINS(pDevIns);
3627 PVM pVM = pDevIns->Internal.s.pVMR3;
3628 VM_ASSERT_EMT(pVM);
3629 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
3630 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
3631
3632 if (pVM->pdm.s.pvVMMDevHeap == NULL)
3633 {
3634 pVM->pdm.s.pvVMMDevHeap = pvHeap;
3635 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3636 pVM->pdm.s.cbVMMDevHeap = cbHeap;
3637 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
3638 }
3639 else
3640 {
3641 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
3642 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
3643 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
3644 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
3645 {
3646 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3647 if (pVM->pdm.s.pfnVMMDevHeapNotify)
3648 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
3649 }
3650 }
3651
3652 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
3653 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3654 return VINF_SUCCESS;
3655}
3656
3657
3658/**
3659 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
3660 */
3661static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
3662{
3663 PDMDEV_ASSERT_DEVINS(pDevIns);
3664 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3665 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
3666 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
3667
3668 /*
3669 * Validate input.
3670 */
3671 if (pFwReg->u32Version != PDM_FWREG_VERSION)
3672 {
3673 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
3674 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
3675 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3676 return VERR_INVALID_PARAMETER;
3677 }
3678 if (!pFwReg->pfnIsHardReset)
3679 {
3680 Assert(pFwReg->pfnIsHardReset);
3681 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3682 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3683 return VERR_INVALID_PARAMETER;
3684 }
3685
3686 if (!ppFwHlp)
3687 {
3688 Assert(ppFwHlp);
3689 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
3690 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3691 return VERR_INVALID_PARAMETER;
3692 }
3693
3694 /*
3695 * Only one DMA device.
3696 */
3697 PVM pVM = pDevIns->Internal.s.pVMR3;
3698 if (pVM->pdm.s.pFirmware)
3699 {
3700 AssertMsgFailed(("Only one firmware device is supported!\n"));
3701 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3702 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3703 return VERR_INVALID_PARAMETER;
3704 }
3705
3706 /*
3707 * Allocate and initialize pci bus structure.
3708 */
3709 int rc = VINF_SUCCESS;
3710 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
3711 if (pFirmware)
3712 {
3713 pFirmware->pDevIns = pDevIns;
3714 pFirmware->Reg = *pFwReg;
3715 pVM->pdm.s.pFirmware = pFirmware;
3716
3717 /* set the helper pointer. */
3718 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
3719 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
3720 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3721 }
3722 else
3723 rc = VERR_NO_MEMORY;
3724
3725 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3726 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3727 return rc;
3728}
3729
3730
3731/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3732static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
3733{
3734 PDMDEV_ASSERT_DEVINS(pDevIns);
3735 PVM pVM = pDevIns->Internal.s.pVMR3;
3736 VM_ASSERT_EMT(pVM);
3737 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
3738 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
3739
3740 /*
3741 * We postpone this operation because we're likely to be inside a I/O instruction
3742 * and the EIP will be updated when we return.
3743 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3744 */
3745 bool fHaltOnReset;
3746 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3747 if (RT_SUCCESS(rc) && fHaltOnReset)
3748 {
3749 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3750 rc = VINF_EM_HALT;
3751 }
3752 else
3753 {
3754 pVM->pdm.s.fResetFlags = fFlags;
3755 VM_FF_SET(pVM, VM_FF_RESET);
3756 rc = VINF_EM_RESET;
3757 }
3758
3759 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3760 return rc;
3761}
3762
3763
3764/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3765static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3766{
3767 int rc;
3768 PDMDEV_ASSERT_DEVINS(pDevIns);
3769 PVM pVM = pDevIns->Internal.s.pVMR3;
3770 VM_ASSERT_EMT(pVM);
3771 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3772 pDevIns->pReg->szName, pDevIns->iInstance));
3773
3774 /** @todo Always take the SMP path - fewer code paths. */
3775 if (pVM->cCpus > 1)
3776 {
3777 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3778 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
3779 AssertRC(rc);
3780 rc = VINF_EM_SUSPEND;
3781 }
3782 else
3783 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3784
3785 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3786 return rc;
3787}
3788
3789
3790/**
3791 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
3792 * EMT request to avoid deadlocks.
3793 *
3794 * @returns VBox status code fit for scheduling.
3795 * @param pVM The cross context VM structure.
3796 * @param pDevIns The device that triggered this action.
3797 */
3798static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
3799{
3800 /*
3801 * Suspend the VM first then do the saving.
3802 */
3803 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3804 if (RT_SUCCESS(rc))
3805 {
3806 PUVM pUVM = pVM->pUVM;
3807 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
3808
3809 /*
3810 * On success, power off the VM, on failure we'll leave it suspended.
3811 */
3812 if (RT_SUCCESS(rc))
3813 {
3814 rc = VMR3PowerOff(pVM->pUVM);
3815 if (RT_FAILURE(rc))
3816 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
3817 }
3818 else
3819 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
3820 }
3821 else
3822 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
3823 return rc;
3824}
3825
3826
3827/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
3828static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
3829{
3830 PDMDEV_ASSERT_DEVINS(pDevIns);
3831 PVM pVM = pDevIns->Internal.s.pVMR3;
3832 VM_ASSERT_EMT(pVM);
3833 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
3834 pDevIns->pReg->szName, pDevIns->iInstance));
3835
3836 int rc;
3837 if ( pVM->pUVM->pVmm2UserMethods
3838 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
3839 {
3840 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
3841 if (RT_SUCCESS(rc))
3842 {
3843 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
3844 rc = VINF_EM_SUSPEND;
3845 }
3846 }
3847 else
3848 rc = VERR_NOT_SUPPORTED;
3849
3850 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3851 return rc;
3852}
3853
3854
3855/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
3856static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
3857{
3858 int rc;
3859 PDMDEV_ASSERT_DEVINS(pDevIns);
3860 PVM pVM = pDevIns->Internal.s.pVMR3;
3861 VM_ASSERT_EMT(pVM);
3862 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
3863 pDevIns->pReg->szName, pDevIns->iInstance));
3864
3865 /** @todo Always take the SMP path - fewer code paths. */
3866 if (pVM->cCpus > 1)
3867 {
3868 /* We might be holding locks here and could cause a deadlock since
3869 VMR3PowerOff rendezvous with the other CPUs. */
3870 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
3871 AssertRC(rc);
3872 /* Set the VCPU state to stopped here as well to make sure no
3873 inconsistency with the EM state occurs. */
3874 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
3875 rc = VINF_EM_OFF;
3876 }
3877 else
3878 rc = VMR3PowerOff(pVM->pUVM);
3879
3880 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3881 return rc;
3882}
3883
3884
3885/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
3886static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
3887{
3888 PDMDEV_ASSERT_DEVINS(pDevIns);
3889 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3890
3891 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
3892
3893 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
3894 return fRc;
3895}
3896
3897
3898/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
3899static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3900{
3901 PDMDEV_ASSERT_DEVINS(pDevIns);
3902 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3903 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
3904 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
3905}
3906
3907
3908/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
3909static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3910 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3911{
3912 PDMDEV_ASSERT_DEVINS(pDevIns);
3913 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3914
3915 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
3916 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
3917 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
3918
3919 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
3920
3921 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
3922 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
3923}
3924
3925
3926/**
3927 * The device helper structure for trusted devices.
3928 */
3929const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
3930{
3931 PDM_DEVHLPR3_VERSION,
3932 pdmR3DevHlp_IoPortCreateEx,
3933 pdmR3DevHlp_IoPortMap,
3934 pdmR3DevHlp_IoPortUnmap,
3935 pdmR3DevHlp_IoPortGetMappingAddress,
3936 pdmR3DevHlp_MmioCreateEx,
3937 pdmR3DevHlp_MmioMap,
3938 pdmR3DevHlp_MmioUnmap,
3939 pdmR3DevHlp_MmioReduce,
3940 pdmR3DevHlp_MmioGetMappingAddress,
3941 pdmR3DevHlp_Mmio2Create,
3942 pdmR3DevHlp_Mmio2Destroy,
3943 pdmR3DevHlp_Mmio2Map,
3944 pdmR3DevHlp_Mmio2Unmap,
3945 pdmR3DevHlp_Mmio2Reduce,
3946 pdmR3DevHlp_Mmio2GetMappingAddress,
3947 pdmR3DevHlp_Mmio2ChangeRegionNo,
3948 pdmR3DevHlp_ROMRegister,
3949 pdmR3DevHlp_ROMProtectShadow,
3950 pdmR3DevHlp_SSMRegister,
3951 SSMR3PutStruct,
3952 SSMR3PutStructEx,
3953 SSMR3PutBool,
3954 SSMR3PutU8,
3955 SSMR3PutS8,
3956 SSMR3PutU16,
3957 SSMR3PutS16,
3958 SSMR3PutU32,
3959 SSMR3PutS32,
3960 SSMR3PutU64,
3961 SSMR3PutS64,
3962 SSMR3PutU128,
3963 SSMR3PutS128,
3964 SSMR3PutUInt,
3965 SSMR3PutSInt,
3966 SSMR3PutGCUInt,
3967 SSMR3PutGCUIntReg,
3968 SSMR3PutGCPhys32,
3969 SSMR3PutGCPhys64,
3970 SSMR3PutGCPhys,
3971 SSMR3PutGCPtr,
3972 SSMR3PutGCUIntPtr,
3973 SSMR3PutRCPtr,
3974 SSMR3PutIOPort,
3975 SSMR3PutSel,
3976 SSMR3PutMem,
3977 SSMR3PutStrZ,
3978 SSMR3GetStruct,
3979 SSMR3GetStructEx,
3980 SSMR3GetBool,
3981 SSMR3GetBoolV,
3982 SSMR3GetU8,
3983 SSMR3GetU8V,
3984 SSMR3GetS8,
3985 SSMR3GetS8V,
3986 SSMR3GetU16,
3987 SSMR3GetU16V,
3988 SSMR3GetS16,
3989 SSMR3GetS16V,
3990 SSMR3GetU32,
3991 SSMR3GetU32V,
3992 SSMR3GetS32,
3993 SSMR3GetS32V,
3994 SSMR3GetU64,
3995 SSMR3GetU64V,
3996 SSMR3GetS64,
3997 SSMR3GetS64V,
3998 SSMR3GetU128,
3999 SSMR3GetU128V,
4000 SSMR3GetS128,
4001 SSMR3GetS128V,
4002 SSMR3GetGCPhys32,
4003 SSMR3GetGCPhys32V,
4004 SSMR3GetGCPhys64,
4005 SSMR3GetGCPhys64V,
4006 SSMR3GetGCPhys,
4007 SSMR3GetGCPhysV,
4008 SSMR3GetUInt,
4009 SSMR3GetSInt,
4010 SSMR3GetGCUInt,
4011 SSMR3GetGCUIntReg,
4012 SSMR3GetGCPtr,
4013 SSMR3GetGCUIntPtr,
4014 SSMR3GetRCPtr,
4015 SSMR3GetIOPort,
4016 SSMR3GetSel,
4017 SSMR3GetMem,
4018 SSMR3GetStrZ,
4019 SSMR3GetStrZEx,
4020 SSMR3Skip,
4021 SSMR3SkipToEndOfUnit,
4022 SSMR3SetLoadError,
4023 SSMR3SetLoadErrorV,
4024 SSMR3SetCfgError,
4025 SSMR3SetCfgErrorV,
4026 SSMR3HandleGetStatus,
4027 SSMR3HandleGetAfter,
4028 SSMR3HandleIsLiveSave,
4029 SSMR3HandleMaxDowntime,
4030 SSMR3HandleHostBits,
4031 SSMR3HandleRevision,
4032 SSMR3HandleVersion,
4033 SSMR3HandleHostOSAndArch,
4034 pdmR3DevHlp_TMTimerCreate,
4035 pdmR3DevHlp_TimerCreate,
4036 pdmR3DevHlp_TimerToPtr,
4037 pdmR3DevHlp_TimerFromMicro,
4038 pdmR3DevHlp_TimerFromMilli,
4039 pdmR3DevHlp_TimerFromNano,
4040 pdmR3DevHlp_TimerGet,
4041 pdmR3DevHlp_TimerGetFreq,
4042 pdmR3DevHlp_TimerGetNano,
4043 pdmR3DevHlp_TimerIsActive,
4044 pdmR3DevHlp_TimerIsLockOwner,
4045 pdmR3DevHlp_TimerLockClock,
4046 pdmR3DevHlp_TimerLockClock2,
4047 pdmR3DevHlp_TimerSet,
4048 pdmR3DevHlp_TimerSetFrequencyHint,
4049 pdmR3DevHlp_TimerSetMicro,
4050 pdmR3DevHlp_TimerSetMillies,
4051 pdmR3DevHlp_TimerSetNano,
4052 pdmR3DevHlp_TimerSetRelative,
4053 pdmR3DevHlp_TimerStop,
4054 pdmR3DevHlp_TimerUnlockClock,
4055 pdmR3DevHlp_TimerUnlockClock2,
4056 pdmR3DevHlp_TimerSetCritSect,
4057 pdmR3DevHlp_TimerSave,
4058 pdmR3DevHlp_TimerLoad,
4059 pdmR3DevHlp_TimerDestroy,
4060 TMR3TimerSkip,
4061 pdmR3DevHlp_TMUtcNow,
4062 CFGMR3Exists,
4063 CFGMR3QueryType,
4064 CFGMR3QuerySize,
4065 CFGMR3QueryInteger,
4066 CFGMR3QueryIntegerDef,
4067 CFGMR3QueryString,
4068 CFGMR3QueryStringDef,
4069 CFGMR3QueryBytes,
4070 CFGMR3QueryU64,
4071 CFGMR3QueryU64Def,
4072 CFGMR3QueryS64,
4073 CFGMR3QueryS64Def,
4074 CFGMR3QueryU32,
4075 CFGMR3QueryU32Def,
4076 CFGMR3QueryS32,
4077 CFGMR3QueryS32Def,
4078 CFGMR3QueryU16,
4079 CFGMR3QueryU16Def,
4080 CFGMR3QueryS16,
4081 CFGMR3QueryS16Def,
4082 CFGMR3QueryU8,
4083 CFGMR3QueryU8Def,
4084 CFGMR3QueryS8,
4085 CFGMR3QueryS8Def,
4086 CFGMR3QueryBool,
4087 CFGMR3QueryBoolDef,
4088 CFGMR3QueryPort,
4089 CFGMR3QueryPortDef,
4090 CFGMR3QueryUInt,
4091 CFGMR3QueryUIntDef,
4092 CFGMR3QuerySInt,
4093 CFGMR3QuerySIntDef,
4094 CFGMR3QueryPtr,
4095 CFGMR3QueryPtrDef,
4096 CFGMR3QueryGCPtr,
4097 CFGMR3QueryGCPtrDef,
4098 CFGMR3QueryGCPtrU,
4099 CFGMR3QueryGCPtrUDef,
4100 CFGMR3QueryGCPtrS,
4101 CFGMR3QueryGCPtrSDef,
4102 CFGMR3QueryStringAlloc,
4103 CFGMR3QueryStringAllocDef,
4104 CFGMR3GetParent,
4105 CFGMR3GetChild,
4106 CFGMR3GetChildF,
4107 CFGMR3GetChildFV,
4108 CFGMR3GetFirstChild,
4109 CFGMR3GetNextChild,
4110 CFGMR3GetName,
4111 CFGMR3GetNameLen,
4112 CFGMR3AreChildrenValid,
4113 CFGMR3GetFirstValue,
4114 CFGMR3GetNextValue,
4115 CFGMR3GetValueName,
4116 CFGMR3GetValueNameLen,
4117 CFGMR3GetValueType,
4118 CFGMR3AreValuesValid,
4119 CFGMR3ValidateConfig,
4120 pdmR3DevHlp_PhysRead,
4121 pdmR3DevHlp_PhysWrite,
4122 pdmR3DevHlp_PhysGCPhys2CCPtr,
4123 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4124 pdmR3DevHlp_PhysReleasePageMappingLock,
4125 pdmR3DevHlp_PhysReadGCVirt,
4126 pdmR3DevHlp_PhysWriteGCVirt,
4127 pdmR3DevHlp_PhysGCPtr2GCPhys,
4128 pdmR3DevHlp_MMHeapAlloc,
4129 pdmR3DevHlp_MMHeapAllocZ,
4130 pdmR3DevHlp_MMHeapFree,
4131 pdmR3DevHlp_VMState,
4132 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4133 pdmR3DevHlp_VMSetError,
4134 pdmR3DevHlp_VMSetErrorV,
4135 pdmR3DevHlp_VMSetRuntimeError,
4136 pdmR3DevHlp_VMSetRuntimeErrorV,
4137 pdmR3DevHlp_DBGFStopV,
4138 pdmR3DevHlp_DBGFInfoRegister,
4139 pdmR3DevHlp_DBGFInfoRegisterArgv,
4140 pdmR3DevHlp_DBGFRegRegister,
4141 pdmR3DevHlp_DBGFTraceBuf,
4142 pdmR3DevHlp_STAMRegister,
4143 pdmR3DevHlp_STAMRegisterV,
4144 pdmR3DevHlp_PCIRegister,
4145 pdmR3DevHlp_PCIRegisterMsi,
4146 pdmR3DevHlp_PCIIORegionRegister,
4147 pdmR3DevHlp_PCIInterceptConfigAccesses,
4148 pdmR3DevHlp_PCIConfigWrite,
4149 pdmR3DevHlp_PCIConfigRead,
4150 pdmR3DevHlp_PCIPhysRead,
4151 pdmR3DevHlp_PCIPhysWrite,
4152 pdmR3DevHlp_PCISetIrq,
4153 pdmR3DevHlp_PCISetIrqNoWait,
4154 pdmR3DevHlp_ISASetIrq,
4155 pdmR3DevHlp_ISASetIrqNoWait,
4156 pdmR3DevHlp_IoApicSendMsi,
4157 pdmR3DevHlp_DriverAttach,
4158 pdmR3DevHlp_DriverDetach,
4159 pdmR3DevHlp_DriverReconfigure,
4160 pdmR3DevHlp_QueueCreatePtr,
4161 pdmR3DevHlp_QueueCreate,
4162 pdmR3DevHlp_QueueToPtr,
4163 pdmR3DevHlp_QueueAlloc,
4164 pdmR3DevHlp_QueueInsert,
4165 pdmR3DevHlp_QueueInsertEx,
4166 pdmR3DevHlp_QueueFlushIfNecessary,
4167 pdmR3DevHlp_TaskCreate,
4168 pdmR3DevHlp_TaskTrigger,
4169 pdmR3DevHlp_SUPSemEventCreate,
4170 pdmR3DevHlp_SUPSemEventClose,
4171 pdmR3DevHlp_SUPSemEventSignal,
4172 pdmR3DevHlp_SUPSemEventWaitNoResume,
4173 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4174 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4175 pdmR3DevHlp_SUPSemEventGetResolution,
4176 pdmR3DevHlp_SUPSemEventMultiCreate,
4177 pdmR3DevHlp_SUPSemEventMultiClose,
4178 pdmR3DevHlp_SUPSemEventMultiSignal,
4179 pdmR3DevHlp_SUPSemEventMultiReset,
4180 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4181 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4182 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4183 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4184 pdmR3DevHlp_CritSectInit,
4185 pdmR3DevHlp_CritSectGetNop,
4186 pdmR3DevHlp_CritSectGetNopR0,
4187 pdmR3DevHlp_CritSectGetNopRC,
4188 pdmR3DevHlp_SetDeviceCritSect,
4189 pdmR3DevHlp_CritSectYield,
4190 pdmR3DevHlp_CritSectEnter,
4191 pdmR3DevHlp_CritSectEnterDebug,
4192 pdmR3DevHlp_CritSectTryEnter,
4193 pdmR3DevHlp_CritSectTryEnterDebug,
4194 pdmR3DevHlp_CritSectLeave,
4195 pdmR3DevHlp_CritSectIsOwner,
4196 pdmR3DevHlp_CritSectIsInitialized,
4197 pdmR3DevHlp_CritSectHasWaiters,
4198 pdmR3DevHlp_CritSectGetRecursion,
4199 pdmR3DevHlp_CritSectScheduleExitEvent,
4200 pdmR3DevHlp_CritSectDelete,
4201 pdmR3DevHlp_ThreadCreate,
4202 PDMR3ThreadDestroy,
4203 PDMR3ThreadIAmSuspending,
4204 PDMR3ThreadIAmRunning,
4205 PDMR3ThreadSleep,
4206 PDMR3ThreadSuspend,
4207 PDMR3ThreadResume,
4208 pdmR3DevHlp_SetAsyncNotification,
4209 pdmR3DevHlp_AsyncNotificationCompleted,
4210 pdmR3DevHlp_RTCRegister,
4211 pdmR3DevHlp_PCIBusRegister,
4212 pdmR3DevHlp_IommuRegister,
4213 pdmR3DevHlp_PICRegister,
4214 pdmR3DevHlp_ApicRegister,
4215 pdmR3DevHlp_IoApicRegister,
4216 pdmR3DevHlp_HpetRegister,
4217 pdmR3DevHlp_PciRawRegister,
4218 pdmR3DevHlp_DMACRegister,
4219 pdmR3DevHlp_DMARegister,
4220 pdmR3DevHlp_DMAReadMemory,
4221 pdmR3DevHlp_DMAWriteMemory,
4222 pdmR3DevHlp_DMASetDREQ,
4223 pdmR3DevHlp_DMAGetChannelMode,
4224 pdmR3DevHlp_DMASchedule,
4225 pdmR3DevHlp_CMOSWrite,
4226 pdmR3DevHlp_CMOSRead,
4227 pdmR3DevHlp_AssertEMT,
4228 pdmR3DevHlp_AssertOther,
4229 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4230 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4231 pdmR3DevHlp_CallR0,
4232 pdmR3DevHlp_VMGetSuspendReason,
4233 pdmR3DevHlp_VMGetResumeReason,
4234 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4235 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4236 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4237 pdmR3DevHlp_CpuGetGuestMicroarch,
4238 0,
4239 0,
4240 0,
4241 0,
4242 0,
4243 0,
4244 0,
4245 0,
4246 0,
4247 0,
4248 pdmR3DevHlp_GetUVM,
4249 pdmR3DevHlp_GetVM,
4250 pdmR3DevHlp_GetVMCPU,
4251 pdmR3DevHlp_GetCurrentCpuId,
4252 pdmR3DevHlp_RegisterVMMDevHeap,
4253 pdmR3DevHlp_FirmwareRegister,
4254 pdmR3DevHlp_VMReset,
4255 pdmR3DevHlp_VMSuspend,
4256 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4257 pdmR3DevHlp_VMPowerOff,
4258 pdmR3DevHlp_A20IsEnabled,
4259 pdmR3DevHlp_A20Set,
4260 pdmR3DevHlp_GetCpuId,
4261 pdmR3DevHlp_TMTimeVirtGet,
4262 pdmR3DevHlp_TMTimeVirtGetFreq,
4263 pdmR3DevHlp_TMTimeVirtGetNano,
4264 pdmR3DevHlp_GetSupDrvSession,
4265 pdmR3DevHlp_QueryGenericUserObject,
4266 pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
4267 PDM_DEVHLPR3_VERSION /* the end */
4268};
4269
4270
4271
4272
4273/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
4274static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
4275{
4276 PDMDEV_ASSERT_DEVINS(pDevIns);
4277 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4278 return NULL;
4279}
4280
4281
4282/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
4283static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
4284{
4285 PDMDEV_ASSERT_DEVINS(pDevIns);
4286 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4287 return NULL;
4288}
4289
4290
4291/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
4292static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
4293{
4294 PDMDEV_ASSERT_DEVINS(pDevIns);
4295 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4296 return NULL;
4297}
4298
4299
4300/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
4301static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(PPDMDEVINS pDevIns)
4302{
4303 PDMDEV_ASSERT_DEVINS(pDevIns);
4304 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4305 return NIL_VMCPUID;
4306}
4307
4308
4309/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
4310static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
4311 RTR3PTR pvHeap, unsigned cbHeap)
4312{
4313 PDMDEV_ASSERT_DEVINS(pDevIns);
4314 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
4315 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4316 return VERR_ACCESS_DENIED;
4317}
4318
4319
4320/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
4321static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4322{
4323 PDMDEV_ASSERT_DEVINS(pDevIns);
4324 NOREF(pFwReg); NOREF(ppFwHlp);
4325 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4326 return VERR_ACCESS_DENIED;
4327}
4328
4329
4330/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4331static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4332{
4333 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
4334 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4335 return VERR_ACCESS_DENIED;
4336}
4337
4338
4339/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4340static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
4341{
4342 PDMDEV_ASSERT_DEVINS(pDevIns);
4343 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4344 return VERR_ACCESS_DENIED;
4345}
4346
4347
4348/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4349static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4350{
4351 PDMDEV_ASSERT_DEVINS(pDevIns);
4352 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4353 return VERR_ACCESS_DENIED;
4354}
4355
4356
4357/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4358static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
4359{
4360 PDMDEV_ASSERT_DEVINS(pDevIns);
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,pfnA20IsEnabled} */
4367static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
4368{
4369 PDMDEV_ASSERT_DEVINS(pDevIns);
4370 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4371 return false;
4372}
4373
4374
4375/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4376static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4377{
4378 PDMDEV_ASSERT_DEVINS(pDevIns);
4379 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4380 NOREF(fEnable);
4381}
4382
4383
4384/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4385static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4386 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4387{
4388 PDMDEV_ASSERT_DEVINS(pDevIns);
4389 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
4390 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4391}
4392
4393
4394/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
4395static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(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 (PSUPDRVSESSION)0;
4400}
4401
4402
4403/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
4404static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
4405{
4406 PDMDEV_ASSERT_DEVINS(pDevIns);
4407 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
4408 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
4409 return NULL;
4410}
4411
4412
4413/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalTypeRegister} */
4414static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
4415 R3PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR3,
4416 const char *pszHandlerR0, const char *pszPfHandlerR0,
4417 const char *pszHandlerRC, const char *pszPfHandlerRC,
4418 const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
4419{
4420 PDMDEV_ASSERT_DEVINS(pDevIns);
4421 RT_NOREF(enmKind, pfnHandlerR3, pszHandlerR0, pszPfHandlerR0, pszHandlerRC, pszPfHandlerRC, pszDesc, phType);
4422 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
4423 pDevIns->pReg->szName, pDevIns->iInstance));
4424 return VERR_ACCESS_DENIED;
4425}
4426
4427
4428/**
4429 * The device helper structure for non-trusted devices.
4430 */
4431const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
4432{
4433 PDM_DEVHLPR3_VERSION,
4434 pdmR3DevHlp_IoPortCreateEx,
4435 pdmR3DevHlp_IoPortMap,
4436 pdmR3DevHlp_IoPortUnmap,
4437 pdmR3DevHlp_IoPortGetMappingAddress,
4438 pdmR3DevHlp_MmioCreateEx,
4439 pdmR3DevHlp_MmioMap,
4440 pdmR3DevHlp_MmioUnmap,
4441 pdmR3DevHlp_MmioReduce,
4442 pdmR3DevHlp_MmioGetMappingAddress,
4443 pdmR3DevHlp_Mmio2Create,
4444 pdmR3DevHlp_Mmio2Destroy,
4445 pdmR3DevHlp_Mmio2Map,
4446 pdmR3DevHlp_Mmio2Unmap,
4447 pdmR3DevHlp_Mmio2Reduce,
4448 pdmR3DevHlp_Mmio2GetMappingAddress,
4449 pdmR3DevHlp_Mmio2ChangeRegionNo,
4450 pdmR3DevHlp_ROMRegister,
4451 pdmR3DevHlp_ROMProtectShadow,
4452 pdmR3DevHlp_SSMRegister,
4453 SSMR3PutStruct,
4454 SSMR3PutStructEx,
4455 SSMR3PutBool,
4456 SSMR3PutU8,
4457 SSMR3PutS8,
4458 SSMR3PutU16,
4459 SSMR3PutS16,
4460 SSMR3PutU32,
4461 SSMR3PutS32,
4462 SSMR3PutU64,
4463 SSMR3PutS64,
4464 SSMR3PutU128,
4465 SSMR3PutS128,
4466 SSMR3PutUInt,
4467 SSMR3PutSInt,
4468 SSMR3PutGCUInt,
4469 SSMR3PutGCUIntReg,
4470 SSMR3PutGCPhys32,
4471 SSMR3PutGCPhys64,
4472 SSMR3PutGCPhys,
4473 SSMR3PutGCPtr,
4474 SSMR3PutGCUIntPtr,
4475 SSMR3PutRCPtr,
4476 SSMR3PutIOPort,
4477 SSMR3PutSel,
4478 SSMR3PutMem,
4479 SSMR3PutStrZ,
4480 SSMR3GetStruct,
4481 SSMR3GetStructEx,
4482 SSMR3GetBool,
4483 SSMR3GetBoolV,
4484 SSMR3GetU8,
4485 SSMR3GetU8V,
4486 SSMR3GetS8,
4487 SSMR3GetS8V,
4488 SSMR3GetU16,
4489 SSMR3GetU16V,
4490 SSMR3GetS16,
4491 SSMR3GetS16V,
4492 SSMR3GetU32,
4493 SSMR3GetU32V,
4494 SSMR3GetS32,
4495 SSMR3GetS32V,
4496 SSMR3GetU64,
4497 SSMR3GetU64V,
4498 SSMR3GetS64,
4499 SSMR3GetS64V,
4500 SSMR3GetU128,
4501 SSMR3GetU128V,
4502 SSMR3GetS128,
4503 SSMR3GetS128V,
4504 SSMR3GetGCPhys32,
4505 SSMR3GetGCPhys32V,
4506 SSMR3GetGCPhys64,
4507 SSMR3GetGCPhys64V,
4508 SSMR3GetGCPhys,
4509 SSMR3GetGCPhysV,
4510 SSMR3GetUInt,
4511 SSMR3GetSInt,
4512 SSMR3GetGCUInt,
4513 SSMR3GetGCUIntReg,
4514 SSMR3GetGCPtr,
4515 SSMR3GetGCUIntPtr,
4516 SSMR3GetRCPtr,
4517 SSMR3GetIOPort,
4518 SSMR3GetSel,
4519 SSMR3GetMem,
4520 SSMR3GetStrZ,
4521 SSMR3GetStrZEx,
4522 SSMR3Skip,
4523 SSMR3SkipToEndOfUnit,
4524 SSMR3SetLoadError,
4525 SSMR3SetLoadErrorV,
4526 SSMR3SetCfgError,
4527 SSMR3SetCfgErrorV,
4528 SSMR3HandleGetStatus,
4529 SSMR3HandleGetAfter,
4530 SSMR3HandleIsLiveSave,
4531 SSMR3HandleMaxDowntime,
4532 SSMR3HandleHostBits,
4533 SSMR3HandleRevision,
4534 SSMR3HandleVersion,
4535 SSMR3HandleHostOSAndArch,
4536 pdmR3DevHlp_TMTimerCreate,
4537 pdmR3DevHlp_TimerCreate,
4538 pdmR3DevHlp_TimerToPtr,
4539 pdmR3DevHlp_TimerFromMicro,
4540 pdmR3DevHlp_TimerFromMilli,
4541 pdmR3DevHlp_TimerFromNano,
4542 pdmR3DevHlp_TimerGet,
4543 pdmR3DevHlp_TimerGetFreq,
4544 pdmR3DevHlp_TimerGetNano,
4545 pdmR3DevHlp_TimerIsActive,
4546 pdmR3DevHlp_TimerIsLockOwner,
4547 pdmR3DevHlp_TimerLockClock,
4548 pdmR3DevHlp_TimerLockClock2,
4549 pdmR3DevHlp_TimerSet,
4550 pdmR3DevHlp_TimerSetFrequencyHint,
4551 pdmR3DevHlp_TimerSetMicro,
4552 pdmR3DevHlp_TimerSetMillies,
4553 pdmR3DevHlp_TimerSetNano,
4554 pdmR3DevHlp_TimerSetRelative,
4555 pdmR3DevHlp_TimerStop,
4556 pdmR3DevHlp_TimerUnlockClock,
4557 pdmR3DevHlp_TimerUnlockClock2,
4558 pdmR3DevHlp_TimerSetCritSect,
4559 pdmR3DevHlp_TimerSave,
4560 pdmR3DevHlp_TimerLoad,
4561 pdmR3DevHlp_TimerDestroy,
4562 TMR3TimerSkip,
4563 pdmR3DevHlp_TMUtcNow,
4564 CFGMR3Exists,
4565 CFGMR3QueryType,
4566 CFGMR3QuerySize,
4567 CFGMR3QueryInteger,
4568 CFGMR3QueryIntegerDef,
4569 CFGMR3QueryString,
4570 CFGMR3QueryStringDef,
4571 CFGMR3QueryBytes,
4572 CFGMR3QueryU64,
4573 CFGMR3QueryU64Def,
4574 CFGMR3QueryS64,
4575 CFGMR3QueryS64Def,
4576 CFGMR3QueryU32,
4577 CFGMR3QueryU32Def,
4578 CFGMR3QueryS32,
4579 CFGMR3QueryS32Def,
4580 CFGMR3QueryU16,
4581 CFGMR3QueryU16Def,
4582 CFGMR3QueryS16,
4583 CFGMR3QueryS16Def,
4584 CFGMR3QueryU8,
4585 CFGMR3QueryU8Def,
4586 CFGMR3QueryS8,
4587 CFGMR3QueryS8Def,
4588 CFGMR3QueryBool,
4589 CFGMR3QueryBoolDef,
4590 CFGMR3QueryPort,
4591 CFGMR3QueryPortDef,
4592 CFGMR3QueryUInt,
4593 CFGMR3QueryUIntDef,
4594 CFGMR3QuerySInt,
4595 CFGMR3QuerySIntDef,
4596 CFGMR3QueryPtr,
4597 CFGMR3QueryPtrDef,
4598 CFGMR3QueryGCPtr,
4599 CFGMR3QueryGCPtrDef,
4600 CFGMR3QueryGCPtrU,
4601 CFGMR3QueryGCPtrUDef,
4602 CFGMR3QueryGCPtrS,
4603 CFGMR3QueryGCPtrSDef,
4604 CFGMR3QueryStringAlloc,
4605 CFGMR3QueryStringAllocDef,
4606 CFGMR3GetParent,
4607 CFGMR3GetChild,
4608 CFGMR3GetChildF,
4609 CFGMR3GetChildFV,
4610 CFGMR3GetFirstChild,
4611 CFGMR3GetNextChild,
4612 CFGMR3GetName,
4613 CFGMR3GetNameLen,
4614 CFGMR3AreChildrenValid,
4615 CFGMR3GetFirstValue,
4616 CFGMR3GetNextValue,
4617 CFGMR3GetValueName,
4618 CFGMR3GetValueNameLen,
4619 CFGMR3GetValueType,
4620 CFGMR3AreValuesValid,
4621 CFGMR3ValidateConfig,
4622 pdmR3DevHlp_PhysRead,
4623 pdmR3DevHlp_PhysWrite,
4624 pdmR3DevHlp_PhysGCPhys2CCPtr,
4625 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4626 pdmR3DevHlp_PhysReleasePageMappingLock,
4627 pdmR3DevHlp_PhysReadGCVirt,
4628 pdmR3DevHlp_PhysWriteGCVirt,
4629 pdmR3DevHlp_PhysGCPtr2GCPhys,
4630 pdmR3DevHlp_MMHeapAlloc,
4631 pdmR3DevHlp_MMHeapAllocZ,
4632 pdmR3DevHlp_MMHeapFree,
4633 pdmR3DevHlp_VMState,
4634 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4635 pdmR3DevHlp_VMSetError,
4636 pdmR3DevHlp_VMSetErrorV,
4637 pdmR3DevHlp_VMSetRuntimeError,
4638 pdmR3DevHlp_VMSetRuntimeErrorV,
4639 pdmR3DevHlp_DBGFStopV,
4640 pdmR3DevHlp_DBGFInfoRegister,
4641 pdmR3DevHlp_DBGFInfoRegisterArgv,
4642 pdmR3DevHlp_DBGFRegRegister,
4643 pdmR3DevHlp_DBGFTraceBuf,
4644 pdmR3DevHlp_STAMRegister,
4645 pdmR3DevHlp_STAMRegisterV,
4646 pdmR3DevHlp_PCIRegister,
4647 pdmR3DevHlp_PCIRegisterMsi,
4648 pdmR3DevHlp_PCIIORegionRegister,
4649 pdmR3DevHlp_PCIInterceptConfigAccesses,
4650 pdmR3DevHlp_PCIConfigWrite,
4651 pdmR3DevHlp_PCIConfigRead,
4652 pdmR3DevHlp_PCIPhysRead,
4653 pdmR3DevHlp_PCIPhysWrite,
4654 pdmR3DevHlp_PCISetIrq,
4655 pdmR3DevHlp_PCISetIrqNoWait,
4656 pdmR3DevHlp_ISASetIrq,
4657 pdmR3DevHlp_ISASetIrqNoWait,
4658 pdmR3DevHlp_IoApicSendMsi,
4659 pdmR3DevHlp_DriverAttach,
4660 pdmR3DevHlp_DriverDetach,
4661 pdmR3DevHlp_DriverReconfigure,
4662 pdmR3DevHlp_QueueCreatePtr,
4663 pdmR3DevHlp_QueueCreate,
4664 pdmR3DevHlp_QueueToPtr,
4665 pdmR3DevHlp_QueueAlloc,
4666 pdmR3DevHlp_QueueInsert,
4667 pdmR3DevHlp_QueueInsertEx,
4668 pdmR3DevHlp_QueueFlushIfNecessary,
4669 pdmR3DevHlp_TaskCreate,
4670 pdmR3DevHlp_TaskTrigger,
4671 pdmR3DevHlp_SUPSemEventCreate,
4672 pdmR3DevHlp_SUPSemEventClose,
4673 pdmR3DevHlp_SUPSemEventSignal,
4674 pdmR3DevHlp_SUPSemEventWaitNoResume,
4675 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4676 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4677 pdmR3DevHlp_SUPSemEventGetResolution,
4678 pdmR3DevHlp_SUPSemEventMultiCreate,
4679 pdmR3DevHlp_SUPSemEventMultiClose,
4680 pdmR3DevHlp_SUPSemEventMultiSignal,
4681 pdmR3DevHlp_SUPSemEventMultiReset,
4682 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4683 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4684 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4685 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4686 pdmR3DevHlp_CritSectInit,
4687 pdmR3DevHlp_CritSectGetNop,
4688 pdmR3DevHlp_CritSectGetNopR0,
4689 pdmR3DevHlp_CritSectGetNopRC,
4690 pdmR3DevHlp_SetDeviceCritSect,
4691 pdmR3DevHlp_CritSectYield,
4692 pdmR3DevHlp_CritSectEnter,
4693 pdmR3DevHlp_CritSectEnterDebug,
4694 pdmR3DevHlp_CritSectTryEnter,
4695 pdmR3DevHlp_CritSectTryEnterDebug,
4696 pdmR3DevHlp_CritSectLeave,
4697 pdmR3DevHlp_CritSectIsOwner,
4698 pdmR3DevHlp_CritSectIsInitialized,
4699 pdmR3DevHlp_CritSectHasWaiters,
4700 pdmR3DevHlp_CritSectGetRecursion,
4701 pdmR3DevHlp_CritSectScheduleExitEvent,
4702 pdmR3DevHlp_CritSectDelete,
4703 pdmR3DevHlp_ThreadCreate,
4704 PDMR3ThreadDestroy,
4705 PDMR3ThreadIAmSuspending,
4706 PDMR3ThreadIAmRunning,
4707 PDMR3ThreadSleep,
4708 PDMR3ThreadSuspend,
4709 PDMR3ThreadResume,
4710 pdmR3DevHlp_SetAsyncNotification,
4711 pdmR3DevHlp_AsyncNotificationCompleted,
4712 pdmR3DevHlp_RTCRegister,
4713 pdmR3DevHlp_PCIBusRegister,
4714 pdmR3DevHlp_IommuRegister,
4715 pdmR3DevHlp_PICRegister,
4716 pdmR3DevHlp_ApicRegister,
4717 pdmR3DevHlp_IoApicRegister,
4718 pdmR3DevHlp_HpetRegister,
4719 pdmR3DevHlp_PciRawRegister,
4720 pdmR3DevHlp_DMACRegister,
4721 pdmR3DevHlp_DMARegister,
4722 pdmR3DevHlp_DMAReadMemory,
4723 pdmR3DevHlp_DMAWriteMemory,
4724 pdmR3DevHlp_DMASetDREQ,
4725 pdmR3DevHlp_DMAGetChannelMode,
4726 pdmR3DevHlp_DMASchedule,
4727 pdmR3DevHlp_CMOSWrite,
4728 pdmR3DevHlp_CMOSRead,
4729 pdmR3DevHlp_AssertEMT,
4730 pdmR3DevHlp_AssertOther,
4731 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4732 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4733 pdmR3DevHlp_CallR0,
4734 pdmR3DevHlp_VMGetSuspendReason,
4735 pdmR3DevHlp_VMGetResumeReason,
4736 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4737 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4738 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4739 pdmR3DevHlp_CpuGetGuestMicroarch,
4740 0,
4741 0,
4742 0,
4743 0,
4744 0,
4745 0,
4746 0,
4747 0,
4748 0,
4749 0,
4750 pdmR3DevHlp_Untrusted_GetUVM,
4751 pdmR3DevHlp_Untrusted_GetVM,
4752 pdmR3DevHlp_Untrusted_GetVMCPU,
4753 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
4754 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
4755 pdmR3DevHlp_Untrusted_FirmwareRegister,
4756 pdmR3DevHlp_Untrusted_VMReset,
4757 pdmR3DevHlp_Untrusted_VMSuspend,
4758 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
4759 pdmR3DevHlp_Untrusted_VMPowerOff,
4760 pdmR3DevHlp_Untrusted_A20IsEnabled,
4761 pdmR3DevHlp_Untrusted_A20Set,
4762 pdmR3DevHlp_Untrusted_GetCpuId,
4763 pdmR3DevHlp_TMTimeVirtGet,
4764 pdmR3DevHlp_TMTimeVirtGetFreq,
4765 pdmR3DevHlp_TMTimeVirtGetNano,
4766 pdmR3DevHlp_Untrusted_GetSupDrvSession,
4767 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
4768 pdmR3DevHlp_Untrusted_PGMHandlerPhysicalTypeRegister,
4769 PDM_DEVHLPR3_VERSION /* the end */
4770};
4771
4772
4773
4774/**
4775 * Queue consumer callback for internal component.
4776 *
4777 * @returns Success indicator.
4778 * If false the item will not be removed and the flushing will stop.
4779 * @param pVM The cross context VM structure.
4780 * @param pItem The item to consume. Upon return this item will be freed.
4781 */
4782DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
4783{
4784 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
4785 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
4786 switch (pTask->enmOp)
4787 {
4788 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
4789 PDMIsaSetIrq(pVM, pTask->u.IsaSetIRQ.iIrq, pTask->u.IsaSetIRQ.iLevel, pTask->u.IsaSetIRQ.uTagSrc);
4790 break;
4791
4792 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
4793 {
4794 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
4795 PPDMPCIDEV pPciDev = pTask->u.PciSetIRQ.pPciDevR3;
4796 if (pPciDev)
4797 {
4798 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
4799 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
4800 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
4801
4802 pdmLock(pVM);
4803 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIRQ.iIrq,
4804 pTask->u.PciSetIRQ.iLevel, pTask->u.PciSetIRQ.uTagSrc);
4805 pdmUnlock(pVM);
4806 }
4807 else
4808 AssertReleaseMsgFailed(("No PCI device registered!\n"));
4809 break;
4810 }
4811
4812 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
4813 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIRQ.iIrq, pTask->u.IoApicSetIRQ.iLevel, pTask->u.IoApicSetIRQ.uTagSrc);
4814 break;
4815
4816 default:
4817 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
4818 break;
4819 }
4820 return true;
4821}
4822
4823/** @} */
4824
Note: See TracBrowser for help on using the repository browser.

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