VirtualBox

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

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

VMM/PDMDevHlp: Adding helpers for getting the mapping addresses of I/O port and MMIO regions, mainly for info handlers and logging (thus only ring-3). bugref:9218

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

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