VirtualBox

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

Last change on this file since 68969 was 68594, checked in by vboxsync, 7 years ago

PDM: Address the todos for cleaning up the PDMDEVHLP structure, bring the reserved slots back to the nominal numver and bump the major version (20 ended up being used by 5.1). Eliminate redundant PDMDEVHLP version dependent conditional compilation

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

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