VirtualBox

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

Last change on this file since 29450 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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

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