VirtualBox

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

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

PDM: logging fixes. bugref:9218

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

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