VirtualBox

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

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

PGM: Fixed getting MMIO2 mapping address mess. bugref:9218

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