VirtualBox

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

最後變更 在這個檔案從26152是 26152,由 vboxsync 提交於 15 年 前

VMM: pdm.h and @copydoc cleanups.

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

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