VirtualBox

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

Last change on this file since 25802 was 25748, checked in by vboxsync, 15 years ago

iprt/cdefs,*: Use RT_LOCK_STRICT and RT_LOCK_STRICT_ORDER for controlling deadlock detection and lock order validation. Currently both are disabled by default, but it's possible to add VBOX_WITH_STRICT_LOCKS=1 to LocalConfig.kmk to enable it all.

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