VirtualBox

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

Last change on this file since 98045 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

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