VirtualBox

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

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

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 183.7 KB
Line 
1/* $Id: PDMDevHlp.cpp 82968 2020-02-04 10:35:17Z 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,pfnPICRegister} */
3250static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
3251{
3252 PDMDEV_ASSERT_DEVINS(pDevIns);
3253 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3254 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
3255 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
3256 PVM pVM = pDevIns->Internal.s.pVMR3;
3257
3258 /*
3259 * Validate input.
3260 */
3261 AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
3262 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
3263 VERR_INVALID_PARAMETER);
3264 AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
3265 AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
3266 AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
3267 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
3268 VERR_INVALID_PARAMETER);
3269 AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
3270
3271 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3272 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3273
3274 /*
3275 * Only one PIC device.
3276 */
3277 AssertMsgReturn(pVM->pdm.s.Pic.pDevInsR3 == NULL, ("%s/%d: Only one PIC!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3278 VERR_ALREADY_EXISTS);
3279
3280 /*
3281 * Take down the callbacks and instance.
3282 */
3283 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3284 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrq;
3285 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterrupt;
3286 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3287
3288 /* set the helper pointer and return. */
3289 *ppPicHlp = &g_pdmR3DevPicHlp;
3290 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3291 return VINF_SUCCESS;
3292}
3293
3294
3295/** @interface_method_impl{PDMDEVHLPR3,pfnApicRegister} */
3296static DECLCALLBACK(int) pdmR3DevHlp_ApicRegister(PPDMDEVINS pDevIns)
3297{
3298 PDMDEV_ASSERT_DEVINS(pDevIns);
3299
3300 /*
3301 * Validate caller context.
3302 */
3303 PVM pVM = pDevIns->Internal.s.pVMR3;
3304 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3305 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3306
3307 /*
3308 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3309 * as they need to communicate and share state easily.
3310 */
3311 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 == NULL,
3312 ("%s/%u: Only one APIC device is supported!\n", pDevIns->pReg->szName, pDevIns->iInstance),
3313 VERR_ALREADY_EXISTS);
3314
3315 /*
3316 * Set the ring-3 and raw-mode bits, leave the ring-0 to ring-0 setup.
3317 */
3318 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3319 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3320 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3321
3322 LogFlow(("pdmR3DevHlp_ApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3323 return VINF_SUCCESS;
3324}
3325
3326
3327/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicRegister} */
3328static DECLCALLBACK(int) pdmR3DevHlp_IoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
3329{
3330 PDMDEV_ASSERT_DEVINS(pDevIns);
3331 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
3332 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
3333 PVM pVM = pDevIns->Internal.s.pVMR3;
3334
3335 /*
3336 * Validate input.
3337 */
3338 AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
3339 ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
3340 VERR_VERSION_MISMATCH);
3341 AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
3342 AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
3343 AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
3344 AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
3345 ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
3346 VERR_VERSION_MISMATCH);
3347 AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
3348 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3349 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3350
3351 /*
3352 * The I/O APIC requires the APIC to be present (hacks++).
3353 * If the I/O APIC does GC stuff so must the APIC.
3354 */
3355 AssertMsgReturn(pVM->pdm.s.Apic.pDevInsR3 != NULL, ("Configuration error / Init order error! No APIC!\n"), VERR_WRONG_ORDER);
3356
3357 /*
3358 * Only one I/O APIC device.
3359 */
3360 AssertMsgReturn(pVM->pdm.s.IoApic.pDevInsR3 == NULL,
3361 ("Only one IOAPIC device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3362 VERR_ALREADY_EXISTS);
3363
3364 /*
3365 * Initialize the R3 bits.
3366 */
3367 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
3368 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrq;
3369 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsi;
3370 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoi;
3371 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3372
3373 /* set the helper pointer and return. */
3374 *ppIoApicHlp = &g_pdmR3DevIoApicHlp;
3375 LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3376 return VINF_SUCCESS;
3377}
3378
3379
3380/** @interface_method_impl{PDMDEVHLPR3,pfnHpetRegister} */
3381static DECLCALLBACK(int) pdmR3DevHlp_HpetRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
3382{
3383 PDMDEV_ASSERT_DEVINS(pDevIns);
3384 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3385 PVM pVM = pDevIns->Internal.s.pVMR3;
3386
3387 /*
3388 * Validate input.
3389 */
3390 AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
3391 ("%s/%u: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
3392 VERR_VERSION_MISMATCH);
3393 AssertPtrReturn(ppHpetHlpR3, VERR_INVALID_POINTER);
3394 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3395 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
3396
3397 /*
3398 * Only one HPET device.
3399 */
3400 AssertMsgReturn(pVM->pdm.s.pHpet == NULL,
3401 ("Only one HPET device is supported! (caller %s/%d)\n", pDevIns->pReg->szName, pDevIns->iInstance),
3402 VERR_ALREADY_EXISTS);
3403
3404 /*
3405 * Do the job (what there is of it).
3406 */
3407 pVM->pdm.s.pHpet = pDevIns;
3408 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
3409
3410 LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3411 return VINF_SUCCESS;
3412}
3413
3414
3415/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
3416static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
3417{
3418 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
3419 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3420 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3421
3422 /*
3423 * Validate input.
3424 */
3425 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
3426 {
3427 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
3428 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3429 return VERR_INVALID_PARAMETER;
3430 }
3431
3432 if (!ppPciRawHlpR3)
3433 {
3434 Assert(ppPciRawHlpR3);
3435 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3436 return VERR_INVALID_PARAMETER;
3437 }
3438
3439 /* set the helper pointer and return. */
3440 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
3441 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3442 return VINF_SUCCESS;
3443}
3444
3445
3446/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
3447static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
3448{
3449 PDMDEV_ASSERT_DEVINS(pDevIns);
3450 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3451 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",
3452 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
3453 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
3454
3455 /*
3456 * Validate input.
3457 */
3458 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
3459 {
3460 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
3461 PDM_DMACREG_VERSION));
3462 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
3463 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3464 return VERR_INVALID_PARAMETER;
3465 }
3466 if ( !pDmacReg->pfnRun
3467 || !pDmacReg->pfnRegister
3468 || !pDmacReg->pfnReadMemory
3469 || !pDmacReg->pfnWriteMemory
3470 || !pDmacReg->pfnSetDREQ
3471 || !pDmacReg->pfnGetChannelMode)
3472 {
3473 Assert(pDmacReg->pfnRun);
3474 Assert(pDmacReg->pfnRegister);
3475 Assert(pDmacReg->pfnReadMemory);
3476 Assert(pDmacReg->pfnWriteMemory);
3477 Assert(pDmacReg->pfnSetDREQ);
3478 Assert(pDmacReg->pfnGetChannelMode);
3479 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3480 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3481 return VERR_INVALID_PARAMETER;
3482 }
3483
3484 if (!ppDmacHlp)
3485 {
3486 Assert(ppDmacHlp);
3487 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
3488 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3489 return VERR_INVALID_PARAMETER;
3490 }
3491
3492 /*
3493 * Only one DMA device.
3494 */
3495 PVM pVM = pDevIns->Internal.s.pVMR3;
3496 if (pVM->pdm.s.pDmac)
3497 {
3498 AssertMsgFailed(("Only one DMA device is supported!\n"));
3499 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3500 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3501 return VERR_INVALID_PARAMETER;
3502 }
3503
3504 /*
3505 * Allocate and initialize pci bus structure.
3506 */
3507 int rc = VINF_SUCCESS;
3508 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
3509 if (pDmac)
3510 {
3511 pDmac->pDevIns = pDevIns;
3512 pDmac->Reg = *pDmacReg;
3513 pVM->pdm.s.pDmac = pDmac;
3514
3515 /* set the helper pointer. */
3516 *ppDmacHlp = &g_pdmR3DevDmacHlp;
3517 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
3518 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3519 }
3520 else
3521 rc = VERR_NO_MEMORY;
3522
3523 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
3524 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3525 return rc;
3526}
3527
3528
3529/**
3530 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
3531 */
3532static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
3533{
3534 PDMDEV_ASSERT_DEVINS(pDevIns);
3535 PVM pVM = pDevIns->Internal.s.pVMR3;
3536 VM_ASSERT_EMT(pVM);
3537 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
3538 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
3539
3540 if (pVM->pdm.s.pvVMMDevHeap == NULL)
3541 {
3542 pVM->pdm.s.pvVMMDevHeap = pvHeap;
3543 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3544 pVM->pdm.s.cbVMMDevHeap = cbHeap;
3545 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
3546 }
3547 else
3548 {
3549 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
3550 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
3551 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
3552 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
3553 {
3554 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
3555 if (pVM->pdm.s.pfnVMMDevHeapNotify)
3556 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
3557 }
3558 }
3559
3560 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
3561 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3562 return VINF_SUCCESS;
3563}
3564
3565
3566/**
3567 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
3568 */
3569static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
3570{
3571 PDMDEV_ASSERT_DEVINS(pDevIns);
3572 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3573 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
3574 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
3575
3576 /*
3577 * Validate input.
3578 */
3579 if (pFwReg->u32Version != PDM_FWREG_VERSION)
3580 {
3581 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
3582 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
3583 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3584 return VERR_INVALID_PARAMETER;
3585 }
3586 if (!pFwReg->pfnIsHardReset)
3587 {
3588 Assert(pFwReg->pfnIsHardReset);
3589 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3590 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3591 return VERR_INVALID_PARAMETER;
3592 }
3593
3594 if (!ppFwHlp)
3595 {
3596 Assert(ppFwHlp);
3597 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
3598 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3599 return VERR_INVALID_PARAMETER;
3600 }
3601
3602 /*
3603 * Only one DMA device.
3604 */
3605 PVM pVM = pDevIns->Internal.s.pVMR3;
3606 if (pVM->pdm.s.pFirmware)
3607 {
3608 AssertMsgFailed(("Only one firmware device is supported!\n"));
3609 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3610 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3611 return VERR_INVALID_PARAMETER;
3612 }
3613
3614 /*
3615 * Allocate and initialize pci bus structure.
3616 */
3617 int rc = VINF_SUCCESS;
3618 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
3619 if (pFirmware)
3620 {
3621 pFirmware->pDevIns = pDevIns;
3622 pFirmware->Reg = *pFwReg;
3623 pVM->pdm.s.pFirmware = pFirmware;
3624
3625 /* set the helper pointer. */
3626 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
3627 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
3628 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3629 }
3630 else
3631 rc = VERR_NO_MEMORY;
3632
3633 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
3634 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3635 return rc;
3636}
3637
3638
3639/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
3640static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
3641{
3642 PDMDEV_ASSERT_DEVINS(pDevIns);
3643 PVM pVM = pDevIns->Internal.s.pVMR3;
3644 VM_ASSERT_EMT(pVM);
3645 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
3646 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
3647
3648 /*
3649 * We postpone this operation because we're likely to be inside a I/O instruction
3650 * and the EIP will be updated when we return.
3651 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
3652 */
3653 bool fHaltOnReset;
3654 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
3655 if (RT_SUCCESS(rc) && fHaltOnReset)
3656 {
3657 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
3658 rc = VINF_EM_HALT;
3659 }
3660 else
3661 {
3662 pVM->pdm.s.fResetFlags = fFlags;
3663 VM_FF_SET(pVM, VM_FF_RESET);
3664 rc = VINF_EM_RESET;
3665 }
3666
3667 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3668 return rc;
3669}
3670
3671
3672/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
3673static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
3674{
3675 int rc;
3676 PDMDEV_ASSERT_DEVINS(pDevIns);
3677 PVM pVM = pDevIns->Internal.s.pVMR3;
3678 VM_ASSERT_EMT(pVM);
3679 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
3680 pDevIns->pReg->szName, pDevIns->iInstance));
3681
3682 /** @todo Always take the SMP path - fewer code paths. */
3683 if (pVM->cCpus > 1)
3684 {
3685 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
3686 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
3687 AssertRC(rc);
3688 rc = VINF_EM_SUSPEND;
3689 }
3690 else
3691 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3692
3693 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3694 return rc;
3695}
3696
3697
3698/**
3699 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
3700 * EMT request to avoid deadlocks.
3701 *
3702 * @returns VBox status code fit for scheduling.
3703 * @param pVM The cross context VM structure.
3704 * @param pDevIns The device that triggered this action.
3705 */
3706static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
3707{
3708 /*
3709 * Suspend the VM first then do the saving.
3710 */
3711 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
3712 if (RT_SUCCESS(rc))
3713 {
3714 PUVM pUVM = pVM->pUVM;
3715 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
3716
3717 /*
3718 * On success, power off the VM, on failure we'll leave it suspended.
3719 */
3720 if (RT_SUCCESS(rc))
3721 {
3722 rc = VMR3PowerOff(pVM->pUVM);
3723 if (RT_FAILURE(rc))
3724 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
3725 }
3726 else
3727 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
3728 }
3729 else
3730 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
3731 return rc;
3732}
3733
3734
3735/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
3736static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
3737{
3738 PDMDEV_ASSERT_DEVINS(pDevIns);
3739 PVM pVM = pDevIns->Internal.s.pVMR3;
3740 VM_ASSERT_EMT(pVM);
3741 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
3742 pDevIns->pReg->szName, pDevIns->iInstance));
3743
3744 int rc;
3745 if ( pVM->pUVM->pVmm2UserMethods
3746 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
3747 {
3748 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
3749 if (RT_SUCCESS(rc))
3750 {
3751 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
3752 rc = VINF_EM_SUSPEND;
3753 }
3754 }
3755 else
3756 rc = VERR_NOT_SUPPORTED;
3757
3758 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3759 return rc;
3760}
3761
3762
3763/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
3764static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
3765{
3766 int rc;
3767 PDMDEV_ASSERT_DEVINS(pDevIns);
3768 PVM pVM = pDevIns->Internal.s.pVMR3;
3769 VM_ASSERT_EMT(pVM);
3770 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
3771 pDevIns->pReg->szName, pDevIns->iInstance));
3772
3773 /** @todo Always take the SMP path - fewer code paths. */
3774 if (pVM->cCpus > 1)
3775 {
3776 /* We might be holding locks here and could cause a deadlock since
3777 VMR3PowerOff rendezvous with the other CPUs. */
3778 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
3779 AssertRC(rc);
3780 /* Set the VCPU state to stopped here as well to make sure no
3781 inconsistency with the EM state occurs. */
3782 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
3783 rc = VINF_EM_OFF;
3784 }
3785 else
3786 rc = VMR3PowerOff(pVM->pUVM);
3787
3788 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3789 return rc;
3790}
3791
3792
3793/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
3794static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
3795{
3796 PDMDEV_ASSERT_DEVINS(pDevIns);
3797 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3798
3799 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
3800
3801 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
3802 return fRc;
3803}
3804
3805
3806/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
3807static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
3808{
3809 PDMDEV_ASSERT_DEVINS(pDevIns);
3810 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3811 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
3812 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
3813}
3814
3815
3816/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
3817static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
3818 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
3819{
3820 PDMDEV_ASSERT_DEVINS(pDevIns);
3821 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3822
3823 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
3824 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
3825 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
3826
3827 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
3828
3829 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
3830 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
3831}
3832
3833
3834/**
3835 * The device helper structure for trusted devices.
3836 */
3837const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
3838{
3839 PDM_DEVHLPR3_VERSION,
3840 pdmR3DevHlp_IoPortCreateEx,
3841 pdmR3DevHlp_IoPortMap,
3842 pdmR3DevHlp_IoPortUnmap,
3843 pdmR3DevHlp_IoPortGetMappingAddress,
3844 pdmR3DevHlp_MmioCreateEx,
3845 pdmR3DevHlp_MmioMap,
3846 pdmR3DevHlp_MmioUnmap,
3847 pdmR3DevHlp_MmioReduce,
3848 pdmR3DevHlp_MmioGetMappingAddress,
3849 pdmR3DevHlp_Mmio2Create,
3850 pdmR3DevHlp_Mmio2Destroy,
3851 pdmR3DevHlp_Mmio2Map,
3852 pdmR3DevHlp_Mmio2Unmap,
3853 pdmR3DevHlp_Mmio2Reduce,
3854 pdmR3DevHlp_Mmio2GetMappingAddress,
3855 pdmR3DevHlp_Mmio2ChangeRegionNo,
3856 pdmR3DevHlp_ROMRegister,
3857 pdmR3DevHlp_ROMProtectShadow,
3858 pdmR3DevHlp_SSMRegister,
3859 SSMR3PutStruct,
3860 SSMR3PutStructEx,
3861 SSMR3PutBool,
3862 SSMR3PutU8,
3863 SSMR3PutS8,
3864 SSMR3PutU16,
3865 SSMR3PutS16,
3866 SSMR3PutU32,
3867 SSMR3PutS32,
3868 SSMR3PutU64,
3869 SSMR3PutS64,
3870 SSMR3PutU128,
3871 SSMR3PutS128,
3872 SSMR3PutUInt,
3873 SSMR3PutSInt,
3874 SSMR3PutGCUInt,
3875 SSMR3PutGCUIntReg,
3876 SSMR3PutGCPhys32,
3877 SSMR3PutGCPhys64,
3878 SSMR3PutGCPhys,
3879 SSMR3PutGCPtr,
3880 SSMR3PutGCUIntPtr,
3881 SSMR3PutRCPtr,
3882 SSMR3PutIOPort,
3883 SSMR3PutSel,
3884 SSMR3PutMem,
3885 SSMR3PutStrZ,
3886 SSMR3GetStruct,
3887 SSMR3GetStructEx,
3888 SSMR3GetBool,
3889 SSMR3GetBoolV,
3890 SSMR3GetU8,
3891 SSMR3GetU8V,
3892 SSMR3GetS8,
3893 SSMR3GetS8V,
3894 SSMR3GetU16,
3895 SSMR3GetU16V,
3896 SSMR3GetS16,
3897 SSMR3GetS16V,
3898 SSMR3GetU32,
3899 SSMR3GetU32V,
3900 SSMR3GetS32,
3901 SSMR3GetS32V,
3902 SSMR3GetU64,
3903 SSMR3GetU64V,
3904 SSMR3GetS64,
3905 SSMR3GetS64V,
3906 SSMR3GetU128,
3907 SSMR3GetU128V,
3908 SSMR3GetS128,
3909 SSMR3GetS128V,
3910 SSMR3GetGCPhys32,
3911 SSMR3GetGCPhys32V,
3912 SSMR3GetGCPhys64,
3913 SSMR3GetGCPhys64V,
3914 SSMR3GetGCPhys,
3915 SSMR3GetGCPhysV,
3916 SSMR3GetUInt,
3917 SSMR3GetSInt,
3918 SSMR3GetGCUInt,
3919 SSMR3GetGCUIntReg,
3920 SSMR3GetGCPtr,
3921 SSMR3GetGCUIntPtr,
3922 SSMR3GetRCPtr,
3923 SSMR3GetIOPort,
3924 SSMR3GetSel,
3925 SSMR3GetMem,
3926 SSMR3GetStrZ,
3927 SSMR3GetStrZEx,
3928 SSMR3Skip,
3929 SSMR3SkipToEndOfUnit,
3930 SSMR3SetLoadError,
3931 SSMR3SetLoadErrorV,
3932 SSMR3SetCfgError,
3933 SSMR3SetCfgErrorV,
3934 SSMR3HandleGetStatus,
3935 SSMR3HandleGetAfter,
3936 SSMR3HandleIsLiveSave,
3937 SSMR3HandleMaxDowntime,
3938 SSMR3HandleHostBits,
3939 SSMR3HandleRevision,
3940 SSMR3HandleVersion,
3941 SSMR3HandleHostOSAndArch,
3942 pdmR3DevHlp_TMTimerCreate,
3943 pdmR3DevHlp_TimerCreate,
3944 pdmR3DevHlp_TimerToPtr,
3945 pdmR3DevHlp_TimerFromMicro,
3946 pdmR3DevHlp_TimerFromMilli,
3947 pdmR3DevHlp_TimerFromNano,
3948 pdmR3DevHlp_TimerGet,
3949 pdmR3DevHlp_TimerGetFreq,
3950 pdmR3DevHlp_TimerGetNano,
3951 pdmR3DevHlp_TimerIsActive,
3952 pdmR3DevHlp_TimerIsLockOwner,
3953 pdmR3DevHlp_TimerLockClock,
3954 pdmR3DevHlp_TimerLockClock2,
3955 pdmR3DevHlp_TimerSet,
3956 pdmR3DevHlp_TimerSetFrequencyHint,
3957 pdmR3DevHlp_TimerSetMicro,
3958 pdmR3DevHlp_TimerSetMillies,
3959 pdmR3DevHlp_TimerSetNano,
3960 pdmR3DevHlp_TimerSetRelative,
3961 pdmR3DevHlp_TimerStop,
3962 pdmR3DevHlp_TimerUnlockClock,
3963 pdmR3DevHlp_TimerUnlockClock2,
3964 pdmR3DevHlp_TimerSetCritSect,
3965 pdmR3DevHlp_TimerSave,
3966 pdmR3DevHlp_TimerLoad,
3967 pdmR3DevHlp_TimerDestroy,
3968 TMR3TimerSkip,
3969 pdmR3DevHlp_TMUtcNow,
3970 CFGMR3Exists,
3971 CFGMR3QueryType,
3972 CFGMR3QuerySize,
3973 CFGMR3QueryInteger,
3974 CFGMR3QueryIntegerDef,
3975 CFGMR3QueryString,
3976 CFGMR3QueryStringDef,
3977 CFGMR3QueryBytes,
3978 CFGMR3QueryU64,
3979 CFGMR3QueryU64Def,
3980 CFGMR3QueryS64,
3981 CFGMR3QueryS64Def,
3982 CFGMR3QueryU32,
3983 CFGMR3QueryU32Def,
3984 CFGMR3QueryS32,
3985 CFGMR3QueryS32Def,
3986 CFGMR3QueryU16,
3987 CFGMR3QueryU16Def,
3988 CFGMR3QueryS16,
3989 CFGMR3QueryS16Def,
3990 CFGMR3QueryU8,
3991 CFGMR3QueryU8Def,
3992 CFGMR3QueryS8,
3993 CFGMR3QueryS8Def,
3994 CFGMR3QueryBool,
3995 CFGMR3QueryBoolDef,
3996 CFGMR3QueryPort,
3997 CFGMR3QueryPortDef,
3998 CFGMR3QueryUInt,
3999 CFGMR3QueryUIntDef,
4000 CFGMR3QuerySInt,
4001 CFGMR3QuerySIntDef,
4002 CFGMR3QueryPtr,
4003 CFGMR3QueryPtrDef,
4004 CFGMR3QueryGCPtr,
4005 CFGMR3QueryGCPtrDef,
4006 CFGMR3QueryGCPtrU,
4007 CFGMR3QueryGCPtrUDef,
4008 CFGMR3QueryGCPtrS,
4009 CFGMR3QueryGCPtrSDef,
4010 CFGMR3QueryStringAlloc,
4011 CFGMR3QueryStringAllocDef,
4012 CFGMR3GetParent,
4013 CFGMR3GetChild,
4014 CFGMR3GetChildF,
4015 CFGMR3GetChildFV,
4016 CFGMR3GetFirstChild,
4017 CFGMR3GetNextChild,
4018 CFGMR3GetName,
4019 CFGMR3GetNameLen,
4020 CFGMR3AreChildrenValid,
4021 CFGMR3GetFirstValue,
4022 CFGMR3GetNextValue,
4023 CFGMR3GetValueName,
4024 CFGMR3GetValueNameLen,
4025 CFGMR3GetValueType,
4026 CFGMR3AreValuesValid,
4027 CFGMR3ValidateConfig,
4028 pdmR3DevHlp_PhysRead,
4029 pdmR3DevHlp_PhysWrite,
4030 pdmR3DevHlp_PhysGCPhys2CCPtr,
4031 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4032 pdmR3DevHlp_PhysReleasePageMappingLock,
4033 pdmR3DevHlp_PhysReadGCVirt,
4034 pdmR3DevHlp_PhysWriteGCVirt,
4035 pdmR3DevHlp_PhysGCPtr2GCPhys,
4036 pdmR3DevHlp_MMHeapAlloc,
4037 pdmR3DevHlp_MMHeapAllocZ,
4038 pdmR3DevHlp_MMHeapFree,
4039 pdmR3DevHlp_VMState,
4040 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4041 pdmR3DevHlp_VMSetError,
4042 pdmR3DevHlp_VMSetErrorV,
4043 pdmR3DevHlp_VMSetRuntimeError,
4044 pdmR3DevHlp_VMSetRuntimeErrorV,
4045 pdmR3DevHlp_DBGFStopV,
4046 pdmR3DevHlp_DBGFInfoRegister,
4047 pdmR3DevHlp_DBGFInfoRegisterArgv,
4048 pdmR3DevHlp_DBGFRegRegister,
4049 pdmR3DevHlp_DBGFTraceBuf,
4050 pdmR3DevHlp_STAMRegister,
4051 pdmR3DevHlp_STAMRegisterV,
4052 pdmR3DevHlp_PCIRegister,
4053 pdmR3DevHlp_PCIRegisterMsi,
4054 pdmR3DevHlp_PCIIORegionRegister,
4055 pdmR3DevHlp_PCIInterceptConfigAccesses,
4056 pdmR3DevHlp_PCIConfigWrite,
4057 pdmR3DevHlp_PCIConfigRead,
4058 pdmR3DevHlp_PCIPhysRead,
4059 pdmR3DevHlp_PCIPhysWrite,
4060 pdmR3DevHlp_PCISetIrq,
4061 pdmR3DevHlp_PCISetIrqNoWait,
4062 pdmR3DevHlp_ISASetIrq,
4063 pdmR3DevHlp_ISASetIrqNoWait,
4064 pdmR3DevHlp_IoApicSendMsi,
4065 pdmR3DevHlp_DriverAttach,
4066 pdmR3DevHlp_DriverDetach,
4067 pdmR3DevHlp_DriverReconfigure,
4068 pdmR3DevHlp_QueueCreatePtr,
4069 pdmR3DevHlp_QueueCreate,
4070 pdmR3DevHlp_QueueToPtr,
4071 pdmR3DevHlp_QueueAlloc,
4072 pdmR3DevHlp_QueueInsert,
4073 pdmR3DevHlp_QueueInsertEx,
4074 pdmR3DevHlp_QueueFlushIfNecessary,
4075 pdmR3DevHlp_TaskCreate,
4076 pdmR3DevHlp_TaskTrigger,
4077 pdmR3DevHlp_SUPSemEventCreate,
4078 pdmR3DevHlp_SUPSemEventClose,
4079 pdmR3DevHlp_SUPSemEventSignal,
4080 pdmR3DevHlp_SUPSemEventWaitNoResume,
4081 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4082 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4083 pdmR3DevHlp_SUPSemEventGetResolution,
4084 pdmR3DevHlp_SUPSemEventMultiCreate,
4085 pdmR3DevHlp_SUPSemEventMultiClose,
4086 pdmR3DevHlp_SUPSemEventMultiSignal,
4087 pdmR3DevHlp_SUPSemEventMultiReset,
4088 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4089 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4090 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4091 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4092 pdmR3DevHlp_CritSectInit,
4093 pdmR3DevHlp_CritSectGetNop,
4094 pdmR3DevHlp_CritSectGetNopR0,
4095 pdmR3DevHlp_CritSectGetNopRC,
4096 pdmR3DevHlp_SetDeviceCritSect,
4097 pdmR3DevHlp_CritSectYield,
4098 pdmR3DevHlp_CritSectEnter,
4099 pdmR3DevHlp_CritSectEnterDebug,
4100 pdmR3DevHlp_CritSectTryEnter,
4101 pdmR3DevHlp_CritSectTryEnterDebug,
4102 pdmR3DevHlp_CritSectLeave,
4103 pdmR3DevHlp_CritSectIsOwner,
4104 pdmR3DevHlp_CritSectIsInitialized,
4105 pdmR3DevHlp_CritSectHasWaiters,
4106 pdmR3DevHlp_CritSectGetRecursion,
4107 pdmR3DevHlp_CritSectScheduleExitEvent,
4108 pdmR3DevHlp_CritSectDelete,
4109 pdmR3DevHlp_ThreadCreate,
4110 PDMR3ThreadDestroy,
4111 PDMR3ThreadIAmSuspending,
4112 PDMR3ThreadIAmRunning,
4113 PDMR3ThreadSleep,
4114 PDMR3ThreadSuspend,
4115 PDMR3ThreadResume,
4116 pdmR3DevHlp_SetAsyncNotification,
4117 pdmR3DevHlp_AsyncNotificationCompleted,
4118 pdmR3DevHlp_RTCRegister,
4119 pdmR3DevHlp_PCIBusRegister,
4120 pdmR3DevHlp_PICRegister,
4121 pdmR3DevHlp_ApicRegister,
4122 pdmR3DevHlp_IoApicRegister,
4123 pdmR3DevHlp_HpetRegister,
4124 pdmR3DevHlp_PciRawRegister,
4125 pdmR3DevHlp_DMACRegister,
4126 pdmR3DevHlp_DMARegister,
4127 pdmR3DevHlp_DMAReadMemory,
4128 pdmR3DevHlp_DMAWriteMemory,
4129 pdmR3DevHlp_DMASetDREQ,
4130 pdmR3DevHlp_DMAGetChannelMode,
4131 pdmR3DevHlp_DMASchedule,
4132 pdmR3DevHlp_CMOSWrite,
4133 pdmR3DevHlp_CMOSRead,
4134 pdmR3DevHlp_AssertEMT,
4135 pdmR3DevHlp_AssertOther,
4136 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4137 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4138 pdmR3DevHlp_CallR0,
4139 pdmR3DevHlp_VMGetSuspendReason,
4140 pdmR3DevHlp_VMGetResumeReason,
4141 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4142 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4143 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4144 0,
4145 0,
4146 0,
4147 0,
4148 0,
4149 0,
4150 0,
4151 0,
4152 0,
4153 0,
4154 pdmR3DevHlp_GetUVM,
4155 pdmR3DevHlp_GetVM,
4156 pdmR3DevHlp_GetVMCPU,
4157 pdmR3DevHlp_GetCurrentCpuId,
4158 pdmR3DevHlp_RegisterVMMDevHeap,
4159 pdmR3DevHlp_FirmwareRegister,
4160 pdmR3DevHlp_VMReset,
4161 pdmR3DevHlp_VMSuspend,
4162 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4163 pdmR3DevHlp_VMPowerOff,
4164 pdmR3DevHlp_A20IsEnabled,
4165 pdmR3DevHlp_A20Set,
4166 pdmR3DevHlp_GetCpuId,
4167 pdmR3DevHlp_TMTimeVirtGet,
4168 pdmR3DevHlp_TMTimeVirtGetFreq,
4169 pdmR3DevHlp_TMTimeVirtGetNano,
4170 pdmR3DevHlp_GetSupDrvSession,
4171 pdmR3DevHlp_QueryGenericUserObject,
4172 PDM_DEVHLPR3_VERSION /* the end */
4173};
4174
4175
4176
4177
4178/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
4179static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
4180{
4181 PDMDEV_ASSERT_DEVINS(pDevIns);
4182 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4183 return NULL;
4184}
4185
4186
4187/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
4188static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
4189{
4190 PDMDEV_ASSERT_DEVINS(pDevIns);
4191 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4192 return NULL;
4193}
4194
4195
4196/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
4197static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
4198{
4199 PDMDEV_ASSERT_DEVINS(pDevIns);
4200 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4201 return NULL;
4202}
4203
4204
4205/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
4206static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(PPDMDEVINS pDevIns)
4207{
4208 PDMDEV_ASSERT_DEVINS(pDevIns);
4209 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4210 return NIL_VMCPUID;
4211}
4212
4213
4214/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
4215static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
4216 RTR3PTR pvHeap, unsigned cbHeap)
4217{
4218 PDMDEV_ASSERT_DEVINS(pDevIns);
4219 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
4220 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4221 return VERR_ACCESS_DENIED;
4222}
4223
4224
4225/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
4226static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4227{
4228 PDMDEV_ASSERT_DEVINS(pDevIns);
4229 NOREF(pFwReg); NOREF(ppFwHlp);
4230 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4231 return VERR_ACCESS_DENIED;
4232}
4233
4234
4235/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4236static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4237{
4238 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
4239 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4240 return VERR_ACCESS_DENIED;
4241}
4242
4243
4244/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4245static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
4246{
4247 PDMDEV_ASSERT_DEVINS(pDevIns);
4248 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4249 return VERR_ACCESS_DENIED;
4250}
4251
4252
4253/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4254static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4255{
4256 PDMDEV_ASSERT_DEVINS(pDevIns);
4257 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4258 return VERR_ACCESS_DENIED;
4259}
4260
4261
4262/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4263static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
4264{
4265 PDMDEV_ASSERT_DEVINS(pDevIns);
4266 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4267 return VERR_ACCESS_DENIED;
4268}
4269
4270
4271/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4272static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
4273{
4274 PDMDEV_ASSERT_DEVINS(pDevIns);
4275 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4276 return false;
4277}
4278
4279
4280/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4281static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4282{
4283 PDMDEV_ASSERT_DEVINS(pDevIns);
4284 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4285 NOREF(fEnable);
4286}
4287
4288
4289/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4290static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4291 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4292{
4293 PDMDEV_ASSERT_DEVINS(pDevIns);
4294 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
4295 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4296}
4297
4298
4299/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
4300static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(PPDMDEVINS pDevIns)
4301{
4302 PDMDEV_ASSERT_DEVINS(pDevIns);
4303 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4304 return (PSUPDRVSESSION)0;
4305}
4306
4307
4308/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
4309static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
4310{
4311 PDMDEV_ASSERT_DEVINS(pDevIns);
4312 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
4313 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
4314 return NULL;
4315}
4316
4317
4318/**
4319 * The device helper structure for non-trusted devices.
4320 */
4321const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
4322{
4323 PDM_DEVHLPR3_VERSION,
4324 pdmR3DevHlp_IoPortCreateEx,
4325 pdmR3DevHlp_IoPortMap,
4326 pdmR3DevHlp_IoPortUnmap,
4327 pdmR3DevHlp_IoPortGetMappingAddress,
4328 pdmR3DevHlp_MmioCreateEx,
4329 pdmR3DevHlp_MmioMap,
4330 pdmR3DevHlp_MmioUnmap,
4331 pdmR3DevHlp_MmioReduce,
4332 pdmR3DevHlp_MmioGetMappingAddress,
4333 pdmR3DevHlp_Mmio2Create,
4334 pdmR3DevHlp_Mmio2Destroy,
4335 pdmR3DevHlp_Mmio2Map,
4336 pdmR3DevHlp_Mmio2Unmap,
4337 pdmR3DevHlp_Mmio2Reduce,
4338 pdmR3DevHlp_Mmio2GetMappingAddress,
4339 pdmR3DevHlp_Mmio2ChangeRegionNo,
4340 pdmR3DevHlp_ROMRegister,
4341 pdmR3DevHlp_ROMProtectShadow,
4342 pdmR3DevHlp_SSMRegister,
4343 SSMR3PutStruct,
4344 SSMR3PutStructEx,
4345 SSMR3PutBool,
4346 SSMR3PutU8,
4347 SSMR3PutS8,
4348 SSMR3PutU16,
4349 SSMR3PutS16,
4350 SSMR3PutU32,
4351 SSMR3PutS32,
4352 SSMR3PutU64,
4353 SSMR3PutS64,
4354 SSMR3PutU128,
4355 SSMR3PutS128,
4356 SSMR3PutUInt,
4357 SSMR3PutSInt,
4358 SSMR3PutGCUInt,
4359 SSMR3PutGCUIntReg,
4360 SSMR3PutGCPhys32,
4361 SSMR3PutGCPhys64,
4362 SSMR3PutGCPhys,
4363 SSMR3PutGCPtr,
4364 SSMR3PutGCUIntPtr,
4365 SSMR3PutRCPtr,
4366 SSMR3PutIOPort,
4367 SSMR3PutSel,
4368 SSMR3PutMem,
4369 SSMR3PutStrZ,
4370 SSMR3GetStruct,
4371 SSMR3GetStructEx,
4372 SSMR3GetBool,
4373 SSMR3GetBoolV,
4374 SSMR3GetU8,
4375 SSMR3GetU8V,
4376 SSMR3GetS8,
4377 SSMR3GetS8V,
4378 SSMR3GetU16,
4379 SSMR3GetU16V,
4380 SSMR3GetS16,
4381 SSMR3GetS16V,
4382 SSMR3GetU32,
4383 SSMR3GetU32V,
4384 SSMR3GetS32,
4385 SSMR3GetS32V,
4386 SSMR3GetU64,
4387 SSMR3GetU64V,
4388 SSMR3GetS64,
4389 SSMR3GetS64V,
4390 SSMR3GetU128,
4391 SSMR3GetU128V,
4392 SSMR3GetS128,
4393 SSMR3GetS128V,
4394 SSMR3GetGCPhys32,
4395 SSMR3GetGCPhys32V,
4396 SSMR3GetGCPhys64,
4397 SSMR3GetGCPhys64V,
4398 SSMR3GetGCPhys,
4399 SSMR3GetGCPhysV,
4400 SSMR3GetUInt,
4401 SSMR3GetSInt,
4402 SSMR3GetGCUInt,
4403 SSMR3GetGCUIntReg,
4404 SSMR3GetGCPtr,
4405 SSMR3GetGCUIntPtr,
4406 SSMR3GetRCPtr,
4407 SSMR3GetIOPort,
4408 SSMR3GetSel,
4409 SSMR3GetMem,
4410 SSMR3GetStrZ,
4411 SSMR3GetStrZEx,
4412 SSMR3Skip,
4413 SSMR3SkipToEndOfUnit,
4414 SSMR3SetLoadError,
4415 SSMR3SetLoadErrorV,
4416 SSMR3SetCfgError,
4417 SSMR3SetCfgErrorV,
4418 SSMR3HandleGetStatus,
4419 SSMR3HandleGetAfter,
4420 SSMR3HandleIsLiveSave,
4421 SSMR3HandleMaxDowntime,
4422 SSMR3HandleHostBits,
4423 SSMR3HandleRevision,
4424 SSMR3HandleVersion,
4425 SSMR3HandleHostOSAndArch,
4426 pdmR3DevHlp_TMTimerCreate,
4427 pdmR3DevHlp_TimerCreate,
4428 pdmR3DevHlp_TimerToPtr,
4429 pdmR3DevHlp_TimerFromMicro,
4430 pdmR3DevHlp_TimerFromMilli,
4431 pdmR3DevHlp_TimerFromNano,
4432 pdmR3DevHlp_TimerGet,
4433 pdmR3DevHlp_TimerGetFreq,
4434 pdmR3DevHlp_TimerGetNano,
4435 pdmR3DevHlp_TimerIsActive,
4436 pdmR3DevHlp_TimerIsLockOwner,
4437 pdmR3DevHlp_TimerLockClock,
4438 pdmR3DevHlp_TimerLockClock2,
4439 pdmR3DevHlp_TimerSet,
4440 pdmR3DevHlp_TimerSetFrequencyHint,
4441 pdmR3DevHlp_TimerSetMicro,
4442 pdmR3DevHlp_TimerSetMillies,
4443 pdmR3DevHlp_TimerSetNano,
4444 pdmR3DevHlp_TimerSetRelative,
4445 pdmR3DevHlp_TimerStop,
4446 pdmR3DevHlp_TimerUnlockClock,
4447 pdmR3DevHlp_TimerUnlockClock2,
4448 pdmR3DevHlp_TimerSetCritSect,
4449 pdmR3DevHlp_TimerSave,
4450 pdmR3DevHlp_TimerLoad,
4451 pdmR3DevHlp_TimerDestroy,
4452 TMR3TimerSkip,
4453 pdmR3DevHlp_TMUtcNow,
4454 CFGMR3Exists,
4455 CFGMR3QueryType,
4456 CFGMR3QuerySize,
4457 CFGMR3QueryInteger,
4458 CFGMR3QueryIntegerDef,
4459 CFGMR3QueryString,
4460 CFGMR3QueryStringDef,
4461 CFGMR3QueryBytes,
4462 CFGMR3QueryU64,
4463 CFGMR3QueryU64Def,
4464 CFGMR3QueryS64,
4465 CFGMR3QueryS64Def,
4466 CFGMR3QueryU32,
4467 CFGMR3QueryU32Def,
4468 CFGMR3QueryS32,
4469 CFGMR3QueryS32Def,
4470 CFGMR3QueryU16,
4471 CFGMR3QueryU16Def,
4472 CFGMR3QueryS16,
4473 CFGMR3QueryS16Def,
4474 CFGMR3QueryU8,
4475 CFGMR3QueryU8Def,
4476 CFGMR3QueryS8,
4477 CFGMR3QueryS8Def,
4478 CFGMR3QueryBool,
4479 CFGMR3QueryBoolDef,
4480 CFGMR3QueryPort,
4481 CFGMR3QueryPortDef,
4482 CFGMR3QueryUInt,
4483 CFGMR3QueryUIntDef,
4484 CFGMR3QuerySInt,
4485 CFGMR3QuerySIntDef,
4486 CFGMR3QueryPtr,
4487 CFGMR3QueryPtrDef,
4488 CFGMR3QueryGCPtr,
4489 CFGMR3QueryGCPtrDef,
4490 CFGMR3QueryGCPtrU,
4491 CFGMR3QueryGCPtrUDef,
4492 CFGMR3QueryGCPtrS,
4493 CFGMR3QueryGCPtrSDef,
4494 CFGMR3QueryStringAlloc,
4495 CFGMR3QueryStringAllocDef,
4496 CFGMR3GetParent,
4497 CFGMR3GetChild,
4498 CFGMR3GetChildF,
4499 CFGMR3GetChildFV,
4500 CFGMR3GetFirstChild,
4501 CFGMR3GetNextChild,
4502 CFGMR3GetName,
4503 CFGMR3GetNameLen,
4504 CFGMR3AreChildrenValid,
4505 CFGMR3GetFirstValue,
4506 CFGMR3GetNextValue,
4507 CFGMR3GetValueName,
4508 CFGMR3GetValueNameLen,
4509 CFGMR3GetValueType,
4510 CFGMR3AreValuesValid,
4511 CFGMR3ValidateConfig,
4512 pdmR3DevHlp_PhysRead,
4513 pdmR3DevHlp_PhysWrite,
4514 pdmR3DevHlp_PhysGCPhys2CCPtr,
4515 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4516 pdmR3DevHlp_PhysReleasePageMappingLock,
4517 pdmR3DevHlp_PhysReadGCVirt,
4518 pdmR3DevHlp_PhysWriteGCVirt,
4519 pdmR3DevHlp_PhysGCPtr2GCPhys,
4520 pdmR3DevHlp_MMHeapAlloc,
4521 pdmR3DevHlp_MMHeapAllocZ,
4522 pdmR3DevHlp_MMHeapFree,
4523 pdmR3DevHlp_VMState,
4524 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4525 pdmR3DevHlp_VMSetError,
4526 pdmR3DevHlp_VMSetErrorV,
4527 pdmR3DevHlp_VMSetRuntimeError,
4528 pdmR3DevHlp_VMSetRuntimeErrorV,
4529 pdmR3DevHlp_DBGFStopV,
4530 pdmR3DevHlp_DBGFInfoRegister,
4531 pdmR3DevHlp_DBGFInfoRegisterArgv,
4532 pdmR3DevHlp_DBGFRegRegister,
4533 pdmR3DevHlp_DBGFTraceBuf,
4534 pdmR3DevHlp_STAMRegister,
4535 pdmR3DevHlp_STAMRegisterV,
4536 pdmR3DevHlp_PCIRegister,
4537 pdmR3DevHlp_PCIRegisterMsi,
4538 pdmR3DevHlp_PCIIORegionRegister,
4539 pdmR3DevHlp_PCIInterceptConfigAccesses,
4540 pdmR3DevHlp_PCIConfigWrite,
4541 pdmR3DevHlp_PCIConfigRead,
4542 pdmR3DevHlp_PCIPhysRead,
4543 pdmR3DevHlp_PCIPhysWrite,
4544 pdmR3DevHlp_PCISetIrq,
4545 pdmR3DevHlp_PCISetIrqNoWait,
4546 pdmR3DevHlp_ISASetIrq,
4547 pdmR3DevHlp_ISASetIrqNoWait,
4548 pdmR3DevHlp_IoApicSendMsi,
4549 pdmR3DevHlp_DriverAttach,
4550 pdmR3DevHlp_DriverDetach,
4551 pdmR3DevHlp_DriverReconfigure,
4552 pdmR3DevHlp_QueueCreatePtr,
4553 pdmR3DevHlp_QueueCreate,
4554 pdmR3DevHlp_QueueToPtr,
4555 pdmR3DevHlp_QueueAlloc,
4556 pdmR3DevHlp_QueueInsert,
4557 pdmR3DevHlp_QueueInsertEx,
4558 pdmR3DevHlp_QueueFlushIfNecessary,
4559 pdmR3DevHlp_TaskCreate,
4560 pdmR3DevHlp_TaskTrigger,
4561 pdmR3DevHlp_SUPSemEventCreate,
4562 pdmR3DevHlp_SUPSemEventClose,
4563 pdmR3DevHlp_SUPSemEventSignal,
4564 pdmR3DevHlp_SUPSemEventWaitNoResume,
4565 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4566 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4567 pdmR3DevHlp_SUPSemEventGetResolution,
4568 pdmR3DevHlp_SUPSemEventMultiCreate,
4569 pdmR3DevHlp_SUPSemEventMultiClose,
4570 pdmR3DevHlp_SUPSemEventMultiSignal,
4571 pdmR3DevHlp_SUPSemEventMultiReset,
4572 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4573 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4574 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4575 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4576 pdmR3DevHlp_CritSectInit,
4577 pdmR3DevHlp_CritSectGetNop,
4578 pdmR3DevHlp_CritSectGetNopR0,
4579 pdmR3DevHlp_CritSectGetNopRC,
4580 pdmR3DevHlp_SetDeviceCritSect,
4581 pdmR3DevHlp_CritSectYield,
4582 pdmR3DevHlp_CritSectEnter,
4583 pdmR3DevHlp_CritSectEnterDebug,
4584 pdmR3DevHlp_CritSectTryEnter,
4585 pdmR3DevHlp_CritSectTryEnterDebug,
4586 pdmR3DevHlp_CritSectLeave,
4587 pdmR3DevHlp_CritSectIsOwner,
4588 pdmR3DevHlp_CritSectIsInitialized,
4589 pdmR3DevHlp_CritSectHasWaiters,
4590 pdmR3DevHlp_CritSectGetRecursion,
4591 pdmR3DevHlp_CritSectScheduleExitEvent,
4592 pdmR3DevHlp_CritSectDelete,
4593 pdmR3DevHlp_ThreadCreate,
4594 PDMR3ThreadDestroy,
4595 PDMR3ThreadIAmSuspending,
4596 PDMR3ThreadIAmRunning,
4597 PDMR3ThreadSleep,
4598 PDMR3ThreadSuspend,
4599 PDMR3ThreadResume,
4600 pdmR3DevHlp_SetAsyncNotification,
4601 pdmR3DevHlp_AsyncNotificationCompleted,
4602 pdmR3DevHlp_RTCRegister,
4603 pdmR3DevHlp_PCIBusRegister,
4604 pdmR3DevHlp_PICRegister,
4605 pdmR3DevHlp_ApicRegister,
4606 pdmR3DevHlp_IoApicRegister,
4607 pdmR3DevHlp_HpetRegister,
4608 pdmR3DevHlp_PciRawRegister,
4609 pdmR3DevHlp_DMACRegister,
4610 pdmR3DevHlp_DMARegister,
4611 pdmR3DevHlp_DMAReadMemory,
4612 pdmR3DevHlp_DMAWriteMemory,
4613 pdmR3DevHlp_DMASetDREQ,
4614 pdmR3DevHlp_DMAGetChannelMode,
4615 pdmR3DevHlp_DMASchedule,
4616 pdmR3DevHlp_CMOSWrite,
4617 pdmR3DevHlp_CMOSRead,
4618 pdmR3DevHlp_AssertEMT,
4619 pdmR3DevHlp_AssertOther,
4620 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4621 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4622 pdmR3DevHlp_CallR0,
4623 pdmR3DevHlp_VMGetSuspendReason,
4624 pdmR3DevHlp_VMGetResumeReason,
4625 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4626 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4627 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4628 0,
4629 0,
4630 0,
4631 0,
4632 0,
4633 0,
4634 0,
4635 0,
4636 0,
4637 0,
4638 pdmR3DevHlp_Untrusted_GetUVM,
4639 pdmR3DevHlp_Untrusted_GetVM,
4640 pdmR3DevHlp_Untrusted_GetVMCPU,
4641 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
4642 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
4643 pdmR3DevHlp_Untrusted_FirmwareRegister,
4644 pdmR3DevHlp_Untrusted_VMReset,
4645 pdmR3DevHlp_Untrusted_VMSuspend,
4646 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
4647 pdmR3DevHlp_Untrusted_VMPowerOff,
4648 pdmR3DevHlp_Untrusted_A20IsEnabled,
4649 pdmR3DevHlp_Untrusted_A20Set,
4650 pdmR3DevHlp_Untrusted_GetCpuId,
4651 pdmR3DevHlp_TMTimeVirtGet,
4652 pdmR3DevHlp_TMTimeVirtGetFreq,
4653 pdmR3DevHlp_TMTimeVirtGetNano,
4654 pdmR3DevHlp_Untrusted_GetSupDrvSession,
4655 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
4656 PDM_DEVHLPR3_VERSION /* the end */
4657};
4658
4659
4660
4661/**
4662 * Queue consumer callback for internal component.
4663 *
4664 * @returns Success indicator.
4665 * If false the item will not be removed and the flushing will stop.
4666 * @param pVM The cross context VM structure.
4667 * @param pItem The item to consume. Upon return this item will be freed.
4668 */
4669DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
4670{
4671 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
4672 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
4673 switch (pTask->enmOp)
4674 {
4675 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
4676 PDMIsaSetIrq(pVM, pTask->u.IsaSetIRQ.iIrq, pTask->u.IsaSetIRQ.iLevel, pTask->u.IsaSetIRQ.uTagSrc);
4677 break;
4678
4679 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
4680 {
4681 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
4682 PPDMPCIDEV pPciDev = pTask->u.PciSetIRQ.pPciDevR3;
4683 if (pPciDev)
4684 {
4685 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
4686 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
4687 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
4688
4689 pdmLock(pVM);
4690 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIRQ.iIrq,
4691 pTask->u.PciSetIRQ.iLevel, pTask->u.PciSetIRQ.uTagSrc);
4692 pdmUnlock(pVM);
4693 }
4694 else
4695 AssertReleaseMsgFailed(("No PCI device registered!\n"));
4696 break;
4697 }
4698
4699 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
4700 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIRQ.iIrq, pTask->u.IoApicSetIRQ.iLevel, pTask->u.IoApicSetIRQ.uTagSrc);
4701 break;
4702
4703 default:
4704 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
4705 break;
4706 }
4707 return true;
4708}
4709
4710/** @} */
4711
Note: See TracBrowser for help on using the repository browser.

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