VirtualBox

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

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

PDM: Doxygen fix. bugref:9218

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

© 2023 Oracle
ContactPrivacy policyTerms of Use