VirtualBox

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

Last change on this file since 62652 was 62643, checked in by vboxsync, 8 years ago

VMMR3: warnings

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