VirtualBox

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

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

PDM/DevHlp: Need to wrap the crit sect methods so we can pass on pVM to the crit sect code later, as we won't be able to sore pointers in the internal critical section data anymore. bugref:9218

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