VirtualBox

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

Last change on this file since 36138 was 36138, checked in by vboxsync, 14 years ago

PCI: some of 64-bit BARs support (many real cards do that)

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

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