VirtualBox

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

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

IOM,PDMDevHlp: Kicked out the old I/O port code. bugref:9218

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