VirtualBox

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

Last change on this file since 45457 was 44902, checked in by vboxsync, 12 years ago

Relevant PDMDevHlpPhysWrite changed to PDMDevHlpPCIPhysWrite. If this breaks anything, add PDM_DO_NOT_RESPECT_PCI_BM_BIT to VMM_COMMON_DEFS to disable the feature.

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