VirtualBox

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

Last change on this file since 22346 was 22277, checked in by vboxsync, 15 years ago

PDMDRVREG change (big changeset).

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