VirtualBox

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

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

VMM/r3: Refactored VMCPU enumeration in preparation that aCpus will be replaced with a pointer array. Removed two raw-mode offset members from the CPUM and CPUMCPU sub-structures. bugref:9217 bugref:9517

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

© 2023 Oracle
ContactPrivacy policyTerms of Use