VirtualBox

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

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

AMD IOMMU: bugref:9654 Skeletal bits.

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