VirtualBox

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

最後變更 在這個檔案從81766是 81753,由 vboxsync 提交於 5 年 前

SSM,PDMDevHlp: Added volatile integer SSM getter variants so we can avoid a lot of unnecessary & risky casting. bugref:9218

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 213.7 KB
 
1/* $Id: PDMDevHlp.cpp 81753 2019-11-09 15:09:42Z 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.alldomusa.eu.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_Mmio2GetMappingAddress: 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_Mmio2GetMappingAddress: caller='%s'/%d: returns %RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys));
696 return GCPhys;
697}
698
699/**
700 * @copydoc PDMDEVHLPR3::pfnMmio2ChangeRegionNo
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,pfnSTAMRegisterV} */
1724static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
1725 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
1726{
1727 PDMDEV_ASSERT_DEVINS(pDevIns);
1728 PVM pVM = pDevIns->Internal.s.pVMR3;
1729 VM_ASSERT_EMT(pVM);
1730
1731 int rc;
1732 if (*pszName == '/')
1733 rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
1734 else
1735 {
1736 /* Provide default device statistics prefix: */
1737 va_list vaCopy;
1738 va_copy(vaCopy, args);
1739 rc = STAMR3RegisterF(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc,
1740 "/Devices/%s#%u/%N", pDevIns->pReg->szName, pDevIns->iInstance, pszName, &vaCopy);
1741 va_end(vaCopy);
1742 }
1743 AssertRC(rc);
1744}
1745
1746
1747/**
1748 * @interface_method_impl{PDMDEVHLPR3,pfnPCIRegister}
1749 */
1750static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t fFlags,
1751 uint8_t uPciDevNo, uint8_t uPciFunNo, const char *pszName)
1752{
1753 PDMDEV_ASSERT_DEVINS(pDevIns);
1754 PVM pVM = pDevIns->Internal.s.pVMR3;
1755 VM_ASSERT_EMT(pVM);
1756 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Rhxs} fFlags=%#x uPciDevNo=%#x uPciFunNo=%#x pszName=%p:{%s}\n",
1757 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->abConfig, fFlags, uPciDevNo, uPciFunNo, pszName, pszName ? pszName : ""));
1758
1759 /*
1760 * Validate input.
1761 */
1762 AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
1763 ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
1764 VERR_WRONG_ORDER);
1765 AssertLogRelMsgReturn(RT_VALID_PTR(pPciDev),
1766 ("'%s'/%d: Invalid pPciDev value: %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pPciDev),
1767 VERR_INVALID_POINTER);
1768 AssertLogRelMsgReturn(PDMPciDevGetVendorId(pPciDev),
1769 ("'%s'/%d: Vendor ID is not set!\n", pDevIns->pReg->szName, pDevIns->iInstance),
1770 VERR_INVALID_POINTER);
1771 AssertLogRelMsgReturn( uPciDevNo < 32
1772 || uPciDevNo == PDMPCIDEVREG_DEV_NO_FIRST_UNUSED
1773 || uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV,
1774 ("'%s'/%d: Invalid PCI device number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciDevNo),
1775 VERR_INVALID_PARAMETER);
1776 AssertLogRelMsgReturn( uPciFunNo < 8
1777 || uPciFunNo == PDMPCIDEVREG_FUN_NO_FIRST_UNUSED,
1778 ("'%s'/%d: Invalid PCI funcion number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciFunNo),
1779 VERR_INVALID_PARAMETER);
1780 AssertLogRelMsgReturn(!(fFlags & ~PDMPCIDEVREG_F_VALID_MASK),
1781 ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
1782 VERR_INVALID_FLAGS);
1783 if (!pszName)
1784 pszName = pDevIns->pReg->szName;
1785 AssertLogRelReturn(RT_VALID_PTR(pszName), VERR_INVALID_POINTER);
1786 AssertLogRelReturn(!pPciDev->Int.s.fRegistered, VERR_PDM_NOT_PCI_DEVICE);
1787 AssertLogRelReturn(pPciDev == PDMDEV_GET_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
1788 AssertLogRelReturn(pPciDev == PDMDEV_CALC_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
1789 AssertMsgReturn(pPciDev->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", pPciDev->u32Magic), VERR_PDM_NOT_PCI_DEVICE);
1790
1791 /*
1792 * Check the registration order - must be following PDMDEVINSR3::apPciDevs.
1793 */
1794 PPDMPCIDEV const pPrevPciDev = pPciDev->Int.s.idxSubDev == 0 ? NULL
1795 : PDMDEV_GET_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev - 1);
1796 if (pPrevPciDev)
1797 {
1798 AssertLogRelReturn(pPrevPciDev->u32Magic == PDMPCIDEV_MAGIC, VERR_INVALID_MAGIC);
1799 AssertLogRelReturn(pPrevPciDev->Int.s.fRegistered, VERR_WRONG_ORDER);
1800 }
1801
1802 /*
1803 * Resolve the PCI configuration node for the device. The default (zero'th)
1804 * is the same as the PDM device, the rest are "PciCfg1..255" CFGM sub-nodes.
1805 */
1806 PCFGMNODE pCfg = pDevIns->Internal.s.pCfgHandle;
1807 if (pPciDev->Int.s.idxSubDev > 0)
1808 pCfg = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "PciCfg%u", pPciDev->Int.s.idxSubDev);
1809
1810 /*
1811 * We resolve PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, the PCI bus handles
1812 * PDMPCIDEVREG_DEV_NO_FIRST_UNUSED and PDMPCIDEVREG_FUN_NO_FIRST_UNUSED.
1813 */
1814 uint8_t const uPciDevNoRaw = uPciDevNo;
1815 uint32_t uDefPciBusNo = 0;
1816 if (uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV)
1817 {
1818 if (pPrevPciDev)
1819 {
1820 uPciDevNo = pPrevPciDev->uDevFn >> 3;
1821 uDefPciBusNo = pPrevPciDev->Int.s.idxPdmBus;
1822 }
1823 else
1824 {
1825 /* Look for PCI device registered with an earlier device instance so we can more
1826 easily have multiple functions spanning multiple PDM device instances. */
1827 PPDMDEVINS pPrevIns = pDevIns->Internal.s.pDevR3->pInstances;
1828 for (;;)
1829 {
1830 AssertLogRelMsgReturn(pPrevIns && pPrevIns != pDevIns,
1831 ("'%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",
1832 pDevIns->pReg->szName, pDevIns->iInstance), VERR_WRONG_ORDER);
1833 if (pPrevIns->Internal.s.pNextR3 == pDevIns)
1834 break;
1835 pPrevIns = pPrevIns->Internal.s.pNextR3;
1836 }
1837
1838 PPDMPCIDEV pOtherPciDev = PDMDEV_GET_PPCIDEV(pPrevIns, 0);
1839 AssertLogRelMsgReturn(pOtherPciDev && pOtherPciDev->Int.s.fRegistered,
1840 ("'%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",
1841 pDevIns->pReg->szName, pDevIns->iInstance),
1842 VERR_WRONG_ORDER);
1843 for (uint32_t iPrevPciDev = 1; iPrevPciDev < pDevIns->cPciDevs; iPrevPciDev++)
1844 {
1845 PPDMPCIDEV pCur = PDMDEV_GET_PPCIDEV(pPrevIns, iPrevPciDev);
1846 AssertBreak(pCur);
1847 if (!pCur->Int.s.fRegistered)
1848 break;
1849 pOtherPciDev = pCur;
1850 }
1851
1852 uPciDevNo = pOtherPciDev->uDevFn >> 3;
1853 uDefPciBusNo = pOtherPciDev->Int.s.idxPdmBus;
1854 }
1855 }
1856
1857 /*
1858 * Choose the PCI bus for the device.
1859 *
1860 * This is simple. If the device was configured for a particular bus, the PCIBusNo
1861 * configuration value will be set. If not the default bus is 0.
1862 */
1863 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIBusNo, uint8_t, 0, 7, 0}
1864 * Selects the PCI bus number of a device. The default value isn't necessarily
1865 * zero if the device is registered using PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, it
1866 * will then also inherit the bus number from the previously registered device.
1867 */
1868 uint8_t u8Bus;
1869 int rc = CFGMR3QueryU8Def(pCfg, "PCIBusNo", &u8Bus, (uint8_t)uDefPciBusNo);
1870 AssertLogRelMsgRCReturn(rc, ("Configuration error: PCIBusNo query failed with rc=%Rrc (%s/%d)\n",
1871 rc, pDevIns->pReg->szName, pDevIns->iInstance), rc);
1872 AssertLogRelMsgReturn(u8Bus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
1873 ("Configuration error: PCIBusNo=%d, max is %d. (%s/%d)\n", u8Bus,
1874 RT_ELEMENTS(pVM->pdm.s.aPciBuses), pDevIns->pReg->szName, pDevIns->iInstance),
1875 VERR_PDM_NO_PCI_BUS);
1876 pPciDev->Int.s.idxPdmBus = u8Bus;
1877 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[u8Bus];
1878 if (pBus->pDevInsR3)
1879 {
1880 /*
1881 * Check the configuration for PCI device and function assignment.
1882 */
1883 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIDeviceNo, uint8_t, 0, 31}
1884 * Overrides the default PCI device number of a device.
1885 */
1886 uint8_t uCfgDevice;
1887 rc = CFGMR3QueryU8(pCfg, "PCIDeviceNo", &uCfgDevice);
1888 if (RT_SUCCESS(rc))
1889 {
1890 AssertMsgReturn(uCfgDevice <= 31,
1891 ("Configuration error: PCIDeviceNo=%d, max is 31. (%s/%d/%d)\n",
1892 uCfgDevice, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1893 VERR_PDM_BAD_PCI_CONFIG);
1894 uPciDevNo = uCfgDevice;
1895 }
1896 else
1897 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1898 ("Configuration error: PCIDeviceNo query failed with rc=%Rrc (%s/%d/%d)\n",
1899 rc, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1900 rc);
1901
1902 /** @cfgm{/Devices/NAME/XX/[PciCfgYY/]PCIFunctionNo, uint8_t, 0, 7}
1903 * Overrides the default PCI function number of a device.
1904 */
1905 uint8_t uCfgFunction;
1906 rc = CFGMR3QueryU8(pCfg, "PCIFunctionNo", &uCfgFunction);
1907 if (RT_SUCCESS(rc))
1908 {
1909 AssertMsgReturn(uCfgFunction <= 7,
1910 ("Configuration error: PCIFunctionNo=%#x, max is 7. (%s/%d/%d)\n",
1911 uCfgFunction, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1912 VERR_PDM_BAD_PCI_CONFIG);
1913 uPciFunNo = uCfgFunction;
1914 }
1915 else
1916 AssertMsgReturn(rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT,
1917 ("Configuration error: PCIFunctionNo query failed with rc=%Rrc (%s/%d/%d)\n",
1918 rc, pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->Int.s.idxSubDev),
1919 rc);
1920
1921
1922 /*
1923 * Initialize the internal data. We only do the wipe and the members
1924 * owned by PDM, the PCI bus does the rest in the registration call.
1925 */
1926 RT_ZERO(pPciDev->Int);
1927
1928 pPciDev->Int.s.idxDevCfg = pPciDev->Int.s.idxSubDev;
1929 pPciDev->Int.s.fReassignableDevNo = uPciDevNoRaw >= VBOX_PCI_MAX_DEVICES;
1930 pPciDev->Int.s.fReassignableFunNo = uPciFunNo >= VBOX_PCI_MAX_FUNCTIONS;
1931 pPciDev->Int.s.pDevInsR3 = pDevIns;
1932 pPciDev->Int.s.idxPdmBus = u8Bus;
1933 pPciDev->Int.s.fRegistered = true;
1934
1935 /* Set some of the public members too. */
1936 pPciDev->pszNameR3 = pszName;
1937
1938 /*
1939 * Call the pci bus device to do the actual registration.
1940 */
1941 pdmLock(pVM);
1942 rc = pBus->pfnRegister(pBus->pDevInsR3, pPciDev, fFlags, uPciDevNo, uPciFunNo, pszName);
1943 pdmUnlock(pVM);
1944 if (RT_SUCCESS(rc))
1945 Log(("PDM: Registered device '%s'/%d as PCI device %d on bus %d\n",
1946 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev->uDevFn, pBus->iBus));
1947 else
1948 pPciDev->Int.s.fRegistered = false;
1949 }
1950 else
1951 {
1952 AssertLogRelMsgFailed(("Configuration error: No PCI bus available. This could be related to init order too!\n"));
1953 rc = VERR_PDM_NO_PCI_BUS;
1954 }
1955
1956 LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1957 return rc;
1958}
1959
1960
1961/** @interface_method_impl{PDMDEVHLPR3,pfnPCIRegisterMsi} */
1962static DECLCALLBACK(int) pdmR3DevHlp_PCIRegisterMsi(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg)
1963{
1964 PDMDEV_ASSERT_DEVINS(pDevIns);
1965 if (!pPciDev) /* NULL is an alias for the default PCI device. */
1966 pPciDev = pDevIns->apPciDevs[0];
1967 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
1968 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: pPciDev=%p:{%#x} pMsgReg=%p:{cMsiVectors=%d, cMsixVectors=%d}\n",
1969 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, pMsiReg, pMsiReg->cMsiVectors, pMsiReg->cMsixVectors));
1970 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
1971
1972 AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
1973 ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
1974 VERR_WRONG_ORDER);
1975 AssertLogRelMsgReturn(pMsiReg->cMsixVectors <= pDevIns->pReg->cMaxMsixVectors,
1976 ("'%s'/%d: cMsixVectors=%u cMaxMsixVectors=%u\n",
1977 pDevIns->pReg->szName, pDevIns->iInstance, pMsiReg->cMsixVectors, pDevIns->pReg->cMaxMsixVectors),
1978 VERR_INVALID_FLAGS);
1979
1980 PVM pVM = pDevIns->Internal.s.pVMR3;
1981 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
1982 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
1983 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
1984
1985 pdmLock(pVM);
1986 int rc;
1987 if (pBus->pfnRegisterMsi)
1988 rc = pBus->pfnRegisterMsi(pBus->pDevInsR3, pPciDev, pMsiReg);
1989 else
1990 rc = VERR_NOT_IMPLEMENTED;
1991 pdmUnlock(pVM);
1992
1993 LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
1994 return rc;
1995}
1996
1997
1998/** @interface_method_impl{PDMDEVHLPR3,pfnPCIIORegionRegister} */
1999static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
2000 RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, uint32_t fFlags,
2001 uint64_t hHandle, PFNPCIIOREGIONMAP pfnMapUnmap)
2002{
2003 PDMDEV_ASSERT_DEVINS(pDevIns);
2004 PVM pVM = pDevIns->Internal.s.pVMR3;
2005 VM_ASSERT_EMT(pVM);
2006 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2007 pPciDev = pDevIns->apPciDevs[0];
2008 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2009 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%d cbRegion=%RGp enmType=%d fFlags=%#x, hHandle=%#RX64 pfnMapUnmap=%p\n",
2010 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iRegion, cbRegion, enmType, fFlags, hHandle, pfnMapUnmap));
2011 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
2012
2013 /*
2014 * Validate input.
2015 */
2016 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
2017 AssertLogRelMsgReturn(VMR3GetState(pVM) == VMSTATE_CREATING,
2018 ("caller='%s'/%d: %s\n", pDevIns->pReg->szName, pDevIns->iInstance, VMR3GetStateName(VMR3GetState(pVM))),
2019 VERR_WRONG_ORDER);
2020
2021 if (iRegion >= VBOX_PCI_NUM_REGIONS)
2022 {
2023 Assert(iRegion < VBOX_PCI_NUM_REGIONS);
2024 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (iRegion)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2025 return VERR_INVALID_PARAMETER;
2026 }
2027
2028 switch ((int)enmType)
2029 {
2030 case PCI_ADDRESS_SPACE_IO:
2031 /*
2032 * Sanity check: don't allow to register more than 32K of the PCI I/O space.
2033 */
2034 AssertLogRelMsgReturn(cbRegion <= _32K,
2035 ("caller='%s'/%d: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cbRegion),
2036 VERR_INVALID_PARAMETER);
2037 break;
2038
2039 case PCI_ADDRESS_SPACE_MEM:
2040 case PCI_ADDRESS_SPACE_MEM_PREFETCH:
2041 /*
2042 * Sanity check: Don't allow to register more than 2GB of the PCI MMIO space.
2043 */
2044 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_32_MAX,
2045 ("caller='%s'/%d: %RGp (max %RGp)\n",
2046 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, (RTGCPHYS)MM_MMIO_32_MAX),
2047 VERR_OUT_OF_RANGE);
2048 break;
2049
2050 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM:
2051 case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH:
2052 /*
2053 * Sanity check: Don't allow to register more than 64GB of the 64-bit PCI MMIO space.
2054 */
2055 AssertLogRelMsgReturn(cbRegion <= MM_MMIO_64_MAX,
2056 ("caller='%s'/%d: %RGp (max %RGp)\n",
2057 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, MM_MMIO_64_MAX),
2058 VERR_OUT_OF_RANGE);
2059 break;
2060
2061 default:
2062 AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
2063 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (enmType)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
2064 return VERR_INVALID_PARAMETER;
2065 }
2066
2067 AssertMsgReturn( pfnMapUnmap
2068 || ( hHandle != UINT64_MAX
2069 && (fFlags & PDMPCIDEV_IORGN_F_HANDLE_MASK) != PDMPCIDEV_IORGN_F_NO_HANDLE),
2070 ("caller='%s'/%d: fFlags=%#x hHandle=%#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags, hHandle),
2071 VERR_INVALID_PARAMETER);
2072
2073 AssertMsgReturn(!(fFlags & ~PDMPCIDEV_IORGN_F_VALID_MASK), ("fFlags=%#x\n", fFlags), VERR_INVALID_FLAGS);
2074 int rc;
2075 switch (fFlags & PDMPCIDEV_IORGN_F_HANDLE_MASK)
2076 {
2077 case PDMPCIDEV_IORGN_F_NO_HANDLE:
2078 break;
2079 case PDMPCIDEV_IORGN_F_IOPORT_HANDLE:
2080 AssertReturn(enmType == PCI_ADDRESS_SPACE_IO, VERR_INVALID_FLAGS);
2081 rc = IOMR3IoPortValidateHandle(pVM, pDevIns, (IOMIOPORTHANDLE)hHandle);
2082 AssertRCReturn(rc, rc);
2083 break;
2084 case PDMPCIDEV_IORGN_F_MMIO_HANDLE:
2085 AssertReturn( (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM
2086 || (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM_PREFETCH,
2087 VERR_INVALID_FLAGS);
2088 rc = IOMR3MmioValidateHandle(pVM, pDevIns, (IOMMMIOHANDLE)hHandle);
2089 AssertRCReturn(rc, rc);
2090 break;
2091 case PDMPCIDEV_IORGN_F_MMIO2_HANDLE:
2092 AssertReturn( (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM
2093 || (enmType & ~PCI_ADDRESS_SPACE_BAR64) == PCI_ADDRESS_SPACE_MEM_PREFETCH,
2094 VERR_INVALID_FLAGS);
2095 rc = PGMR3PhysMmio2ValidateHandle(pVM, pDevIns, (PGMMMIO2HANDLE)hHandle);
2096 AssertRCReturn(rc, rc);
2097 break;
2098 default:
2099 AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
2100 break;
2101 }
2102
2103 /*
2104 * We're currently restricted to page aligned MMIO regions.
2105 */
2106 if ( ((enmType & ~(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH)) == PCI_ADDRESS_SPACE_MEM)
2107 && cbRegion != RT_ALIGN_64(cbRegion, PAGE_SIZE))
2108 {
2109 Log(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: aligning cbRegion %RGp -> %RGp\n",
2110 pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, RT_ALIGN_64(cbRegion, PAGE_SIZE)));
2111 cbRegion = RT_ALIGN_64(cbRegion, PAGE_SIZE);
2112 }
2113
2114 /*
2115 * For registering PCI MMIO memory or PCI I/O memory, the size of the region must be a power of 2!
2116 */
2117 int iLastSet = ASMBitLastSetU64(cbRegion);
2118 Assert(iLastSet > 0);
2119 uint64_t cbRegionAligned = RT_BIT_64(iLastSet - 1);
2120 if (cbRegion > cbRegionAligned)
2121 cbRegion = cbRegionAligned * 2; /* round up */
2122
2123 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2124 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_WRONG_ORDER);
2125 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2126
2127 pdmLock(pVM);
2128 rc = pBus->pfnIORegionRegister(pBus->pDevInsR3, pPciDev, iRegion, cbRegion, enmType, fFlags, hHandle, pfnMapUnmap);
2129 pdmUnlock(pVM);
2130
2131 LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2132 return rc;
2133}
2134
2135
2136/** @interface_method_impl{PDMDEVHLPR3,pfnPCIInterceptConfigAccesses} */
2137static DECLCALLBACK(int) pdmR3DevHlp_PCIInterceptConfigAccesses(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
2138 PFNPCICONFIGREAD pfnRead, PFNPCICONFIGWRITE pfnWrite)
2139{
2140 PDMDEV_ASSERT_DEVINS(pDevIns);
2141 PVM pVM = pDevIns->Internal.s.pVMR3;
2142 VM_ASSERT_EMT(pVM);
2143 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2144 pPciDev = pDevIns->apPciDevs[0];
2145 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2146 LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: pPciDev=%p pfnRead=%p pfnWrite=%p\n",
2147 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pfnRead, pfnWrite));
2148 PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
2149
2150 /*
2151 * Validate input.
2152 */
2153 AssertPtr(pfnRead);
2154 AssertPtr(pfnWrite);
2155 AssertPtr(pPciDev);
2156
2157 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2158 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
2159 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2160 AssertRelease(VMR3GetState(pVM) != VMSTATE_RUNNING);
2161
2162 /*
2163 * Do the job.
2164 */
2165 pdmLock(pVM);
2166 pBus->pfnInterceptConfigAccesses(pBus->pDevInsR3, pPciDev, pfnRead, pfnWrite);
2167 pdmUnlock(pVM);
2168
2169 LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: returns VINF_SUCCESS\n",
2170 pDevIns->pReg->szName, pDevIns->iInstance));
2171 return VINF_SUCCESS;
2172}
2173
2174
2175/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigWrite} */
2176static DECLCALLBACK(VBOXSTRICTRC)
2177pdmR3DevHlp_PCIConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t u32Value)
2178{
2179 PDMDEV_ASSERT_DEVINS(pDevIns);
2180 PVM pVM = pDevIns->Internal.s.pVMR3;
2181 AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2182 LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d u32Value=%#x\n",
2183 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, u32Value));
2184
2185 /*
2186 * Resolve the bus.
2187 */
2188 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2189 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
2190 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2191
2192 /*
2193 * Do the job.
2194 */
2195 VBOXSTRICTRC rcStrict = pBus->pfnConfigWrite(pBus->pDevInsR3, pPciDev, uAddress, cb, u32Value);
2196
2197 LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: returns %Rrc\n",
2198 pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict)));
2199 return rcStrict;
2200}
2201
2202
2203/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigRead} */
2204static DECLCALLBACK(VBOXSTRICTRC)
2205pdmR3DevHlp_PCIConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t *pu32Value)
2206{
2207 PDMDEV_ASSERT_DEVINS(pDevIns);
2208 PVM pVM = pDevIns->Internal.s.pVMR3;
2209 AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2210 LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d pu32Value=%p:{%#x}\n",
2211 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, pu32Value, *pu32Value));
2212
2213 /*
2214 * Resolve the bus.
2215 */
2216 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2217 AssertReturn(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses), VERR_INTERNAL_ERROR_2);
2218 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2219
2220 /*
2221 * Do the job.
2222 */
2223 VBOXSTRICTRC rcStrict = pBus->pfnConfigRead(pBus->pDevInsR3, pPciDev, uAddress, cb, pu32Value);
2224
2225 LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: returns %Rrc (*pu32Value=%#x)\n",
2226 pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict), *pu32Value));
2227 return rcStrict;
2228}
2229
2230
2231/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysRead} */
2232static DECLCALLBACK(int)
2233pdmR3DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
2234{
2235 PDMDEV_ASSERT_DEVINS(pDevIns);
2236 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2237 pPciDev = pDevIns->apPciDevs[0];
2238 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2239 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2240
2241#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
2242 /*
2243 * Just check the busmaster setting here and forward the request to the generic read helper.
2244 */
2245 if (PCIDevIsBusmaster(pPciDev))
2246 { /* likely */ }
2247 else
2248 {
2249 Log(("pdmR3DevHlp_PCIPhysRead: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
2250 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
2251 memset(pvBuf, 0xff, cbRead);
2252 return VERR_PDM_NOT_PCI_BUS_MASTER;
2253 }
2254#endif
2255
2256 return pDevIns->pHlpR3->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
2257}
2258
2259
2260/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
2261static DECLCALLBACK(int)
2262pdmR3DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
2263{
2264 PDMDEV_ASSERT_DEVINS(pDevIns);
2265 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2266 pPciDev = pDevIns->apPciDevs[0];
2267 AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
2268 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2269
2270#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
2271 /*
2272 * Just check the busmaster setting here and forward the request to the generic read helper.
2273 */
2274 if (PCIDevIsBusmaster(pPciDev))
2275 { /* likely */ }
2276 else
2277 {
2278 Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
2279 pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
2280 return VERR_PDM_NOT_PCI_BUS_MASTER;
2281 }
2282#endif
2283
2284 return pDevIns->pHlpR3->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
2285}
2286
2287
2288/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
2289static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2290{
2291 PDMDEV_ASSERT_DEVINS(pDevIns);
2292 if (!pPciDev) /* NULL is an alias for the default PCI device. */
2293 pPciDev = pDevIns->apPciDevs[0];
2294 AssertReturnVoid(pPciDev);
2295 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
2296 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
2297 PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
2298
2299 /*
2300 * Validate input.
2301 */
2302 Assert(iIrq == 0);
2303 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2304
2305 /*
2306 * Must have a PCI device registered!
2307 */
2308 PVM pVM = pDevIns->Internal.s.pVMR3;
2309 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
2310 AssertReturnVoid(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
2311 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
2312
2313 pdmLock(pVM);
2314 uint32_t uTagSrc;
2315 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2316 {
2317 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2318 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2319 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2320 else
2321 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2322 }
2323 else
2324 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2325
2326 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, iIrq, iLevel, uTagSrc);
2327
2328 if (iLevel == PDM_IRQ_LEVEL_LOW)
2329 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2330 pdmUnlock(pVM);
2331
2332 LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2333}
2334
2335
2336/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
2337static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
2338{
2339 pdmR3DevHlp_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
2340}
2341
2342
2343/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
2344static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2345{
2346 PDMDEV_ASSERT_DEVINS(pDevIns);
2347 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
2348
2349 /*
2350 * Validate input.
2351 */
2352 Assert(iIrq < 16);
2353 Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
2354
2355 PVM pVM = pDevIns->Internal.s.pVMR3;
2356
2357 /*
2358 * Do the job.
2359 */
2360 pdmLock(pVM);
2361 uint32_t uTagSrc;
2362 if (iLevel & PDM_IRQ_LEVEL_HIGH)
2363 {
2364 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2365 if (iLevel == PDM_IRQ_LEVEL_HIGH)
2366 VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2367 else
2368 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2369 }
2370 else
2371 uTagSrc = pDevIns->Internal.s.uLastIrqTag;
2372
2373 PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */
2374
2375 if (iLevel == PDM_IRQ_LEVEL_LOW)
2376 VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2377 pdmUnlock(pVM);
2378
2379 LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2380}
2381
2382
2383/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
2384static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
2385{
2386 pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
2387}
2388
2389
2390/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicSendMsi} */
2391static DECLCALLBACK(void) pdmR3DevHlp_IoApicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue)
2392{
2393 PDMDEV_ASSERT_DEVINS(pDevIns);
2394 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: GCPhys=%RGp uValue=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, uValue));
2395
2396 /*
2397 * Validate input.
2398 */
2399 Assert(GCPhys != 0);
2400 Assert(uValue != 0);
2401
2402 PVM pVM = pDevIns->Internal.s.pVMR3;
2403
2404 /*
2405 * Do the job.
2406 */
2407 pdmLock(pVM);
2408 uint32_t uTagSrc;
2409 pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing);
2410 VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc));
2411
2412 PDMIoApicSendMsi(pVM, GCPhys, uValue, uTagSrc); /* (The API takes the lock recursively.) */
2413
2414 pdmUnlock(pVM);
2415
2416 LogFlow(("pdmR3DevHlp_IoApicSendMsi: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
2417}
2418
2419
2420/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
2421static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
2422{
2423 PDMDEV_ASSERT_DEVINS(pDevIns);
2424 PVM pVM = pDevIns->Internal.s.pVMR3;
2425 VM_ASSERT_EMT(pVM);
2426 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
2427 pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
2428
2429 /*
2430 * Lookup the LUN, it might already be registered.
2431 */
2432 PPDMLUN pLunPrev = NULL;
2433 PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;
2434 for (; pLun; pLunPrev = pLun, pLun = pLun->pNext)
2435 if (pLun->iLun == iLun)
2436 break;
2437
2438 /*
2439 * Create the LUN if if wasn't found, else check if driver is already attached to it.
2440 */
2441 if (!pLun)
2442 {
2443 if ( !pBaseInterface
2444 || !pszDesc
2445 || !*pszDesc)
2446 {
2447 Assert(pBaseInterface);
2448 Assert(pszDesc || *pszDesc);
2449 return VERR_INVALID_PARAMETER;
2450 }
2451
2452 pLun = (PPDMLUN)MMR3HeapAlloc(pVM, MM_TAG_PDM_LUN, sizeof(*pLun));
2453 if (!pLun)
2454 return VERR_NO_MEMORY;
2455
2456 pLun->iLun = iLun;
2457 pLun->pNext = pLunPrev ? pLunPrev->pNext : NULL;
2458 pLun->pTop = NULL;
2459 pLun->pBottom = NULL;
2460 pLun->pDevIns = pDevIns;
2461 pLun->pUsbIns = NULL;
2462 pLun->pszDesc = pszDesc;
2463 pLun->pBase = pBaseInterface;
2464 if (!pLunPrev)
2465 pDevIns->Internal.s.pLunsR3 = pLun;
2466 else
2467 pLunPrev->pNext = pLun;
2468 Log(("pdmR3DevHlp_DriverAttach: Registered LUN#%d '%s' with device '%s'/%d.\n",
2469 iLun, pszDesc, pDevIns->pReg->szName, pDevIns->iInstance));
2470 }
2471 else if (pLun->pTop)
2472 {
2473 AssertMsgFailed(("Already attached! The device should keep track of such things!\n"));
2474 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_DRIVER_ALREADY_ATTACHED));
2475 return VERR_PDM_DRIVER_ALREADY_ATTACHED;
2476 }
2477 Assert(pLun->pBase == pBaseInterface);
2478
2479
2480 /*
2481 * Get the attached driver configuration.
2482 */
2483 int rc;
2484 PCFGMNODE pNode = CFGMR3GetChildF(pDevIns->Internal.s.pCfgHandle, "LUN#%u", iLun);
2485 if (pNode)
2486 rc = pdmR3DrvInstantiate(pVM, pNode, pBaseInterface, NULL /*pDrvAbove*/, pLun, ppBaseInterface);
2487 else
2488 rc = VERR_PDM_NO_ATTACHED_DRIVER;
2489
2490 LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2491 return rc;
2492}
2493
2494
2495/** @interface_method_impl{PDMDEVHLPR3,pfnDriverDetach} */
2496static DECLCALLBACK(int) pdmR3DevHlp_DriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
2497{
2498 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
2499 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: pDrvIns=%p\n",
2500 pDevIns->pReg->szName, pDevIns->iInstance, pDrvIns));
2501
2502#ifdef VBOX_STRICT
2503 PVM pVM = pDevIns->Internal.s.pVMR3;
2504 VM_ASSERT_EMT(pVM);
2505#endif
2506
2507 int rc = pdmR3DrvDetach(pDrvIns, fFlags);
2508
2509 LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2510 return rc;
2511}
2512
2513
2514/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreatePtr} */
2515static DECLCALLBACK(int) pdmR3DevHlp_QueueCreatePtr(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2516 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)
2517{
2518 PDMDEV_ASSERT_DEVINS(pDevIns);
2519 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} ppQueue=%p\n",
2520 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, ppQueue));
2521
2522 PVM pVM = pDevIns->Internal.s.pVMR3;
2523 VM_ASSERT_EMT(pVM);
2524
2525 if (pDevIns->iInstance > 0)
2526 {
2527 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2528 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2529 }
2530
2531 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, ppQueue);
2532
2533 LogFlow(("pdmR3DevHlp_QueueCreatePtr: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppQueue));
2534 return rc;
2535}
2536
2537
2538/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
2539static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
2540 PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName,
2541 PDMQUEUEHANDLE *phQueue)
2542{
2543 PDMDEV_ASSERT_DEVINS(pDevIns);
2544 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} phQueue=%p\n",
2545 pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, phQueue));
2546
2547 PVM pVM = pDevIns->Internal.s.pVMR3;
2548 VM_ASSERT_EMT(pVM);
2549
2550 if (pDevIns->iInstance > 0)
2551 {
2552 pszName = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s_%u", pszName, pDevIns->iInstance);
2553 AssertLogRelReturn(pszName, VERR_NO_MEMORY);
2554 }
2555
2556 PPDMQUEUE pQueue = NULL;
2557 int rc = PDMR3QueueCreateDevice(pVM, pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, &pQueue);
2558 *phQueue = (uintptr_t)pQueue;
2559
2560 LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phQueue));
2561 return rc;
2562}
2563
2564
2565/** @interface_method_impl{PDMDEVHLPR3,pfnQueueToPtr} */
2566static DECLCALLBACK(PPDMQUEUE) pdmR3DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2567{
2568 PDMDEV_ASSERT_DEVINS(pDevIns);
2569 RT_NOREF(pDevIns);
2570 return (PPDMQUEUE)hQueue;
2571}
2572
2573
2574/** @interface_method_impl{PDMDEVHLPR3,pfnQueueAlloc} */
2575static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR3DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2576{
2577 return PDMQueueAlloc(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2578}
2579
2580
2581/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsert} */
2582static DECLCALLBACK(void) pdmR3DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
2583{
2584 return PDMQueueInsert(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem);
2585}
2586
2587
2588/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsertEx} */
2589static DECLCALLBACK(void) pdmR3DevHlp_QueueInsertEx(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem,
2590 uint64_t cNanoMaxDelay)
2591{
2592 return PDMQueueInsertEx(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue), pItem, cNanoMaxDelay);
2593}
2594
2595
2596/** @interface_method_impl{PDMDEVHLPR3,pfnQueueFlushIfNecessary} */
2597static DECLCALLBACK(bool) pdmR3DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
2598{
2599 return PDMQueueFlushIfNecessary(pdmR3DevHlp_QueueToPtr(pDevIns, hQueue));
2600}
2601
2602
2603/** @interface_method_impl{PDMDEVHLPR3,pfnTaskCreate} */
2604static DECLCALLBACK(int) pdmR3DevHlp_TaskCreate(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszName,
2605 PFNPDMTASKDEV pfnCallback, void *pvUser, PDMTASKHANDLE *phTask)
2606{
2607 PDMDEV_ASSERT_DEVINS(pDevIns);
2608 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: pfnCallback=%p fFlags=%#x pszName=%p:{%s} phTask=%p\n",
2609 pDevIns->pReg->szName, pDevIns->iInstance, pfnCallback, fFlags, pszName, pszName, phTask));
2610 PVM pVM = pDevIns->Internal.s.pVMR3;
2611 VM_ASSERT_EMT(pVM);
2612
2613 int rc = PDMR3TaskCreate(pVM, fFlags, pszName, PDMTASKTYPE_DEV, pDevIns, (PFNRT)pfnCallback, pvUser, phTask);
2614
2615 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2616 return rc;
2617}
2618
2619
2620/** @interface_method_impl{PDMDEVHLPR3,pfnTaskTrigger} */
2621static DECLCALLBACK(int) pdmR3DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
2622{
2623 PDMDEV_ASSERT_DEVINS(pDevIns);
2624 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
2625
2626 int rc = PDMTaskTrigger(pDevIns->Internal.s.pVMR3, PDMTASKTYPE_DEV, pDevIns, hTask);
2627
2628 LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2629 return rc;
2630}
2631
2632
2633/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventCreate} */
2634static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventCreate(PPDMDEVINS pDevIns, PSUPSEMEVENT phEvent)
2635{
2636 PDMDEV_ASSERT_DEVINS(pDevIns);
2637 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEvent));
2638 PVM pVM = pDevIns->Internal.s.pVMR3;
2639 VM_ASSERT_EMT(pVM);
2640
2641 int rc = SUPSemEventCreate(pVM->pSession, phEvent);
2642
2643 LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: returns %Rrc *phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEvent));
2644 return rc;
2645}
2646
2647
2648/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventClose} */
2649static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventClose(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2650{
2651 PDMDEV_ASSERT_DEVINS(pDevIns);
2652 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2653
2654 int rc = SUPSemEventClose(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2655
2656 LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2657 return rc;
2658}
2659
2660
2661/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventSignal} */
2662static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
2663{
2664 PDMDEV_ASSERT_DEVINS(pDevIns);
2665 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
2666
2667 int rc = SUPSemEventSignal(pDevIns->Internal.s.pVMR3->pSession, hEvent);
2668
2669 LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2670 return rc;
2671}
2672
2673
2674/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNoResume} */
2675static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
2676{
2677 PDMDEV_ASSERT_DEVINS(pDevIns);
2678 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
2679 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
2680
2681 int rc = SUPSemEventWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEvent, cMillies);
2682
2683 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2684 return rc;
2685}
2686
2687
2688/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsAbsIntr} */
2689static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
2690{
2691 PDMDEV_ASSERT_DEVINS(pDevIns);
2692 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
2693 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
2694
2695 int rc = SUPSemEventWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, uNsTimeout);
2696
2697 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2698 return rc;
2699}
2700
2701
2702/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsRelIntr} */
2703static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
2704{
2705 PDMDEV_ASSERT_DEVINS(pDevIns);
2706 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
2707 pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
2708
2709 int rc = SUPSemEventWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEvent, cNsTimeout);
2710
2711 LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2712 return rc;
2713}
2714
2715
2716/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventGetResolution} */
2717static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
2718{
2719 PDMDEV_ASSERT_DEVINS(pDevIns);
2720 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2721
2722 uint32_t cNsResolution = SUPSemEventGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2723
2724 LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2725 return cNsResolution;
2726}
2727
2728
2729/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiCreate} */
2730static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiCreate(PPDMDEVINS pDevIns, PSUPSEMEVENTMULTI phEventMulti)
2731{
2732 PDMDEV_ASSERT_DEVINS(pDevIns);
2733 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEventMulti));
2734 PVM pVM = pDevIns->Internal.s.pVMR3;
2735 VM_ASSERT_EMT(pVM);
2736
2737 int rc = SUPSemEventMultiCreate(pVM->pSession, phEventMulti);
2738
2739 LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: returns %Rrc *phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEventMulti));
2740 return rc;
2741}
2742
2743
2744/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiClose} */
2745static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiClose(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2746{
2747 PDMDEV_ASSERT_DEVINS(pDevIns);
2748 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2749
2750 int rc = SUPSemEventMultiClose(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2751
2752 LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2753 return rc;
2754}
2755
2756
2757/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiSignal} */
2758static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2759{
2760 PDMDEV_ASSERT_DEVINS(pDevIns);
2761 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2762
2763 int rc = SUPSemEventMultiSignal(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2764
2765 LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2766 return rc;
2767}
2768
2769
2770/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiReset} */
2771static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
2772{
2773 PDMDEV_ASSERT_DEVINS(pDevIns);
2774 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
2775
2776 int rc = SUPSemEventMultiReset(pDevIns->Internal.s.pVMR3->pSession, hEventMulti);
2777
2778 LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2779 return rc;
2780}
2781
2782
2783/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNoResume} */
2784static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2785 uint32_t cMillies)
2786{
2787 PDMDEV_ASSERT_DEVINS(pDevIns);
2788 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
2789 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
2790
2791 int rc = SUPSemEventMultiWaitNoResume(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cMillies);
2792
2793 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2794 return rc;
2795}
2796
2797
2798/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsAbsIntr} */
2799static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2800 uint64_t uNsTimeout)
2801{
2802 PDMDEV_ASSERT_DEVINS(pDevIns);
2803 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
2804 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
2805
2806 int rc = SUPSemEventMultiWaitNsAbsIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, uNsTimeout);
2807
2808 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2809 return rc;
2810}
2811
2812
2813/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsRelIntr} */
2814static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
2815 uint64_t cNsTimeout)
2816{
2817 PDMDEV_ASSERT_DEVINS(pDevIns);
2818 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
2819 pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
2820
2821 int rc = SUPSemEventMultiWaitNsRelIntr(pDevIns->Internal.s.pVMR3->pSession, hEventMulti, cNsTimeout);
2822
2823 LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2824 return rc;
2825}
2826
2827
2828/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiGetResolution} */
2829static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
2830{
2831 PDMDEV_ASSERT_DEVINS(pDevIns);
2832 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
2833
2834 uint32_t cNsResolution = SUPSemEventMultiGetResolution(pDevIns->Internal.s.pVMR3->pSession);
2835
2836 LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
2837 return cNsResolution;
2838}
2839
2840
2841/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
2842static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
2843 const char *pszNameFmt, va_list va)
2844{
2845 PDMDEV_ASSERT_DEVINS(pDevIns);
2846 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
2847 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
2848
2849 PVM pVM = pDevIns->Internal.s.pVMR3;
2850 VM_ASSERT_EMT(pVM);
2851 int rc = pdmR3CritSectInitDevice(pVM, pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
2852
2853 LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
2854 return rc;
2855}
2856
2857
2858/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
2859static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
2860{
2861 PDMDEV_ASSERT_DEVINS(pDevIns);
2862 PVM pVM = pDevIns->Internal.s.pVMR3;
2863 VM_ASSERT_EMT(pVM);
2864
2865 PPDMCRITSECT pCritSect = PDMR3CritSectGetNop(pVM);
2866 LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
2867 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2868 return pCritSect;
2869}
2870
2871
2872/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopR0} */
2873static DECLCALLBACK(R0PTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopR0(PPDMDEVINS pDevIns)
2874{
2875 PDMDEV_ASSERT_DEVINS(pDevIns);
2876 PVM pVM = pDevIns->Internal.s.pVMR3;
2877 VM_ASSERT_EMT(pVM);
2878
2879 R0PTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopR0(pVM);
2880 LogFlow(("pdmR3DevHlp_CritSectGetNopR0: caller='%s'/%d: return %RHv\n",
2881 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2882 return pCritSect;
2883}
2884
2885
2886/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNopRC} */
2887static DECLCALLBACK(RCPTRTYPE(PPDMCRITSECT)) pdmR3DevHlp_CritSectGetNopRC(PPDMDEVINS pDevIns)
2888{
2889 PDMDEV_ASSERT_DEVINS(pDevIns);
2890 PVM pVM = pDevIns->Internal.s.pVMR3;
2891 VM_ASSERT_EMT(pVM);
2892
2893 RCPTRTYPE(PPDMCRITSECT) pCritSect = PDMR3CritSectGetNopRC(pVM);
2894 LogFlow(("pdmR3DevHlp_CritSectGetNopRC: caller='%s'/%d: return %RRv\n",
2895 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
2896 return pCritSect;
2897}
2898
2899
2900/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
2901static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2902{
2903 /*
2904 * Validate input.
2905 *
2906 * Note! We only allow the automatically created default critical section
2907 * to be replaced by this API.
2908 */
2909 PDMDEV_ASSERT_DEVINS(pDevIns);
2910 AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
2911 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p (%s)\n",
2912 pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pCritSect->s.pszName));
2913 AssertReturn(PDMCritSectIsInitialized(pCritSect), VERR_INVALID_PARAMETER);
2914 PVM pVM = pDevIns->Internal.s.pVMR3;
2915 AssertReturn(pCritSect->s.pVMR3 == pVM, VERR_INVALID_PARAMETER);
2916
2917 VM_ASSERT_EMT(pVM);
2918 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
2919
2920 AssertReturn(pDevIns->pCritSectRoR3, VERR_PDM_DEV_IPE_1);
2921 AssertReturn(pDevIns->pCritSectRoR3->s.fAutomaticDefaultCritsect, VERR_WRONG_ORDER);
2922 AssertReturn(!pDevIns->pCritSectRoR3->s.fUsedByTimerOrSimilar, VERR_WRONG_ORDER);
2923 AssertReturn(pDevIns->pCritSectRoR3 != pCritSect, VERR_INVALID_PARAMETER);
2924
2925 /*
2926 * Replace the critical section and destroy the automatic default section.
2927 */
2928 PPDMCRITSECT pOldCritSect = pDevIns->pCritSectRoR3;
2929 pDevIns->pCritSectRoR3 = pCritSect;
2930 pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_CHANGED_CRITSECT;
2931
2932 Assert(RT_BOOL(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED) == pDevIns->fR0Enabled);
2933 if ( (pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_R0_ENABLED)
2934 && !(pDevIns->Internal.s.pDevR3->pReg->fFlags & PDM_DEVREG_FLAGS_NEW_STYLE))
2935 {
2936 PDMDEVICECOMPATSETCRITSECTREQ Req;
2937 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
2938 Req.Hdr.cbReq = sizeof(Req);
2939 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
2940 Req.pDevInsR3 = pDevIns;
2941 Req.pCritSectR3 = pCritSect;
2942 int rc = VMMR3CallR0(pVM, VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT, 0, &Req.Hdr);
2943 AssertLogRelRCReturn(rc, rc);
2944 }
2945
2946 PDMR3CritSectDelete(pOldCritSect);
2947 Assert((uintptr_t)pOldCritSect - (uintptr_t)pDevIns < pDevIns->cbRing3);
2948
2949 LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
2950 return VINF_SUCCESS;
2951}
2952
2953
2954/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectYield} */
2955static DECLCALLBACK(bool) pdmR3DevHlp_CritSectYield(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2956{
2957 PDMDEV_ASSERT_DEVINS(pDevIns);
2958 return PDMR3CritSectYield(pDevIns->Internal.s.pVMR3, pCritSect);
2959}
2960
2961
2962/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnter} */
2963static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
2964{
2965 PDMDEV_ASSERT_DEVINS(pDevIns);
2966 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2967 return PDMCritSectEnter(pCritSect, rcBusy);
2968}
2969
2970
2971/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnterDebug} */
2972static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2973{
2974 PDMDEV_ASSERT_DEVINS(pDevIns);
2975 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2976 return PDMCritSectEnterDebug(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
2977}
2978
2979
2980/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnter} */
2981static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
2982{
2983 PDMDEV_ASSERT_DEVINS(pDevIns);
2984 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2985 return PDMCritSectTryEnter(pCritSect);
2986}
2987
2988
2989/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnterDebug} */
2990static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
2991{
2992 PDMDEV_ASSERT_DEVINS(pDevIns);
2993 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
2994 return PDMCritSectTryEnterDebug(pCritSect, uId, RT_SRC_POS_ARGS);
2995}
2996
2997
2998/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectLeave} */
2999static DECLCALLBACK(int) pdmR3DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
3000{
3001 PDMDEV_ASSERT_DEVINS(pDevIns);
3002 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
3003 return PDMCritSectLeave(pCritSect);
3004}
3005
3006
3007/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsOwner} */
3008static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
3009{
3010 PDMDEV_ASSERT_DEVINS(pDevIns);
3011 RT_NOREF(pDevIns); /** @todo pass pDevIns->Internal.s.pVMR3 to the crit sect code. */
3012 return PDMCritSectIsOwner(pCritSect);
3013}
3014
3015
3016/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsInitialized} */
3017static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
3018{
3019 PDMDEV_ASSERT_DEVINS(pDevIns);
3020 RT_NOREF(pDevIns);
3021 return PDMCritSectIsInitialized(pCritSect);
3022}
3023
3024
3025/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectHasWaiters} */
3026static DECLCALLBACK(bool) pdmR3DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
3027{
3028 PDMDEV_ASSERT_DEVINS(pDevIns);
3029 RT_NOREF(pDevIns);
3030 return PDMCritSectHasWaiters(pCritSect);
3031}
3032
3033
3034/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetRecursion} */
3035static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
3036{
3037 PDMDEV_ASSERT_DEVINS(pDevIns);
3038 RT_NOREF(pDevIns);
3039 return PDMCritSectGetRecursion(pCritSect);
3040}
3041
3042
3043/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectDelete} */
3044static DECLCALLBACK(int) pdmR3DevHlp_CritSectDelete(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
3045{
3046 PDMDEV_ASSERT_DEVINS(pDevIns);
3047 RT_NOREF(pDevIns);
3048 return PDMR3CritSectDelete(pCritSect);
3049}
3050
3051
3052/** @interface_method_impl{PDMDEVHLPR3,pfnThreadCreate} */
3053static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
3054 PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
3055{
3056 PDMDEV_ASSERT_DEVINS(pDevIns);
3057 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3058 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
3059 pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
3060
3061 int rc = pdmR3ThreadCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
3062
3063 LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
3064 rc, *ppThread));
3065 return rc;
3066}
3067
3068
3069/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
3070static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
3071{
3072 PDMDEV_ASSERT_DEVINS(pDevIns);
3073 VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
3074 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
3075
3076 int rc = VINF_SUCCESS;
3077 AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
3078 AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
3079 AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
3080 VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
3081 AssertStmt( enmVMState == VMSTATE_SUSPENDING
3082 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
3083 || enmVMState == VMSTATE_SUSPENDING_LS
3084 || enmVMState == VMSTATE_RESETTING
3085 || enmVMState == VMSTATE_RESETTING_LS
3086 || enmVMState == VMSTATE_POWERING_OFF
3087 || enmVMState == VMSTATE_POWERING_OFF_LS,
3088 rc = VERR_INVALID_STATE);
3089
3090 if (RT_SUCCESS(rc))
3091 pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
3092
3093 LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3094 return rc;
3095}
3096
3097
3098/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
3099static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
3100{
3101 PDMDEV_ASSERT_DEVINS(pDevIns);
3102 PVM pVM = pDevIns->Internal.s.pVMR3;
3103
3104 VMSTATE enmVMState = VMR3GetState(pVM);
3105 if ( enmVMState == VMSTATE_SUSPENDING
3106 || enmVMState == VMSTATE_SUSPENDING_EXT_LS
3107 || enmVMState == VMSTATE_SUSPENDING_LS
3108 || enmVMState == VMSTATE_RESETTING
3109 || enmVMState == VMSTATE_RESETTING_LS
3110 || enmVMState == VMSTATE_POWERING_OFF
3111 || enmVMState == VMSTATE_POWERING_OFF_LS)
3112 {
3113 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
3114 VMR3AsyncPdmNotificationWakeupU(pVM->pUVM);
3115 }
3116 else
3117 LogFlow(("pdmR3DevHlp_AsyncNotificationCompleted: caller='%s'/%d: enmVMState=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, enmVMState));
3118}
3119
3120
3121/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
3122static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
3123{
3124 PDMDEV_ASSERT_DEVINS(pDevIns);
3125 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3126 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
3127 pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
3128 pRtcReg->pfnWrite, ppRtcHlp));
3129
3130 /*
3131 * Validate input.
3132 */
3133 if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
3134 {
3135 AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
3136 PDM_RTCREG_VERSION));
3137 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
3138 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3139 return VERR_INVALID_PARAMETER;
3140 }
3141 if ( !pRtcReg->pfnWrite
3142 || !pRtcReg->pfnRead)
3143 {
3144 Assert(pRtcReg->pfnWrite);
3145 Assert(pRtcReg->pfnRead);
3146 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
3147 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3148 return VERR_INVALID_PARAMETER;
3149 }
3150
3151 if (!ppRtcHlp)
3152 {
3153 Assert(ppRtcHlp);
3154 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
3155 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3156 return VERR_INVALID_PARAMETER;
3157 }
3158
3159 /*
3160 * Only one DMA device.
3161 */
3162 PVM pVM = pDevIns->Internal.s.pVMR3;
3163 if (pVM->pdm.s.pRtc)
3164 {
3165 AssertMsgFailed(("Only one RTC device is supported!\n"));
3166 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
3167 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3168 return VERR_INVALID_PARAMETER;
3169 }
3170
3171 /*
3172 * Allocate and initialize pci bus structure.
3173 */
3174 int rc = VINF_SUCCESS;
3175 PPDMRTC pRtc = (PPDMRTC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pRtc));
3176 if (pRtc)
3177 {
3178 pRtc->pDevIns = pDevIns;
3179 pRtc->Reg = *pRtcReg;
3180 pVM->pdm.s.pRtc = pRtc;
3181
3182 /* set the helper pointer. */
3183 *ppRtcHlp = &g_pdmR3DevRtcHlp;
3184 Log(("PDM: Registered RTC device '%s'/%d pDevIns=%p\n",
3185 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3186 }
3187 else
3188 rc = VERR_NO_MEMORY;
3189
3190 LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
3191 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3192 return rc;
3193}
3194
3195
3196/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
3197static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
3198{
3199 PDMDEV_ASSERT_DEVINS(pDevIns);
3200 PVM pVM = pDevIns->Internal.s.pVMR3;
3201 VM_ASSERT_EMT(pVM);
3202 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
3203 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
3204 int rc = VINF_SUCCESS;
3205 if (pVM->pdm.s.pDmac)
3206 pVM->pdm.s.pDmac->Reg.pfnRegister(pVM->pdm.s.pDmac->pDevIns, uChannel, pfnTransferHandler, pvUser);
3207 else
3208 {
3209 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3210 rc = VERR_PDM_NO_DMAC_INSTANCE;
3211 }
3212 LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
3213 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3214 return rc;
3215}
3216
3217
3218/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
3219static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
3220{
3221 PDMDEV_ASSERT_DEVINS(pDevIns);
3222 PVM pVM = pDevIns->Internal.s.pVMR3;
3223 VM_ASSERT_EMT(pVM);
3224 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
3225 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
3226 int rc = VINF_SUCCESS;
3227 if (pVM->pdm.s.pDmac)
3228 {
3229 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnReadMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3230 if (pcbRead)
3231 *pcbRead = cb;
3232 }
3233 else
3234 {
3235 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3236 rc = VERR_PDM_NO_DMAC_INSTANCE;
3237 }
3238 LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
3239 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3240 return rc;
3241}
3242
3243
3244/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
3245static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
3246{
3247 PDMDEV_ASSERT_DEVINS(pDevIns);
3248 PVM pVM = pDevIns->Internal.s.pVMR3;
3249 VM_ASSERT_EMT(pVM);
3250 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
3251 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
3252 int rc = VINF_SUCCESS;
3253 if (pVM->pdm.s.pDmac)
3254 {
3255 uint32_t cb = pVM->pdm.s.pDmac->Reg.pfnWriteMemory(pVM->pdm.s.pDmac->pDevIns, uChannel, pvBuffer, off, cbBlock);
3256 if (pcbWritten)
3257 *pcbWritten = cb;
3258 }
3259 else
3260 {
3261 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3262 rc = VERR_PDM_NO_DMAC_INSTANCE;
3263 }
3264 LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
3265 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3266 return rc;
3267}
3268
3269
3270/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
3271static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
3272{
3273 PDMDEV_ASSERT_DEVINS(pDevIns);
3274 PVM pVM = pDevIns->Internal.s.pVMR3;
3275 VM_ASSERT_EMT(pVM);
3276 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
3277 pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
3278 int rc = VINF_SUCCESS;
3279 if (pVM->pdm.s.pDmac)
3280 pVM->pdm.s.pDmac->Reg.pfnSetDREQ(pVM->pdm.s.pDmac->pDevIns, uChannel, uLevel);
3281 else
3282 {
3283 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3284 rc = VERR_PDM_NO_DMAC_INSTANCE;
3285 }
3286 LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
3287 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3288 return rc;
3289}
3290
3291/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
3292static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
3293{
3294 PDMDEV_ASSERT_DEVINS(pDevIns);
3295 PVM pVM = pDevIns->Internal.s.pVMR3;
3296 VM_ASSERT_EMT(pVM);
3297 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
3298 pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
3299 uint8_t u8Mode;
3300 if (pVM->pdm.s.pDmac)
3301 u8Mode = pVM->pdm.s.pDmac->Reg.pfnGetChannelMode(pVM->pdm.s.pDmac->pDevIns, uChannel);
3302 else
3303 {
3304 AssertMsgFailed(("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3305 u8Mode = 3 << 2 /* illegal mode type */;
3306 }
3307 LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
3308 pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
3309 return u8Mode;
3310}
3311
3312/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
3313static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
3314{
3315 PDMDEV_ASSERT_DEVINS(pDevIns);
3316 PVM pVM = pDevIns->Internal.s.pVMR3;
3317 VM_ASSERT_EMT(pVM);
3318 LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d: VM_FF_PDM_DMA %d -> 1\n",
3319 pDevIns->pReg->szName, pDevIns->iInstance, VM_FF_IS_SET(pVM, VM_FF_PDM_DMA)));
3320
3321 AssertMsg(pVM->pdm.s.pDmac, ("Configuration error: No DMAC controller available. This could be related to init order too!\n"));
3322 VM_FF_SET(pVM, VM_FF_PDM_DMA);
3323 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
3324}
3325
3326
3327/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
3328static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
3329{
3330 PDMDEV_ASSERT_DEVINS(pDevIns);
3331 PVM pVM = pDevIns->Internal.s.pVMR3;
3332 VM_ASSERT_EMT(pVM);
3333
3334 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
3335 pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
3336 int rc;
3337 if (pVM->pdm.s.pRtc)
3338 {
3339 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3340 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3341 if (RT_SUCCESS(rc))
3342 {
3343 rc = pVM->pdm.s.pRtc->Reg.pfnWrite(pDevInsRtc, iReg, u8Value);
3344 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
3345 }
3346 }
3347 else
3348 rc = VERR_PDM_NO_RTC_INSTANCE;
3349
3350 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3351 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3352 return rc;
3353}
3354
3355
3356/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
3357static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
3358{
3359 PDMDEV_ASSERT_DEVINS(pDevIns);
3360 PVM pVM = pDevIns->Internal.s.pVMR3;
3361 VM_ASSERT_EMT(pVM);
3362
3363 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
3364 pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
3365 int rc;
3366 if (pVM->pdm.s.pRtc)
3367 {
3368 PPDMDEVINS pDevInsRtc = pVM->pdm.s.pRtc->pDevIns;
3369 rc = PDMCritSectEnter(pDevInsRtc->pCritSectRoR3, VERR_IGNORED);
3370 if (RT_SUCCESS(rc))
3371 {
3372 rc = pVM->pdm.s.pRtc->Reg.pfnRead(pDevInsRtc, iReg, pu8Value);
3373 PDMCritSectLeave(pDevInsRtc->pCritSectRoR3);
3374 }
3375 }
3376 else
3377 rc = VERR_PDM_NO_RTC_INSTANCE;
3378
3379 LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
3380 pDevIns->pReg->szName, pDevIns->iInstance, rc));
3381 return rc;
3382}
3383
3384
3385/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
3386static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3387{
3388 PDMDEV_ASSERT_DEVINS(pDevIns);
3389 if (VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3390 return true;
3391
3392 char szMsg[100];
3393 RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3394 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3395 AssertBreakpoint();
3396 return false;
3397}
3398
3399
3400/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
3401static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
3402{
3403 PDMDEV_ASSERT_DEVINS(pDevIns);
3404 if (!VM_IS_EMT(pDevIns->Internal.s.pVMR3))
3405 return true;
3406
3407 char szMsg[100];
3408 RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
3409 RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
3410 AssertBreakpoint();
3411 return false;
3412}
3413
3414
3415/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
3416static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3417 const char *pszSymPrefix, const char *pszSymList)
3418{
3419 PDMDEV_ASSERT_DEVINS(pDevIns);
3420 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3421 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3422 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3423
3424 int rc;
3425 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3426 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3427 {
3428 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)
3429 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3430 pvInterface, cbInterface,
3431 pDevIns->pReg->pszRCMod, pDevIns->Internal.s.pDevR3->pszRCSearchPath,
3432 pszSymPrefix, pszSymList,
3433 false /*fRing0OrRC*/);
3434 else
3435 {
3436 AssertMsgFailed(("Not a raw-mode enabled driver\n"));
3437 rc = VERR_PERMISSION_DENIED;
3438 }
3439 }
3440 else
3441 {
3442 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3443 pszSymPrefix, pDevIns->pReg->szName));
3444 rc = VERR_INVALID_NAME;
3445 }
3446
3447 LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3448 pDevIns->iInstance, rc));
3449 return rc;
3450}
3451
3452
3453/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
3454static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
3455 const char *pszSymPrefix, const char *pszSymList)
3456{
3457 PDMDEV_ASSERT_DEVINS(pDevIns);
3458 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3459 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
3460 pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
3461
3462 int rc;
3463 if ( strncmp(pszSymPrefix, "dev", 3) == 0
3464 && RTStrIStr(pszSymPrefix + 3, pDevIns->pReg->szName) != NULL)
3465 {
3466 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3467 rc = PDMR3LdrGetInterfaceSymbols(pDevIns->Internal.s.pVMR3,
3468 pvInterface, cbInterface,
3469 pDevIns->pReg->pszR0Mod, pDevIns->Internal.s.pDevR3->pszR0SearchPath,
3470 pszSymPrefix, pszSymList,
3471 true /*fRing0OrRC*/);
3472 else
3473 {
3474 AssertMsgFailed(("Not a ring-0 enabled driver\n"));
3475 rc = VERR_PERMISSION_DENIED;
3476 }
3477 }
3478 else
3479 {
3480 AssertMsgFailed(("Invalid prefix '%s' for '%s'; must start with 'dev' and contain the driver name!\n",
3481 pszSymPrefix, pDevIns->pReg->szName));
3482 rc = VERR_INVALID_NAME;
3483 }
3484
3485 LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3486 pDevIns->iInstance, rc));
3487 return rc;
3488}
3489
3490
3491/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
3492static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
3493{
3494 PDMDEV_ASSERT_DEVINS(pDevIns);
3495 PVM pVM = pDevIns->Internal.s.pVMR3;
3496 PVMCPU pVCpu = VMMGetCpu(pVM);
3497 AssertReturn(pVCpu, VERR_VM_THREAD_IS_EMT);
3498 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
3499 pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
3500
3501 /*
3502 * Resolve the ring-0 entry point. There is not need to remember this like
3503 * we do for drivers since this is mainly for construction time hacks and
3504 * other things that aren't performance critical.
3505 */
3506 int rc;
3507 if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
3508 {
3509 /*
3510 * Make the ring-0 call.
3511 */
3512 PDMDEVICEGENCALLREQ Req;
3513 RT_ZERO(Req.Params);
3514 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
3515 Req.Hdr.cbReq = sizeof(Req);
3516 Req.pDevInsR3 = pDevIns;
3517 Req.idxR0Device = pDevIns->Internal.s.idxR0Device;
3518 Req.enmCall = PDMDEVICEGENCALL_REQUEST;
3519 Req.Params.Req.uReq = uOperation;
3520 Req.Params.Req.uArg = u64Arg;
3521 rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_PDM_DEVICE_GEN_CALL, 0, &Req.Hdr);
3522 }
3523 else
3524 rc = VERR_ACCESS_DENIED;
3525 LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
3526 pDevIns->iInstance, rc));
3527 return rc;
3528}
3529
3530
3531/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
3532static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
3533{
3534 PDMDEV_ASSERT_DEVINS(pDevIns);
3535 PVM pVM = pDevIns->Internal.s.pVMR3;
3536 VM_ASSERT_EMT(pVM);
3537 VMSUSPENDREASON enmReason = VMR3GetSuspendReason(pVM->pUVM);
3538 LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
3539 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3540 return enmReason;
3541}
3542
3543
3544/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
3545static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
3546{
3547 PDMDEV_ASSERT_DEVINS(pDevIns);
3548 PVM pVM = pDevIns->Internal.s.pVMR3;
3549 VM_ASSERT_EMT(pVM);
3550 VMRESUMEREASON enmReason = VMR3GetResumeReason(pVM->pUVM);
3551 LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
3552 pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
3553 return enmReason;
3554}
3555
3556
3557/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
3558static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
3559{
3560 PDMDEV_ASSERT_DEVINS(pDevIns);
3561 LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3562 return pDevIns->Internal.s.pVMR3->pUVM;
3563}
3564
3565
3566/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
3567static DECLCALLBACK(PVM) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
3568{
3569 PDMDEV_ASSERT_DEVINS(pDevIns);
3570 LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pVMR3));
3571 return pDevIns->Internal.s.pVMR3;
3572}
3573
3574
3575/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
3576static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
3577{
3578 PDMDEV_ASSERT_DEVINS(pDevIns);
3579 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3580 LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, VMMGetCpuId(pDevIns->Internal.s.pVMR3)));
3581 return VMMGetCpu(pDevIns->Internal.s.pVMR3);
3582}
3583
3584
3585/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
3586static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
3587{
3588 PDMDEV_ASSERT_DEVINS(pDevIns);
3589 VMCPUID idCpu = VMMGetCpuId(pDevIns->Internal.s.pVMR3);
3590 LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
3591 return idCpu;
3592}
3593
3594
3595/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
3596static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
3597 PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
3598{
3599 PDMDEV_ASSERT_DEVINS(pDevIns);
3600 PVM pVM = pDevIns->Internal.s.pVMR3;
3601 VM_ASSERT_EMT(pVM);
3602 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
3603 ".pfnInterceptConfigAccesses=%p, pfnConfigRead=%p, pfnConfigWrite=%p, .pfnSetIrqR3=%p, .u32EndVersion=%#x} ppPciHlpR3=%p piBus=%p\n",
3604 pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
3605 pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnInterceptConfigAccesses, pPciBusReg->pfnConfigRead,
3606 pPciBusReg->pfnConfigWrite, pPciBusReg->pfnSetIrqR3, pPciBusReg->u32EndVersion, ppPciHlp, piBus));
3607
3608 /*
3609 * Validate the structure and output parameters.
3610 */
3611 AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGR3_VERSION,
3612 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3613 VERR_INVALID_PARAMETER);
3614 AssertPtrReturn(pPciBusReg->pfnRegisterR3, VERR_INVALID_PARAMETER);
3615 AssertPtrNullReturn(pPciBusReg->pfnRegisterMsiR3, VERR_INVALID_POINTER);
3616 AssertPtrReturn(pPciBusReg->pfnIORegionRegisterR3, VERR_INVALID_POINTER);
3617 AssertPtrReturn(pPciBusReg->pfnInterceptConfigAccesses, VERR_INVALID_POINTER);
3618 AssertPtrReturn(pPciBusReg->pfnConfigWrite, VERR_INVALID_POINTER);
3619 AssertPtrReturn(pPciBusReg->pfnConfigRead, VERR_INVALID_POINTER);
3620 AssertPtrReturn(pPciBusReg->pfnSetIrqR3, VERR_INVALID_POINTER);
3621 AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGR3_VERSION,
3622 ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
3623 VERR_INVALID_PARAMETER);
3624 AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
3625 AssertPtrNullReturn(piBus, VERR_INVALID_POINTER);
3626 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
3627
3628 /*
3629 * Find free PCI bus entry.
3630 */
3631 unsigned iBus = 0;
3632 for (iBus = 0; iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses); iBus++)
3633 if (!pVM->pdm.s.aPciBuses[iBus].pDevInsR3)
3634 break;
3635 AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses),
3636 ("Too many PCI buses. Max=%u\n", RT_ELEMENTS(pVM->pdm.s.aPciBuses)),
3637 VERR_OUT_OF_RESOURCES);
3638 PPDMPCIBUS pPciBus = &pVM->pdm.s.aPciBuses[iBus];
3639
3640 /*
3641 * Init the R3 bits.
3642 */
3643 pPciBus->iBus = iBus;
3644 pPciBus->pDevInsR3 = pDevIns;
3645 pPciBus->pfnRegister = pPciBusReg->pfnRegisterR3;
3646 pPciBus->pfnRegisterMsi = pPciBusReg->pfnRegisterMsiR3;
3647 pPciBus->pfnIORegionRegister = pPciBusReg->pfnIORegionRegisterR3;
3648 pPciBus->pfnInterceptConfigAccesses = pPciBusReg->pfnInterceptConfigAccesses;
3649 pPciBus->pfnConfigRead = pPciBusReg->pfnConfigRead;
3650 pPciBus->pfnConfigWrite = pPciBusReg->pfnConfigWrite;
3651 pPciBus->pfnSetIrqR3 = pPciBusReg->pfnSetIrqR3;
3652
3653 Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3654
3655 /* set the helper pointer and return. */
3656 *ppPciHlp = &g_pdmR3DevPciHlp;
3657 if (piBus)
3658 *piBus = iBus;
3659 LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS, iBus));
3660 return VINF_SUCCESS;
3661}
3662
3663
3664/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
3665static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
3666{
3667 PDMDEV_ASSERT_DEVINS(pDevIns);
3668 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3669 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",
3670 pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrqR3, pPicReg->pfnGetInterruptR3,
3671 pPicReg->pszSetIrqRC, pPicReg->pszSetIrqRC, pPicReg->pszGetInterruptRC, pPicReg->pszGetInterruptRC,
3672 pPicReg->pszSetIrqR0, pPicReg->pszSetIrqR0, pPicReg->pszGetInterruptR0, pPicReg->pszGetInterruptR0,
3673 ppPicHlpR3));
3674
3675 /*
3676 * Validate input.
3677 */
3678 if (pPicReg->u32Version != PDM_PICREG_VERSION)
3679 {
3680 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPicReg->u32Version, PDM_PICREG_VERSION));
3681 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3682 return VERR_INVALID_PARAMETER;
3683 }
3684 if ( !pPicReg->pfnSetIrqR3
3685 || !pPicReg->pfnGetInterruptR3)
3686 {
3687 Assert(pPicReg->pfnSetIrqR3);
3688 Assert(pPicReg->pfnGetInterruptR3);
3689 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3690 return VERR_INVALID_PARAMETER;
3691 }
3692 if ( ( pPicReg->pszSetIrqRC
3693 || pPicReg->pszGetInterruptRC)
3694 && ( !VALID_PTR(pPicReg->pszSetIrqRC)
3695 || !VALID_PTR(pPicReg->pszGetInterruptRC))
3696 )
3697 {
3698 Assert(VALID_PTR(pPicReg->pszSetIrqRC));
3699 Assert(VALID_PTR(pPicReg->pszGetInterruptRC));
3700 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3701 return VERR_INVALID_PARAMETER;
3702 }
3703 if ( pPicReg->pszSetIrqRC
3704 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC))
3705 {
3706 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC);
3707 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (RC flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3708 return VERR_INVALID_PARAMETER;
3709 }
3710 if ( pPicReg->pszSetIrqR0
3711 && !(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))
3712 {
3713 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0);
3714 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (R0 flag)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3715 return VERR_INVALID_PARAMETER;
3716 }
3717 if (!ppPicHlpR3)
3718 {
3719 Assert(ppPicHlpR3);
3720 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc (ppPicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3721 return VERR_INVALID_PARAMETER;
3722 }
3723
3724 /*
3725 * Only one PIC device.
3726 */
3727 PVM pVM = pDevIns->Internal.s.pVMR3;
3728 if (pVM->pdm.s.Pic.pDevInsR3)
3729 {
3730 AssertMsgFailed(("Only one pic device is supported!\n"));
3731 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3732 return VERR_INVALID_PARAMETER;
3733 }
3734
3735 /*
3736 * RC stuff.
3737 */
3738 if (pPicReg->pszSetIrqRC)
3739 {
3740 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszSetIrqRC, &pVM->pdm.s.Pic.pfnSetIrqRC);
3741 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pPicReg->pszSetIrqRC, rc));
3742 if (RT_SUCCESS(rc))
3743 {
3744 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pPicReg->pszGetInterruptRC, &pVM->pdm.s.Pic.pfnGetInterruptRC);
3745 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pPicReg->pszGetInterruptRC, rc));
3746 }
3747 if (RT_FAILURE(rc))
3748 {
3749 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3750 return rc;
3751 }
3752 pVM->pdm.s.Pic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3753 }
3754 else
3755 {
3756 pVM->pdm.s.Pic.pDevInsRC = 0;
3757 pVM->pdm.s.Pic.pfnSetIrqRC = 0;
3758 pVM->pdm.s.Pic.pfnGetInterruptRC = 0;
3759 }
3760
3761 /*
3762 * R0 stuff.
3763 */
3764 if (pPicReg->pszSetIrqR0)
3765 {
3766 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszSetIrqR0, &pVM->pdm.s.Pic.pfnSetIrqR0);
3767 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pPicReg->pszSetIrqR0, rc));
3768 if (RT_SUCCESS(rc))
3769 {
3770 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pPicReg->pszGetInterruptR0, &pVM->pdm.s.Pic.pfnGetInterruptR0);
3771 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pPicReg->pszGetInterruptR0, rc));
3772 }
3773 if (RT_FAILURE(rc))
3774 {
3775 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3776 return rc;
3777 }
3778 pVM->pdm.s.Pic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3779 Assert(pVM->pdm.s.Pic.pDevInsR0);
3780 }
3781 else
3782 {
3783 pVM->pdm.s.Pic.pfnSetIrqR0 = 0;
3784 pVM->pdm.s.Pic.pfnGetInterruptR0 = 0;
3785 pVM->pdm.s.Pic.pDevInsR0 = 0;
3786 }
3787
3788 /*
3789 * R3 stuff.
3790 */
3791 pVM->pdm.s.Pic.pDevInsR3 = pDevIns;
3792 pVM->pdm.s.Pic.pfnSetIrqR3 = pPicReg->pfnSetIrqR3;
3793 pVM->pdm.s.Pic.pfnGetInterruptR3 = pPicReg->pfnGetInterruptR3;
3794 Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
3795
3796 /* set the helper pointer and return. */
3797 *ppPicHlpR3 = &g_pdmR3DevPicHlp;
3798 LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3799 return VINF_SUCCESS;
3800}
3801
3802
3803/** @interface_method_impl{PDMDEVHLPR3,pfnAPICRegister} */
3804static DECLCALLBACK(int) pdmR3DevHlp_APICRegister(PPDMDEVINS pDevIns)
3805{
3806 PDMDEV_ASSERT_DEVINS(pDevIns);
3807 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3808
3809 /*
3810 * Only one APIC device. On SMP we have single logical device covering all LAPICs,
3811 * as they need to communicate and share state easily.
3812 */
3813 PVM pVM = pDevIns->Internal.s.pVMR3;
3814 if (pVM->pdm.s.Apic.pDevInsR3)
3815 {
3816 AssertMsgFailed(("Only one APIC device is supported!\n"));
3817 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3818 return VERR_INVALID_PARAMETER;
3819 }
3820
3821 /*
3822 * Initialize the RC, R0 and HC bits.
3823 */
3824 pVM->pdm.s.Apic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3825 Assert(pVM->pdm.s.Apic.pDevInsRC || !VM_IS_RAW_MODE_ENABLED(pVM));
3826
3827 pVM->pdm.s.Apic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3828 Assert(pVM->pdm.s.Apic.pDevInsR0);
3829
3830 pVM->pdm.s.Apic.pDevInsR3 = pDevIns;
3831 LogFlow(("pdmR3DevHlp_APICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
3832 return VINF_SUCCESS;
3833}
3834
3835
3836/** @interface_method_impl{PDMDEVHLPR3,pfnIOAPICRegister} */
3837static DECLCALLBACK(int) pdmR3DevHlp_IOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
3838{
3839 PDMDEV_ASSERT_DEVINS(pDevIns);
3840 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
3841 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrqR3=%p, .pszSetIrqRC=%p:{%s}, .pszSetIrqR0=%p:{%s}} ppIoApicHlpR3=%p\n",
3842 pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrqR3,
3843 pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqRC, pIoApicReg->pszSetIrqR0, pIoApicReg->pszSetIrqR0, ppIoApicHlpR3));
3844
3845 /*
3846 * Validate input.
3847 */
3848 if (pIoApicReg->u32Version != PDM_IOAPICREG_VERSION)
3849 {
3850 AssertMsgFailed(("u32Version=%#x expected %#x\n", pIoApicReg->u32Version, PDM_IOAPICREG_VERSION));
3851 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3852 return VERR_INVALID_PARAMETER;
3853 }
3854 if (!pIoApicReg->pfnSetIrqR3 || !pIoApicReg->pfnSendMsiR3 || !pIoApicReg->pfnSetEoiR3)
3855 {
3856 Assert(pIoApicReg->pfnSetIrqR3);
3857 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (R3 callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3858 return VERR_INVALID_PARAMETER;
3859 }
3860 if ( pIoApicReg->pszSetIrqRC
3861 && !VALID_PTR(pIoApicReg->pszSetIrqRC))
3862 {
3863 Assert(VALID_PTR(pIoApicReg->pszSetIrqRC));
3864 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3865 return VERR_INVALID_PARAMETER;
3866 }
3867 if ( pIoApicReg->pszSendMsiRC
3868 && !VALID_PTR(pIoApicReg->pszSendMsiRC))
3869 {
3870 Assert(VALID_PTR(pIoApicReg->pszSendMsiRC));
3871 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3872 return VERR_INVALID_PARAMETER;
3873 }
3874 if ( pIoApicReg->pszSetEoiRC
3875 && !VALID_PTR(pIoApicReg->pszSetEoiRC))
3876 {
3877 Assert(VALID_PTR(pIoApicReg->pszSetEoiRC));
3878 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (GC callbacks)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3879 return VERR_INVALID_PARAMETER;
3880 }
3881 if ( pIoApicReg->pszSetIrqR0
3882 && !VALID_PTR(pIoApicReg->pszSetIrqR0))
3883 {
3884 Assert(VALID_PTR(pIoApicReg->pszSetIrqR0));
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->pszSendMsiR0
3889 && !VALID_PTR(pIoApicReg->pszSendMsiR0))
3890 {
3891 Assert(VALID_PTR(pIoApicReg->pszSendMsiR0));
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->pszSetEoiR0
3896 && !VALID_PTR(pIoApicReg->pszSetEoiR0))
3897 {
3898 Assert(VALID_PTR(pIoApicReg->pszSetEoiR0));
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 (!ppIoApicHlpR3)
3903 {
3904 Assert(ppIoApicHlpR3);
3905 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (ppApicHlp)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3906 return VERR_INVALID_PARAMETER;
3907 }
3908
3909 /*
3910 * The I/O APIC requires the APIC to be present (hacks++).
3911 * If the I/O APIC does GC stuff so must the APIC.
3912 */
3913 PVM pVM = pDevIns->Internal.s.pVMR3;
3914 if (!pVM->pdm.s.Apic.pDevInsR3)
3915 {
3916 AssertMsgFailed(("Configuration error / Init order error! No APIC!\n"));
3917 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3918 return VERR_INVALID_PARAMETER;
3919 }
3920#if 0
3921 if ( pIoApicReg->pszSetIrqRC
3922 && !pVM->pdm.s.Apic.pDevInsRC)
3923 {
3924 AssertMsgFailed(("Configuration error! APIC doesn't do GC, I/O APIC does!\n"));
3925 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (no GC APIC)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3926 return VERR_INVALID_PARAMETER;
3927 }
3928#endif
3929
3930 /*
3931 * Only one I/O APIC device.
3932 */
3933 if (pVM->pdm.s.IoApic.pDevInsR3)
3934 {
3935 AssertMsgFailed(("Only one ioapic device is supported!\n"));
3936 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc (only one)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
3937 return VERR_INVALID_PARAMETER;
3938 }
3939
3940 /*
3941 * Resolve & initialize the GC bits.
3942 */
3943 if (pIoApicReg->pszSetIrqRC)
3944 {
3945 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetIrqRC, &pVM->pdm.s.IoApic.pfnSetIrqRC);
3946 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetIrqRC, rc));
3947 if (RT_FAILURE(rc))
3948 {
3949 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3950 return rc;
3951 }
3952 pVM->pdm.s.IoApic.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3953 }
3954 else
3955 {
3956 pVM->pdm.s.IoApic.pDevInsRC = 0;
3957 pVM->pdm.s.IoApic.pfnSetIrqRC = 0;
3958 }
3959
3960 if (pIoApicReg->pszSendMsiRC)
3961 {
3962 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSendMsiRC, &pVM->pdm.s.IoApic.pfnSendMsiRC);
3963 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSendMsiRC, rc));
3964 if (RT_FAILURE(rc))
3965 {
3966 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3967 return rc;
3968 }
3969 }
3970 else
3971 {
3972 pVM->pdm.s.IoApic.pfnSendMsiRC = 0;
3973 }
3974
3975 if (pIoApicReg->pszSetEoiRC)
3976 {
3977 int rc = pdmR3DevGetSymbolRCLazy(pDevIns, pIoApicReg->pszSetEoiRC, &pVM->pdm.s.IoApic.pfnSetEoiRC);
3978 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszRCMod, pIoApicReg->pszSetEoiRC, rc));
3979 if (RT_FAILURE(rc))
3980 {
3981 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
3982 return rc;
3983 }
3984 }
3985 else
3986 {
3987 pVM->pdm.s.IoApic.pfnSetEoiRC = 0;
3988 }
3989
3990 /*
3991 * Resolve & initialize the R0 bits.
3992 */
3993 if (pIoApicReg->pszSetIrqR0)
3994 {
3995 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetIrqR0, &pVM->pdm.s.IoApic.pfnSetIrqR0);
3996 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetIrqR0, rc));
3997 if (RT_FAILURE(rc))
3998 {
3999 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4000 return rc;
4001 }
4002 pVM->pdm.s.IoApic.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
4003 Assert(pVM->pdm.s.IoApic.pDevInsR0);
4004 }
4005 else
4006 {
4007 pVM->pdm.s.IoApic.pfnSetIrqR0 = 0;
4008 pVM->pdm.s.IoApic.pDevInsR0 = 0;
4009 }
4010
4011 if (pIoApicReg->pszSendMsiR0)
4012 {
4013 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSendMsiR0, &pVM->pdm.s.IoApic.pfnSendMsiR0);
4014 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSendMsiR0, rc));
4015 if (RT_FAILURE(rc))
4016 {
4017 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4018 return rc;
4019 }
4020 }
4021 else
4022 {
4023 pVM->pdm.s.IoApic.pfnSendMsiR0 = 0;
4024 }
4025
4026 if (pIoApicReg->pszSetEoiR0)
4027 {
4028 int rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pIoApicReg->pszSetEoiR0, &pVM->pdm.s.IoApic.pfnSetEoiR0);
4029 AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->pszR0Mod, pIoApicReg->pszSetEoiR0, rc));
4030 if (RT_FAILURE(rc))
4031 {
4032 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4033 return rc;
4034 }
4035 }
4036 else
4037 {
4038 pVM->pdm.s.IoApic.pfnSetEoiR0 = 0;
4039 }
4040
4041
4042 /*
4043 * Initialize the R3 bits.
4044 */
4045 pVM->pdm.s.IoApic.pDevInsR3 = pDevIns;
4046 pVM->pdm.s.IoApic.pfnSetIrqR3 = pIoApicReg->pfnSetIrqR3;
4047 pVM->pdm.s.IoApic.pfnSendMsiR3 = pIoApicReg->pfnSendMsiR3;
4048 pVM->pdm.s.IoApic.pfnSetEoiR3 = pIoApicReg->pfnSetEoiR3;
4049 Log(("PDM: Registered I/O APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
4050
4051 /* set the helper pointer and return. */
4052 *ppIoApicHlpR3 = &g_pdmR3DevIoApicHlp;
4053 LogFlow(("pdmR3DevHlp_IOAPICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
4054 return VINF_SUCCESS;
4055}
4056
4057
4058/** @interface_method_impl{PDMDEVHLPR3,pfnHPETRegister} */
4059static DECLCALLBACK(int) pdmR3DevHlp_HPETRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
4060{
4061 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
4062 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4063 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
4064
4065 /*
4066 * Validate input.
4067 */
4068 if (pHpetReg->u32Version != PDM_HPETREG_VERSION)
4069 {
4070 AssertMsgFailed(("u32Version=%#x expected %#x\n", pHpetReg->u32Version, PDM_HPETREG_VERSION));
4071 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4072 return VERR_INVALID_PARAMETER;
4073 }
4074
4075 if (!ppHpetHlpR3)
4076 {
4077 Assert(ppHpetHlpR3);
4078 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc (ppApicHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4079 return VERR_INVALID_PARAMETER;
4080 }
4081
4082 /* set the helper pointer and return. */
4083 *ppHpetHlpR3 = &g_pdmR3DevHpetHlp;
4084 LogFlow(("pdmR3DevHlp_HPETRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
4085 return VINF_SUCCESS;
4086}
4087
4088
4089/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
4090static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
4091{
4092 PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
4093 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4094 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
4095
4096 /*
4097 * Validate input.
4098 */
4099 if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
4100 {
4101 AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
4102 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4103 return VERR_INVALID_PARAMETER;
4104 }
4105
4106 if (!ppPciRawHlpR3)
4107 {
4108 Assert(ppPciRawHlpR3);
4109 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4110 return VERR_INVALID_PARAMETER;
4111 }
4112
4113 /* set the helper pointer and return. */
4114 *ppPciRawHlpR3 = &g_pdmR3DevPciRawHlp;
4115 LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
4116 return VINF_SUCCESS;
4117}
4118
4119
4120/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
4121static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
4122{
4123 PDMDEV_ASSERT_DEVINS(pDevIns);
4124 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4125 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",
4126 pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
4127 pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
4128
4129 /*
4130 * Validate input.
4131 */
4132 if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
4133 {
4134 AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
4135 PDM_DMACREG_VERSION));
4136 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
4137 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4138 return VERR_INVALID_PARAMETER;
4139 }
4140 if ( !pDmacReg->pfnRun
4141 || !pDmacReg->pfnRegister
4142 || !pDmacReg->pfnReadMemory
4143 || !pDmacReg->pfnWriteMemory
4144 || !pDmacReg->pfnSetDREQ
4145 || !pDmacReg->pfnGetChannelMode)
4146 {
4147 Assert(pDmacReg->pfnRun);
4148 Assert(pDmacReg->pfnRegister);
4149 Assert(pDmacReg->pfnReadMemory);
4150 Assert(pDmacReg->pfnWriteMemory);
4151 Assert(pDmacReg->pfnSetDREQ);
4152 Assert(pDmacReg->pfnGetChannelMode);
4153 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
4154 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4155 return VERR_INVALID_PARAMETER;
4156 }
4157
4158 if (!ppDmacHlp)
4159 {
4160 Assert(ppDmacHlp);
4161 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
4162 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4163 return VERR_INVALID_PARAMETER;
4164 }
4165
4166 /*
4167 * Only one DMA device.
4168 */
4169 PVM pVM = pDevIns->Internal.s.pVMR3;
4170 if (pVM->pdm.s.pDmac)
4171 {
4172 AssertMsgFailed(("Only one DMA device is supported!\n"));
4173 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
4174 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4175 return VERR_INVALID_PARAMETER;
4176 }
4177
4178 /*
4179 * Allocate and initialize pci bus structure.
4180 */
4181 int rc = VINF_SUCCESS;
4182 PPDMDMAC pDmac = (PPDMDMAC)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pDmac));
4183 if (pDmac)
4184 {
4185 pDmac->pDevIns = pDevIns;
4186 pDmac->Reg = *pDmacReg;
4187 pVM->pdm.s.pDmac = pDmac;
4188
4189 /* set the helper pointer. */
4190 *ppDmacHlp = &g_pdmR3DevDmacHlp;
4191 Log(("PDM: Registered DMAC device '%s'/%d pDevIns=%p\n",
4192 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
4193 }
4194 else
4195 rc = VERR_NO_MEMORY;
4196
4197 LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
4198 pDevIns->pReg->szName, pDevIns->iInstance, rc));
4199 return rc;
4200}
4201
4202
4203/**
4204 * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
4205 */
4206static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
4207{
4208 PDMDEV_ASSERT_DEVINS(pDevIns);
4209 PVM pVM = pDevIns->Internal.s.pVMR3;
4210 VM_ASSERT_EMT(pVM);
4211 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
4212 pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
4213
4214 if (pVM->pdm.s.pvVMMDevHeap == NULL)
4215 {
4216 pVM->pdm.s.pvVMMDevHeap = pvHeap;
4217 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
4218 pVM->pdm.s.cbVMMDevHeap = cbHeap;
4219 pVM->pdm.s.cbVMMDevHeapLeft = cbHeap;
4220 }
4221 else
4222 {
4223 Assert(pVM->pdm.s.pvVMMDevHeap == pvHeap);
4224 Assert(pVM->pdm.s.cbVMMDevHeap == cbHeap);
4225 Assert(pVM->pdm.s.GCPhysVMMDevHeap != GCPhys || GCPhys == NIL_RTGCPHYS);
4226 if (pVM->pdm.s.GCPhysVMMDevHeap != GCPhys)
4227 {
4228 pVM->pdm.s.GCPhysVMMDevHeap = GCPhys;
4229 if (pVM->pdm.s.pfnVMMDevHeapNotify)
4230 pVM->pdm.s.pfnVMMDevHeapNotify(pVM, pvHeap, GCPhys);
4231 }
4232 }
4233
4234 LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
4235 pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
4236 return VINF_SUCCESS;
4237}
4238
4239
4240/**
4241 * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
4242 */
4243static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4244{
4245 PDMDEV_ASSERT_DEVINS(pDevIns);
4246 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4247 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
4248 pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
4249
4250 /*
4251 * Validate input.
4252 */
4253 if (pFwReg->u32Version != PDM_FWREG_VERSION)
4254 {
4255 AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
4256 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
4257 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4258 return VERR_INVALID_PARAMETER;
4259 }
4260 if (!pFwReg->pfnIsHardReset)
4261 {
4262 Assert(pFwReg->pfnIsHardReset);
4263 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
4264 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4265 return VERR_INVALID_PARAMETER;
4266 }
4267
4268 if (!ppFwHlp)
4269 {
4270 Assert(ppFwHlp);
4271 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
4272 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4273 return VERR_INVALID_PARAMETER;
4274 }
4275
4276 /*
4277 * Only one DMA device.
4278 */
4279 PVM pVM = pDevIns->Internal.s.pVMR3;
4280 if (pVM->pdm.s.pFirmware)
4281 {
4282 AssertMsgFailed(("Only one firmware device is supported!\n"));
4283 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
4284 pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
4285 return VERR_INVALID_PARAMETER;
4286 }
4287
4288 /*
4289 * Allocate and initialize pci bus structure.
4290 */
4291 int rc = VINF_SUCCESS;
4292 PPDMFW pFirmware = (PPDMFW)MMR3HeapAlloc(pDevIns->Internal.s.pVMR3, MM_TAG_PDM_DEVICE, sizeof(*pFirmware));
4293 if (pFirmware)
4294 {
4295 pFirmware->pDevIns = pDevIns;
4296 pFirmware->Reg = *pFwReg;
4297 pVM->pdm.s.pFirmware = pFirmware;
4298
4299 /* set the helper pointer. */
4300 *ppFwHlp = &g_pdmR3DevFirmwareHlp;
4301 Log(("PDM: Registered firmware device '%s'/%d pDevIns=%p\n",
4302 pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
4303 }
4304 else
4305 rc = VERR_NO_MEMORY;
4306
4307 LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
4308 pDevIns->pReg->szName, pDevIns->iInstance, rc));
4309 return rc;
4310}
4311
4312
4313/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4314static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4315{
4316 PDMDEV_ASSERT_DEVINS(pDevIns);
4317 PVM pVM = pDevIns->Internal.s.pVMR3;
4318 VM_ASSERT_EMT(pVM);
4319 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x VM_FF_RESET %d -> 1\n",
4320 pDevIns->pReg->szName, pDevIns->iInstance, fFlags, VM_FF_IS_SET(pVM, VM_FF_RESET)));
4321
4322 /*
4323 * We postpone this operation because we're likely to be inside a I/O instruction
4324 * and the EIP will be updated when we return.
4325 * We still return VINF_EM_RESET to break out of any execution loops and force FF evaluation.
4326 */
4327 bool fHaltOnReset;
4328 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
4329 if (RT_SUCCESS(rc) && fHaltOnReset)
4330 {
4331 Log(("pdmR3DevHlp_VMReset: Halt On Reset!\n"));
4332 rc = VINF_EM_HALT;
4333 }
4334 else
4335 {
4336 pVM->pdm.s.fResetFlags = fFlags;
4337 VM_FF_SET(pVM, VM_FF_RESET);
4338 rc = VINF_EM_RESET;
4339 }
4340
4341 LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4342 return rc;
4343}
4344
4345
4346/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4347static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
4348{
4349 int rc;
4350 PDMDEV_ASSERT_DEVINS(pDevIns);
4351 PVM pVM = pDevIns->Internal.s.pVMR3;
4352 VM_ASSERT_EMT(pVM);
4353 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
4354 pDevIns->pReg->szName, pDevIns->iInstance));
4355
4356 /** @todo Always take the SMP path - fewer code paths. */
4357 if (pVM->cCpus > 1)
4358 {
4359 /* We own the IOM lock here and could cause a deadlock by waiting for a VCPU that is blocking on the IOM lock. */
4360 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3Suspend, 2, pVM->pUVM, VMSUSPENDREASON_VM);
4361 AssertRC(rc);
4362 rc = VINF_EM_SUSPEND;
4363 }
4364 else
4365 rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
4366
4367 LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4368 return rc;
4369}
4370
4371
4372/**
4373 * Worker for pdmR3DevHlp_VMSuspendSaveAndPowerOff that is invoked via a queued
4374 * EMT request to avoid deadlocks.
4375 *
4376 * @returns VBox status code fit for scheduling.
4377 * @param pVM The cross context VM structure.
4378 * @param pDevIns The device that triggered this action.
4379 */
4380static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker(PVM pVM, PPDMDEVINS pDevIns)
4381{
4382 /*
4383 * Suspend the VM first then do the saving.
4384 */
4385 int rc = VMR3Suspend(pVM->pUVM, VMSUSPENDREASON_VM);
4386 if (RT_SUCCESS(rc))
4387 {
4388 PUVM pUVM = pVM->pUVM;
4389 rc = pUVM->pVmm2UserMethods->pfnSaveState(pVM->pUVM->pVmm2UserMethods, pUVM);
4390
4391 /*
4392 * On success, power off the VM, on failure we'll leave it suspended.
4393 */
4394 if (RT_SUCCESS(rc))
4395 {
4396 rc = VMR3PowerOff(pVM->pUVM);
4397 if (RT_FAILURE(rc))
4398 LogRel(("%s/SSP: VMR3PowerOff failed: %Rrc\n", pDevIns->pReg->szName, rc));
4399 }
4400 else
4401 LogRel(("%s/SSP: pfnSaveState failed: %Rrc\n", pDevIns->pReg->szName, rc));
4402 }
4403 else
4404 LogRel(("%s/SSP: Suspend failed: %Rrc\n", pDevIns->pReg->szName, rc));
4405 return rc;
4406}
4407
4408
4409/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4410static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4411{
4412 PDMDEV_ASSERT_DEVINS(pDevIns);
4413 PVM pVM = pDevIns->Internal.s.pVMR3;
4414 VM_ASSERT_EMT(pVM);
4415 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
4416 pDevIns->pReg->szName, pDevIns->iInstance));
4417
4418 int rc;
4419 if ( pVM->pUVM->pVmm2UserMethods
4420 && pVM->pUVM->pVmm2UserMethods->pfnSaveState)
4421 {
4422 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)pdmR3DevHlp_VMSuspendSaveAndPowerOffWorker, 2, pVM, pDevIns);
4423 if (RT_SUCCESS(rc))
4424 {
4425 LogRel(("%s: Suspending, Saving and Powering Off the VM\n", pDevIns->pReg->szName));
4426 rc = VINF_EM_SUSPEND;
4427 }
4428 }
4429 else
4430 rc = VERR_NOT_SUPPORTED;
4431
4432 LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4433 return rc;
4434}
4435
4436
4437/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4438static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
4439{
4440 int rc;
4441 PDMDEV_ASSERT_DEVINS(pDevIns);
4442 PVM pVM = pDevIns->Internal.s.pVMR3;
4443 VM_ASSERT_EMT(pVM);
4444 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
4445 pDevIns->pReg->szName, pDevIns->iInstance));
4446
4447 /** @todo Always take the SMP path - fewer code paths. */
4448 if (pVM->cCpus > 1)
4449 {
4450 /* We might be holding locks here and could cause a deadlock since
4451 VMR3PowerOff rendezvous with the other CPUs. */
4452 rc = VMR3ReqCallNoWait(pVM, VMCPUID_ANY_QUEUE, (PFNRT)VMR3PowerOff, 1, pVM->pUVM);
4453 AssertRC(rc);
4454 /* Set the VCPU state to stopped here as well to make sure no
4455 inconsistency with the EM state occurs. */
4456 VMCPU_SET_STATE(VMMGetCpu(pVM), VMCPUSTATE_STOPPED);
4457 rc = VINF_EM_OFF;
4458 }
4459 else
4460 rc = VMR3PowerOff(pVM->pUVM);
4461
4462 LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
4463 return rc;
4464}
4465
4466
4467/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4468static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
4469{
4470 PDMDEV_ASSERT_DEVINS(pDevIns);
4471 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4472
4473 bool fRc = PGMPhysIsA20Enabled(VMMGetCpu(pDevIns->Internal.s.pVMR3));
4474
4475 LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
4476 return fRc;
4477}
4478
4479
4480/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4481static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4482{
4483 PDMDEV_ASSERT_DEVINS(pDevIns);
4484 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4485 LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
4486 PGMR3PhysSetA20(VMMGetCpu(pDevIns->Internal.s.pVMR3), fEnable);
4487}
4488
4489
4490/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4491static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4492 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4493{
4494 PDMDEV_ASSERT_DEVINS(pDevIns);
4495 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
4496
4497 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
4498 pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
4499 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
4500
4501 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx);
4502
4503 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
4504 pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
4505}
4506
4507
4508/**
4509 * The device helper structure for trusted devices.
4510 */
4511const PDMDEVHLPR3 g_pdmR3DevHlpTrusted =
4512{
4513 PDM_DEVHLPR3_VERSION,
4514 pdmR3DevHlp_IoPortCreateEx,
4515 pdmR3DevHlp_IoPortMap,
4516 pdmR3DevHlp_IoPortUnmap,
4517 pdmR3DevHlp_IoPortGetMappingAddress,
4518 pdmR3DevHlp_IOPortRegister,
4519 pdmR3DevHlp_IOPortRegisterRC,
4520 pdmR3DevHlp_IOPortRegisterR0,
4521 pdmR3DevHlp_IOPortDeregister,
4522 pdmR3DevHlp_MmioCreateEx,
4523 pdmR3DevHlp_MmioMap,
4524 pdmR3DevHlp_MmioUnmap,
4525 pdmR3DevHlp_MmioReduce,
4526 pdmR3DevHlp_MmioGetMappingAddress,
4527 pdmR3DevHlp_MMIORegister,
4528 pdmR3DevHlp_MMIORegisterRC,
4529 pdmR3DevHlp_MMIORegisterR0,
4530 pdmR3DevHlp_MMIODeregister,
4531 pdmR3DevHlp_Mmio2Create,
4532 pdmR3DevHlp_Mmio2Destroy,
4533 pdmR3DevHlp_Mmio2Map,
4534 pdmR3DevHlp_Mmio2Unmap,
4535 pdmR3DevHlp_Mmio2Reduce,
4536 pdmR3DevHlp_Mmio2GetMappingAddress,
4537 pdmR3DevHlp_Mmio2ChangeRegionNo,
4538 pdmR3DevHlp_MMIO2Register,
4539 pdmR3DevHlp_MMIOExDeregister,
4540 pdmR3DevHlp_MMIOExMap,
4541 pdmR3DevHlp_MMIOExUnmap,
4542 pdmR3DevHlp_MMIOExReduce,
4543 pdmR3DevHlp_MMHyperMapMMIO2,
4544 pdmR3DevHlp_MMIO2MapKernel,
4545 pdmR3DevHlp_ROMRegister,
4546 pdmR3DevHlp_ROMProtectShadow,
4547 pdmR3DevHlp_SSMRegister,
4548 SSMR3PutStruct,
4549 SSMR3PutStructEx,
4550 SSMR3PutBool,
4551 SSMR3PutU8,
4552 SSMR3PutS8,
4553 SSMR3PutU16,
4554 SSMR3PutS16,
4555 SSMR3PutU32,
4556 SSMR3PutS32,
4557 SSMR3PutU64,
4558 SSMR3PutS64,
4559 SSMR3PutU128,
4560 SSMR3PutS128,
4561 SSMR3PutUInt,
4562 SSMR3PutSInt,
4563 SSMR3PutGCUInt,
4564 SSMR3PutGCUIntReg,
4565 SSMR3PutGCPhys32,
4566 SSMR3PutGCPhys64,
4567 SSMR3PutGCPhys,
4568 SSMR3PutGCPtr,
4569 SSMR3PutGCUIntPtr,
4570 SSMR3PutRCPtr,
4571 SSMR3PutIOPort,
4572 SSMR3PutSel,
4573 SSMR3PutMem,
4574 SSMR3PutStrZ,
4575 SSMR3GetStruct,
4576 SSMR3GetStructEx,
4577 SSMR3GetBool,
4578 SSMR3GetBoolV,
4579 SSMR3GetU8,
4580 SSMR3GetU8V,
4581 SSMR3GetS8,
4582 SSMR3GetS8V,
4583 SSMR3GetU16,
4584 SSMR3GetU16V,
4585 SSMR3GetS16,
4586 SSMR3GetS16V,
4587 SSMR3GetU32,
4588 SSMR3GetU32V,
4589 SSMR3GetS32,
4590 SSMR3GetS32V,
4591 SSMR3GetU64,
4592 SSMR3GetU64V,
4593 SSMR3GetS64,
4594 SSMR3GetS64V,
4595 SSMR3GetU128,
4596 SSMR3GetU128V,
4597 SSMR3GetS128,
4598 SSMR3GetS128V,
4599 SSMR3GetGCPhys32,
4600 SSMR3GetGCPhys32V,
4601 SSMR3GetGCPhys64,
4602 SSMR3GetGCPhys64V,
4603 SSMR3GetGCPhys,
4604 SSMR3GetGCPhysV,
4605 SSMR3GetUInt,
4606 SSMR3GetSInt,
4607 SSMR3GetGCUInt,
4608 SSMR3GetGCUIntReg,
4609 SSMR3GetGCPtr,
4610 SSMR3GetGCUIntPtr,
4611 SSMR3GetRCPtr,
4612 SSMR3GetIOPort,
4613 SSMR3GetSel,
4614 SSMR3GetMem,
4615 SSMR3GetStrZ,
4616 SSMR3GetStrZEx,
4617 SSMR3Skip,
4618 SSMR3SkipToEndOfUnit,
4619 SSMR3SetLoadError,
4620 SSMR3SetLoadErrorV,
4621 SSMR3SetCfgError,
4622 SSMR3SetCfgErrorV,
4623 SSMR3HandleGetStatus,
4624 SSMR3HandleGetAfter,
4625 SSMR3HandleIsLiveSave,
4626 SSMR3HandleMaxDowntime,
4627 SSMR3HandleHostBits,
4628 SSMR3HandleRevision,
4629 SSMR3HandleVersion,
4630 pdmR3DevHlp_TMTimerCreate,
4631 pdmR3DevHlp_TimerCreate,
4632 pdmR3DevHlp_TimerToPtr,
4633 pdmR3DevHlp_TimerFromMicro,
4634 pdmR3DevHlp_TimerFromMilli,
4635 pdmR3DevHlp_TimerFromNano,
4636 pdmR3DevHlp_TimerGet,
4637 pdmR3DevHlp_TimerGetFreq,
4638 pdmR3DevHlp_TimerGetNano,
4639 pdmR3DevHlp_TimerIsActive,
4640 pdmR3DevHlp_TimerIsLockOwner,
4641 pdmR3DevHlp_TimerLock,
4642 pdmR3DevHlp_TimerSet,
4643 pdmR3DevHlp_TimerSetFrequencyHint,
4644 pdmR3DevHlp_TimerSetMicro,
4645 pdmR3DevHlp_TimerSetMillies,
4646 pdmR3DevHlp_TimerSetNano,
4647 pdmR3DevHlp_TimerSetRelative,
4648 pdmR3DevHlp_TimerStop,
4649 pdmR3DevHlp_TimerUnlock,
4650 pdmR3DevHlp_TimerSetCritSect,
4651 pdmR3DevHlp_TimerSave,
4652 pdmR3DevHlp_TimerLoad,
4653 pdmR3DevHlp_TimerDestroy,
4654 TMR3TimerSkip,
4655 pdmR3DevHlp_TMUtcNow,
4656 CFGMR3Exists,
4657 CFGMR3QueryType,
4658 CFGMR3QuerySize,
4659 CFGMR3QueryInteger,
4660 CFGMR3QueryIntegerDef,
4661 CFGMR3QueryString,
4662 CFGMR3QueryStringDef,
4663 CFGMR3QueryBytes,
4664 CFGMR3QueryU64,
4665 CFGMR3QueryU64Def,
4666 CFGMR3QueryS64,
4667 CFGMR3QueryS64Def,
4668 CFGMR3QueryU32,
4669 CFGMR3QueryU32Def,
4670 CFGMR3QueryS32,
4671 CFGMR3QueryS32Def,
4672 CFGMR3QueryU16,
4673 CFGMR3QueryU16Def,
4674 CFGMR3QueryS16,
4675 CFGMR3QueryS16Def,
4676 CFGMR3QueryU8,
4677 CFGMR3QueryU8Def,
4678 CFGMR3QueryS8,
4679 CFGMR3QueryS8Def,
4680 CFGMR3QueryBool,
4681 CFGMR3QueryBoolDef,
4682 CFGMR3QueryPort,
4683 CFGMR3QueryPortDef,
4684 CFGMR3QueryUInt,
4685 CFGMR3QueryUIntDef,
4686 CFGMR3QuerySInt,
4687 CFGMR3QuerySIntDef,
4688 CFGMR3QueryPtr,
4689 CFGMR3QueryPtrDef,
4690 CFGMR3QueryGCPtr,
4691 CFGMR3QueryGCPtrDef,
4692 CFGMR3QueryGCPtrU,
4693 CFGMR3QueryGCPtrUDef,
4694 CFGMR3QueryGCPtrS,
4695 CFGMR3QueryGCPtrSDef,
4696 CFGMR3QueryStringAlloc,
4697 CFGMR3QueryStringAllocDef,
4698 CFGMR3GetParent,
4699 CFGMR3GetChild,
4700 CFGMR3GetChildF,
4701 CFGMR3GetChildFV,
4702 CFGMR3GetFirstChild,
4703 CFGMR3GetNextChild,
4704 CFGMR3GetName,
4705 CFGMR3GetNameLen,
4706 CFGMR3AreChildrenValid,
4707 CFGMR3GetFirstValue,
4708 CFGMR3GetNextValue,
4709 CFGMR3GetValueName,
4710 CFGMR3GetValueNameLen,
4711 CFGMR3GetValueType,
4712 CFGMR3AreValuesValid,
4713 CFGMR3ValidateConfig,
4714 pdmR3DevHlp_PhysRead,
4715 pdmR3DevHlp_PhysWrite,
4716 pdmR3DevHlp_PhysGCPhys2CCPtr,
4717 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
4718 pdmR3DevHlp_PhysReleasePageMappingLock,
4719 pdmR3DevHlp_PhysReadGCVirt,
4720 pdmR3DevHlp_PhysWriteGCVirt,
4721 pdmR3DevHlp_PhysGCPtr2GCPhys,
4722 pdmR3DevHlp_MMHeapAlloc,
4723 pdmR3DevHlp_MMHeapAllocZ,
4724 pdmR3DevHlp_MMHeapFree,
4725 pdmR3DevHlp_VMState,
4726 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
4727 pdmR3DevHlp_VMSetError,
4728 pdmR3DevHlp_VMSetErrorV,
4729 pdmR3DevHlp_VMSetRuntimeError,
4730 pdmR3DevHlp_VMSetRuntimeErrorV,
4731 pdmR3DevHlp_DBGFStopV,
4732 pdmR3DevHlp_DBGFInfoRegister,
4733 pdmR3DevHlp_DBGFInfoRegisterArgv,
4734 pdmR3DevHlp_DBGFRegRegister,
4735 pdmR3DevHlp_DBGFTraceBuf,
4736 pdmR3DevHlp_STAMRegister,
4737 pdmR3DevHlp_STAMRegisterV,
4738 pdmR3DevHlp_PCIRegister,
4739 pdmR3DevHlp_PCIRegisterMsi,
4740 pdmR3DevHlp_PCIIORegionRegister,
4741 pdmR3DevHlp_PCIInterceptConfigAccesses,
4742 pdmR3DevHlp_PCIConfigWrite,
4743 pdmR3DevHlp_PCIConfigRead,
4744 pdmR3DevHlp_PCIPhysRead,
4745 pdmR3DevHlp_PCIPhysWrite,
4746 pdmR3DevHlp_PCISetIrq,
4747 pdmR3DevHlp_PCISetIrqNoWait,
4748 pdmR3DevHlp_ISASetIrq,
4749 pdmR3DevHlp_ISASetIrqNoWait,
4750 pdmR3DevHlp_IoApicSendMsi,
4751 pdmR3DevHlp_DriverAttach,
4752 pdmR3DevHlp_DriverDetach,
4753 pdmR3DevHlp_QueueCreatePtr,
4754 pdmR3DevHlp_QueueCreate,
4755 pdmR3DevHlp_QueueToPtr,
4756 pdmR3DevHlp_QueueAlloc,
4757 pdmR3DevHlp_QueueInsert,
4758 pdmR3DevHlp_QueueInsertEx,
4759 pdmR3DevHlp_QueueFlushIfNecessary,
4760 pdmR3DevHlp_TaskCreate,
4761 pdmR3DevHlp_TaskTrigger,
4762 pdmR3DevHlp_SUPSemEventCreate,
4763 pdmR3DevHlp_SUPSemEventClose,
4764 pdmR3DevHlp_SUPSemEventSignal,
4765 pdmR3DevHlp_SUPSemEventWaitNoResume,
4766 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
4767 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
4768 pdmR3DevHlp_SUPSemEventGetResolution,
4769 pdmR3DevHlp_SUPSemEventMultiCreate,
4770 pdmR3DevHlp_SUPSemEventMultiClose,
4771 pdmR3DevHlp_SUPSemEventMultiSignal,
4772 pdmR3DevHlp_SUPSemEventMultiReset,
4773 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
4774 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
4775 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
4776 pdmR3DevHlp_SUPSemEventMultiGetResolution,
4777 pdmR3DevHlp_CritSectInit,
4778 pdmR3DevHlp_CritSectGetNop,
4779 pdmR3DevHlp_CritSectGetNopR0,
4780 pdmR3DevHlp_CritSectGetNopRC,
4781 pdmR3DevHlp_SetDeviceCritSect,
4782 pdmR3DevHlp_CritSectYield,
4783 pdmR3DevHlp_CritSectEnter,
4784 pdmR3DevHlp_CritSectEnterDebug,
4785 pdmR3DevHlp_CritSectTryEnter,
4786 pdmR3DevHlp_CritSectTryEnterDebug,
4787 pdmR3DevHlp_CritSectLeave,
4788 pdmR3DevHlp_CritSectIsOwner,
4789 pdmR3DevHlp_CritSectIsInitialized,
4790 pdmR3DevHlp_CritSectHasWaiters,
4791 pdmR3DevHlp_CritSectGetRecursion,
4792 pdmR3DevHlp_CritSectDelete,
4793 pdmR3DevHlp_ThreadCreate,
4794 PDMR3ThreadDestroy,
4795 PDMR3ThreadIAmSuspending,
4796 PDMR3ThreadIAmRunning,
4797 PDMR3ThreadSleep,
4798 PDMR3ThreadSuspend,
4799 PDMR3ThreadResume,
4800 pdmR3DevHlp_SetAsyncNotification,
4801 pdmR3DevHlp_AsyncNotificationCompleted,
4802 pdmR3DevHlp_RTCRegister,
4803 pdmR3DevHlp_PCIBusRegister,
4804 pdmR3DevHlp_PICRegister,
4805 pdmR3DevHlp_APICRegister,
4806 pdmR3DevHlp_IOAPICRegister,
4807 pdmR3DevHlp_HPETRegister,
4808 pdmR3DevHlp_PciRawRegister,
4809 pdmR3DevHlp_DMACRegister,
4810 pdmR3DevHlp_DMARegister,
4811 pdmR3DevHlp_DMAReadMemory,
4812 pdmR3DevHlp_DMAWriteMemory,
4813 pdmR3DevHlp_DMASetDREQ,
4814 pdmR3DevHlp_DMAGetChannelMode,
4815 pdmR3DevHlp_DMASchedule,
4816 pdmR3DevHlp_CMOSWrite,
4817 pdmR3DevHlp_CMOSRead,
4818 pdmR3DevHlp_AssertEMT,
4819 pdmR3DevHlp_AssertOther,
4820 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
4821 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
4822 pdmR3DevHlp_CallR0,
4823 pdmR3DevHlp_VMGetSuspendReason,
4824 pdmR3DevHlp_VMGetResumeReason,
4825 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
4826 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
4827 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
4828 pdmR3DevHlp_MMIOExChangeRegionNo,
4829 0,
4830 0,
4831 0,
4832 0,
4833 0,
4834 0,
4835 0,
4836 0,
4837 0,
4838 0,
4839 pdmR3DevHlp_GetUVM,
4840 pdmR3DevHlp_GetVM,
4841 pdmR3DevHlp_GetVMCPU,
4842 pdmR3DevHlp_GetCurrentCpuId,
4843 pdmR3DevHlp_RegisterVMMDevHeap,
4844 pdmR3DevHlp_FirmwareRegister,
4845 pdmR3DevHlp_VMReset,
4846 pdmR3DevHlp_VMSuspend,
4847 pdmR3DevHlp_VMSuspendSaveAndPowerOff,
4848 pdmR3DevHlp_VMPowerOff,
4849 pdmR3DevHlp_A20IsEnabled,
4850 pdmR3DevHlp_A20Set,
4851 pdmR3DevHlp_GetCpuId,
4852 pdmR3DevHlp_TMTimeVirtGet,
4853 pdmR3DevHlp_TMTimeVirtGetFreq,
4854 pdmR3DevHlp_TMTimeVirtGetNano,
4855 pdmR3DevHlp_GetSupDrvSession,
4856 pdmR3DevHlp_QueryGenericUserObject,
4857 PDM_DEVHLPR3_VERSION /* the end */
4858};
4859
4860
4861
4862
4863/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
4864static DECLCALLBACK(PUVM) pdmR3DevHlp_Untrusted_GetUVM(PPDMDEVINS pDevIns)
4865{
4866 PDMDEV_ASSERT_DEVINS(pDevIns);
4867 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4868 return NULL;
4869}
4870
4871
4872/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
4873static DECLCALLBACK(PVM) pdmR3DevHlp_Untrusted_GetVM(PPDMDEVINS pDevIns)
4874{
4875 PDMDEV_ASSERT_DEVINS(pDevIns);
4876 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4877 return NULL;
4878}
4879
4880
4881/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
4882static DECLCALLBACK(PVMCPU) pdmR3DevHlp_Untrusted_GetVMCPU(PPDMDEVINS pDevIns)
4883{
4884 PDMDEV_ASSERT_DEVINS(pDevIns);
4885 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4886 return NULL;
4887}
4888
4889
4890/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
4891static DECLCALLBACK(VMCPUID) pdmR3DevHlp_Untrusted_GetCurrentCpuId(PPDMDEVINS pDevIns)
4892{
4893 PDMDEV_ASSERT_DEVINS(pDevIns);
4894 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4895 return NIL_VMCPUID;
4896}
4897
4898
4899/** @interface_method_impl{PDMDEVHLPR3,pfnRegisterVMMDevHeap} */
4900static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
4901 RTR3PTR pvHeap, unsigned cbHeap)
4902{
4903 PDMDEV_ASSERT_DEVINS(pDevIns);
4904 NOREF(GCPhys); NOREF(pvHeap); NOREF(cbHeap);
4905 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4906 return VERR_ACCESS_DENIED;
4907}
4908
4909
4910/** @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister} */
4911static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
4912{
4913 PDMDEV_ASSERT_DEVINS(pDevIns);
4914 NOREF(pFwReg); NOREF(ppFwHlp);
4915 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4916 return VERR_ACCESS_DENIED;
4917}
4918
4919
4920/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
4921static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
4922{
4923 PDMDEV_ASSERT_DEVINS(pDevIns); NOREF(fFlags);
4924 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4925 return VERR_ACCESS_DENIED;
4926}
4927
4928
4929/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
4930static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspend(PPDMDEVINS pDevIns)
4931{
4932 PDMDEV_ASSERT_DEVINS(pDevIns);
4933 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4934 return VERR_ACCESS_DENIED;
4935}
4936
4937
4938/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
4939static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
4940{
4941 PDMDEV_ASSERT_DEVINS(pDevIns);
4942 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4943 return VERR_ACCESS_DENIED;
4944}
4945
4946
4947/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
4948static DECLCALLBACK(int) pdmR3DevHlp_Untrusted_VMPowerOff(PPDMDEVINS pDevIns)
4949{
4950 PDMDEV_ASSERT_DEVINS(pDevIns);
4951 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4952 return VERR_ACCESS_DENIED;
4953}
4954
4955
4956/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
4957static DECLCALLBACK(bool) pdmR3DevHlp_Untrusted_A20IsEnabled(PPDMDEVINS pDevIns)
4958{
4959 PDMDEV_ASSERT_DEVINS(pDevIns);
4960 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4961 return false;
4962}
4963
4964
4965/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
4966static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_A20Set(PPDMDEVINS pDevIns, bool fEnable)
4967{
4968 PDMDEV_ASSERT_DEVINS(pDevIns);
4969 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4970 NOREF(fEnable);
4971}
4972
4973
4974/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
4975static DECLCALLBACK(void) pdmR3DevHlp_Untrusted_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
4976 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
4977{
4978 PDMDEV_ASSERT_DEVINS(pDevIns);
4979 NOREF(iLeaf); NOREF(pEax); NOREF(pEbx); NOREF(pEcx); NOREF(pEdx);
4980 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4981}
4982
4983
4984/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
4985static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_Untrusted_GetSupDrvSession(PPDMDEVINS pDevIns)
4986{
4987 PDMDEV_ASSERT_DEVINS(pDevIns);
4988 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
4989 return (PSUPDRVSESSION)0;
4990}
4991
4992
4993/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
4994static DECLCALLBACK(void *) pdmR3DevHlp_Untrusted_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
4995{
4996 PDMDEV_ASSERT_DEVINS(pDevIns);
4997 AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d %RTuuid\n",
4998 pDevIns->pReg->szName, pDevIns->iInstance, pUuid));
4999 return NULL;
5000}
5001
5002
5003/**
5004 * The device helper structure for non-trusted devices.
5005 */
5006const PDMDEVHLPR3 g_pdmR3DevHlpUnTrusted =
5007{
5008 PDM_DEVHLPR3_VERSION,
5009 pdmR3DevHlp_IoPortCreateEx,
5010 pdmR3DevHlp_IoPortMap,
5011 pdmR3DevHlp_IoPortUnmap,
5012 pdmR3DevHlp_IoPortGetMappingAddress,
5013 pdmR3DevHlp_IOPortRegister,
5014 pdmR3DevHlp_IOPortRegisterRC,
5015 pdmR3DevHlp_IOPortRegisterR0,
5016 pdmR3DevHlp_IOPortDeregister,
5017 pdmR3DevHlp_MmioCreateEx,
5018 pdmR3DevHlp_MmioMap,
5019 pdmR3DevHlp_MmioUnmap,
5020 pdmR3DevHlp_MmioReduce,
5021 pdmR3DevHlp_MmioGetMappingAddress,
5022 pdmR3DevHlp_MMIORegister,
5023 pdmR3DevHlp_MMIORegisterRC,
5024 pdmR3DevHlp_MMIORegisterR0,
5025 pdmR3DevHlp_MMIODeregister,
5026 pdmR3DevHlp_Mmio2Create,
5027 pdmR3DevHlp_Mmio2Destroy,
5028 pdmR3DevHlp_Mmio2Map,
5029 pdmR3DevHlp_Mmio2Unmap,
5030 pdmR3DevHlp_Mmio2Reduce,
5031 pdmR3DevHlp_Mmio2GetMappingAddress,
5032 pdmR3DevHlp_Mmio2ChangeRegionNo,
5033 pdmR3DevHlp_MMIO2Register,
5034 pdmR3DevHlp_MMIOExDeregister,
5035 pdmR3DevHlp_MMIOExMap,
5036 pdmR3DevHlp_MMIOExUnmap,
5037 pdmR3DevHlp_MMIOExReduce,
5038 pdmR3DevHlp_MMHyperMapMMIO2,
5039 pdmR3DevHlp_MMIO2MapKernel,
5040 pdmR3DevHlp_ROMRegister,
5041 pdmR3DevHlp_ROMProtectShadow,
5042 pdmR3DevHlp_SSMRegister,
5043 SSMR3PutStruct,
5044 SSMR3PutStructEx,
5045 SSMR3PutBool,
5046 SSMR3PutU8,
5047 SSMR3PutS8,
5048 SSMR3PutU16,
5049 SSMR3PutS16,
5050 SSMR3PutU32,
5051 SSMR3PutS32,
5052 SSMR3PutU64,
5053 SSMR3PutS64,
5054 SSMR3PutU128,
5055 SSMR3PutS128,
5056 SSMR3PutUInt,
5057 SSMR3PutSInt,
5058 SSMR3PutGCUInt,
5059 SSMR3PutGCUIntReg,
5060 SSMR3PutGCPhys32,
5061 SSMR3PutGCPhys64,
5062 SSMR3PutGCPhys,
5063 SSMR3PutGCPtr,
5064 SSMR3PutGCUIntPtr,
5065 SSMR3PutRCPtr,
5066 SSMR3PutIOPort,
5067 SSMR3PutSel,
5068 SSMR3PutMem,
5069 SSMR3PutStrZ,
5070 SSMR3GetStruct,
5071 SSMR3GetStructEx,
5072 SSMR3GetBool,
5073 SSMR3GetBoolV,
5074 SSMR3GetU8,
5075 SSMR3GetU8V,
5076 SSMR3GetS8,
5077 SSMR3GetS8V,
5078 SSMR3GetU16,
5079 SSMR3GetU16V,
5080 SSMR3GetS16,
5081 SSMR3GetS16V,
5082 SSMR3GetU32,
5083 SSMR3GetU32V,
5084 SSMR3GetS32,
5085 SSMR3GetS32V,
5086 SSMR3GetU64,
5087 SSMR3GetU64V,
5088 SSMR3GetS64,
5089 SSMR3GetS64V,
5090 SSMR3GetU128,
5091 SSMR3GetU128V,
5092 SSMR3GetS128,
5093 SSMR3GetS128V,
5094 SSMR3GetGCPhys32,
5095 SSMR3GetGCPhys32V,
5096 SSMR3GetGCPhys64,
5097 SSMR3GetGCPhys64V,
5098 SSMR3GetGCPhys,
5099 SSMR3GetGCPhysV,
5100 SSMR3GetUInt,
5101 SSMR3GetSInt,
5102 SSMR3GetGCUInt,
5103 SSMR3GetGCUIntReg,
5104 SSMR3GetGCPtr,
5105 SSMR3GetGCUIntPtr,
5106 SSMR3GetRCPtr,
5107 SSMR3GetIOPort,
5108 SSMR3GetSel,
5109 SSMR3GetMem,
5110 SSMR3GetStrZ,
5111 SSMR3GetStrZEx,
5112 SSMR3Skip,
5113 SSMR3SkipToEndOfUnit,
5114 SSMR3SetLoadError,
5115 SSMR3SetLoadErrorV,
5116 SSMR3SetCfgError,
5117 SSMR3SetCfgErrorV,
5118 SSMR3HandleGetStatus,
5119 SSMR3HandleGetAfter,
5120 SSMR3HandleIsLiveSave,
5121 SSMR3HandleMaxDowntime,
5122 SSMR3HandleHostBits,
5123 SSMR3HandleRevision,
5124 SSMR3HandleVersion,
5125 pdmR3DevHlp_TMTimerCreate,
5126 pdmR3DevHlp_TimerCreate,
5127 pdmR3DevHlp_TimerToPtr,
5128 pdmR3DevHlp_TimerFromMicro,
5129 pdmR3DevHlp_TimerFromMilli,
5130 pdmR3DevHlp_TimerFromNano,
5131 pdmR3DevHlp_TimerGet,
5132 pdmR3DevHlp_TimerGetFreq,
5133 pdmR3DevHlp_TimerGetNano,
5134 pdmR3DevHlp_TimerIsActive,
5135 pdmR3DevHlp_TimerIsLockOwner,
5136 pdmR3DevHlp_TimerLock,
5137 pdmR3DevHlp_TimerSet,
5138 pdmR3DevHlp_TimerSetFrequencyHint,
5139 pdmR3DevHlp_TimerSetMicro,
5140 pdmR3DevHlp_TimerSetMillies,
5141 pdmR3DevHlp_TimerSetNano,
5142 pdmR3DevHlp_TimerSetRelative,
5143 pdmR3DevHlp_TimerStop,
5144 pdmR3DevHlp_TimerUnlock,
5145 pdmR3DevHlp_TimerSetCritSect,
5146 pdmR3DevHlp_TimerSave,
5147 pdmR3DevHlp_TimerLoad,
5148 pdmR3DevHlp_TimerDestroy,
5149 TMR3TimerSkip,
5150 pdmR3DevHlp_TMUtcNow,
5151 CFGMR3Exists,
5152 CFGMR3QueryType,
5153 CFGMR3QuerySize,
5154 CFGMR3QueryInteger,
5155 CFGMR3QueryIntegerDef,
5156 CFGMR3QueryString,
5157 CFGMR3QueryStringDef,
5158 CFGMR3QueryBytes,
5159 CFGMR3QueryU64,
5160 CFGMR3QueryU64Def,
5161 CFGMR3QueryS64,
5162 CFGMR3QueryS64Def,
5163 CFGMR3QueryU32,
5164 CFGMR3QueryU32Def,
5165 CFGMR3QueryS32,
5166 CFGMR3QueryS32Def,
5167 CFGMR3QueryU16,
5168 CFGMR3QueryU16Def,
5169 CFGMR3QueryS16,
5170 CFGMR3QueryS16Def,
5171 CFGMR3QueryU8,
5172 CFGMR3QueryU8Def,
5173 CFGMR3QueryS8,
5174 CFGMR3QueryS8Def,
5175 CFGMR3QueryBool,
5176 CFGMR3QueryBoolDef,
5177 CFGMR3QueryPort,
5178 CFGMR3QueryPortDef,
5179 CFGMR3QueryUInt,
5180 CFGMR3QueryUIntDef,
5181 CFGMR3QuerySInt,
5182 CFGMR3QuerySIntDef,
5183 CFGMR3QueryPtr,
5184 CFGMR3QueryPtrDef,
5185 CFGMR3QueryGCPtr,
5186 CFGMR3QueryGCPtrDef,
5187 CFGMR3QueryGCPtrU,
5188 CFGMR3QueryGCPtrUDef,
5189 CFGMR3QueryGCPtrS,
5190 CFGMR3QueryGCPtrSDef,
5191 CFGMR3QueryStringAlloc,
5192 CFGMR3QueryStringAllocDef,
5193 CFGMR3GetParent,
5194 CFGMR3GetChild,
5195 CFGMR3GetChildF,
5196 CFGMR3GetChildFV,
5197 CFGMR3GetFirstChild,
5198 CFGMR3GetNextChild,
5199 CFGMR3GetName,
5200 CFGMR3GetNameLen,
5201 CFGMR3AreChildrenValid,
5202 CFGMR3GetFirstValue,
5203 CFGMR3GetNextValue,
5204 CFGMR3GetValueName,
5205 CFGMR3GetValueNameLen,
5206 CFGMR3GetValueType,
5207 CFGMR3AreValuesValid,
5208 CFGMR3ValidateConfig,
5209 pdmR3DevHlp_PhysRead,
5210 pdmR3DevHlp_PhysWrite,
5211 pdmR3DevHlp_PhysGCPhys2CCPtr,
5212 pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
5213 pdmR3DevHlp_PhysReleasePageMappingLock,
5214 pdmR3DevHlp_PhysReadGCVirt,
5215 pdmR3DevHlp_PhysWriteGCVirt,
5216 pdmR3DevHlp_PhysGCPtr2GCPhys,
5217 pdmR3DevHlp_MMHeapAlloc,
5218 pdmR3DevHlp_MMHeapAllocZ,
5219 pdmR3DevHlp_MMHeapFree,
5220 pdmR3DevHlp_VMState,
5221 pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
5222 pdmR3DevHlp_VMSetError,
5223 pdmR3DevHlp_VMSetErrorV,
5224 pdmR3DevHlp_VMSetRuntimeError,
5225 pdmR3DevHlp_VMSetRuntimeErrorV,
5226 pdmR3DevHlp_DBGFStopV,
5227 pdmR3DevHlp_DBGFInfoRegister,
5228 pdmR3DevHlp_DBGFInfoRegisterArgv,
5229 pdmR3DevHlp_DBGFRegRegister,
5230 pdmR3DevHlp_DBGFTraceBuf,
5231 pdmR3DevHlp_STAMRegister,
5232 pdmR3DevHlp_STAMRegisterV,
5233 pdmR3DevHlp_PCIRegister,
5234 pdmR3DevHlp_PCIRegisterMsi,
5235 pdmR3DevHlp_PCIIORegionRegister,
5236 pdmR3DevHlp_PCIInterceptConfigAccesses,
5237 pdmR3DevHlp_PCIConfigWrite,
5238 pdmR3DevHlp_PCIConfigRead,
5239 pdmR3DevHlp_PCIPhysRead,
5240 pdmR3DevHlp_PCIPhysWrite,
5241 pdmR3DevHlp_PCISetIrq,
5242 pdmR3DevHlp_PCISetIrqNoWait,
5243 pdmR3DevHlp_ISASetIrq,
5244 pdmR3DevHlp_ISASetIrqNoWait,
5245 pdmR3DevHlp_IoApicSendMsi,
5246 pdmR3DevHlp_DriverAttach,
5247 pdmR3DevHlp_DriverDetach,
5248 pdmR3DevHlp_QueueCreatePtr,
5249 pdmR3DevHlp_QueueCreate,
5250 pdmR3DevHlp_QueueToPtr,
5251 pdmR3DevHlp_QueueAlloc,
5252 pdmR3DevHlp_QueueInsert,
5253 pdmR3DevHlp_QueueInsertEx,
5254 pdmR3DevHlp_QueueFlushIfNecessary,
5255 pdmR3DevHlp_TaskCreate,
5256 pdmR3DevHlp_TaskTrigger,
5257 pdmR3DevHlp_SUPSemEventCreate,
5258 pdmR3DevHlp_SUPSemEventClose,
5259 pdmR3DevHlp_SUPSemEventSignal,
5260 pdmR3DevHlp_SUPSemEventWaitNoResume,
5261 pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
5262 pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
5263 pdmR3DevHlp_SUPSemEventGetResolution,
5264 pdmR3DevHlp_SUPSemEventMultiCreate,
5265 pdmR3DevHlp_SUPSemEventMultiClose,
5266 pdmR3DevHlp_SUPSemEventMultiSignal,
5267 pdmR3DevHlp_SUPSemEventMultiReset,
5268 pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
5269 pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
5270 pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
5271 pdmR3DevHlp_SUPSemEventMultiGetResolution,
5272 pdmR3DevHlp_CritSectInit,
5273 pdmR3DevHlp_CritSectGetNop,
5274 pdmR3DevHlp_CritSectGetNopR0,
5275 pdmR3DevHlp_CritSectGetNopRC,
5276 pdmR3DevHlp_SetDeviceCritSect,
5277 pdmR3DevHlp_CritSectYield,
5278 pdmR3DevHlp_CritSectEnter,
5279 pdmR3DevHlp_CritSectEnterDebug,
5280 pdmR3DevHlp_CritSectTryEnter,
5281 pdmR3DevHlp_CritSectTryEnterDebug,
5282 pdmR3DevHlp_CritSectLeave,
5283 pdmR3DevHlp_CritSectIsOwner,
5284 pdmR3DevHlp_CritSectIsInitialized,
5285 pdmR3DevHlp_CritSectHasWaiters,
5286 pdmR3DevHlp_CritSectGetRecursion,
5287 pdmR3DevHlp_CritSectDelete,
5288 pdmR3DevHlp_ThreadCreate,
5289 PDMR3ThreadDestroy,
5290 PDMR3ThreadIAmSuspending,
5291 PDMR3ThreadIAmRunning,
5292 PDMR3ThreadSleep,
5293 PDMR3ThreadSuspend,
5294 PDMR3ThreadResume,
5295 pdmR3DevHlp_SetAsyncNotification,
5296 pdmR3DevHlp_AsyncNotificationCompleted,
5297 pdmR3DevHlp_RTCRegister,
5298 pdmR3DevHlp_PCIBusRegister,
5299 pdmR3DevHlp_PICRegister,
5300 pdmR3DevHlp_APICRegister,
5301 pdmR3DevHlp_IOAPICRegister,
5302 pdmR3DevHlp_HPETRegister,
5303 pdmR3DevHlp_PciRawRegister,
5304 pdmR3DevHlp_DMACRegister,
5305 pdmR3DevHlp_DMARegister,
5306 pdmR3DevHlp_DMAReadMemory,
5307 pdmR3DevHlp_DMAWriteMemory,
5308 pdmR3DevHlp_DMASetDREQ,
5309 pdmR3DevHlp_DMAGetChannelMode,
5310 pdmR3DevHlp_DMASchedule,
5311 pdmR3DevHlp_CMOSWrite,
5312 pdmR3DevHlp_CMOSRead,
5313 pdmR3DevHlp_AssertEMT,
5314 pdmR3DevHlp_AssertOther,
5315 pdmR3DevHlp_LdrGetRCInterfaceSymbols,
5316 pdmR3DevHlp_LdrGetR0InterfaceSymbols,
5317 pdmR3DevHlp_CallR0,
5318 pdmR3DevHlp_VMGetSuspendReason,
5319 pdmR3DevHlp_VMGetResumeReason,
5320 pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
5321 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
5322 pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
5323 pdmR3DevHlp_MMIOExChangeRegionNo,
5324 0,
5325 0,
5326 0,
5327 0,
5328 0,
5329 0,
5330 0,
5331 0,
5332 0,
5333 0,
5334 pdmR3DevHlp_Untrusted_GetUVM,
5335 pdmR3DevHlp_Untrusted_GetVM,
5336 pdmR3DevHlp_Untrusted_GetVMCPU,
5337 pdmR3DevHlp_Untrusted_GetCurrentCpuId,
5338 pdmR3DevHlp_Untrusted_RegisterVMMDevHeap,
5339 pdmR3DevHlp_Untrusted_FirmwareRegister,
5340 pdmR3DevHlp_Untrusted_VMReset,
5341 pdmR3DevHlp_Untrusted_VMSuspend,
5342 pdmR3DevHlp_Untrusted_VMSuspendSaveAndPowerOff,
5343 pdmR3DevHlp_Untrusted_VMPowerOff,
5344 pdmR3DevHlp_Untrusted_A20IsEnabled,
5345 pdmR3DevHlp_Untrusted_A20Set,
5346 pdmR3DevHlp_Untrusted_GetCpuId,
5347 pdmR3DevHlp_TMTimeVirtGet,
5348 pdmR3DevHlp_TMTimeVirtGetFreq,
5349 pdmR3DevHlp_TMTimeVirtGetNano,
5350 pdmR3DevHlp_Untrusted_GetSupDrvSession,
5351 pdmR3DevHlp_Untrusted_QueryGenericUserObject,
5352 PDM_DEVHLPR3_VERSION /* the end */
5353};
5354
5355
5356
5357/**
5358 * Queue consumer callback for internal component.
5359 *
5360 * @returns Success indicator.
5361 * If false the item will not be removed and the flushing will stop.
5362 * @param pVM The cross context VM structure.
5363 * @param pItem The item to consume. Upon return this item will be freed.
5364 */
5365DECLCALLBACK(bool) pdmR3DevHlpQueueConsumer(PVM pVM, PPDMQUEUEITEMCORE pItem)
5366{
5367 PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)pItem;
5368 LogFlow(("pdmR3DevHlpQueueConsumer: enmOp=%d pDevIns=%p\n", pTask->enmOp, pTask->pDevInsR3));
5369 switch (pTask->enmOp)
5370 {
5371 case PDMDEVHLPTASKOP_ISA_SET_IRQ:
5372 PDMIsaSetIrq(pVM, pTask->u.IsaSetIRQ.iIrq, pTask->u.IsaSetIRQ.iLevel, pTask->u.IsaSetIRQ.uTagSrc);
5373 break;
5374
5375 case PDMDEVHLPTASKOP_PCI_SET_IRQ:
5376 {
5377 /* Same as pdmR3DevHlp_PCISetIrq, except we've got a tag already. */
5378 PPDMPCIDEV pPciDev = pTask->u.PciSetIRQ.pPciDevR3;
5379 if (pPciDev)
5380 {
5381 size_t const idxBus = pPciDev->Int.s.idxPdmBus;
5382 AssertBreak(idxBus < RT_ELEMENTS(pVM->pdm.s.aPciBuses));
5383 PPDMPCIBUS pBus = &pVM->pdm.s.aPciBuses[idxBus];
5384
5385 pdmLock(pVM);
5386 pBus->pfnSetIrqR3(pBus->pDevInsR3, pPciDev, pTask->u.PciSetIRQ.iIrq,
5387 pTask->u.PciSetIRQ.iLevel, pTask->u.PciSetIRQ.uTagSrc);
5388 pdmUnlock(pVM);
5389 }
5390 else
5391 AssertReleaseMsgFailed(("No PCI device registered!\n"));
5392 break;
5393 }
5394
5395 case PDMDEVHLPTASKOP_IOAPIC_SET_IRQ:
5396 PDMIoApicSetIrq(pVM, pTask->u.IoApicSetIRQ.iIrq, pTask->u.IoApicSetIRQ.iLevel, pTask->u.IoApicSetIRQ.uTagSrc);
5397 break;
5398
5399 default:
5400 AssertReleaseMsgFailed(("Invalid operation %d\n", pTask->enmOp));
5401 break;
5402 }
5403 return true;
5404}
5405
5406/** @} */
5407
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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