VirtualBox

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

Last change on this file since 63682 was 63682, checked in by vboxsync, 9 years ago

PDM,IOM: MMIO range length is now a RTGCPHYS instead of uint32_t.

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

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